Aaron
Aaron

Reputation: 1323

DirectShow videoinfoheader manual set up

I'm trying to get a camera app to take pics of documents that are legible once blown up to full screen (I'm putting the png I create into a pdf file so we can transfer it to our database.

The tablet is a full version windows tablet with atom processor, not RT.

If I send in the camera's default size (448x252), everything works fine. When I try to set up manual size (the camera supports 1920x1080, 1280x720, 960x540, 640x480, 640x360), I get an unspecified error.

Something is going wrong with the videoinfoheader in the SetConfigParms function. If I use the function normally, I get an imagesize of -2147467259. I played around with it, and I'm pretty sure the image size should be height x width x 1.5 (that's what it is at 448x252 at least, and that also doesn't throw a buffer length error, regardless of resolution). So I added in: v.BmiHeader.ImageSize = iHeight * iWidth * 1.5 The app still works fine at 448x252, but if I try 1280x720 or 1920x1080, I get an unspecified error.

I'm starting to think it's the other videoinfoheader data that's not being changed that's messing it up. The srcRect, for example, stays at 0x448x0x252 even after the height and width are manually entered. The ImageSize does not automatically calculate (as described above), and other parameters are probably in question as well.

Does anyone have a link as to how to manually calculate all the fields for the videoinfo header? Or can someone try to help me figure this out? I've done everything I can, I've googled for hours.. I just can't get it.

Here's the SetConfigParms function if it'll help. Let me know if you want any of the other functions, or the full camera class. It's long so I'm not going to include it until someone asks for it.

Private Sub SetConfigParms(pStill As IPin, iWidth As Integer, iHeight As Integer, iBPP As Short)

    Dim hr As Integer
    Dim media As AMMediaType
    Dim v As VideoInfoHeader

    Dim videoStreamConfig As IAMStreamConfig = TryCast(pStill, IAMStreamConfig)
    ' Get the existing format block
    hr = videoStreamConfig.GetFormat(media)
    DsError.ThrowExceptionForHR(hr)
    Try
        ' copy out the videoinfoheader
        v = New VideoInfoHeader()
        Marshal.PtrToStructure(media.formatPtr, v)

        ' 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
        ' if overriding the bits per pixel
        If iBPP > 0 Then
            v.BmiHeader.BitCount = iBPP
        End If
        v.BmiHeader.ImageSize = iHeight * iWidth * 1.5
        ' Copy the media structure back           
        Marshal.StructureToPtr(v, media.formatPtr, True)
        ' Set the new format
        hr = videoStreamConfig.SetFormat(media)
        MsgBox(DsError.GetErrorText(hr))
        DsError.ThrowExceptionForHR(hr)
    Finally
        DsUtils.FreeAMMediaType(media)
        media = Nothing
    End Try
End Sub

Upvotes: 1

Views: 1713

Answers (1)

Roman Ryltsov
Roman Ryltsov

Reputation: 69734

You initialize just too few fields... Compare fields you set up and those defined in VIDEOINFOHEADER + BITMAPINFOHEADER - you don't do Planes, BitCount, Compression etc.

It does not work like this, you need a well defined format for starters, and then it may be accepted or rejected by the device.

It has to be something like this (C#):

        var vif = new VideoInfoHeader();
        vif.BmiHeader = new BitmapInfoHeader();

        // The HEADER macro returns the BITMAPINFO within the VIDEOINFOHEADER
        vif.BmiHeader.Size = Marshal.SizeOf(typeof (BitmapInfoHeader));
        vif.BmiHeader.Compression = 0;
        vif.BmiHeader.BitCount = bitCount;
        vif.BmiHeader.Width = width;
        vif.BmiHeader.Height = height;
        vif.BmiHeader.Planes = 1;

        int iSampleSize = vif.BmiHeader.Width*vif.BmiHeader.Height*(vif.BmiHeader.BitCount/8);
        vif.BmiHeader.ImageSize = iSampleSize;

Upvotes: 2

Related Questions