Sample Grabber misses samples

Hi All,

I'm struggling to work out why the sample grabber sometimes misses samples.

I have a filter graph which consists of a DV camera as source, dv splitter, dv decoder and a sample grabber on the video chain through to a video renderer, and the audio chain terminates in a null renderer.

I'm using the sample grabber's buffercb method, which includes a double SampleTime parameter. I write a simple callback which basically divides this double value by 0.040 (my video is 25Hz, 40ms/frame) to get a frame number. I'm then just storing this frame number in an array. I'm not doing anything else in the callback, so it's very lean and mean

After ~50 minutes of video, I dump the array contents out so i can analyse what frames i received a callback for. About 8% are missing, thus my callback is not getting called about 8% of the time.

IAMDroppedFrames does not show any dropped frames after my callback starts; my cpu utilization never exceeds 10%, and my system is a dual core athlon x2 4200+, with 2Gb RAM. I'm not touching anything on the PC while it runs.

Has anyone got any idea why i'm missing samples? what happens to them? how can i get to look at all of them?

Any help much appreciated.

Slip

[1268 byte] By [Slippyr4] at [2007-12-22]
# 1

Well, a couple of thoughts:

- It seems unlikely that sample grabber is "missing" the frames. All the frames that go through the graph will go thru the sample grabber.

- Doing the division against the frame time may not give perfect results. Capture devices aren't always religious about their timestamps.

- Have you tried just using the camera's utils to copy the video, then use another tool to count frames and compare that to the count of times your cb is called?

LGS at 2007-8-30 > top of Msdn Tech,Software Development for Windows Vista,DirectShow Development...
# 2
> It seems unlikely that sample grabber is "missing" the frames.

That is what I thought. In my understanding, the only time frames would be missed would be if the renderer sends a quality control message back up the graph and the source filter drops some. And, in that instance, IAMDroppedFrames would show the missed frames.

If frame time is not an accurate way of establishing frame number from within the BufferCB callback, then how can I? obviously I can increment a static variable but this wouldn't get implemented if I did miss a callback! Would IAMDroppedFrames::GetNumDropped() + GetNumNotDropped() be an accurate reference?

My app needs to know the frame number in the callback; it's actual goal is to grab selected frames based on an array of frame numbers. So, even if i'm not generally missing any callbacks, i would still need to somehow recover my frame count in the event that frames were dropped via quality control. Otherwise my entire run is junk because i'd have drift in the frames I meant to capture.

Incidentally, is writing my own simple Trans-in-place filter to grab the frames I need likely to be more efficient than the sample grabber?

thanks

slip

Slippyr4 at 2007-8-30 > top of Msdn Tech,Software Development for Windows Vista,DirectShow Development...
# 3

Ok, I've reimplemented my callback a little differently and I am still missing frames.

My source is a DV VCR. The tape i'm playing has video footage, and i correspondingly have an array of frame numbers that i need to capture, starting from a particular point on the tape. The frame numbers go along the lines of 0,145,342,711, etc. There are a total of about 12,000 frames to capture, which span over about 56 minutes of tape.

Further to the above posts, I decided to reimplement the code, using SampleCB instead of BufferCB. I reason that I can increment a (static volatile) frame counter member variable, and compare the value of this with the frame number i'm looking to capture to decide whether to capture it or not.

Additionally, checking events for quality change events, and checking every sample's IsDiscontinuity property, should highlight if something has gone wrong.

Here is my callback, in kind of made up code (it's actually some hacked c# (although I am experiencing these problems both in c# and also c++).


HRESULT ISampleGrabberCB.SampleCB(double SampleTime, IMediaSample pSample)
{

// if this is the first callback, see how many dropped frames we've had so far
// DV drops frames a lot when you first play the tape, or rewind or whatever. so often
// the dropped frame count is not zero the first time the callback runs
if (m_callbackCount == 0)
{
IAMDroppedFrames.GetNumDropped(out nDroppedAtStart);
IAMDroppedFrames.GetNumNotDropped(out nNotDroppedAtStart);
}


// log stuff if this sample is a discontinuity
if (pSample.IsDiscontinuity() == S_OK)
{
int dropped, notdropped;
IAMDroppedFrames.GetNumDropped(out dropped);
IAMDroppedFrames.GetNumNotDropped(out notdropped);
LogWriter.Instance.WriteLine("DISCONTINUITY: " + (dropped - nDroppedAtStart) + " dropped, " + (notdropped - nNotDroppedAtStart) + " not dropped");
}


// check events
int hr; int p1, p2;
EventCode ec;

for (hr = IMediaEvent.GetEvent(out ec, out p1, out p2, 0); hr >= 0; hr = IMediaEvent.GetEvent(out ec, out p1, out p2, 0))
{
if (ec == EventCode.QualityChange)
{

int dropped, notdropped;
IAMDroppedFrames.GetNumDropped(out dropped);
IAMDroppedFrames.GetNumNotDropped(out notdropped);
LogWriter.Instance.WriteLine("QUALITY CHANGE: " + (dropped - nDroppedAtStart) + " dropped, " + (notdropped - nNotDroppedAtStart) + " not dropped");
}
}

// check if we want this frame
// m_framesToGrab is an int array containing frames numbers i want to capture, starting from 0
if (m_framesToGrab[m_index].Frame <= m_callbackCount)
{

m_index++;


// chopped code here copied the data from the buffer and added it to a FIFO queue being processed
// by another (low priority) thread
}


// incremement the callback count
m_callbackCount++;


return S_OK;

}

So when running this code, in my mind I should either get a look at every single frame, or my log should show that there were discontinuities and/or quality changes - representing missing calls of my SampleCB

However, when i run the code against my 56 minute tape, i get no evidence in the log of discontinuities or quality changes, yet I know the capture is incorrect because the capture completes about 20 seconds after it should do. (I can tell from the content of the video when the capture ought to have ended). So, there is a drift in 56 minutes of tape of about 20 seconds - around 0.66 % of frames are evidentally not calling my callback.

How can I get round this?

< tearing my hair out>

cheers

slip

Slippyr4 at 2007-8-30 > top of Msdn Tech,Software Development for Windows Vista,DirectShow Development...
# 4

I'm trying to understand this paragraph:

However, when i run the code against my 56 minute tape, i get no evidence in the log of discontinuities or quality changes, yet I know the capture is incorrect because the capture completes about 20 seconds after it should do. (I can tell from the content of the video when the capture ought to have ended). So, there is a drift in 56 minutes of tape of about 20 seconds - around 0.66 % of frames are evidentally not calling my callback.

Can you describe this 20 seconds again? You capture 56 minutes of video, call IMediaControl::Stop, and, what, it takes 20 seconds to stop the capture? The capture file shows a length of 56:20?

LGS at 2007-8-30 > top of Msdn Tech,Software Development for Windows Vista,DirectShow Development...
# 5
No, not quite.

First, remember i'm not capturing to a file. My graph runs from DV camera through the sample grabber, to a video renderer. My output is jpeg encoded frames that correspond to frames in the list of frames i want.

I regard capture to start at frame 0, and it's "finished" when i've grabbed the last of the frames in my list of frames.

The list of frames contains about 12,000 entries, and the highest video frame number i need to capture is 84,733. The video is PAL, progressive scan, 25.0 fps, so in real time that corresponds to 56:29.08 . So, once I start capturing, my process should be complete after that period of time.

However, it's not. 56:29 after i start capturing, my SampleCB implementation doesn't think it's had 84,733 frames. It takes about another 20 seconds before the counter in SampleCB increments high up to 84,733.

Does that make any sense?

slip

Slippyr4 at 2007-8-30 > top of Msdn Tech,Software Development for Windows Vista,DirectShow Development...
# 6

Perhaps the camera isn't religously spitting out 25 frames every second. What if it is only doing 24.9 or something? It might also be interesting to compare the sample times with the clock times to see if there is an increasing variance.

LGS at 2007-8-30 > top of Msdn Tech,Software Development for Windows Vista,DirectShow Development...

Software Development for Windows Vista

Site Classified