home *** CD-ROM | disk | FTP | other *** search
- /****************************************************************************
- *
- * AVIEASY.C
- *
- * low-level routines for writing Standard AVI files
- *
- * AVIPhys...()
- *
- * Copyright (c) 1992-1993 Microsoft Corporation. All Rights Reserved.
- *
- * You have a royalty-free right to use, modify, reproduce and
- * distribute the Sample Files (and/or any modified version) in
- * any way you find useful, provided that you agree that
- * Microsoft has no warranty obligations or liability for any
- * Sample Application Files which are modified.
- *
- ***************************************************************************/
-
- #include <windows.h>
- #include <windowsx.h>
- #include <mmsystem.h>
- #include <compman.h>
- #include <memory.h>
- #include "avifmt.h"
- #include "avieasy.h"
-
- // C6 needs a little help....
- #undef GlobalFreePtr
- #define GlobalFreePtr(lp) (BOOL)GlobalFree(GlobalPtrHandle(lp))
-
- extern LONG FAR PASCAL muldiv32(LONG,LONG,LONG);
-
- #define MAXSTREAMS 16
- typedef struct {
- HMMIO hmmio;
- DWORD dwStart;
- int iMaxStream;
- LPVOID lpFormat[MAXSTREAMS];
- DWORD cbFormat[MAXSTREAMS];
- AVIStreamHeader strhdr[MAXSTREAMS];
- AVIINDEXENTRY huge * hpIndex;
- DWORD dwIndex;
- DWORD dwIndexAlloc;
- DWORD dwIndexRec;
- MMCKINFO ckRECORD;
- MainAVIHeader avihdr;
- } PHYSINFO, FAR *PPHYS;
-
- /* Some simple functions for dealing with AVI indices. */
- static BOOL NEAR PASCAL InitIndex(PPHYS pphys);
- static BOOL NEAR PASCAL AddChunkToIndex(PPHYS pphys, MMCKINFO FAR * lpck, DWORD dwFlags);
- static BOOL NEAR PASCAL WriteIndex(PPHYS pphys);
-
-
- ///////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////
-
-
- /*****************************************************************************
- * @doc EXTERNAL
- *
- * @api LONG | avifileOpen | Open an AVI file for writing.
- *
- * @parm HAVI FAR * | lphfile | Holds the returned file handle if the
- * function succeeds.
- *
- * @parm LPSTR | lpFileName | The file name to use.
- *
- * @parm MainAVIHeader FAR * | lphdr | The main AVI header to write to the file.
- *
- * @rdesc Returns AVIERR_OK if successful, an error code otherwise.
- *
- * @xref avifileClose
- ****************************************************************************/
- LONG FAR avifileOpen(HAVI FAR *lphfile, LPSTR lpFileName, MainAVIHeader FAR *lphdr)
- {
- PPHYS pwrite;
- LONG lRet = AVIERR_OK;
-
- pwrite = (PPHYS) GlobalAllocPtr(GHND, sizeof(PHYSINFO));
- if (!pwrite)
- return AVIERR_MEMORY;
-
- pwrite->hmmio = mmioOpen(lpFileName, NULL, MMIO_WRITE | MMIO_CREATE);
-
- pwrite->avihdr = *lphdr;
-
- pwrite->avihdr.dwStreams = 0; // we'll use the # of streams they add
-
- if (!pwrite->hmmio)
- goto OpenError;
-
- if (!InitIndex(pwrite))
- goto FileError;
-
- *lphfile = (HAVI) pwrite;
-
- goto exit;
-
- FileError:
- lRet = AVIERR_FILEWRITE;
- mmioClose(pwrite->hmmio, 0);
- goto exit;
-
- OpenError:
- lRet = AVIERR_FILEOPEN;
-
- exit:
- return lRet;
-
- }
-
- ///////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////
-
- /*****************************************************************************
- * @doc EXTERNAL
- *
- * @api LONG | avifileAddStream | Add a new stream to an AVI file.
- *
- * @parm HAVI | hfile | The handle returned from <f avifileOpen>.
- *
- * @parm int FAR * | lpstream | A pointer to an integer that will receive
- * the number of the new stream. Can be NULL.
- *
- * @parm AVIStreamHeader FAR * | lphdr | The stream's header information.
- *
- * @parm LPVOID | lpFormat | A pointer to the stream's format, such as a
- * <t BITMAPINFO> or <t WAVEFORMAT> structure.
- *
- * @parm LONG | cbFormat | The size of the format pointed to be <p lpFormat>.
- *
- * @rdesc Returns AVIERR_OK if successful, an error code otherwise.
- *
- * @xref avifileOpen avifileWriteToHeader
- ****************************************************************************/
- LONG FAR avifileAddStream(HAVI hfile, int FAR *lpstream,
- AVIStreamHeader FAR *lphdr,
- LPVOID lpFormat,
- LONG cbFormat)
- {
- PPHYS pwrite = (PPHYS) hfile;
- int stream = (int) pwrite->avihdr.dwStreams++;
-
- if (lpstream)
- *lpstream = stream;
-
- pwrite->cbFormat[stream] = cbFormat;
- pwrite->lpFormat[stream] = GlobalAllocPtr(GMEM_MOVEABLE, cbFormat);
- // !!!
- hmemcpy(pwrite->lpFormat[stream], lpFormat, cbFormat);
- pwrite->strhdr[stream] = *lphdr;
- pwrite->strhdr[stream].dwLength = 0;
-
- // Fix up values in header...
- if (lphdr->fccType == streamtypeAUDIO) {
- LPWAVEFORMAT lpwf = (LPWAVEFORMAT) lpFormat;
- pwrite->strhdr[stream].dwSampleSize = lpwf->nBlockAlign;
- pwrite->strhdr[stream].dwRate = lpwf->nSamplesPerSec;
- pwrite->strhdr[stream].dwScale = lpwf->nBlockAlign;
- } else {
- pwrite->strhdr[stream].dwSampleSize = 0;
-
- // Default to 15/sec....
- if (pwrite->strhdr[stream].dwRate == 0 ||
- pwrite->strhdr[stream].dwScale == 0) {
- pwrite->strhdr[stream].dwRate = 15;
- pwrite->strhdr[stream].dwScale = 1;
- }
- }
-
- if (lphdr->fccType == streamtypeVIDEO) {
- LPBITMAPINFOHEADER lpbi = (LPBITMAPINFOHEADER) lpFormat;
-
- if (pwrite->avihdr.dwWidth < (DWORD) lpbi->biWidth)
- pwrite->avihdr.dwWidth = lpbi->biWidth;
-
- if (pwrite->avihdr.dwHeight < (DWORD) lpbi->biHeight)
- pwrite->avihdr.dwHeight = lpbi->biHeight;
- }
-
- return AVIERR_OK;
- }
-
- ///////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////
-
- /*****************************************************************************
- * @doc EXTERNAL
- *
- * @api LONG | avifileWriteToHeader | Add data to the header of an AVI file.
- *
- * @parm HAVI | hfile | The handle returned from <f avifileOpen>.
- *
- * @parm int | stream | The stream to write to. Can be -1, which indicates
- * that the data should be associated with the file as a whole, rather
- * than a single stream.
- *
- * @parm DWORD | ckid | The RIFF ckid to use for the data.
- *
- * @parm LPVOID | lpData | A pointer to the data to be written
- *
- * @parm LONG | cbData | The size of the data pointed to be <p lpData>.
- *
- * @rdesc Returns AVIERR_OK if successful, an error code otherwise.
- *
- * @xref avifileAddStream
- ****************************************************************************/
- LONG FAR avifileWriteToHeader(HAVI hfile,
- int stream,
- DWORD ckid,
- LPVOID lpData,
- LONG cbData)
- {
- // !!! Add this data onto a list kept for each stream, so we can write
- // it later.
-
- // stream -1 means main header?
-
- return AVIERR_OK;
- }
-
- ///////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////
-
- /*****************************************************************************
- * @doc EXTERNAL
- *
- * @api LONG | avifileWrite | Write data to an AVI file.
- *
- * @parm HAVI | hfile | The handle returned from <f avifileOpen>.
- *
- * @parm int | stream | The stream to write to.
- *
- * @parm LPVOID | lpData | A pointer to the data to be written
- *
- * @parm LONG | cbData | The size of the data pointed to be <p lpData>.
- *
- * @parm WORD | cktype | The TWOCC to use for the data. Mostly obsolete,
- * except for RGB and RLE DIB data.
- *
- * @parm DWORD | dwFlags | Flags associated with this data. In particular:
- *
- * @flag AVIIF_KEYFRAME | This data represents a key frame.
- *
- * @flag AVIIF_NOTIME | This data is control data, and does not take up
- * a frame's worth of time.
- *
- * @rdesc Returns AVIERR_OK if successful, an error code otherwise.
- *
- * @xref avifileAddStream
- ****************************************************************************/
- LONG FAR avifileWrite(HAVI hfile,
- int stream,
- LPVOID lpData,
- LONG cbData,
- WORD cktype,
- DWORD dwFlags)
- {
- PPHYS pwrite = (PPHYS) hfile;
- MMCKINFO ck;
- DWORD dw;
- int i;
-
- if (stream >= (int) pwrite->avihdr.dwStreams)
- return AVIERR_BADPARAM;
-
- if (cktype < 256 * ' ')
- cktype = aviTWOCC('x', 'x');
-
- if (pwrite->dwStart == 0) {
- // Figure out where to start writing the data
- dw = 0;
- for (i = 0; i < (int) pwrite->avihdr.dwStreams; i++) {
- dw += pwrite->cbFormat[i] + 512;
- }
- // Reserve some space for the header
- pwrite->dwStart = max(4096L, dw);
-
- mmioSeek(pwrite->hmmio, pwrite->dwStart, SEEK_SET);
-
- if (pwrite->avihdr.dwFlags & AVIF_ISINTERLEAVED) {
- /* Start the 'rec' list */
- pwrite->ckRECORD.cksize = 0;
- pwrite->ckRECORD.fccType = listtypeAVIRECORD;
- if (mmioCreateChunk(pwrite->hmmio, &pwrite->ckRECORD, MMIO_CREATELIST)) {
- goto FileError;
- }
-
- pwrite->dwIndexRec = pwrite->dwIndex;
-
- if (!AddChunkToIndex(pwrite, &pwrite->ckRECORD, AVIIF_LIST))
- return AVIERR_MEMORY;
- }
- }
-
- if (!(dwFlags & AVIIF_NOTIME)) {
- if (pwrite->strhdr[stream].dwSampleSize)
- pwrite->strhdr[stream].dwLength += cbData / pwrite->strhdr[stream].dwSampleSize;
- else
- ++pwrite->strhdr[stream].dwLength;
- }
-
- // ck.ckid = MAKEAVICKID(cktype, stream);
- ck.ckid = ((LONG) cktype << 16) | ('0' << 8) | ('0' + stream);
- ck.cksize = cbData;
-
- if (mmioCreateChunk(pwrite->hmmio, &ck, 0))
- goto FileError;
-
- if (mmioWrite(pwrite->hmmio, lpData, cbData) != (LONG) cbData)
- goto FileError;
-
- if (mmioAscend(pwrite->hmmio, &ck, 0))
- goto FileError;
-
- if (!AddChunkToIndex(pwrite, &ck, dwFlags))
- return AVIERR_MEMORY;
-
- return AVIERR_OK;
-
- FileError:
- return AVIERR_FILEWRITE;
- }
-
- ///////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////
-
- /*****************************************************************************
- * @doc EXTERNAL
- *
- * @api LONG | avifileEndRecord | Mark the end of a record of data for
- * interleaved files.
- *
- * @parm HAVI | hfile | The handle returned from <f avifileOpen>.
- *
- * @rdesc Returns AVIERR_OK if successful, an error code otherwise.
- *
- * @xref avifileWrite
- ****************************************************************************/
- LONG FAR avifileEndRecord(HAVI hfile)
- {
- PPHYS pwrite = (PPHYS) hfile;
-
- if (pwrite->avihdr.dwFlags & AVIF_ISINTERLEAVED) {
- /* !!!! Pad here? */
-
- if (mmioAscend(pwrite->hmmio, &pwrite->ckRECORD, 0))
- goto FileError;
-
- pwrite->hpIndex[pwrite->dwIndexRec].dwChunkLength = pwrite->ckRECORD.cksize;
-
- /* Start the next 'rec' list */
- pwrite->ckRECORD.cksize = 0;
- pwrite->ckRECORD.fccType = listtypeAVIRECORD;
- if (mmioCreateChunk(pwrite->hmmio, &pwrite->ckRECORD, MMIO_CREATELIST)) {
- goto FileError;
- }
-
- pwrite->dwIndexRec = pwrite->dwIndex;
- if (!AddChunkToIndex(pwrite, &pwrite->ckRECORD, AVIIF_LIST))
- return AVIERR_MEMORY;
- }
-
- return AVIERR_OK;
-
- FileError:
- return AVIERR_FILEWRITE;
- }
-
- ///////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////
-
- /*****************************************************************************
- * @doc EXTERNAL
- *
- * @api LONG | avifileClose | Finish writing and close an AVI file.
- *
- * @parm HAVI | hfile | The handle returned from <f avifileOpen>.
- *
- * @rdesc Returns AVIERR_OK if successful, an error code otherwise.
- *
- * @xref avifileOpen
- ****************************************************************************/
- LONG FAR avifileClose(HAVI hfile)
- {
- PPHYS pwrite = (PPHYS) hfile;
- int stream;
- MMCKINFO ck;
- MMCKINFO ckRIFF;
- MMCKINFO ckLIST;
- MMCKINFO ckStream;
- LONG lCur;
- LONG lRet = AVIERR_OK;
-
- // Make the main header
- if (pwrite->avihdr.dwMicroSecPerFrame == 0) {
- pwrite->avihdr.dwMicroSecPerFrame =
- muldiv32(1000000L,
- pwrite->strhdr[0].dwScale,
- pwrite->strhdr[0].dwRate);
- }
-
- pwrite->avihdr.dwFlags |= AVIF_HASINDEX;
- pwrite->avihdr.dwFlags &= ~(AVIF_ISINTERLEAVED | AVIF_WASCAPTUREFILE |
- AVIF_MUSTUSEINDEX);
-
- pwrite->avihdr.dwTotalFrames = pwrite->strhdr[0].dwLength; // !!!
- pwrite->avihdr.dwInitialFrames = 0; // !!!
-
- // Go back and write out the header
-
- lCur = mmioSeek(pwrite->hmmio, 0, SEEK_CUR);
- mmioSeek(pwrite->hmmio, 0, SEEK_SET);
-
- /* Create RIFF chunk */
- ckRIFF.cksize = 0;
- ckRIFF.fccType = formtypeAVI;
- if (mmioCreateChunk(pwrite->hmmio, &ckRIFF, MMIO_CREATERIFF)) {
- goto FileError;
- }
-
- /* Create header list */
- ckLIST.cksize = 0;
- ckLIST.fccType = listtypeAVIHEADER;
- if (mmioCreateChunk(pwrite->hmmio, &ckLIST, MMIO_CREATELIST)) {
- goto FileError;
- }
-
- /* Create AVI header chunk */
- ck.cksize = sizeof(pwrite->avihdr);
- ck.ckid = ckidAVIMAINHDR;
- if (mmioCreateChunk(pwrite->hmmio, &ck, 0)) {
- goto FileError;
- }
-
- /* Write AVI header info */
- if (mmioWrite(pwrite->hmmio,
- (LPSTR)&pwrite->avihdr,
- sizeof(pwrite->avihdr)) != sizeof(pwrite->avihdr)) {
- goto FileError;
- }
-
- if (mmioAscend(pwrite->hmmio, &ck, 0)) {
- goto FileError;
- }
-
- for (stream = 0; stream < (int) pwrite->avihdr.dwStreams; stream++) {
- /* Create stream header list */
- ckStream.cksize = 0;
- ckStream.fccType = listtypeSTREAMHEADER;
- if (mmioCreateChunk(pwrite->hmmio,&ckStream,MMIO_CREATELIST)) {
- goto FileError;
- }
-
- ck.ckid = ckidSTREAMHEADER;
- if (mmioCreateChunk(pwrite->hmmio, &ck, 0)) {
- goto FileError;
- }
-
- if (mmioWrite(pwrite->hmmio,
- (LPVOID) &pwrite->strhdr[stream],
- sizeof(pwrite->strhdr[stream])) != sizeof(pwrite->strhdr[stream])) {
- goto FileError;
- }
-
- if (mmioAscend(pwrite->hmmio, &ck, 0)) {
- goto FileError;
- }
-
-
- ck.cksize = pwrite->cbFormat[stream];
- ck.ckid = ckidSTREAMFORMAT;
-
- if (mmioCreateChunk(pwrite->hmmio, &ck, 0))
- goto FileError;
-
- if (mmioWrite(pwrite->hmmio, pwrite->lpFormat[stream], ck.cksize) !=
- (LONG) ck.cksize)
- goto FileError;
-
- if (mmioAscend(pwrite->hmmio, &ck, 0))
- goto FileError;
-
- /* Ascend out of stream's header */
- if (mmioAscend(pwrite->hmmio, &ckStream, 0)) {
- goto FileError;
- }
- }
-
- /* ascend from the Header list */
- if (mmioAscend(pwrite->hmmio, &ckLIST, 0)) {
- goto FileError;
- }
-
- /* Pad this header out so that the real data will start on a 2K
- ** boundary by writing a JUNK chunk.
- */
- ck.ckid = ckidAVIPADDING;
- if (mmioCreateChunk(pwrite->hmmio,&ck,0)) {
- goto FileError;
- }
-
- if (mmioSeek(pwrite->hmmio, 0, SEEK_CUR) >
- (LONG) (pwrite->dwStart - 3 * sizeof(DWORD))) {
- // !!! Ack: we didn't leave enough space for the header.
- // !!! How can we avoid this?
- goto FileError;
- }
-
- mmioSeek(pwrite->hmmio, pwrite->dwStart - 3 * sizeof(DWORD), SEEK_SET);
-
- if (mmioAscend(pwrite->hmmio, &ck, 0)) {
- goto FileError;
- }
-
- /* Start the 'movi' list, where all of the actual data will be. */
- ckLIST.cksize = 0;
- ckLIST.fccType = listtypeAVIMOVIE;
- if (mmioCreateChunk(pwrite->hmmio, &ckLIST, MMIO_CREATELIST)) {
- goto FileError;
- }
-
- mmioSeek(pwrite->hmmio, lCur, SEEK_SET);
-
- if (mmioAscend(pwrite->hmmio, &ckLIST, 0))
- goto FileError;
-
- /*
- ** Now write index out!
- */
- if (!WriteIndex(pwrite))
- goto FileError;
-
- FinishUp:
- if (mmioAscend(pwrite->hmmio, &ckRIFF, 0))
- goto FileError;
-
- if (mmioFlush(pwrite->hmmio, 0))
- goto FileError;
-
- /* Close the file */
- if (mmioClose(pwrite->hmmio, 0))
- goto FileError;
-
-
- GlobalFreePtr(pwrite); // C6 doesn't like this line
-
- return lRet;
-
- FileError:
- lRet = AVIERR_FILEWRITE;
- goto FinishUp;
- }
- ///////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////
-
- /* Internal indexing functions.... */
-
- #define INDEXALLOC 256
-
- static BOOL NEAR PASCAL InitIndex(PPHYS pphys)
- {
- pphys->hpIndex = (AVIINDEXENTRY huge *)
- GlobalAllocPtr(GMEM_MOVEABLE,
- INDEXALLOC * sizeof(AVIINDEXENTRY));
- if (!pphys->hpIndex)
- return FALSE;
- pphys->dwIndex = 0;
- pphys->dwIndexAlloc = INDEXALLOC;
- return TRUE;
- }
-
- static BOOL NEAR PASCAL AddChunkToIndex(PPHYS pphys, MMCKINFO FAR *lpck, DWORD dwFlags)
- {
- if (pphys->dwIndex == pphys->dwIndexAlloc) {
- AVIINDEXENTRY huge * hp;
-
- hp = (AVIINDEXENTRY huge *)
- GlobalReAllocPtr(pphys->hpIndex,
- (pphys->dwIndexAlloc + INDEXALLOC) * sizeof(AVIINDEXENTRY),
- GMEM_MOVEABLE);
- if (!hp)
- return FALSE;
-
- pphys->hpIndex = hp;
- pphys->dwIndexAlloc += INDEXALLOC;
- }
-
- /* Record the position of the chunk we just wrote out. */
- pphys->hpIndex[pphys->dwIndex].ckid = lpck->ckid;
- pphys->hpIndex[pphys->dwIndex].dwChunkLength = lpck->cksize;
- /* dwChunkOffset is the offset of the chunk itself, not the
- ** data contained in the chunk....
- */
- // !!! fix to write out relative indexes!
- pphys->hpIndex[pphys->dwIndex].dwChunkOffset =
- lpck->dwDataOffset - 2 * sizeof(DWORD);
- pphys->hpIndex[pphys->dwIndex].dwFlags = dwFlags;
- pphys->dwIndex++;
-
- return TRUE;
- }
-
- static BOOL NEAR PASCAL WriteIndex(PPHYS pphys)
- {
- MMCKINFO ck;
-
- ck.ckid = ckidAVINEWINDEX;
- ck.cksize = sizeof(AVIINDEXENTRY) * pphys->dwIndex;
-
- if (mmioCreateChunk(pphys->hmmio, &ck, 0))
- return FALSE;
-
- if (mmioWrite(pphys->hmmio, (HPSTR) pphys->hpIndex, ck.cksize) !=
- (LONG) ck.cksize)
- return FALSE;
-
- if (mmioAscend(pphys->hmmio, &ck, 0))
- return FALSE;
-
- return TRUE;
- }
-
-
-
-
- /*****************************************************************************
- * @doc EXTERNAL
- *
- * @api LONG | aviVideoOpen | Helper function for writing AVI files consisting
- * only of a single video stream.
- *
- * @parm HAVI FAR * | lphfile | Holds the returned file handle if the
- * function succeeds.
- *
- * @parm LPSTR | lpFileName | The file name to use.
- *
- * @parm LPBITMAPINFOHEADER | lpbi | The format of the video to be written.
- *
- * @parm DWORD | dwMicroSecPerFrame | The spacing of frames in time. If
- * zero, a default of 15 frames/sec will be used.
- *
- * @rdesc Returns AVIERR_OK if successful, an error code otherwise.
- *
- * @xref avifileOpen
- ****************************************************************************/
- LONG FAR aviVideoOpen(HAVI FAR *lphfile,
- LPSTR lpFileName,
- LPBITMAPINFOHEADER lpbi,
- DWORD dwMicroSecPerFrame)
- {
- LONG l;
- MainAVIHeader hdrNew;
- AVIStreamHeader strhdr;
-
- if (dwMicroSecPerFrame == 0)
- dwMicroSecPerFrame = 1000000L/15;
-
- _fmemset(&hdrNew, 0, sizeof(hdrNew));
- hdrNew.dwMicroSecPerFrame = dwMicroSecPerFrame;
- hdrNew.dwMaxBytesPerSec = 0;
- hdrNew.dwPaddingGranularity = 0;
-
- hdrNew.dwFlags = AVIF_HASINDEX;
- hdrNew.dwTotalFrames = 0;
-
- hdrNew.dwStreams = 1;
- hdrNew.dwSuggestedBufferSize = 0;
-
- hdrNew.dwWidth = lpbi->biWidth;
- hdrNew.dwHeight = lpbi->biHeight;
-
- l = avifileOpen(lphfile, lpFileName, &hdrNew);
-
- if (l != AVIERR_OK)
- return l;
-
- _fmemset(&strhdr, 0, sizeof(strhdr));
- strhdr.fccType = streamtypeVIDEO;
- strhdr.fccHandler = 0;
- strhdr.dwScale = dwMicroSecPerFrame;
- strhdr.dwRate = 1000000;
- strhdr.dwSuggestedBufferSize = lpbi->biSizeImage;
-
- l = avifileAddStream(*lphfile, NULL, &strhdr, lpbi,
- lpbi->biSize + lpbi->biClrUsed * sizeof(RGBQUAD));
-
- if (l != AVIERR_OK)
- avifileClose(*lphfile);
-
-
- return l;
- }
-
-
- /*****************************************************************************
- * @doc EXTERNAL
- *
- * @api LONG | avifileWrite | Write data to an AVI file.
- *
- * @parm HAVI | hfile | The handle returned from <f avifileOpen>.
- *
- * @parm LPBITMAPINFOHEADER | lpbi | The format of the frame to write.
- *
- * @parm LPVOID | lpData | A pointer to the bits to write.
- *
- * @parm DWORD | dwFlags | Flags associated with this data. In particular:
- *
- * @flag AVIIF_KEYFRAME | This data represents a key frame.
- *
- * @rdesc Returns AVIERR_OK if successful, an error code otherwise.
- *
- * @xref avifileWrite
- ****************************************************************************/
- LONG FAR aviVideoWriteFrame(HAVI hfile, LPBITMAPINFOHEADER lpbi, LPVOID lp, DWORD dwFlags)
- {
- if (lpbi == NULL)
- return -1;
-
- if (lp == NULL)
- lp = (LPBYTE) lpbi + lpbi->biSize + lpbi->biClrUsed * sizeof(RGBQUAD);
-
- return avifileWrite(hfile, 0, lp, lpbi->biSizeImage,
- (lpbi->biCompression ? cktypeDIBcompressed : cktypeDIBbits),
- dwFlags);
- }
-