使用SourceReader/SinkWriter复制HEVC视频流后输出文件无法播放
解决Windows Media Foundation复制HEVC视频流缺失媒体类型信息的问题
核心原因
HEVC(H.265)与H.264在Media Foundation中的处理逻辑存在差异:H.264的SinkWriter可自动识别并写入SPS/PPS等序列参数集,而HEVC必须手动提取并注入VPS/SPS/PPS这些关键头部参数,否则输出文件的复用器无法生成正确的媒体轨道信息,导致播放器无法识别。
具体解决步骤
1. 从源视频媒体类型提取HEVC参数集
通过SourceReader获取源视频流的IMFMediaType后,提取以下关键Blob属性:
MF_MT_HEVC_SEQUENCE_PARAMETER_SET:包含SPS和VPS数据MF_MT_HEVC_PICTURE_PARAMETER_SET:包含PPS数据
这些参数是解码器识别HEVC流的核心,存储在源媒体类型的属性中,可通过GetBlob方法读取。
2. 手动配置SinkWriter的输出媒体类型
不能直接将源媒体类型传递给SinkWriter,需手动构建输出媒体类型并复制关键属性:
- 设置媒体类型主类型为
MFMediaType_Video,子类型为MFVideoFormat_HEVC - 复制源媒体类型中的分辨率、帧率、像素格式等基础属性
- 将步骤1提取的HEVC参数集Blob写入输出媒体类型对应的属性中
3. 可选:写入配置样本确保参数集生效
若SinkWriter仍未正确识别参数集,可在写入第一个视频样本前,将参数集封装为配置类型样本(设置MF_SAMPLE_DATATYPE_CONFIGURATION属性)写入SinkWriter,强制复用器将参数集写入文件头部。
代码示例(C++)
// 从源媒体类型提取HEVC参数集 BYTE* pSpsVpsData = nullptr; DWORD dwSpsVpsSize = 0; hr = pSourceMediaType->GetBlob(MF_MT_HEVC_SEQUENCE_PARAMETER_SET, &pSpsVpsData, &dwSpsVpsSize); BYTE* pPpsData = nullptr; DWORD dwPpsSize = 0; hr = pSourceMediaType->GetBlob(MF_MT_HEVC_PICTURE_PARAMETER_SET, &pPpsData, &dwPpsSize); // 创建并配置输出媒体类型 IMFMediaType* pOutputMediaType = nullptr; hr = MFCreateMediaType(&pOutputMediaType); hr = pOutputMediaType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video); hr = pOutputMediaType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_HEVC); // 复制源媒体类型的基础属性 hr = pSourceMediaType->CopyAllItems(pOutputMediaType); // 注入HEVC参数集 hr = pOutputMediaType->SetBlob(MF_MT_HEVC_SEQUENCE_PARAMETER_SET, pSpsVpsData, dwSpsVpsSize); hr = pOutputMediaType->SetBlob(MF_MT_HEVC_PICTURE_PARAMETER_SET, pPpsData, dwPpsSize); // 配置SinkWriter DWORD dwStreamIndex = 0; hr = pSinkWriter->AddStream(pOutputMediaType, &dwStreamIndex); hr = pSinkWriter->SetInputMediaType(dwStreamIndex, pOutputMediaType, nullptr); hr = pSinkWriter->BeginWriting();
注意事项
- 确保运行环境为Windows 10及以上,Media Foundation在Win10才完整支持HEVC
- 若源文件是MP4格式,SourceReader会自动解析轨道中的参数集到媒体类型属性,无需手动解析文件结构
- 避免复用源媒体类型的私有属性,手动复制关键属性能减少兼容性问题
内容的提问来源于stack exchange,提问作者Renate Schaaf
相关产品推荐
相关产品推荐

