使用Directshownet寻求密钥帧
-
12-10-2019 - |
题
我的任务是:我创建图形,将samplegrabber附加到其上,并在构建图形后使用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;
}
因此,我已经建立了东西。现在,当我运行程序时,一切都正确加载。但是回调仅被调用一次,然后渲染停止。没有更多的渲染,也没有更多回调。我尝试了另一个回调方法IsampleGrabber :: buffercb()查看它是否遵循相同的命运。但不是!每当抓取框架并呈现视频到最后时,每次都称为buffercb()。
我究竟做错了什么?对此有任何建议吗?谢谢 :)
解决方案
好的..我终于能够解决这个问题。我会在这里描述它,以防它帮助其他人。我实际上并未在回调方法中释放IMediasample对象。那是必须做的,它是一个com对象。
只需将元帅.releasecomobject()添加到我的samplecb()回调方法时,现在每次samplegrabber都会捕获样品。
public int SampleCB ( double sampleTime, IMediaSample mediaSample )
{
Console.WriteLine ( "SampleCB Callback" );
Console.WriteLine ( mediaSample.IsSyncPoint ( ) + " " );
/* other code */
Marshal.ReleaseComObject ( mediaSample );
return 0;
}
我现在面临另一个问题。但是,我为此发表了另一篇文章,因为它与这个问题没有完全相关。
不隶属于 StackOverflow