TestCap based virtual video driver problems with Windows 8.1 (part 2)

Sorry for creating similar topic, but I cannot continue discussion in the previous one (due to its age).
Here’s the link - http://www.osronline.com/showthread.cfm?link=252687

First of all, I’d like to say thanks to Tim Roberts for giving me a clue on Topoedit.
This tool is very helpful. However, it doesn’t show any failures in code with my camera. Instead, I see only a white screen (nothing is being rendered).

However, it seems to me that I found the reason of the problem.
In my driver, I do not set correct presentation times for the stream.
With DirectShow client application, I receive the SRB_INDICATE_MASTER_CLOCK event in HwReceiveControlPacket callback and therefore I am able to use this clock to set timestamps.

case SRB_INDICATE_MASTER_CLOCK:
PSTREAMEX pStrmEx = (PSTREAMEX)pSrb->StreamObject->HwStreamExtension;
pStrmEx->hMasterClock = pSrb->CommandData.MasterClockHandle;
break;

With MediaFoundation client application, I do not receive this event so I never set correct timestamps.
Here’s a piece of code:

if (pStrmEx->hMasterClock )
{
pDataPacket->PresentationTime.Time = pStrmEx->QST_StreamTime;
pDataPacket->OptionsFlags |= KSSTREAM_HEADER_OPTIONSF_TIMEVALID | KSSTREAM_HEADER_OPTIONSF_DURATIONVALID;
}
else
{
// no clock or the preview stream, so just mark the time as unknown and clear the timestamp valid flags
pDataPacket->PresentationTime.Time = 0;
pDataPacket->OptionsFlags &= ~(KSSTREAM_HEADER_OPTIONSF_TIMEVALID | KSSTREAM_HEADER_OPTIONSF_DURATIONVALID);
}

I’m not sure how to resolve this but I feel that this might be the reason of the problem.
Should I create my own Clock in such case? Or maybe there is some other event that MediaFoundation framework is signalling in order to set up master clock?

Your help is very appreciated.

Thanks,
Anton

xxxxx@gmail.com wrote:

However, it seems to me that I found the reason of the problem.
In my driver, I do not set correct presentation times for the stream.
With DirectShow client application, I receive the SRB_INDICATE_MASTER_CLOCK event in HwReceiveControlPacket callback and therefore I am able to use this clock to set timestamps.

With MediaFoundation client application, I do not receive this event so I never set correct timestamps.
Here’s a piece of code:

if (pStrmEx->hMasterClock )
{
pDataPacket->PresentationTime.Time = pStrmEx->QST_StreamTime;
pDataPacket->OptionsFlags |= KSSTREAM_HEADER_OPTIONSF_TIMEVALID | KSSTREAM_HEADER_OPTIONSF_DURATIONVALID;
}
else
{
// no clock or the preview stream, so just mark the time as unknown and clear the timestamp valid flags
pDataPacket->PresentationTime.Time = 0;
pDataPacket->OptionsFlags &= ~(KSSTREAM_HEADER_OPTIONSF_TIMEVALID | KSSTREAM_HEADER_OPTIONSF_DURATIONVALID);
}

I’m dubious that this is the cause of your problem. A capture source is
not required to supply timestamps. Many inexpensive web cams do not
supply timestamps.

By the way, you can set pDataPacket->Duration and DURATIONVALID without
having the current stream time. You know your frame rate, don’t you?

It’s not impossible that Media Foundation requires them where DirectShow
did not, I suppose. It has already been made clear to me that MF makes
a number of assumptions that DShow did not, but I’ve never found such a
list enumerated. It would be trivial for you to create your own clock
as an experiment, by using KeQueryPerformanceCounter and converting it
to 100ns units, but the general rule is that if the graph does not have
a clock, you should set the timestamp to 0.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

I have tried various combinations of TIMEVALID and DURATION valid flags (I’ve also generated my own timestamps) - nothing works.

Today I’ve tried not to think about timestamps and have figured out many interesting things.
First of all, I have noticed that client application sends only two SRB_READ_DATA requests at startup and then … nothing. Normally, it should always call the SRB_READ_DATA so I could call my VideoQueueAddSRB and then call VideoQueueRemoveSRB to process data.

I have commented out only one line of code that make client app behave normally (continuously send SRB requests).
pSrb->CommandData.DataBufferArray->DataUsed = biSizeImage;
biSizeImage normally equals 230400bytes (e.g. for 320x240, RGB24).
As only I set the DataUsed variable to “zero” - MediaFoundation app starts to send SRB requests.

However, no image is displayed in client application. Well, of course it is not displayed because I had set the DataUsed to 0 : ) So it’s not a solution - just a observation.

Finally, I started to debug one more MediaFoundation app (MFCaptureD3D from http://archive.msdn.microsoft.com/mediafoundation). There, I was able to find out interesting things in IMFSourceReaderCallback::OnReadSample callback function.
INDEED, it is called only twice for my device. The dwStreamFlags in this callback are set to MF_SOURCE_READERF_STREAMTICK (that means there is a gap in the stream…). Btw, for these two calls - I see that there are timestamps. Probably, MF sets them on its own… I provide only zeros with DURATIONVALID flag.

All these thread is not only about my virtual camera implementation.
I see the same issue with my Creative Cam Socialize HD 1080. And there are lots of users reports saying “my camera doesnt work inb skype for metro” etc.
My second camera (Logitech C270) works just fine.

Any ideas what the hell is going on with mediafoundation?

Sorry for such a chaotic post, but my brain is too hot right now %)

xxxxx@gmail.com wrote:

I have tried various combinations of TIMEVALID and DURATION valid flags (I’ve also generated my own timestamps) - nothing works.

Does your driver work with DirectShow apps?

There was a significant change between Windows 8.0 and 8.1 in the
handling of IOCTL_KS_READ_STREAM requests. The stream header in the
ioctl has always been, for video streams, a KSSTREAM_HEADER followed by
a KS_FRAME_INFO. The members of the KS_FRAME_INFO haven’t been
important, and most drivers ignored them.

Starting with Windows 8.1, that’s not true. There is now a
FrameCompletionNumber in the KS_FRAME_INFO that **MUST** be filled in.
If that field is left at 0, Media Foundation assumes that the frame was
cancelled, and nothing gets displayed. DirectShow doesn’t care.

(And, by the way, I cannot recall another time when Microsoft made such
a significant, incompatible, and virtually undocumented change in an API
as part of a minor version upgrade. This change breaks drivers that
worked perfectly well in Win 8.0.)

Now, I don’t know whether this applies to SRB_READ_DATA, or if it only
applies to AVStream. I’m not sure there is any place in the SRB
structure for the system to tell you that the KSSTREAM_HEADER is
actually larger than just a KSSTREAM_HEADER. Perhaps you could see if
the dword just past the end of your KSSTREAM_HEADER contains the size of
a KS_FRAME_INFO.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Tim,

I am such an idiot : )
Actually, I have seen the FrameCompletionNumber on MSDN. I have even recompiled my driver with Visual Studio 2013 / WDK 8.1 to set this member properly (currently I use VS2010/WDK8.0).

So, I recompiled the driver but … did nothing with FrameCompletionNumber! Most likely I was too exhausted from work so became inattentive.

Tomorrow is a new day (it’s already today) and I have added only one line of code:
pStrmEx->FrameInfo.FrameCompletionNumber = pStrmEx->FrameInfo.PictureNumber; // Picture number is simply increased on each iteration

And it worked out! Oh, such a relief!

I’ve seen lots of similar posts, so I’d like to popularize this topic.
Here’s my similar answer on SO - http://stackoverflow.com/questions/22067789/problems-capturing-with-media-foundation-windows-8-in-c/

Thanks for your help!
Cheers

xxxxx@gmail.com wrote:

I am such an idiot : )

Don’t be too hard on yourself. I’ve been doing Windows capture drivers
for 20 years, and I didn’t discover the FrameCompletionNumber thing
until a client reported that one of my usbvideo filters stopped working,
and even then I had to spend two full days reverse engineering in WinDbg
before I figured it out.

Personally, I think this was an extremely poor design decision on the
part of Microsoft. There’s no way that a good programmer would assign a
meaning to a previously “reserved” field during a minor upgrade, and
then introduce software that doesn’t work if that previously reserved
field is left unfilled. It’s not right.

And it worked out! Oh, such a relief!

I’m glad to hear it. I will mark in my knowledge base that this is
required for stream-class as well as AVStream.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.