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, desiredFrameSize, desiredFrameRate, ref videoCapabilities );
if ( isSapshotSupported )
{
GetPinCapabilitiesAndConfigureSizeAndRate( captureGraph, sourceBase,
PinCategory.StillImage, desiredSnapshotSize, 0, 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 );
}
}