为何MediaFoundation的H.264解码器会出现"CopyDecodedFrame failed"错误?
针对复用IMFMediaBuffer解码H.264帧时,IMFTransform::ProcessOutput抛出"CopyDecodedFrame failed"异常的问题,可按以下步骤排查解决:
严格满足缓冲区字节对齐要求
微软H.264 MFT解码器对输出缓冲区的内存对齐有硬性要求(通常为16或32字节),复用缓冲区时若对齐参数不匹配会导致内部拷贝失败。改用MFCreateAlignedMemoryBuffer创建缓冲区,对齐值需与解码器输出媒体类型的MF_MT_DEFAULT_STRIDE属性匹配,可通过IMFMediaType::GetUINT32获取该值后计算对齐参数。复用前完整重置缓冲区状态
每次复用缓冲区前必须执行:- 调用
IMFMediaBuffer::SetCurrentLength(0)重置有效长度; - 若缓冲区实现
IMF2DBuffer接口,需确保已调用Unlock2D解除所有内存锁定; - 避免在缓冲区仍有未处理的锁定区域时传入解码器。
- 调用
动态匹配输出帧的缓冲区大小
部分H.264流存在分辨率动态变化的情况,复用固定大小的缓冲区会因后续帧尺寸超出容量导致拷贝失败。每次调用ProcessOutput前,通过解码器输出媒体类型的MF_MT_FRAME_SIZE属性获取当前帧的宽高,计算所需缓冲区总字节数,若复用缓冲区大小不足则重新分配。确保缓冲区无并发访问冲突
即使AddRef/Release显示解码器未持有缓冲区引用,也要保证ProcessOutput调用期间,缓冲区未被其他线程修改、锁定或释放。复用缓冲池需实现严格的线程同步机制,同一缓冲区同一时间只能被一个解码流程使用。尝试调整解码器输出模式
若解码器支持,可设置MFT_OUTPUT_STREAM_PROVIDES_SAMPLES属性,让解码器使用内部缓冲区完成解码,之后再将数据拷贝到复用的缓冲区中;或调用ProcessOutput时传入MFT_PROCESS_OUTPUT_DISCARD_WHEN_NO_BUFFER标志,强制解码器将输出写入指定缓冲区(需确保缓冲区参数完全符合要求)。
内容的提问来源于stack exchange,提问作者Andrzej Szombierski

