//==========================================================================;
//
//  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
//  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
//  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
//  PURPOSE.
//
//  Copyright (c) 1992 - 1996  Microsoft Corporation.  All Rights Reserved.
//
//--------------------------------------------------------------------------;

// Extended streaming interface definitions for the ActiveMovie streaming and
// synchronisation architecture. Core streaming interfaces are in AXCore.idl,
// and control interfaces for the type library are in Control.odl

// include after unknwn.idl, objidl.idl and axcore.idl


// forward declarations - these are the interfaces declared in this file

interface IEnumRegFilters;
interface IFileSourceFilter;
interface IFileSinkFilter;
interface IFileSinkFilter2;
interface IGraphBuilder;
interface ICaptureGraphBuilder;
interface IAMCopyCaptureFileProgress;
interface IFilterMapper;
interface IFilterMapper2;
interface IMediaEventSink;
interface IOverlay;
interface IOverlayNotify;
interface IQualityControl;
interface ISeekingPassThru;
interface IAMStreamConfig;
interface IAMDevMemoryAllocator;
interface IAMDevMemoryControl;
interface IConfigInterleaving;
interface IConfigAviMux;
interface IAMVideoCompression;
interface IAMVfwCaptureDialogs;
interface IAMVfwCompressDialogs;
interface IAMDroppedFrames;
interface IAMAudioInputMixer;
interface IAMBufferNegotiation;
interface IAMAnalogVideoDecoder;
interface IAMVideoProcAmp;
interface IAMAnalogVideoEncoder;
interface IAMCameraControl;
interface IAMCrossbar;
interface IAMTVTuner;
interface IKsPropertySet;
interface IAMPhysicalPinInfo;
interface IAMExtDevice;
interface IAMExtTransport;
interface IAMTimecodeReader;
interface IAMTimecodeGenerator;
interface IAMTimecodeDisplay;


//==========================================================================
//==========================================================================
// IEnumRegFilters interface -- enumerates registered filters.
// enumerator interface returned from IFilterMapper::EnumMatchingFilters().
// based on IEnum pseudo-template
//==========================================================================
//==========================================================================

typedef struct {
    CLSID Clsid;             // class id of the filter
    LPWSTR Name;             // name of filter
} REGFILTER;

[
object,
uuid(56a868a4-0ad4-11ce-b03a-0020af0ba770),
pointer_default(unique)
]

// The point of the mapper is to avoid loading filters.  By looking in the
// registry we can reduce the number of filters which must be loaded and tried.
// This enumerator returns descriptors of filters (including the GUIDs that
// CoCreateInstance can instantiate).  The filters themselves are not loaded.

interface IEnumRegFilters : IUnknown {
    import "unknwn.idl";

    // The caller must use CoTaskMemFree to free each REGFILTER* returned
    // in the array.
    HRESULT Next
        ( [in]  ULONG cFilters,           // place this many filters...
          [out] REGFILTER ** apRegFilter, // ...in this array of REGFILTER*
          [out] ULONG * pcFetched         // actual count passed returned here
        );

    // I can't think why anyone would want to skip, so it's not implemented.
    // (anyone who thinks they know what they would be skipping over is probably
    // missing some piece of the jigsaw). This ALWAYS returns E_NOTIMPL.

    HRESULT Skip(
        [in] ULONG cFilters
    );

    HRESULT Reset(void);

    // No cloning either - also ALWAYS returns E_NOTIMPL.

    HRESULT Clone(
        [out] IEnumRegFilters **ppEnum
    );
}


typedef IEnumRegFilters *PENUMREGFILTERS;

//========================================================================
//========================================================================
// abstraction representing the registered information about filters.
// This allows properties of filters to be looked up without loading them.
//========================================================================
//========================================================================

[
object,
uuid(56a868a3-0ad4-11ce-b03a-0020af0ba770),
pointer_default(unique)
]
interface IFilterMapper : IUnknown {
    import "unknwn.idl";

    //==========================================================================
    // Registration functions.
    // A filter should be registered before any other use.
    // The registration can be NON_VOLATILE (i.e. permanent, do once ever)
    // or VOLATILE (once per boot of the system).
    // UnregisterFilter (obviously) removes the registration.
    // The action of any of the other calls on unregistered filters is undefined.
    // it will either work or you'll get an error, but I'm not saying which.
    //==========================================================================

    // Four predefined values controling the order in which filters are tried
    // for intelligent graph building.  Intermediate values are legal.
    // Any value <=MERIT_DO_NOT_USE will mean that the filter will never
    // be tried by the filtergrah to automatically complete a connection.

    enum { MERIT_PREFERRED     = 0x800000,
           MERIT_NORMAL        = 0x600000,
           MERIT_UNLIKELY      = 0x400000,
           MERIT_DO_NOT_USE    = 0x200000,
           MERIT_SW_COMPRESSOR = 0x100000,
           MERIT_HW_COMPRESSOR = 0x100050
         };

    // Register a filter

    HRESULT RegisterFilter
        ( [in] CLSID   clsid,    // GUID of the filter
          [in] LPCWSTR Name,     // Descriptive name for the filter
          [in] DWORD   dwMerit   // DO_NOT_USE, UNLIKELY, NORMAL or PREFERRED.
        );


    // Register an identifiable instance of a filter.  This deals with cases
    // such as two similar sound cards which are driven by the same driver,
    // but we want to choose which oif these cards the sound will come out of.
    // This is not needed if there is only one instance of the filter
    // (e.g. there is only one sound card in the machine) or if all instances
    // of the filter are equivalent.

    // The filter itself must have already been registered   // ??? Is that true?
    HRESULT RegisterFilterInstance
        ( [in]  CLSID  clsid,      // GUID of the filter
          [in]  LPCWSTR Name,      // Descriptive name of instance.
          [out] CLSID *MRId        // Returned Media Resource Id.  A
                                   // locally unique id for this instance
                                   // of this filter
        );


    HRESULT RegisterPin
        ( [in] CLSID   Filter,           // GUID of filter
          [in] LPCWSTR Name,             // Name of the pin
          [in] BOOL    bRendered,        // The filter renders this input
          [in] BOOL    bOutput,          // TRUE if this is an Output pin
          [in] BOOL    bZero,            // TRUE if OK for zero instances of pin
                                         // In this case you will have to Create
                                         // a pin to have even one instance
          [in] BOOL    bMany,            // TRUE if OK for many instances of pin
          [in] CLSID   ConnectsToFilter, // Filter it connects to if it has
                                         // subterranean connection, else NULL
          [in] LPCWSTR ConnectsToPin     // Name of pin it connects to
                                         // NULL for output pins
        );

    HRESULT RegisterPinType
        ( [in] CLSID   clsFilter,        // GUID of filter
          [in] LPCWSTR strName,          // Descriptive name of the pin
          [in] CLSID   clsMajorType,     // Major type of the data stream
          [in] CLSID   clsSubType        // Sub type of the data stream
        );


    HRESULT UnregisterFilter
        ( [in] CLSID  Filter             // GUID of filter
        );


    HRESULT UnregisterFilterInstance
        ( [in] CLSID  MRId               // Media Resource Id of this instance
        );


    HRESULT UnregisterPin
        ( [in] CLSID   Filter,           // GUID of filter
          [in] LPCWSTR Name              // Name of the pin
        );


    // Set *ppEnum to be an enumerator for filters matching the requirements.

    HRESULT EnumMatchingFilters
       ( [out] IEnumRegFilters **ppEnum  // enumerator returned
       , [in]  DWORD dwMerit             // at least this merit needed
       , [in]  BOOL  bInputNeeded        // need at least one input pin
       , [in]  CLSID clsInMaj            // input major type
       , [in]  CLSID clsInSub            // input sub type
       , [in]  BOOL  bRender             // must the input be rendered?
       , [in]  BOOL  bOututNeeded        // need at least one output pin
       , [in]  CLSID clsOutMaj           // output major type
       , [in]  CLSID clsOutSub           // output sub type
       );

}

// structure used to identify media types a pin handles. Used for
// registration through IFilterMapper and IFilterMapper2
//
typedef struct
{
    const CLSID * clsMajorType;
    const CLSID * clsMinorType;
} REGPINTYPES;

// describes pin for filter registration. Used for registration
// through IFilterMapper and IFilterMapper2
//
typedef struct
{
    LPWSTR           strName;

    // The filter renders this input
    BOOL             bRendered;

    // This is an Output pin
    BOOL             bOutput;

    // OK to have zero instances of pin In this case you will have to
    // Create a pin to have even one instance
    BOOL             bZero;

    // OK to create many instance of  pin
    BOOL             bMany;

    const CLSID *    clsConnectsToFilter;
    const WCHAR *    strConnectsToPin;

    UINT             nMediaTypes;
    const REGPINTYPES * lpMediaType;
} REGFILTERPINS;

// mediums (as defined in the Windows NT DDK) for registration with
// IFilterMapper2
//
typedef struct
{
    CLSID clsMedium;
    DWORD dw1;
    DWORD dw2;
} REGPINMEDIUM;

// flags for dwFlags in REFILTERPINS2
enum
{
    // OK to have zero instances of pin In this case you will have to
    // Create a pin to have even one instance
    REG_PINFLAG_B_ZERO = 0x1,

    // The filter renders this input
    REG_PINFLAG_B_RENDERER = 0x2,

    // OK to create many instance of  pin
    REG_PINFLAG_B_MANY = 0x4,

    // This is an Output pin
    REG_PINFLAG_B_OUTPUT = 0x8
};


// describes pin for filter registration through IFilterMapper2
typedef struct
{
    // combination of REG_PINFLAG flags
    DWORD dwFlags;

    // number of instances of the pin if known
    UINT             cInstances;

    UINT             nMediaTypes;
    [size_is(nMediaTypes)] const REGPINTYPES * lpMediaType;

    UINT             nMediums;
    [size_is(nMediums)] const REGPINMEDIUM *lpMedium;

    // pin category (for Kernel Streaming pins) as defined in the
    // Windows NT DDK
    const CLSID      *clsPinCategory;

} REGFILTERPINS2;

// describes filter for registration through IFilterMapper2
typedef struct
{
    DWORD dwVersion;            // 1 or 2
    DWORD dwMerit;

    /* unnamed union */
    [switch_is(dwVersion)] [switch_type(DWORD)] union
    {
        [case(1)]

            struct
            {
                ULONG cPins;
                [size_is(cPins)] const REGFILTERPINS *rgPins;
            };

        [case(2)]

            struct
            {
                ULONG cPins2;
                [size_is(cPins2)] const REGFILTERPINS2 *rgPins2;
            };

        [default]
            ;
    } ;

} REGFILTER2;



[
object,
uuid(b79bb0b0-33c1-11d1-abe1-00a0c905f375),
pointer_default(unique)
]
interface IFilterMapper2 : IUnknown {
    import "unknwn.idl";

    // create or rename ActiveMovie category
    HRESULT CreateCategory
        ( [in] REFCLSID clsidCategory,
          [in] DWORD dwCategoryMerit,
          [in] LPCWSTR Description
          );

    HRESULT UnregisterFilter
        ( [in] const CLSID *pclsidCategory,
          [in] const OLECHAR *szInstance,
          [in] REFCLSID Filter // GUID of filter
        );

    // Register a filter, pins, and media types under a category.
    HRESULT RegisterFilter
        ( [in] REFCLSID clsidFilter,     // GUID of the filter
          [in] LPCWSTR Name,             // Descriptive name for the filter

          // ppMoniker can be null. or *ppMoniker can contain the
          // moniker where this filter data will be written;
          // *ppMoniker will be set to null on return. or *ppMoniker
          // can be null in which case the moniker will be returned
          // with refcount.
          [in, out] IMoniker **ppMoniker,

          // can be null
          [in] const CLSID *pclsidCategory,

          // cannot be null
          [in] const OLECHAR *szInstance,

          // rest of filter and pin registration
          [in] const REGFILTER2 *prf2
        );

    // Set *ppEnum to be an enumerator for filters matching the
    // requirements.
    HRESULT EnumMatchingFilters
       ( [out] IEnumMoniker **ppEnum           // enumerator returned
       , [in]  DWORD dwFlags                   // 0
       , [in]  BOOL bExactMatch                // don't match wildcards
       , [in]  DWORD dwMerit                   // at least this merit needed
       , [in]  BOOL  bInputNeeded              // need at least one input pin
       , [in]  DWORD cInputTypes               // Number of input types to match
                                               // Any match is OK
       , [size_is(cInputTypes*2)]  const GUID *pInputTypes // input major+subtype pair array
       , [in]  const REGPINMEDIUM *pMedIn      // input medium
       , [in]  const CLSID *pPinCategoryIn     // input pin category
       , [in]  BOOL  bRender                   // must the input be rendered?
       , [in]  BOOL  bOutputNeeded             // need at least one output pin
       , [in]  DWORD cOutputTypes              // Number of output types to match
                                               // Any match is OK
       , [size_is(cOutputTypes*2)]  const GUID *pOutputTypes // output major+subtype pair array
       , [in]  const REGPINMEDIUM *pMedOut     // output medium
       , [in]  const CLSID *pPinCategoryOut    // output pin category
       );
}

//========================================================================
//========================================================================
// Defines IQualityControl interface
//
// Defines quality messages and allows a quality manager to install itself
// as the sink for quality messages.
//========================================================================
//========================================================================

typedef enum tagQualityMessageType {
    Famine,
    Flood
} QualityMessageType;

typedef struct tagQuality {
    QualityMessageType Type;
    long                Proportion;   // milli-units.  1000 = no change
                            // for Flood:
                            // What proportion of the media samples currently
                            // coming through are required in the future.
                            // 800 means please drop another 20%
                            // For Famine:
                            // How much to "keep in" e.g. 800 means send me
                            // 20% less e.g. by dropping 20% of the samples.
                            // 1100 would mean "I'm coping, send me more".
    REFERENCE_TIME       Late;
                            // How much you need to catch up by
    REFERENCE_TIME       TimeStamp;
                            // The stream time when this was generated (probably
                            // corresponds to the start time on some sample).
} Quality;

typedef IQualityControl *PQUALITYCONTROL;


[
object,
uuid(56a868a5-0ad4-11ce-b03a-0020af0ba770),
pointer_default(unique)
]
interface IQualityControl : IUnknown {

    // Notify the recipient that a quality change is requested.
    // pSelf is the IBaseFilter* of the sender.
    // this is sent from a filter
    // to (the quality manager or) an upstream peer.
    HRESULT Notify
        ( [in] IBaseFilter * pSelf,
          [in] Quality q
        );

    // Notify the recipient that future quality messages are to be sent
    // to iqc.  If piqc is NULL then quality messages are to default back to
    // the upstream peer.
    // This is sent from the quality manager to a filter.
    // The recipient should hold piqc as a WEAK reference,
    // i.e. do not AddRef it, do not Release it.
    HRESULT SetSink
        ( [in] IQualityControl * piqc
        );
}

//=====================================================================
//=====================================================================
// Definitions required for overlay transport
//=====================================================================
//=====================================================================


// Used to communicate the colour that the IOverlay client wants the window
// painted in so that it can draw directly to the correct clipping region
// A colour key can be described in two alternate ways, the first is by a
// range of one or more (system) palette indices. The second is by defining
// a colour cube with two RGB values, any of which would be acceptable.
//
// The CK values are consistent with GDI PALETTEINDEX and PALETTERGB macros


enum { CK_NOCOLORKEY = 0x0,     // No color key is required
       CK_INDEX       = 0x1,    // Index into the current system palette
       CK_RGB         = 0x2 };  // Color key is an RGB value (or range)

typedef struct tagCOLORKEY {

    DWORD    KeyType;           // Explains meaning of the structure
    DWORD    PaletteIndex;      // Palette index if available
    COLORREF LowColorValue;     // Low colour space RGB value
    COLORREF HighColorValue;    // Defines the high RGB value

} COLORKEY;

// When a filter sets up an advise link it can ask that only certain types
// of notifications be sent, for example just palette changes. While this
// doesn't mean that the other notification call backs won't ever be called
// the IOverlay implementation may use this as an efficiency optimisation

enum { ADVISE_NONE = 0x0,               // No notifications required
       ADVISE_CLIPPING = 0x1,           // Synchronous clip information
       ADVISE_PALETTE = 0x2,            // Palette change notifications
       ADVISE_COLORKEY = 0x4,           // Called when colour key changes
       ADVISE_POSITION = 0x8 };         // Likewise when window moves etc

const DWORD ADVISE_ALL = ADVISE_CLIPPING |
                         ADVISE_PALETTE |
                         ADVISE_COLORKEY |
                         ADVISE_POSITION;

// This isn't defined when you run IDL

cpp_quote("#ifndef _WINGDI_")

typedef struct _RGNDATAHEADER {
    DWORD dwSize;
    DWORD iType;
    DWORD nCount;
    DWORD nRgnSize;
    RECT  rcBound;
} RGNDATAHEADER;

typedef struct _RGNDATA {
    RGNDATAHEADER rdh;
    char Buffer[1];
} RGNDATA;

cpp_quote("#endif")


//=====================================================================
//=====================================================================
// Defines IOverlayNotify interface
//
// This interface gives asynchronous notifications of changes to the
// rendering window - such as changes to the exposed window area
//=====================================================================
//=====================================================================

[
object,
local,
uuid(56a868a0-0ad4-11ce-b03a-0020af0ba770),
pointer_default(unique)
]
interface IOverlayNotify : IUnknown {

    // IOverlayNotify methods

    // This notifies the filter of palette changes, the filter should copy
    // the array of RGBQUADs if it needs to use them after returning. This
    // is not called when the palette is actually changed in the display
    // but at a short time after (in sync with WM_PALETTECHANGED messages)

    HRESULT OnPaletteChange(
        [in] DWORD dwColors,                // Number of colours present
        [in] const PALETTEENTRY *pPalette); // Array of palette colours

    // This provides synchronous clip changes so that the client is called
    // before the window is moved to freeze the video, and then when the
    // window has stabilised it is called again to start playback again.
    // If the window rect is all zero then the window is invisible, the
    // filter must take a copy of the information if it wants to keep it

    HRESULT OnClipChange(
        [in] const RECT *pSourceRect,       // Region of video to use
        [in] const RECT *pDestinationRect,  // Where video goes
        [in] const RGNDATA *pRgnData);      // Defines clipping information

    HRESULT OnColorKeyChange([in] const COLORKEY *pColorKey);

    // The calls to OnClipChange happen in sync with the window. So it is
    // called with an empty clip list before the window moves to freeze
    // the video, and then when the window has stabilised it is called
    // again with the new clip list. The OnPositionChange callback is for
    // overlay cards that don't want the expense of synchronous clipping
    // updates and just want to know when the source or destination video
    // positions change. They will NOT be called in sync with the window
    // but at some point after the window has changed (basicly in time
    // with WM_SIZE etc messages received). This is therefore suitable
    // for overlay cards that don't inlay their data to the frame buffer
    // NOTE the destination is NOT clipped to the visible display area

    HRESULT OnPositionChange([in] const RECT *pSourceRect,
                             [in] const RECT *pDestinationRect);
}

typedef IOverlayNotify *POVERLAYNOTIFY;


//=====================================================================
//=====================================================================
// Defines IOverlay interface
//
// This interface provides information so that a filter can write direct to
// the frame buffer while placing the video in the correct window position
//=====================================================================
//=====================================================================

[
object,
local,
uuid(56a868a1-0ad4-11ce-b03a-0020af0ba770),
pointer_default(unique)
]
interface IOverlay : IUnknown {

    // IOverlay methods

    HRESULT GetPalette(
        [out] DWORD *pdwColors,              // Number of colours present
        [out] PALETTEENTRY **ppPalette);     // Where to put palette data

    HRESULT SetPalette(
        [in] DWORD dwColors,                 // Number of colours present
        [in] PALETTEENTRY *pPalette);        // Colours to use for palette

    // If you change the colour key through SetColorKey then all the advise
    // links will receive an OnColorKeyChange callback with the new colour

    HRESULT GetDefaultColorKey([out] COLORKEY *pColorKey);
    HRESULT GetColorKey([out] COLORKEY *pColorKey);
    HRESULT SetColorKey([in,out] COLORKEY *pColorKey);
    HRESULT GetWindowHandle([out] HWND *pHwnd);

    // The IOverlay implementation allocates the memory for the clipping
    // rectangles as it can be variable in length. The filter calling
    // this method should free the memory when it is finished with it

    HRESULT GetClipList([out] RECT *pSourceRect,
                        [out] RECT *pDestinationRect,
                        [out] RGNDATA **ppRgnData);

    // Returns the current video source and destination

    HRESULT GetVideoPosition([out] RECT *pSourceRect,
                             [out] RECT *pDestinationRect);

    HRESULT Advise(
        [in] IOverlayNotify *pOverlayNotify, // Notification interface
        [in] DWORD dwInterests);             // Callbacks interested in

    HRESULT Unadvise();                      // Stop the callbacks now
}

typedef IOverlay *POVERLAY;


//=====================================================================
//=====================================================================
// control related interfaces (others are defined in control.odl)
//=====================================================================
//=====================================================================


//=====================================================================
//=====================================================================
// Defines IMediaEventSink interface
//
// Exposed by filtergraph. Called by filters to notify events. Will be
// passed on to application by the IMediaControl event methods.
//=====================================================================
//=====================================================================

[
        object,
        uuid(56a868a2-0ad4-11ce-b03a-0020af0ba770),
        pointer_default(unique)
]
interface IMediaEventSink : IUnknown {

    // notify an event. will be queued, but not delivered to
    // the application on this thread.
    HRESULT Notify(
        [in] long EventCode,
        [in] long EventParam1,
        [in] long EventParam2
    );
}

typedef IMediaEventSink *PMEDIAEVENTSINK;

//=====================================================================
//=====================================================================
// Defines IFileSourceFilter interface
//
// Exposed by source filters to set the file name and media type.
//=====================================================================
//=====================================================================

[
        object,
        uuid(56a868a6-0ad4-11ce-b03a-0020af0ba770),
        pointer_default(unique)
]
interface IFileSourceFilter : IUnknown {

    // Load a file and assign it the given media type
    HRESULT Load(
        [in] LPCOLESTR pszFileName,     // Pointer to absolute path of file to open
        [in] const AM_MEDIA_TYPE *pmt   // Media type of file - can be NULL
    );
    // Get the currently loaded file name
    HRESULT GetCurFile(
        [out] LPOLESTR *ppszFileName,   // Pointer to the path for the current file
        [out] AM_MEDIA_TYPE *pmt        // Pointer to the media type
    );
}

typedef IFileSourceFilter *PFILTERFILESOURCE;

//=====================================================================
//=====================================================================
// Defines IFileSinkFilter interface
//
// Exposed by renderers to set the output file name.
//=====================================================================
//=====================================================================

[
        object,
        uuid(a2104830-7c70-11cf-8bce-00aa00a3f1a6),
        pointer_default(unique)
]
interface IFileSinkFilter : IUnknown {

    // Output to this file. default is to open the existing file
    HRESULT SetFileName(
        [in] LPCOLESTR pszFileName,     // Pointer to absolute path of output file
        [in] const AM_MEDIA_TYPE *pmt   // Media type of file - can be NULL
    );
    // Get the current file name
    HRESULT GetCurFile(
        [out] LPOLESTR *ppszFileName,   // Pointer to the path for the current file
        [out] AM_MEDIA_TYPE *pmt        // Pointer to the media type
    );
}

typedef IFileSinkFilter *PFILTERFILESINK;

[
        object,
        uuid(00855B90-CE1B-11d0-BD4F-00A0C911CE86),
        pointer_default(unique)
]
interface IFileSinkFilter2 : IFileSinkFilter {

    HRESULT SetMode(
        [in] DWORD dwFlags              // AM_FILESINK_FLAGS
    );

    HRESULT GetMode(
        [out] DWORD *pdwFlags           // AM_FILESINK_FLAGS
    );
}

typedef IFileSinkFilter2 *PFILESINKFILTER2;

typedef enum {

    // create a new file
    AM_FILE_OVERWRITE = 0x00000001,

} AM_FILESINK_FLAGS;


//=====================================================================
//=====================================================================
// Defines IFileAsyncIO interface
//
// Exposed by high performance file readers
//=====================================================================
//=====================================================================

typedef struct _AsyncIOReq {
   DWORD         engine[4];  // used by IO engine
   [size_is(cb)] BYTE * lpv; // points to buffer of data to be transferred
   DWORD         cb;         // size of data to be transferred

   // the following 4 fields intentionally mimic an OVERLAPPED structure
   //
   DWORD         dwError;    // on return, contains error/success code
   DWORD         cbDone;     // number of bytes actually transferred
   LARGE_INTEGER liPos;      // 64 bit seek location. on return contains read/write location
   DWORD         hEvent;     // handle (used to mimic OVERLAPPED structure)

   DWORD         dwUser;     // preserved, for user data
   } AsyncIOReq;

[
        object,
        uuid(56a868a7-0ad4-11ce-b03a-0020af0ba770),
        pointer_default(unique)
]
interface IFileAsyncIO : IUnknown {

    // query the required alignment for io buffers & sizes
    //
    HRESULT QueryAlignment (
        [out] LPDWORD  pdwAlign
    );

    // do async, aligned read from a specific location in the file
    //
    HRESULT Read (
        [in] AsyncIOReq * pReq
    );

    // do async, aligned write to a specific location in the file
    // the file may be extended as a result.
    //
    HRESULT Write (
        [in] AsyncIOReq * pReq
    );

    // wait for the next available read to complete, on success
    // returns the buffer pointer and
    //
    HRESULT WaitForNext (
        [out] AsyncIOReq **  ppReq,    // returns pointer to next request to complete
        [in]  DWORD          dwTimeout // how long to wait, 0 does not wait
    );

    // wait for a specific io request to complete
    //
    HRESULT WaitForSpecific (
        [out] AsyncIOReq * pReq,    // wait for this request to complete
        [in]  DWORD        dwTimeout
    );

    // discard all pending io and place all requests on the 'done' queue
    //
    HRESULT DiscardPending (void);

    // wait for all pending io's to be complete
    //
    HRESULT Flush (void);
}

typedef IFileAsyncIO * PFILEASYNCIO;


//
// Intelligent connectivity for filters - an interface supported by
// filter graphs (since it is an extension to IFilterGraph) that supports
// building of graphs by automatic selection and connection of appropriate
// filters

[
    object,
    local,
    uuid(56a868a9-0ad4-11ce-b03a-0020af0ba770),
    pointer_default(unique)
]
interface IGraphBuilder : IFilterGraph {
    // Connect these two pins directly or indirectly, using transform filters
    // if necessary.

    HRESULT Connect
        ( [in] IPin * ppinOut,    // the output pin
          [in] IPin * ppinIn      // the input pin
        );


    // Connect this output pin directly or indirectly, using transform filters
    // if necessary to something that will render it.

    HRESULT Render
        ( [in] IPin * ppinOut     // the output pin
        );


    // Build a filter graph that will render this file using this play list.
    // If lpwstrPlayList is NULL then it will use the default play list
    // which will typically render the whole file.

    HRESULT RenderFile
        ( [in] LPCWSTR lpcwstrFile,
          [in] LPCWSTR lpcwstrPlayList
        );


    // Add to the filter graph a source filter for this file.  This would
    // be the same source filter that would be added by calling Render.
    // This call gives you more control over building
    // the rest of the graph, e.g. AddFilter(<a renderer of your choice>)
    // and then Connect the two.
    // The IBaseFilter* interface exposed by the source filter is returned
    // in ppFilter, addrefed already for you
    // The filter will be known by the name lpcwstrFIlterName
    // nn this filter graph,
    HRESULT AddSourceFilter
        ( [in]      LPCWSTR lpcwstrFileName,
          [in]      LPCWSTR lpcwstrFilterName,
          [out]     IBaseFilter* *ppFilter
        );


    // If this call is made then trace information will be written to the
    // file showing the actions taken in attempting to perform an operation.
    HRESULT SetLogFile
        ( [in]      HANDLE hFile  // open file handle e.g. from CreateFile
        );


    // Request that the graph builder should return as soon as possible from
    // its current task.
    // Note that it is possible fot the following to occur in the following
    // sequence:
    //     Operation begins; Abort is requested; Operation completes normally.
    // This would be normal whenever the quickest way to finish an operation
    // was to simply continue to the end.
    HRESULT Abort();

    // Return S_OK if the curent operation is to continue,
    // return S_FALSE if the current operation is to be aborted.
    // This method can be called as a callback from a filter which is doing
    // some operation at the request of the graph.
    HRESULT ShouldOperationContinue();

}


//
// New capture graph builder

[
    object,
    local,
    uuid(bf87b6e0-8c27-11d0-b3f0-00aa003761c5),
    pointer_default(unique)
]
interface ICaptureGraphBuilder : IUnknown {

    // Use this filtergraph
    HRESULT SetFiltergraph(
	[in] IGraphBuilder *pfg);

    // what filtergraph are you using?
    // *ppfg->Release() when you're done with it
    HRESULT GetFiltergraph(
	[out] IGraphBuilder **ppfg);

    // creates a rendering section in the filtergraph consisting of a MUX
    // of some filetype, and a file writer (and connects them together)
    // *ppf->Release() when you're done with it
    // *ppSink->Release() when you're done with it
    HRESULT SetOutputFileName(
	[in] const GUID *pType,	// type of file to write, eg. MEDIASUBTYPE_Avi
	[in] LPCOLESTR lpstrFile,	// filename given to file writer
	[out] IBaseFilter **ppf,	// returns pointer to the MUX
        [out] IFileSinkFilter **ppSink);// queried from file writer

    // Looks for an interface on the filter and on the output pin of the given
    // category.  Possible categories are "capture" and "preview" and NULL for
    // "don't care". (And in the future "time code" and "VBI data").
    // It will also look upstream and downstream of
    // the pin for the interface, to find interfaces on renderers, MUXES, TV
    // Tuners, etc.
    // Call *ppint->Release() when you're done with it
    HRESULT FindInterface(
	[in] const GUID *pCategory,	// can be NULL for all pins
	[in] IBaseFilter *pf,
	[in] REFIID riid,
	[out] void **ppint);

    // Connects the pin of the given category of the source filter to the
    // rendering filter, optionally through another filter (compressor?)
    // For the "capture" category, it will
    // instantiate and connect additional required filters upstream too, like
    // TV Tuners and Crossbars (this part can only be done if you give a
    // Moniker) If there is only one output pin on the source, use a NULL
    // category.  You can also have pSource be a pin, and not use the moniker
    HRESULT RenderStream(
	[in] const GUID *pCategory,	// can be NULL if only one output pin
	[in] IUnknown *pSource,		// must match pMSource
	[in] IBaseFilter *pfCompressor,
	[in] IBaseFilter *pfRenderer);	// can be NULL

    // Sends IAMStreamControl messages to the pin of the desired category, eg.
    // "capture" or "preview"
    // REFERENCE_TIME=NULL means NOW
    // REFERENCE_TIME=MAX_TIME means never, or cancel previous request
    // NULL controls all capture filters in the graph - you will get one
    //     notification for each filter with a pin of that category found
    // returns S_FALSE if stop will be signalled before last sample is
    //     rendered.
    // return a FAILURE code if the filter does not support IAMStreamControl
    HRESULT ControlStream(
	[in] const GUID *pCategory,
	[in] IBaseFilter *pFilter,
	[in] REFERENCE_TIME *pstart,
	[in] REFERENCE_TIME *pstop,
	[in] WORD wStartCookie,		// high word reserved
	[in] WORD wStopCookie);		// high word reserved

    // creates a pre-allocated file of a given size in bytes
    HRESULT AllocCapFile(
	[in] LPCOLESTR lpstr,
	[in] DWORDLONG dwlSize);

    // Copies the valid file data out of the old, possibly huge old capture
    //   file into a shorter new file.
    // Return S_FALSE from your progress function to abort capture, S_OK to
    //   continue
    HRESULT CopyCaptureFile(
	[in] LPOLESTR lpwstrOld,
	[in] LPOLESTR lpwstrNew,
	[in] int fAllowEscAbort,	// pressing ESC will abort?
	[in] IAMCopyCaptureFileProgress *pCallback);	// implement this to
							// get progress
}


//
// Capture graph builder "CopyCapturedFile" progress callback

[
    object,
    uuid(670d1d20-a068-11d0-b3f0-00aa003761c5),
    pointer_default(unique)
]
interface IAMCopyCaptureFileProgress : IUnknown {

    // If you support this interface somewhere, this function will be called
    // periodically while ICaptureGraphBuilder::CopyCaptureFile is executing
    // to let you know the progress
    //
    // Return S_OK from this function to continue.  Return S_FALSE to abort the
    // copy
    HRESULT Progress(
	[in] int iProgress);		// a number between 0 and 100 (%)
}

enum _AM_RENSDEREXFLAGS {
    AM_RENDEREX_RENDERTOEXISTINGRENDERERS = 0x01 // Dont add any renderers
};

//
// IFilterGraph2
//
// New methods on for IFilterGraph and IGraphBuilder will have to go here.
//

[
    object,
    local,
    uuid(36b73882-c2c8-11cf-8b46-00805f6cef60),
    pointer_default(unique)
]
interface IFilterGraph2: IGraphBuilder {

    // Add a Moniker source moniker
    HRESULT AddSourceFilterForMoniker(
          [in] IMoniker *pMoniker,
          [in] IBindCtx *pCtx,
          [in] LPCWSTR lpcwstrFilterName,
          [out] IBaseFilter **ppFilter
    );

    // Specify the type for a reconnect
    // This is better than Reconnect as sometime the parties to a
    // reconnection can't remember what type they'd agreed (!)
    HRESULT ReconnectEx
        ( [in] IPin * ppin,             // the pin to disconnect and reconnect
          [in] const AM_MEDIA_TYPE *pmt // the type to reconnect with - can be NULL
        );

    // Render a pin without adding any new renderers
    HRESULT RenderEx( [in] IPin *pPinOut,         // Pin to render
                      [in] DWORD dwFlags,         // flags
                      [in, out] LPVOID pvContext   // Unused - set to NULL
                    );

#if 0
    // Method looks for a filter which supports the specified interface.  If such
    // a filter exists, an AddRef()'ed pointer to the requested interface is placed
    // in *ppInterface.
    //
    // *ppInterface will be NULL on return if such a filter could not be found, and
    // the method will return E_NOINTERFACE.
    //
    // pdwIndex is an internal index that is used for obtaining subsequent interfaces.
    // *pdwIndex should be initialized to zero.  It is set on return to a value that
    // allows the implementation of FindFilterInterface to search for further interfaces
    // if called again.  If no more such interfaces exist, the method will return E_NOINTERFACE.
    //
    // If pdwIndex is NULL, FindFilterInterface returns an interface only if there is just
    // a single filter in the graph that supports the interface.  Otherwise it returns
    // E_NOINTERFACE.
    //
    HRESULT FindFilterInterface( [in] REFIID iid, [out] void ** ppInterface, [in,out] LPDWORD pdwIndex );

    // Tries to obtain the interface from the filter graph itself.  If this fails,
    // it attempts to find the unique filter that supports the interface.
    // On failure the method will return E_NOINTERFACE.  On success, it returns
    // S_OK and an AddRef()'ed pointer to the requested interface in *ppInterface.
    //
    HRESULT FindInterface( [in] REFIID iid, [out] void ** ppInterface );

#endif
}

//
// StreamBuilder
// aka Graph building with constraints
// aka convergent graphs
// aka Closed captioning

[
    object,
    local,
    uuid(56a868bf-0ad4-11ce-b03a-0020af0ba770),
    pointer_default(unique)
]
interface IStreamBuilder : IUnknown {

    // Connect this output pin directly or indirectly, using transform filters
    // if necessary to thing(s) that will render it, within this graph
    // Move from Initial state to Rendered state.

    HRESULT Render
        ( [in] IPin * ppinOut,         // the output pin
          [in] IGraphBuilder * pGraph  // the graph
        );

    // Undo what you did in Render.  Return to Initial state.
    HRESULT Backout
        ( [in] IPin * ppinOut,         // the output pin
          [in] IGraphBuilder * pGraph  // the graph
        );
}


// async reader interface - supported by file source filters. Allows
// multiple overlapped reads from different positions


[
        object,
        uuid(56a868aa-0ad4-11ce-b03a-0020af0ba770),
        pointer_default(unique)
]
interface IAsyncReader : IUnknown
{
    // pass in your preferred allocator and your preferred properties.
    // method returns the actual allocator to be used. Call GetProperties
    // on returned allocator to learn alignment and prefix etc chosen.
    // this allocator will be not be committed and decommitted by
    // the async reader, only by the consumer.
    // Must call this before calling Request.
    HRESULT RequestAllocator(
                [in]  IMemAllocator* pPreferred,
                [in]  ALLOCATOR_PROPERTIES* pProps,
                [out] IMemAllocator ** ppActual);

    // queue a request for data.
    // media sample start and stop times contain the requested absolute
    // byte position (start inclusive, stop exclusive).
    // may fail if sample not obtained from agreed allocator.
    // may fail if start/stop position does not match agreed alignment.
    // samples allocated from source pin's allocator may fail
    // GetPointer until after returning from WaitForNext.
    // Stop position must be aligned - this means it may exceed duration.
    // on completion, stop position will be corrected to unaligned
    // actual data.
    HRESULT Request(
                [in] IMediaSample* pSample,
                [in] DWORD dwUser);	        // user context

    // block until the next sample is completed or the timeout occurs.
    // timeout (millisecs) may be 0 or INFINITE. Samples may not
    // be delivered in order. If there is a read error of any sort, a
    // notification will already have been sent by the source filter,
    // and HRESULT will be an error.
    // If ppSample is not null, then a Request completed with the result
    // code returned.
    HRESULT WaitForNext(
                [in]  DWORD dwTimeout,
                [out] IMediaSample** ppSample,  // completed sample
                [out] DWORD * pdwUser);		// user context

    // sync read of data. Sample passed in must have been acquired from
    // the agreed allocator. Start and stop position must be aligned.
    // equivalent to a Request/WaitForNext pair, but may avoid the
    // need for a thread on the source filter.
    HRESULT SyncReadAligned(
                [in] IMediaSample* pSample);


    // sync read. works in stopped state as well as run state.
    // need not be aligned. Will fail if read is beyond actual total
    // length.
    HRESULT SyncRead(
                [in]  LONGLONG llPosition,	// absolute file position
                [in]  LONG lLength,		// nr bytes required
                [out, size_is(lLength)]
		      BYTE* pBuffer);		// write data here

    // return total length of stream, and currently available length.
    // reads for beyond the available length but within the total length will
    // normally succeed but may block for a long period.
    HRESULT Length(
                [out] LONGLONG* pTotal,
                [out] LONGLONG* pAvailable);

    // cause all outstanding reads to return, possibly with a failure code
    //(VFW_E_TIMEOUT) indicating they were cancelled.
    // Between BeginFlush and EndFlush calls, Request calls will fail and
    // WaitForNext calls will always complete immediately.
    HRESULT BeginFlush(void);
    HRESULT EndFlush(void);
}


// interface provided by the filtergraph itself to let other objects
// (especially plug-in distributors, but also apps like graphedt) know
// when the graph has changed.
[
    object,
    uuid(56a868ab-0ad4-11ce-b03a-0020af0ba770),
    pointer_default(unique)
]
interface IGraphVersion : IUnknown
{
    // returns the current graph version number
    // this is incremented every time there is a change in the
    // set of filters in the graph or in their connections
    //
    // if this is changed since your last enumeration, then re-enumerate
    // the graph
    HRESULT QueryVersion(LONG* pVersion);
}




//
// interface describing an object that uses resources.
//
// implement if: you request resources using IResourceManager. You will
// need to pass your implementation of this pointer as an in param.
//
// use if: you are a resource manager who implements IResourceManager
[
    object,
    uuid(56a868ad-0ad4-11ce-b03a-0020af0ba770),
    pointer_default(unique)
]
interface IResourceConsumer : IUnknown
{
    // you may acquire the resource specified.
    // return values:
    //      S_OK    -- I have successfully acquired it
    //      S_FALSE -- I will acquire it and call NotifyAcquire afterwards
    //      VFW_S_NOT_NEEDED: I no longer need the resource
    //      FAILED(hr)-I tried to acquire it and failed.

    HRESULT
    AcquireResource(
        [in] LONG idResource);



    // Please release the resource.
    // return values:
    //      S_OK    -- I have released it (and want it again when available)
    //      S_FALSE -- I will call NotifyRelease when I have released it
    //      other   something went wrong.
    HRESULT
    ReleaseResource(
        [in] LONG idResource);
}



// interface describing a resource manager that will resolve contention for
// named resources.
//
// implement if: you are a resource manager. The filtergraph will be a resource
// manager, internally delegating to the system wide resource manager
// (when there is one)
//
// use if: you need resources that are limited. Use the resource manager to
// resolve contention by registering the resource with this interface,
// and requesting it from this interface whenever needed.
//
// or use if: you detect focus changes which should affect resource usage.
// Notifying change of focus to the resource manager will cause the resource
// manager to switch contended resources to the objects that have the user's
// focus
[
    object,
    uuid(56a868ac-0ad4-11ce-b03a-0020af0ba770),
    pointer_default(unique)
]
interface IResourceManager : IUnknown
{
    // tell the manager how many there are of a resource.
    // ok if already registered. will take new count. if new count
    // is lower, will de-allocate resources to new count.
    //
    // You get back a token that will be used in further calls.
    //
    // Passing a count of 0 will eliminate this resource. There is currently
    // no defined way to find the id without knowing the count.
    //
    HRESULT
    Register(
        [in] LPCWSTR pName,         // this named resource
        [in] LONG   cResource,      // has this many instances
        [out] LONG* plToken         // token placed here on return
        );

    HRESULT
    RegisterGroup(
        [in] LPCWSTR pName,         // this named resource group
        [in] LONG cResource,        // has this many resources
        [in, size_is(cResource)]
             LONG* palTokens,      // these are the contained resources
        [out] LONG* plToken        // group resource id put here on return
        );

    // request the use of a given, registered resource.
    // possible return values:
    //      S_OK == yes you can use it now
    //      S_FALSE == you will be called back when the resource is available
    //      other - there is an error.
    //
    // The priority of this request should be affected by the associated
    // focus object -- that is, when SetFocus is called for that focus
    // object (or a 'related' object) then my request should be put through.
    //
    // A filter should pass the filter's IUnknown here. The filtergraph
    // will match filters to the filtergraph, and will attempt to trace
    // filters to common source filters when checking focus objects.
    // The Focus object must be valid for the entire lifetime of the request
    // -- until you call CancelRequest or NotifyRelease(id, p, FALSE)
    HRESULT
    RequestResource(
        [in] LONG idResource,
        [in] IUnknown* pFocusObject,
        [in] IResourceConsumer* pConsumer
        );


    // notify the resource manager that an acquisition attempt completed.
    // Call this method after an AcquireResource method returned
    // S_FALSE to indicate asynchronous acquisition.
    // HR should be S_OK if the resource was successfully acquired, or a
    // failure code if the resource could not be acquired.
    HRESULT
    NotifyAcquire(
        [in] LONG idResource,
        [in] IResourceConsumer* pConsumer,
        [in] HRESULT hr);

    // Notify the resource manager that you have released a resource. Call
    // this in response to a ReleaseResource method, or when you have finished
    // with the resource. bStillWant should be TRUE if you still want the
    // resource when it is next available, or FALSE if you no longer want
    // the resource.
    HRESULT
    NotifyRelease(
        [in] LONG idResource,
        [in] IResourceConsumer* pConsumer,
        [in] BOOL bStillWant);

    // I don't currently have the resource, and I no longer need it.
    HRESULT
    CancelRequest(
        [in] LONG idResource,
        [in] IResourceConsumer* pConsumer);

    // Notify the resource manager that a given object has been given the
    // user's focus. In ActiveMovie, this will normally be a video renderer
    // whose window has received the focus. The filter graph will switch
    // contended resources to (in order):
    //      requests made with this same focus object
    //      requests whose focus object shares a common source with this
    //      requests whose focus object shares a common filter graph
    // After calling this, you *must* call ReleaseFocus before the IUnknown
    // becomes invalid, unless you can guarantee that another SetFocus
    // of a different object is done in the meantime. No addref is held.
    //
    // The resource manager will hold this pointer until replaced or cancelled,
    // and will use it to resolve resource contention. It will call
    // QueryInterface for IBaseFilter at least and if found will call methods on
    // that interface.
    HRESULT
    SetFocus(
        [in] IUnknown* pFocusObject);

    // Sets the focus to NULL if the current focus object is still
    // pFocusObject. Call this when
    // the focus object is about to be destroyed to ensure that no-one is
    // still referencing the object.
    HRESULT
    ReleaseFocus(
        [in] IUnknown* pFocusObject);



// !!! still need
//      -- app override (some form of SetPriority)
//      -- enumeration and description of resources

}


//
// Interface representing an object that can be notified about state
// and other changes within a filter graph. The filtergraph will call plug-in
// distributors that expose this optional interface so that they can
// respond to appropriate changes.
//
// Implement if: you are a plug-in distributor (your class id is found
// under HKCR\Interface\<IID>\Distributor= for some interface).
//
// Use if: you are the filtergraph.
[
    object,
    uuid(56a868af-0ad4-11ce-b03a-0020af0ba770),
    pointer_default(unique)
]
interface IDistributorNotify : IUnknown
{
    // called when graph is entering stop state. Called before
    // filters are stopped.
    HRESULT Stop(void);

    // called when graph is entering paused state, before filters are
    // notified
    HRESULT Pause(void);

    // called when graph is entering running state, before filters are
    // notified. tStart is the stream-time offset parameter that will be
    // given to each filter's IBaseFilter::Run method.
    HRESULT Run(REFERENCE_TIME tStart);

    // called when the graph's clock is changing, with the new clock. Addref
    // the clock if you hold it beyond this method. Called before
    // the filters are notified.
    HRESULT SetSyncSource(
        [in] IReferenceClock * pClock);

    // called when the set of filters or their connections has changed.
    // Called on every AddFilter, RemoveFilter or ConnectDirect (or anything
    // that will lead to one of these).
    // You don't need to rebuild your list of interesting filters at this point
    // but you should release any refcounts you hold on any filters that
    // have been removed.
    HRESULT NotifyGraphChange(void);
}

typedef enum {
    AM_STREAM_INFO_START_DEFINED = 0x00000001,
    AM_STREAM_INFO_STOP_DEFINED  = 0x00000002,
    AM_STREAM_INFO_DISCARDING    = 0x00000004,
    AM_STREAM_INFO_STOP_SEND_EXTRA = 0x00000010
} AM_STREAM_INFO_FLAGS;

//  Stream information
typedef struct {
    REFERENCE_TIME tStart;
    REFERENCE_TIME tStop;
    DWORD dwStartCookie;
    DWORD dwStopCookie;
    DWORD dwFlags;
} AM_STREAM_INFO;

//
// IAMStreamControl
//

[
    object,
    uuid(36b73881-c2c8-11cf-8b46-00805f6cef60),
    pointer_default(unique)
]
interface IAMStreamControl : IUnknown
{
    // The REFERENCE_TIME pointers may be null, which
    // indicates immediately.  If the pointer is non-NULL
    // and dwCookie is non-zero, then pins should send
    // EC_STREAM_CONTROL_STOPPED / EC_STREAM_CONTROL_STARTED
    // with an IPin pointer and the cookie, thus allowing
    // apps to tie the events back to their requests.
    // If either dwCookies is zero, or the pointer is null,
    // then no event is sent.

    // If you have a capture pin hooked up to a MUX input pin and they
    // both support IAMStreamControl, you'll want the MUX to signal the
    // stop so you know the last frame was written out.  In order for the
    // MUX to know it's finished, the capture pin will have to send one
    // extra sample after it was supposed to stop, so the MUX can trigger
    // off that.  So you would set bSendExtra to TRUE for the capture pin
    // Leave it FALSE in all other cases.

    HRESULT StartAt( [in] const REFERENCE_TIME * ptStart,
                     [in] DWORD dwCookie );
    HRESULT StopAt(  [in] const REFERENCE_TIME * ptStop,
                     [in] BOOL bSendExtra,
                     [in] DWORD dwCookie );
    HRESULT GetInfo( [out] AM_STREAM_INFO *pInfo);
}



//
// ISeekingPassThru
//

[
    object,
    uuid(36b73883-c2c8-11cf-8b46-00805f6cef60),
    pointer_default(unique)
]
interface ISeekingPassThru : IUnknown
{
    HRESULT Init(  [in] BOOL bSupportRendering,
				   [in] IPin *pPin);
}



//
// IAMStreamConfig - pin interface
//

// A capture filter or compression filter's output pin
// supports this interface - no matter what data type you produce.

// This interface can be used to set the output format of a pin (as an
// alternative to connecting the pin using a specific media type).
// After setting an output format, the pin will use that format
// the next time it connects to somebody, so you can just Render that
// pin and get a desired format without using Connect(CMediaType)
// Your pin should do that by ONLY OFFERING the media type set in SetFormat
// in its enumeration of media types, and no others.  This will ensure that
// that format is indeed used for connection (or at least offer it first).
// An application interested in enumerating accepted mediatypes may have to
// do so BEFORE calling SetFormat.

// But this interface's GetStreamCaps function can get more information
// about accepted media types than the traditional way of enumerating a pin's
// media types, so it should typically be used instead.
// GetStreamCaps gets information about the kinds of formats allowed... how
// it can stretch and crop, and the frame rate and data rates allowed (for
// video)

// VIDEO EXAMPLE
//
// GetStreamCaps returns a whole array of {MediaType, Capabilities}.
// Let's say your capture card supports JPEG anywhere between 160x120 and
// 320x240, and also the size 640x480.  Also, say it supports RGB24 at
// resolutions between 160x120 and 320x240 but only multiples of 8.  You would
// expose these properties by offering a media type of 320 x 240 JPEG
// (if that is your default or preferred size) coupled with
// capabilities saying minimum 160x120 and maximum 320x240 with granularity of
// 1.  The next pair you expose is a media type of 640x480 JPEG coupled with
// capabilities of min 640x480 max 640x480.  The third pair is media type
// 320x240 RGB24 with capabilities min 160x120 max 320x240 granularity 8.
// In this way you can expose almost every quirk your card might have.
// An application interested in knowing what compression formats you provide
// can get all the pairs and make a list of all the unique sub types of the
// media types.
//
// If a filter's output pin is connected with a media type that has rcSource
// and rcTarget not empty, it means the filter is being asked to stretch the
// rcSource sub-rectangle of its InputSize (the format of the input pin for
// a compressor, and the largest bitmap a capture filter can generate with
// every pixel unique) into the rcTarget sub-rectangle of its output format.
// For instance, if a video compressor has as input 160x120 RGB, and as output
// 320x240 MPEG with an rcSource of (10,10,20,20) and rcTarget of (0,0,100,100)
// this means the compressor is being asked to take a 10x10 piece of the 160x120
// RGB bitmap, and make it fill the top 100x100 area of a 320x240 bitmap,
// leaving the rest of the 320x240 bitmap untouched.
// A filter does not have to support this and can fail to connect with a
// media type where rcSource and rcTarget are not empty.
//
// Your output pin is connected to the next filter with a certain media
// type (either directly or using the media type passed by SetFormat),
// and you need to look at the AvgBytesPerSecond field of the format
// of that mediatype to see what data rate you are being asked to compress
// the video to, and use that data rate.  Using the number of frames per
// second in AvgTimePerFrame, you can figure out how many bytes each frame
// is supposed to be.  You can make it smaller, but NEVER EVER make a bigger
// data rate.  For a video compressor, your input pin's media type tells you
// the frame rate (use that AvgTimePerFrame).  For a capture filter, the
// output media type tells you, so use that AvgTimePerFrame.
//
// The cropping rectangle described below is the same as the rcSrc of the
// output pin's media type.
//
// The output rectangle described below is the same of the width and height
// of the BITMAPINFOHEADER of the media type of the output pin's media type


// AUDIO EXAMPLE
//
// This API can return an array of pairs of (media type, capabilities).
// This can be used to expose all kinds of wierd capabilities.  Let's say you
// do any PCM frequency from 11,025 to 44,100 at 8 or 16 bit mono or
// stereo, and you also do 48,000 16bit stereo as a special combination.
// You would expose 3 pairs.  The first pair would have Min Freq of 11025 and
// Max Freq of 44100, with MaxChannels=2 and MinBits=8 and MaxBits=8 for the
// capabilites structure, and a media type of anything you like, maybe
// 22kHz, 8bit stereo as a default.
// The 2nd pair would be the same except for MinBits=16 and MaxBits=16 in
// the capabilities structure and the media type could be something like
// 44kHz, 16bit stereo as a default (the media type in the pair should always
// be something legal as described by the capabilities structure... the
// structure tells you how you can change the media type to produce other
// legal media types... for instance changing 44kHz to 29010Hz would be legal,
// but changing bits from 16 to 14 would not be.)
// The 3rd pair would be MinFreq=48000 MaxFreq=48000 MaxChannels=2
// MinBits=16 and MaxBits=16, and the media type would be 48kHz 16bit stereo.
// You can also use the Granularity elements of the structure (like the example
// for video) if you support values that multiples of n, eg.  you could say
// minimum bits per sample 8, max 16, and granularity 8 to describe doing
// either 8 or 16 bit all in one structure
//
// If you support non-PCM formats, the media type returned in GetStreamCaps
// can show which non-PCM formats you support (with a default sample rate,
// bit rate and channels) and the capabilities structure going with that
// media type can describe which other sample rates, bit rates and channels
// you support.

[
    object,
    uuid(C6E13340-30AC-11d0-A18C-00A0C9118956),
    pointer_default(unique)
]
interface IAMStreamConfig : IUnknown
{

    // this is the structure returned by a VIDEO filter
    //
    typedef struct _VIDEO_STREAM_CONFIG_CAPS {

	GUID	    guid;	// will be MEDIATYPE_Video

	// the logical or of all the AnalogVideoStandard's supported
	// typically zero if not supported
	ULONG	    VideoStandard;

	// the inherent size of the incoming signal... taken from the input
	// pin for a compressor, or the largest size a capture filter can
	// digitize the signal with every pixel still unique
        SIZE        InputSize;

	// The input of a compressor filter may have to be connected for these
	// to be known

	// smallest rcSrc cropping rect allowed
        SIZE        MinCroppingSize;
	// largest rcSrc cropping rect allowed
        SIZE        MaxCroppingSize;
	// granularity of cropping size - eg only widths a multiple of 4 allowed
        int         CropGranularityX;
        int         CropGranularityY;
	// alignment of cropping rect - eg rect must start on multiple of 4
	int	    CropAlignX;
	int	    CropAlignY;

	// The input of a compressor filter may have to be connected for these
	// to be known

	// smallest bitmap this pin can produce
        SIZE        MinOutputSize;
	// largest bitmap this pin can produce
        SIZE        MaxOutputSize;
	// granularity of output bitmap size
        int         OutputGranularityX;
        int         OutputGranularityY;
	// !!! what about alignment of rcTarget inside BIH if different?

	// how well can you stretch in the x direction?  0==not at all
	// 1=pixel doubling 2=interpolation(2 taps) 3=better interpolation
	// etc.
	int	    StretchTapsX;
	int	    StretchTapsY;
	// how well can you shrink in the x direction?  0==not at all
	// 1=pixel doubling 2=interpolation(2 taps) 3=better interpolation
	// etc.
	int	    ShrinkTapsX;
	int	    ShrinkTapsY;

	// CAPTURE filter only - what frame rates are allowed?
        LONGLONG    MinFrameInterval;
        LONGLONG    MaxFrameInterval;

	// what data rates can this pin produce?
        LONG        MinBitsPerSecond;
        LONG        MaxBitsPerSecond;
    } VIDEO_STREAM_CONFIG_CAPS;


    // this is the structure returned by an AUDIO filter
    //
    typedef struct _AUDIO_STREAM_CONFIG_CAPS {

  	GUID	   guid;	// will be MEDIATYPE_Audio
	ULONG 	   MinimumChannels;
   	ULONG      MaximumChannels;
	ULONG      ChannelsGranularity;
   	ULONG      MinimumBitsPerSample;
   	ULONG      MaximumBitsPerSample;
	ULONG      BitsPerSampleGranularity;
   	ULONG      MinimumSampleFrequency;
   	ULONG      MaximumSampleFrequency;
	ULONG      SampleFrequencyGranularity;
    } AUDIO_STREAM_CONFIG_CAPS;

    // - only allowed when pin is not streaming, else the call will FAIL
    // - If your output pin is not yet connected, and you can
    //   connect your output pin with this media type, you should
    //   succeed the call, and start offering it first (enumerate as format#0)
    //   from GetMediaType so that this format will be used to connect with
    //   when you do connect to somebody
    // - if your output pin is already connected, and you can provide this
    //   type, reconnect your pin.  If the other pin can't accept it, FAIL
    //   this call and leave your connection alone.
    HRESULT SetFormat(
            [in] AM_MEDIA_TYPE *pmt);

    // the format it's connected with, or will connect with
    // the application is responsible for calling DeleteMediaType(*ppmt);
    HRESULT GetFormat(
            [out] AM_MEDIA_TYPE **ppmt);

    // how many different Stream Caps structures are there?
    // also, how big is the stream caps structure?
    HRESULT GetNumberOfCapabilities(
            [out] int *piCount,
	    [out] int *piSize);	// pSCC of GetStreamCaps needs to be this big

    // - gets one of the pairs of {Mediatype, Caps}
    // - return S_FALSE if iIndex is too high
    // - the application is responsible for calling DeleteMediaType(*ppmt);
    // - the first thing pSCC points to is a GUID saying MEDIATYPE_Video
    //   or MEDIATYPE_Audio, so you can tell if you have a pointer to a
    //   VIDEO_STREAM_CONFIG_CAPS or an AUDIO_STREAM_CONFIG_CAPS structure
    //   There could potentially be many more possibilities other than video
    //   or audio.
    HRESULT GetStreamCaps(
	    [in]  int iIndex,	// 0 to #caps-1
	    [out] AM_MEDIA_TYPE **ppmt,
            [out] BYTE *pSCC);

}



// Interface to control interleaving of different streams in one file
[
object,
uuid(BEE3D220-157B-11d0-BD23-00A0C911CE86),
pointer_default(unique)
]
interface IConfigInterleaving : IUnknown
{
    import "unknwn.idl";

    typedef enum
    {
        // uninterleaved - samples written out in the order they
        // arrive
        INTERLEAVE_NONE,

            // approximate interleaving with less overhead for video
            // capture
        INTERLEAVE_CAPTURE,

        // full, precise interleaving. slower.
        INTERLEAVE_FULL

    } InterleavingMode;

    HRESULT put_Mode(
        [in] InterleavingMode mode
        );

    HRESULT get_Mode(
        [out] InterleavingMode *pMode
        );

    HRESULT put_Interleaving(
        [in] const REFERENCE_TIME *prtInterleave,
        [in] const REFERENCE_TIME *prtPreroll
        );

    HRESULT get_Interleaving(
        [out] REFERENCE_TIME *prtInterleave,
        [out] REFERENCE_TIME *prtPreroll
        );
}

// Interface to control the AVI mux
[
object,
uuid(5ACD6AA0-F482-11ce-8B67-00AA00A3F1A6),
pointer_default(unique)
]
interface IConfigAviMux : IUnknown
{
    import "unknwn.idl";

    // control whether the AVI mux adjusts the frame rate or audio
    // sampling rate for drift when the file is closed. -1 to disables
    // this behavior.
    HRESULT SetMasterStream([in] LONG iStream);
    HRESULT GetMasterStream([out] LONG *pStream);

    // control whether the AVI mux writes out an idx1 index chunk for
    // compatibility with older AVI players.
    HRESULT SetOutputCompatibilityIndex([in] BOOL fOldIndex);
    HRESULT GetOutputCompatibilityIndex([out] BOOL *pfOldIndex);
}

    //---------------------------------------------------------------------
    //  CompressionCaps enum
    //---------------------------------------------------------------------

    // This tells you which features of IAMVideoCompression are supported

    // CanCrunch means that it can compress video to a specified data rate
    // If so, then the output pin's media type will contain that data rate
    // in the format's AvgBytesPerSecond field, and that should be used.

    typedef enum
    {
        CompressionCaps_CanQuality =  0x01,
        CompressionCaps_CanCrunch =   0x02,
        CompressionCaps_CanKeyFrame = 0x04,
        CompressionCaps_CanBFrame =   0x08,
        CompressionCaps_CanWindow =   0x10
    } CompressionCaps;



    //---------------------------------------------------------------------
    // IAMVideoCompression interface
    //
    // Control compression parameters - pin interface
    //---------------------------------------------------------------------

    // This interface is implemented by the output pin of a video capture
    // filter or video compressor that provides video data

    // You use this interface to control how video is compressed... how
    // many keyframes, etc., and to find information like capabilities and
    // the description of this compressor

    [
	object,
        uuid(C6E13343-30AC-11d0-A18C-00A0C9118956),
        pointer_default(unique)
    ]
    interface IAMVideoCompression : IUnknown
    {
	// - Only valid if GetInfo's pCapabilities sets
	//   CompressionCaps_CanKeyFrame
        // - KeyFrameRate < 0 means use the compressor default
	// - KeyFrames == 0 means only the first frame is a key
        HRESULT put_KeyFrameRate (
                    [in] long KeyFrameRate);

        HRESULT get_KeyFrameRate (
                    [out] long * pKeyFrameRate);

	// - Only valid if GetInfo's pCapabilities sets
	//   CompressionCaps_CanBFrame
	// - If keyframes are every 10, and there are 3 P Frames per key,
	//   they will be spaced evenly between the key frames and the other
	//   6 frames will be B frames
	// - PFramesPerKeyFrame < 0 means use the compressor default
        HRESULT put_PFramesPerKeyFrame (
                    [in] long PFramesPerKeyFrame);

        HRESULT get_PFramesPerKeyFrame (
                    [out] long * pPFramesPerKeyFrame);

	// - Only valid if GetInfo's pCapabilities sets
	//   CompressionCaps_CanQuality
	// - Controls image quality
	// - If you are compressing to a fixed data rate, a high quality
	//   means try and use all of the data rate, and a low quality means
	//   feel free to use much lower than the data rate if you want to.
        // - Quality < 0 means use the compressor default
        HRESULT put_Quality (
                    [in] double Quality);

        HRESULT get_Quality (
                    [out] double * pQuality);

	// If you have set a data rate of 100K/sec on a 10fps movie, that
	// will normally mean each frame must be <=10K.  But a window size
	// means every consecutive n frames must average to the data rate,
	// but an individual frame (if n > 1) is allowed to exceed the
	// frame size suggested by the data rate
        HRESULT put_WindowSize (
                    [in] DWORDLONG WindowSize);

        HRESULT get_WindowSize (
                    [out] DWORDLONG * pWindowSize);

	// - pszVersion might be "Version 2.1.0"
	// - pszDescription might be "Danny's awesome video compressor"
	// - pcbVersion and pcbDescription will be filled in with the
	//   required length if they are too short
	// - *pCapabilities is a logical OR of some CompressionCaps flags
        HRESULT GetInfo(
                    [out, size_is(*pcbVersion)] WCHAR * pszVersion,
                    [in,out] int *pcbVersion,
                    [out, size_is(*pcbDescription)] LPWSTR pszDescription,
                    [in,out] int *pcbDescription,
		    [out] long *pDefaultKeyFrameRate,
		    [out] long *pDefaultPFramesPerKey,
		    [out] double *pDefaultQuality,
                    [out] long *pCapabilities  //CompressionCaps
        );

	// - this means when this frame number comes along after the graph
	//   is running, make it a keyframe even if you weren't going to
        HRESULT OverrideKeyFrame(
                    [in]  long FrameNumber
        );

	// - Only valid if GetInfo's pCapabilities sets
	//   CompressionCaps_CanCrunch
	// - this means when this frame number comes along after the graph
	//   is running, make it this many bytes big instead of whatever size
	//   you were going to make it.
        HRESULT OverrideFrameSize(
                    [in]  long FrameNumber,
                    [in]  long Size
        );

    }

    //---------------------------------------------------------------------
    //  VfwCaptureDialogs enum
    //---------------------------------------------------------------------

    typedef enum
    {
         VfwCaptureDialog_Source = 0x01,
	 VfwCaptureDialog_Format = 0x02,
	 VfwCaptureDialog_Display = 0x04
    } VfwCaptureDialogs;


    //---------------------------------------------------------------------
    //  VfwCompressDialogs enum
    //---------------------------------------------------------------------

    typedef enum
    {
         VfwCompressDialog_Config = 0x01,
	 VfwCompressDialog_About =  0x02
    } VfwCompressDialogs;


    //---------------------------------------------------------------------
    // IAMVfwCaptureDialogs - filter interface
    //
    // Show a VfW capture driver dialog - SOURCE, FORMAT, or DISPLAY
    //---------------------------------------------------------------------

    // This interface is supported only by Microsoft's Video For Windows
    // capture driver Capture Filter.  It allows an application to bring up
    // one of the 3 driver dialogs that VfW capture drivers have.

    [
	object,
	local,
        uuid(D8D715A0-6E5E-11D0-B3F0-00AA003761C5),
        pointer_default(unique)
    ]
    interface IAMVfwCaptureDialogs : IUnknown
    {
        HRESULT HasDialog(
                    [in]  int iDialog	// VfwCaptureDialogs enum
        );

        HRESULT ShowDialog(
                    [in]  int iDialog,	// VfwCaptureDialogs enum
		    [in]  HWND hwnd
        );

        HRESULT SendDriverMessage(
                    [in]  int iDialog,	// VfwCaptureDialogs enum
                    [in]  int uMsg,
                    [in]  long dw1,
                    [in]  long dw2
        );

        // - iDialog can be one of the VfwCaptureDialogs enums
        // - HasDialog returns S_OK if it has the dialog, else S_FALSE
 	// - ShowDialog can only be called when not streaming or when another
	//   dialog is not already up
	// - SendDriverMessage can send a secret message to the capture driver.
	//   USE IT AT YOUR OWN RISK!
    }

    //---------------------------------------------------------------------
    // IAMVfwCompressDialogs - filter interface
    //
    // Show a VfW codec driver dialog - CONFIG or ABOUT
    //---------------------------------------------------------------------

    // This interface is supported only by Microsoft's ICM Compressor filter
    // (Co).  It allows an application to bring up either the Configure or
    // About dialogs for the ICM codec that it is currently using.

    [
	object,
	local,
        uuid(D8D715A3-6E5E-11D0-B3F0-00AA003761C5),
        pointer_default(unique)
    ]
    interface IAMVfwCompressDialogs : IUnknown
    {

        // Bring up a dialog for this codec
        HRESULT ShowDialog(
                    [in]  int iDialog,   // VfwCompressDialogs enum
		    [in]  HWND hwnd
        );

        // Calls ICGetState and gives you the result
        HRESULT GetState(
                    [out, size_is(*pcbState)] LPVOID pState,
		    [in, out]  int *pcbState
        );

        // Calls ICSetState
        HRESULT SetState(
                    [in, size_is(cbState)] LPVOID pState,
		    [in]  int cbState
        );

        // Send a codec specific message
        HRESULT SendDriverMessage(
                    [in]  int uMsg,
                    [in]  long dw1,
                    [in]  long dw2
        );

        // - iDialog can be one of the VfwCaptureDialogs enums
 	// - ShowDialog can only be called when not streaming or when no other
	//   dialog is up already
 	// - an application can call GetState after ShowDialog(CONFIG) to
	//   see how the compressor was configured and next time the graph
   	//   is used, it can call SetState with the data it saved to return
	//   the codec to the state configured by the dialog box from last time
	// - GetState with a NULL pointer returns the size needed
	// - SendDriverMessage can send a secret message to the codec.
	//   USE IT AT YOUR OWN RISK!
    }


    //---------------------------------------------------------------------
    // IAMDroppedFrames interface
    //
    // Report status of capture - pin interface
    //---------------------------------------------------------------------

    // A capture filter's video output pin supports this.  It reports
    // how many frames were not sent (dropped), etc.

    // Every time your filter goes from STOPPED-->PAUSED, you reset all your
    // counts to zero.

    // An app may call this all the time while you are capturing to see how
    // capturing is going.  MAKE SURE you always return as current information
    // as possible while you are running.

    // When your capture filter starts running, it starts by sending frame 0,
    // then 1, 2, 3, etc.  The time stamp of each frame sent should correspond
    // to the graph clock's time when the image was digitized.  The end time
    // is the start time plus the duration of the video frame.
    // You should also set the MediaTime of each sample (SetMediaTime) as well.
    // This should be the frame number ie (0,1) (1,2) (2,3).
    // If a frame is dropped, a downstream filter will be able to tell easily
    // not by looking for gaps in the regular time stamps, but by noticing a
    // frame number is missing (eg.  (1,2) (2,3) (4,5) (5,6) means frame 3
    // was dropped.

    // Using the info provided by this interface, an application can figure out
    // the number of frames dropped, the frame rate achieved (the length of
    // time the graph was running divided by the number of frames not dropped),
    // and the data rate acheived (the length of time the graph was running
    // divided by the average frame size).

    // If your filter is running, then paused, and then run again, you need
    // to continue to deliver frames as if it was never paused.  The first
    // frame after the second RUN cannot be time stamped earlier than the last
    // frame sent before the pause.

    // Your filter must always increment the MediaTime of each sample sent.
    // Never send the same frame # twice, and never go back in time.  The
    // regular time stamp of a sample can also never go back in time.

    [
	object,
        uuid(C6E13344-30AC-11d0-A18C-00A0C9118956),
        pointer_default(unique)
    ]
    interface IAMDroppedFrames : IUnknown
    {
        // Get the number of dropped frames
        HRESULT GetNumDropped(
                    [out]  long * plDropped

        );

        //Get the number of non-dropped frames
        HRESULT GetNumNotDropped(
                    [out]  long * plNotDropped

        );

	// - plArray points to an array of lSize longs.  The filter will
	//   fill it with the frame number of the first lSize frames dropped.
	//   A filter may not have bothered to remember as many as you asked
	//   for, so it will set *plNumCopied to the number of frames it filled
	//   in.
        HRESULT GetDroppedInfo(
                    [in]   long lSize,
                    [out]  long * plArray,
                    [out]  long *  plNumCopied
        );

	// - This is the average size of the frames it didn't drop (in bytes)
        HRESULT GetAverageFrameSize(
                    [out]  long * plAverageSize

        );

    }



    cpp_quote("#define AMF_AUTOMATICGAIN -1.0")

    //---------------------------------------------------------------------
    // IAMAudioInputMixer interface
    //
    // Sets the recording levels, pan and EQ for the audio card inputs
    //---------------------------------------------------------------------

    // This interface is implemented by each input pin of an audio capture
    // filter, to tell it what level, panning, and EQ to use for each input.
    // The name of each pin will reflect the type of input, eg. "Line input 1"
    // or "Mic".  An application uses the pin names to decide how it wants to
    // set the recording levels

    // This interface can also be supported by the audio capture filter itself
    // to control to overall record level and panning after the mix

    [
	object,
        uuid(54C39221-8380-11d0-B3F0-00AA003761C5),
        pointer_default(unique)
    ]
    interface IAMAudioInputMixer : IUnknown
    {
	// This interface is only supported by the input pins, not the filter
 	// If disabled, this channel will not be mixed in as part of the
	// recorded signal.
        HRESULT put_Enable (
		    [in] BOOL fEnable);	// TRUE=enable FALSE=disable

	//Is this channel enabled?
        HRESULT get_Enable (
		    [out] BOOL *pfEnable);

	// When set to mono mode, making a stereo recording of this channel
 	// will have both channels contain the same data... a mixture of the
	// left and right signals
        HRESULT put_Mono (
		    [in] BOOL fMono);	// TRUE=mono FALSE=multi channel

        //all channels combined into a mono signal?
        HRESULT get_Mono (
		    [out] BOOL *pfMono);

 	// !!! WILL CARDS BE ABLE TO BOOST THE GAIN?
        //Set the record level for this channel
        HRESULT put_MixLevel (
                    [in] double Level);	// 0 = off, 1 = full (unity?) volume
					// AMF_AUTOMATICGAIN, if supported,
					// means automatic

        //Get the record level for this channel
        HRESULT get_MixLevel (
                    [out] double *pLevel);

	// For instance, when panned full left, and you make a stereo recording
	// of this channel, you will record a silent right channel.
        HRESULT put_Pan (
                    [in] double Pan);	// -1 = full left, 0 = centre, 1 = right

        //Get the pan for this channel
        HRESULT get_Pan (
                    [out] double *pPan);

	// Boosts the bass of low volume signals before they are recorded
	// to compensate for the fact that your ear has trouble hearing quiet
	// bass sounds
        HRESULT put_Loudness (
		    [in] BOOL fLoudness);// TRUE=on FALSE=off

        HRESULT get_Loudness (
		    [out] BOOL *pfLoudness);

	// boosts or cuts the treble of the signal before it's recorded by
	// a certain amount of dB
        HRESULT put_Treble (
                    [in] double Treble); // gain in dB (-ve = attenuate)

        //Get the treble EQ for this channel
        HRESULT get_Treble (
                    [out] double *pTreble);

	// This is the maximum value allowed in put_Treble.  ie 6.0 means
	// any value between -6.0 and 6.0 is allowed
        HRESULT get_TrebleRange (
                    [out] double *pRange); // largest value allowed

	// boosts or cuts the bass of the signal before it's recorded by
	// a certain amount of dB
        HRESULT put_Bass (
                    [in] double Bass); // gain in dB (-ve = attenuate)

        // Get the bass EQ for this channel
        HRESULT get_Bass (
                    [out] double *pBass);

	// This is the maximum value allowed in put_Bass.  ie 6.0 means
	// any value between -6.0 and 6.0 is allowed
        HRESULT get_BassRange (
                    [out] double *pRange); // largest value allowed

    }


    //---------------------------------------------------------------------
    // IAMBufferNegotiation interface
    //
    // Tells a pin what kinds of buffers to use when connected
    //---------------------------------------------------------------------

    // This interface can be implemented by any pin that will connect to
    // another pin using IMemInputPin.  All capture filters should support
    // this interface.

    // SuggestAllocatorProperties is a way for an application to get
    // in on the buffer negotiation process for a pin.  This pin will use
    // the numbers given to it by the application as its request to the
    // allocator.  An application can use a negative number for any element
    // in the ALLOCATOR_PROPERTIES to mean "don't care".  An application must
    // call this function before the pin is connected, or it will be too late
    // To ensure that an application gets what it wants, it would be wise to
    // call this method on both pins being connected together, so the other
    // pin doesn't overrule the application's request.

    // GetAllocatorProperties can only be called after a pin is connected and
    // it returns the properties of the current allocator being used

    [
	object,
        uuid(56ED71A0-AF5F-11D0-B3F0-00AA003761C5),
        pointer_default(unique)
    ]
    interface IAMBufferNegotiation : IUnknown
    {
        HRESULT SuggestAllocatorProperties (
		    [in] const ALLOCATOR_PROPERTIES *pprop);

        HRESULT GetAllocatorProperties (
		    [out] ALLOCATOR_PROPERTIES *pprop);

    }


    //---------------------------------------------------------------------
    // AnalogVideoStandard enum
    //---------------------------------------------------------------------

    typedef enum tagAnalogVideoStandard
    {
        AnalogVideo_None     = 0x00000000,  // This is a digital sensor
        AnalogVideo_NTSC_M   = 0x00000001,  //        75 IRE Setup
        AnalogVideo_NTSC_M_J = 0x00000002,  // Japan,  0 IRE Setup
        AnalogVideo_NTSC_433 = 0x00000004,

        AnalogVideo_PAL_B    = 0x00000010,
        AnalogVideo_PAL_D    = 0x00000020,
        AnalogVideo_PAL_G    = 0x00000040,
        AnalogVideo_PAL_H    = 0x00000080,
        AnalogVideo_PAL_I    = 0x00000100,
        AnalogVideo_PAL_M    = 0x00000200,
        AnalogVideo_PAL_N    = 0x00000400,

        AnalogVideo_PAL_60   = 0x00000800,

        AnalogVideo_SECAM_B  = 0x00001000,
        AnalogVideo_SECAM_D  = 0x00002000,
        AnalogVideo_SECAM_G  = 0x00004000,
        AnalogVideo_SECAM_H  = 0x00008000,
        AnalogVideo_SECAM_K  = 0x00010000,
        AnalogVideo_SECAM_K1 = 0x00020000,
        AnalogVideo_SECAM_L  = 0x00040000,
        AnalogVideo_SECAM_L1 = 0x00080000
    } AnalogVideoStandard;

    cpp_quote("#define AnalogVideo_NTSC_Mask  0x00000007")
    cpp_quote("#define AnalogVideo_PAL_Mask   0x00000FF0")
    cpp_quote("#define AnalogVideo_SECAM_Mask 0x000FF000")


    //---------------------------------------------------------------------
    // TunerInputType enum
    //---------------------------------------------------------------------

    typedef enum tagTunerInputType
    {
        TunerInputCable,
        TunerInputAntenna
    } TunerInputType;

    //---------------------------------------------------------------------
    // VideoCopyProtectionType enum
    //---------------------------------------------------------------------

    typedef enum
    {
        VideoCopyProtectionMacrovisionBasic,
        VideoCopyProtectionMacrovisionCBI
    } VideoCopyProtectionType;

    //---------------------------------------------------------------------
    // PhysicalConnectorType enum
    //---------------------------------------------------------------------

    typedef enum tagPhysicalConnectorType
    {
        PhysConn_Video_Tuner = 1,
        PhysConn_Video_Composite,
        PhysConn_Video_SVideo,
        PhysConn_Video_RGB,
        PhysConn_Video_YRYBY,
        PhysConn_Video_SerialDigital,
        PhysConn_Video_ParallelDigital,
        PhysConn_Video_SCSI,
        PhysConn_Video_AUX,
        PhysConn_Video_1394,
        PhysConn_Video_USB,
        PhysConn_Video_VideoDecoder,
        PhysConn_Video_VideoEncoder,
        PhysConn_Video_SCART,
        PhysConn_Video_Black,			


        PhysConn_Audio_Tuner = 0x1000,
        PhysConn_Audio_Line,
        PhysConn_Audio_Mic,
        PhysConn_Audio_AESDigital,
        PhysConn_Audio_SPDIFDigital,
        PhysConn_Audio_SCSI,
        PhysConn_Audio_AUX,
        PhysConn_Audio_1394,
        PhysConn_Audio_USB,
        PhysConn_Audio_AudioDecoder,
    } PhysicalConnectorType;




    //---------------------------------------------------------------------
    // IAMAnalogVideoDecoder interface
    //---------------------------------------------------------------------

    [
	object,
        uuid(C6E13350-30AC-11d0-A18C-00A0C9118956),
	pointer_default(unique)
    ]
    interface IAMAnalogVideoDecoder : IUnknown
    {

         //Gets the supported analog video standards (NTSC/M, PAL/B, SECAM/K1...
        HRESULT get_AvailableTVFormats(
                    [out] long *lAnalogVideoStandard
                    );

        //Sets or gets the current analog video standard (NTSC/M, PAL/B, SECAM/K1, ...
        HRESULT put_TVFormat(
                    [in] long lAnalogVideoStandard
                    );

        // Sets or gets the current analog video standard (NTSC/M, PAL/B, SECAM/K1, ...
        HRESULT get_TVFormat(
                    [out] long * plAnalogVideoStandard
                    );

        // True if horizontal sync is locked
        HRESULT get_HorizontalLocked (
                    [out] long * plLocked);

        // True if connected to a VCR (changes PLL timing)
        HRESULT put_VCRHorizontalLocking (
                    [in] long lVCRHorizontalLocking);

        HRESULT get_VCRHorizontalLocking (
                    [out] long * plVCRHorizontalLocking);

        // Returns the number of lines in the video signal")]
        HRESULT get_NumberOfLines (
                    [out] long *plNumberOfLines);

        // Enables or disables the output bus
        HRESULT put_OutputEnable (
                    [in] long lOutputEnable);

        HRESULT get_OutputEnable (
                    [out] long *plOutputEnable);

    }


    //---------------------------------------------------------------------
    // VideoProcAmp Property enum
    //---------------------------------------------------------------------

    typedef enum tagVideoProcAmpProperty
    {
        VideoProcAmp_Brightness,
        VideoProcAmp_Contrast,
        VideoProcAmp_Hue,
        VideoProcAmp_Saturation,
        VideoProcAmp_Sharpness,
        VideoProcAmp_Gamma,
        VideoProcAmp_ColorEnable,
        VideoProcAmp_WhiteBalance,
        VideoProcAmp_BacklightCompensation
    } VideoProcAmpProperty;

    //---------------------------------------------------------------------
    // VideoProcAmp Flags enum
    //---------------------------------------------------------------------

    typedef enum tagVideoProcAmpFlags
    {
        VideoProcAmp_Flags_Manual = 0x0000,
        VideoProcAmp_Flags_Auto   = 0x0001,
    } VideoProcAmpFlags;

    //---------------------------------------------------------------------
    // IAMVideoProcAmp interface
    //
    // Adjusts video quality in either the analog or digital domain.
    //
    //---------------------------------------------------------------------

    [
	object,
        uuid(C6E13360-30AC-11d0-A18C-00A0C9118956),
	pointer_default(unique)
    ]
    interface IAMVideoProcAmp : IUnknown
    {
        // Returns min, max, step size, and default values
        HRESULT GetRange(
		    [in] long Property,         // Which property to query
		    [out] long * pMin,          // Range minimum
		    [out] long * pMax,          // Range maxumum
		    [out] long * pSteppingDelta,// Step size
		    [out] long * pDefault,      // Default value
		    [out] long * pCapsFlags     // VideoProcAmpFlags

        );

        // Set a VideoProcAmp property
        HRESULT Set(
		    [in]  long Property,        // VideoProcAmpProperty
		    [in]  long lValue,          // Value to set
		    [in]  long Flags            // VideoProcAmp_Flags_*

        );

        // Get a VideoProcAmp property
        HRESULT Get(
		    [in]  long Property,        // VideoProcAmpProperty
		    [out] long * lValue,        // Current value
		    [out] long * Flags          // VideoProcAmp_Flags_*
        );
    }


    //---------------------------------------------------------------------
    // CameraControl Property enum
    //---------------------------------------------------------------------

    typedef enum tagCameraControlProperty
    {
        CameraControl_Pan,
        CameraControl_Tilt,
        CameraControl_Roll,
        CameraControl_Zoom,
        CameraControl_Exposure,
        CameraControl_Iris,
        CameraControl_Focus
    } CameraControlProperty;

    //---------------------------------------------------------------------
    // CameraControl Flags enum
    //---------------------------------------------------------------------

    typedef enum tagCameraControlFlags
    {
        CameraControl_Flags_Manual   = 0x0000,
        CameraControl_Flags_Auto     = 0x0001
    } CameraControlFlags;

    //---------------------------------------------------------------------
    // IAMCameraControl interface
    //
    // Control of local or remote cameras
    //---------------------------------------------------------------------

    [
	object,
        uuid(C6E13370-30AC-11d0-A18C-00A0C9118956),
	pointer_default(unique)
    ]
    interface IAMCameraControl : IUnknown
    {
        // Returns min, max, step size, and default values
        HRESULT GetRange(
		    [in] long Property,         // Which property to query
		    [out] long * pMin,          // Range minimum
		    [out] long * pMax,          // Range maxumum
		    [out] long * pSteppingDelta,// Step size
		    [out] long * pDefault,      // Default value
		    [out] long * pCapsFlags     // CamaeraControlFlags

        );

        // Set a CameraControl property
        HRESULT Set(
		    [in]  long Property,        // CameraControlProperty
		    [in]  long lValue,          // Value to set
		    [in]  long Flags            // CameraControl_Flags_*

        );

        // Get a CameraControl property
        HRESULT Get(
		    [in]  long Property,        // CameraControlProperty
		    [out] long * lValue,        // Current value
		    [out] long * Flags          // CameraControl_Flags_*
        );
    }


    //---------------------------------------------------------------------
    // IAMCrossbar interface
    //
    // Controls a routing matrix for analog or digital video or audio
    //---------------------------------------------------------------------

    [
	object,
        uuid(C6E13380-30AC-11d0-A18C-00A0C9118956),
	pointer_default(unique)
    ]
    interface IAMCrossbar : IUnknown
    {

        // How many pins are there?
        HRESULT get_PinCounts(
                [out] long * OutputPinCount,        // count of output pins
                [out] long * InputPinCount);        // count of input pins

        // True if routing is possible
        HRESULT CanRoute (
                [in]  long OutputPinIndex,          // the output pin
                [in]  long InputPinIndex);          // the input pin

        // Routes an input pin to an output pin
        HRESULT Route (
                [in]  long OutputPinIndex,          // the output pin
                [in]  long InputPinIndex);          // the input pin

        // Returns the input pin connected to a given output pin
        HRESULT get_IsRoutedTo (
                [in]  long OutputPinIndex,          // the output pin
                [out] long * InputPinIndex);        // the connected input pin

        // Returns a pin which is related to a given pin
        // (ie. this audio pin is related to a video pin)
        HRESULT get_CrossbarPinInfo (
                [in] BOOL IsInputPin,               // TRUE for input pins
                [in] long PinIndex,                 // a pin
                [out] long * PinIndexRelated,       // Index of related pin
                [out] long * PhysicalType);         // Physical type of pin

    }


	//---------------------------------------------------------------------
	// IAMTuner interface
	//
	// base tuner device
	//---------------------------------------------------------------------
	
	// predefined subchannel values
	typedef enum tagAMTunerSubChannel 
	{
		AMTUNER_SUBCHAN_NO_TUNE     = -2,   // don't tune
		AMTUNER_SUBCHAN_DEFAULT     = -1    // use default sub chan
	} AMTunerSubChannel;
	
	// predefined signal strength values
	typedef enum tagAMTunerSignalStrength
	{
		AMTUNER_HASNOSIGNALSTRENGTH = -1,   // cannot indicate signal strength
		AMTUNER_NOSIGNAL            = 0,    // no signal available
		AMTUNER_SIGNALPRESENT       = 1     // signal present
	} AMTunerSignalStrength;

    // specifies the mode of operation of the tuner	
	typedef enum tagAMTunerModeType
	{
		AMTUNER_MODE_DEFAULT    = 0x0000,   // default tuner mode
		AMTUNER_MODE_TV         = 0x0001,   // tv
		AMTUNER_MODE_FM_RADIO   = 0x0002,   // fm radio
		AMTUNER_MODE_AM_RADIO   = 0x0004,   // am radio
		AMTUNER_MODE_DSS        = 0x0008,   // dss
	} AMTunerModeType;
	
	// Events reported by IAMTunerNotification
	typedef enum tagAMTunerEventType{
		AMTUNER_EVENT_CHANGED   = 0x0001,   // status changed
	} AMTunerEventType;
	
    interface IAMTunerNotification;

	[
		object,
		local,
		uuid(211A8761-03AC-11d1-8D13-00AA00BD8339),
		pointer_default(unique)
	]
	interface IAMTuner : IUnknown
	{
		// Sets and gets the Channel
		HRESULT put_Channel(
			[in] long lChannel,
			[in] long lVideoSubChannel,
			[in] long lAudioSubChannel
			);
		HRESULT get_Channel(
			[out] long *plChannel,
			[out] long *plVideoSubChannel,
			[out] long *plAudioSubChannel
			);
	
		// Gets the minimum and maximum channel available
		HRESULT ChannelMinMax(
			[out] long *lChannelMin,
			[out] long *lChannelMax
			);
	
		// CountryCode is the same as the international
		// long distance telephone dialing prefix
		
		HRESULT put_CountryCode(
			[in] long lCountryCode
			);
		HRESULT get_CountryCode(
			[out] long *plCountryCode
			);
	
		HRESULT put_TuningSpace(
			[in] long lTuningSpace
			);
		HRESULT get_TuningSpace(
			[out] long *plTuningSpace
			);
	
		HRESULT Logon(
			[in] HANDLE hCurrentUser
            );
		HRESULT Logout();
	
		// Signal status for current channel
		// signal strength == TUNER_NOSIGNAL, or strength value
		HRESULT SignalPresent(
			[out] long * plSignalStrength	// AMTunerSignalStrength
			);
	
		// allow multifunction tuner to be switch between modes
		HRESULT put_Mode(
			[in] AMTunerModeType lMode		// AMTunerModeType
			);
		HRESULT get_Mode(
			[out] AMTunerModeType *plMode	// AMTunerModeType
			);
	
		// retrieve a bitmask of the possible modes
		HRESULT GetAvailableModes(
			[out] long *plModes				// AMTunerModeType
			);
	
		// allow IAMTuner clients to receive event notification
		HRESULT RegisterNotificationCallBack(
			[in] IAMTunerNotification *pNotify,
			[in] long lEvents       // bitmask from AMTunerEventType enumeration
			);
		HRESULT UnRegisterNotificationCallBack(
			IAMTunerNotification *pNotify
			);
	}
	
	//---------------------------------------------------------------------
	// IAMTunerNotification interface
	//
	// Provided to IAMTuner if notification callbacks are desired
	//---------------------------------------------------------------------
	
	[
		object,
		local,
		uuid(211A8760-03AC-11d1-8D13-00AA00BD8339),
		pointer_default(unique)
	]
	interface IAMTunerNotification : IUnknown
	{
		HRESULT OnEvent([in] AMTunerEventType Event);
	}
	
	
	//---------------------------------------------------------------------
	// IAMTVTuner interface
	//
	// Controls an analog TV tuner device
	//---------------------------------------------------------------------

	[
		object,
		local,
		uuid(211A8766-03AC-11d1-8D13-00AA00BD8339),
		pointer_default(unique)
	]
	interface IAMTVTuner : IAMTuner
	{
		// Gets the supported analog video standards (NTSC/M, PAL/B, SECAM/K1, ...
		HRESULT get_AvailableTVFormats(
			[out] long *lAnalogVideoStandard
			);
	
		// Gets the current analog video standard (NTSC/M, PAL/B, SECAM/K1, ...)
		HRESULT get_TVFormat(
			[out] long * plAnalogVideoStandard
			);
	
		// Scans for a signal on a given channel
		// NOTE: this is equivalent to put_Channel(), SignalStrength()
		HRESULT AutoTune(
			[in] long lChannel,
			[out] long * plFoundSignal
			);
	
		// Saves the fine tuning information for all channels")]
		HRESULT StoreAutoTune();
	
		// The number of TV sources plugged into the tuner
		HRESULT get_NumInputConnections(
			[out] long * plNumInputConnections
			);
	
		// Sets or gets the tuner input type (Cable or Antenna)
		HRESULT put_InputType(
			[in] long lIndex,
			[in] TunerInputType InputType
			);
		HRESULT get_InputType(
			[in] long lIndex,
			[out] TunerInputType * pInputType
			);
	
		// Sets or gets the tuner input
		HRESULT put_ConnectInput(
			[in] long lIndex
			);
		HRESULT get_ConnectInput(
			[out] long *plIndex
			);
	
		// Gets the video and audio carrier frequencies
		HRESULT get_VideoFrequency(
			[out] long *lFreq
			);
		HRESULT get_AudioFrequency(
			[out] long *lFreq
			);
	}

	
	//---------------------------------------------------------------------
	// IBPCSatelliteTuner interface
	//
	// An interface supporting Satellite tuning-related functions
	//---------------------------------------------------------------------
	[
		object,
		local,
		uuid(211A8765-03AC-11d1-8D13-00AA00BD8339),
		pointer_default(unique)
	]
	interface IBPCSatelliteTuner : IAMTuner
	{
		HRESULT get_DefaultSubChannelTypes(
			[out] long *plDefaultVideoType, // Provider-specific service type
			[out] long *plDefaultAudioType  // Provider-specific service type
			);
	
		HRESULT put_DefaultSubChannelTypes(
			[in] long lDefaultVideoType,    // Provider-specific service type
			[in] long lDefaultAudioType     // Provider-specific service type
			);
	
		HRESULT IsTapingPermitted();        // S_OK yes, S_FALSE no
	}



	//---------------------------------------------------------------------
	// IAMTVAudio interface
	//
	// TV Audio control
	//---------------------------------------------------------------------
	
	typedef enum tagTVAudioMode
	{
		AMTVAUDIO_MODE_MONO		    = 0x0001,       // Mono               	
		AMTVAUDIO_MODE_STEREO       = 0x0002,       // Stereo
		AMTVAUDIO_MODE_LANG_A       = 0x0010,       // Primary language
		AMTVAUDIO_MODE_LANG_B       = 0x0020,       // 2nd avail language
		AMTVAUDIO_MODE_LANG_C       = 0x0040,       // 3rd avail language
	} TVAudioMode;

	// Events reported by IAMTVAudioNotification
	typedef enum tagAMTVAudioEventType
	{
		AMTVAUDIO_EVENT_CHANGED     = 0x0001,       // mode changed
	} AMTVAudioEventType;

    interface IAMTVAudioNotification;

	[
		object,
		local,
		uuid(83EC1C30-23D1-11d1-99E6-00A0C9560266),
		pointer_default(unique)
	]
	interface IAMTVAudio : IUnknown
	{
		// retrieve a bitmask of the formats available in the hardware
		HRESULT GetHardwareSupportedTVAudioModes(
			[out] long *plModes				// TVAudioMode
			);
			
		// retrieve a bitmask of the possible modes
		HRESULT GetAvailableTVAudioModes(
			[out] long *plModes				// TVAudioMode
			);
			
		HRESULT get_TVAudioMode(
			[out] long *plMode              // TVAudioMode
			);
		HRESULT put_TVAudioMode(
			[in] long lMode					// TVAudioMode
			);

		// allow IAMTVAudio clients to receive event notification
		HRESULT RegisterNotificationCallBack(
			[in] IAMTunerNotification *pNotify,
			[in] long lEvents       // bitmask from AMTVAudioEventType enumeration
			);
		HRESULT UnRegisterNotificationCallBack(
			IAMTunerNotification *pNotify
			);
	}

	//---------------------------------------------------------------------
	// IAMTVAudioNotification interface
	//
	// Provided to IAMTVAudio clients if notification callbacks are desired
	//---------------------------------------------------------------------
	
	[
		object,
		local,
		uuid(83EC1C33-23D1-11d1-99E6-00A0C9560266),
		pointer_default(unique)
	]
	interface IAMTVAudioNotification : IUnknown
	{
		HRESULT OnEvent([in] AMTVAudioEventType Event);
	}




    //---------------------------------------------------------------------
    // IAMAnalogVideoEncoder interface
    //---------------------------------------------------------------------

    [
   object,
        uuid(C6E133B0-30AC-11d0-A18C-00A0C9118956),
	pointer_default(unique)
    ]
    interface IAMAnalogVideoEncoder : IUnknown
    {
        // Gets the supported analog video standards (NTSC/M, PAL/B, SECAM/K1, ...)
        HRESULT get_AvailableTVFormats(
                    [out] long *lAnalogVideoStandard
                    );

        // Sets or gets the current analog video standard (NTSC/M, PAL/B, SECAM/K1, ...)
        HRESULT put_TVFormat(
                    [in] long lAnalogVideoStandard
                    );

        HRESULT get_TVFormat(
                    [out] long * plAnalogVideoStandard
                    );

        // Sets or gets the copy protection
        HRESULT put_CopyProtection (
                    [in]  long lVideoCopyProtection); // VideoCopyProtectionType

        HRESULT get_CopyProtection (
                    [out] long *lVideoCopyProtection); // VideoCopyProtectionType


        // Enables and disables close captioning
        HRESULT put_CCEnable (
                    [in] long lCCEnable);

        HRESULT get_CCEnable (
                    [out] long *lCCEnable);

    }

    // used by IKsPropertySet set AMPROPSETID_Pin
    typedef enum {
	AMPROPERTY_PIN_CATEGORY,
        AMPROPERTY_PIN_MEDIUM
    } AMPROPERTY_PIN;

    //---------------------------------------------------------------------
    // IKsPropertySet interface
    //
    // Sets or gets a property identified by a property set GUID and a
    // property ID.
    //
    // Return codes for all 3 methods:
    //    E_PROP_SET_UNSUPPORTED  the property set is not supported
    //    E_PROP_ID_UNSUPPORTED   the property ID is not supported
    //                                for the specified property set
    //---------------------------------------------------------------------

cpp_quote("#ifndef _IKsPropertySet_")
cpp_quote("#define _IKsPropertySet_")

    //---------------------------------------------------------------------
    // #defines for IKsPropertySet::QuerySupported return result in pTypeSupport
    //---------------------------------------------------------------------

cpp_quote("#define KSPROPERTY_SUPPORT_GET  1")
cpp_quote("#define KSPROPERTY_SUPPORT_SET  2")


    [
	object,
    local,
        uuid(31EFAC30-515C-11d0-A9AA-00AA0061BE93),
	pointer_default(unique)
    ]
    interface IKsPropertySet : IUnknown
    {
        HRESULT Set(
                    [in]    REFGUID     guidPropSet,
                    [in]    DWORD       dwPropID,
                    [out, size_is(cbInstanceData)] LPVOID pInstanceData,
                    [in]    DWORD	    cbInstanceData,
                    [out, size_is(cbPropData)] LPVOID pPropData,
                    [in]    DWORD	    cbPropData);

        // To get a property, the caller allocates a buffer which the called
        // function fills in.  To determine necessary buffer size, call Get with
        // pPropData=NULL and cbPropData=0.
        HRESULT Get(
                    [in]    REFGUID     guidPropSet,
                    [in]    DWORD       dwPropID,
                    [out, size_is(cbInstanceData)] LPVOID pInstanceData,
                    [in]    DWORD	    cbInstanceData,
                    [out, size_is(cbPropData)] LPVOID pPropData,
                    [in]    DWORD	    cbPropData,
                    [out]   DWORD *	    pcbReturned);

        // QuerySupported must either return E_NOTIMPL or correctly indicate
        // if getting or setting the property set and property is supported.
        // S_OK indicates the property set and property ID combination is
        HRESULT QuerySupported(
                    [in]    REFGUID     guidPropSet,
                    [in]    DWORD       dwPropID,
                    [out]   DWORD       *pTypeSupport);
    }
cpp_quote("#endif // _IKsPropertySet_")

[
object,
uuid(6025A880-C0D5-11d0-BD4E-00A0C911CE86),
pointer_default(unique)
]
interface IMediaPropertyBag : IPropertyBag
{
    import "ocidl.idl";

    typedef IMediaPropertyBag *LPMEDIAPROPERTYBAG;

    // return the i'th element in the property bag
    [local]
    HRESULT EnumProperty(
        [in]  ULONG iProperty,
        [in, out] VARIANT * pvarPropertyName,
        [in, out] VARIANT * pvarPropertyValue
        );

}


[
object,
uuid(5738E040-B67F-11d0-BD4D-00A0C911CE86),
pointer_default(unique)
]
interface IPersistMediaPropertyBag : IPersist
{
    import "ocidl.idl";
    import "unknwn.idl";

    HRESULT InitNew(
        void
        );

    HRESULT Load(
        [in] IMediaPropertyBag * pPropBag,
        [in] IErrorLog * pErrorLog
        );

    HRESULT Save(
        [in] IMediaPropertyBag * pPropBag,
        [in] BOOL fClearDirty,
        [in] BOOL fSaveAllProperties
        );


    typedef IPersistMediaPropertyBag * LPPERSISTMEDIAPROPERTYBAG;
}


   //---------------------------------------------------------------------
   //
   // Defines IAMPhysicalPinInfo Interface
   //
   // Returns an enum and string that describes an input pin's physical type.
   //
   // Implement if: you have physical input pins such as video or audio (like
   // on a video capture card or a VCR)
   //
   // Use if: you want to communicate to a user available physical input pins
   // and allow them to select the active one if there is more than one
   //---------------------------------------------------------------------


[
	object,
     uuid(F938C991-3029-11cf-8C44-00AA006B6814),
     pointer_default(unique)
 ]
interface IAMPhysicalPinInfo : IUnknown {

	// Returns VFW_E_NO_ACCEPTABLE_TYPES if not a physical pin
	HRESULT GetPhysicalType(
		[out] long *pType,			// the enum representing the Physical Type
		[out] LPOLESTR *ppszType		// a friendly name
	);
}
typedef IAMPhysicalPinInfo *PAMPHYSICALPININFO;

   //---------------------------------------------------------------------
   // Defines IAMExtDevice Interface
   //
   // Base interface for external professional devices
   //
   // Implement if: the filter controls an external device such as a VCR,
   // timecode reader/generator, etc.  The intent is to build a object from
   // this implementation plus another that specifically describes the device,
   // such as IAMExtTransport.
   //
   // Use if: you want to control and external device such as a VCR
   //
   // See edevdefs.h for the enumerated parameter list
   //---------------------------------------------------------------------
 [
	object,
     uuid(B5730A90-1A2C-11cf-8C23-00AA006B6814),
	pointer_default(unique)
 ]
 interface IAMExtDevice : IUnknown
 {
	// General device capabilities property.  See edevdefs.h for supported
	// values
	HRESULT GetCapability(
     	[in] long Capability,		// identify the property
		[out] long *pValue,			// return value
		[out] double *pdblValue		// return value
 	);

	// Get external device identification string.  Usually the model #
	// of the device
	HRESULT get_ExternalDeviceID(
		[out] LPOLESTR *ppszData		// ID string
	);
	
	HRESULT get_ExternalDeviceVersion(
		[out] LPOLESTR *ppszData		// revision string
	);
	
	// Controls the external device's power mode
	HRESULT put_DevicePower([in] long PowerMode
	);
	HRESULT get_DevicePower([out] long *pPowerMode
	);
	
	// Some devices need to be reset in some way, i.e., rewinding a VCR
	// to the beginning of the tape and resetting the counter to zero.
	HRESULT Calibrate(
		[in] HEVENT hEvent,
		[in] long Mode,
		[out] long *pStatus		// OATRUE is active, OAFALSE is inactive
	);

	// Selects the device's communications port, i.e.,COM1, IEEE1394, etc.
	// See edevdefs.h for enums
	HRESULT put_DevicePort([in] long DevicePort
	);
	HRESULT get_DevicePort([out] long *pDevicePort
	);
	
}
typedef IAMExtDevice *PEXTDEVICE;

   //---------------------------------------------------------------------
   // Defines IAMExtTransport Interface
   //
   // Contains properties and methods that control behavior of an external
   // transport device such as a VTR
   //
   // Implement if: you control such a device.  Intended to be agregated
   // with IAMExtDevice.
   //
   // Use if: you want to control such a device
   //
   // See edevdefs.h for the parameter lists
   //---------------------------------------------------------------------
[
	object,
     uuid(A03CD5F0-3045-11cf-8C44-00AA006B6814),
     pointer_default(unique)
 ]
interface IAMExtTransport : IUnknown {

	// General transport capabilities property.  See edevdefs.h for enums
	HRESULT GetCapability(
     	[in] long Capability,		// identify the property
		[out] long *pValue,			// return value
		[out] double *pdblValue		// return value
 	);

	// For disc-based devices: spinning, or not spinning.
	// For tape-based device: threaded, unthreaded or ejected
	HRESULT put_MediaState([in] long State
	);
	HRESULT get_MediaState([out] long *pState	// see edevdefs.h
	);
		
	// Determines state of unit's front panel
	HRESULT put_LocalControl([in] long State
	);
	HRESULT get_LocalControl([out] long *pState	// OATRUE or OAFALSE
	);
	
	// Transport status such as Play, Stop, etc.  More extensive
	// than AM states.
	HRESULT GetStatus(
		[in] long StatusItem,	// see edevdefs.h
		[out] long *pValue
	);

	// Parameters such as recording speed, servo reference, ballistics, etc.
	HRESULT GetTransportBasicParameters(
		[in] long Param,
		[out] long *pValue,
		[out] LPOLESTR *ppszData
	);

	HRESULT SetTransportBasicParameters(
		[in] long Param,
		[in] long Value,
		[in] LPCOLESTR pszData
	);
	
	// Parameters such as video output mode
	HRESULT GetTransportVideoParameters(
		[in] long Param,
		[out] long *pValue
	);

	HRESULT SetTransportVideoParameters(
		[in] long Param,
		[in] long Value
	);

	// Parameters such as audio channel enable
	HRESULT GetTransportAudioParameters(
		[in] long Param,
		[out] long *pValue
	);

	HRESULT SetTransportAudioParameters(
		[in] long Param,
		[in] long Value
	);
	
	// Mode is  the movement of the transport, i.e., Play, Stop,
	// Record, Edit, etc.
	HRESULT put_Mode([in] long Mode
	);
	HRESULT get_Mode([out] long *pMode
	);

	// Rate is for variable speed control of the the device.  This
	// can be linked to IMediaControl::Rate() in the implementation
	// if desired.
	HRESULT put_Rate([in] double dblRate
	);
	HRESULT get_Rate([out] double *pdblRate
	);

	// This is a lengthy method, that is, it is in effect until canceled or complete and
	// requires housekeeping by the filter.  It puts transport in play mode and maintains
	// fixed relationship between master time reference and transport position.
	HRESULT GetChase(
		[out] long *pEnabled,	// OATRUE | OAFALSE
		[out] long *pOffset,	// offset in current time format
		[out] HEVENT *phEvent	// completion notification
	);
	HRESULT SetChase(
		[in] long Enable,		// OATRUE | OAFALSE
		[in] long Offset,		// offset in current time format
		[in] HEVENT hEvent		// completion notification
	);

	// Also a lengthy method: temporarily change transport speed (for synchronizing).
	HRESULT GetBump(
		[out] long *pSpeed,
		[out] long *pDuration	// in current time format
	);
	HRESULT SetBump(
		[in] long Speed,
		[in] long Duration	// in current time format
	);
	
	// Enable/Disable transport anti-headclog control.
	HRESULT get_AntiClogControl([out] long *pEnabled	// OATRUE | OAFALSE
	);
	HRESULT put_AntiClogControl([in] long Enable	// OATRUE | OAFALSE
	);
	
	// The following group of properties describes edit events.  An edit event can be a
	// standard insert or assemble edit or a memorized position called a bookmark.
	// A NOTE ABOUT EVENTS: as with all lengthy commands, event objects must be created to
	// signal completion or error.

	// Intended usage: an edit event is prepared for use by:
	// 1. Registering an edit property set and getting an EditID
	// 2. Setting the necessary edit properties
	// 3. Setting the edit property set active

	// Please see edevdefs.h for properties and values

	// The reference clock's advance is the mechanism that puts an edit in motion (see
	// ED_EDIT_REC_INPOINT).
	
	// Property set methods
	HRESULT GetEditPropertySet(
		[in] long EditID,
		[out] long *pState	// ED_SET_ACTIVE | ED_SET_INACTIVE | ED_SET_INVALID
							// | ED_SET_EXECUTING
	);

	HRESULT SetEditPropertySet(
		[in, out] long *pEditID,
		[in] long State		// ED_SET_REGISTER | ED_SET_DELETE | ED_SET_ACTIVE |
	);						// ED_SET_INACTIVE

	// the following properties define an edit event such as a bookmark, seek point, or
	//  actual edit
	HRESULT GetEditProperty(
		[in] long EditID,
		[in] long Param,
		[out] long *pValue
	);
	HRESULT SetEditProperty(
		[in] long EditID,
		[in] long Param,
		[in] long Value
	);
	
	// Activates a capable transport's edit control (typically used for "on the fly" editing).
	HRESULT get_EditStart([out] long *pValue	// OATRUE or OAFALSE
	);
	HRESULT put_EditStart([in] long Value			// OATRUE or OAFALSE
	);
}
typedef IAMExtTransport *PIAMEXTTRANSPORT;

   //---------------------------------------------------------------------
   // Defines IAMTimecodeReader Interface
   //
   // Contains properties and methods that define behavior of a
   // SMPTE/MIDI Timecode Reader.  It is expected that this interface
   // will be combined (aggregated) with IAMExtTransport to "build" a pro
   // VCR.
   //
   // Implement if: you control such a device
   //
   // Use if: you want to control such a device
   //
   // See edevdefs.h for the parameter lists
   //=====================================================================


// timecode structures
cpp_quote("#if 0")
cpp_quote("/* the following is what MIDL knows how to remote */")
typedef struct tagTIMECODE {
		WORD	wFrameRate;	// will be replaced by AM defs, but see ED_FORMAT_SMPTE for now
		WORD	wFrameFract;	// fractional frame.  full scale is always 0x1000
		DWORD	dwFrames;
}TIMECODE;
cpp_quote("#else /* 0 */")
cpp_quote("#ifndef TIMECODE_DEFINED")
cpp_quote("#define TIMECODE_DEFINED")
cpp_quote("typedef union _timecode {")
cpp_quote("   struct {")
cpp_quote("	 WORD   wFrameRate;")
cpp_quote("	 WORD   wFrameFract;")
cpp_quote("	 DWORD  dwFrames;")
cpp_quote("	 };")
cpp_quote("   DWORDLONG  qw;")
cpp_quote("   } TIMECODE;")
cpp_quote("")
cpp_quote("#endif /* TIMECODE_DEFINED */")
cpp_quote("#endif /* 0 */")

typedef TIMECODE *PTIMECODE;

typedef struct tagTIMECODE_SAMPLE {
	LONGLONG	qwTick;		// ActiveMovie 100ns timestamp
	TIMECODE	timecode;	// timecode
	DWORD		dwUser;		// timecode user data (aka user bits)
	DWORD		dwFlags;	   // timecode flags - see below
} TIMECODE_SAMPLE;
typedef TIMECODE_SAMPLE *PTIMECODE_SAMPLE;


[
	object,
     uuid(9B496CE1-811B-11cf-8C77-00AA006B6814),
     pointer_default(unique)
]
interface IAMTimecodeReader : IUnknown
{
	// Timecode Reader Mode - gets/sets the following properties
	// ED_TCR_SOURCE - timecode gen (readback), LTC, VITC, or Control Track
	HRESULT GetTCRMode(
		[in] long Param,
		[out] long *pValue);
	HRESULT SetTCRMode(
		[in] long Param,
		[in] long Value);
	
	// Select which line of the vertical interval timecode will be read from (if VITC).
	// To read VITC on specific multiple lines, the caller would make successive calls to
	// put_VITCLine(), once for each line desired.
	HRESULT put_VITCLine(
		[in] long Line );	// valid lines are 11-20, 0 means autoselect,
							// hi bit set means add to list of lines (for
							// readers that test across multiple lines)
	HRESULT get_VITCLine(
		[out] long *pLine ); // hi bit set means multiple lines are used,
							// and successive calls will cycle through the
							// line numbers (like an enumerator, only simpler)

	// GetTimecode can be used to obtain the most recent timecode value available in the
	// stream. The client can use this to monitor the timecode, parse duplicates and
	// discontinuities. The source filter supplying the timecode or possibly a down stream
	// filter might want to parse for discontinuities or errors since you have to look at
	// every sample to do this properly.
	//

	HRESULT GetTimecode(
      [out] PTIMECODE_SAMPLE pTimecodeSample) ;

}
typedef IAMTimecodeReader *PIAMTIMECODEREADER;

   //---------------------------------------------------------------------
   //=====================================================================
   // Defines IAMTimecodeGenerator Interface
   //
   // Contains properties and methods that define behavior of an external
   // SMPTE/MIDI Timecode Generator.  It is expected that this interface
   // will be combined (aggregated) with IAMExtTransport to "build" a pro
   // VCR.
   //
   // Implement if: you control such a device
   //
   // Use if: you want to control such a device
   //
   // See edevdefs.h for the parameter lists
    //---------------------------------------------------------------------
[
	object,
     uuid(9B496CE0-811B-11cf-8C77-00AA006B6814),
     pointer_default(unique)
 ]
interface IAMTimecodeGenerator : IUnknown {

	// Timecode Generator Mode - gets/sets the following properties (see
	// vcrdefss.h for detailed values):
	// ED_TCG_TIMECODE_TYPE - LTC, VITC, or MIDI
	// ED_TCG_FRAMERATE - 24, 25, 30 drop or 30 nondrop
	// ED_TCG_SYNC_SOURCE - what is driving the bitclock
	// ED_TCG_REFERENCE_SOURCE - what is driving the count value
	HRESULT GetTCGMode(
		[in] long Param,
		[out] long *pValue);

	HRESULT SetTCGMode(
		[in] long Param,
		[in] long Value);

	// Select into which line(s) of the vertical interval timecode will be inserted (if VITC).
	// Hi bit set means add this line to any previously set lines.
	// To generate VITC on specific multiple lines, the caller would make successive calls to
	// put_VITCLine(), once for each line desired.
	HRESULT put_VITCLine(
		[in] long Line		// valid lines are 11-20, 0 means autoselect(this setting
	);						// is for TC readers that decode from multiple lines)
	HRESULT get_VITCLine(
		[out] long *pLine
	);

	// Sets timecode and/or userbit value.  If generator is running, takes effect
	// immediately.  If caller wants to set only timecode, set userbit value to -1L (and
	// same for setting userbits only)
	//

	HRESULT SetTimecode(
      [in] PTIMECODE_SAMPLE pTimecodeSample) ;


	// GetTimecode can be used to obtain the most recent timecode value available in the
	// stream. The client can use this to monitor the timecode and verify the generator is
	// working properly
	//

	HRESULT GetTimecode(
      [out] PTIMECODE_SAMPLE pTimecodeSample) ;

}
typedef IAMTimecodeGenerator *PIAMTIMECODEGENERATOR;

    //---------------------------------------------------------------------
   // Defines IAMTimecodeDisplay Interface
   //
   // Contains properties and methods that define behavior of an external
   // SMPTE/MIDI Timecode Display device (aka "character generator" for
   // making "burn-ins" or "window dubs"). It is expected that this interface
   // will be combined (aggregated) with IAMExtTransport and the timecode
   // interfaces to "build" a pro VCR.
   //
   // Implement if: you control such a device
   //
   // Use if: you want to control such a device
   //
   // See edevdefs.h for the parameter lists
    //---------------------------------------------------------------------
[
	object,
     uuid(9B496CE2-811B-11cf-8C77-00AA006B6814),
     pointer_default(unique)
 ]
interface IAMTimecodeDisplay : IUnknown
{
	// Enable/disable external device's timecode reader's character generator output.  Some
	// readers have this feature - this is not intended for rendering inside the PC!
	HRESULT GetTCDisplayEnable(
		[out] long *pState);	// OATRUE | OAFALSE
	HRESULT SetTCDisplayEnable(
		[in] long State);		// OATRUE | OAFALSE
								// Timecode reader's character generator output
								//  characteristics (size, position, intensity, etc.).
	HRESULT GetTCDisplay(
		[in] long Param,
		[out] long *pValue);
	HRESULT SetTCDisplay(
		[in] long Param,
		[in] long Value);

	/* Allowable params and values (see edevdefs.h for details):
		ED_TCD_SOURCE
			ED_TCR | ED_TCG
		ED_TCD_SIZE
			ED_SMALL | ED_MED | ED_LARGE
		ED_TCD_POSITION
			ED_TOP | ED_MIDDLE | ED_BOTTOM or'd  with
			ED_LEFT | ED_CENTER | ED_RIGHT
		ED_TCD_INTENSITY
			ED_HIGH | ED_LOW
		ED_TCD_TRANSPARENCY	// set from 0 to 4, 0 being completely opaque
		ED_TCD_INVERT		// white on black or black on white
			OATRUE | OAFALSE
		ED_TCD_BORDER		// white border for black chars, black border for white letters
			OATRUE | OAFALSE
	*/
}
typedef IAMTimecodeDisplay *PIAMTIMECODEDISPLAY;


[
    object,
    uuid(c6545bf0-e76b-11d0-bd52-00a0c911ce86),
    pointer_default(unique)
]
interface IAMDevMemoryAllocator : IUnknown
{
    HRESULT GetInfo(
        [out] DWORD *pdwcbTotalFree,
        [out] DWORD *pdwcbLargestFree,
        [out] DWORD *pdwcbTotalMemory,
        [out] DWORD *pdwcbMinimumChunk);

    HRESULT CheckMemory(
        [in] const BYTE *pBuffer);

    HRESULT Alloc(
        [out] BYTE **ppBuffer,
        [in, out] DWORD *pdwcbBuffer);

    HRESULT Free(
        [in] BYTE *pBuffer);

    HRESULT GetDevMemoryObject(
        [out] IUnknown **ppUnkInnner,
        [in] IUnknown *pUnkOuter);
}
typedef IAMDevMemoryAllocator *PAMDEVMEMORYALLOCATOR;


[
    object,
    uuid(c6545bf1-e76b-11d0-bd52-00a0c911ce86),
    pointer_default(unique)
]
interface IAMDevMemoryControl : IUnknown
{
    HRESULT QueryWriteSync();

    HRESULT WriteSync();

    HRESULT GetDevId(
        [out] DWORD *pdwDevId);

}
typedef IAMDevMemoryControl *PAMDEVMEMORYCONTROL;

//  Flags for IAMStreamSelection::Info
enum _AMSTREAMSELECTINFOFLAGS {
    AMSTREAMSELECTINFO_ENABLED   = 0x01,  // Enable - off for disable
    AMSTREAMSELECTINFO_EXCLUSIVE = 0x02   // Turns off the others in the group
                                          // when enabling this one
};
//  Flags for IAMStreamSelection::Enable
enum _AMSTREAMSELECTENABLEFLAGS {
    //  Currently valid values are :
    //  0 - disable all streams in the group containing this stream
    //  ..._ENABLE - enable only this stream with in the given group
    //               and disable all others
    //  ..._ENABLEALL - send out all streams
    AMSTREAMSELECTENABLE_ENABLE    = 0x01,  // Enable
    AMSTREAMSELECTENABLE_ENABLEALL = 0x02   // Enable all streams in the group
                                            // containing this stream
};

//  Control which logical streams are played and find out information about
//  them
//  Normally supported by a filter
[
    object,
    uuid(c1960960-17f5-11d1-abe1-00a0c905f375),
    pointer_default(unique)
]
interface IAMStreamSelect : IUnknown
{
    //  Returns total count of streams
    HRESULT Count(
        [out] DWORD *pcStreams);      // Count of logical streams

    //  Return info for a given stream - S_FALSE if iIndex out of range
    //  The first steam in each group is the default
    HRESULT Info(
        [in] long lIndex,              // 0-based index
        [out] AM_MEDIA_TYPE **ppmt,   // Media type - optional
                                      // Use DeleteMediaType to free
        [out] DWORD *pdwFlags,        // flags - optional
        [out] LCID  *plcid,           // LCID (returns 0 if none) - optional
        [out] DWORD *pdwGroup,        // Logical group - optional
        [out] WCHAR **ppszName,       // Name - optional - free with CoTaskMemFree
                                      // optional
        [out] IUnknown **ppObject,    // Associated object - optional
                                      // Object may change if Enable is
                                      // called on this interface
                                      // - returns NULL if no associated object
                                      // Returns pin or filter for DShow
        [out] IUnknown **ppUnk);      // Stream specific interface

    //  Enable or disable a given stream
    HRESULT Enable(
        [in]  long lIndex,
        [in]  DWORD dwFlags);
}
typedef IAMStreamSelect *PAMSTREAMSELECT;


