Windows Media 编码器不保存 MF_MT_MPEG_SEQUENCE_HEADER
Posted
技术标签:
【中文标题】Windows Media 编码器不保存 MF_MT_MPEG_SEQUENCE_HEADER【英文标题】:Windows Media Encoder not saving MF_MT_MPEG_SEQUENCE_HEADER 【发布时间】:2019-03-29 07:42:22 【问题描述】:我想使用 Win7 Media Foundation SDK 将视频帧编码为 H264,然后使用 sinkwriter 将它们保存为 .mp4 文件。
但是,当我没有手动将MF_MT_MPEG_SEQUENCE_HEADER
添加到输出媒体类型并且文件不可播放时,sinkwriter 完成失败。
我检查了编码器,它应该添加它(参见H.264 Video Encoder)。但它只会给出MF_E_ATTRIBUTENOTFOUND
错误。
IMFMediaType * outputType;
hr = m_pEncoder->GetOutputCurrentType(0, &outputType);
UINT32 sequenceHeaderDataSize;
hr = outputType->GetBlobSize(MF_MT_MPEG_SEQUENCE_HEADER, &sequenceHeaderDataSize);
使用我在网上找到的MF_MT_MPEG_SEQUENCE_HEADER
(适用于 1080p),我能够获得可播放的文件。然而,它在亮度(随机变化〜每 0.5 秒)和阻塞错误方面仍然存在一些错误。
UINT8 blob[] = 0x00, 0x00, 0x00, 0x01, 0x67, 0x64, 0x00, 0x2A, 0xAD, 0x84, 0x01, 0x0C, 0x20, 0x08, 0x61, 0x00, 0x43, 0x08, 0x02, 0x18, 0x40, 0x10, 0xC2, 0x00, 0x84, 0x2B, 0x50, 0x3C, 0x01, 0x13, 0xF2, 0xC2, 0x00, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x79, 0x08, 0x00, 0x00, 0x00, 0x01, 0x68, 0xEE, 0x3C, 0xB0;
//create sink attributes
IMFAttributes * sinkAttributes = NULL;
HRESULT hr = MFCreateAttributes(&sinkAttributes, 1);
hr = sinkAttributes->SetUINT32(MF_READWRITE_DISABLE_CONVERTERS, true);
//create sink
IMFSinkWriter * pSinkWriter = NULL;
hr = MFCreateSinkWriterFromURL(L"output.mp4", NULL, sinkAttributes, &pSinkWriter);
// Set the output media type.
IMFMediaType * pMediaTypeOut = NULL;
CHECK_HR(MFCreateMediaType(&pMediaTypeOut));
CHECK_HR(pMediaTypeOut->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video));
CHECK_HR(pMediaTypeOut->SetGUID(MF_MT_SUBTYPE, VIDEO_INPUT_FORMAT));
CHECK_HR(MFSetAttributeSize(pMediaTypeOut, MF_MT_FRAME_SIZE, VIDEO_WIDTH, VIDEO_HEIGHT));
CHECK_HR(MFSetAttributeRatio(pMediaTypeOut, MF_MT_FRAME_RATE, VIDEO_FPS, 1));
CHECK_HR(pMediaTypeOut->SetBlob(MF_MT_MPEG_SEQUENCE_HEADER, blob, sizeof(blob)));
CHECK_HR(pSinkWriter->AddStream(pMediaTypeOut, &streamIndex));
// Tell the sink writer to start accepting data.
hr = pSinkWriter->BeginWriting();
这可能与 windows 7 相关,很遗憾我无法在 windows 10 计算机上进行检查。
其他地方需要编码的帧,所以我不能跳过编码直接将我的帧放入接收器。
【问题讨论】:
【参考方案1】:一些编码器,比如 - 如果我没记错的话 - 在 Windows 7 Intel Quick Sync 上非常流行和可用,只有在您开始样本处理后才能使用 MF_MT_MPEG_SEQUENCE_HEADER
。也就是说,当您管理 MFT 时,您必须执行 ProcessInput
、ProcessOutput
、处理动态格式更改、更改媒体类型,并且在新的媒体类型中您有序列头。也就是说,只有在您准备好从编码器接收到初始输入后的数据时,您才应该开始编码并初始化接收器写入器。
您必须拥有正确的MF_MT_MPEG_SEQUENCE_HEADER
,并且您不能对随机值进行硬编码。您可以像以前一样进行故障排除,但这些不仅仅是给定分辨率的一些字节。
注意Windows 8 updates to MPEG-4 source and sink:
可以从 MPEG-4 sink 的输入样本中提取 SPS 和 PPS。
当 SPS 和 PPS 没有通过 MPEG-4 接收器的输入媒体类型上的 MF_MT_MPEG_SEQUENCE_HEADER 设置时,MPEG-4 接收器将尝试从输入样本中提取 SPS 和 PPS。 MPEG-4 sink 会忽略任何输入样本,直到找到第一个 SPS 和 PPS,因为没有 SPS 和 PPS 的所有输入样本都无法解码。
确实,由于更新而在 Windows 8 中工作的东西在 Windows 7 中不可用,您必须自己处理MF_MT_MPEG_SEQUENCE_HEADER
。
【讨论】:
确实,我使用的是 Windows 7 Intel Quick Sync。然而,m_pEncoder->ProcessOutput
-方法永远不会返回MF_E_TRANSFORM_STREAM_CHANGE
,即使在几帧之后也是如此。我还检查了以后是否添加了MF_MT_MPEG_SEQUENCE_HEADER
,但没有运气。当然,对标头进行硬编码只是为了调试目的。
(我没有Win7可以检查)也许你可以从有效载荷中提取标题?它应该相当简单 - 使用编码器的第一个输出。
标头不包含在有效负载中。至少你不能从任何编码器输出中提取它。我确实有机会在 win10 电脑上试用,一切正常。稍后我将尝试在 Win10 计算机上提取 Header 并将其硬编码以在 Win7 中使用(即使这不是一件好事)。
我经常看到示例数据中重复的参数集,所以我希望这可以从有效负载中提取。供应商特定的 SDK 通常将此作为重复参数集的选项,但是当涉及到他们的编码器 MFT 时,我只记得 AMD 不会用 I 帧重复它们。以上是关于Windows Media 编码器不保存 MF_MT_MPEG_SEQUENCE_HEADER的主要内容,如果未能解决你的问题,请参考以下文章
无法设置 windows media video 9 屏幕编码器
怎样才能让windows media player能播放H264编码的AVI文件(音频是AC3)
Windows Media Player 无法播放该文件。可能是播放机不支持该文件类型,或者不支持用于压缩该文件的编...
怎样可以让Windows Media Player可以播放MP4格式电影