From e658c999a64640d63beddf9ddde96a0706bf331a Mon Sep 17 00:00:00 2001 From: Shao-Feng Date: Tue, 24 Dec 2024 14:34:09 +0000 Subject: [PATCH] Re-init decoder when REPOSITION error happen and append SPS once the header bitstream is less than SPS+PPS SPS is missed in AVC case Signed-off-by: Shao-Feng --- .../src/mfx_c2_decoder_component.cpp | 10 +++- c2_utils/include/mfx_frame_constructor.h | 18 +++++++ c2_utils/src/mfx_frame_constructor.cpp | 49 ++++++++++++++++++- 3 files changed, 75 insertions(+), 2 deletions(-) diff --git a/c2_components/src/mfx_c2_decoder_component.cpp b/c2_components/src/mfx_c2_decoder_component.cpp index db7ccfea..2c4bd009 100755 --- a/c2_components/src/mfx_c2_decoder_component.cpp +++ b/c2_components/src/mfx_c2_decoder_component.cpp @@ -1129,8 +1129,16 @@ mfxStatus MfxC2DecoderComponent::InitDecoder(std::shared_ptr c2_all m_mfxVideoParams.NumExtParam = m_extBuffers.size(); m_mfxVideoParams.ExtParam = &m_extBuffers.front(); + std::shared_ptr bs = m_c2Bitstream->GetFrameConstructor()->GetMfxBitstream(); + std::shared_ptr header = m_c2Bitstream->GetFrameConstructor()->GetHeaderInfo(); + + if (nullptr != header && nullptr != bs && header->DataLength > bs->DataLength) { + m_c2Bitstream->GetFrameConstructor()->AppendSps(bs); + } + // decoding header - mfx_res = m_mfxDecoder->DecodeHeader(m_c2Bitstream->GetFrameConstructor()->GetMfxBitstream().get(), &m_mfxVideoParams); + mfx_res = m_mfxDecoder->DecodeHeader(bs.get(), &m_mfxVideoParams); + // MSDK will call the function av1_native_profile_to_mfx_profile to change CodecProfile in DecodeHeader while // decoder type is av1. So after calling DecodeHeader, we have to revert this value to avoid unexpected behavior. if (m_decoderType == DECODER_AV1) diff --git a/c2_utils/include/mfx_frame_constructor.h b/c2_utils/include/mfx_frame_constructor.h index 902d107b..5c214d6f 100755 --- a/c2_utils/include/mfx_frame_constructor.h +++ b/c2_utils/include/mfx_frame_constructor.h @@ -69,6 +69,10 @@ class IMfxC2FrameConstructor virtual mfxPayload* GetSEI(mfxU32 /*type*/) = 0; // save current SPS/PPS virtual mfxStatus SaveHeaders(std::shared_ptr sps, std::shared_ptr pps, bool is_reset) = 0; + + virtual std::shared_ptr GetHeaderInfo() = 0; + + virtual mfxStatus AppendSps(std::shared_ptr bs) = 0; // get whether in reset state virtual bool IsInReset() = 0; @@ -112,6 +116,15 @@ class MfxC2FrameConstructor : public IMfxC2FrameConstructor (void)is_reset; return MFX_ERR_NONE; } + + virtual std::shared_ptr GetHeaderInfo() { + return nullptr; + } + + virtual mfxStatus AppendSps(std::shared_ptr bs) { + return MFX_ERR_NONE; + } + // get whether in reset state virtual bool IsInReset(); @@ -168,6 +181,10 @@ class MfxC2AVCFrameConstructor : public MfxC2FrameConstructor // save current SPS/PPS virtual mfxStatus SaveHeaders(std::shared_ptr sps, std::shared_ptr pps, bool is_reset); + virtual std::shared_ptr GetHeaderInfo(); + + virtual mfxStatus AppendSps(std::shared_ptr bs); + protected: // functions virtual mfxStatus Load(const mfxU8* data, mfxU32 size, mfxU64 pts, bool header, bool complete_frame); virtual mfxStatus LoadHeader(const mfxU8* data, mfxU32 size, bool header); @@ -189,6 +206,7 @@ class MfxC2AVCFrameConstructor : public MfxC2FrameConstructor mfxBitstream m_sps; mfxBitstream m_pps; + mfxU8* m_cache_data = nullptr; private: MFX_CLASS_NO_COPY(MfxC2AVCFrameConstructor) diff --git a/c2_utils/src/mfx_frame_constructor.cpp b/c2_utils/src/mfx_frame_constructor.cpp index 20595eb9..68d6d03d 100755 --- a/c2_utils/src/mfx_frame_constructor.cpp +++ b/c2_utils/src/mfx_frame_constructor.cpp @@ -127,7 +127,6 @@ mfxStatus MfxC2FrameConstructor::LoadHeader(const mfxU8* data, mfxU32 size, bool mfx_res = BstBufRealloc(m_bstHeader->DataLength); if (MFX_ERR_NONE == mfx_res) { mfxU8* buf = m_bstBuf->Data + m_bstBuf->DataOffset + m_bstBuf->DataLength; - std::copy(m_bstHeader->Data + m_bstHeader->DataOffset, m_bstHeader->Data + m_bstHeader->DataOffset + m_bstHeader->DataLength, buf); m_bstBuf->DataLength += m_bstHeader->DataLength; @@ -369,6 +368,50 @@ MfxC2AVCFrameConstructor::~MfxC2AVCFrameConstructor() MFX_FREE(m_sps.Data); MFX_FREE(m_pps.Data); + + if (m_cache_data) { + free(m_cache_data); + m_cache_data = nullptr; + } +} + +mfxStatus MfxC2AVCFrameConstructor::AppendSps(std::shared_ptr bs) +{ + MFX_DEBUG_TRACE_FUNC; + if (m_sps.Data && m_sps.DataLength && bs->Data && bs->DataLength) { + mfxU8* data = (mfxU8*)calloc(0, m_sps.DataLength + bs->DataLength); + std::copy(m_sps.Data + m_sps.DataOffset, m_sps.Data + m_sps.DataOffset + m_sps.DataLength, data); + std::copy(bs->Data + bs->DataOffset, bs->Data + bs->DataOffset + bs->DataLength, data + m_sps.DataLength); + + if (m_cache_data) free(m_cache_data); + m_cache_data = bs->Data; + bs->Data = data; + bs->DataLength = m_sps.DataLength + bs->DataLength; + bs->DataOffset = 0; + return MFX_ERR_NONE; + } + return MFX_ERR_MEMORY_ALLOC; +} + +std::shared_ptr MfxC2AVCFrameConstructor::GetHeaderInfo() +{ + MFX_DEBUG_TRACE_FUNC; + + std::shared_ptr header = std::make_shared(); + MFX_ZERO_MEMORY((*header)); + + if ((m_sps.Data && m_sps.DataLength) && + (m_pps.Data && m_pps.DataLength)){ + header->DataOffset = 0; + header->DataLength = m_sps.DataLength + m_pps.DataLength; + header->TimeStamp = m_sps.TimeStamp; + header->MaxLength = m_sps.MaxLength + m_pps.MaxLength; + header->FrameType = m_sps.FrameType; + header->DataFlag = m_sps.DataFlag; + } else { + header = nullptr; + } + return header; } mfxStatus MfxC2AVCFrameConstructor::SaveHeaders(std::shared_ptr sps, std::shared_ptr pps, bool is_reset) @@ -387,6 +430,8 @@ mfxStatus MfxC2AVCFrameConstructor::SaveHeaders(std::shared_ptr sp std::copy(sps->Data + sps->DataOffset, sps->Data + sps->DataOffset + sps->DataLength, m_sps.Data); m_sps.DataLength = sps->DataLength; + m_sps.FrameType = sps->FrameType; + m_sps.DataFlag = sps->DataFlag; } if (nullptr != pps) { if (m_pps.MaxLength < pps->DataLength) { @@ -397,6 +442,8 @@ mfxStatus MfxC2AVCFrameConstructor::SaveHeaders(std::shared_ptr sp } std::copy(pps->Data + pps->DataOffset, pps->Data + pps->DataOffset + pps->DataLength, m_pps.Data); m_pps.DataLength = pps->DataLength; + m_pps.FrameType = pps->FrameType; + m_pps.DataFlag = pps->DataFlag; } return MFX_ERR_NONE; }