views:

165

answers:

2
+2  Q: 

SetPosition

Task: grabbing arbitrary frames from mpeg2 video files. Now I use custom render filter for grabbing, but problem with positioning video on required frame.

I use SetPosition(), after Pause() for passing frames through graph, wait for filter receive first frame and Stop().

If I get frame by frame, first i receive exact for this time frame, after this frame repeat some times, and again exact frame.

Why SetPosition get wrong result?

+1  A: 

The decoder needs to start decoding at the previous i frame. Typically, the demux will start pushing data at least a second before that. When you start receiving frames, you should check the timestamp to see if they are the one you want. Your filter will receive a "NewSegment" call which gives the seek start position in the file. If you add this start time to the sample time on the frame, you will get the absolute position of the frame within the file and you can compare that to your requested location.

G

Geraint Davies
I add start time to sample time.Absolute position is grather on ~o.5 second of that I set by SetPosition.
Fanruten
sounds about right. that's the beginning of the GOP. Keep consuming until you get to the frame you want.
Geraint Davies
A: 

You need to pause the graph after you have rendered the graph. After that you can change the frame you want to show using SetPositions.

Something like this:

int ShowFrame(long lFrame)
{
    if (FAILED(m_pMC->Pause()))
       return -1;
    LONGLONG llUnknown = 0;
    LONGLONG  llTime = LONGLONG(m_lFrameTime) * lFrame + m_lFrameTime / 2;
    GUID TimeFormat;
    if (FAILED(m_pMS->GetTimeFormat(&TimeFormat))) return -1;
    if (TimeFormat == TIME_FORMAT_MEDIA_TIME)
    {
       llUnknown = llTime;
    }
    else
    {
       if (FAILED(m_pMS->ConvertTimeFormat(&llUnknown, &TimeFormat, llTime, &TIME_FORMAT_MEDIA_TIME))) return -1;
    }
    if (FAILED(m_pMS->SetPositions(&llUnknown, AM_SEEKING_AbsolutePositioning, 0, AM_SEEKING_NoPositioning))) return -1;
    return 0;
}

m_lFrameTime is the time per one frame, you can get in your custom renderer. When video renderer pin is connected you can get the VIDEOINFO::AvgTimePerFrame on that pin.

AndreiM