1

次のコードを使用してデバイスに接続し、ビデオをストリーミングします。実際のフレームがいつ変更されたかを検出する方法がわからないことを除いて、うまく機能します

変数

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 を使用してみましたが、これはビデオ ストリームの開始または停止が発生したときにのみ発生するため、新しいフレームが追加されるたびに知る必要があります。

4

1 に答える 1

0

ビデオ レンダラーは、コールバックの使用などのフレーム プレゼンテーションを報告しません。フレームがビデオ レンダラーに到達すると、タイム スタンプが付加されている可能性があるため、プレゼンテーションのキューに入れられます。次に、ビデオ レンダラーは、データを破棄するか、表示するか、キューに入れるかを決定します。

どうしてもプレゼンテーション時間を知りたい場合は、

  • レンダラーの前に Sample Grabber フィルタを接続する
  • データが解凍されていることを確認してください
  • SampleCBグラバー コールバックでそれぞれのフラグを削除して、フレームの時間を削除します

フレームは、ビデオ レンダラーが受け取るとすぐに表示されます。ただし、それが発生する前に、まだ制御できます。の後に必要な場合は、メディア サンプルをレンダラーに実際に配信するカスタム フィルターが必要です。フィルターに制御を戻すと、フレームがユーザーに表示されたことがわかります。

于 2012-11-09T00:51:47.800 に答える