/// <summary>
/// Worker thread.
/// </summary>
///
private void WorkerThread( )
{
ReasonToFinishPlaying reasonToStop = ReasonToFinishPlaying.StoppedByUser;
// grabber
Grabber grabber = new Grabber( this );
// objects
object graphObject = null;
object grabberObject = null;
// interfaces
IGraphBuilder graph = null;
IBaseFilter sourceBase = null;
IBaseFilter grabberBase = null;
ISampleGrabber sampleGrabber = null;
IMediaControl mediaControl = null;
IMediaEventEx mediaEvent = null;
try
{
// get type for filter graph
Type type = Type.GetTypeFromCLSID( Clsid.FilterGraph );
if ( type == null )
throw new ApplicationException( "Failed creating filter graph" );
// create filter graph
graphObject = Activator.CreateInstance( type );
graph = (IGraphBuilder) graphObject;
// create source device's object
graph.AddSourceFilter( fileName, "source", out sourceBase );
if ( sourceBase == null )
throw new ApplicationException( "Failed creating source filter" );
// get type for sample grabber
type = Type.GetTypeFromCLSID( Clsid.SampleGrabber );
if ( type == null )
throw new ApplicationException( "Failed creating sample grabber" );
// create sample grabber
grabberObject = Activator.CreateInstance( type );
sampleGrabber = (ISampleGrabber) grabberObject;
grabberBase = (IBaseFilter) grabberObject;
// add grabber filters to graph
graph.AddFilter( grabberBase, "grabber" );
// set media type
AMMediaType mediaType = new AMMediaType( );
mediaType.MajorType = MediaType.Video;
mediaType.SubType = MediaSubType.RGB24;
sampleGrabber.SetMediaType( mediaType );
// connect pins
int pinToTry = 0;
IPin inPin = Tools.GetInPin( grabberBase, 0 );
IPin outPin = null;
// find output pin acceptable by sample grabber
while ( true )
{
outPin = Tools.GetOutPin( sourceBase, pinToTry );
if ( outPin == null )
{
Marshal.ReleaseComObject( inPin );
throw new ApplicationException( "Did not find acceptable output video pin in the given source" );
}
if ( graph.Connect( outPin, inPin ) < 0 )
{
Marshal.ReleaseComObject( outPin );
outPin = null;
pinToTry++;
}
else
{
break;
}
}
Marshal.ReleaseComObject( outPin );
Marshal.ReleaseComObject( inPin );
// get media type
if ( sampleGrabber.GetConnectedMediaType( mediaType ) == 0 )
{
VideoInfoHeader vih = (VideoInfoHeader) Marshal.PtrToStructure( mediaType.FormatPtr, typeof( VideoInfoHeader ) );
grabber.Width = vih.BmiHeader.Width;
grabber.Height = vih.BmiHeader.Height;
mediaType.Dispose( );
}
// let's do rendering, if we don't need to prevent freezing
if ( !preventFreezing )
{
// render pin
graph.Render( Tools.GetOutPin( grabberBase, 0 ) );
// configure video window
IVideoWindow window = (IVideoWindow) graphObject;
window.put_AutoShow( false );
window = null;
}
// configure sample grabber
sampleGrabber.SetBufferSamples( false );
sampleGrabber.SetOneShot( false );
sampleGrabber.SetCallback( grabber, 1 );
// disable clock, if someone requested it
if ( !referenceClockEnabled )
{
IMediaFilter mediaFilter = (IMediaFilter) graphObject;
mediaFilter.SetSyncSource( null );
}
// get media control
mediaControl = (IMediaControl) graphObject;
// get media events' interface
mediaEvent = (IMediaEventEx) graphObject;
IntPtr p1, p2;
DsEvCode code;
// run
mediaControl.Run( );
do
{
if ( mediaEvent != null )
{
if ( mediaEvent.GetEvent( out code, out p1, out p2, 0 ) >= 0 )
{
mediaEvent.FreeEventParams( code, p1, p2 );
if ( code == DsEvCode.Complete )
{
reasonToStop = ReasonToFinishPlaying.EndOfStreamReached;
break;
}
}
}
}
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
graph = null;
grabberBase = null;
sampleGrabber = null;
mediaControl = null;
mediaEvent = null;
if ( graphObject != null )
{
Marshal.ReleaseComObject( graphObject );
graphObject = null;
}
if ( sourceBase != null )
{
Marshal.ReleaseComObject( sourceBase );
sourceBase = null;
}
if ( grabberObject != null )
{
Marshal.ReleaseComObject( grabberObject );
grabberObject = null;
}
}
if ( PlayingFinished != null )
{
PlayingFinished( this, reasonToStop );
}
}