Is there a way to detect that a DirectShow filtergraph has reached the end of its file? By end of its file, I mean that a filtergraph with a SampleGrabber filter will never receive another SampleCB call.
Here are some things that don't work:
- Trust
IMediaDet::get_StreamLength
(it's often says there are more frames in a video than really exist) - Trust
IMediaSeeking::GetDuration
(it's consistent with IMediaDet, +/- one frame) - Use
IMediaControl::GetState
(the filtergraph remains running even if all frames have already been processed from a file)
Background:
I am doing video processing and I have a class that creates a filtergraph with a SampleGrabber. Whenever SampleGrabber::SampleCB
is called, I block it with a mutex so I can run the filtergraph in pull mode. When I'm ready for another frame, I unblock the mutex in my main thread and wait for SampleGrabber::SampleCB
to send me a signal that it's done. For some videos, IMediaDet::get_StreamLength
tells me that the video has more frames than really exist. Once I've extracted the final frame and request one more than actually exists, the main thread then blocks forever because SampleGrabber::SampleCB
will never get called again. I'd like to be able to detect when SampleGrabber::SampleCB
will never be called for file sources. Applications like Windows Media Player are able to somehow do this because the GUI reports that the video has ended after the last real frame, so apparently there's a way to do this.
EDIT:
I'm using WaitForSingleObject
to implement the main thread blocking. The workaround that I've been using so far is to do what Greg suggested: have a finite timeout. Unfortunately, this gets a little tricky. The wait can fail for many reasons such as a true eof, slow network filesystem, lost network connection, slow decoder, etc.