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