none
DirectShow Capture Devices in Expression Encoder 4

    Question

  • Hi

    I am trying to interface a custom capture device to MS Expression Encoder Pro 4 (EE4).  I am starting on a steep learning curve for DirectShow.

    EE4 has a DirectShow capture filter input but I cannot find out what input formats it supports.  I have a Direct Show filter for the capture card that supports MPEG2 Transport stream on its output (i.e. MEDIATYPE_Stream & MEDIASUBTYPE_MPEG2_TRANSPORT) .  I believe EE4 does not support this, but will support MPEG 2 Video (i.e. MEDIATYPE_Video & MEDIASUBTYPE_MPEG2_VIDEO).  I have changed the supported Media Type reported to EE4 in my debugger and this seems to support this suposition.

    So my question is, can I create a DirectShow graph (using available DirectShow filters), and somehow publishing this Graph as a Direct Show Capture Filter as an input for EE4 to use?

    Sorry if my terminology is not correct, I have understood from MSDN the principle of the different filter types, and a graph puts them together.  What if I then want to create an input to EE4 using a "collection" of filters, rather than one specific filter

    I hope someone can help as I have wasted alot of time with no success.

    John

     

     

    Thursday, July 08, 2010 2:00 PM

Answers

  • EE4 can support more than just a source filter as it will use automatic graph building to connect the source to its processing filter.  The real problem lays in the MPEG2 Demux which won't connect to anything until configured, which will cause automatic graph building to fail unless you can pull of some magnificent timing (i.e. configure the output of the MPEG2 Demux during the connection to your TS source).

    If you want to go with the sub-graph approach then use the following graph.

    TS Capture source -> MPEG2 Demux -> MPEG2 Decoder -> Sample Grabber -> NULL Renderer

    And for the main graph

    Push Source (custom) -> [ EE4 stuff ] 

     

    Use the Sample Grabber callback mechanism to queue samples in your Push Source.  In fact the entire sub-graph can be contained inside the Push Source (universe in a bottle approach).

     


    www.chrisnet.net
    • Marked as answer by reynot Thursday, July 22, 2010 4:07 PM
    Tuesday, July 13, 2010 1:45 PM

All replies

  • My understanding has improved slowly after more reading and playing with Graph Editor and EE4.

    My direct show filter for the capture device outputs MPEG2 TRANSPORT Stream.  When I place this filter on Graph Editor and on the capture pin, select Render Pin, it adds an MPEG-2 Demultiplexer (with clock) but this has no output.  I believe my Filter is not reporting sufficient information on interogation, will continue to read.

    When I repeat the same with an MPEG2 Transport stream file, the direct show graph completes, with MPEG2 Audio/Video decoders and renderers.  So the MPEG file capture source is obviously reporting something I am not.

    Any help appreciated or a reference to how to write a real time capture device

    Ta

    John

    Thursday, July 08, 2010 4:06 PM
  • If you haven't already, look at Vivek's vcam example on my Downloads page.

    I don't know how EE4 integrates with dshow.  However, I think your first step should be to provide a capture device that outputs a simple video type such as MEDIASUBTYPE_RGB24 and get it working with EE4 before the tackling MPEG2 part.


    Please use Vote As Helpful (green up arrow at top-left of posts) and Mark As Answer where appropriate.
    My dshow site is http://tmhare.mvps.org.
    Thursday, July 08, 2010 4:17 PM
  • Hi March Hare

    Thanks for the reply, I was away at the weekend, so just got back.

    I have tried your virtual cam example with EE4 and this works fine and gives me hope that a correctly implemented push filter will do the job.

    Further reading tells me that the MSFT MPEG2 demux only supports TS streams in push mode.  I have my source filter and I need to connect it to the MSFT demux filter.  I must map the MSFT demux A/V output pins to specific PID's.  I already have the PID information but can't find where and how I do the mapping?

    Many thanks

    John

    Monday, July 12, 2010 12:07 PM
  • The Microsoft MPEG demux filter doesn't support PID mapping in Pull mode.  I believe this mode is designed for file playback of program streams so I don't think it will work if your source is "live".  If your source knows the length of the source content and can support random reads/seeks then it could work if you can build a virtual or physical program stream file.

    From the description you give I think it might be easier to encapsulate your output as a transport stream so that the demux can operate in Push mode and you can configure the PID map.


    www.chrisnet.net
    Monday, July 12, 2010 3:19 PM
  • Ooops, I don't seem to be getting notifications of replies!  Thanks, this confirms my understanding. 

    From my understanding EE4 only takes a DirectShow capture filter on its input (e.g. web cams etc).  So what I believe I need to create is a DirectShow capture filter based on VCam, that builds my required DirectShow graph and outputs the source to my Output Pin.
    i.e.

    TS Capture Source -> MPEG2 Demux -> MPG2 Decoder -> Virtual Renderer

    So one last bit of help, is what virtual renderer device can I use that take RGB on its input to pass RGB to the output Pin of my new Capture filter?  I guess I will have to register a callback that can then call my output pin FillBuffer() function?

    Many thanks for help

    John

    Tuesday, July 13, 2010 12:56 PM
  • EE4 can support more than just a source filter as it will use automatic graph building to connect the source to its processing filter.  The real problem lays in the MPEG2 Demux which won't connect to anything until configured, which will cause automatic graph building to fail unless you can pull of some magnificent timing (i.e. configure the output of the MPEG2 Demux during the connection to your TS source).

    If you want to go with the sub-graph approach then use the following graph.

    TS Capture source -> MPEG2 Demux -> MPEG2 Decoder -> Sample Grabber -> NULL Renderer

    And for the main graph

    Push Source (custom) -> [ EE4 stuff ] 

     

    Use the Sample Grabber callback mechanism to queue samples in your Push Source.  In fact the entire sub-graph can be contained inside the Push Source (universe in a bottle approach).

     


    www.chrisnet.net
    • Marked as answer by reynot Thursday, July 22, 2010 4:07 PM
    Tuesday, July 13, 2010 1:45 PM
  • Thanks Chris for your reply again.

    I have read several posts (doing more reading than coding) about the Sample Grabber -> Null Renderer approach, or creating a rendering sync approach.  

    I think I am right in assuming the Sample Grabber -> Null renderer method is efficient in that it doesn't have extra mem copies?

    Some further questions (if you will allow),

    How is the Grabber callback mechanism made to the push source?  I can't find an example of this?  I am trying to get my head around which context we will be operating in but I guess the COM thread model means all will be within the push context?

    I also have to configure the MPEG demux as you state which is provided by the application that initiates EE4 (using EE4 SDK) and the loading of the filter.  I guess I should then be able to get a reference to my Push Source filter, and then set properties I have defined on it to configure the Demux Pids etc.  Not sure how I get this reference.

    Thanks very much for your replies, 

    John

    Tuesday, July 13, 2010 4:24 PM
  • The Sampler Grabber -> Null renderer has no additional buffer copies verses a custom renderer.  The Sampler Grabber is a in-place filter hence has no buffer of its own (buffer belongs to the NULL renderer).

    Don't worry about the COM threading model, these are not true COM objects, just regular objects with COM style interfaces.  In your push source pin simply inherit from your base class (e.g. CSourceStream) and the ISamplerGrabberCB interface and implement BufferCB and SampleCB methods.  BufferCB should do nothing and return S_FALSE, SampleCB should be your actual implementation that receives the sample and either buffers it internally or increments the reference count before it transfers it to the main graph sample buffer in FillBuffer().

    You will know when the MPEG Demux is created as the graph builder will attempt to connect it to the TS Source, which assuming the TS Source is your custom filter you can then attempt to configuring it at the end of connect.  Can't guarantee this will work as the filter may not allow configuration until connect has returned with success.


    www.chrisnet.net
    Tuesday, July 13, 2010 5:11 PM
  • Thanks Chris will give this approach a whirl and see how far I get.  I will leave the question open in the event of more questions which I hope not to have!

    Many thanks for all your help,

    John

    Wednesday, July 14, 2010 8:17 AM
  • Hi

    I have implemented most of what is discussed, and have created a Sub Graph (using Vcam->Grabber->NullRenderer to start) within my CSourceStream filter class.  All works well thus far and I have registered the graph with the ROT and I can see my sub graph being correctly created.  I am getting callbacks with samples from the Grabber and need to feed these to the output pin.  This is where I was unsure of how to implement

    It seems FillBuffer() is called regularly by the output pin, I was expecting to push it to the pin.  My understanding is I need to store the buffers from my Grabber in a queue, and then copy a buffer contents from the queue when FillBuffer() is called.  I think I have to increment the ref count when adding to the queue and dec on copying the data in the Fill buffer call?  I cant find the reference count for IMediaSample?

    So I wasn't expecting to have to perform a copy here, and is my understanding reasonable?

    Thanks

    John

    Thursday, July 15, 2010 9:34 AM
  • To save time, it seems this thread was asking the same question.  I have implemented a simple semaphore queue which is getting me further forward.  

    http://social.msdn.microsoft.com/Forums/en/windowsdirectshowdevelopment/thread/998df8b2-9143-4d67-8b15-cc0e1b68ea14

    My filter now correctly displays the VCam output in GraphEditor but EE4 reports an "unknown error".

    Thursday, July 15, 2010 1:05 PM
  • FillBuffer() is called by a thread that is created inside the CSourceStream class.  FillBuffer() is called as fast as possible and you are free to block there for short periods of time while waiting for a sample to arrive.  You can't block indefinitely as you will prevent the graph from changing state.

    A simple queue with the samples seems like the way to go, with a copy to the output sample in FillBuffer.

    Can you list your 2 graph topologies again?  I'm a little confused by what you posted 2 posts up, I think you might have something a little backwards.


    www.chrisnet.net
    Thursday, July 15, 2010 1:58 PM
  • Hi Chris

    Thanks for the reply,  I have implemented a simple queue with a semaphore that will time out after a second, if a new sample has not been received.  So I am performing a copy of the contents of the IMediaSample from one to the other.  I do some size checks to ensure there is sufficient room.  I am incrementing the reference count when adding to the queue, and releasing once removed and copied.

    If I run Graph editor through the debugger, all is well.

    The original setup as discussed was going to be ;

     

    TS Capture source -> MPEG2 Demux -> MPEG2 Decoder -> Sample Grabber -> NULL Renderer

    And for the main graph  :   Push Source (custom) -> [ EE4 stuff ] 

    I changed it slightly to reduce the number of issues to solve to, sorry I did not make it clear  ;

     

    VCam Filter(Vikram) -> Sample Grabber -> NULL Renderer

    And remaining for the main graph  :  Push Source (custom) -> [ EE4 stuff ] 

     

    So running within the Visual Studio 2008 debugger all is well,  no errors.

    If I run Graph Editor independently, add my filter to a graph, render the pin and then Run (Play), I get "The Graph could not change state. Invalid Pointer (Return Code: 0x80004003)".  I can't find any definition of this error on the web.  If I ignore this error, the playback is ok but the DirectShow SDK Filter graph crashes on shutdown also.

    Something is obviously a miss, difficult outside of the debugger.  Any clue as to the error?

    Thanks as always

     

    Thursday, July 15, 2010 2:58 PM
  • You've probably got an uninitialized variable that is hosing you outside of the debugger.  Invalid pointer is an error returned by certain functions that check the input parameters, if it receives NULL when expecting a valid pointer it will return this.

    For EE4 are you emulating a Live source or a file source?


    www.chrisnet.net
    Thursday, July 15, 2010 3:24 PM
  • I've been looking for uninitialised variables, that the debugger is "so" kindly initialising, one of those pleasant tasks.

    One thing I had missed on closing the debugger is I have "1 object left active" causing an assertion, although this doesn't explain why it fails on run when not in the debugger.

    For EE4 I was using my chain to emulate a live Source, I can add the other parts into my graph but wanted to sort the EE4 interface out first, if that makes sense?

    Thursday, July 15, 2010 3:39 PM
  • I have found the object I left active causing the assertion on shut down, so that is resolved.

    I am still getting the invalid pointer so will need to find the initialisation issue.  Anyway of working out which function is complaining?

    Thanks

    Thursday, July 15, 2010 3:48 PM
  • Never ignore code.

    Gradually Ive stripped out my code and found the cause, this macro returns an invalid pointer that was the cause of the error

    CheckPointer(pMediaSampleToProcess, E_POINTER);

    Doh!!!

    Thanks for bouncing off ideas, moving onto real data tomorrow.

    Thursday, July 15, 2010 4:49 PM
  • The reason I asked about the EE4 live is that in order for EE4 to see you source as a live source (emulated capture device) it has to be registered in the capture device category, which is what the VCam sample filter does.  

    So your graphs should be:

    Sub-graph:

    Push Source -> Sample Grabber -> NULL Renderer

    Main graph:

    VCam Filter(Vikram) -> [ EE4 stuff ] 

     

    Tracking down the invalid pointer issue will be a little tricky.  Fortunately it doesn't appear to be fatal.  Because it is happening during the Run() transition I would look at all methods that get called in the filter during the transition.  Also try pressing Pause() before Run() and see if you have the same result.


    www.chrisnet.net
    Thursday, July 15, 2010 5:10 PM
  • Ah ok re: EE4.  Yes my main graph is based on VCam to register as a capture device.

     

    I found the invalid pointer issue, after stripping out functionality.  Semaphore initial state was signalled, so we went into the data processing block on the first time with a null packet, all nice once explained.

    This demo filter works in EE4 also, so real progress being made, thanks ....

    Friday, July 16, 2010 9:08 AM
  • Hi Chris and anyone else listening

    I have created my code capturing real samples, and have it working with some constants, had a few questions if anyone could help.

    (1) Sub Graph Class

    My class that creates the sub graph was initially being created on the Capture Filter constructor.  However EE4 seemed to be creating and destroying this class in a polling fashion, so need to move it.  I thought moving the it to the CSourceStream Pin for the capture Filter.  I thought the ::Active() callback would be ideal for construction of my sub graph.  However now the call to create the graph builder hangs.

      hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,IID_IGraphBuilder, (void**)&pIGraphBuilder );

    It does not return from the call, and effectively hangs the application, any ideas?

    (2) Video Sizing

    Having difficulty understanding the MPEG2 Demux and why I need to define the video size information.  Surely it is just splitting out packets and feeding to the MPEG2 Decoder.  Although I get the impression some decoders require to be told video sizing and others can work it out from the ES stream.  FFD show seems the less intelligent version?

    Thanks

    Tim

    Wednesday, July 21, 2010 9:23 AM
  • I found out the answer to the Sub Graph class issue, which several people seem to have had.  I created the graph builder on construction in the CSOURCE constructor, which in this context it will do.  I believe the creation must have a message handler associated.  I add the components to the Graph on the first run only.  Works will in both EE4 and Graph Editor, which do not behave the same.

     

    Still no idea how to overcome the video sizing issue?

    John

    Wednesday, July 21, 2010 4:23 PM
  • FFDShow can figure out the size from the bitstream, however this requires a dynamic format change downstream of the decoder.  If the downstream filter doesn't accept the dynamic format change then it will fail.  If the size matches the original configuration then no format change is necessary.  I'm guessing the connecting filter doesn't support this.

    Note: it also might depend on what version of FFDShow you are testing with.  The version I tested was one of the "ffdshow tryouts" builds.


    www.chrisnet.net
    Wednesday, July 21, 2010 5:55 PM
  • Thanks Chris

    I don't quite understand the change in size and how it is decided.  Is there somewhere I can read about this, as I haven't come across discussions in my travels.  Will check what version of FFDshow I down loaded, it was only recently.

    I have made great progress with EE4 input aswell.  EE4 takes my Capture filter and all is well.  

    I do not have any reference back to the Capture filter created, if I know the CLSID of the object, can I get a reference back to an active object?  I need this to feed the input samples into the filter.

    Many thanks for your help

    Thursday, July 22, 2010 4:07 PM