This is a Push Source filter for DirectShow. It can be used for pushing
(uploading) data to DirectShow.


Requires DSPACK from www.progdigy.com (see DSPACK subdirectory)
Note that when compiled with V2.3.4 an error migth occur when
the graph is stopped. The included DSPACK files don't have this
problem and are of a more recent CVS version.
The only addition to this CVS code is a single line in BaseClass.pas:
     IInterface = IUnknown;


Version history
20060115:  V1.00  - Initial release
20060119:  V1.00  - Added SAMPLE.GRF. The MPEG 2 demultiplexer has the PIDs
                    for the video/audio associated with the SAMPLE.TS file,
                    so you will at least see something when pushing SAMPLE.TS.
                    Note that you first need to render the output pins
                    of the MPEG2 demultiplexer (audio and video) before
                    starting the graph and pushing the file from the
                    property page.


Hints/Notes:
. After initialization/setup only one procedure of the filter is called
  for pushing data: PushData()
. The filter can be used without any application code from within GraphEdit.
  Make sure the buffer requirements and the media types are set before
  connecting (rendering) the output pin. Then render the whole graph.
  After starting the graph you can use 'Push file' for pushing data from a file.


*******************************************************************************
Typical application code/steps (untested!), see SAMPLE directory for an
working implemenation:

1> Include the IMajorPushSource definition and the CLSID identifiers in you application:

         IID_MajorPushSource          = '{6D616A6F-7269-7479-6E6C-535243020100}';
         T_IID_MajorPushSource: TGUID = IID_MajorPushSource;

         IMajorPushSource = interface(IUnknown)
         [IID_MajorPushSource]
           function  GetVersionInformation(out Info: PChar): HRESULT; stdcall;        // Get version information
           function  GetInformation       (out Info: PChar): HRESULT; stdcall;        // Get next text information (debug)
           function  GetInformationCount  (out Count: Integer): HRESULT; stdcall;     // Get information count (debug)
           function  GetDeliveredCount    (out Count: Integer): HRESULT; stdcall;     // Get number of bytes delivered to output pin
           procedure SetLog               (OnOff: Boolean); stdcall;                  // (De)activate file log
           function  GetLog               (out OnOff: Boolean): HRESULT; stdcall;     // Get status activation log file
           procedure SetAddTimestamps     (OnOff: Boolean); stdcall;                  // (De)activate timestamps in media samples
           function  GetAddTimestamps     (out OnOff: Boolean): HRESULT; stdcall;     // Get status timestamps
           procedure SetMediaType         (MajorType: PCLSID; MinorType: PCLSID; FormatType: PCLSID; CheckType: Boolean); stdcall;                // Set media types when pin (re)connects
           function  GetMediaType         (MajorType: PCLSID; MinorType: PCLSID; FormatType: PCLSID; out CheckType: Boolean): HRESULT; stdcall;   // Get media types to use when pin (re)connects
           procedure SetBufferSize        (BufferSize: Integer; BufferAlignment: Integer); stdcall;                           // Set (preferred) buffer requirements
           function  GetBufferSize        (out BufferSize: Integer; out BufferAlignment: Integer): HRESULT; stdcall;          // Get (decided) buffer requirements
           function  GetPushedData        (Buffer: PByte; Size: Integer): HRESULT; stdcall;                                   // Get first xx bytes of media sample of last pushed data (debug)
           procedure FlushData; stdcall;                                              // Flush data (assures next data is realigned)
           function  PushData             (Buffer: PByte; Size: Integer; out Delivered: Integer): HRESULT; stdcall;           // Push data
         end;

2> Define variables
         var
           FFilterPushSourceFilter   : IBaseFilter;
           FFilterPushSourceInterface: IMajorPushSource;
           FFilterGraph              : IFilterGraph2;

3> Create filter manager
         Hr := CoCreateInstance(CLSID_FilterGraph, nil, CLSCTX_INPROC_SERVER, IID_IFilterGraph2, FFilterGraph);

4> Create push filter
         Hr := CoCreateInstance(CLSID_MajorPushSource, nil, CLSCTX_INPROC_SERVER, IID_IBaseFilter, FFilterPushSourceFilter);

   or load predefined graph and use the FindFilterByName for example to get the interface
         Hr := FFilterGraph.FindFilterByName('Major Push Source', FFilterPushSourceFilter);

5> Get the interface
         Hr := FFilterPushSource.QueryInterface(T_IID_MajorPushSource, FFilterPushSourceInterface);

   Note: Getting the interface can be omitted if we are using the
         "(FFilterPushSourceFilter as IMajorPushSource).XXXX" convention, which does an
         automatic QueryInterface. This is usefull if we only have to call some
         individual functions.

6> Change push source settings if appropriate (e.g. buffer size)
   This will not be possible when the graph is already complete, since the output pin of
   the filter is only set when the pin is being connected. In such a case, find
   the pin, disconnect it and reconnect it.
         (FFilterPushSourceFilter as IMajorPushSource).SetBufferSize(96256, 188, False);
   or
         FFilterPushSourceInterface.SetBufferSize(96256, 188, False);

7> Make sure the graph is rendered and the pins are connected (when a complete graph was loaded then
   this is already so).

8> Run the graph (pushing data when the graph is not in running state has little use)
         (FFilterGraph as IMediaControl).Run;

9> Push data
         (FFilterPushSourceFilter as IMajorPushSource).PushData(Buffer, BufferLength);
   or
         FFilterPushSourceInterface.PushData(Buffer, BufferLength);

10> Stop the graph when done pushing all data
         (FFilterGraph as IMediaControl).Stop;
         FFilterGraph.Abort;

11> Release the interfaces and such when completely done
         FFilterPushSourceInterface := nil;
         FFilterPushSourceFilter := nil;
         FFilterGraph := nil;