使用DirectShowNet寻找关键帧 [英] Seeking keyframes using DirectShowNet
问题描述
我的任务是:创建一个图形,将SampleGrabber附加到该图形上,并在构建图形后使用IMediaSeeking界面获取关键帧.
My task is : I create a graph, attach a SampleGrabber to it, and grab the keyframes using the IMediaSeeking interface after building the graph.
以下是我所做的: 在Main方法中:
The following is what I have done : In the Main method :
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()回调方法中:
In the SampleCB() callback method :
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().
Thus, I have set up the things. Now, when i run the program, everything loads correctly. But the callback is called only once, and then the rendering stops. No more rendering and no more callbacks. I had tried the another callback method ISampleGrabber::BufferCB() to see if it follows the same fate. But no! BufferCB() is called everytime a frame is grabbed and the video is rendered till the end.
我做错了什么?有什么建议吗? 谢谢:)
What am I doing wrong? Any suggestions on this? Thank you :)
推荐答案
好..我终于能够解决该问题.我会在这里描述它,以防它对其他人有帮助. 我实际上并没有在回调方法中释放IMediaSample对象.这是必须要做的,因为它是一个COM对象.
ok..I have finally been able to solve that problem. I would describe it here in case it helps anyone else. I was not actually releasing the IMediaSample object in the callback method. That is a must to do, it being a COM object.
只需将Marshal.ReleaseComObject()添加到我的SampleCB()回调方法中,现在每次SampleGrabber抓取一个样本时都会调用它.
On simply adding the Marshal.ReleaseComObject() to my SampleCB() callback method, it is now called everytime the SampleGrabber grabs a sample.
public int SampleCB ( double sampleTime, IMediaSample mediaSample )
{
Console.WriteLine ( "SampleCB Callback" );
Console.WriteLine ( mediaSample.IsSyncPoint ( ) + " " );
/* other code */
Marshal.ReleaseComObject ( mediaSample );
return 0;
}
我现在面临另一个问题.但是,我为此发表了另一篇文章,因为它并不完全与此问题相关.
I am facing another issue now. However, I have made another post for that as it doesnt totally relate to this question.
这篇关于使用DirectShowNet寻找关键帧的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!