如何检查 Media Foundation 是不是可以实际播放文件而不仅仅是加载它

Posted

技术标签:

【中文标题】如何检查 Media Foundation 是不是可以实际播放文件而不仅仅是加载它【英文标题】:How to check if Media Foundation can actually play a file and not just load it如何检查 Media Foundation 是否可以实际播放文件而不仅仅是加载它 【发布时间】:2020-10-24 14:19:44 【问题描述】:

我在使用 MPEG1 视频和 Media Foundation 时遇到了一些问题:所以 Media Foundation 不支持播放 MPEG1 视频流 (see here),但由于某种原因,它仍然会打开它们,甚至会报告正确的持续时间和帧大小。所以在打开时,一切看起来都可以播放这些文件。

但它不能!一旦您尝试实际播放 MPEG1 视频文件,IMFAsyncCallback::Invoke() 将被调用,状态为MESessionTopologySet,然后IMFMediaEvent::GetStatus() 将返回 0xc004f011,仅此而已。

那么有没有办法检查媒体基金会在打开视频格式后是否真的可以播放它,或者有没有办法让媒体基金会只打开它可以实际播放的文件?目前我只能通过尝试开始播放来判断文件是否可以播放,然后查看它是否有效,这有点不方便。我希望能够更早地判断文件是否可以播放。

【问题讨论】:

构建拓扑和暂停对您解决提出的任务有用吗?我相信在SL_E_LICENSE_FILE_NOT_INSTALLED 的情况下暂停是不会成功的。 @RomanR.:抱歉,没有用。 IMFMediaSession::Pause 在 MPEG1 文件上返回 0,即成功。 那么使用标准组件的下一个不错的选择可能是构建播放拓扑(带解码!)到samplegrabber sink。那么它必须在播放时失败。 @RomanR.:但这不会在受 DRM 保护的内容上也失败吗? AFAIR 并非所有编解码器都允许采样... @RomanR.:谢谢。为简单起见,我用IMFSourceReader 代替样本采集器做了一些实验。这似乎可以解决问题。见下文,我已经发布了这个问题的答案。 【参考方案1】:

我现在使用IMFSourceReader 解决了这个问题。我发现尝试将媒体类型设置为MFVideoFormat_RGB32 将在 MPEG1 视频流中失败,但它可以在 MPEG4 中正常工作,因此这可能是检查 Media Foundation 是否可以实际播放文件的可行方法。在代码中,解决方案如下所示:

hr = MFCreateAttributes(&pAttr, 1);
if(SUCCEEDED(hr)) 
            
    IMFAttributes_SetUINT32(pAttr, &MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, TRUE);
    IMFAttributes_SetUINT32(pAttr, &MF_SOURCE_READER_ENABLE_VIDEO_PROCESSING, TRUE);

    hr = MFCreateSourceReaderFromURL(filename, pAttr, &pReader);
    if(SUCCEEDED(hr)) 
            
        hr = IMFSourceReader_GetCurrentMediaType(pReader, MF_SOURCE_READER_FIRST_VIDEO_STREAM, &pFileVideoMediaType);
        if(SUCCEEDED(hr)) 
                        
            hr = MFCreateMediaType(&pTypeUncomp);
            if(SUCCEEDED(hr)) 
                        
                IMFMediaType_CopyAllItems(pFileVideoMediaType, (IMFAttributes *) pTypeUncomp);

                IMFMediaType_SetGUID(pTypeUncomp, &MF_MT_SUBTYPE, &MFVideoFormat_RGB32);
                IMFMediaType_SetUINT32(pTypeUncomp, &MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE);
                IMFMediaType_SetUINT32(pTypeUncomp, &MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive);

                hr = IMFSourceReader_SetCurrentMediaType(pReader, MF_SOURCE_READER_FIRST_VIDEO_STREAM, 0, pTypeUncomp);
                if(SUCCEEDED(hr)) printf("NOT AN MPEG1 STREAM!\n");
            
        
    
    
    SAFERELEASE(&pAttr);

【讨论】:

以上是关于如何检查 Media Foundation 是不是可以实际播放文件而不仅仅是加载它的主要内容,如果未能解决你的问题,请参考以下文章

如何确定 Windows Media Foundation 接收器编写器是不是需要自下而上或自上而下的图像?

Media Foundation 多音频流文件解码错误

Media Foundation Capture - 如何检测真正的原生输入格式

如何使用 Media Foundation 从 IMFSourceReader 播放音频缓冲区

如何确定 Media Foundation 中特定 MJPEG 子类型的色度子采样?

使用 Media Foundation SDK 进行直播