DirectShow decoders dropping media time
In DirectShow, a media sample has two time-related properties: its time stamp and its media time. My application needs to seek to specific frames within a video and thus requires the media time. As it seems, however, most decoder filters do not pass on this information.
I have a DirectShow graph that looks like this:
[File Source (Async.)] -> [AVI Splitter] -> [<Video decoder>] -> [My filter]
I have tried the following video decoders:
- DMO Wrapper Filter with Mpeg4s Decoder DMO (that's the default for MPEG-4 on my machine)
- Xvid MPEG-4 Video Decoder
- MainConcept (Demo) MPEG-4 Video Decoder
- ffdshow Video Decoder (ffdshow tryouts)
Of these four, only the ffdshow decoder produces samples with media time. The other three only set the time stamp, but leave the media time empty. This seems strange as each sample they get from the AVI splitter has its media time set correctly.
Does anybody know why this happens? Is there a workaround for getting the media time that works reliably even when the application continually jumps through the video?
Edit (in response to kidjan):
Let's assume I want to read video frame #100. With a 25fps file, this frame is 4 seconds into the video. Using the filter graph's IMediaSeeking interface, I seek to that position. Internally, this seek request is forwarded to the splitter filter (the AVI splitter in the example). However, there are two potential problems:
- Depending on the video format, I cannot be sure that the splitter will be able to seek precisely to frame #100. It may arrive at frame #95 instead and I will have to read 5 frames before getting the correct frame.
- The splitter may be frame-accurate, but due to the asynchronous nature of DirectShow the next frame yielded by the decoder filter may be a rel开发者_开发百科ict from before the seeking. If the decoder filter uses threading, it may deliver that frame after the seek action.
In these cases, it would be helpful if the decoder filter set the samples' media time. This way, I would know for certain which frame I receive.
What my question boils down to is basically:
How can I grab a specific video frame (by number) within a DirectShow graph?Not all decoders follow all the rules of DirectShow, so losing media times is one of the things you'll have to bear with. If you're only working with AVI files, just rely on accuracy of the splitter when using IMediaSeeking and use Stop() and Pause() of IMediaControl appropriately to ensure any cached frames are dismissed and you've got the frame you need. With AVI file you can get true frame rate from its header and calculate correct seek times if using media times fails.
But for non-AVI files there may be no constant framerate and using media times for seeking doesn't make sense there.
I'm confused--you do not need media times to "...seek to specific frames within a video." Why not use the time stamp to do seeking? Also, seeking is typically handled by the source filter, and downstream filters really don't have to do much. I have a filter graph that looks like:
[Custom source filter implementing IMediaSeeking] -> [Decoder filter] -> [Renderer]
...and all of the seeking happens with time stamps and not media times. So I'm not sure why you want to use media times instead of time stamps.
Are you using IMediaSeeking?
精彩评论