0

I'd like to be able to seek to an arbitrary frame in a MPEG-2 file (from DVD, I guess it's called MPEG-2 Program Stream). So far I had been using OpenCV 2.1 for accessing those frames but that would only work on a frame after frame basis (only forward seeking). Later when I installed OpenCV 2.3.1 that possibility was lost though, i.e. limited to AVI. Anyways, I'd like to do that without OpenCV. I've managed to seek to keyframes (I suppose) or every so and so frame (e.g. every 12th frame). Now, looking at VirtualDub frame accurate seeking is possible. It says: ''parsing interleaved MPEG-2 file''. What exactly does that mean and where would I have to start to do the same? Is it even legal, I remember reading something about that somewhere, can't really remember though. I'm programming in C++ using directshow. As far as I know directshow won't do it. Then I was looking into CBaseFilter, streamtime method etc but before I dive into that complex topic I'd like to know if that's the right way to go. Looking forward to your answers, thanks!

@ Geraint: code snippet of filter graph:

CoCreateInstance(CLSID_FilterGraph,NULL,CLSCTX_INPROC,IID_IGraphBuilder,(LPVOID *)&pGraphBuilder);
 CoCreateInstance(CLSID_MPEG2Demultiplexer,NULL,CLSCTX_INPROC,IID_IBaseFilter,(LPVOID *)&pib);
 CoCreateInstance(CLSID_CMPEG2VidDecoderDS,NULL,CLSCTX_INPROC,IID_IBaseFilter,(LPVOID *)&pib2);

 pGraphBuilder->AddFilter(pib,L"Sample Splitter");
 pGraphBuilder->AddFilter(pib2,L"Sample Decoder");

 ZeroMemory(&am_media_type, sizeof(am_media_type));
am_media_type.majortype = MEDIATYPE_Video;
am_media_type.subtype = MEDIASUBTYPE_MPEG2_VIDEO;
am_media_type.formattype = FORMAT_MPEG2Video;

pGraphBuilder->QueryInterface(IID_IMediaControl,(LPVOID *)&pMediaControl);
pGraphBuilder->QueryInterface(IID_IMediaSeeking, (void**)(&pMediaSeeking));
pGraphBuilder->QueryInterface(__uuidof(IVideoFrameStep), (PVOID *)&fst); 
pGraphBuilder->QueryInterface(IID_IMediaEvent, (void **)&imev);
pGraphBuilder->QueryInterface(IID_IBasicVideo,(LPVOID *)&ibv);

pGraphBuilder->RenderFile(FILENAME,0);

and then I use IMediaSeeking for seeking the vid. I've also tried frame stepping (hence the references above).

user1331044
  • 83
  • 1
  • 11
  • You say you want to seek to an arbitrary frame. But what do you want to do after seeking? Should that frame for example be displayed on your screen? Basically I like to know do you want to seek inside the compressed mpeg bitstream, or do you want to seek inside the decoded video frames? – wimh Feb 07 '13 at 18:42
  • well, I mentioned OpenCV (Computer ''Vision''), so you can imagine that I want to seek the decoded frames :-) – user1331044 Feb 07 '13 at 20:21

1 Answers1

3

DirectShow is capable of delivering frame-accurate seeking. However, without an index, this is based on a time offset from file start, not a frame count.

Use IMediaSeeking to set the start time. The demux will begin delivery of compressed frames some way before that. The decoder will start decoding at the previous key frame but will discard any frames that are before your chosen start point.

G

Geraint Davies
  • 2,847
  • 15
  • 9
  • Hi Geraint, I've implemented a seek bar which displays the chosen frame. For that purpose I've been using IMediaSeeking::SetPositions so far with TIME_FORMAT_MEDIA_TIME (default), I guess that's what you are suggesting, right? With AVI that's fine but when I seek through an MPEG-2 Video it will only bring me to the keyframes, even if I indicate another time (=frame). However I want to get to any arbitrary frame, not just the keyframes. Here's how I set the positions: pMediaSeeking->SetPositions(&llPlay, AM_SEEKING_AbsolutePositioning,NULL, AM_SEEKING_NoPositioning);} llPlay in media time. – user1331044 Feb 08 '13 at 22:16
  • What does your graph look like? If you seek to an arbitrary frame in a playback graph (demux => decoder => renderer), the decoder will decode from keyframe to chosen frame and output the chosen frame to the renderer, discarding the frames that it needs to decode to get there. – Geraint Davies Feb 10 '13 at 13:07
  • I think I'm lacking the demux and the decoder part (at least the decoder). I have edited the original post to show the code. How do I implement the demux and decoder then? – user1331044 Feb 10 '13 at 13:55
  • I've edited again and included a demuxer and decoder. But somehow it still won't show non-keyframes. Only keyframes. What am I doing wrong? – user1331044 Feb 10 '13 at 18:31
  • I'm not sure that I can tell you from the information here. I know it is against the Stack Overflow principles, but you could contact me directly and we'll update the answers here once resolved. – Geraint Davies Feb 11 '13 at 18:19