Setting the video capture format in DirectShow.NET

by Svilen S. 12. July 2010 15:58

Here is one way to set the video capture format in the VideoRecorder sample (part of DVDBuilder.NET). The following piece of code sets the format of the capture device to colorspace I420, frame size 640x480 and frame rate of 25 fps. Apart from the new code for setting the video capture format the only change in the original sample (in RecorderForm.cs) is that the video filters are connected later, i.e. AFTER the video capture format is set using the code below:


// BEGIN: set video capture parameters

/* NOTE: at this point the video filters are in the graph but they are not connected:

[video capture device] [smart tee] [video sample grabber] [video null renderer]

After the video capture format is set the filters will be connected manually

*/

hr = ms.captureGraph.FindInterface(PinCategory.Capture, MediaType.Video,

                        ms.videoInput, streamConfigId, out videoConfigObj);

DsError.ThrowExceptionForHR(hr);

videoConfig = videoConfigObj as IAMStreamConfig;

if (null == videoConfig)

   throw new COMException("Cannot obtain IAMStreamConfig");

 

// enumerate the capabilities of the video capture device

// This code looks for a specific video format:

// colorspace I420, frame dimensions 640x480, frame rate of 25 fps

int capsCount, capSize;

hr = videoConfig.GetNumberOfCapabilities(out capsCount, out capSize);

DsError.ThrowExceptionForHR(hr);

 

VideoInfoHeader vih = new VideoInfoHeader();

VideoStreamConfigCaps vsc = new VideoStreamConfigCaps();

IntPtr pSC = Marshal.AllocHGlobal(capSize);

AMMediaType mt = null;

int videoFormatIndex = -1;

long frameInterval = 10000000 / 25; // 25 fps

 

for (int i = 0; i < capsCount; ++i)

{

   // the video format is described in AMMediaType and VideoStreamConfigCaps

   hr = videoConfig.GetStreamCaps(i, out mt, pSC);

   DsError.ThrowExceptionForHR(hr);

 

   // copy the unmanaged structures to managed in order to check the format

   Marshal.PtrToStructure(mt.formatPtr, vih);

   Marshal.PtrToStructure(pSC, vsc);

 

   // log the video format

   string capline = String.Format("width:{0} height:{1} fps (min-max): {2}-{3}",

                 vih.BmiHeader.Width, vih.BmiHeader.Height,

                 10000000 / vsc.MaxFrameInterval,

                 10000000 / vsc.MinFrameInterval);

    Debug.WriteLine(capline);

 

    // check colorspace

    if (mt.subType == DirectShowLib.MediaSubType.I420)

    {

       // the video format has a range of supported frame rates (min-max)

       // check the required frame rate and frame size

       if (vih.BmiHeader.Width == 640 &&

           vih.BmiHeader.Height == 480 &&

           vsc.MinFrameInterval <= frameInterval &&

           vsc.MaxFrameInterval >= frameInterval)

       {

          // remember the index of the video format that we'll use

          videoFormatIndex = i;

       }

    }

    DsUtils.FreeAMMediaType(mt);

 }

 

 // set the desired format to the video capture device

 if (videoFormatIndex != -1)

 {

    hr = videoConfig.GetStreamCaps(videoFormatIndex, out mt, pSC);

    DsError.ThrowExceptionForHR(hr);

    // explicitly set the framerate since the default may not what we want

    Marshal.PtrToStructure(mt.formatPtr, vih);

    vih.AvgTimePerFrame = frameInterval;

    Marshal.StructureToPtr(vih, mt.formatPtr, false);

    hr = videoConfig.SetFormat(mt);

    DsError.ThrowExceptionForHR(hr);

    DsUtils.FreeAMMediaType(mt);

 }

 

 Marshal.FreeHGlobal(pSC);

 // END: set video capture parameters

 

This is just a sample that shows how to set the capture format. However the device may not support the required format (I420, 640x480, 25 fps). In a real-world scenario the code should look for the closest (but not exact) match or probably provide a choice among several supported formats.

Tags: , , ,

DVDBuilder