【问题标题】:DirectShow filter that scales up the framerate of a videoDirectShow 过滤器可提高视频的帧速率
【发布时间】:2012-04-20 13:50:59
【问题描述】:

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

提前致谢,大卫

【问题讨论】:

  • 没有库存过滤器,如果存在,您将需要创建它或使用第三方解决方案。

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


【解决方案1】:

【讨论】:

  • 我注意到这个答案被认为没有帮助。投票者能解释一下原因吗?我还没有尝试过帧速率转换器本身,但尝试了同一个 DSP 系列中的其他几个 Directshow 过滤器,它们工作正常。
  • 我还没试过,但听起来很有希望!非常感谢!
  • 这个答案是正确的,也许它被否决了,因为链接指向媒体基金会文档,并且问题被标记为 directshow,但过滤器本身是 DMO 过滤器,因此可以嵌入使用股票包装过滤器的 DirectShow 图。我正在添加一个答案以详细说明所需的步骤。
【解决方案2】:

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

   }

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

    • 我有一个覆盖过滤器,我需要一个过滤器来调整其中一个流的帧率。
    • 但是你的覆盖过滤器不支持不同速率的流,这就是我提到新覆盖过滤器实现的原因。
    • 对不起,没想到!但问题是我们的核心团队已经离开了公司,我对 DirectShow 的经验不是很丰富,所以我宁愿退回到第三方过滤器!还是谢谢!
    猜你喜欢
    • 1970-01-01
    • 2020-04-18
    • 1970-01-01
    • 1970-01-01
    • 2020-11-12
    • 1970-01-01
    • 2020-11-06
    • 2011-12-23
    • 1970-01-01
    相关资源
    最近更新 更多