如何让 Microsoft MPEG4 Source 打开比特率高于 4Gbps 的 MOV
Posted
技术标签:
【中文标题】如何让 Microsoft MPEG4 Source 打开比特率高于 4Gbps 的 MOV【英文标题】:How to get Microsoft MPEG4 Source to open MOV with bitrate higher than 4Gbps 【发布时间】:2020-09-03 23:21:36 【问题描述】:似乎当 MOV 的比特率太高且无法适应 32 位时,Microsoft MPEG 4 Source 将无法解析它。有谁知道这种行为的解决方法?
我很确定它与比特率有关,因为我已经生成了测试文件,并且通过仅调整帧速率我生成了两个文件 - 一个比特率超过 4.2Gbps(32 位)的文件无法打开,但是另一个比特率低于 4.2Gps 的打开文件。
我尝试使用 IMFSourceReader 打开文件:
IMFSourceReader* reader = nullptr;
hr = MFCreateSourceReaderFromURL(L"input.mov", nullptr, &reader);
SAFE_RELEASE(reader);
但这只是返回 E_FAIL。
我尝试通过 IMFSourceResolver 打开它:
IMFMediaSource* source = nullptr;
IMFSourceResolver* resolver = nullptr;
MFCreateSourceResolver(&resolver);
MF_OBJECT_TYPE objectType;
IUnknown* result = nullptr;
hr = resolver->CreateObjectFromURL(L"input.mov", MF_RESOLUTION_MEDIASOURCE | MF_RESOLUTION_CONTENT_DOES_NOT_HAVE_TO_MATCH_EXTENSION_OR_MIME_TYPE | MF_RESOLUTION_READ, nullptr, &objectType, &result);
这也失败了。
为了重现这一点,我上传了一个小的400KB ZIP,其中包含:
-
3000x3000 源图片
.bat ffmpeg 命令生成视频
一个 3000x3000 @ 59fps HapQ MOV 文件 - MPEG4 源可以解决这个问题,比特率低于 4.2Gbps
3000x3000 @ 60fps HapQ MOV 文件 - MPEG4 源无法解决此问题,比特率仅为 4.2Gbps
这里生成的视频供参考:
ffmpeg -y -loop 1 -i black3000.png -t 0.2 -r 59 -s 3000x3000 -c:v hap -format hap_q -compressor none output-good.mov
ffmpeg -y -loop 1 -i black3000.png -t 0.2 -r 60 -s 3000x3000 -c:v hap -format hap_q -compressor none output-bad.mov
pause
之前有没有其他人看到过这种行为并知道解决方法?
谢谢,
【问题讨论】:
如果您激活 MF 跟踪,您将看到 MF 尝试它拥有的所有字节流处理程序 (IMFByteStreamHandler) 以及所有(在我的 PC 上,即 MPEG4、ADTS、AC-3、MF AMRNB、ASF、 AVI、WTV、MF FLAC、MPEG2、MKV、MP3、NSC、SAMI、WAV、LPCM) 报告 MF_E_INVALID_FILE_FORMAT 错误。因此,没有字节流处理程序支持该流。要解决此问题,您可以尝试添加自己的 MFRegisterLocalByteStreamHandler。 是的,我一直在使用 MFTrace - 对于良好的流,它能够找到处理程序 - MPEG 4 源。对于坏流(比特率太高),它确实失败了。 实际上,MF_MT_AVG_BITRATE 是一个 UINT32 docs.microsoft.com/en-us/windows/win32/medfound/…,在好的情况下,您可以清楚地看到 MPEG4 添加了“MF_MT_AVG_BITRATE=4235297882”。所以我猜,MPEG4 处理程序计算这个并且可能溢出。 MF_MT_AVG_BITRATE 更像是一个输出的东西,不确定它在做什么。你可以尝试用你自己的包装它并使用 MFRegisterLocalByteStreamHandler 注册它。 哦,我明白你的意思了 - 好的,我会尝试并更新如果它有效。 (顺便说一句,您的幻数数据库很棒,我已经多次使用它来查找晦涩的 GUIDS)。 谢谢 :-) 对所有 MF 的指导特别有用!例如,CLSID_MPEG4ByteStreamPlugin,它是 MPEG4 字节流处理程序。 【参考方案1】:看起来就像@Simon Mourier 建议的那样,解决这个问题的唯一方法是实现自定义ByteStreamHandler 并将其注册到MFRegisterLocalByteStreamHandler,但您还必须创建自定义IMFMediaSource,因为我找不到任何方法简单地实例化 MPEG4 源,因为您似乎只能通过它的 ByteStreamHandler 来创建它。
作为参考,这是我用来手动创建 MPEG4 源而不使用 Source Resolver 的伪测试代码:
#include <initguid.h>
DEFINE_GUID(CLSID_MPEG4ByteStreamPlugin, 0x271c3902, 0x6095, 0x4c45, 0xa2, 0x2f, 0x20, 0x09, 0x18, 0x16, 0xee, 0x9e);
class CallbackTest : public IMFAsyncCallback
public:
CallbackTest(IMFByteStreamHandler* handler)
_handler = handler;
IMFByteStreamHandler* _handler;
virtual HRESULT QueryInterface(REFIID riid, void ** ppvObject) override
return HRESULT();
virtual ULONG AddRef(void) override
return 1;
virtual ULONG Release(void) override
return 1;
virtual HRESULT GetParameters(DWORD * pdwFlags, DWORD * pdwQueue) override
return E_NOTIMPL;
virtual HRESULT __stdcall Invoke(IMFAsyncResult * pAsyncResult) override
// At this point HR = E_FAIL for > 4.2Gbps MOV
HRESULT hr = pAsyncResult->GetStatus();
MF_OBJECT_TYPE objectType;
IUnknown* unknownObject = nullptr;
hr = _handler->EndCreateObject(pAsyncResult, &objectType, &unknownObject);
// NOTE: I also tried to just force creating the MPEG 4 Source by calling
// EndCreateObject with a dummy IMFAsyncResult but that always failed..
IMFMediaSource* mediaSource = nullptr;
hr = unknownObject->QueryInterface(&mediaSource);
return S_OK;
;
void Test()
HRESULT hr;
// Create a bytestream from the file
IMFByteStream* byteStream = nullptr;
hr = MFCreateFile(MF_ACCESSMODE_READ, MF_OPENMODE_FAIL_IF_NOT_EXIST, MF_FILEFLAGS_NOBUFFERING, fileUrl, &byteStream);
// Create the MPEG4 ByteStreamHandler
IMFByteStreamHandler* handler = nullptr;
hr = CoCreateInstance(CLSID_MPEG4ByteStreamPlugin, nullptr, CLSCTX_ALL, IID_IMFByteStreamHandler, (void**)&handler);
IMFAsyncCallback* callback = new CallbackTest(handler);
hr = handler->BeginCreateObject(byteStream, nullptr, MF_RESOLUTION_MEDIASOURCE | MF_RESOLUTION_READ | MF_RESOLUTION_CONTENT_DOES_NOT_HAVE_TO_MATCH_EXTENSION_OR_MIME_TYPE, nullptr, nullptr, callback, handler);
【讨论】:
以上是关于如何让 Microsoft MPEG4 Source 打开比特率高于 4Gbps 的 MOV的主要内容,如果未能解决你的问题,请参考以下文章
如何编程实现视频转码? 用C/C++实现将MPEG4标准的视频转化为H.264标准的视频