Video input of a capture board.

The class is used to describe video input of devices like video capture boards, which usually provide several inputs.

Example #1
0
        // Ok button clicked
        private void okButton_Click(object sender, EventArgs e)
        {
            videoDeviceMoniker = videoDevice.Source;

            // set video size
            if (videoCapabilitiesDictionary.Count != 0)
            {
                VideoCapabilities caps = videoCapabilitiesDictionary[(string)videoResolutionsCombo.SelectedItem];

                videoDevice.VideoResolution = caps;
                captureSize = caps.FrameSize;
            }

            if (configureSnapshots)
            {
                // set snapshots size
                if (snapshotCapabilitiesDictionary.Count != 0)
                {
                    VideoCapabilities caps = snapshotCapabilitiesDictionary[(string)snapshotResolutionsCombo.SelectedItem];

                    videoDevice.ProvideSnapshots   = true;
                    videoDevice.SnapshotResolution = caps;

                    snapshotSize = caps.FrameSize;
                }
            }

            if (availableVideoInputs.Length != 0)
            {
                videoInput = availableVideoInputs[videoInputsCombo.SelectedIndex];
                videoDevice.CrossbarVideoInput = videoInput;
            }
        }
        // Ok button clicked
        private void okButton_Click(object sender, EventArgs e)
        {
            videoDeviceMoniker = videoDevice.Source;

            // set video size
            if (videoCapabilitiesDictionary.Count != 0)
            {
                VideoCapabilities caps = videoCapabilitiesDictionary[(string)videoResolutionsCombo.SelectedItem];

                videoDevice.VideoResolution = caps;
                captureSize = caps.FrameSize;
            }

            if (configureSnapshots)
            {
                // set snapshots size
                if (snapshotCapabilitiesDictionary.Count != 0)
                {
                    VideoCapabilities caps = snapshotCapabilitiesDictionary[(string)snapshotResolutionsCombo.SelectedItem];

                    videoDevice.ProvideSnapshots = true;
                    videoDevice.SnapshotResolution = caps;

                    snapshotSize = caps.FrameSize;
                }
            }

            if (availableVideoInputs.Length != 0)
            {
                videoInput = availableVideoInputs[videoInputsCombo.SelectedIndex];
                videoDevice.CrossbarVideoInput = videoInput;
            }
        }
        private void WorkerThread(bool runGraph)
        {
            ReasonToFinishPlaying reasonToStop = ReasonToFinishPlaying.StoppedByUser;
            bool isSnapshotSupported = false;

            // grabber
            Grabber videoGrabber = new Grabber(this, false, this.pixelFormat);
            Grabber snapshotGrabber = new Grabber(this, true, this.pixelFormat);

            // objects
            object captureGraphObject = null;
            object graphObject = null;
            object videoGrabberObject = null;
            object snapshotGrabberObject = null;
            object crossbarObject = null;

            // interfaces
            ICaptureGraphBuilder2 captureGraph = null;
            IFilterGraph2 graph = null;
            IBaseFilter sourceBase = null;
            IBaseFilter videoGrabberBase = null;
            IBaseFilter snapshotGrabberBase = null;
            ISampleGrabber videoSampleGrabber = null;
            ISampleGrabber snapshotSampleGrabber = null;
            IMediaControl mediaControl = null;
            IAMVideoControl videoControl = null;
            IMediaEventEx mediaEvent = null;
            IPin pinStillImage = null;
            IAMCrossbar crossbar = null;

            try
            {
                // get type of capture graph builder
                Type type = Type.GetTypeFromCLSID(Clsid.CaptureGraphBuilder2);
                if (type == null)
                    throw new ApplicationException("Failed creating capture graph builder");

                // create capture graph builder
                captureGraphObject = Activator.CreateInstance(type);
                captureGraph = (ICaptureGraphBuilder2)captureGraphObject;

                // get type of filter graph
                type = Type.GetTypeFromCLSID(Clsid.FilterGraph);
                if (type == null)
                    throw new ApplicationException("Failed creating filter graph");

                // create filter graph
                graphObject = Activator.CreateInstance(type);
                graph = (IFilterGraph2)graphObject;

                // set filter graph to the capture graph builder
                captureGraph.SetFiltergraph((IGraphBuilder)graph);

                // create source device's object
                sourceObject = FilterInfo.CreateFilter(deviceMoniker);
                if (sourceObject == null)
                    throw new ApplicationException("Failed creating device object for moniker");

                // get base filter interface of source device
                sourceBase = (IBaseFilter)sourceObject;

                // get video control interface of the device
                try
                {
                    videoControl = (IAMVideoControl)sourceObject;
                }
                catch
                {
                    // some camera drivers may not support IAMVideoControl interface
                }

                // get type of sample grabber
                type = Type.GetTypeFromCLSID(Clsid.SampleGrabber);
                if (type == null)
                    throw new ApplicationException("Failed creating sample grabber");

                // create sample grabber used for video capture
                videoGrabberObject = Activator.CreateInstance(type);
                videoSampleGrabber = (ISampleGrabber)videoGrabberObject;
                videoGrabberBase = (IBaseFilter)videoGrabberObject;
                // create sample grabber used for snapshot capture
                snapshotGrabberObject = Activator.CreateInstance(type);
                snapshotSampleGrabber = (ISampleGrabber)snapshotGrabberObject;
                snapshotGrabberBase = (IBaseFilter)snapshotGrabberObject;

                // add source and grabber filters to graph
                graph.AddFilter(sourceBase, "source");
                graph.AddFilter(videoGrabberBase, "grabber_video");
                graph.AddFilter(snapshotGrabberBase, "grabber_snapshot");

                // set media type
                AMMediaType mediaType = new AMMediaType();
                mediaType.MajorType = MediaType.Video;
                mediaType.SubType = MediaSubType.ConvertFrom(pixelFormat);

                videoSampleGrabber.SetMediaType(mediaType);
                snapshotSampleGrabber.SetMediaType(mediaType);

                // get crossbar object to to allows configuring pins of capture card
                captureGraph.FindInterface(FindDirection.UpstreamOnly, Guid.Empty, sourceBase, typeof(IAMCrossbar).GUID, out crossbarObject);
                if (crossbarObject != null)
                {
                    crossbar = (IAMCrossbar)crossbarObject;
                }
                isCrossbarAvailable = (crossbar != null);
                crossbarVideoInputs = ColletCrossbarVideoInputs(crossbar);

                if (videoControl != null)
                {
                    // find Still Image output pin of the video device
                    captureGraph.FindPin(sourceObject, PinDirection.Output,
                        PinCategory.StillImage, MediaType.Video, false, 0, out pinStillImage);
                    // check if it support trigger mode
                    if (pinStillImage != null)
                    {
                        VideoControlFlags caps;
                        videoControl.GetCaps(pinStillImage, out caps);
                        isSnapshotSupported = ((caps & VideoControlFlags.ExternalTriggerEnable) != 0);
                    }
                }

                // configure video sample grabber
                videoSampleGrabber.SetBufferSamples(false);
                videoSampleGrabber.SetOneShot(false);
                videoSampleGrabber.SetCallback(videoGrabber, 1);

                // configure snapshot sample grabber
                snapshotSampleGrabber.SetBufferSamples(true);
                snapshotSampleGrabber.SetOneShot(false);
                snapshotSampleGrabber.SetCallback(snapshotGrabber, 1);

                // configure pins
                GetPinCapabilitiesAndConfigureSizeAndRate(captureGraph, sourceBase,
                    PinCategory.Capture, videoResolution, ref videoCapabilities);
                if (isSnapshotSupported)
                {
                    GetPinCapabilitiesAndConfigureSizeAndRate(captureGraph, sourceBase,
                        PinCategory.StillImage, snapshotResolution, ref snapshotCapabilities);
                }
                else
                {
                    snapshotCapabilities = new VideoCapabilities[0];
                }

                // put video/snapshot capabilities into cache
                lock (cacheVideoCapabilities)
                {
                    if ((videoCapabilities != null) && (!cacheVideoCapabilities.ContainsKey(deviceMoniker)))
                    {
                        cacheVideoCapabilities.Add(deviceMoniker, videoCapabilities);
                    }
                }
                lock (cacheSnapshotCapabilities)
                {
                    if ((snapshotCapabilities != null) && (!cacheSnapshotCapabilities.ContainsKey(deviceMoniker)))
                    {
                        cacheSnapshotCapabilities.Add(deviceMoniker, snapshotCapabilities);
                    }
                }

                if (runGraph)
                {
                    // render capture pin
                    captureGraph.RenderStream(PinCategory.Capture, MediaType.Video, sourceBase, null, videoGrabberBase);

                    if (videoSampleGrabber.GetConnectedMediaType(mediaType) == 0)
                    {
                        VideoInfoHeader vih = (VideoInfoHeader)Marshal.PtrToStructure(mediaType.FormatPtr, typeof(VideoInfoHeader));

                        videoGrabber.Width = vih.BmiHeader.Width;
                        videoGrabber.Height = vih.BmiHeader.Height;

                        mediaType.Dispose();
                    }

                    if ((isSnapshotSupported) && (provideSnapshots))
                    {
                        // render snapshot pin
                        captureGraph.RenderStream(PinCategory.StillImage, MediaType.Video, sourceBase, null, snapshotGrabberBase);

                        if (snapshotSampleGrabber.GetConnectedMediaType(mediaType) == 0)
                        {
                            VideoInfoHeader vih = (VideoInfoHeader)Marshal.PtrToStructure(mediaType.FormatPtr, typeof(VideoInfoHeader));

                            snapshotGrabber.Width = vih.BmiHeader.Width;
                            snapshotGrabber.Height = vih.BmiHeader.Height;

                            mediaType.Dispose();
                        }
                    }

                    // get media control
                    mediaControl = (IMediaControl)graphObject;

                    // get media events' interface
                    mediaEvent = (IMediaEventEx)graphObject;
                    IntPtr p1, p2;
                    DsEvCode code;

                    // run
                    mediaControl.Run();

                    if ((isSnapshotSupported) && (provideSnapshots))
                    {
                        startTime = DateTime.Now;
                        videoControl.SetMode(pinStillImage, VideoControlFlags.ExternalTriggerEnable);
                    }

                    do
                    {
                        if (mediaEvent != null)
                        {
                            if (mediaEvent.GetEvent(out code, out p1, out p2, 0) >= 0)
                            {
                                mediaEvent.FreeEventParams(code, p1, p2);

                                if (code == DsEvCode.DeviceLost)
                                {
                                    reasonToStop = ReasonToFinishPlaying.DeviceLost;
                                    break;
                                }
                            }
                        }

                        if (needToSetVideoInput)
                        {
                            needToSetVideoInput = false;
                            // set/check current input type of a video card (frame grabber)
                            if (isCrossbarAvailable.Value)
                            {
                                SetCurrentCrossbarInput(crossbar, crossbarVideoInput);
                                crossbarVideoInput = GetCurrentCrossbarInput(crossbar);
                            }
                        }

                        if (needToSimulateTrigger)
                        {
                            needToSimulateTrigger = false;

                            if ((isSnapshotSupported) && (provideSnapshots))
                            {
                                videoControl.SetMode(pinStillImage, VideoControlFlags.Trigger);
                            }
                        }

                        if (needToDisplayPropertyPage)
                        {
                            needToDisplayPropertyPage = false;
                            DisplayPropertyPage(parentWindowForPropertyPage, sourceObject);

                            if (crossbar != null)
                            {
                                crossbarVideoInput = GetCurrentCrossbarInput(crossbar);
                            }
                        }

                        if (needToDisplayCrossBarPropertyPage)
                        {
                            needToDisplayCrossBarPropertyPage = false;

                            if (crossbar != null)
                            {
                                DisplayPropertyPage(parentWindowForPropertyPage, crossbar);
                                crossbarVideoInput = GetCurrentCrossbarInput(crossbar);
                            }
                        }
                    }
                    while (!stopEvent.WaitOne(100, false));

                    mediaControl.Stop();
                }
            }
            catch (Exception exception)
            {
                // provide information to clients
                if (VideoSourceError != null)
                {
                    VideoSourceError(this, new VideoSourceErrorEventArgs(exception.Message));
                }
            }
            finally
            {
                // release all objects
                captureGraph = null;
                graph = null;
                sourceBase = null;
                mediaControl = null;
                videoControl = null;
                mediaEvent = null;
                pinStillImage = null;
                crossbar = null;

                videoGrabberBase = null;
                snapshotGrabberBase = null;
                videoSampleGrabber = null;
                snapshotSampleGrabber = null;

                if (graphObject != null)
                {
                    Marshal.ReleaseComObject(graphObject);
                    graphObject = null;
                }
                if (sourceObject != null)
                {
                    Marshal.ReleaseComObject(sourceObject);
                    sourceObject = null;
                }
                if (videoGrabberObject != null)
                {
                    Marshal.ReleaseComObject(videoGrabberObject);
                    videoGrabberObject = null;
                }
                if (snapshotGrabberObject != null)
                {
                    Marshal.ReleaseComObject(snapshotGrabberObject);
                    snapshotGrabberObject = null;
                }
                if (captureGraphObject != null)
                {
                    Marshal.ReleaseComObject(captureGraphObject);
                    captureGraphObject = null;
                }
                if (crossbarObject != null)
                {
                    Marshal.ReleaseComObject(crossbarObject);
                    crossbarObject = null;
                }
            }

            if (PlayingFinished != null)
            {
                PlayingFinished(this, reasonToStop);
            }
        }
        // Set type of input connected to video output of the crossbar
        private void SetCurrentCrossbarInput(IAMCrossbar crossbar, VideoInput videoInput)
        {
            if (videoInput.Type != PhysicalConnectorType.Default)
            {
                int inPinsCount, outPinsCount;

                // gen number of pins in the crossbar
                if (crossbar.get_PinCounts(out outPinsCount, out inPinsCount) == 0)
                {
                    int videoOutputPinIndex = -1;
                    int videoInputPinIndex = -1;
                    int pinIndexRelated;
                    PhysicalConnectorType type;

                    // find index of the video output pin
                    for (int i = 0; i < outPinsCount; i++)
                    {
                        if (crossbar.get_CrossbarPinInfo(false, i, out pinIndexRelated, out type) != 0)
                            continue;

                        if (type == PhysicalConnectorType.VideoDecoder)
                        {
                            videoOutputPinIndex = i;
                            break;
                        }
                    }

                    // find index of the required input pin
                    for (int i = 0; i < inPinsCount; i++)
                    {
                        if (crossbar.get_CrossbarPinInfo(true, i, out pinIndexRelated, out type) != 0)
                            continue;

                        if ((type == videoInput.Type) && (i == videoInput.Index))
                        {
                            videoInputPinIndex = i;
                            break;
                        }
                    }

                    // try connecting pins
                    if ((videoInputPinIndex != -1) && (videoOutputPinIndex != -1) &&
                         (crossbar.CanRoute(videoOutputPinIndex, videoInputPinIndex) == 0))
                    {
                        crossbar.Route(videoOutputPinIndex, videoInputPinIndex);
                    }
                }
            }
        }
        // Get type of input connected to video output of the crossbar
        private VideoInput GetCurrentCrossbarInput(IAMCrossbar crossbar)
        {
            VideoInput videoInput = VideoInput.Default;

            int inPinsCount, outPinsCount;

            // gen number of pins in the crossbar
            if (crossbar.get_PinCounts(out outPinsCount, out inPinsCount) == 0)
            {
                int videoOutputPinIndex = -1;
                int pinIndexRelated;
                PhysicalConnectorType type;

                // find index of the video output pin
                for (int i = 0; i < outPinsCount; i++)
                {
                    if (crossbar.get_CrossbarPinInfo(false, i, out pinIndexRelated, out type) != 0)
                        continue;

                    if (type == PhysicalConnectorType.VideoDecoder)
                    {
                        videoOutputPinIndex = i;
                        break;
                    }
                }

                if (videoOutputPinIndex != -1)
                {
                    int videoInputPinIndex;

                    // get index of the input pin connected to the output
                    if (crossbar.get_IsRoutedTo(videoOutputPinIndex, out videoInputPinIndex) == 0)
                    {
                        PhysicalConnectorType inputType;

                        crossbar.get_CrossbarPinInfo(true, videoInputPinIndex, out pinIndexRelated, out inputType);

                        videoInput = new VideoInput(videoInputPinIndex, inputType);
                    }
                }
            }

            return videoInput;
        }
        // Collect all video inputs of the specified crossbar
        private VideoInput[] ColletCrossbarVideoInputs(IAMCrossbar crossbar)
        {
            lock (cacheCrossbarVideoInputs)
            {
                if (cacheCrossbarVideoInputs.ContainsKey(deviceMoniker))
                {
                    return cacheCrossbarVideoInputs[deviceMoniker];
                }

                List<VideoInput> videoInputsList = new List<VideoInput>();

                if (crossbar != null)
                {
                    int inPinsCount, outPinsCount;

                    // gen number of pins in the crossbar
                    if (crossbar.get_PinCounts(out outPinsCount, out inPinsCount) == 0)
                    {
                        // collect all video inputs
                        for (int i = 0; i < inPinsCount; i++)
                        {
                            int pinIndexRelated;
                            PhysicalConnectorType type;

                            if (crossbar.get_CrossbarPinInfo(true, i, out pinIndexRelated, out type) != 0)
                                continue;

                            if (type < PhysicalConnectorType.AudioTuner)
                            {
                                videoInputsList.Add(new VideoInput(i, type));
                            }
                        }
                    }
                }

                VideoInput[] videoInputs = new VideoInput[videoInputsList.Count];
                videoInputsList.CopyTo(videoInputs);

                cacheCrossbarVideoInputs.Add(deviceMoniker, videoInputs);

                return videoInputs;
            }
        }