1

I am continuing work on my DirectShow application and am just putting the finishing touches on it. What the program is doing is going through a video file in 1 second intervals and capturing from the samplegrabber the current buffer and processing it before moving on. However, I was noticing that I was getting duplicate images in my tests to which I found out that DirectShow has not incremented through the video in that 1 second interval fast enough. My question is if there is a way to check when DirectShow is ready for me to call the samplegrabber to get the current frame and to process it. At the moment I call sleep for 1 second but there has to be a better method. Thank you in advance for the help.

EDIT

I just tried running a check to see if the video's position is equal to the next position that I would like to grab and process. That decreased the number of duplicate frames but I still see them showing up in chunks.

Seb
  • 3,414
  • 10
  • 73
  • 106

2 Answers2

0

I always let the DS framework handle the processing rate: in the main application thread, configure the sample grabber callback and then when the callback is triggered, you get the media sample as well as sample time: at this point you can process the sample if the appropriate interval i.e. 1 second has elapsed.

What do you mean you call sleep for a second and from where (which thread) do you call it? If you're doing this from inside the callback you are effectively blocking the DirectShow pipeline? Perhaps if you could explain your setup in more detail I could be more helpful.

/// Callback that is triggered per media sample
/// Note this all happens in the DirectShow streaming thread!
STDMETHODIMP SampleCB( double dSampleTime, IMediaSample * pSample )
{
  // check timestamp and if one second has elapsed process sample accordingly
  // else do nothing

  ...

  // Get byte pointer
  BYTE* pbData(NULL);
  HRESULT hr = pSample->GetPointer(&pbData);
  if (FAILED(hr)) 
  {
    return hr;
  }

  ...
}

P.S if you want to process the samples as fast as possible, you can set the sample timestamp to NULL in your callback.

  // set time to NULL to allow for fast rendering since the 
  // the video renderer controls the rendering rate according
  // to the timestamps
  pSample->SetTime(NULL, NULL);
Ralf
  • 9,405
  • 2
  • 28
  • 46
  • I currently don't have any callback functions setup as I am currently just grabbing data from the sample grabber whenever it is ready and processing it from there. I took a look online and saw very limited resources on how the IMediaSample class is used. I tried to Query the Graph's interface with an "E_NOINTERFACE" handle being returned. – Seb Feb 17 '11 at 19:45
  • In my DirectShow experience, the "correct" way to do this is via the sample grabber callback: by being notified of every sample that passes through the graph, you have complete control of what to do with each sample. As for the IMediaSample interface, there isn't much to it, all you need to do is get the media sample buffer as shown in the code section above so that you can process/save it. You can't query the graph for the IMediaSample interface. The IMediaSample is a container for the media sample and is passed through the DS graph (i.e. from filter to filter). – Ralf Feb 18 '11 at 05:25
  • After refactoring my code to have a callback from the Samplegrabber everything works out perfectly. I was able to delete any Sleep calls and get a huge performance boost with no duplicate images. Thank you for your help. – Seb Feb 18 '11 at 15:56
0

Try setting your graph timer to NULL. It will allow to:

  • process the file as fast as possible
  • will relieve you of the issues you have.

Of course, it won't work if you are rendering the file to screen at the same time.

Daniel Mošmondor
  • 19,718
  • 12
  • 58
  • 99
  • I've searched all over the place, but I couldn't find anything for a graph timer. Could you please go into further detail? – Seb Feb 17 '11 at 22:28
  • To set the graph clock, have a look at http://msdn.microsoft.com/en-us/library/dd377588(v=vs.85).aspx. It essentially has the same effect as setting the media sample timestamps to NULL as I explained. However, I'm not sure if this approach would work: without a callback configured on the sample grabber and the graph running as fast as possible, how are you going to retrieve samples in the appropriate intervals? – Ralf Feb 18 '11 at 05:19
  • In sample callback, every sample has a timestamp that corresponds to media time. Check http://msdn.microsoft.com/en-us/library/dd376985(v=vs.85).aspx - ISampleGrabberCB methods, both of them have first parameter as SampleTime – Daniel Mošmondor Feb 18 '11 at 08:56