使用DirectShow检测从Camera Stream显示新帧的时间

时间:2012-10-31 17:37:39

标签: delphi directshow multimedia

我使用以下代码连接到设备并流式传输视频,除了我不知道如何检测实际帧何时更改外,其工作效果很好

VARS

fGraph: iGraphBuilder;
fBuilder: iCaptureGraphBuilder2;
fDevEnum: iCreateDevEnum;
fClassEnum: iEnumMoniker;
fMoniker: iMoniker;
fSrc: iBaseFilter;
fFetched: pLongInt;
fvideoWindow: iVideoWindow;
fmediaControl: iMediaControl;
fEvent: IMediaEvent;
fMediaEvent: IMediaEventEx;

代码:

fGraph := createComObject(CLSID_FilterGraph) as iGraphBuilder;
fBuilder := createComObject(CLSID_CaptureGraphBuilder2) as iCaptureGraphBuilder2;
fBuilder.SetFiltergraph(fGraph);
fDevEnum := createComObject(CLSID_SystemDeviceEnum) as iCreateDevEnum;
fDevEnum.createClassEnumerator(CLSID_VideoInputDeviceCategory , fClassEnum , 0);
fClassEnum.next(1 , fMoniker , fFetched);
fMoniker.bindToObject(nil , nil , IID_IBaseFilter , fSrc);
fGraph.addFilter(fSrc , 'Video Capture');
fGraph.queryInterface(IID_IMediaControl , fmediaControl);
fGraph.queryInterface(IID_IVideoWindow , fvideoWindow);
fGraph.queryInterface(IID_IMediaEvent , fEvent);
fEvent.queryInterface(IID_IMediaEventEx , fMediaEvent); // TForm(fOwner)
fMediaEvent.SetNotifyWindow(self.Handle , WM_MMNOTIFY , Integer(self));
fBuilder.renderStream(@PIN_CATEGORY_PREVIEW , @MEDIATYPE_VIDEO , fSrc , nil , nil);
fvideoWindow.put_windowStyle(WS_CHILD or WS_CLIPSIBLINGS);
fvideoWindow.setWindowPosition(0 , 0 , self.width , self.height);
fvideoWindow.put_owner(self.Handle);
fmediaControl.run;

正如您所看到的,我尝试使用IMediaEvent和IMediaEventEx,但只有在视频流启动或停止时才会触发,我需要知道每次添加新帧时。

1 个答案:

答案 0 :(得分:0)

视频渲染器不报告帧呈现,例如使用回调。当帧到达视频渲染器时,它根据可能附加的时间戳排队等待显示。然后视频渲染器决定是否丢弃,呈现或排队数据。

如果您完全需要了解演示时间,您可能想要做的是

  • 在渲染器之前连接了Sample Grabber过滤器
  • 确保数据已解压缩
  • 通过移除SampleCB抓取器回调
  • 中的相应标志来剥离帧的时间

只要视频渲染器收到该帧,就会很快显示该帧。尽管如此,你仍然可以控制它。如果您需要之后,则需要一个自定义过滤器,它实际上将媒体样本传递给渲染器,并且在将控制权返回到过滤器时,您知道该帧刚刚呈现给用户。