Adding Simeltaneous Video Recording + Playback to WPFMediaKit's VideoCaptureElement

When it comes to awesome WPF + DirectX video hacks it's Jeremiah Morrill's world, we're just living in it. One of his great contributions to the WPF ecosystem is the WPF Media Kit which adds DVD playback, webcam playback and a number of other capabilities to WPF. One slight deficiency with the webcam control (VideoCaptureElement) is that it doesn't allow simeltaneous recording and display of webcam content....until now!

This code adds simeltaneous video playback and capture to the VideoCaptureElement. VideoCaptureElement gets a "OutputFileName" property which is used to specify where the webcam output will be saved. If this property isn't set then the control functions as before, just showing webcam playback. Most of the changes are in VideoCapturePlayer (VideoCaptureElement is really only a WPF-ized wrapper around VideoCapturePlayer). I've left a copy of the un-modified version of VideoCapturePlayer.cs in the same directory (called VideoCapturePlayer_old.cs) for those who want to look at the differences for themselves, but the main part is where we check to see if the fileName field has been set and if so set up the relevant properties. 

IBaseFilter mux = null;
IFileSinkFilter sink = null;
if (!string.IsNullOrEmpty(this.fileName))
{
    hr = graphBuilder.SetOutputFileName(MediaSubType.Asf, this.fileName, out mux, out sink);
    DsError.ThrowExceptionForHR(hr);

    hr = graphBuilder.RenderStream(PinCategory.Capture, MediaType.Video, m_captureDevice, null, mux);
    DsError.ThrowExceptionForHR(hr);

    // use the first audio device
    var audioDevices = DsDevice.GetDevicesOfCat(FilterCategory.AudioInputDevice);

    if (audioDevices.Length > 0)
    {
        var audioDevice = AddFilterByDevicePath(m_graph,
                                            FilterCategory.AudioInputDevice,
                                            audioDevices[0].DevicePath);

        hr = graphBuilder.RenderStream(PinCategory.Capture, MediaType.Audio, audioDevice, null, mux);
        DsError.ThrowExceptionForHR(hr);
    }
}

hr = graphBuilder.RenderStream(PinCategory.Preview,
                               MediaType.Video,
                               m_captureDevice,
                               null,
                               m_renderer);

The last call to RenderStream() uses a PinCategory of Preview which allows the display of video, the previous calls to RenderStream() were using the Capture pin category, which causes the media to be written to disk. I've updated the sample application that accompanies WPFMediaKit to default to the "webcam sample" screen, and to save the webcam output as a randomly named .wmv file to the "my documents" folder. 

This code is very much proof-of-concept, and I'm concerned about leaks in there, but it does work. One limitation is that the file name can't be set after the graph has been set up, but this seems to be a common limitation with properties on the capture device - to change them you have to re-create the graph.

In any case I hope you find this code useful, and I'll be offering it up to Jeremiah for consideration as a patch to WPFMediaKit.