DirectShow过滤器,可以扩展视频的帧速率

时间:2012-04-20 13:50:59

标签: video filter directshow video-processing frame-rate

我目前正在制作同时录制两个视频的软件。第一个帧速率为25fps,第二个帧速率为10fps(或未来可能为15fps)。之后,这两个视频被放在一个带有画中画的视频中。问题是,画中画的DirectShow过滤器不支持具有不同帧速率的视频。现在我正在寻找一个DirectShow过滤器,可以产生“虚拟帧”,将第二个视频的帧速率扩展到25fps。有谁知道这样的DirectShow过滤器?

先谢谢大卫

3 个答案:

答案 0 :(得分:2)

答案 1 :(得分:0)

您需要实现自己的叠加过滤器并将其放在解码器和渲染器之间。此过滤器应该能够接受流 - >两个输入引脚。在第一个流的情况下,它将仅获取帧并将图像叠加应用于其,由第二个流生成。因此,每次您将在叠加流中存储一个图像。另一种解决方案是使用第三方覆盖过滤器。

实现此目的的第二种方法是在VMR9过滤器上使用自定义direct3d分配器演示器。这样,您将在3d环境中渲染期间混合图像。在这种情况下,第二个流实际上将实现为单独的图形,并且输出必须使用samplegrabber过滤器或自定义渲染器生成bmp图像。这种方式将产生更灵活的解决方案 - 您可以在需要时随时与您交换叠加视频。

答案 2 :(得分:0)

Appleton给出的答案是正确的。我正在扩展这个答案,提供一些示例代码(在C ++ / CLI中),显示如何实例化手动构建的DirectShow图的过滤器(从可用的稀疏文档中挑选碎片可能很耗时)。相关代码在REDUCE_FRAME_RATE有条件编译的代码内。 COM_CALL()是我自定义的HRESULT检查宏。

// Additional include files required for DMO support

#include <ParserUIDs.h>
#include <dmodshow.h>
#include <propsys.h>
    …

static void AddDecodedVideoSampleGrabber(
      AVStreamSourceBox^ sourceBox,
      IGraphBuilder* pGraph,
      CComPtr<IBaseFilter>& pDecodedVideoSampleGrabber,
      IPin* pSourcePin,
      CComPtr<IPin>& pDecodedVideoSampleGrabberOutPin
   ) {
      HRESULT hRes;

      COM_CALL(pDecodedVideoSampleGrabber.CoCreateInstance(CLSID_SampleGrabber));
      COM_CALL(pGraph->AddFilter(pDecodedVideoSampleGrabber, L"DecodedVideoSampleGrabber"));
      CComPtr<IPin> pDecodedVideoSampleGrabberInPin(FilterTools::GetPin(pDecodedVideoSampleGrabber, "Input"));
      COM_CALL(pGraph->ConnectDirect(pSourcePin, pDecodedVideoSampleGrabberInPin, NULL));
      pDecodedVideoSampleGrabberOutPin = FilterTools::GetPin(pDecodedVideoSampleGrabber, "Output");

      auto pFrameCallbackSink = (SampleGrabberCBSink*)sourceBox->SetupSampleGrabberCallback(
         FRAME_SAMPLE_GRABBER,
         IntPtr(pDecodedVideoSampleGrabber)
      ).ToPointer();
      sourceBox->SetDecodedVideoSampleGrabber(IntPtr(pFrameCallbackSink));

   #ifdef REDUCE_FRAME_RATE
      // insert frame-reduction filter before x264 encoding  
      CComPtr<IBaseFilter> pFrameReducer;
      COM_CALL(pFrameReducer.CoCreateInstance(CLSID_DMOWrapperFilter));
      COM_CALL(pGraph->AddFilter(pFrameReducer, L"FrameReducer"));

      CComPtr<IDMOWrapperFilter> pDmoWrapper;
      COM_CALL(pFrameReducer->QueryInterface(__uuidof(IDMOWrapperFilter), (void**)&pDmoWrapper));
      COM_CALL(pDmoWrapper->Init(__uuidof(CFrameRateConvertDmo), DMOCATEGORY_VIDEO_EFFECT));
      CComPtr<IPropertyStore> pPropStore;
      COM_CALL(pFrameReducer->QueryInterface(IID_PPV_ARGS(&pPropStore)));

      PROPVARIANT var;
      PropVariantInit(&var);
      var.vt = VT_UI8;
      var.uhVal.HighPart = OUTPUT_FPS;    // Desired frame rate
      var.uhVal.LowPart = 1;
      pPropStore->SetValue(MFPKEY_CONV_OUTPUTFRAMERATE, var);
      PropVariantClear(&var);
      CComPtr<IPin>&pDmoInPin(FilterTools::GetPin(pFrameReducer, "in0"));
      COM_CALL(pGraph->ConnectDirect(pDecodedVideoSampleGrabberOutPin, pDmoInPin, NULL));
      CComPtr<IPin>&pDmoOutPin(FilterTools::GetPin(pFrameReducer, "out0"));
      pDecodedVideoSampleGrabberOutPin = pDmoOutPin;
   #endif

   }