2011-01-19 6 views
1

私の仕事は次のとおりです。グラフを作成した後、IMediaSeekingインターフェイスを使用してグラフを作成し、SampleGrabberを添付し、キーフレームを取得します。DirectShowNetを使用してキーフレームを検索する

次は私がやっていることです:メインの方法で :SampleCB()コールバックメソッドで

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); 

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; 
    } 

したがって、私は物事を設定しています。今、私がプログラムを実行すると、すべてが正しくロードされます。しかし、コールバックは一度だけ呼び出され、レンダリングは停止します。レンダリングがなくなり、コールバックがなくなりました。 別のコールバックメソッドISampleGrabber :: BufferCB()を使って、同じ運命に従っているかどうかを確認しました。しかし、いいえ! BufferCB()は、フレームが取得され、ビデオが最後までレンダリングされるたびに呼び出されます。

私は間違っていますか?これに関する提案はありますか? ありがとうございました:)

答えて

2

ok ..私はついにこの問題を解決することができました。それが他の誰にも役立つ場合は、ここでそれを説明します。 コールバックメソッドでIMediaSampleオブジェクトを実際にリリースしていませんでした。これはCOMオブジェクトである必要があります。

Marshal.ReleaseComObject()をMy SampleCB()コールバックメソッドに追加するだけで、SampleGrabberがサンプルを取得するたびに呼び出されるようになりました。

public int SampleCB (double sampleTime, IMediaSample mediaSample) 
{ 
    Console.WriteLine ("SampleCB Callback"); 
    Console.WriteLine (mediaSample.IsSyncPoint () + " "); 

     /* other code */ 
    Marshal.ReleaseComObject (mediaSample); 
    return 0; 
} 

私はもう別の問題に直面しています。しかし、私はそれが完全にこの質問に関連していないため、別の投稿をしました。

関連する問題