【问题标题】:Media Foundation: SPS/PPS problem with Intel hardware MFT媒体基金会:英特尔硬件 MFT 的 SPS/PPS 问题
【发布时间】:2020-03-15 02:31:57
【问题描述】:

我正在使用英特尔硬件 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;
            }
        }
    }
}

【问题讨论】:

    标签: video-streaming rtp ms-media-foundation live555


    【解决方案1】:

    据我了解,并在其他线程中进一步查找,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

    Explanation:

    SPS nalu 类型定义为 7 在第一个字节的最后 5 位中,在起始码之后。 (不是 67)。

    PPS nalu 类型是8 在第一个字节的最后5 位,分别在起始码之后(不是68)。

    注意:起始码只能包含3个字节,值分别为:0 0 1。

    【讨论】:

    • 此信息可能会引起某些人的困惑,并且部分不正确。 SPS 是类型 7,但是是 5 位,而不是 4。所以 0x27 是 SPS,但 0x17 不是。只有第一个半字节中的偶数和 7 才是 SPS。 PPS 也是如此,只有 8 个。
    猜你喜欢
    • 1970-01-01
    • 2017-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-10
    • 2020-03-05
    • 1970-01-01
    相关资源
    最近更新 更多