0

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

在此先感谢,大卫

4

3 回答 3

1

试试帧率转换器

http://msdn.microsoft.com/en-us/library/windows/desktop/ff819100(v=vs.85).aspx

于 2012-04-20T23:08:08.863 回答
1

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

   }
于 2019-05-26T01:11:56.987 回答
0

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

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

于 2012-04-20T14:01:25.837 回答