/****************************************************************************/
/*                                                                          */
/*        AVIFMT.H - Include file for working with AVI files                */
/*                                                                          */
/*        Note: You must include WINDOWS.H and MMSYSTEM.H before            */
/*        including this file.                                              */
/*                                                                          */
/*        Copyright 1991 - 1998, Microsoft Corp.  All rights reserved.      */
/*                                                                          */
/*                                                                          */
/****************************************************************************/

#ifndef _INC_AVIFMT
#define _INC_AVIFMT 100 /* version number * 100 + revision */

#ifdef __cplusplus
extern "C" {            /* Assume C declarations for C++ */
#endif  /* __cplusplus */

// begin_vfw32

#ifdef _MSC_VER
#pragma warning(disable:4200)
#endif

/* The following is a short description of the AVI file format.  Please
 * see the accompanying documentation for a full explanation.
 *
 * An AVI file is the following RIFF form:
 *
 *  RIFF('AVI'
 *        LIST('hdrl'
 *          avih(<MainAVIHeader>)
 *                  LIST ('strl'
 *                      strh(<Stream header>)
 *                      strf(<Stream format>)
 *                      ... additional header data
 *            LIST('movi'   
 *            { LIST('rec'
 *                    SubChunk...
 *                 )
 *                | SubChunk } .... 
 *            )
 *            [ <AVIIndex> ]
 *      )
 *
 *  The main file header specifies how many streams are present.  For
 *  each one, there must be a stream header chunk and a stream format
 *  chunk, enlosed in a 'strl' LIST chunk.  The 'strf' chunk contains
 *  type-specific format information; for a video stream, this should
 *  be a BITMAPINFO structure, including palette.  For an audio stream,
 *  this should be a WAVEFORMAT (or PCMWAVEFORMAT) structure.
 *
 *  The actual data is contained in subchunks within the 'movi' LIST
 *  chunk.  The first two characters of each data chunk are the
 *  stream number with which that data is associated.
 *
 *  Some defined chunk types:
 *           Video Streams:
 *                  ##db:   RGB DIB bits
 *                  ##dc:   RLE8 compressed DIB bits
 *                  ##pc:   Palette Change
 *
 *           Audio Streams:
 *                  ##wb:   waveform audio bytes
 *
 * The grouping into LIST 'rec' chunks implies only that the contents of
 *   the chunk should be read into memory at the same time.  This
 *   grouping is used for files specifically intended to be played from
 *   CD-ROM.
 *
 * The index chunk at the end of the file should contain one entry for
 *   each data chunk in the file.
 *
 * Limitations for the current software:
 *  Only one video stream and one audio stream are allowed.
 *  The streams must start at the beginning of the file.
 *
 *
 * To register codec types please obtain a copy of the Multimedia
 * Developer Registration Kit from:
 *
 *  Microsoft Corporation
 *  Multimedia Systems Group
 *  Product Marketing
 *  One Microsoft Way
 *  Redmond, WA 98052-6399
 *
 */

#ifndef mmioFOURCC
#define mmioFOURCC( ch0, ch1, ch2, ch3 )                \
        ( (DWORD)(BYTE)(ch0) | ( (DWORD)(BYTE)(ch1) << 8 ) |    \
        ( (DWORD)(BYTE)(ch2) << 16 ) | ( (DWORD)(BYTE)(ch3) << 24 ) )
#endif

/* Macro to make a TWOCC out of two characters */
#ifndef aviTWOCC
#define aviTWOCC(ch0, ch1) ((WORD)(BYTE)(ch0) | ((WORD)(BYTE)(ch1) << 8))
#endif

typedef WORD TWOCC;

/* form types, list types, and chunk types */
#define formtypeAVI             mmioFOURCC('A', 'V', 'I', ' ')
#define listtypeAVIHEADER       mmioFOURCC('h', 'd', 'r', 'l')
#define ckidAVIMAINHDR          mmioFOURCC('a', 'v', 'i', 'h')
#define listtypeSTREAMHEADER    mmioFOURCC('s', 't', 'r', 'l')
#define ckidSTREAMHEADER        mmioFOURCC('s', 't', 'r', 'h')
#define ckidSTREAMFORMAT        mmioFOURCC('s', 't', 'r', 'f')
#define ckidSTREAMHANDLERDATA   mmioFOURCC('s', 't', 'r', 'd')
#define ckidSTREAMNAME      mmioFOURCC('s', 't', 'r', 'n')

#define listtypeAVIMOVIE        mmioFOURCC('m', 'o', 'v', 'i')
#define listtypeAVIRECORD       mmioFOURCC('r', 'e', 'c', ' ')

#define ckidAVINEWINDEX         mmioFOURCC('i', 'd', 'x', '1')

/*
** Stream types for the <fccType> field of the stream header.
*/
#define streamtypeVIDEO         mmioFOURCC('v', 'i', 'd', 's')
#define streamtypeAUDIO         mmioFOURCC('a', 'u', 'd', 's')
#define streamtypeMIDI      mmioFOURCC('m', 'i', 'd', 's')
#define streamtypeTEXT          mmioFOURCC('t', 'x', 't', 's')

/* Basic chunk types */
#define cktypeDIBbits           aviTWOCC('d', 'b')
#define cktypeDIBcompressed     aviTWOCC('d', 'c')
#define cktypePALchange         aviTWOCC('p', 'c')
#define cktypeWAVEbytes         aviTWOCC('w', 'b')

/* Chunk id to use for extra chunks for padding. */
#define ckidAVIPADDING          mmioFOURCC('J', 'U', 'N', 'K')

/*
** Useful macros
**
** Warning: These are nasty macro, and MS C 6.0 compiles some of them
** incorrectly if optimizations are on.  Ack.
*/

/* Macro to get stream number out of a FOURCC ckid */
#define FromHex(n)  (((n) >= 'A') ? ((n) + 10 - 'A') : ((n) - '0'))
#define StreamFromFOURCC(fcc) ((WORD) ((FromHex(LOBYTE(LOWORD(fcc))) << 4) + \
                                             (FromHex(HIBYTE(LOWORD(fcc))))))

/* Macro to get TWOCC chunk type out of a FOURCC ckid */
#define TWOCCFromFOURCC(fcc)    HIWORD(fcc)

/* Macro to make a ckid for a chunk out of a TWOCC and a stream number
** from 0-255.
*/
#define ToHex(n)    ((BYTE) (((n) > 9) ? ((n) - 10 + 'A') : ((n) + '0')))
#define MAKEAVICKID(tcc, stream) \
        MAKELONG((ToHex((stream) & 0x0f) << 8) | \
                (ToHex(((stream) & 0xf0) >> 4)), tcc)

/*
** Main AVI File Header
*/  
        
/* flags for use in <dwFlags> in AVIFileHdr */
#define AVIF_HASINDEX       0x00000010  // Index at end of file
#define AVIF_MUSTUSEINDEX   0x00000020
#define AVIF_ISINTERLEAVED  0x00000100
#define AVIF_TRUSTCKTYPE    0x00000800  // Use CKType to find key frames
#define AVIF_WASCAPTUREFILE 0x00010000
#define AVIF_COPYRIGHTED    0x00020000

/* The AVI File Header LIST chunk should be padded to this size */
#define AVI_HEADERSIZE  2048                    // size of AVI header list

typedef struct
{
    DWORD       dwMicroSecPerFrame; // frame display rate (or 0L)
    DWORD       dwMaxBytesPerSec;   // max. transfer rate
    DWORD       dwPaddingGranularity;   // pad to multiples of this
                                                // size; normally 2K.
    DWORD       dwFlags;        // the ever-present flags
    DWORD       dwTotalFrames;      // # frames in file
    DWORD       dwInitialFrames;
    DWORD       dwStreams;
    DWORD       dwSuggestedBufferSize;

    DWORD       dwWidth;
    DWORD       dwHeight;

    DWORD       dwReserved[4];
} MainAVIHeader;

/*
** Stream header
*/

#define AVISF_DISABLED          0x00000001

#define AVISF_VIDEO_PALCHANGES      0x00010000

typedef struct {
    FOURCC      fccType;
    FOURCC      fccHandler;
    DWORD       dwFlags;    /* Contains AVITF_* flags */
    WORD        wPriority;
    WORD        wLanguage;
    DWORD       dwInitialFrames;
    DWORD       dwScale;    
    DWORD       dwRate; /* dwRate / dwScale == samples/second */
    DWORD       dwStart;
    DWORD       dwLength; /* In units above... */
    DWORD       dwSuggestedBufferSize;
    DWORD       dwQuality;
    DWORD       dwSampleSize;
    RECT        rcFrame;
} AVIStreamHeader;

/* Flags for index */
#define AVIIF_LIST          0x00000001L // chunk is a 'LIST'
#define AVIIF_KEYFRAME      0x00000010L // this frame is a key frame.

#define AVIIF_NOTIME        0x00000100L // this frame doesn't take any time
#define AVIIF_COMPUSE       0x0FFF0000L // these bits are for compressor use

typedef struct
{
    DWORD       ckid;
    DWORD       dwFlags;
    DWORD       dwChunkOffset;      // Position of chunk
    DWORD       dwChunkLength;      // Length of chunk
} AVIINDEXENTRY;

/*
** Palette change chunk
**
** Used in video streams.
*/
typedef struct
{
    BYTE        bFirstEntry;    /* first entry to change */
    BYTE        bNumEntries;    /* # entries to change (0 if 256) */
    WORD        wFlags;     /* Mostly to preserve alignment... */
    PALETTEENTRY    peNew[];    /* New color specifications */
} AVIPALCHANGE;

// end_vfw32

#ifdef __cplusplus
}                       /* End of extern "C" { */
#endif  /* __cplusplus */

#endif /* _INC_AVIFMT */