Search code examples
c++directshowvideo-capture

VMR9 imposing wrong video size on captured file


I have the following code, which I'm trying to use to capture from a webcam and at the same time previewing the video (pRenderer points to a windowed VMR9 filter, and mPMux to a mux returned by ICaptureGraphBuilder2::SetOutputFileName):

hr = mPBuild->RenderStream(
    &PIN_CATEGORY_PREVIEW,
    &MEDIATYPE_Video,
    mPCapVideo,
    NULL,
    pRenderer);

hr = mPBuild->RenderStream(
    &PIN_CATEGORY_CAPTURE,
    &MEDIATYPE_Video,
    mPCapVideo,
    NULL,
    mPMux);

Although preview looks fine, the captured video is only 352x288 in resolution, and is heavily distorted and although I can still recognize two instances of my face in it, it is flooded with bright green areas and it presents interlacing artifacts. Only Windows Media Player seems to fail at rendering this video, VLC and Quicktime shows a correctly rendered 352x288 video.

If I use the default renderer:

hr = mPBuild->RenderStream(
    &PIN_CATEGORY_PREVIEW,
    &MEDIATYPE_Video,
    mPCapVideo,
    NULL,
    NULL);

hr = mPBuild->RenderStream(
    &PIN_CATEGORY_CAPTURE,
    &MEDIATYPE_Video,
    mPCapVideo,
    NULL,
    mPMux);

The captured AVI has a size of 640x480, and all players are able to reproduce it properly, including Media Player.

It looks like VMR9 is imposing a video size on the entire graph, even for the captured file. This intuition is confirmed by the following code, placed right before the call to IMediaControl::Run:

IBasicVideo *pBasicVideo;
hr = mPGraph->QueryInterface(IID_PPV_ARGS(&pBasicVideo));
long w, h;
hr = pBasicVideo->GetVideoSize(&w, &h);

With the default renderer w and h are 640, 480 while with my VMR9 instance they are 352, 288.

** Edit **

The problem was that at some point, for some reason, the format of the output PIN of the camera switched from:

RGB24
352x288

To:

I420
352x288

And I guess Media Player has a problem with such format inside an AVI. An interesting fact is that the thumbnail of the video in Explorer was ok, and I could see the first frame with the right colors.


Solution

  • Well, when you connect two filters they must agree on a video format (including resolution). Different renderers may prefer different formats so you've got this behavior. You can query webcam's output pin for IAMStreamConfig interface to get a list of supported formats and select the one you need. Problems with playback of captured videos you had should have been caused by incorrect header: actual video format wasn't the one specified in the file header.