video-streaming - 媒体基金会:英特尔硬件 MFT 的 SPS/PPS 问题
问题描述
我正在使用英特尔硬件 MFT 将 NV12 帧编码为 H264 流,并使用 Live555 通过 LAN 上的 RTP 流式传输编码的帧,并在另一端设置 ffplay 来解码和显示相同的帧。该设置适用于软件编码器(SYNC 或 ASYNC 软件 MFT),但 ffplay 抱怨在英特尔硬件 MFT 中进行编码时 SPS/PPS 不可用,并且只显示一个加扰的屏幕。我发现英特尔硬件编码器在输入初始样本后触发 MF_E_TRANSFORM_STREAM_CHANGE 事件并通过 MF_MT_MPEG_SEQUENCE_HEADER 使 SPS/PPS 可用。我能够捕捉到 MF_E_TRANSFORM_STREAM_CHANGE 事件并获取序列头 blob。
问题是,Live555 需要单独设置 SPS 和 PPS。但是,我对从 MF_MT_MPEG_SEQUENCE_HEADER blob 中提取 SPS 和 PPS 感到非常困惑。
根据我的理解,以及在其他线程中的进一步查找,SPS 和 PPS 分别以 00 00 00 01 67 和 0 00 00 01 68 开头。但是,我在从英特尔编码器收到的 blob 中的任何地方都找不到这些序列。
https://github.com/cisco/openh264/issues/756 SPS 开始:00 00 00 01 67 PPS 开始:00 00 00 01 68
从 intel MFT 获得的序列头:
序列头大小 50
序列头:0 0 1 27 64 0 28 ac 2b 40 3c 1 13 f2 e0 22 0 0 3 0 2 0 0 3 0 79 d0 80 f 42 0 3 d0 93 7b df 7 68 70 ca 80 0 0 0 1 28 ee 3c b0 0
vector<byte> sequenceHeaderData;
UINT32 sequenceHeaderDataSize = 0;
MFT_OUTPUT_DATA_BUFFER _outputDataBuffer;
memset(&_outputDataBuffer, 0, sizeof _outputDataBuffer);
_outputDataBuffer.dwStreamID = outputStreamID;
_outputDataBuffer.dwStatus = 0;
_outputDataBuffer.pEvents = nullptr;
_outputDataBuffer.pSample = nullptr;
HRESULT mftProcessOutput = _pEncoder->ProcessOutput(0, 1, &_outputDataBuffer, &processOutputStatus);
if (MF_E_TRANSFORM_STREAM_CHANGE == mftProcessOutput)
{
// some encoders want to renegotiate the output format.
if (_outputDataBuffer.dwStatus & MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE)
{
CComPtr<IMFMediaType> pNewOutputMediaType = nullptr;
HRESULT res = _pEncoder->GetOutputAvailableType(outputStreamID, 1, &pNewOutputMediaType);
res = _pEncoder->SetOutputType(outputStreamID, pNewOutputMediaType, 0);//setting the type again
CHECK_HR(res, "Failed to set output type during stream change");
{
CComPtr<IMFMediaType> pCurOutputMediaType = nullptr;
HRESULT res = _pEncoder->GetOutputAvailableType(outputStreamID, 1, &pCurOutputMediaType);
res = pCurOutputMediaType->GetBlobSize(MF_MT_MPEG_SEQUENCE_HEADER, &sequenceHeaderDataSize);
if (SUCCEEDED(res) && sequenceHeaderDataSize > 0)
{
sequenceHeaderData.resize(sequenceHeaderDataSize);
pCurOutputMediaType->GetBlob(MF_MT_MPEG_SEQUENCE_HEADER, sequenceHeaderData.data(), sequenceHeaderDataSize, NULL);
cout << "Sequence header size " << sequenceHeaderDataSize << std::endl;
}
else
{
cout << "Sequence header is not available" << std::endl;
}
}
}
}
解决方案
根据我的理解,以及在其他线程中的进一步查找,SPS 和 PPS 分别以 00 00 00 01 67 和 0 00 00 01 68 开头。
你假设错了。
从您的示例标题中:
这是 SPS: 0 0 1 27 64 0 28 ac 2b 40 3c 1 13 f2 e0 22 0 0 3 0 2 0 0 3 0 79 d0 80 f 42 0 3 d0 93 7b df 7 68 70 ca 80
这是 PPS:0 0 0 1 28 ee 3c b0 0
说明:
SPS nalu 类型定义为 7 在第一个字节的最后 5 位中,在起始码之后。(不是 67)。
PPS nalu 类型是第一个字节的最后 5 位中的 8,分别位于起始码之后(不是 68)。
注意:起始码只能包含 3 个字节,其值分别为:0 0 1。
推荐阅读
- javascript - HTTPInterceptor 未拦截来自 Angular 8 应用程序中第 3 方小部件的 http 请求
- webpack - 未捕获错误类型错误:无法使用“in”运算符在 next-dev.js:8 的未定义中搜索“电子”
- python - 为什么在尝试为 CNN 添加训练集时显示以下错误?
- python - 如何通过确定元素对嵌套列表进行排序?
- c# - 如何为 C# 传递experimental_allow_proto3_optional
在 proto3 中启用可选的定义? - php - PHP 警告:模块 'xxxxxxx' 已经加载到第 0 行的未知中,重复写入 error_log
- python-3.x - 总结两列忽略 NaN 的熊猫数据框
- javascript - 如何使用 Context API 在 React js 中删除列表
- c# - word.ExportAsFixedFormat 在不同的系统中给出不同的输出
- r - glm 预测和使用相同 glm 的 geom_smooth() 之间的差异