Reputation: 3782
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?
Upvotes: 2
Views: 701
Reputation: 113
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.
Upvotes: 0
Reputation: 2847
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
Upvotes: 3