Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dxsnap not displaying the video properly after first time open

I am using DirectShowLib-2005 - DxSnap example to display and capture the image from Webcam.
Everything works fine with the example.
But when i try to merge it with my application (i tried to call that form from my main form) it is working for the first time. Once i close and open the capture window, it is not displaying the video properly.
But the capturing of the image works perfectly all the time.

 public partial class frmMain : Form
{
    public frmMain()
    {
        InitializeComponent();
    }


    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    private static void Main()
    {
        Application.Run(new frmMain());
    }

    private void button1_Click(object sender, EventArgs e)
    {
        frmdxSnap frmdxSnap = new frmdxSnap();
        frmdxSnap.ShowDialog(this);
    }
}

Video Display Error

Even after restarting the PC, its still the same.
I have not changed anything in the DxSnap form.

like image 313
Olivarsham Avatar asked Oct 18 '22 15:10

Olivarsham


1 Answers

While DxSnap is a good introductory sample, it cuts a couple of corners making artifacts like mentioned possible. The problem is the assumption this in the following line:

m_stride = m_videoWidth * (videoInfoHeader.BmiHeader.BitCount / 8);

Actual stride might be different and it's a well known effect of video hardware suggesting increased strides. When you copy image from Sample Grabber buffer, it would be more accurate to re-compute stride as BufferLen / m_videoHeight (see code snippet below; also note assertion there -- presumably you are ignoring it or running Release builds). It would be even better to simply check current media type and obtain stride from there.

You might be not having the problem with first instance of video pipeline since it might be using video overlay and different code path. You might have no issue at all with well-aligned frame sizes (widths) like 640, 1024 etc.

/// <summary> buffer callback, COULD BE FROM FOREIGN THREAD. </summary>
int ISampleGrabberCB.BufferCB( double SampleTime, IntPtr pBuffer, int BufferLen )
{
    // Note that we depend on only being called once per call to Click.  Otherwise
    // a second call can overwrite the previous image.
    Debug.Assert(BufferLen == Math.Abs(m_stride) * m_videoHeight, "Incorrect buffer length");

    if (m_WantOne)
    {
        m_WantOne = false;
        Debug.Assert(m_ipBuffer != IntPtr.Zero, "Unitialized buffer");

        // Save the buffer
        CopyMemory(m_ipBuffer, pBuffer, BufferLen);
        ////////////////////////////////////////////
        // HOTFIX: Let's have the stride re-computed for the case it was changed dynamically or otherwise
        m_stride = BufferLen / m_videoHeight;
        ////////////////////////////////////////////

        // Picture is ready.
        m_PictureReady.Set();
    }

    return 0;
}
like image 91
Roman R. Avatar answered Oct 30 '22 22:10

Roman R.