This project is read-only.

Selecting the right webcam resolution

Sep 6, 2011 at 8:44 AM

I was wondering why the capturedevice class of the sample only works with 640x480 resolution of connected webcams. I found that overwriting the BMIHeader of the VideoStreamConfig structure of the media format you from GetFormat is not working. So I extended the SetConfigParms method  in following way: Instead of using GetFormat to retriev the media structure I enum all possible formats (VideoStreamConfig.GetNumberOfCapabilities and VideoStreamConfig.GetStreamCaps), select the media format I want to use and write this structure back.

Here is the method extended SetConfigParms (sorry I translated the whole class to 

    ' Set the Framerate, and video size
    Private Sub SetConfigParms(ByVal capGraph As ICaptureGraphBuilder2, ByVal capFilter As IBaseFilter, ByVal iFrameRate As Integer, ByVal iWidth As Integer, ByVal iHeight As Integer)
        Dim hr As Integer
        Dim o As Object
        Dim media As AMMediaType
        Dim FoundFormat As Boolean
        ' Find the stream config interface
        hr = capGraph.FindInterface(PinCategory.Capture, MediaType.Video, capFilter, GetType(IAMStreamConfig).GUID, o)
        Dim videoStreamConfig As IAMStreamConfig = CType(o, IAMStreamConfig)

        If (videoStreamConfig Is Nothing) Then
            Throw New Exception("Failed to get IAMStreamConfig")
        End If

        Dim iCount As Integer = 0, iSize As Integer = 0
        videoStreamConfig.GetNumberOfCapabilities(iCount, iSize)
        Dim pmtConfig As New AMMediaType
        For iFormat As Integer = 0 To iCount - 1
            Dim scc As New VideoStreamConfigCaps, pScc As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(scc))

            hr = videoStreamConfig.GetStreamCaps(iFormat, pmtConfig, pScc)
            Marshal.PtrToStructure(pScc, scc)

            '' copy out the videoinfoheader
            Dim header As VideoInfoHeader = New VideoInfoHeader
            Marshal.PtrToStructure(pmtConfig.formatPtr, header)

            ''Examine the format, and possibly use it. 
            If pmtConfig.subType = MediaSubType.RGB24 Then
                Debug.Print("iFormat: " & header.BmiHeader.Width & "x" & header.BmiHeader.Height)
                If header.BmiHeader.Width = iWidth And header.BmiHeader.Height = iHeight Then
                    If (iFrameRate > 0) Then
                        'header.AvgTimePerFrame = (10000000 / iFrameRate)
                    End If
                    hr = videoStreamConfig.SetFormat(pmtConfig)
                    FoundFormat = True
                End If
            End If

            ''Delete the media type when you are done.
            Marshal.DestroyStructure(pScc, GetType(VideoStreamConfigCaps))
            Marshal.DestroyStructure(pmtConfig.formatPtr, GetType(VideoInfoHeader))
            pmtConfig = Nothing
            header = Nothing
            scc = Nothing


        If Not FoundFormat Then
            ' Get the existing format block
            hr = videoStreamConfig.GetFormat(media)
            ' copy out the videoinfoheader
            Dim v As VideoInfoHeader = New VideoInfoHeader
            Marshal.PtrToStructure(media.formatPtr, v)
            ' if overriding the framerate, set the frame rate
            If (iFrameRate > 0) Then
                v.AvgTimePerFrame = (10000000 / iFrameRate)
            End If
            ' if overriding the width, set the width
            If (iWidth > 0) Then
                v.BmiHeader.Width = iWidth
            End If
            ' if overriding the Height, set the Height
            If (iHeight > 0) Then
                v.BmiHeader.Height = iHeight
            End If
            ' Copy the media structure back
            Marshal.StructureToPtr(v, media.formatPtr, False)
            ' Set the new format
            hr = videoStreamConfig.SetFormat(media)
            media = Nothing
        End If
    End Sub

Whith that enum it's also very easy to examin the possible resolutions of a webcam.