Directshow:如何更改视频的大小和帧率?

Posted

技术标签:

【中文标题】Directshow:如何更改视频的大小和帧率?【英文标题】:Directshow : How to change Size and frame rate of video? 【发布时间】:2020-11-06 05:02:36 【问题描述】:

(起初,对不起我的英语)

我有一个这样的 DirectShow 过滤器图:

这是我的代码:

   HRESULT BuildGraph(IGraphBuilder *pGraph, LPCOLESTR srcFile1)
  
   HRESULT hr = S_OK;

//graph builder
CComPtr<ICaptureGraphBuilder2> pBuilder;
hr = pBuilder.CoCreateInstance(CLSID_CaptureGraphBuilder2);
CHECK_HR(hr, L"Can't create Capture Graph Builder");
hr = pBuilder->SetFiltergraph(pGraph);
CHECK_HR(hr, L"Can't SetFiltergraph");

//add File Source (Async.)
CComPtr<IBaseFilter> pFileSourceAsync;
hr = pFileSourceAsync.CoCreateInstance(CLSID_GSN_FileSourceAsync);
CHECK_HR(hr, L"Can't create File Source (Async.)");
hr = pGraph->AddFilter(pFileSourceAsync, L"File Source (Async.)");
CHECK_HR(hr, L"Can't add File Source (Async.) to graph");

//set source filename
CComQIPtr<IFileSourceFilter, &IID_IFileSourceFilter> pFileSourceAsync_src(pFileSourceAsync);
if (!pFileSourceAsync_src)
    CHECK_HR(E_NOINTERFACE, L"Can't get IFileSourceFilter");
hr = pFileSourceAsync_src->Load(srcFile1, NULL);
CHECK_HR(hr, L"Can't load file");

//add LAV Splitter
CComPtr<IBaseFilter> pLAVSplitter;
hr = pLAVSplitter.CoCreateInstance(CLSID_GSN_LAVSplitter);
CHECK_HR(hr, L"Can't create LAV Splitter");
hr = pGraph->AddFilter(pLAVSplitter, L"LAV Splitter");
CHECK_HR(hr, L"Can't add LAV Splitter to graph");

//add LAV Video Decoder
CComPtr<IBaseFilter> pLAVVideoDecoder;
hr = pLAVVideoDecoder.CoCreateInstance(CLSID_GSN_LAVVideoDecoder);
CHECK_HR(hr, L"Can't create LAV Video Decoder");
hr = pGraph->AddFilter(pLAVVideoDecoder, L"LAV Video Decoder");
CHECK_HR(hr, L"Can't add LAV Video Decoder to graph");

//add Infinite Pin Tee Filter
CComPtr<IBaseFilter> pInfinitePinTeeFilter;
hr = pInfinitePinTeeFilter.CoCreateInstance(CLSID_GSN_InfinitePinTeeFilter);
CHECK_HR(hr, L"Can't create Infinite Pin Tee Filter");
hr = pGraph->AddFilter(pInfinitePinTeeFilter, L"Infinite Pin Tee Filter");
CHECK_HR(hr, L"Can't add Infinite Pin Tee Filter to graph");

//add AVI Decompressor
CComPtr<IBaseFilter> pAVIDecompressor;
hr = pAVIDecompressor.CoCreateInstance(CLSID_GSN_AVIDecompressor);
CHECK_HR(hr, L"Can't create AVI Decompressor");
hr = pGraph->AddFilter(pAVIDecompressor, L"AVI Decompressor");
CHECK_HR(hr, L"Can't add AVI Decompressor to graph");

//add Color Space Converter
CComPtr<IBaseFilter> pColorSpaceConverter;
hr = pColorSpaceConverter.CoCreateInstance(CLSID_GSN_ColorSpaceConverter);
CHECK_HR(hr, L"Can't create Color Space Converter");
hr = pGraph->AddFilter(pColorSpaceConverter, L"Color Space Converter");
CHECK_HR(hr, L"Can't add Color Space Converter to graph");

//add Decklink Video Render
CComPtr<IBaseFilter> pDecklinkVideoRender;
hr = pDecklinkVideoRender.CoCreateInstance(CLSID_GSN_DecklinkVideoRender);
CHECK_HR(hr, L"Can't create Decklink Video Render");
hr = pGraph->AddFilter(pDecklinkVideoRender, L"Decklink Video Render");
CHECK_HR(hr, L"Can't add Decklink Video Render to graph");

//add Enhanced Video Renderer
CComPtr<IBaseFilter> pEnhancedVideoRenderer;
hr = pEnhancedVideoRenderer.CoCreateInstance(CLSID_GSN_EnhancedVideoRenderer);
CHECK_HR(hr, L"Can't create Enhanced Video Renderer");
hr = pGraph->AddFilter(pEnhancedVideoRenderer, L"Enhanced Video Renderer");
CHECK_HR(hr, L"Can't add Enhanced Video Renderer to graph");

//connect File Source (Async.) and LAV Splitter
hr = pGraph->ConnectDirect(GetPin(pFileSourceAsync, L"Output"), GetPin(pLAVSplitter, L"Input"), NULL);
CHECK_HR(hr, L"Can't connect File Source (Async.) and LAV Splitter");

//connect LAV Splitter and LAV Video Decoder
hr = pGraph->ConnectDirect(GetPin(pLAVSplitter, L"Video"), GetPin(pLAVVideoDecoder, L"Input"), NULL);
CHECK_HR(hr, L"Can't connect LAV Splitter and LAV Video Decoder");

//connect LAV Video Decoder and Infinite Pin Tee Filter
hr = pGraph->ConnectDirect(GetPin(pLAVVideoDecoder, L"Output"), GetPin(pInfinitePinTeeFilter, L"Input"), NULL);
CHECK_HR(hr, L"Can't connect LAV Video Decoder and Infinite Pin Tee Filter");

//connect Infinite Pin Tee Filter and AVI Decompressor
hr = pGraph->ConnectDirect(GetPin(pInfinitePinTeeFilter, L"Output2"), GetPin(pAVIDecompressor, L"XForm In"), NULL);
CHECK_HR(hr, L"Can't connect Infinite Pin Tee Filter and AVI Decompressor");

//connect Infinite Pin Tee Filter and Decklink Video Render
hr = pGraph->ConnectDirect(GetPin(pInfinitePinTeeFilter, L"Output4"), GetPin(pDecklinkVideoRender, L"In"), NULL);
CHECK_HR(hr, L"Can't connect Infinite Pin Tee Filter and Decklink Video Render");

//connect AVI Decompressor and Color Space Converter
hr = pGraph->ConnectDirect(GetPin(pAVIDecompressor, L"XForm Out"), GetPin(pColorSpaceConverter, L"Input"), NULL);
CHECK_HR(hr, L"Can't connect AVI Decompressor and Color Space Converter");

//connect Color Space Converter and Enhanced Video Renderer
hr = pGraph->ConnectDirect(GetPin(pColorSpaceConverter, L"XForm Out"), GetPin(pEnhancedVideoRenderer, L"EVR Input0"), NULL);
CHECK_HR(hr, L"Can't connect Color Space Converter and Enhanced Video Renderer");

return S_OK;

效果很好,但是如果源是 1080p50,我想在 EVR 中将其显示为 PAL (720x576 25fps),在 Deklink 渲染器中显示为 1080i50。

我的问题:如何更改源的大小和帧速率? (我可以使用什么过滤器和接口...)

注意:我在谷歌上搜索并发现了很多关于在使用IAMStreamConfig 接口捕获时更改视频帧速率/大小的帖子,但我的源是文件,并且文件源过滤器没有IAMStreamConfig 接口。

【问题讨论】:

如果您还没有找到解决方案,我工作的公司有 2 个 DirectShow 过滤器,它们完全符合您的描述:Frame Rate Controller 和 Video Resize filter。它们是 LEADTOOLS 多媒体 SDK 的一部分,您可以通过this page 进行免费评估。 【参考方案1】:

video resizer dsp 可用于缩小视频。但它是 DMO/MFT,而不是原生 DirectShow 过滤器。但是为什么要在 EVR 之前缩小它呢?使用IMFVideoPositionMapper::MapOutputCoordinateToInputStream,您可以直接缩小显示。

使用Frame Rate Converter DSP,您可以降低帧速率。这也是一个 DMO/MFT。

为什么要将视频隔行扫描发送到 Decklink?我不知道有任何过滤器/dmo/mft 可以做到这一点。

【讨论】:

感谢您的回答,我知道那些 DSP 过滤器,但正如您所说,我们不能将它们用于 EVR 和 Decklink 渲染器,使用 IMFVideoPositionMapper 我可以调整它的大小,但 FrameRate 怎么样? , ""但是你为什么要在 EVR 之前缩小它?"" 我想把 EVR 窗口放到第二个显示器上以实现特殊目的。 ""为什么要将视频隔行发送到 Decklink?"" 我希望能够以不同的分辨率和电视广播标准显示输出。

以上是关于Directshow:如何更改视频的大小和帧率?的主要内容,如果未能解决你的问题,请参考以下文章

Android使用camera2复制内置视频录制质量和帧率

使用 MediaCodec 和 MediaMuxer 录制视频,但码率和帧率不正确

FFmpeg基础:音视频中的那些核心参数

《FFmpeg Basics》中文版-03-比特率/帧率/文件大小

如何使用Filmage Screen降低视频文件大小?

Android FFmage 修改视频分辨率,帧率,区域裁剪