Directshownetを使用してキーフレームを探しています
-
12-10-2019 - |
質問
私のタスクは、グラフを作成し、サンプルグラバーを添付し、グラフを構築した後にImediaseekingインターフェイスを使用してキーフレームをつかみます。
以下は私がやったことです:主な方法:
Type comType = Type.GetTypeFromCLSID ( new Guid ( "e436ebb3-524f-11ce-9f53-0020af0ba770" ) );
IGraphBuilder graphBuilder = (IGraphBuilder) Activator.CreateInstance ( comType );
comType = Type.GetTypeFromCLSID ( new Guid ( "C1F400A0-3F08-11d3-9F0B-006008039E37" ) );
ISampleGrabber sampleGrabber = (ISampleGrabber) Activator.CreateInstance ( comType );
graphBuilder.AddFilter ( (IBaseFilter) sampleGrabber, "samplegrabber" );
AMMediaType mediaType = new AMMediaType ( );
mediaType.majorType = MediaType.Video;
mediaType.subType = MediaSubType.RGB24;
mediaType.formatType = FormatType.VideoInfo;
sampleGrabber.SetMediaType ( mediaType );
int hr = graphBuilder.RenderFile ( @"D:\test.wmv", null );
IMediaEventEx mediaEvent = (IMediaEventEx) graphBuilder;
IMediaControl mediaControl = (IMediaControl) graphBuilder;
IVideoWindow videoWindow = (IVideoWindow) graphBuilder;
IBasicAudio basicAudio = (IBasicAudio) graphBuilder;
videoWindow.put_AutoShow ( OABool.False );
basicAudio.put_Volume ( -10000 );
sampleGrabber.SetOneShot ( false );
sampleGrabber.SetBufferSamples ( true );
//the same object has implemented the ISampleGrabberCB interface.
//0 sets the callback to the ISampleGrabberCB::SampleCB() method.
sampleGrabber.SetCallback (this, 0);
mediaControl.Run ( );
EventCode eventCode;
mediaEvent.WaitForCompletion ( -1, out eventCode );
Marshal.ReleaseComObject ( sampleGrabber );
Marshal.ReleaseComObject ( graphBuilder );
samplecb()コールバックメソッド:
public int SampleCB ( double sampleTime, IMediaSample mediaSample )
{
Console.WriteLine ( "SampleCB Callback" );
Console.WriteLine ( mediaSample.IsSyncPoint ( ) + " " + mediaSample.GetActualDataLength() );
//check if its a keyframe using mediaSample.IsSyncPoint()
//and convert the buffer into image and save it.
return 0;
}
したがって、私は物事を設定しました。今、私がプログラムを実行すると、すべてが正しくロードされます。ただし、コールバックは1回だけ呼び出され、レンダリングが停止します。これ以上のレンダリングもコールバックもありません。別のコールバックメソッドを試してみましたが、isamplegrabber :: buffercb()は、同じ運命に従うかどうかを確認しました。しかし、いや! BufferCB()は、フレームがつかまれ、ビデオが最後までレンダリングされるたびに呼び出されます。
私は何が間違っているのですか?これに関する提案はありますか?ありがとうございました :)
解決
OK ..私はついにその問題を解決することができました。他の人に役立つ場合に備えて、ここで説明します。実際にコールバックメソッドでImediaSampleオブジェクトをリリースしていませんでした。それは必須であり、それはcomオブジェクトです。
marshal.releasecomobject()をmy samplecb()コールバックメソッドに追加するだけで、サンプルがサンプルをつかむたびに呼び出されます。
public int SampleCB ( double sampleTime, IMediaSample mediaSample )
{
Console.WriteLine ( "SampleCB Callback" );
Console.WriteLine ( mediaSample.IsSyncPoint ( ) + " " );
/* other code */
Marshal.ReleaseComObject ( mediaSample );
return 0;
}
私は今別の問題に直面しています。しかし、この質問に完全に関係していないので、私はそのために別の投稿をしました。
所属していません StackOverflow