C# DirectShow Retrieving Device Capabilties

A lot of people has been pondering on how to get the capabilties for video hardware. So far the code has work on 

  1. Blackmagic Design Cards such as Intensity Pro and SDI cards
  2. USB cameras

Less talk so the below code is an example of retrieving the entire capabilties using c# by using DirectShow Libraries.

Guid cat = PinCategory.Capture;
Guid med = MediaType.Video;
int hr;
unsafe
{
    try
    {
        Guid iid = typeof(IAMStreamConfig).GUID;
        object comobject;             

        hr = capGraph.FindInterface(ref cat, ref med, capFilter, iid, out comobject);
                    
        IAMStreamConfig videoConfig = comobject as IAMStreamConfig;
                    
                    
        int capsCount, capSize;
        hr = videoConfig.GetNumberOfCapabilities(out capsCount, out capSize);

        VideoInfoHeader vih = new VideoInfoHeader();
                    
        IntPtr pSC = Marshal.AllocHGlobal(capSize);
        AMMediaType mt = null;
                   

        for (int i = 0; i < capsCount; ++i)
        {
            // the video format is described in AMMediaType and VideoStreamConfigCaps
            hr = videoConfig.GetStreamCaps(i, out mt, pSC);
            Marshal.PtrToStructure(mt.formatPtr, vih);
                        
            string pixelformat = "";
                        
            if (vih.BmiHeader.BitCount == 16)
                pixelformat = "8 bit 4:2:2 YUV";
            else if (vih.BmiHeader.BitCount == 20)
                pixelformat = "10 bit 4:2:2 YUV";
            else if (vih.BmiHeader.BitCount == 30)
                pixelformat = "10 bit 4:4:4 RGB";

            string supported = "";

            if (mt.subType == k_viewer.DeviceListing.MediaSubType.YUYV)
            {
                supported = "YUYV";
            }
            else if (mt.subType == k_viewer.DeviceListing.MediaSubType.YUY2)
            {
                supported = "YUY2";
            }
            else if (mt.subType == k_viewer.DeviceListing.MediaSubType.V210)
            {
                supported = "V210";
            }
            else if (mt.subType == k_viewer.DeviceListing.MediaSubType.V210A)
            {
                supported = "V210A";
            }
            else if (mt.subType == k_viewer.DeviceListing.MediaSubType.r210)
            {
                supported = "210";
            }

            string readString = "";
          
            if (486 == vih.BmiHeader.Height)
            {
                if (417083 == vih.AvgTimePerFrame)
                {
                    readString = "NTSC - " + pixelformat +" (3:2 pulldown removal)";
                }
                else
                {
                    readString = "NTSC - " + pixelformat;
                }
            }
            else if (576 == vih.BmiHeader.Height)
            {
                readString = "PAL - " + pixelformat;
            }
            else
            {
                float frameRate = (float)10000000 / vih.AvgTimePerFrame;

                if (720 == vih.BmiHeader.Height)
                {
                    // 720p
                    if ((frameRate - (int)frameRate) > 0.01)
                    {
                        readString = "HD 720p " + frameRate + " - " + pixelformat;
                    }
                    else
                    {
                        readString = "HD 720p " + frameRate + " - " + pixelformat;
                    }
                }
                else if (1080 == vih.BmiHeader.Height)
                {
                    if ((frameRate < 25.00) || (frameRate >= 50.0))     // 1080p23, 1080p24, 1080p50, 1080p5994, 1080p60
                    {
                        // Progressive 1080
                        if ((frameRate - (int)frameRate) > 0.01)
                        {
                            readString = "HD 1080p " + frameRate + " - " + pixelformat;
                        }
                        else
                        {
                            readString = "HD 1080p " + frameRate + " - " + pixelformat;
                        }
                    }
                    else
                    {
                        // Interlaced 1080
                        if ((frameRate - (int)frameRate) > 0.01)
                        {
                            readString = "HD 1080i " + frameRate * 2.0f + " - " + pixelformat;
                        }
                        else
                        {
                            readString = "HD 1080i " + frameRate * 2.0f + " - " + pixelformat;
                        }
                    }
                }
                else if (1556 == vih.BmiHeader.Height)
                {
                    if ((frameRate - (int)frameRate) > 0.01)
                    {
                        readString = "2K 1556p " + frameRate + " - " + pixelformat;
                    }
                    else
                    {
                        readString = "2K 1556p " + frameRate + " - " + pixelformat;
                    }
                }
                else
                {
                    readString = vih.BmiHeader.Width + "x" + vih.BmiHeader.Height + " Frame : " + vih.AvgTimePerFrame + " " + pixelformat;
                }
            }


            Marshal.FreeCoTaskMem(mt.formatPtr);


            //Marshal.FreeHGlobal(pSC);
        }
    }
    catch (Exception ex) { }
}

After in which the capabilities has been retrieved, the below codes are how to set the format after the capabilties has been captured. 2 of the most common media type that will see are usually r210 and YUV2 if dealing with Blackmagic cards.

if (vihIndex > -1)
{
    Guid iid = typeof(IAMStreamConfig).GUID;
    object comobject;

                        

    hr = capGraph.FindInterface(ref cat, ref med, capFilter, iid, out comobject);

    IAMStreamConfig videoConfig = comobject as IAMStreamConfig;
   

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

    VideoInfoHeader vih = new VideoInfoHeader();

    IntPtr pSC = Marshal.AllocHGlobal(capSize);
    AMMediaType mt = null;

    hr = videoConfig.GetStreamCaps(vihIndex, out mt, pSC);
    if (hr < 0)
    {
        Marshal.ThrowExceptionForHR(hr);
    }

   ;
    Marshal.PtrToStructure(mt.formatPtr, vih);
                        
    hr = videoConfig.SetFormat(mt);
    if (hr < 0)
    {
        Marshal.ThrowExceptionForHR(hr);
    }

    try
    {
        ids = capFilter as DecklinkPublicLib.IDecklinkStatus;
        ids.RegisterVideoStatusChangeEvent((uint)mstatus);

    }
    catch { }

    Marshal.FreeCoTaskMem(mt.formatPtr);
    Marshal.FreeHGlobal(pSC);

                        
}

Now you are able to retrieved the hardware capabilties and set according to the designated EDID required.

Write a Reply or Comment

Your email address will not be published. Required fields are marked *