diff --git a/src/codechandler/AVCCodecHandler.cpp b/src/codechandler/AVCCodecHandler.cpp index a40f4a990..bdef5e73d 100644 --- a/src/codechandler/AVCCodecHandler.cpp +++ b/src/codechandler/AVCCodecHandler.cpp @@ -12,7 +12,7 @@ using namespace UTILS; -AVCCodecHandler::AVCCodecHandler(AP4_SampleDescription* sd, bool isRequiredAnnexB) +AVCCodecHandler::AVCCodecHandler(AP4_SampleDescription* sd) : CodecHandler{sd}, m_countPictureSetIds{0}, m_needSliceInfo{false}, @@ -29,16 +29,8 @@ AVCCodecHandler::AVCCodecHandler(AP4_SampleDescription* sd, bool isRequiredAnnex if (AP4_AvcSampleDescription* avcSampleDescription = AP4_DYNAMIC_CAST(AP4_AvcSampleDescription, m_sampleDescription)) { - if (isRequiredAnnexB) - { - ExtraDataToAnnexB(); - } - else - { - m_extraData.SetData(avcSampleDescription->GetRawBytes().GetData(), - avcSampleDescription->GetRawBytes().GetDataSize()); - } - + m_extraData.SetData(avcSampleDescription->GetRawBytes().GetData(), + avcSampleDescription->GetRawBytes().GetDataSize()); m_countPictureSetIds = avcSampleDescription->GetPictureParameters().ItemCount(); m_naluLengthSize = avcSampleDescription->GetNaluLengthSize(); m_needSliceInfo = (m_countPictureSetIds > 1 || width == 0 || height == 0); @@ -89,50 +81,6 @@ bool AVCCodecHandler::CheckExtraData(std::vector& extraData, bool isReq return false; } -bool AVCCodecHandler::ExtraDataToAnnexB() -{ - if (AP4_AvcSampleDescription* avcSampleDescription = - AP4_DYNAMIC_CAST(AP4_AvcSampleDescription, m_sampleDescription)) - { - //calculate the size for annexb - AP4_Size sz(0); - AP4_Array& pps(avcSampleDescription->GetPictureParameters()); - for (unsigned int i{0}; i < pps.ItemCount(); ++i) - sz += 4 + pps[i].GetDataSize(); - AP4_Array& sps(avcSampleDescription->GetSequenceParameters()); - for (unsigned int i{0}; i < sps.ItemCount(); ++i) - sz += 4 + sps[i].GetDataSize(); - - if (sz > 0) - { - m_extraData.SetDataSize(sz); - AP4_Byte* cursor(m_extraData.UseData()); - - for (unsigned int i{0}; i < sps.ItemCount(); ++i) - { - cursor[0] = 0; - cursor[1] = 0; - cursor[2] = 0; - cursor[3] = 1; - memcpy(cursor + 4, sps[i].GetData(), sps[i].GetDataSize()); - cursor += sps[i].GetDataSize() + 4; - } - for (unsigned int i{0}; i < pps.ItemCount(); ++i) - { - cursor[0] = 0; - cursor[1] = 0; - cursor[2] = 0; - cursor[3] = 1; - memcpy(cursor + 4, pps[i].GetData(), pps[i].GetDataSize()); - cursor += pps[i].GetDataSize() + 4; - } - return true; - } - } - - return false; -} - void AVCCodecHandler::UpdatePPSId(const AP4_DataBuffer& buffer) { if (!m_needSliceInfo) diff --git a/src/codechandler/AVCCodecHandler.h b/src/codechandler/AVCCodecHandler.h index 337cebd9f..6b350b359 100644 --- a/src/codechandler/AVCCodecHandler.h +++ b/src/codechandler/AVCCodecHandler.h @@ -13,10 +13,9 @@ class ATTR_DLL_LOCAL AVCCodecHandler : public CodecHandler { public: - AVCCodecHandler(AP4_SampleDescription* sd, bool isRequiredAnnexB); + AVCCodecHandler(AP4_SampleDescription* sd); bool CheckExtraData(std::vector& extraData, bool isRequiredAnnexB) override; - bool ExtraDataToAnnexB() override; void UpdatePPSId(const AP4_DataBuffer& buffer) override; bool GetInformation(kodi::addon::InputstreamInfo& info) override; STREAMCODEC_PROFILE GetProfile() override { return m_codecProfile; }; diff --git a/src/codechandler/CodecHandler.h b/src/codechandler/CodecHandler.h index 6ba39c5b7..30f00631b 100644 --- a/src/codechandler/CodecHandler.h +++ b/src/codechandler/CodecHandler.h @@ -33,7 +33,7 @@ class ATTR_DLL_LOCAL CodecHandler * \return True if some info is changed, otherwise false */ virtual bool GetInformation(kodi::addon::InputstreamInfo& info); - virtual bool ExtraDataToAnnexB() { return false; }; + /*! * \brief Check for extradata data format, if needed it will be converted * \param extraData The data diff --git a/src/codechandler/HEVCCodecHandler.cpp b/src/codechandler/HEVCCodecHandler.cpp index aff633791..ca1942d7d 100644 --- a/src/codechandler/HEVCCodecHandler.cpp +++ b/src/codechandler/HEVCCodecHandler.cpp @@ -13,21 +13,13 @@ using namespace UTILS; -HEVCCodecHandler::HEVCCodecHandler(AP4_SampleDescription* sd, bool isRequiredAnnexB) - : CodecHandler(sd) +HEVCCodecHandler::HEVCCodecHandler(AP4_SampleDescription* sd) : CodecHandler(sd) { if (AP4_HevcSampleDescription* hevcSampleDescription = AP4_DYNAMIC_CAST(AP4_HevcSampleDescription, m_sampleDescription)) { - if (isRequiredAnnexB) - { - ExtraDataToAnnexB(); - } - else - { - m_extraData.SetData(hevcSampleDescription->GetRawBytes().GetData(), - hevcSampleDescription->GetRawBytes().GetDataSize()); - } + m_extraData.SetData(hevcSampleDescription->GetRawBytes().GetData(), + hevcSampleDescription->GetRawBytes().GetDataSize()); m_naluLengthSize = hevcSampleDescription->GetNaluLengthSize(); } } @@ -40,9 +32,8 @@ bool HEVCCodecHandler::CheckExtraData(std::vector& extraData, bool isRe // Make sure that extradata is in the required format if (isRequiredAnnexB && !UTILS::IsAnnexB(extraData)) { - //! @todo: this was never implemented on the older ISA versions - LOG::LogF(LOGDEBUG, "Required extradata annex b format, data conversion not implemented"); - return false; + extraData = UTILS::HvccToAnnexb(extraData); + return true; } if (!isRequiredAnnexB && UTILS::IsAnnexB(extraData)) { @@ -53,52 +44,6 @@ bool HEVCCodecHandler::CheckExtraData(std::vector& extraData, bool isRe return false; } -bool HEVCCodecHandler::ExtraDataToAnnexB() -{ - if (AP4_HevcSampleDescription* hevcSampleDescription = - AP4_DYNAMIC_CAST(AP4_HevcSampleDescription, m_sampleDescription)) - { - const AP4_Array& sequences = hevcSampleDescription->GetSequences(); - - if (sequences.ItemCount() == 0) - { - LOG::LogF(LOGWARNING, "No available sequences for HEVC codec extra data"); - return false; - } - - //calculate the size for annexb - AP4_Size size{0}; - for (unsigned int i{0}; i < sequences.ItemCount(); ++i) - { - for (unsigned int j{0}; j < sequences[i].m_Nalus.ItemCount(); ++j) - { - size += sequences[i].m_Nalus[j].GetDataSize() + 4; - } - } - - m_extraData.SetDataSize(size); - uint8_t* cursor(m_extraData.UseData()); - - for (unsigned int i{0}; i < sequences.ItemCount(); ++i) - { - for (unsigned int j{0}; j < sequences[i].m_Nalus.ItemCount(); ++j) - { - cursor[0] = 0; - cursor[1] = 0; - cursor[2] = 0; - cursor[3] = 1; - memcpy(cursor + 4, sequences[i].m_Nalus[j].GetData(), - sequences[i].m_Nalus[j].GetDataSize()); - cursor += sequences[i].m_Nalus[j].GetDataSize() + 4; - } - } - LOG::LogF(LOGDEBUG, "Converted %lu bytes HEVC codec extradata", m_extraData.GetDataSize()); - return true; - } - LOG::LogF(LOGWARNING, "No HevcSampleDescription - annexb extradata not available"); - return false; -} - bool HEVCCodecHandler::GetInformation(kodi::addon::InputstreamInfo& info) { bool isChanged = UpdateInfoCodecName(info, CODEC::FOURCC_HEVC); diff --git a/src/codechandler/HEVCCodecHandler.h b/src/codechandler/HEVCCodecHandler.h index e4186afac..73cd002c7 100644 --- a/src/codechandler/HEVCCodecHandler.h +++ b/src/codechandler/HEVCCodecHandler.h @@ -13,9 +13,8 @@ class ATTR_DLL_LOCAL HEVCCodecHandler : public CodecHandler { public: - HEVCCodecHandler(AP4_SampleDescription* sd, bool isRequiredAnnexB); + HEVCCodecHandler(AP4_SampleDescription* sd); bool CheckExtraData(std::vector& extraData, bool isRequiredAnnexB) override; - bool ExtraDataToAnnexB() override; bool GetInformation(kodi::addon::InputstreamInfo& info) override; }; diff --git a/src/samplereader/FragmentedSampleReader.cpp b/src/samplereader/FragmentedSampleReader.cpp index 60d432910..a8fafcb97 100644 --- a/src/samplereader/FragmentedSampleReader.cpp +++ b/src/samplereader/FragmentedSampleReader.cpp @@ -94,6 +94,9 @@ bool CFragmentedSampleReader::Initialize(SESSION::CStream* stream) break; } + // Create codec handler and get extradata + UpdateSampleDescription(); + return true; } @@ -107,9 +110,6 @@ void CFragmentedSampleReader::SetDecrypter(std::shared_ptrm_extraData.GetDataSize() && !info.CompareExtraData(m_codecHandler->m_extraData.GetData(), @@ -361,6 +363,18 @@ AP4_Result CFragmentedSampleReader::ProcessMoof(AP4_ContainerAtom* moof, { m_sampleDescIndex = tfhd->GetSampleDescriptionIndex(); UpdateSampleDescription(); + + //! @todo: mix of types AP4_DataBuffer vs std::vector + //! bento4 AP4_DataBuffer is not really needed, to change it required also decrypters cleanups + AP4_DataBuffer& chExtradata = m_codecHandler->m_extraData; + std::vector extradata(chExtradata.GetData(), + chExtradata.GetData() + chExtradata.GetDataSize()); + if (m_codecHandler->CheckExtraData( + extradata, + (m_decrypterCaps.flags & DRM::DecrypterCapabilites::SSD_ANNEXB_REQUIRED) != 0)) + { + m_codecHandler->m_extraData.SetData(extradata.data(), extradata.size()); + } } //Correct PTS @@ -496,22 +510,19 @@ void CFragmentedSampleReader::UpdateSampleDescription() } else { - const bool isRequiredAnnexB = - (m_decrypterCaps.flags & DRM::DecrypterCapabilites::SSD_ANNEXB_REQUIRED) != 0; - switch (desc->GetFormat()) { case AP4_SAMPLE_FORMAT_AVC1: case AP4_SAMPLE_FORMAT_AVC2: case AP4_SAMPLE_FORMAT_AVC3: case AP4_SAMPLE_FORMAT_AVC4: - m_codecHandler = new AVCCodecHandler(desc, isRequiredAnnexB); + m_codecHandler = new AVCCodecHandler(desc); break; case AP4_SAMPLE_FORMAT_HEV1: case AP4_SAMPLE_FORMAT_HVC1: case AP4_SAMPLE_FORMAT_DVHE: case AP4_SAMPLE_FORMAT_DVH1: - m_codecHandler = new HEVCCodecHandler(desc, isRequiredAnnexB); + m_codecHandler = new HEVCCodecHandler(desc); break; case AP4_SAMPLE_FORMAT_STPP: m_codecHandler = new TTMLCodecHandler(desc, false);