From a588a0138a32adce3c2341a319862156e869ede8 Mon Sep 17 00:00:00 2001 From: David Guglielmi Date: Tue, 26 Sep 2023 22:05:52 +0200 Subject: [PATCH] media-tv/kodi: fix crash with pvr.hts --- media-tv/kodi/Manifest | 5 +- ...-FFmpeg-extradata-in-dedicated-class.patch | 1122 +++++++++++++++++ ...h-in-avcodec_parameters_from_context.patch | 36 + ...tom-destructor-for-AVCodecParameters.patch | 55 + ...odi-20.2-r1.ebuild => kodi-20.2-r2.ebuild} | 2 + 5 files changed, 1219 insertions(+), 1 deletion(-) create mode 100644 media-tv/kodi/files/kodi-20.2-Handle-FFmpeg-extradata-in-dedicated-class.patch create mode 100644 media-tv/kodi/files/kodi-20.2-fix-crash-in-avcodec_parameters_from_context.patch create mode 100644 media-tv/kodi/files/kodi-20.2-smart_ptr-and-custom-destructor-for-AVCodecParameters.patch rename media-tv/kodi/{kodi-20.2-r1.ebuild => kodi-20.2-r2.ebuild} (98%) diff --git a/media-tv/kodi/Manifest b/media-tv/kodi/Manifest index b80bbb7..d4adf7a 100644 --- a/media-tv/kodi/Manifest +++ b/media-tv/kodi/Manifest @@ -1,10 +1,13 @@ AUX kodi-20.2-Fix-playback-of-optical-dvds-without-mount-support.patch 2322 BLAKE2B 6064117e9995de379859fed4e8c27a0c233a5ff5e15cc586d9852691493f3bf230fb564512dc40db16ff4e61f7c8907b741a36fb8bcd0493159ba7f0af4e2c06 SHA512 eb855d05368d32582456261c7c98bfa6b5ddae8a74cac52d36c3bf54952e473b8b0254bf3fd9cac4943242a69cc039e42b02b09945cf9ca3ef654649ced6dcce +AUX kodi-20.2-Handle-FFmpeg-extradata-in-dedicated-class.patch 47068 BLAKE2B 2a2ebab22fe209b625122676e96c2c56aee96d3929b831b75b5ed98b4d6fbe65b471ba6dda15ce4eb217032fd5509716ba487ef59fca7e1b58f2e3ff2d4a1871 SHA512 b73f913b9383c01ef3bfe1b411c07cfb44ac51ea72565276db8007d90678db3e3a7a112a72bfa9a9bf2e8fdecdc1e52b02154f0d84aa3133e35244f3ba6cdce2 AUX kodi-20.2-VideoPlayerAudio-invalidate-previous-sync-type-after-Audio.patch 1010 BLAKE2B e623854a71f0b53b90950fbbf71ee4d666a24c3071c6ae8489d476a8407068e01028a69c8ec5cbff909a646dd15efe7a1807aeee214995ae1486281bce309e30 SHA512 3db461ebad0f922fab7727e902beada28b5b43e2b71d9c6e39bdf9b2a7767d214ea6caf3a975649a27ba77b7a9a93d5e7b1df6c1ec0edf61223855e2463d5115 AUX kodi-20.2-ffmpeg5.patch 94498 BLAKE2B f8244260911df037ec6cdf945fe19dae7e71e98c052c0ce3ec4c9bf5459205bef7696af599b00a86d5b554d0cbc674fed6f7835a45dd6df40ae4e83549e55175 SHA512 9dc21d7e41eac956816330e79e826456566a88c5fdc747be234fe873ff3b9e7241d87dcc6ecd804189fff8b61c027ac4e31e1af0da5de0537f91e8f51b3d96c5 AUX kodi-20.2-ffmpeg6.patch 24798 BLAKE2B d9ed0a7e8d0d873f46ffe95e84eefb94ca4f5328da80a447acd3996971b3b913a2ce249ddf8b5c4019db58e5fdb158b2c5d1034cd3962c8ca6d6aab34e9c6f15 SHA512 3e419a882a112bc9c12078f9c8f8c31c6eb5546f12e71e558f31a862ac8119999aa1e63c8e42cc654361534024e0483288da3bec62a45c601ecf7694c04a66c2 +AUX kodi-20.2-fix-crash-in-avcodec_parameters_from_context.patch 1351 BLAKE2B 0c1739fbda97c0e5a8064c0242a2d1d2e5db499bf336abc8d0119398aef156128a114f1f8616cee235f09e39752df156d99f3049fd2f13693246526593c5e08f SHA512 34da97b3803b585f90f2e5fced64bc0c7447c36df73384df29f539348bc8d230bbb9fcdfa7a12baf2794d0d0e1493248723e012ebe3ac0862e1d4add06f64b94 +AUX kodi-20.2-smart_ptr-and-custom-destructor-for-AVCodecParameters.patch 2113 BLAKE2B 4e6e3401c8b25297f633ff88457eda364de639e915b210d71a5905877c309bc81cf7d6e748307e76e8b9badca76024e313e7d32d88bba626642d4daa91e63357 SHA512 2b1a50e6f7f5eec62f2dc13cf3afb126cb0a05a5db7c87a5dfc9a4962b45c93c12ea71cb77fa007b4fab2a98109c08b1890a78cc5a85c99b658ac7e9648d0bcd DIST ffmpeg-kodi-5.1.2-Nexus-Alpha3.tar.gz 14416966 BLAKE2B fe35ef6a9aa2d60a2b34432ae8063850003d550208f223ea43af8ebcaa73e6993639e8cfe8a38676bac79e6b1816bd791b75b66ef58ff4d740bc9a5e0e7f9b78 SHA512 ce60852b8456d6f4bfc60de0ceadb33034d9b3eea8c0bc84d8b7199984ecbf334a2c4d9b42eade439d0ef30ce22e3b2ca0a49d4df837a18cd3136b4343ed3113 DIST kodi-20.2-Nexus.tar.gz 54587775 BLAKE2B 05c90cf9559f1e98c58deb5edd51c91d8ce60f75f13669e33c7168913870d13ca0ef68615834d9a6dd47c8f563ed591c1d43ec70e579938fb2f3251725538842 SHA512 ddeaa626f324817f6d038fd1eaeb851d0006156fa9ef96ef475932ec50c64cbdcc7ce8b93ceea0d8bfcd1f24edc1c9d0c4a97a163a615842a9fb698e5393f7ca DIST libdvdcss-1.4.3-Next-Nexus-Alpha2-2.tar.gz 102124 BLAKE2B 2f503d3ab767094958f7ec10b4ad11ffd02665deee571c8f3c739bef5fc7e2ff84babc5a3fdee638dc095f896b72fe3ce65e6b688674cb5f7b7b77190992688c SHA512 d3be3bfc13c5ea56d8db745c2aab090c99760684fe4c8f62a13d266feb319e9180ceeecf8116bfd2ed90d9accba2c11dbbf93b61ad00f69a40812ebf4eabcdda DIST libdvdnav-6.1.1-Next-Nexus-Alpha2-2.tar.gz 128547 BLAKE2B db4d05836d8fbb3637ae50bdbfc0e4b612ee6b3be24addfea94ce772c3bf28d58b63a3f252d6f9f016f72f8cbb841cc1820b091226b136f4c4664385a32da73c SHA512 51e6fc033121241354a5f0b3fc9a430577ae3ff6bb7f31445aa548ef4893037fb80eea3b2c6774c81e9ebaf9c45e9b490c98c2c65eb38f9f7daba84b236f7e1d DIST libdvdread-6.1.3-Next-Nexus-Alpha2-2.tar.gz 110513 BLAKE2B c94feb5a03a12efa5b7767965118d2500a088299ea36f3b82e46d157e45893e6b04503cb50f179ca681bac914457607fab26acfa6e304752b355c407578572d1 SHA512 629a41157d07b8ec0ea1fe89ae5ec48f63047472a862782b805c531ae31a0376fc4dc15175f8280c3ef91d7fa977bacebb1b51232640034a34bab2293210fc5e -EBUILD kodi-20.2-r1.ebuild 10972 BLAKE2B 136660a011e9a98b38cc2f0753a36acdd501cac0d0748cd1d77785b39b918f8756525289d2fcee5bc3d7d4e7ae2fc8696727e948c8cc0d007de31a197ad9d9e8 SHA512 0976494912c9c1050160fff44a415dcdde47cddc50dc77146a2b45155749f4c3a7c208cf926bcf898ded50862b7a630ce81dcaefb1201f69e5c8a1d78599e0dd +EBUILD kodi-20.2-r2.ebuild 11123 BLAKE2B 734f643818c5bfdbfa2149511f20e688b58e00bfe38ee3a23b0117cfefdf360663531edc938baeffb97df27f316c7e85f4edf8ab625467d0252eb912cfc1bf1c SHA512 d6cf0030183a193d7ca4e4303b6a71b6378679c59fb1144f86e65cd6ef925524e3fa59385312e7fd7d625a4781c426334ecfa65ee16e75250bb64791d4cb9528 diff --git a/media-tv/kodi/files/kodi-20.2-Handle-FFmpeg-extradata-in-dedicated-class.patch b/media-tv/kodi/files/kodi-20.2-Handle-FFmpeg-extradata-in-dedicated-class.patch new file mode 100644 index 0000000..1f464ff --- /dev/null +++ b/media-tv/kodi/files/kodi-20.2-Handle-FFmpeg-extradata-in-dedicated-class.patch @@ -0,0 +1,1122 @@ +From e5922ff2197c5276c7a38891c395a1297da03a96 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Markus=20H=C3=A4rer?= +Date: Sat, 22 Apr 2023 00:21:09 +0200 +Subject: [PATCH] FFmpeg: Handle FFmpeg extradata in dedicated class + +This ensures that everything is allocated with av_malloc and freed with +av_free. The padding is also handled consistently. And as a bonus it's more +ergonomic than handling the raw data. +--- + xbmc/cores/FFmpeg.cpp | 105 ++++++++++++++---- + xbmc/cores/FFmpeg.h | 30 ++++- + .../Audio/DVDAudioCodecAndroidMediaCodec.cpp | 10 +- + .../DVDCodecs/Audio/DVDAudioCodecFFmpeg.cpp | 9 +- + .../Overlay/DVDOverlayCodecFFmpeg.cpp | 13 ++- + .../DVDCodecs/Overlay/DVDOverlayCodecSSA.cpp | 3 +- + .../DVDCodecs/Overlay/OverlayCodecWebVTT.cpp | 3 +- + .../DVDCodecs/Video/AddonVideoCodec.cpp | 4 +- + .../Video/DVDVideoCodecAndroidMediaCodec.cpp | 52 ++++----- + .../DVDCodecs/Video/DVDVideoCodecDRMPRIME.cpp | 11 +- + .../DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp | 12 +- + .../DVDCodecs/Video/DVDVideoCodecStarfish.cpp | 10 +- + xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemux.h | 5 +- + .../DVDDemuxers/DVDDemuxClient.cpp | 36 ++---- + .../DVDDemuxers/DVDDemuxFFmpeg.cpp | 17 ++- + .../DVDDemuxers/DVDDemuxVobsub.cpp | 5 +- + .../DVDInputStreams/InputStreamAddon.cpp | 5 +- + .../DVDInputStreams/InputStreamPVRBase.cpp | 11 +- + xbmc/cores/VideoPlayer/DVDStreamInfo.cpp | 59 ++++------ + xbmc/cores/VideoPlayer/DVDStreamInfo.h | 3 +- + xbmc/cores/VideoPlayer/VideoPlayerVideo.cpp | 2 +- + xbmc/utils/BitstreamConverter.cpp | 51 ++++----- + xbmc/utils/BitstreamConverter.h | 8 +- + 23 files changed, 261 insertions(+), 203 deletions(-) + +diff --git a/xbmc/cores/FFmpeg.cpp b/xbmc/cores/FFmpeg.cpp +index 73b7ea2ae875c..67dbaedaf92a3 100644 +--- a/xbmc/cores/FFmpeg.cpp ++++ b/xbmc/cores/FFmpeg.cpp +@@ -135,15 +135,78 @@ void ff_avutil_log(void* ptr, int level, const char* format, va_list va) + buffer.erase(0, start); + } + +-std::tuple GetPacketExtradata(const AVPacket* pkt, const AVCodecParameters* codecPar) ++FFmpegExtraData::FFmpegExtraData(size_t size) ++ : m_data(reinterpret_cast(av_malloc(size + AV_INPUT_BUFFER_PADDING_SIZE))), m_size(size) ++{ ++ if (!m_data) ++ throw std::bad_alloc(); ++} ++ ++FFmpegExtraData::FFmpegExtraData(const uint8_t* data, size_t size) : FFmpegExtraData(size) ++{ ++ std::memcpy(m_data, data, size); ++} ++ ++FFmpegExtraData::~FFmpegExtraData() ++{ ++ av_free(m_data); ++} ++ ++FFmpegExtraData::FFmpegExtraData(const FFmpegExtraData& e) : FFmpegExtraData(e.m_size) ++{ ++ std::memcpy(m_data, e.m_data, m_size); ++} ++ ++FFmpegExtraData::FFmpegExtraData(FFmpegExtraData&& other) noexcept : FFmpegExtraData() ++{ ++ std::swap(m_data, other.m_data); ++ std::swap(m_size, other.m_size); ++} ++ ++FFmpegExtraData& FFmpegExtraData::operator=(const FFmpegExtraData& other) ++{ ++ if (this != &other) ++ { ++ if (m_size >= other.m_size) // reuse current buffer if large enough ++ { ++ std::memcpy(m_data, other.m_data, other.m_size); ++ m_size = other.m_size; ++ } ++ else ++ { ++ FFmpegExtraData extraData(other); ++ *this = std::move(extraData); ++ } ++ } ++ return *this; ++} ++ ++FFmpegExtraData& FFmpegExtraData::operator=(FFmpegExtraData&& other) noexcept ++{ ++ if (this != &other) ++ { ++ std::swap(m_data, other.m_data); ++ std::swap(m_size, other.m_size); ++ } ++ return *this; ++} ++ ++bool FFmpegExtraData::operator==(const FFmpegExtraData& other) const ++{ ++ return m_size == other.m_size && std::memcmp(m_data, other.m_data, m_size) == 0; ++} ++ ++bool FFmpegExtraData::operator!=(const FFmpegExtraData& other) const ++{ ++ return !(*this == other); ++} ++ ++FFmpegExtraData GetPacketExtradata(const AVPacket* pkt, const AVCodecParameters* codecPar) + { + constexpr int FF_MAX_EXTRADATA_SIZE = ((1 << 28) - AV_INPUT_BUFFER_PADDING_SIZE); + + if (!pkt) +- return std::make_tuple(nullptr, 0); +- +- uint8_t* extraData = nullptr; +- int extraDataSize = 0; ++ return {}; + + /* extract_extradata bitstream filter is implemented only + * for certain codecs, as noted in discussion of PR#21248 +@@ -165,29 +228,29 @@ std::tuple GetPacketExtradata(const AVPacket* pkt, const AVCodecP + codecId != AV_CODEC_ID_CAVS + ) + // clang-format on +- return std::make_tuple(nullptr, 0); ++ return {}; + + const AVBitStreamFilter* f = av_bsf_get_by_name("extract_extradata"); + if (!f) +- return std::make_tuple(nullptr, 0); ++ return {}; + + AVBSFContext* bsf = nullptr; + int ret = av_bsf_alloc(f, &bsf); + if (ret < 0) +- return std::make_tuple(nullptr, 0); ++ return {}; + + ret = avcodec_parameters_copy(bsf->par_in, codecPar); + if (ret < 0) + { + av_bsf_free(&bsf); +- return std::make_tuple(nullptr, 0); ++ return {}; + } + + ret = av_bsf_init(bsf); + if (ret < 0) + { + av_bsf_free(&bsf); +- return std::make_tuple(nullptr, 0); ++ return {}; + } + + AVPacket* dstPkt = av_packet_alloc(); +@@ -196,7 +259,7 @@ std::tuple GetPacketExtradata(const AVPacket* pkt, const AVCodecP + CLog::LogF(LOGERROR, "failed to allocate packet"); + + av_bsf_free(&bsf); +- return std::make_tuple(nullptr, 0); ++ return {}; + } + AVPacket* pktRef = dstPkt; + +@@ -205,7 +268,7 @@ std::tuple GetPacketExtradata(const AVPacket* pkt, const AVCodecP + { + av_bsf_free(&bsf); + av_packet_free(&dstPkt); +- return std::make_tuple(nullptr, 0); ++ return {}; + } + + ret = av_bsf_send_packet(bsf, pktRef); +@@ -214,9 +277,10 @@ std::tuple GetPacketExtradata(const AVPacket* pkt, const AVCodecP + av_packet_unref(pktRef); + av_bsf_free(&bsf); + av_packet_free(&dstPkt); +- return std::make_tuple(nullptr, 0); ++ return {}; + } + ++ FFmpegExtraData extraData; + ret = 0; + while (ret >= 0) + { +@@ -234,23 +298,22 @@ std::tuple GetPacketExtradata(const AVPacket* pkt, const AVCodecP + av_packet_get_side_data(pktRef, AV_PKT_DATA_NEW_EXTRADATA, &retExtraDataSize); + if (retExtraData && retExtraDataSize > 0 && retExtraDataSize < FF_MAX_EXTRADATA_SIZE) + { +- extraData = static_cast(av_malloc(retExtraDataSize + AV_INPUT_BUFFER_PADDING_SIZE)); +- if (!extraData) ++ try ++ { ++ extraData = FFmpegExtraData(retExtraData, retExtraDataSize); ++ } ++ catch (const std::bad_alloc&) + { + CLog::LogF(LOGERROR, "failed to allocate {} bytes for extradata", retExtraDataSize); + + av_packet_unref(pktRef); + av_bsf_free(&bsf); + av_packet_free(&dstPkt); +- return std::make_tuple(nullptr, 0); ++ return {}; + } + + CLog::LogF(LOGDEBUG, "fetching extradata, extradata_size({})", retExtraDataSize); + +- memcpy(extraData, retExtraData, retExtraDataSize); +- memset(extraData + retExtraDataSize, 0, AV_INPUT_BUFFER_PADDING_SIZE); +- extraDataSize = retExtraDataSize; +- + av_packet_unref(pktRef); + break; + } +@@ -261,5 +324,5 @@ std::tuple GetPacketExtradata(const AVPacket* pkt, const AVCodecP + av_bsf_free(&bsf); + av_packet_free(&dstPkt); + +- return std::make_tuple(extraData, extraDataSize); ++ return extraData; + } +diff --git a/xbmc/cores/FFmpeg.h b/xbmc/cores/FFmpeg.h +index 5e35d58c6b0a6..9f99389a2c3e3 100644 +--- a/xbmc/cores/FFmpeg.h ++++ b/xbmc/cores/FFmpeg.h +@@ -72,5 +72,31 @@ class CFFmpegLog + int level; + }; + +-std::tuple GetPacketExtradata(const AVPacket* pkt, +- const AVCodecParameters* codecPar); ++class FFmpegExtraData ++{ ++public: ++ FFmpegExtraData() = default; ++ explicit FFmpegExtraData(size_t size); ++ FFmpegExtraData(const uint8_t* data, size_t size); ++ FFmpegExtraData(const FFmpegExtraData& other); ++ FFmpegExtraData(FFmpegExtraData&& other) noexcept; ++ ++ ~FFmpegExtraData(); ++ ++ FFmpegExtraData& operator=(const FFmpegExtraData& other); ++ FFmpegExtraData& operator=(FFmpegExtraData&& other) noexcept; ++ ++ bool operator==(const FFmpegExtraData& other) const; ++ bool operator!=(const FFmpegExtraData& other) const; ++ ++ operator bool() const { return m_data != nullptr && m_size != 0; } ++ uint8_t* GetData() { return m_data; } ++ const uint8_t* GetData() const { return m_data; } ++ size_t GetSize() const { return m_size; } ++ ++private: ++ uint8_t* m_data{nullptr}; ++ size_t m_size{}; ++}; ++ ++FFmpegExtraData GetPacketExtradata(const AVPacket* pkt, const AVCodecParameters* codecPar); +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Audio/DVDAudioCodecAndroidMediaCodec.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Audio/DVDAudioCodecAndroidMediaCodec.cpp +index 5c2ee81af8be3..30aca1c8d3de6 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Audio/DVDAudioCodecAndroidMediaCodec.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Audio/DVDAudioCodecAndroidMediaCodec.cpp +@@ -109,7 +109,7 @@ bool CDVDAudioCodecAndroidMediaCodec::Open(CDVDStreamInfo &hints, CDVDCodecOptio + + CLog::Log(LOGDEBUG, + "CDVDAudioCodecAndroidMediaCodec::Open codec({}), profile({}), tag({}), extrasize({})", +- hints.codec, hints.profile, hints.codec_tag, hints.extrasize); ++ hints.codec, hints.profile, hints.codec_tag, hints.extradata.GetSize()); + + // First check if passthrough decoder is supported + CAEStreamInfo::DataType ptStreamType = CAEStreamInfo::STREAM_TYPE_NULL; +@@ -132,7 +132,7 @@ bool CDVDAudioCodecAndroidMediaCodec::Open(CDVDStreamInfo &hints, CDVDCodecOptio + { + case AV_CODEC_ID_AAC: + case AV_CODEC_ID_AAC_LATM: +- if (!m_hints.extrasize) ++ if (!m_hints.extradata) + { + CLog::Log(LOGINFO, "CDVDAudioCodecAndroidMediaCodec: extradata required for aac decoder!"); + return false; +@@ -529,10 +529,10 @@ bool CDVDAudioCodecAndroidMediaCodec::ConfigureMediaCodec(void) + if (!m_decryptCodec) + { + // handle codec extradata +- if (m_hints.extrasize) ++ if (m_hints.extradata) + { +- size_t size = m_hints.extrasize; +- void *src_ptr = m_hints.extradata; ++ size_t size = m_hints.extradata.GetSize(); ++ void* src_ptr = m_hints.extradata.GetData(); + // Allocate a byte buffer via allocateDirect in java instead of NewDirectByteBuffer, + // since the latter doesn't allocate storage of its own, and we don't know how long + // the codec uses the buffer. +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Audio/DVDAudioCodecFFmpeg.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Audio/DVDAudioCodecFFmpeg.cpp +index d1fb2cfe96afc..cbc806030dc19 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Audio/DVDAudioCodecFFmpeg.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Audio/DVDAudioCodecFFmpeg.cpp +@@ -103,13 +103,14 @@ bool CDVDAudioCodecFFmpeg::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options + if(m_pCodecContext->bits_per_coded_sample == 0) + m_pCodecContext->bits_per_coded_sample = 16; + +- if( hints.extradata && hints.extrasize > 0 ) ++ if (hints.extradata) + { +- m_pCodecContext->extradata = (uint8_t*)av_mallocz(hints.extrasize + AV_INPUT_BUFFER_PADDING_SIZE); ++ m_pCodecContext->extradata = ++ (uint8_t*)av_mallocz(hints.extradata.GetSize() + AV_INPUT_BUFFER_PADDING_SIZE); + if(m_pCodecContext->extradata) + { +- m_pCodecContext->extradata_size = hints.extrasize; +- memcpy(m_pCodecContext->extradata, hints.extradata, hints.extrasize); ++ m_pCodecContext->extradata_size = hints.extradata.GetSize(); ++ memcpy(m_pCodecContext->extradata, hints.extradata.GetData(), hints.extradata.GetSize()); + } + } + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Overlay/DVDOverlayCodecFFmpeg.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Overlay/DVDOverlayCodecFFmpeg.cpp +index 5c74c50229d83..3eb85be4eec7d 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Overlay/DVDOverlayCodecFFmpeg.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Overlay/DVDOverlayCodecFFmpeg.cpp +@@ -60,16 +60,17 @@ bool CDVDOverlayCodecFFmpeg::Open(CDVDStreamInfo &hints, CDVDCodecOptions &optio + m_pCodecContext->pkt_timebase.num = 1; + m_pCodecContext->pkt_timebase.den = DVD_TIME_BASE; + +- if( hints.extradata && hints.extrasize > 0 ) ++ if (hints.extradata) + { +- m_pCodecContext->extradata_size = hints.extrasize; +- m_pCodecContext->extradata = (uint8_t*)av_mallocz(hints.extrasize + AV_INPUT_BUFFER_PADDING_SIZE); +- memcpy(m_pCodecContext->extradata, hints.extradata, hints.extrasize); ++ m_pCodecContext->extradata_size = hints.extradata.GetSize(); ++ m_pCodecContext->extradata = ++ (uint8_t*)av_mallocz(hints.extradata.GetSize() + AV_INPUT_BUFFER_PADDING_SIZE); ++ memcpy(m_pCodecContext->extradata, hints.extradata.GetData(), hints.extradata.GetSize()); + + // start parsing of extra data - create a copy to be safe and make it zero-terminating to avoid access violations! +- unsigned int parse_extrasize = hints.extrasize; ++ unsigned int parse_extrasize = hints.extradata.GetSize(); + char* parse_extra = new char[parse_extrasize + 1]; +- memcpy(parse_extra, hints.extradata, parse_extrasize); ++ memcpy(parse_extra, hints.extradata.GetData(), parse_extrasize); + parse_extra[parse_extrasize] = '\0'; + + // assume that the extra data is formatted as a concatenation of lines ('\n' terminated) +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Overlay/DVDOverlayCodecSSA.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Overlay/DVDOverlayCodecSSA.cpp +index 82c1c76dd5564..33e0c7bcc83d4 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Overlay/DVDOverlayCodecSSA.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Overlay/DVDOverlayCodecSSA.cpp +@@ -38,7 +38,8 @@ bool CDVDOverlayCodecSSA::Open(CDVDStreamInfo& hints, CDVDCodecOptions& options) + + m_pOverlay.reset(); + +- return m_libass->DecodeHeader(static_cast(hints.extradata), hints.extrasize); ++ return m_libass->DecodeHeader(reinterpret_cast(hints.extradata.GetData()), ++ hints.extradata.GetSize()); + } + + OverlayMessage CDVDOverlayCodecSSA::Decode(DemuxPacket* pPacket) +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Overlay/OverlayCodecWebVTT.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Overlay/OverlayCodecWebVTT.cpp +index e33ab1dad503e..d1c03af8d4851 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Overlay/OverlayCodecWebVTT.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Overlay/OverlayCodecWebVTT.cpp +@@ -39,7 +39,8 @@ bool COverlayCodecWebVTT::Open(CDVDStreamInfo& hints, CDVDCodecOptions& options) + // Extradata can be provided by Inputstream addons (e.g. inputstream.adaptive) + if (hints.extradata) + { +- std::string extradata{static_cast(hints.extradata), hints.extrasize}; ++ std::string extradata{reinterpret_cast(hints.extradata.GetData()), ++ hints.extradata.GetSize()}; + if (extradata == "file") + { + // WebVTT data like single file are sent one time only, +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AddonVideoCodec.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AddonVideoCodec.cpp +index 07b2d1b3ccf8d..daf64ea67ac43 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AddonVideoCodec.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AddonVideoCodec.cpp +@@ -231,8 +231,8 @@ bool CAddonVideoCodec::CopyToInitData(VIDEOCODEC_INITDATA &initData, CDVDStreamI + sizeof(initData.cryptoSession.sessionId) - 1); + } + +- initData.extraData = reinterpret_cast(hints.extradata); +- initData.extraDataSize = hints.extrasize; ++ initData.extraData = hints.extradata.GetData(); ++ initData.extraDataSize = hints.extradata.GetSize(); + initData.width = hints.width; + initData.height = hints.height; + initData.videoFormats = m_formats; +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAndroidMediaCodec.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAndroidMediaCodec.cpp +index ede663ebe917b..8cc2431498ad2 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAndroidMediaCodec.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAndroidMediaCodec.cpp +@@ -387,7 +387,7 @@ bool CDVDVideoCodecAndroidMediaCodec::Open(CDVDStreamInfo &hints, CDVDCodecOptio + "CDVDVideoCodecAndroidMediaCodec::Open hints: Width {} x Height {}, Fpsrate {} / Fpsscale " + "{}, CodecID {}, Level {}, Profile {}, PTS_invalid {}, Tag {}, Extradata-Size: {}", + hints.width, hints.height, hints.fpsrate, hints.fpsscale, hints.codec, hints.level, +- hints.profile, hints.ptsinvalid, hints.codec_tag, hints.extrasize); ++ hints.profile, hints.ptsinvalid, hints.codec_tag, hints.extradata.GetSize()); + + m_render_surface = CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(CSettings::SETTING_VIDEOPLAYER_USEMEDIACODECSURFACE); + m_state = MEDIACODEC_STATE_UNINITIALIZED; +@@ -447,9 +447,7 @@ bool CDVDVideoCodecAndroidMediaCodec::Open(CDVDStreamInfo &hints, CDVDCodecOptio + } + m_mime = "video/x-vnd.on2.vp9"; + m_formatname = "amc-vp9"; +- free(m_hints.extradata); +- m_hints.extradata = nullptr; +- m_hints.extrasize = 0; ++ m_hints.extradata = {}; + break; + case AV_CODEC_ID_AVS: + case AV_CODEC_ID_CAVS: +@@ -493,7 +491,8 @@ bool CDVDVideoCodecAndroidMediaCodec::Open(CDVDStreamInfo &hints, CDVDCodecOptio + if (m_hints.extradata && !m_hints.cryptoSession) + { + m_bitstream = std::make_unique(); +- if (!m_bitstream->Open(m_hints.codec, (uint8_t*)m_hints.extradata, m_hints.extrasize, true)) ++ if (!m_bitstream->Open(m_hints.codec, m_hints.extradata.GetData(), ++ m_hints.extradata.GetSize(), true)) + { + m_bitstream.reset(); + } +@@ -564,7 +563,8 @@ bool CDVDVideoCodecAndroidMediaCodec::Open(CDVDStreamInfo &hints, CDVDCodecOptio + if (m_hints.extradata && !m_hints.cryptoSession) + { + m_bitstream = std::make_unique(); +- if (!m_bitstream->Open(m_hints.codec, (uint8_t*)m_hints.extradata, m_hints.extrasize, true)) ++ if (!m_bitstream->Open(m_hints.codec, m_hints.extradata.GetData(), ++ m_hints.extradata.GetSize(), true)) + { + m_bitstream.reset(); + } +@@ -572,28 +572,26 @@ bool CDVDVideoCodecAndroidMediaCodec::Open(CDVDStreamInfo &hints, CDVDCodecOptio + break; + } + case AV_CODEC_ID_WMV3: +- if (m_hints.extrasize == 4 || m_hints.extrasize == 5) ++ if (m_hints.extradata.GetSize() == 4 || m_hints.extradata.GetSize() == 5) + { + // Convert to SMPTE 421M-2006 Annex-L + static uint8_t annexL_hdr1[] = {0x8e, 0x01, 0x00, 0xc5, 0x04, 0x00, 0x00, 0x00}; + static uint8_t annexL_hdr2[] = {0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +- free(m_hints.extradata); +- m_hints.extrasize = 36; +- m_hints.extradata = malloc(m_hints.extrasize); ++ m_hints.extradata = FFmpegExtraData(36); + + unsigned int offset = 0; + char buf[4]; +- memcpy(m_hints.extradata, annexL_hdr1, sizeof(annexL_hdr1)); ++ memcpy(m_hints.extradata.GetData(), annexL_hdr1, sizeof(annexL_hdr1)); + offset += sizeof(annexL_hdr1); +- memcpy(&((char *)(m_hints.extradata))[offset], hints.extradata, 4); ++ memcpy(m_hints.extradata.GetData() + offset, hints.extradata.GetData(), 4); + offset += 4; + BS_WL32(buf, hints.height); +- memcpy(&((char *)(m_hints.extradata))[offset], buf, 4); ++ memcpy(m_hints.extradata.GetData() + offset, buf, 4); + offset += 4; + BS_WL32(buf, hints.width); +- memcpy(&((char *)(m_hints.extradata))[offset], buf, 4); ++ memcpy(m_hints.extradata.GetData() + offset, buf, 4); + offset += 4; +- memcpy(&((char *)(m_hints.extradata))[offset], annexL_hdr2, sizeof(annexL_hdr2)); ++ memcpy(m_hints.extradata.GetData() + offset, annexL_hdr2, sizeof(annexL_hdr2)); + } + + m_mime = "video/x-ms-wmv"; +@@ -601,26 +599,24 @@ bool CDVDVideoCodecAndroidMediaCodec::Open(CDVDStreamInfo &hints, CDVDCodecOptio + break; + case AV_CODEC_ID_VC1: + { +- if (m_hints.extrasize < 16) ++ if (m_hints.extradata.GetSize() < 16) + goto FAIL; + + // Reduce extradata to first SEQ header + unsigned int seq_offset = 0; +- for (; seq_offset <= m_hints.extrasize-4; ++seq_offset) ++ for (; seq_offset <= m_hints.extradata.GetSize() - 4; ++seq_offset) + { +- char *ptr = &((char*)m_hints.extradata)[seq_offset]; ++ const uint8_t* ptr = m_hints.extradata.GetData() + seq_offset; + if (ptr[0] == 0x00 && ptr[1] == 0x00 && ptr[2] == 0x01 && ptr[3] == 0x0f) + break; + } +- if (seq_offset > m_hints.extrasize-4) ++ if (seq_offset > m_hints.extradata.GetSize() - 4) + goto FAIL; + + if (seq_offset) + { +- free(m_hints.extradata); +- m_hints.extrasize -= seq_offset; +- m_hints.extradata = malloc(m_hints.extrasize); +- memcpy(m_hints.extradata, &((char *)(hints.extradata))[seq_offset], m_hints.extrasize); ++ hints.extradata = FFmpegExtraData(hints.extradata.GetData() + seq_offset, ++ hints.extradata.GetSize() - seq_offset); + } + + m_mime = "video/wvc1"; +@@ -643,9 +639,7 @@ bool CDVDVideoCodecAndroidMediaCodec::Open(CDVDStreamInfo &hints, CDVDCodecOptio + } + m_mime = "video/av01"; + m_formatname = "amc-av1"; +- free(m_hints.extradata); +- m_hints.extradata = nullptr; +- m_hints.extrasize = 0; ++ m_hints.extradata = {}; + break; + } + default: +@@ -1314,12 +1308,12 @@ void CDVDVideoCodecAndroidMediaCodec::SignalEndOfStream() + + void CDVDVideoCodecAndroidMediaCodec::InjectExtraData(CJNIMediaFormat& mediaformat) + { +- if (!m_hints.extrasize) ++ if (!m_hints.extradata) + return; + + CLog::Log(LOGDEBUG, "CDVDVideoCodecAndroidMediaCodec::{}", __func__); +- size_t size = m_hints.extrasize; +- void* src_ptr = m_hints.extradata; ++ size_t size = m_hints.extradata.GetSize(); ++ void* src_ptr = m_hints.extradata.GetData(); + if (m_bitstream) + { + size = m_bitstream->GetExtraSize(); +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.cpp +index ab65c4ecd44aa..eb2943bb8ccb9 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.cpp +@@ -351,12 +351,15 @@ bool CDVDVideoCodecDRMPRIME::Open(CDVDStreamInfo& hints, CDVDCodecOptions& optio + m_pCodecContext->time_base.den = DVD_TIME_BASE; + m_pCodecContext->thread_count = CServiceBroker::GetCPUInfo()->GetCPUCount(); + +- if (hints.extradata && hints.extrasize > 0) ++ if (hints.extradata) + { +- m_pCodecContext->extradata_size = hints.extrasize; + m_pCodecContext->extradata = +- static_cast(av_mallocz(hints.extrasize + AV_INPUT_BUFFER_PADDING_SIZE)); +- memcpy(m_pCodecContext->extradata, hints.extradata, hints.extrasize); ++ static_cast(av_mallocz(hints.extradata.GetSize() + AV_INPUT_BUFFER_PADDING_SIZE)); ++ if (m_pCodecContext->extradata) ++ { ++ m_pCodecContext->extradata_size = hints.extradata.GetSize(); ++ memcpy(m_pCodecContext->extradata, hints.extradata.GetData(), hints.extradata.GetSize()); ++ } + } + + for (auto&& option : options.m_keys) +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp +index c775281791719..032ee16454492 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp +@@ -400,11 +400,15 @@ bool CDVDVideoCodecFFmpeg::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options + m_pCodecContext->bits_per_coded_sample = hints.bitsperpixel; + m_pCodecContext->bits_per_raw_sample = hints.bitdepth; + +- if( hints.extradata && hints.extrasize > 0 ) ++ if (hints.extradata) + { +- m_pCodecContext->extradata_size = hints.extrasize; +- m_pCodecContext->extradata = (uint8_t*)av_mallocz(hints.extrasize + AV_INPUT_BUFFER_PADDING_SIZE); +- memcpy(m_pCodecContext->extradata, hints.extradata, hints.extrasize); ++ m_pCodecContext->extradata = ++ (uint8_t*)av_mallocz(hints.extradata.GetSize() + AV_INPUT_BUFFER_PADDING_SIZE); ++ if (m_pCodecContext->extradata) ++ { ++ m_pCodecContext->extradata_size = hints.extradata.GetSize(); ++ memcpy(m_pCodecContext->extradata, hints.extradata.GetData(), hints.extradata.GetSize()); ++ } + } + + // advanced setting override for skip loop filter (see avcodec.h for valid options) +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecStarfish.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecStarfish.cpp +index fcdc441205958..dbf91ea5a54dd 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecStarfish.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecStarfish.cpp +@@ -93,7 +93,7 @@ bool CDVDVideoCodecStarfish::OpenInternal(CDVDStreamInfo& hints, CDVDCodecOption + "CDVDVideoCodecStarfish: hints: Width {} x Height {}, Fpsrate {} / Fpsscale {}, " + "CodecID {}, Level {}, Profile {}, PTS_invalid {}, Tag {}, Extradata-Size: {}", + hints.width, hints.height, hints.fpsrate, hints.fpsscale, hints.codec, hints.level, +- hints.profile, hints.ptsinvalid, hints.codec_tag, hints.extrasize); ++ hints.profile, hints.ptsinvalid, hints.codec_tag, hints.extradata.GetSize()); + + if (ms_codecMap.find(hints.codec) == ms_codecMap.cend() || + ms_formatInfoMap.find(hints.codec) == ms_formatInfoMap.cend()) +@@ -115,8 +115,8 @@ bool CDVDVideoCodecStarfish::OpenInternal(CDVDStreamInfo& hints, CDVDCodecOption + if (m_hints.extradata && !m_hints.cryptoSession) + { + m_bitstream = std::make_unique(); +- if (!m_bitstream->Open(m_hints.codec, reinterpret_cast(m_hints.extradata), +- m_hints.extrasize, true)) ++ if (!m_bitstream->Open(m_hints.codec, m_hints.extradata.GetData(), ++ m_hints.extradata.GetSize(), true)) + { + m_bitstream.reset(); + } +@@ -153,8 +153,8 @@ bool CDVDVideoCodecStarfish::OpenInternal(CDVDStreamInfo& hints, CDVDCodecOption + if (m_hints.extradata && !m_hints.cryptoSession) + { + m_bitstream = std::make_unique(); +- if (!m_bitstream->Open(m_hints.codec, reinterpret_cast(m_hints.extradata), +- m_hints.extrasize, true)) ++ if (!m_bitstream->Open(m_hints.codec, m_hints.extradata.GetData(), ++ m_hints.extradata.GetSize(), true)) + { + m_bitstream.reset(); + } +diff --git a/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemux.h b/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemux.h +index aeb6839177e71..af5ff8e513dae 100644 +--- a/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemux.h ++++ b/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemux.h +@@ -9,6 +9,7 @@ + #pragma once + + #include "Interface/StreamInfo.h" ++#include "cores/FFmpeg.h" + + #include + #include +@@ -83,7 +84,6 @@ class CDemuxStream + source = STREAM_SOURCE_NONE; + iDuration = 0; + pPrivate = NULL; +- ExtraSize = 0; + disabled = false; + changes = 0; + flags = StreamFlags::FLAG_NONE; +@@ -106,8 +106,7 @@ class CDemuxStream + + int iDuration; // in mseconds + void* pPrivate; // private pointer for the demuxer +- std::unique_ptr ExtraData; // extra data for codec to use +- unsigned int ExtraSize; // size of extra data ++ FFmpegExtraData extraData; + + StreamFlags flags; + std::string language; // RFC 5646 language code (empty string if undefined) +diff --git a/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxClient.cpp b/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxClient.cpp +index 2a42244b62b68..e6986467fa8b8 100644 +--- a/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxClient.cpp ++++ b/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxClient.cpp +@@ -121,7 +121,7 @@ bool CDVDDemuxClient::ParsePacket(DemuxPacket* pkt) + bool change = false; + + CDemuxStream* st = GetStream(pkt->iStreamId); +- if (st == nullptr || st->changes < 0 || st->ExtraSize || !CodecHasExtraData(st->codec)) ++ if (st == nullptr || st->changes < 0 || st->extraData || !CodecHasExtraData(st->codec)) + return change; + + CDemuxStreamClientInternal* stream = dynamic_cast(st); +@@ -174,13 +174,12 @@ bool CDVDDemuxClient::ParsePacket(DemuxPacket* pkt) + return false; + } + +- auto [retExtraData, len] = GetPacketExtradata(avpkt, codecPar.get()); +- if (len > 0) ++ FFmpegExtraData retExtraData = GetPacketExtradata(avpkt, codecPar.get()); ++ if (retExtraData) + { + st->changes++; + st->disabled = false; +- st->ExtraSize = len; +- st->ExtraData = std::unique_ptr(retExtraData); ++ st->extraData = std::move(retExtraData); + stream->m_parser_split = false; + change = true; + CLog::Log(LOGDEBUG, "CDVDDemuxClient::ParsePacket - split extradata"); +@@ -444,12 +443,9 @@ void CDVDDemuxClient::SetStreamProps(CDemuxStream *stream, std::mapiBlockAlign = source->iBlockAlign; + streamAudio->iBitRate = source->iBitRate; + streamAudio->iBitsPerSample = source->iBitsPerSample; +- if (source->ExtraSize > 0 && source->ExtraData) ++ if (source->extraData) + { +- streamAudio->ExtraData = std::make_unique(source->ExtraSize); +- streamAudio->ExtraSize = source->ExtraSize; +- for (unsigned int j=0; jExtraSize; j++) +- streamAudio->ExtraData[j] = source->ExtraData[j]; ++ streamAudio->extraData = source->extraData; + } + streamAudio->m_parser_split = true; + streamAudio->changes++; +@@ -484,12 +480,9 @@ void CDVDDemuxClient::SetStreamProps(CDemuxStream *stream, std::mapiFpsRate = source->iFpsRate; + } + streamVideo->iBitRate = source->iBitRate; +- if (source->ExtraSize > 0 && source->ExtraData) ++ if (source->extraData) + { +- streamVideo->ExtraData = std::make_unique(source->ExtraSize); +- streamVideo->ExtraSize = source->ExtraSize; +- for (unsigned int j=0; jExtraSize; j++) +- streamVideo->ExtraData[j] = source->ExtraData[j]; ++ streamVideo->extraData = source->extraData; + } + streamVideo->colorPrimaries = source->colorPrimaries; + streamVideo->colorRange = source->colorRange; +@@ -526,12 +519,9 @@ void CDVDDemuxClient::SetStreamProps(CDemuxStream *stream, std::mapm_parser->flags |= PARSER_FLAG_COMPLETE_FRAMES; + } + +- if (source->ExtraSize == 4) ++ if (source->extraData.GetSize() == 4) + { +- streamSubtitle->ExtraData = std::make_unique(4); +- streamSubtitle->ExtraSize = 4; +- for (int j=0; j<4; j++) +- streamSubtitle->ExtraData[j] = source->ExtraData[j]; ++ streamSubtitle->extraData = source->extraData; + } + map[stream->uniqueId] = streamSubtitle; + toStream = streamSubtitle; +@@ -656,10 +646,8 @@ bool CDVDDemuxClient::IsVideoReady() + { + for (const auto& stream : m_streams) + { +- if (stream.first == m_videoStreamPlaying && +- stream.second->type == STREAM_VIDEO && +- CodecHasExtraData(stream.second->codec) && +- stream.second->ExtraData == nullptr) ++ if (stream.first == m_videoStreamPlaying && stream.second->type == STREAM_VIDEO && ++ CodecHasExtraData(stream.second->codec) && !stream.second->extraData) + return false; + } + return true; +diff --git a/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxFFmpeg.cpp b/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxFFmpeg.cpp +index 9e696cfc8ff8b..4847cdde2900a 100644 +--- a/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxFFmpeg.cpp ++++ b/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxFFmpeg.cpp +@@ -1881,10 +1881,8 @@ CDemuxStream* CDVDDemuxFFmpeg::AddStream(int streamIdx) + + if (stream->type != STREAM_NONE && pStream->codecpar->extradata && pStream->codecpar->extradata_size > 0) + { +- stream->ExtraSize = pStream->codecpar->extradata_size; +- stream->ExtraData = std::make_unique(pStream->codecpar->extradata_size); +- memcpy(stream->ExtraData.get(), pStream->codecpar->extradata, +- pStream->codecpar->extradata_size); ++ stream->extraData = ++ FFmpegExtraData(pStream->codecpar->extradata, pStream->codecpar->extradata_size); + } + + #ifdef HAVE_LIBBLURAY +@@ -2166,7 +2164,8 @@ bool CDVDDemuxFFmpeg::IsProgramChange() + return true; + } + } +- if (m_pFormatContext->streams[idx]->codecpar->extradata_size != static_cast(stream->ExtraSize)) ++ if (m_pFormatContext->streams[idx]->codecpar->extradata_size != ++ static_cast(stream->extraData.GetSize())) + return true; + } + return false; +@@ -2299,11 +2298,11 @@ void CDVDDemuxFFmpeg::ParsePacket(AVPacket* pkt) + parser->second->m_parserCtx->parser && + !st->codecpar->extradata) + { +- auto [retExtraData, i] = GetPacketExtradata(pkt, st->codecpar); +- if (i > 0) ++ FFmpegExtraData retExtraData = GetPacketExtradata(pkt, st->codecpar); ++ if (retExtraData) + { +- st->codecpar->extradata_size = i; +- st->codecpar->extradata = retExtraData; ++ st->codecpar->extradata_size = retExtraData.GetSize(); ++ st->codecpar->extradata = retExtraData.GetData(); + + if (parser->second->m_parserCtx->parser->parser_parse) + { +diff --git a/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxVobsub.cpp b/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxVobsub.cpp +index 5c7ef1bb907c7..ba02a306e5489 100644 +--- a/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxVobsub.cpp ++++ b/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxVobsub.cpp +@@ -113,9 +113,8 @@ bool CDVDDemuxVobsub::Open(const std::string& filename, int source, const std::s + + for(unsigned i=0;iExtraSize = state.extra.length()+1; +- m_Streams[i]->ExtraData = std::make_unique(m_Streams[i]->ExtraSize); +- strcpy((char*)m_Streams[i]->ExtraData.get(), state.extra.c_str()); ++ m_Streams[i]->extraData = ++ FFmpegExtraData(reinterpret_cast(state.extra.data()), state.extra.length() + 1); + } + + return true; +diff --git a/xbmc/cores/VideoPlayer/DVDInputStreams/InputStreamAddon.cpp b/xbmc/cores/VideoPlayer/DVDInputStreams/InputStreamAddon.cpp +index 2ca5d01b2b053..f5bfe16264b2a 100644 +--- a/xbmc/cores/VideoPlayer/DVDInputStreams/InputStreamAddon.cpp ++++ b/xbmc/cores/VideoPlayer/DVDInputStreams/InputStreamAddon.cpp +@@ -531,10 +531,7 @@ KODI_HANDLE CInputStreamAddon::cb_get_stream_transfer(KODI_HANDLE handle, + + if (stream->m_ExtraData && stream->m_ExtraSize) + { +- demuxStream->ExtraData = std::make_unique(stream->m_ExtraSize); +- demuxStream->ExtraSize = stream->m_ExtraSize; +- for (unsigned int j = 0; j < stream->m_ExtraSize; ++j) +- demuxStream->ExtraData[j] = stream->m_ExtraData[j]; ++ demuxStream->extraData = FFmpegExtraData(stream->m_ExtraData, stream->m_ExtraSize); + } + + if (stream->m_cryptoSession.keySystem != STREAM_CRYPTO_KEY_SYSTEM_NONE && +diff --git a/xbmc/cores/VideoPlayer/DVDInputStreams/InputStreamPVRBase.cpp b/xbmc/cores/VideoPlayer/DVDInputStreams/InputStreamPVRBase.cpp +index 03c4bf4de7412..00199b6503e2f 100644 +--- a/xbmc/cores/VideoPlayer/DVDInputStreams/InputStreamPVRBase.cpp ++++ b/xbmc/cores/VideoPlayer/DVDInputStreams/InputStreamPVRBase.cpp +@@ -322,12 +322,11 @@ void CInputStreamPVRBase::UpdateStreamMap() + + if (stream.iSubtitleInfo) + { +- streamSubtitle->ExtraData = std::make_unique(4); +- streamSubtitle->ExtraSize = 4; +- streamSubtitle->ExtraData[0] = (stream.iSubtitleInfo >> 8) & 0xff; +- streamSubtitle->ExtraData[1] = (stream.iSubtitleInfo >> 0) & 0xff; +- streamSubtitle->ExtraData[2] = (stream.iSubtitleInfo >> 24) & 0xff; +- streamSubtitle->ExtraData[3] = (stream.iSubtitleInfo >> 16) & 0xff; ++ streamSubtitle->extraData = FFmpegExtraData(4); ++ streamSubtitle->extraData.GetData()[0] = (stream.iSubtitleInfo >> 8) & 0xff; ++ streamSubtitle->extraData.GetData()[1] = (stream.iSubtitleInfo >> 0) & 0xff; ++ streamSubtitle->extraData.GetData()[2] = (stream.iSubtitleInfo >> 24) & 0xff; ++ streamSubtitle->extraData.GetData()[3] = (stream.iSubtitleInfo >> 16) & 0xff; + } + dStream = streamSubtitle; + } +diff --git a/xbmc/cores/VideoPlayer/DVDStreamInfo.cpp b/xbmc/cores/VideoPlayer/DVDStreamInfo.cpp +index 696cec5e03d49..f387301e56971 100644 +--- a/xbmc/cores/VideoPlayer/DVDStreamInfo.cpp ++++ b/xbmc/cores/VideoPlayer/DVDStreamInfo.cpp +@@ -13,18 +13,25 @@ + + #include + +-CDVDStreamInfo::CDVDStreamInfo() { extradata = NULL; Clear(); } +-CDVDStreamInfo::CDVDStreamInfo(const CDVDStreamInfo &right, bool withextradata ) { extradata = NULL; Clear(); Assign(right, withextradata); } +-CDVDStreamInfo::CDVDStreamInfo(const CDemuxStream &right, bool withextradata ) { extradata = NULL; Clear(); Assign(right, withextradata); } +- +-CDVDStreamInfo::~CDVDStreamInfo() ++CDVDStreamInfo::CDVDStreamInfo() + { +- if( extradata && extrasize ) free(extradata); +- +- extradata = NULL; +- extrasize = 0; ++ extradata = {}; ++ Clear(); ++} ++CDVDStreamInfo::CDVDStreamInfo(const CDVDStreamInfo& right, bool withextradata) ++{ ++ extradata = {}; ++ Clear(); ++ Assign(right, withextradata); ++} ++CDVDStreamInfo::CDVDStreamInfo(const CDemuxStream& right, bool withextradata) ++{ ++ extradata = {}; ++ Clear(); ++ Assign(right, withextradata); + } + ++CDVDStreamInfo::~CDVDStreamInfo() = default; + + void CDVDStreamInfo::Clear() + { +@@ -38,10 +45,7 @@ void CDVDStreamInfo::Clear() + filename.clear(); + dvd = false; + +- if( extradata && extrasize ) free(extradata); +- +- extradata = NULL; +- extrasize = 0; ++ extradata = {}; + + cryptoSession = nullptr; + externalInterfaces = nullptr; +@@ -87,13 +91,9 @@ bool CDVDStreamInfo::Equal(const CDVDStreamInfo& right, int compare) + flags != right.flags) + return false; + +- if (compare & COMPARE_EXTRADATA) ++ if (compare & COMPARE_EXTRADATA && extradata != right.extradata) + { +- if( extrasize != right.extrasize ) return false; +- if( extrasize ) +- { +- if( memcmp(extradata, right.extradata, extrasize) != 0 ) return false; +- } ++ return false; + } + + // VIDEO +@@ -200,20 +200,13 @@ void CDVDStreamInfo::Assign(const CDVDStreamInfo& right, bool withextradata) + filename = right.filename; + dvd = right.dvd; + +- if( extradata && extrasize ) free(extradata); +- +- if( withextradata && right.extrasize ) ++ if (withextradata && right.extradata) + { +- extrasize = right.extrasize; +- extradata = malloc(extrasize); +- if (!extradata) +- return; +- memcpy(extradata, right.extradata, extrasize); ++ extradata = right.extradata; + } + else + { +- extrasize = 0; +- extradata = 0; ++ extradata = {}; + } + + cryptoSession = right.cryptoSession; +@@ -270,13 +263,9 @@ void CDVDStreamInfo::Assign(const CDemuxStream& right, bool withextradata) + level = right.level; + flags = right.flags; + +- if (withextradata && right.ExtraSize) ++ if (withextradata && right.extraData) + { +- extrasize = right.ExtraSize; +- extradata = malloc(extrasize); +- if (!extradata) +- return; +- memcpy(extradata, right.ExtraData.get(), extrasize); ++ extradata = right.extraData; + } + + cryptoSession = right.cryptoSession; +diff --git a/xbmc/cores/VideoPlayer/DVDStreamInfo.h b/xbmc/cores/VideoPlayer/DVDStreamInfo.h +index 4acd85737c9e7..b3d0eb6bf4a3b 100644 +--- a/xbmc/cores/VideoPlayer/DVDStreamInfo.h ++++ b/xbmc/cores/VideoPlayer/DVDStreamInfo.h +@@ -91,8 +91,7 @@ class CDVDStreamInfo + // SUBTITLE + + // CODEC EXTRADATA +- void* extradata; // extra data for codec to use +- unsigned int extrasize; // size of extra data ++ FFmpegExtraData extradata; // extra data for codec to use + unsigned int codec_tag; // extra identifier hints for decoding + + // Crypto initialization Data +diff --git a/xbmc/cores/VideoPlayer/VideoPlayerVideo.cpp b/xbmc/cores/VideoPlayer/VideoPlayerVideo.cpp +index c108091505fb4..ccfca71b7951c 100644 +--- a/xbmc/cores/VideoPlayer/VideoPlayerVideo.cpp ++++ b/xbmc/cores/VideoPlayer/VideoPlayerVideo.cpp +@@ -103,7 +103,7 @@ bool CVideoPlayerVideo::OpenStream(CDVDStreamInfo hint) + { + if (hint.flags & AV_DISPOSITION_ATTACHED_PIC) + return false; +- if (hint.extrasize == 0) ++ if (!hint.extradata) + { + // codecs which require extradata + // clang-format off +diff --git a/xbmc/utils/BitstreamConverter.cpp b/xbmc/utils/BitstreamConverter.cpp +index f2224a5457939..1bca7d14d8400 100644 +--- a/xbmc/utils/BitstreamConverter.cpp ++++ b/xbmc/utils/BitstreamConverter.cpp +@@ -317,9 +317,7 @@ CBitstreamConverter::CBitstreamConverter() + m_convertSize = 0; + m_inputBuffer = NULL; + m_inputSize = 0; +- m_to_annexb = false; +- m_extradata = NULL; +- m_extrasize = 0; ++ m_to_annexb = false; + m_convert_3byteTo4byteNALSize = false; + m_convert_bytestream = false; + m_sps_pps_context.sps_pps_data = NULL; +@@ -350,10 +348,9 @@ bool CBitstreamConverter::Open(enum AVCodecID codec, uint8_t *in_extradata, int + if ( in_extradata[0] == 1 ) + { + CLog::Log(LOGINFO, "CBitstreamConverter::Open bitstream to annexb init"); +- m_extrasize = in_extrasize; +- m_extradata = (uint8_t*)av_malloc(in_extrasize); +- memcpy(m_extradata, in_extradata, in_extrasize); +- m_convert_bitstream = BitstreamConvertInitAVC(m_extradata, m_extrasize); ++ m_extraData = FFmpegExtraData(in_extradata, in_extrasize); ++ m_convert_bitstream = ++ BitstreamConvertInitAVC(m_extraData.GetData(), m_extraData.GetSize()); + return true; + } + else +@@ -381,9 +378,7 @@ bool CBitstreamConverter::Open(enum AVCodecID codec, uint8_t *in_extradata, int + // extract the avcC atom data into extradata then write it into avcCData for VDADecoder + in_extrasize = avio_close_dyn_buf(pb, &in_extradata); + // make a copy of extradata contents +- m_extradata = (uint8_t *)av_malloc(in_extrasize); +- memcpy(m_extradata, in_extradata, in_extrasize); +- m_extrasize = in_extrasize; ++ m_extraData = FFmpegExtraData(in_extradata, in_extrasize); + // done with the converted extradata, we MUST free using av_free + av_free(in_extradata); + return true; +@@ -404,16 +399,12 @@ bool CBitstreamConverter::Open(enum AVCodecID codec, uint8_t *in_extradata, int + in_extradata[4] = 0xFF; + m_convert_3byteTo4byteNALSize = true; + +- m_extradata = (uint8_t *)av_malloc(in_extrasize); +- memcpy(m_extradata, in_extradata, in_extrasize); +- m_extrasize = in_extrasize; ++ m_extraData = FFmpegExtraData(in_extradata, in_extrasize); + return true; + } + } + // valid avcC atom +- m_extradata = (uint8_t*)av_malloc(in_extrasize); +- memcpy(m_extradata, in_extradata, in_extrasize); +- m_extrasize = in_extrasize; ++ m_extraData = FFmpegExtraData(in_extradata, in_extrasize); + return true; + } + return false; +@@ -437,10 +428,9 @@ bool CBitstreamConverter::Open(enum AVCodecID codec, uint8_t *in_extradata, int + if (in_extradata[0] || in_extradata[1] || in_extradata[2] > 1) + { + CLog::Log(LOGINFO, "CBitstreamConverter::Open bitstream to annexb init"); +- m_extrasize = in_extrasize; +- m_extradata = (uint8_t*)av_malloc(in_extrasize); +- memcpy(m_extradata, in_extradata, in_extrasize); +- m_convert_bitstream = BitstreamConvertInitHEVC(m_extradata, m_extrasize); ++ m_extraData = FFmpegExtraData(in_extradata, in_extrasize); ++ m_convert_bitstream = ++ BitstreamConvertInitHEVC(m_extraData.GetData(), m_extraData.GetSize()); + return true; + } + else +@@ -476,9 +466,7 @@ bool CBitstreamConverter::Open(enum AVCodecID codec, uint8_t *in_extradata, int + } + } + // valid hvcC atom +- m_extradata = (uint8_t*)av_malloc(in_extrasize); +- memcpy(m_extradata, in_extradata, in_extrasize); +- m_extrasize = in_extrasize; ++ m_extraData = FFmpegExtraData(in_extradata, in_extrasize); + return true; + } + return false; +@@ -499,9 +487,7 @@ void CBitstreamConverter::Close(void) + av_free(m_convertBuffer), m_convertBuffer = NULL; + m_convertSize = 0; + +- if (m_extradata) +- av_free(m_extradata), m_extradata = NULL; +- m_extrasize = 0; ++ m_extraData = {}; + + m_inputSize = 0; + m_inputBuffer = NULL; +@@ -637,19 +623,26 @@ int CBitstreamConverter::GetConvertSize() const + return m_inputSize; + } + +-uint8_t *CBitstreamConverter::GetExtraData() const ++uint8_t* CBitstreamConverter::GetExtraData() ++{ ++ if (m_convert_bitstream) ++ return m_sps_pps_context.sps_pps_data; ++ else ++ return m_extraData.GetData(); ++} ++const uint8_t* CBitstreamConverter::GetExtraData() const + { + if(m_convert_bitstream) + return m_sps_pps_context.sps_pps_data; + else +- return m_extradata; ++ return m_extraData.GetData(); + } + int CBitstreamConverter::GetExtraSize() const + { + if(m_convert_bitstream) + return m_sps_pps_context.size; + else +- return m_extrasize; ++ return m_extraData.GetSize(); + } + + void CBitstreamConverter::ResetStartDecode(void) +diff --git a/xbmc/utils/BitstreamConverter.h b/xbmc/utils/BitstreamConverter.h +index 3c57e14057ecd..be63b7590cfad 100644 +--- a/xbmc/utils/BitstreamConverter.h ++++ b/xbmc/utils/BitstreamConverter.h +@@ -8,6 +8,8 @@ + + #pragma once + ++#include "cores/FFmpeg.h" ++ + #include + + extern "C" { +@@ -92,7 +94,8 @@ class CBitstreamConverter + bool Convert(uint8_t *pData, int iSize); + uint8_t* GetConvertBuffer(void) const; + int GetConvertSize() const; +- uint8_t* GetExtraData(void) const; ++ uint8_t* GetExtraData(); ++ const uint8_t* GetExtraData() const; + int GetExtraSize() const; + void ResetStartDecode(void); + bool CanStartDecode() const; +@@ -135,8 +138,7 @@ class CBitstreamConverter + bool m_convert_bitstream; + bool m_to_annexb; + +- uint8_t *m_extradata; +- int m_extrasize; ++ FFmpegExtraData m_extraData; + bool m_convert_3byteTo4byteNALSize; + bool m_convert_bytestream; + AVCodecID m_codec; diff --git a/media-tv/kodi/files/kodi-20.2-fix-crash-in-avcodec_parameters_from_context.patch b/media-tv/kodi/files/kodi-20.2-fix-crash-in-avcodec_parameters_from_context.patch new file mode 100644 index 0000000..376aa59 --- /dev/null +++ b/media-tv/kodi/files/kodi-20.2-fix-crash-in-avcodec_parameters_from_context.patch @@ -0,0 +1,36 @@ +From 3ad9588656e30abd421e48147b23aee9fb4b3557 Mon Sep 17 00:00:00 2001 +From: Miguel Borges de Freitas <92enen@gmail.com> +Date: Sun, 12 Feb 2023 12:08:36 +0000 +Subject: [PATCH] [video] fix crash in avcodec_parameters_from_context + +--- + xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxClient.cpp | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxClient.cpp b/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxClient.cpp +index 9ca07b9a2dd39..26fa9522eea7a 100644 +--- a/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxClient.cpp ++++ b/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxClient.cpp +@@ -162,11 +162,12 @@ bool CDVDDemuxClient::ParsePacket(DemuxPacket* pkt) + avpkt->size = pkt->iSize; + avpkt->dts = avpkt->pts = AV_NOPTS_VALUE; + +- AVCodecParameters* codecPar = nullptr; ++ AVCodecParameters* codecPar = avcodec_parameters_alloc(); + int ret = avcodec_parameters_from_context(codecPar, stream->m_context); + if (ret < 0) + { + CLog::LogF(LOGERROR, "avcodec_parameters_from_context failed"); ++ avcodec_parameters_free(&codecPar); + return false; + } + +@@ -188,7 +189,7 @@ bool CDVDDemuxClient::ParsePacket(DemuxPacket* pkt) + avcodec_close(stream->m_context); + } + } +- ++ avcodec_parameters_free(&codecPar); + av_packet_free(&avpkt); + } + diff --git a/media-tv/kodi/files/kodi-20.2-smart_ptr-and-custom-destructor-for-AVCodecParameters.patch b/media-tv/kodi/files/kodi-20.2-smart_ptr-and-custom-destructor-for-AVCodecParameters.patch new file mode 100644 index 0000000..2ebf378 --- /dev/null +++ b/media-tv/kodi/files/kodi-20.2-smart_ptr-and-custom-destructor-for-AVCodecParameters.patch @@ -0,0 +1,55 @@ +From 456d6557ea570f63dc18831242b9189f96c1097d Mon Sep 17 00:00:00 2001 +From: Steve Hartwell +Date: Sun, 12 Feb 2023 18:10:45 +0000 +Subject: [PATCH] [video] use smart_ptr and custom destructor for + AVCodecParameters + +Co-authored-by: Miguel Borges de Freitas <92enen@gmail.com> +--- + .../cores/VideoPlayer/DVDDemuxers/DVDDemuxClient.cpp | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +diff --git a/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxClient.cpp b/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxClient.cpp +index 26fa9522eea7a..2a42244b62b68 100644 +--- a/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxClient.cpp ++++ b/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxClient.cpp +@@ -14,7 +14,9 @@ + #include "cores/VideoPlayer/Interface/TimingConstants.h" + #include "utils/log.h" + ++#include + #include ++#include + #include + + class CDemuxStreamClientInternal +@@ -162,16 +164,17 @@ bool CDVDDemuxClient::ParsePacket(DemuxPacket* pkt) + avpkt->size = pkt->iSize; + avpkt->dts = avpkt->pts = AV_NOPTS_VALUE; + +- AVCodecParameters* codecPar = avcodec_parameters_alloc(); +- int ret = avcodec_parameters_from_context(codecPar, stream->m_context); ++ constexpr auto codecParDeleter = [](AVCodecParameters* p) { avcodec_parameters_free(&p); }; ++ auto codecPar = std::unique_ptr( ++ avcodec_parameters_alloc(), codecParDeleter); ++ int ret = avcodec_parameters_from_context(codecPar.get(), stream->m_context); + if (ret < 0) + { + CLog::LogF(LOGERROR, "avcodec_parameters_from_context failed"); +- avcodec_parameters_free(&codecPar); + return false; + } + +- auto [retExtraData, len] = GetPacketExtradata(avpkt, codecPar); ++ auto [retExtraData, len] = GetPacketExtradata(avpkt, codecPar.get()); + if (len > 0) + { + st->changes++; +@@ -189,7 +192,6 @@ bool CDVDDemuxClient::ParsePacket(DemuxPacket* pkt) + avcodec_close(stream->m_context); + } + } +- avcodec_parameters_free(&codecPar); + av_packet_free(&avpkt); + } + diff --git a/media-tv/kodi/kodi-20.2-r1.ebuild b/media-tv/kodi/kodi-20.2-r2.ebuild similarity index 98% rename from media-tv/kodi/kodi-20.2-r1.ebuild rename to media-tv/kodi/kodi-20.2-r2.ebuild index 020bd7a..e160ec7 100644 --- a/media-tv/kodi/kodi-20.2-r1.ebuild +++ b/media-tv/kodi/kodi-20.2-r2.ebuild @@ -192,6 +192,8 @@ PATCHES=( "${FILESDIR}"/${P}-ffmpeg5.patch "${FILESDIR}"/${P}-ffmpeg6.patch "${FILESDIR}"/${P}-Fix-playback-of-optical-dvds-without-mount-support.patch + "${FILESDIR}"/${P}-fix-crash-in-avcodec_parameters_from_context.patch + "${FILESDIR}"/${P}-smart_ptr-and-custom-destructor-for-AVCodecParameters.patch ) pkg_setup() {