private void WorkerThread( bool runGraph ) { ReasonToFinishPlaying reasonToStop = ReasonToFinishPlaying.StoppedByUser; bool isSapshotSupported = false; // grabber Grabber videoGrabber = new Grabber( this, false ); Grabber snapshotGrabber = new Grabber( this, true ); // 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.RGB24; 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 vedio 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 ); isSapshotSupported = ( ( 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 ( isSapshotSupported ) { 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 ( ( isSapshotSupported ) && ( 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 ( ( isSapshotSupported ) && ( 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 ( ( isSapshotSupported ) && ( 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 ); } } } }
// 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; } }
// 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; }
// 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; } }