//------------------------------------------------------------------------------
// File: AXCore.idl
//
// Desc: Core streaming interfaces.  Other ActiveMovie-only interfaces
//       are in AXExtend.idl.
//
// Copyright (c) 1992-2002, Microsoft Corporation.  All rights reserved.
//------------------------------------------------------------------------------


// include unknwn.idl and objidl.idl first

#define CHARS_IN_GUID 39  // 128 bits, plus { - } punctuation and terminal null
                          // chars NOT BYTES in the standard representation
                          // e.g. {D3588AB0-0781-11ce-B03A-0020AF0BA770} + null

cpp_quote("#define CHARS_IN_GUID     39")


//=====================================================================
//=====================================================================
// media types & formats
//=====================================================================
//=====================================================================

// There is a high-level media type (audio, compressed video,
// mpeg video, midi). Within each type, there is a subtype (cinepak, pcm)
// and a length+untyped data block defining the format in a
// type-specific manner. EG for video/cinepak, the data block would be
// a bitmapinfo.
// The contents of the format block are defined by the formattype GUID.
// For example, FORMAT_VideoInfo, FORMAT_WaveFormatEx. In the future, this
// may be a pointer to an object supporting property style interfaces
// in which case the GUID may be something like FORMAT_IUnknown. When
// you are passed a media type you should check the format type, if
// it isn't a type you recognize, then don't touch the format block

typedef struct _AMMediaType {
    GUID     majortype;
    GUID     subtype;
    BOOL     bFixedSizeSamples;
    BOOL     bTemporalCompression;
    ULONG    lSampleSize;
    GUID     formattype;
    IUnknown *pUnk;
    ULONG    cbFormat;
    [size_is(cbFormat)] BYTE * pbFormat;
} AM_MEDIA_TYPE;

//=====================================================================
//=====================================================================
// pin information
//=====================================================================
//=====================================================================

// is this an input or output pin
typedef enum _PinDirection {
    PINDIR_INPUT,
    PINDIR_OUTPUT
} PIN_DIRECTION;

// other types that need defining
#define MAX_PIN_NAME     128
cpp_quote("#define MAX_PIN_NAME     128")
cpp_quote("#define MAX_FILTER_NAME  128")
#define MAX_FILTER_NAME  128


//=====================================================================
//=====================================================================
// time information
//
// This represents a time (either reference or stream) in 100ns units.
// The class library contains a CRefTime helper class
// that supports simple comparison and arithmetic operations
//=====================================================================
//=====================================================================

typedef LONGLONG REFERENCE_TIME;
typedef double REFTIME;

// Win32 HANDLEs have to be cast to these as the MIDL compiler doesn't
// like the HANDLE type or in fact anything remotely associated with
// them. If this ever gets ported to a MAC environment then these will
// have to become an alertable synchronisation object that it supports

typedef DWORD_PTR HSEMAPHORE;
typedef DWORD_PTR HEVENT;

//=====================================================================
//=====================================================================
// Allocator properties
//
// Used to describe the actual properties of an allocator,
// and used to request properties from an allocator or from an upstream
// filter that could create an allocator. See IMemAllocator and
// IMemInputPin.
//=====================================================================
//=====================================================================
typedef struct _AllocatorProperties {
        long cBuffers;  // count of buffers at this allocator
        long cbBuffer;  // size of each buffer, excluding any prefix

        // alignment of the buffer - buffer start will be aligned on a multiple of
        // this amount
        long cbAlign;

        // prefix amount. Each buffer is immediately preceeded by cbPrefix bytes.
        // note that GetPointer points to the beginning of the buffer proper.
        // the prefix is aligned, i.e. (GetPointer() - cbPrefix) is aligned on cbAlign.
        long cbPrefix;
} ALLOCATOR_PROPERTIES;





// forward declarations (in alphabetical order - we were getting duplicates)
interface IAMovieSetup;
interface IEnumFilters;
interface IEnumMediaTypes;
interface IEnumPins;
interface IBaseFilter;
interface IFilterGraph;
interface IMediaFilter;
interface IMediaSample;
interface IMemAllocator;
interface IMemAllocatorCallbackTemp;
interface IMemAllocatorNotifyCallbackTemp;
interface IMemInputPin;
interface IPin;
interface IReferenceClock;



//=====================================================================
//=====================================================================
// Defines IPin interface
//
// interface representing a single, unidirection connection point on a
// filter. A Pin will connect to exactly one other pin on another filter.
// This interface represents the interface other objects can call on
// this pin. The interface between the filter and the pin is private to
// the implementation of a specific filter.
//
// During the connection process, one pin will be instructed to take
// the lead: the connect interface on this pin will be calling, passing
// the IPin* for the other pin. This connecting pin will call the
// ReceiveConnection member function on the other pin, as well as presumably
// other format-enumeration and queryinterface calls to establish whether
// the connection is possible.
//=====================================================================
//=====================================================================

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

    // initiate a connection to another pin. calls ReceiveConnection on the
    // other pin. Verifies that the connection is possible and may reject
    // it.
    // The mediatype parameter is optional. If it is not null, the pin must
    // connect using that media type if possible. The subtype and/or format
    // type can be GUID_NULL, meaning that the pin can fill them in as desired.
    // This allows an application to partially specify the media type to be
    // used for the connection, insisting on eg YUV 422 but leaving details
    // (such as the image size) to be negotiated between the pins.
    HRESULT Connect(
        [in] IPin * pReceivePin,        // connect yourself to this pin
        [in] const AM_MEDIA_TYPE * pmt  // (optional) connect using this type
    );

    // called by a connecting pin to make a connection
    HRESULT ReceiveConnection(
        [in] IPin * pConnector,
        [in] const AM_MEDIA_TYPE *pmt   // this is the media type we will exchange
    );

    // break a connection - no params since there is only one connection
    // possible on this pin
    HRESULT Disconnect(void);

    // Find the pin this pin is connected to (if any)
    // The pointer returned is AddRef()d
    // Fails if the pin is not connected
    HRESULT ConnectedTo(
        [out] IPin **pPin
    );

    // Return the media type of a connection if the pin is connected
    HRESULT ConnectionMediaType(
        [out] AM_MEDIA_TYPE *pmt
    );

    // get information about the pin itself
    typedef struct _PinInfo {
    IBaseFilter *pFilter;   // the filter this pin is on
    PIN_DIRECTION dir;  // am I an input or output pin?
    WCHAR achName[MAX_PIN_NAME];    // the name of this pin within this filter
    } PIN_INFO;

    HRESULT QueryPinInfo(
        [out] PIN_INFO * pInfo
    );

    // We often want to know the direction.  Rather than use the
    // relatively expensive QueryPinInfo, use this
    HRESULT QueryDirection(
        [out] PIN_DIRECTION *pPinDir
    );

    // Get an identifier for the pin (allows connections to be saved).
    // The storage will be allocated by the filter using CoTaskMemAlloc
    // The caller should free it using CoTaskMemFree
    HRESULT QueryId(
        [out] LPWSTR * Id
    );

    // will the pin accept the format type, S_OK yes, S_FALSE no
    HRESULT QueryAccept(
        [in] const AM_MEDIA_TYPE *pmt
    );

    // return an enumerator for this pin's preferred media types
    HRESULT EnumMediaTypes(
        [out] IEnumMediaTypes **ppEnum
    );

    // return an array of IPin* - the pins that this pin internally connects to
    // All pins put in the array must be AddReffed (but no others)
    // Errors: "Can't say" - FAIL; not enough slots - return S_FALSE
    // Default: return E_NOTIMPL
    // The filter graph will interpret E_NOTIMPL as any input pin connects to
    // all visible output pins and vise versa.
    // apPin can be NULL if nPin==0 (not otherwise).
    HRESULT QueryInternalConnections(
        [out] IPin* *apPin,     // array of IPin*
        [in, out] ULONG *nPin   // on input, the number of slots
                                // on output  the number of pins
    );

    // notify the pin that no more data is expected until a new run
    // command is issued. End of stream should be queued and delivered after
    // all queued data is delivered. Pass through if there is no queued data.
    // Flush should flush any queued EOS.
    // returns S_OK unless there is some error.
    // input pins only: output pins will normally return E_UNEXPECTED.
    HRESULT EndOfStream(void);

    // Flush

    // Enter flush state: do the following steps (in order)
    // -- prevent any more Receives succeeding (set a flushing flag)
    // -- discard any queued data
    // -- free anyone blocked on Receive in your filter
    // -- pass BeginFlush to any downstream pins
    HRESULT BeginFlush(void);

    // End flush state: do the following steps in order
    // -- ensure no more data will be pushed by your filter
    //    (sync with thread if you have one, stop it pushing and
    //     discard any queued data)
    // -- re-enable Receive (clear internal flushing flag)
    // -- pass EndFlush to any downstream pins
    HRESULT EndFlush(void);

    // informational: all data arriving after this call is part of a segment
    // from StartTime to StopTime, played at rate. This allows filters that
    // process buffers containing more than one sample to clip the rendering
    // to within the start and stop times.
    //
    // A source pin will call a destination pin on this method after completing
    // delivery of any previous data, and before any Receive calls for the
    // new data
    HRESULT NewSegment(
                [in] REFERENCE_TIME tStart,
                [in] REFERENCE_TIME tStop,
                [in] double dRate);
}

typedef IPin *PPIN;


//=====================================================================
//=====================================================================
// Defines IEnumPins interface
//
// interface returned from IBaseFilter::EnumPins(). based on IEnumXXXX
//=====================================================================
//=====================================================================

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

    HRESULT Next(
        [in] ULONG cPins,                       // place this many pins...
        [out, size_is(cPins)] IPin ** ppPins,   // ...in this array
        [out] ULONG * pcFetched                 // actual count passed
    );

    HRESULT Skip(
        [in] ULONG cPins);

    HRESULT Reset(void);

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

typedef IEnumPins *PENUMPINS;


//=====================================================================
//=====================================================================
// Defines IEnumMediaTypes interface
//
// Enumerates the preferred formats for a pin
//=====================================================================
//=====================================================================

[
object,
uuid(89c31040-846b-11ce-97d3-00aa0055595a),
pointer_default(unique)
]
interface IEnumMediaTypes : IUnknown {

    // to call this member function pass in the address of a pointer to a
    // media type. The interface will allocate the necessary AM_MEDIA_TYPE
    // structures and initialise them with the variable format block

    HRESULT Next(
        [in] ULONG cMediaTypes,             // place this many types...
        [out, size_is(cMediaTypes)]
             AM_MEDIA_TYPE ** ppMediaTypes, // ...in this array
        [out] ULONG * pcFetched             // actual count passed
    );

    HRESULT Skip(
        [in] ULONG cMediaTypes);

    HRESULT Reset(void);

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

typedef IEnumMediaTypes *PENUMMEDIATYPES;



//========================================================================
//========================================================================
// Defines IFilterGraph interface
//
// abstraction representing a graph of filters
// This allows filters to be joined into a graph and operated as a unit.
//========================================================================
//========================================================================

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

    //==========================================================================
    // Low level filter functions
    //==========================================================================

        // Add a filter to the graph and name it with *pName.
        // If the name is not unique, The request will fail.
        // The Filter graph will call the JoinFilterGraph
        // member function of the filter to inform it.
        // This must be called before attempting Connect, ConnectDirect or Render
        // for pins of the filter.

        HRESULT AddFilter
            ( [in] IBaseFilter * pFilter,
              [in, string] LPCWSTR pName
            );


        // Remove a filter from the graph. The filter graph implementation
        // will inform the filter that it is being removed.

        HRESULT RemoveFilter
            ( [in] IBaseFilter * pFilter
            );


        // Set *ppEnum to be an enumerator for all filters in the graph.

        HRESULT EnumFilters
            ( [out] IEnumFilters **ppEnum
            );


        // Set *ppFilter to be the filter which was added with the name *pName
        // Will fail and set *ppFilter to NULL if the name is not in this graph.

        HRESULT FindFilterByName
            ( [in, string] LPCWSTR pName,
              [out] IBaseFilter ** ppFilter
            );

    //==========================================================================
    // Low level connection functions
    //==========================================================================

        // Connect these two pins directly (i.e. without intervening filters)
        // the media type is optional, and may be partially specified (that is
        // the subtype and/or format type may be GUID_NULL). See IPin::Connect
        // for details of the media type parameter.
        HRESULT ConnectDirect
            ( [in] IPin * ppinOut,              // the output pin
              [in] IPin * ppinIn,               // the input pin
              [in, unique] const AM_MEDIA_TYPE* pmt     // optional mediatype
            );

        // Break the connection that this pin has and reconnect it to the
        // same other pin.

        HRESULT Reconnect
            ( [in] IPin * ppin        // the pin to disconnect and reconnect
            );



        // Disconnect this pin, if connected.  Successful no-op if not connected.

        HRESULT Disconnect
            ( [in] IPin * ppin
            );

    //==========================================================================
    // intelligent connectivity - now in IGraphBuilder, axextend.idl
    //==========================================================================

    //==========================================================================
    // Whole graph functions
    //==========================================================================

    // Once a graph is built, it can behave as a (composite) filter.
    // To control this filter, QueryInterface for IMediaFilter.

    // The filtergraph will by default ensure that the graph has a sync source
    // when it is made to Run.  SetSyncSource(NULL) will prevent that and allow
    // all the filters to run unsynchronised until further notice.
    // SetDefaultSyncSource will set the default sync source (the same as would
    // have been set by default on the first call to Run).
    HRESULT SetDefaultSyncSource(void);

}

typedef IFilterGraph *PFILTERGRAPH;



//==========================================================================
//==========================================================================
// Defines IEnumFilters interface
//
// enumerator interface returned from IFilterGraph::EnumFilters().
// based on IEnum pseudo-template
//==========================================================================
//==========================================================================

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

    HRESULT Next
        ( [in]  ULONG cFilters,           // place this many filters...
          [out] IBaseFilter ** ppFilter,  // ...in this array of IBaseFilter*
          [out] ULONG * pcFetched         // actual count passed returned here
        );


    HRESULT Skip
        ( [in] ULONG cFilters
        );


    HRESULT Reset(void);


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

typedef IEnumFilters *PENUMFILTERS;


//=====================================================================
//=====================================================================
// Defines IMediaFilter interface
//
// multimedia components that provide time-based data will expose this.
// this interface abstracts an object that processes time-based data streams
// and represents a multimedia device (possibly implemented in software).
// it controls the active/running state of the object and its synchronization
// to other objects in the system.
//
// derived from IPersist so that all filter-type objects in a graph
// can have their class id serialised.
//=====================================================================
//=====================================================================

[
object,
uuid(56a86899-0ad4-11ce-b03a-0020af0ba770),
pointer_default(unique)
]
interface IMediaFilter : IPersist {

    // tell the filter to transition to the new state. The state transition
    // may not be instantaneous (external mechanical activity may be involved,
    // for example). The state functions may return before the state
    // transition has completed

    // these functions will return S_OK if the transition is complete, S_FALSE if
    // the transition is not complete but no error has occurred, or some error value
    // if the transition failed.
    HRESULT Stop(void);
    HRESULT Pause(void);

    // in order to synchronise independent streams, you must pass a time
    // value with the Run command. This is the difference between stream
    // time and reference time. That is, it is the amount to be added to
    // the IMediaSample timestamp to get the time at which that sample
    // should be rendered according to the reference clock.
    // If we are starting at the beginning of the stream, it will thus be
    // simply the time at which the first sample should appear. If we are
    // restarting from Paused mode in midstream, then it will be the total
    // time we have been paused added to the initial start time.

    // the filtergraph will provide this information to its filters. If you
    // are an app calling the filtergraph, it's ok to pass a start time of
    // 0, in which case the filter graph will calculate a soon-as-possible
    // time. FilterGraphs will accept 0 meaning ASAP; most filters will not.

    HRESULT Run(REFERENCE_TIME tStart);


    // possible states that the filter could be in
    typedef enum _FilterState {
        State_Stopped,            // not in use
        State_Paused,             // holding resources, ready to go
        State_Running             // actively processing media stream
    } FILTER_STATE;

    // find out what state the filter is in.
    // If timeout is 0, will return immediately - if a state transition is
    // not complete, it will return the state being transitioned into, and
    // the return code will be VFW_S_STATE_INTERMEDIATE.  if no state
    // transition is in progress the state will be returned and the return
    // code will be S_OK.
    //
    // If timeout is non-zero, GetState will not return until the state
    // transition is complete, or the timeout expires.
    // The timeout is in milliseconds.
    // You can also pass in INFINITE as a special value for the timeout, in
    // which case it will block indefinitely waiting for the state transition
    // to complete. If the timeout expires, the state returned is the
    // state we are trying to reach, and the return code will be
    // VFW_S_STATE_INTERMEDIATE. If no state transition is in progress
    // the routine returns immediately with return code S_OK.

    //
    // return State is State_Running, State_Paused or State_Stopped.
    // return code is S_OK, or VFW_S_STATE_INTERMEDIATE if state
    // transition is not complete or an error value if the method failed.
    HRESULT GetState(
                [in] DWORD dwMilliSecsTimeout,
                [out] FILTER_STATE *State);


    // tell the filter the reference clock to which it should synchronize
    // activity. This is most important to rendering filters and may not
    // be of any interest to other filters.
    HRESULT SetSyncSource(
        [in] IReferenceClock * pClock);

    // get the reference clock currently in use (it may be NULL)
    HRESULT GetSyncSource(
        [out] IReferenceClock ** pClock);
}

typedef IMediaFilter *PMEDIAFILTER;


//=====================================================================
//=====================================================================
// Defines IBaseFilter interface
//
// all multimedia components will expose this interface
// this interface abstracts an object that has typed input and output
// connections and can be dynamically aggregated.
//
// IMediaFilter supports synchronisation and activity state: IBaseFilter
// is derived from that since all filters need to support IMediaFilter,
// whereas a few objects (plug-in control distributors for example) will
// support IMediaFilter but not IBaseFilter.
//
// IMediaFilter is itself derived from IPersist so that every filter
//supports GetClassID()
//=====================================================================
//=====================================================================

[
object,
uuid(56a86895-0ad4-11ce-b03a-0020af0ba770),
pointer_default(unique)
]
interface IBaseFilter : IMediaFilter {

    // enumerate all the pins available on this filter
    // allows enumeration of all pins only.
    //
    HRESULT EnumPins(
        [out] IEnumPins ** ppEnum     // enum interface returned here
    );

    // Convert the external identifier of a pin to an IPin *
    // This pin id is quite different from the pin Name in CreatePin.
    // In CreatePin the Name is invented by the caller.  In FindPin the Id
    // must have come from a previous call to IPin::QueryId.  Whether or not
    // this operation would cause a pin to be created depends on the filter
    // design, but if called twice with the same id it should certainly
    // return the same pin both times.
    HRESULT FindPin(
        [in, string] LPCWSTR Id,
        [out] IPin ** ppPin
    );

    // find out information about this filter
    typedef struct _FilterInfo {
    WCHAR achName[MAX_FILTER_NAME]; // maybe null if not part of graph
        IFilterGraph * pGraph;                   // null if not part of graph
    } FILTER_INFO;

    HRESULT QueryFilterInfo(
        [out] FILTER_INFO * pInfo
    );

    // notify a filter that it has joined a filter graph. It is permitted to
    // refuse. The filter should addref and store this interface for later use
    // since it may need to notify events to this interface. A null pointer indicates
    // that the filter is no longer part of a graph.
    HRESULT JoinFilterGraph(
        [in] IFilterGraph * pGraph,
        [in, string] LPCWSTR pName
    );

    // return a Vendor information string. Optional - may return E_NOTIMPL.
    // memory returned should be freed using CoTaskMemFree
    HRESULT QueryVendorInfo(
        [out, string] LPWSTR* pVendorInfo
    );
}

typedef IBaseFilter *PFILTER;


//=====================================================================
//=====================================================================
// sync and state management
//=====================================================================
//=====================================================================


//=====================================================================
//=====================================================================
// Defines IReferenceClock interface
//=====================================================================
//=====================================================================

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

    // get the time now
    HRESULT GetTime(
        [out] REFERENCE_TIME *pTime
    );

    // ask for an async notification that a time has elapsed
    HRESULT AdviseTime(
        [in] REFERENCE_TIME baseTime,       // base reference time
        [in] REFERENCE_TIME streamTime,     // stream offset time
    [in] HEVENT hEvent,                     // advise via this event
        [out] DWORD_PTR * pdwAdviseCookie   // where your cookie goes
    );

    // ask for an async periodic notification that a time has elapsed
    HRESULT AdvisePeriodic(
        [in] REFERENCE_TIME startTime,      // starting at this time
        [in] REFERENCE_TIME periodTime,     // time between notifications
        [in] HSEMAPHORE hSemaphore,         // advise via a semaphore
    [out] DWORD_PTR * pdwAdviseCookie       // where your cookie goes
    );

    // cancel a request for notification
    HRESULT Unadvise(
        [in] DWORD_PTR dwAdviseCookie);
}

typedef IReferenceClock *PREFERENCECLOCK;

//=====================================================================
//=====================================================================
// Defines IReferenceClock2 interface
//=====================================================================
//=====================================================================

[
        object,
        uuid(36b73885-c2c8-11cf-8b46-00805f6cef60),
        pointer_default(unique)
]
interface IReferenceClock2 : IReferenceClock {
}

typedef IReferenceClock2 *PREFERENCECLOCK2;


//=====================================================================
//=====================================================================
// Data transport interfaces
//=====================================================================
//=====================================================================


//=====================================================================
//=====================================================================
// Defines IMediaSample interface
//=====================================================================
//=====================================================================

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

    // get me a read/write pointer to this buffer's memory. I will actually
    // want to use sizeUsed bytes.
    HRESULT GetPointer([out] BYTE ** ppBuffer);

    // return the size in bytes of the buffer data area
    long GetSize(void);

    // get the stream time at which this sample should start and finish.
    HRESULT GetTime(
        [out] REFERENCE_TIME * pTimeStart,  // put time here
        [out] REFERENCE_TIME * pTimeEnd
    );

    // Set the stream time at which this sample should start and finish.
    // pTimeStart==pTimeEnd==NULL will invalidate the time stamps in
    // this sample
    HRESULT SetTime(
        [in] REFERENCE_TIME * pTimeStart,   // put time here
        [in] REFERENCE_TIME * pTimeEnd
    );

    // sync-point property. If true, then the beginning of this
    // sample is a sync-point. (note that if AM_MEDIA_TYPE.bTemporalCompression
    // is false then all samples are sync points). A filter can start
    // a stream at any sync point.  S_FALSE if not sync-point, S_OK if true.

    HRESULT IsSyncPoint(void);
    HRESULT SetSyncPoint(BOOL bIsSyncPoint);

    // preroll property.  If true, this sample is for preroll only and
    // shouldn't be displayed.
    HRESULT IsPreroll(void);
    HRESULT SetPreroll(BOOL bIsPreroll);

    long GetActualDataLength(void);
    HRESULT SetActualDataLength(long);

    // these allow for limited format changes in band - if no format change
    // has been made when you receive a sample GetMediaType will return S_FALSE

    HRESULT GetMediaType(AM_MEDIA_TYPE **ppMediaType);
    HRESULT SetMediaType(AM_MEDIA_TYPE *pMediaType);

    // returns S_OK if there is a discontinuity in the data (this frame is
    // not a continuation of the previous stream of data
    // - there has been a seek or some dropped samples).
    HRESULT IsDiscontinuity(void);
    // set the discontinuity property - TRUE if this sample is not a
    // continuation, but a new sample after a seek or a dropped sample.
    HRESULT SetDiscontinuity(BOOL bDiscontinuity);

    // get the media times for this sample
    HRESULT GetMediaTime(
        [out] LONGLONG * pTimeStart,
        [out] LONGLONG * pTimeEnd
    );

    // Set the media times for this sample
    // pTimeStart==pTimeEnd==NULL will invalidate the media time stamps in
    // this sample
    HRESULT SetMediaTime(
        [in] LONGLONG * pTimeStart,
        [in] LONGLONG * pTimeEnd
    );
}

typedef IMediaSample *PMEDIASAMPLE;

//  Values for dwFlags for AM_SAMPLE_PROPERTIES
enum tagAM_SAMPLE_PROPERTY_FLAGS
     { AM_SAMPLE_SPLICEPOINT        = 0x01,   /* Is this a splice point
                                                 IE can it be decoded
                                                 without reference to
                                                 previous data */
       AM_SAMPLE_PREROLL            = 0x02,   /* Is this a preroll sample */
       AM_SAMPLE_DATADISCONTINUITY  = 0x04,   /* Set if start of new segment */
       AM_SAMPLE_TYPECHANGED        = 0x08,   /* Has the type changed */
       AM_SAMPLE_TIMEVALID          = 0x10,   /* Set if time is valid */
       AM_SAMPLE_TIMEDISCONTINUITY  = 0x40,   /* time gap in data starts after
                                                 this sample - pbBuffer can
                                                 be NULL
                                              */
       AM_SAMPLE_FLUSH_ON_PAUSE     = 0x80,   /*  For live data - discard
                                                  in paused state
                                              */
       AM_SAMPLE_STOPVALID          = 0x100,  /*  Stop time is valid */
       AM_SAMPLE_ENDOFSTREAM        = 0x200,  /*  End of stream after
                                                  this data
                                                  This is reserved for
                                                  kernel streaming and is
                                                  not currently used by
                                                  ActiveMovie
                                              */
       AM_STREAM_MEDIA              = 0,      /*  Normal data stream id */
       AM_STREAM_CONTROL            = 1       /*  Control stream id */
                                              /*  > 7FFFFFFF is application
                                                  defined stream
                                              */
     };

//  Media sample generic properties structure
typedef struct tagAM_SAMPLE2_PROPERTIES {
    DWORD    cbData;         //  Length of generic data for extensiblity
                             //  Number of bytes INCLUDING this field
    DWORD    dwTypeSpecificFlags; // Type specific flag data
    DWORD    dwSampleFlags;  //  Flags bits defined by  AM_SAMPLE_xxx flags
                             //  All undefined bits RESERVED (set to 0,
                             //  leave on copy)
    LONG     lActual;        //  Length of data in buffer
    REFERENCE_TIME tStart;   //  Start time if valid
    REFERENCE_TIME tStop;    //  Stop time if valid
    DWORD    dwStreamId;     //  Stream 0 is normal media transport
                             //  Stream 1 is control
    AM_MEDIA_TYPE *pMediaType; // Copy of media type - INVALID after Release()
    BYTE    *pbBuffer;       //  Pointer to buffer - INVALID after Release()
    LONG     cbBuffer;       //  Length of buffer
} AM_SAMPLE2_PROPERTIES;

//=====================================================================
//=====================================================================
// Defines IMediaSample2 interface
//=====================================================================
//=====================================================================

[
        local,
        object,
        uuid(36b73884-c2c8-11cf-8b46-00805f6cef60),
        pointer_default(unique)
]
interface IMediaSample2 : IMediaSample {

    //  Get sample properties
    //
    //      cbProperties - length of generic data to retrieve
    //      pbProperties - pointer to generic data buffer - can
    //                     be NULL if cbProperties is NULL
    //                     data conforms to AM_SAMPLE_PROPERTIES
    //
    HRESULT GetProperties(
        [in] DWORD cbProperties,
        [out, size_is(cbProperties)] BYTE * pbProperties
    );
    //  Set sample properties
    //
    //      cbProperties - length of generic data to set
    //      pbProperties - pointer to generic data buffer - can
    //                      be NULL if cbProperties is NULL
    //                      data conforms to AM_SAMPLE_PROPERTIES
    //
    //
    HRESULT SetProperties(
        [in] DWORD cbProperties,
        [in, size_is(cbProperties)] const BYTE * pbProperties
    );


    // //  Get the clock associated with the sample
    // HRESULT GetClock(
    //     [out] IReferenceClock2 **ppClock
    // );

    // //  Get a pointer to the object containing the data
    // //
    // //  riid      - IID of interface required on object
    // //  ppvobject - Pointer to object containing the data
    // //
    // //  Returns
    // //      S_OK - Got the object
    // //      E_NOINTERFACE - object does not support this interface
    // //                      if IUnknown is not supported
    // //                      there is no backing object
    // //      E_NOTIMPL     - samples don't have backing objects
    // //
    // //
    // HRESULT GetBackingObject(
    //     [in]  REFIID riid,
    //     [out] void **ppvObject
    // );
}

typedef IMediaSample2 *PMEDIASAMPLE2;


// flags for dwFlags in IMemAllocator::GetBuffer
// AM_GBF_PREVFRAMESKIPPED is only significant when asking for a buffer from the
// video renderer.  It should be TRUE if and only if the previous frame
// was skipped.  It affects quality management.
// AM_GBF_NOTASYNCPOINT indicates to the downstream filter (most likely the
// video renderer) that you are not going to fill this buffer with a sync point
// (keyframe) so now would be a bad time to return a buffer with a dynamic
// format change, because you will be unable to switch to the new format without
// waiting for the next sync point, causing some frames to be dropped.
#define AM_GBF_PREVFRAMESKIPPED 1
#define AM_GBF_NOTASYNCPOINT    2
cpp_quote("#define AM_GBF_PREVFRAMESKIPPED 1")
cpp_quote("#define AM_GBF_NOTASYNCPOINT 2")

// This may not be supported by allocators
cpp_quote("#define AM_GBF_NOWAIT 4")

// This flag is supported by the VMR's surface allocator
// When set the DDraw surface used for the media sample
// is returned is an un-locked state.  Calls the GetPointer on
// the returned media sample will fail and return a NULL pointer
//
cpp_quote("#define AM_GBF_NODDSURFACELOCK 8")

//=====================================================================
//=====================================================================
// Defines IMemAllocator interface
//
// an allocator of IMediaSample blocks to be used for data transfer between
// pins. Can be provided by input, output or a third party. Release
// the IMediaSample object obtained back to the pool by calling
// IMediaSample::Release.
//=====================================================================
//=====================================================================

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

    // negotiate buffer sizes, buffer count and alignment. pRequest is filled
    // in by the caller with the requested values. pActual will be returned
    // by the allocator with the closest that the allocator can come to this.
    // Cannot be called unless the allocator is decommitted.
    // Calls to GetBuffer need not succeed until Commit is called.
    HRESULT SetProperties(
        [in] ALLOCATOR_PROPERTIES* pRequest,
        [out] ALLOCATOR_PROPERTIES* pActual);

    // return the properties actually being used on this allocator
    HRESULT GetProperties(
        [out] ALLOCATOR_PROPERTIES* pProps);


    // commit the memory for the agreed buffers
    HRESULT Commit(void);

    // release the memory for the agreed buffers. Any threads waiting in
    // GetBuffer will return with an error. GetBuffer calls will always fail
    // if called before Commit or after Decommit.
    HRESULT Decommit(void);

    // get container for a sample. Blocking, synchronous call to get the
    // next free buffer (as represented by an IMediaSample interface).
    // on return, the time etc properties will be invalid, but the buffer
    // pointer and size will be correct.
    // Will only succeed if memory is committed. If GetBuffer is blocked
    // waiting for a buffer and Decommit is called on another thread,
    // GetBuffer will return with an error.
    HRESULT GetBuffer(
        [out] IMediaSample **ppBuffer,
        [in] REFERENCE_TIME * pStartTime,
        [in] REFERENCE_TIME * pEndTime,
        [in] DWORD dwFlags
    );

    // put a buffer back on the allocators free list.
    // this is typically called by the Release() method of the media
    // sample when the reference count goes to 0
    //
    HRESULT ReleaseBuffer(
        [in] IMediaSample *pBuffer
    );
}

typedef IMemAllocator *PMEMALLOCATOR;

//=====================================================================
//=====================================================================
// Defines IMemAllocatorCallbackTemp interface
//
// If the allocator supports IMemAllocator2 then callbacks are
// available
//
//=====================================================================
//=====================================================================
[
        object,
        uuid(379a0cf0-c1de-11d2-abf5-00a0c905f375),
        pointer_default(unique)
]
interface IMemAllocatorCallbackTemp : IMemAllocator {

    //  Set notification interface.  pNotify can be NULL
    HRESULT SetNotify(
        [in] IMemAllocatorNotifyCallbackTemp *pNotify);

    //  Get current stats
    HRESULT GetFreeCount(
        [out] LONG *plBuffersFree);
}

//=====================================================================
//=====================================================================
// Defines IMemAllocatorNotify interface
//
//=====================================================================
//=====================================================================
[
        object,
        uuid(92980b30-c1de-11d2-abf5-00a0c905f375),
        pointer_default(unique)
]
interface IMemAllocatorNotifyCallbackTemp : IUnknown {

    //  Called whenever ReleaseBuffer is called in the allocator
    //  Note the caller may have acquired locks and this call may
    //  occur in any context so generally the implementor of this
    //  call will just set an event or post a message for another
    //  thread to take action.
    HRESULT NotifyRelease();
}

//=====================================================================
//=====================================================================
// Defines IMemInputPin interface
//
// basic shared memory transport interface.
//=====================================================================
//=====================================================================

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

    // return the allocator interface that this input pin
    // would like the output pin to use
    HRESULT GetAllocator(
                [out] IMemAllocator ** ppAllocator);

    // tell the input pin which allocator the output pin is actually
    // going to use.
    // If the readonly flag is set, then all samples from this allocator are
    // to be treated as read-only, and should be copied before being modified.
    HRESULT NotifyAllocator(
                [in] IMemAllocator * pAllocator,
                [in] BOOL bReadOnly
                );

    // this method is optional (can return E_NOTIMPL). Output pins are not obliged to call
    // this method, nor are they obliged to fulfil the request. Input pins making such a
    // request should check the allocator in NotifyAllocator to see if it meets their needs. If
    // not, the input pin is responsible for any necessary data copy.
    // Zero values will be treated as don't care: so a pin can return an alignment value
    // and leave the other values 0.
    HRESULT GetAllocatorRequirements( [out] ALLOCATOR_PROPERTIES*pProps);

    // here's the next block of data from the stream. AddRef it if
    // you need to hold it beyond the end of the Receive call.
    // call pSample->Release when done with it.
    //
    // This is a blocking synchronous call.  Usually no blocking
    // will occur but if a filter cannot process the sample immediately
    // it may use the caller's thread to wait until it can.
    HRESULT Receive(
                [in] IMediaSample * pSample);

    // Same as Receive but with multiple samples.  Useful for
    // fragmented streams
    HRESULT ReceiveMultiple(
                [in, size_is(nSamples)] IMediaSample **pSamples,
                [in] long nSamples,
                [out] long *nSamplesProcessed);

    // See if Receive might block
    // Returns S_OK if it can block, S_FALSE if it can't or some
    // failure code (assume it can in this case)
    HRESULT ReceiveCanBlock();
}

typedef IMemInputPin *PMEMINPUTPIN;


//=====================================================================
//=====================================================================
// Defines IAMovieSetup interface
//
// exported by filter to allow it to be self-registering
//=====================================================================
//=====================================================================

[
object,
uuid(a3d8cec0-7e5a-11cf-bbc5-00805f6cef20),
pointer_default(unique)
]
interface IAMovieSetup : IUnknown {

    // methods to register and unregister filter, etc.

    HRESULT Register( );
    HRESULT Unregister( );
}

typedef IAMovieSetup *PAMOVIESETUP;


//=====================================================================
//=====================================================================
// Defines IMediaSeeking interface
//
// Controls seeking (time, bytes, frames, fields and samples)
//=====================================================================
//=====================================================================

typedef enum AM_SEEKING_SeekingFlags
{
    AM_SEEKING_NoPositioning        = 0x00,     // No change
    AM_SEEKING_AbsolutePositioning  = 0x01,     // Position is supplied and is absolute
    AM_SEEKING_RelativePositioning  = 0x02,     // Position is supplied and is relative
    AM_SEEKING_IncrementalPositioning   = 0x03, // (Stop) position relative to current
                                                // Useful for seeking when paused (use +1)
    AM_SEEKING_PositioningBitsMask  = 0x03,     // Useful mask
    AM_SEEKING_SeekToKeyFrame       = 0x04,     // Just seek to key frame (performance gain)
    AM_SEEKING_ReturnTime           = 0x08,     // Plug the media time equivalents back into the supplied LONGLONGs

    AM_SEEKING_Segment              = 0x10,     // At end just do EC_ENDOFSEGMENT,
                                                // don't do EndOfStream
    AM_SEEKING_NoFlush              = 0x20      // Don't flush
} AM_SEEKING_SEEKING_FLAGS;

typedef enum AM_SEEKING_SeekingCapabilities
{
    AM_SEEKING_CanSeekAbsolute     = 0x001,
    AM_SEEKING_CanSeekForwards     = 0x002,
    AM_SEEKING_CanSeekBackwards    = 0x004,
    AM_SEEKING_CanGetCurrentPos    = 0x008,
    AM_SEEKING_CanGetStopPos       = 0x010,
    AM_SEEKING_CanGetDuration      = 0x020,
    AM_SEEKING_CanPlayBackwards    = 0x040,
    AM_SEEKING_CanDoSegments       = 0x080,
    AM_SEEKING_Source              = 0x100  // Doesn't pass thru used to
                                            // count segment ends
} AM_SEEKING_SEEKING_CAPABILITIES;

[
        object,
        uuid(36b73880-c2c8-11cf-8b46-00805f6cef60),
        pointer_default(unique)
]
interface IMediaSeeking : IUnknown {

    // Returns the capability flags
    HRESULT GetCapabilities( [out] DWORD * pCapabilities );

    // And's the capabilities flag with the capabilities requested.
    // Returns S_OK if all are present, S_FALSE if some are present, E_FAIL if none.
    // *pCababilities is always updated with the result of the 'and'ing and can be
    // checked in the case of an S_FALSE return code.
    HRESULT CheckCapabilities( [in,out] DWORD * pCapabilities );

    // returns S_OK if mode is supported, S_FALSE otherwise
    HRESULT IsFormatSupported([in] const GUID * pFormat);
    HRESULT QueryPreferredFormat([out] GUID * pFormat);

    HRESULT GetTimeFormat([out] GUID *pFormat);
    // Returns S_OK if *pFormat is the current time format, otherwise S_FALSE
    // This may be used instead of the above and will save the copying of the GUID
    HRESULT IsUsingTimeFormat([in] const GUID * pFormat);

    // (may return VFE_E_WRONG_STATE if graph is stopped)
    HRESULT SetTimeFormat([in] const GUID * pFormat);

    // return current properties
    HRESULT GetDuration([out] LONGLONG *pDuration);
    HRESULT GetStopPosition([out] LONGLONG *pStop);
    HRESULT GetCurrentPosition([out] LONGLONG *pCurrent);

    // Convert time from one format to another.
    // We must be able to convert between all of the formats that we say we support.
    // (However, we can use intermediate formats (e.g. MEDIA_TIME).)
    // If a pointer to a format is null, it implies the currently selected format.
    HRESULT ConvertTimeFormat([out] LONGLONG * pTarget, [in] const GUID * pTargetFormat,
                              [in]  LONGLONG    Source, [in] const GUID * pSourceFormat );


    // Set current and end positions in one operation
    // Either pointer may be null, implying no change
    HRESULT SetPositions( [in,out] LONGLONG * pCurrent, [in] DWORD dwCurrentFlags
            , [in,out] LONGLONG * pStop, [in] DWORD dwStopFlags );

    // Get CurrentPosition & StopTime
    // Either pointer may be null, implying not interested
    HRESULT GetPositions( [out] LONGLONG * pCurrent,
                          [out] LONGLONG * pStop );

    // Get earliest / latest times to which we can currently seek "efficiently".
    // This method is intended to help with graphs where the source filter has
    // a very high latency.  Seeking within the returned limits should just
    // result in a re-pushing of already cached data.  Seeking beyond these
    // limits may result in extended delays while the data is fetched (e.g.
    // across a slow network).
    // (NULL pointer is OK, means caller isn't interested.)
    HRESULT GetAvailable( [out] LONGLONG * pEarliest, [out] LONGLONG * pLatest );

    // Rate stuff
    HRESULT SetRate([in]  double dRate);
    HRESULT GetRate([out] double * pdRate);

    // Preroll
    HRESULT GetPreroll([out] LONGLONG * pllPreroll);
}

typedef IMediaSeeking *PMEDIASEEKING;

//  Flags for IMediaEventEx
cpp_quote("enum tagAM_MEDIAEVENT_FLAGS")
cpp_quote("{")
cpp_quote("    AM_MEDIAEVENT_NONOTIFY = 0x01")
cpp_quote("};")