Video streaming 媒体基础:英特尔硬件MFT的SPS/PPS问题

Video streaming 媒体基础:英特尔硬件MFT的SPS/PPS问题,video-streaming,rtp,ms-media-foundation,live555,Video Streaming,Rtp,Ms Media Foundation,Live555,我使用Intel hardware MFT将NV12帧编码为H264流,并使用Live555通过局域网上的RTP对编码帧进行流式传输,并在另一端设置ffplay对其进行解码和显示。软件编码器(同步或异步软件MFT)的设置工作正常,但ffplay抱怨在英特尔硬件MFT中进行编码时SPS/PPS不可用,只显示一个加扰屏幕。我发现Intel硬件编码器在输入初始样本后触发MF_E_TRANSFORM_STREAM_CHANGE事件,并通过MF_MT_MPEG_SEQUENCE_头使SPS/PPS可用。我

我使用Intel hardware MFT将NV12帧编码为H264流,并使用Live555通过局域网上的RTP对编码帧进行流式传输,并在另一端设置ffplay对其进行解码和显示。软件编码器(同步或异步软件MFT)的设置工作正常,但ffplay抱怨在英特尔硬件MFT中进行编码时SPS/PPS不可用,只显示一个加扰屏幕。我发现Intel硬件编码器在输入初始样本后触发MF_E_TRANSFORM_STREAM_CHANGE事件,并通过MF_MT_MPEG_SEQUENCE_头使SPS/PPS可用。我能够捕获MF_E_TRANSFORM_STREAM_CHANGE事件并获取序列头blob

问题是,Live555要求单独设置SP和PPS。但是,我对从MF_MT_MPEG_SEQUENCE_HEADER blob中提取SP和PPS感到非常困惑

根据我的理解,在其他线程中进一步查找,SP和PPS分别从00 01 67和0 00 01 68开始。但是,我从Intel编码器收到的blob中没有找到这些序列

SPS的开始时间:00 01 67 PPS开始时间:00 01 68

从英特尔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 1 28 ee 3c b0 0

矢量序列头数据;
UINT32 sequenceHeaderDataSize=0;
MFT_输出_数据_缓冲器_输出数据缓冲器;
memset(&_outputDataBuffer,0,sizeof_outputDataBuffer);
_outputDataBuffer.dwStreamID=outputStreamID;
_outputDataBuffer.dwStatus=0;
_outputDataBuffer.pEvents=nullptr;
_outputDataBuffer.pSample=nullptr;
HRESULT mftProcessOutput=\u pEncoder->ProcessOutput(0、1和&u outputDataBuffer和&processOutputStatus);
if(MF_E_TRANSFORM_STREAM_CHANGE==mftProcessOutput)
{
//一些编码器想要重新协商输出格式。
if(_outputDataBuffer.dwStatus&MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE)
{
CComPtr pNewOutputMediaType=nullptr;
HRESULT res=\u pEncoder->GetOutputAvailableType(outputStreamID、1和PneOutputMediaType);
res=\u pEncoder->SetOutputType(outputStreamID,pNewOutputMediaType,0);//再次设置类型
检查_HR(res,“流更改期间设置输出类型失败”);
{
CComPtr pCurOutputMediaType=nullptr;
HRESULT res=\u pEncoder->GetOutputAvailableType(outputStreamID、1和pCurOutputMediaType);
res=pCurOutputMediaType->GetBlobSize(MF\u MT\u MPEG\u SEQUENCE\u HEADER和sequenceHeaderDataSize);
if(成功(res)&&sequenceHeaderDataSize>0)
{
sequenceHeaderData.resize(sequenceHeaderDataSize);
pCurOutputMediaType->GetBlob(MF\u MT\u MPEG\u SEQUENCE\u HEADER,sequenceHeaderData.data(),sequenceHeaderDataSize,NULL);
库特
根据我的理解,在其他线程中进一步查找,SP和PPS分别从00 01 67和0 00 01 68开始

你想错了

从示例标题:

这是SPS: 0 0 1 27 64 0 28 ac 2b 40 3c 1 13 f2 e0 22 0 0 3 0 0 79 d0 80 f 42 0 3 d0 93 7b df 7 68 70 ca 80

这是PPS: 0 0 1 28 ee 3c b0 0

:

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

PPS nalu type在起始代码之后的第一个字节的最后5位中分别为8(不是68)


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

此信息可能会引起某些人的混淆,并且部分不正确。SPS是类型7,但S是5位,而不是4位。因此0x27是SPS,而0x17不是。只有第一个半字节中的偶数(7)是SPS。对于PPS也是如此,只有8。
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;
            }
        }
    }
}