Search code examples
c#directshow

Task for taking webcam snapshots without display


I want to take webcam snapshots on windows with DirectShow. These snapshots will be saved to disk without any display of these images. I want to start the snapshot process that takes a snapshot every second until I stop it, while the main process continues.

So I choose Yet Another Web Camera Control for DirectShow to use it with C#, and the demo works fine.
But I got problem when I use the wrapper in an own task, I get the typical threading error The calling thread cannot access this object because a different thread owns it.

The calling code looks like this:

Task.Run(() =>
{
    using (var cam1 = new SnapshotCam(camList.First(), "person", webCameraControl))
    {
        // Act
        Bitmap image = null;
        if (!cam1._wcc.IsCapturing)
        {
            cam1._wcc.StartCapture(cam1._cameraId);
            Task.Delay(500).Wait();
        }
        image = cam1._wcc.GetCurrentImage();
        // Assert
        Assert.NotNull(image);
    }
}).Wait();

The difficult object for me to handle is the webCameraControl stored in cam1._wcc: This object inherits from System.Windows.Controls.UserControl and could be attached to a UI. But in my case I do not have any UI, the snapshots have to be taken in a "headless" style.

So the trouble begins when I want to use the _wcc-object. I tried already to call the _wcc.Dispatcher for the corresponding thread but didn't succeed.

How can I call the code above in an own task/thread independent from the rest of the code?


Solution

  • The problem you are hitting immediately is threading related, but eventually it was an unlucky choice of library for webcam capture. You don't need camera frame displaying but the library is implementing taking the stills by rendering video stream to Direct3D device (sort of presentation even if it is "invisible") with copying of last known frame on request.

    Perhaps you should rather prefer DxSnap sample application from DirectShow.NET package. Even though not ideal either:

    • it extracts frame data using Sample Grabber without need of displaying filter
    • it shows how to pass data between threads accurately, see here
    • you avoid over-complications with multi-layered external control library

    See also: