From 675c0532ef23fa4337cad3f3b051a84625440e6c Mon Sep 17 00:00:00 2001 From: David Guglielmi Date: Mon, 25 Sep 2023 16:48:26 +0200 Subject: [PATCH] media-plugins/kodi-inputstream-ffmpegdirect: add ffmpeg 6.0 support --- .../kodi-inputstream-ffmpegdirect/Manifest | 5 +- ...extradata-with-extract_extradata-BSF.patch | 290 ++++++++++++++++ ...utstream-ffmpegdirect-20.5.0-ffmpeg5.patch | 319 ++++++++++++++++++ ...utstream-ffmpegdirect-20.5.0-ffmpeg6.patch | 31 ++ ...inputstream-ffmpegdirect-20.5.0-r1.ebuild} | 8 +- 5 files changed, 651 insertions(+), 2 deletions(-) create mode 100644 media-plugins/kodi-inputstream-ffmpegdirect/files/kodi-inputstream-ffmpegdirect-20.5.0-Get-extradata-with-extract_extradata-BSF.patch create mode 100644 media-plugins/kodi-inputstream-ffmpegdirect/files/kodi-inputstream-ffmpegdirect-20.5.0-ffmpeg5.patch create mode 100644 media-plugins/kodi-inputstream-ffmpegdirect/files/kodi-inputstream-ffmpegdirect-20.5.0-ffmpeg6.patch rename media-plugins/kodi-inputstream-ffmpegdirect/{kodi-inputstream-ffmpegdirect-20.5.0.ebuild => kodi-inputstream-ffmpegdirect-20.5.0-r1.ebuild} (79%) diff --git a/media-plugins/kodi-inputstream-ffmpegdirect/Manifest b/media-plugins/kodi-inputstream-ffmpegdirect/Manifest index b0ec0ec..79bb5e8 100644 --- a/media-plugins/kodi-inputstream-ffmpegdirect/Manifest +++ b/media-plugins/kodi-inputstream-ffmpegdirect/Manifest @@ -1,2 +1,5 @@ +AUX kodi-inputstream-ffmpegdirect-20.5.0-Get-extradata-with-extract_extradata-BSF.patch 9834 BLAKE2B d26b4a56ddad02488868c94670440ab369a2016416a606b9f05386b615367028379279e270771d6635c69370e670178bd4dc80d4296d8ea69165b297708ded38 SHA512 77964f8d726e6bad4ea20fc9c5320f36a20047d9d9b999cc154f78e1f38612624a742c23a45ae060289e8507cc122fbd828b6f460e9449fa3e44bbc22ac61c14 +AUX kodi-inputstream-ffmpegdirect-20.5.0-ffmpeg5.patch 13078 BLAKE2B 50fa84e7790b06960177cc48a097fca12d1f984bd41db335f98e01ebd2ecca5c4fad8e917af5af8a6d8bcc3408856542d44784834fecbd119a82ee75ec243df4 SHA512 63427c395dea7533c0909cbc43fecf8e14998bb108da50a43c2e755f8fa94cdd74751ce4b09ebc8db1780eaaf1fc717f5e4ed156443f78c9fdd6fb3bf730482b +AUX kodi-inputstream-ffmpegdirect-20.5.0-ffmpeg6.patch 1467 BLAKE2B 1a82346927a978c059e0d69bde63451a5463fec0035b8f32ea735a1fd26374254aec3f4b60041f13a49993542f9244ebf232c734b4aff5c5cece0d1bdde2320f SHA512 6c385aad0afa07379235ee7bd70a11e434befabde46dd5185c90ad85258d4ac5451c8426354f4d6e1e16b4e7c6e6a267843c4abba9a2e6601677c2e7023ce9b1 DIST kodi-inputstream-ffmpegdirect-20.5.0.tar.gz 289362 BLAKE2B 2e8c63bd47d54f84cade2acb092a8e3ef11c31170071f66b5f22d4aa6fd27992a22b19ecb8070ce7d952f80882fe617e5eaed70dcf325b9bdb579220ddd59688 SHA512 9db8e25f04400635e13cf7c79f7079be9c7ffbf427423abcfc449dcd06f6259dcf9ed1ad1eae1563db239978c8399e054e7c6adcbebb5cc70c4de1c01643d074 -EBUILD kodi-inputstream-ffmpegdirect-20.5.0.ebuild 794 BLAKE2B 44d2ce9b511f0be4b5221fc48a6a7d85b624627695f609cc0bfa8151a71d014de06b4f6b9e7d9677d7baafd9d8ae02c3e914d6a2c959fa77cce67f08c2d32f91 SHA512 42122128ad256b70b854b52a3d39b7899040c2798748a3856400f355a5560001abc8b95147f9ca994053aa05d6d9fe556451e6cf558b4611d101acdab8017c44 +EBUILD kodi-inputstream-ffmpegdirect-20.5.0-r1.ebuild 945 BLAKE2B 3487a7db820b60364d1916ae97377d437c0130c439e0c35ecd2f43c37ceb98118b2724575cca1ec692d0c26129d3b1f3eb9e7758f37c53bc4937f5dc44a8cbe1 SHA512 a6d0bad64f7e66badae0f357b47d8e16bc9f4b975c7a22ed5c8c4e0abc362bad7565dff983f9d90750e85ccf28d53e1eb7ac0ee27042df0d13771d5f6f2a1da4 diff --git a/media-plugins/kodi-inputstream-ffmpegdirect/files/kodi-inputstream-ffmpegdirect-20.5.0-Get-extradata-with-extract_extradata-BSF.patch b/media-plugins/kodi-inputstream-ffmpegdirect/files/kodi-inputstream-ffmpegdirect-20.5.0-Get-extradata-with-extract_extradata-BSF.patch new file mode 100644 index 0000000..edc8629 --- /dev/null +++ b/media-plugins/kodi-inputstream-ffmpegdirect/files/kodi-inputstream-ffmpegdirect-20.5.0-Get-extradata-with-extract_extradata-BSF.patch @@ -0,0 +1,290 @@ +From 07ea26d7ce6bde1350ceb15380f4908da454f004 Mon Sep 17 00:00:00 2001 +From: Vasyl Gello +Date: Sat, 15 Oct 2022 16:17:48 +0000 +Subject: [PATCH] ffmpeg5: Get extradata with extract_extradata BSF + +Fixes the transport stream playback failures described in +https://bugs.debian.org/1016925 + +@Rogo95 made an excellent technical analysis of the root cause +and reported that to the bug thread. + +Later on, James Almer (@jamrial) suggested the solution to use +extract_extradata bitstream filter to replace the removed split() +function. + +Finally, I adapted the following code snippet: +https://gist.github.com/moonpfe/f6795d51294d91ee0f82f62ff6985db0 +to Kodi and tested it by playing the affected files in TS format. + +Signed-off-by: Vasyl Gello +--- + src/stream/FFmpegStream.cpp | 222 ++++++++++++++++++++++++++++++------ + src/stream/FFmpegStream.h | 2 + + 2 files changed, 192 insertions(+), 32 deletions(-) + +diff --git a/src/stream/FFmpegStream.cpp b/src/stream/FFmpegStream.cpp +index f2140a17..95d1da83 100644 +--- a/src/stream/FFmpegStream.cpp ++++ b/src/stream/FFmpegStream.cpp +@@ -29,6 +29,7 @@ + #endif + + extern "C" { ++#include + #include + #include + } +@@ -1586,6 +1587,168 @@ bool FFmpegStream::SeekTime(double time, bool backwards, double* startpts) + return false; + } + ++int FFmpegStream::GetPacketExtradata(const AVPacket* pkt, const AVCodecParserContext* parserCtx, AVCodecContext* codecCtx, uint8_t **p_extradata) ++{ ++ int extradata_size = 0; ++ ++ if (!pkt || !p_extradata) ++ return 0; ++ ++ *p_extradata = nullptr; ++ ++#if LIBAVFORMAT_BUILD >= AV_VERSION_INT(59, 0, 100) ++ /* extract_extradata bitstream filter is implemented only ++ * for certain codecs, as noted in discussion of PR#21248 ++ */ ++ ++ AVCodecID codecId = codecCtx->codec_id; ++ ++ // clang-format off ++ if ( ++ codecId != AV_CODEC_ID_MPEG1VIDEO && ++ codecId != AV_CODEC_ID_MPEG2VIDEO && ++ codecId != AV_CODEC_ID_H264 && ++ codecId != AV_CODEC_ID_HEVC && ++ codecId != AV_CODEC_ID_MPEG4 && ++ codecId != AV_CODEC_ID_VC1 && ++ codecId != AV_CODEC_ID_AV1 && ++ codecId != AV_CODEC_ID_AVS2 && ++ codecId != AV_CODEC_ID_AVS3 && ++ codecId != AV_CODEC_ID_CAVS ++ ) ++ // clang-format on ++ return 0; ++ ++ AVBSFContext *bsf = nullptr; ++ AVPacket *dst_pkt = nullptr; ++ const AVBitStreamFilter *f; ++ AVPacket *pkt_ref = nullptr; ++ int ret = 0; ++ uint8_t *ret_extradata = nullptr; ++ size_t ret_extradata_size = 0; ++ ++ f = av_bsf_get_by_name("extract_extradata"); ++ if (!f) ++ return 0; ++ ++ bsf = nullptr; ++ ret = av_bsf_alloc(f, &bsf); ++ if (ret < 0) ++ return 0; ++ ++ bsf->par_in->codec_id = codecCtx->codec_id; ++ ++ ret = av_bsf_init(bsf); ++ if (ret < 0) ++ { ++ av_bsf_free(&bsf); ++ return 0; ++ } ++ ++ dst_pkt = av_packet_alloc(); ++ pkt_ref = dst_pkt; ++ ++ ret = av_packet_ref(pkt_ref, pkt); ++ if (ret < 0) ++ { ++ av_bsf_free(&bsf); ++ av_packet_free(&dst_pkt); ++ return 0; ++ } ++ ++ ret = av_bsf_send_packet(bsf, pkt_ref); ++ if (ret < 0) ++ { ++ av_packet_unref(pkt_ref); ++ av_bsf_free(&bsf); ++ av_packet_free(&dst_pkt); ++ return 0; ++ } ++ ++ ret = 0; ++ while (ret >= 0) ++ { ++ ret = av_bsf_receive_packet(bsf, pkt_ref); ++ if (ret < 0) ++ { ++ if (ret != AVERROR(EAGAIN) && ret != AVERROR_EOF) ++ break; ++ ++ continue; ++ } ++ ++ ret_extradata = av_packet_get_side_data(pkt_ref, ++ AV_PKT_DATA_NEW_EXTRADATA, ++ &ret_extradata_size); ++ if (ret_extradata && ++ ret_extradata_size > 0 && ++ ret_extradata_size < FF_MAX_EXTRADATA_SIZE) ++ { ++ *p_extradata = (uint8_t*)av_malloc(ret_extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); ++ if (!*p_extradata) ++ { ++ Log(LOGLEVEL_ERROR, ++ "%s - failed to allocate %zu bytes for extradata", ++ __FUNCTION__, ++ ret_extradata_size); ++ ++ av_packet_unref(pkt_ref); ++ av_bsf_free(&bsf); ++ av_packet_free(&dst_pkt); ++ return 0; ++ } ++ ++ Log(LOGLEVEL_DEBUG, ++ "%s - fetching extradata, extradata_size(%zu)", ++ __FUNCTION__, ++ ret_extradata_size); ++ ++ memcpy(*p_extradata, ret_extradata, ret_extradata_size); ++ memset(*p_extradata + ret_extradata_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); ++ extradata_size = ret_extradata_size; ++ ++ av_packet_unref(pkt_ref); ++ break; ++ } ++ ++ av_packet_unref(pkt_ref); ++ } ++ ++ av_bsf_free(&bsf); ++ av_packet_free(&dst_pkt); ++#else ++ if (codecCtx && parserCtx && parserCtx->parser && parserCtx->parser->split) ++ extradata_size = parserCtx->parser->split(codecCtx, pkt->data, pkt->size); ++ ++ if (extradata_size <= 0 || extradata_size >= FF_MAX_EXTRADATA_SIZE) ++ { ++ Log(LOGLEVEL_DEBUG, "%s - fetched extradata of weird size %zd", ++ __FUNCTION__, extradata_size); ++ return 0; ++ } ++ ++ *p_extradata = (uint8_t*)av_malloc(extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); ++ if (!*p_extradata) ++ { ++ Log(LOGLEVEL_ERROR, ++ "%s - failed to allocate %zd bytes for extradata", ++ __FUNCTION__, ++ extradata_size); ++ return 0; ++ } ++ ++ Log(LOGLEVEL_DEBUG, ++ "%s - fetching extradata, extradata_size(%zd)", ++ __FUNCTION__, ++ extradata_size); ++ ++ memcpy(*p_extradata, pkt->data, extradata_size); ++ memset(*p_extradata + extradata_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); ++#endif ++ ++ return extradata_size; ++} ++ + void FFmpegStream::ParsePacket(AVPacket* pkt) + { + AVStream* st = m_pFormatContext->streams[pkt->stream_index]; +@@ -1617,43 +1780,38 @@ void FFmpegStream::ParsePacket(AVPacket* pkt) + + if (parser->second->m_parserCtx && + parser->second->m_parserCtx->parser && +- parser->second->m_parserCtx->parser->split && + !st->codecpar->extradata) + { +- int i = parser->second->m_parserCtx->parser->split(parser->second->m_codecCtx, pkt->data, pkt->size); +- if (i > 0 && i < FF_MAX_EXTRADATA_SIZE) ++ int i = GetPacketExtradata(pkt, ++ parser->second->m_parserCtx, ++ parser->second->m_codecCtx, ++ &st->codecpar->extradata); ++ if (i > 0) + { +- st->codecpar->extradata = (uint8_t*)av_malloc(i + AV_INPUT_BUFFER_PADDING_SIZE); +- if (st->codecpar->extradata) +- { +- Log(LOGLEVEL_DEBUG, "CDVDDemuxFFmpeg::ParsePacket() fetching extradata, extradata_size(%d)", i); +- st->codecpar->extradata_size = i; +- memcpy(st->codecpar->extradata, pkt->data, i); +- memset(st->codecpar->extradata + i, 0, AV_INPUT_BUFFER_PADDING_SIZE); ++ st->codecpar->extradata_size = i; + +- if (parser->second->m_parserCtx->parser->parser_parse) ++ if (parser->second->m_parserCtx->parser->parser_parse) ++ { ++ parser->second->m_codecCtx->extradata = st->codecpar->extradata; ++ parser->second->m_codecCtx->extradata_size = st->codecpar->extradata_size; ++ const uint8_t* outbufptr; ++ int bufSize; ++ parser->second->m_parserCtx->flags |= PARSER_FLAG_COMPLETE_FRAMES; ++ parser->second->m_parserCtx->parser->parser_parse(parser->second->m_parserCtx, ++ parser->second->m_codecCtx, ++ &outbufptr, &bufSize, ++ pkt->data, pkt->size); ++ parser->second->m_codecCtx->extradata = nullptr; ++ parser->second->m_codecCtx->extradata_size = 0; ++ ++ if (parser->second->m_parserCtx->width != 0) + { +- parser->second->m_codecCtx->extradata = st->codecpar->extradata; +- parser->second->m_codecCtx->extradata_size = st->codecpar->extradata_size; +- const uint8_t* outbufptr; +- int bufSize; +- parser->second->m_parserCtx->flags |= PARSER_FLAG_COMPLETE_FRAMES; +- parser->second->m_parserCtx->parser->parser_parse(parser->second->m_parserCtx, +- parser->second->m_codecCtx, +- &outbufptr, &bufSize, +- pkt->data, pkt->size); +- parser->second->m_codecCtx->extradata = nullptr; +- parser->second->m_codecCtx->extradata_size = 0; +- +- if (parser->second->m_parserCtx->width != 0) +- { +- st->codecpar->width = parser->second->m_parserCtx->width; +- st->codecpar->height = parser->second->m_parserCtx->height; +- } +- else +- { +- Log(LOGLEVEL_ERROR, "CDVDDemuxFFmpeg::ParsePacket() invalid width/height"); +- } ++ st->codecpar->width = parser->second->m_parserCtx->width; ++ st->codecpar->height = parser->second->m_parserCtx->height; ++ } ++ else ++ { ++ Log(LOGLEVEL_ERROR, "CDVDDemuxFFmpeg::ParsePacket() invalid width/height"); + } + } + } +diff --git a/src/stream/FFmpegStream.h b/src/stream/FFmpegStream.h +index 356905dd..f0634d0f 100644 +--- a/src/stream/FFmpegStream.h ++++ b/src/stream/FFmpegStream.h +@@ -109,6 +109,8 @@ class FFmpegStream + bool IsPaused() { return m_speed == STREAM_PLAYSPEED_PAUSE; } + virtual bool CheckReturnEmptyOnPacketResult(int result); + ++ int GetPacketExtradata(const AVPacket* pkt, const AVCodecParserContext* parserCtx, AVCodecContext* codecCtx, uint8_t **p_extradata); ++ + int64_t m_demuxerId; + mutable std::recursive_mutex m_mutex; + double m_currentPts; // used for stream length estimation diff --git a/media-plugins/kodi-inputstream-ffmpegdirect/files/kodi-inputstream-ffmpegdirect-20.5.0-ffmpeg5.patch b/media-plugins/kodi-inputstream-ffmpegdirect/files/kodi-inputstream-ffmpegdirect-20.5.0-ffmpeg5.patch new file mode 100644 index 0000000..cdeae6d --- /dev/null +++ b/media-plugins/kodi-inputstream-ffmpegdirect/files/kodi-inputstream-ffmpegdirect-20.5.0-ffmpeg5.patch @@ -0,0 +1,319 @@ +From fcad1884954ec1998f353750dd7332501e204ddb Mon Sep 17 00:00:00 2001 +From: Vasyl Gello +Date: Sat, 15 Oct 2022 16:08:14 +0000 +Subject: [PATCH] Adapt AlwinEsch's ffmpeg5 port patch + +Signed-off-by: Vasyl Gello +--- + src/stream/FFmpegStream.cpp | 96 ++++++++++++++++++++++++++++++++----- + src/stream/FFmpegStream.h | 6 ++- + src/utils/FFmpegCompat.h | 20 ++++++++ + 3 files changed, 107 insertions(+), 15 deletions(-) + create mode 100644 src/utils/FFmpegCompat.h + +diff --git a/src/stream/FFmpegStream.cpp b/src/stream/FFmpegStream.cpp +index 73e0963c..f2140a17 100644 +--- a/src/stream/FFmpegStream.cpp ++++ b/src/stream/FFmpegStream.cpp +@@ -462,7 +462,14 @@ DEMUX_PACKET* FFmpegStream::DemuxRead() + // we already check for a valid m_streams[pPacket->iStreamId] above + else if (stream->type == INPUTSTREAM_TYPE_AUDIO) + { +- if (static_cast(stream)->iChannels != m_pFormatContext->streams[pPacket->iStreamId]->codecpar->channels || ++#if LIBAVCODEC_BUILD >= AV_VERSION_INT(59, 37, 100) && \ ++ LIBAVUTIL_BUILD >= AV_VERSION_INT(57, 28, 100) ++ int codecparChannels = ++ m_pFormatContext->streams[pPacket->iStreamId]->codecpar->ch_layout.nb_channels; ++#else ++ int codecparChannels = m_pFormatContext->streams[pPacket->iStreamId]->codecpar->channels; ++#endif ++ if (static_cast(stream)->iChannels != codecparChannels || + static_cast(stream)->iSampleRate != m_pFormatContext->streams[pPacket->iStreamId]->codecpar->sample_rate) + { + // content has changed +@@ -658,7 +665,7 @@ bool FFmpegStream::Aborted() + + bool FFmpegStream::Open(bool fileinfo) + { +- AVInputFormat* iformat = NULL; ++ FFMPEG_FMT_CONST AVInputFormat* iformat = nullptr; + std::string strFile; + m_streaminfo = !m_isRealTimeStream && !m_reopen;; + m_currentPts = STREAM_NOPTS_VALUE; +@@ -729,6 +736,8 @@ bool FFmpegStream::Open(bool fileinfo) + m_streaminfo = true; + } + ++ // https://github.com/FFmpeg/FFmpeg/blob/56450a0ee4/doc/APIchanges#L18-L26 ++#if LIBAVFORMAT_BUILD < AV_VERSION_INT(59, 0, 100) + if (iformat && (strcmp(iformat->name, "mov,mp4,m4a,3gp,3g2,mj2") == 0)) + { + CURL url(m_streamUrl); +@@ -736,6 +745,7 @@ bool FFmpegStream::Open(bool fileinfo) + if (!url.GetProtocol().empty() && !url.IsProtocol("file")) + m_pFormatContext->iformat->flags |= AVFMT_NOGENSEARCH; + } ++#endif + + // we need to know if this is matroska, avi or sup later + m_bMatroska = strncmp(m_pFormatContext->iformat->name, "matroska", 8) == 0; // for "matroska.webm" +@@ -785,8 +795,11 @@ bool FFmpegStream::Open(bool fileinfo) + // if format can be nonblocking, let's use that + m_pFormatContext->flags |= AVFMT_FLAG_NONBLOCK; + +- // deprecated, will be always set in future versions ++ // https://github.com/FFmpeg/FFmpeg/blob/d682ae70b4/doc/APIchanges#L18-L21 ++#if LIBAVFORMAT_BUILD < AV_VERSION_INT(57, 66, 105) && \ ++ LIBAVCODEC_BUILD < AV_VERSION_INT(57, 83, 101) + m_pFormatContext->flags |= AVFMT_FLAG_KEEP_SIDE_DATA; ++#endif + + UpdateCurrentPTS(); + +@@ -828,12 +841,23 @@ bool FFmpegStream::Open(bool fileinfo) + { + int idx = m_pFormatContext->programs[i]->stream_index[j]; + AVStream* st = m_pFormatContext->streams[idx]; ++#if LIBAVFORMAT_BUILD >= AV_VERSION_INT(59, 3, 100) ++ // Related to https://patchwork.ffmpeg.org/project/ffmpeg/patch/20210429143825.53040-1-jamrial@gmail.com/ ++ // has been replaced with AVSTREAM_EVENT_FLAG_NEW_PACKETS. ++ if ((st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && (st->event_flags & AVSTREAM_EVENT_FLAG_NEW_PACKETS)) || ++ (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && st->codecpar->sample_rate > 0)) ++ { ++ nProgram = i; ++ break; ++ } ++#else + if ((st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && st->codec_info_nb_frames > 0) || + (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && st->codecpar->sample_rate > 0)) + { + nProgram = i; + break; + } ++#endif + } + } + +@@ -870,7 +894,7 @@ bool FFmpegStream::Open(bool fileinfo) + return true; + } + +-bool FFmpegStream::OpenWithFFmpeg(AVInputFormat* iformat, const AVIOInterruptCB& int_cb) ++bool FFmpegStream::OpenWithFFmpeg(FFMPEG_FMT_CONST AVInputFormat* iformat, const AVIOInterruptCB& int_cb) + { + Log(LOGLEVEL_INFO, "%s - IO handled by FFmpeg's AVFormat", __FUNCTION__); + +@@ -959,7 +983,7 @@ bool FFmpegStream::OpenWithFFmpeg(AVInputFormat* iformat, const AVIOInterruptCB& + return true; + } + +-bool FFmpegStream::OpenWithCURL(AVInputFormat* iformat) ++bool FFmpegStream::OpenWithCURL(FFMPEG_FMT_CONST AVInputFormat* iformat) + { + Log(LOGLEVEL_INFO, "%s - IO handled by Kodi's cURL", __FUNCTION__); + +@@ -1039,8 +1063,7 @@ bool FFmpegStream::OpenWithCURL(AVInputFormat* iformat) + // is present, we assume it is PCM audio. + // AC3 is always wrapped in iec61937 (ffmpeg "spdif"), while DTS + // may be just padded. +- AVInputFormat* iformat2; +- iformat2 = av_find_input_format("spdif"); ++ FFMPEG_FMT_CONST AVInputFormat* iformat2 = av_find_input_format("spdif"); + + if (iformat2 && iformat2->read_probe(&pd) > AVPROBE_SCORE_MAX / 4) + { +@@ -1147,11 +1170,19 @@ void FFmpegStream::UpdateCurrentPTS() + if (idx >= 0) + { + AVStream* stream = m_pFormatContext->streams[idx]; ++#if LIBAVFORMAT_BUILD >= AV_VERSION_INT(59, 3, 100) ++ if (stream && m_pkt.pkt.dts != (int64_t)AV_NOPTS_VALUE) ++ { ++ double ts = ConvertTimestamp(m_pkt.pkt.dts, stream->time_base.den, stream->time_base.num); ++ m_currentPts = ts; ++ } ++#else + if (stream && stream->cur_dts != (int64_t)AV_NOPTS_VALUE) + { + double ts = ConvertTimestamp(stream->cur_dts, stream->time_base.den, stream->time_base.num); + m_currentPts = ts; + } ++#endif + } + } + +@@ -1230,9 +1261,15 @@ bool FFmpegStream::IsProgramChange() + return true; + if (m_pFormatContext->streams[idx]->codecpar->codec_id != stream->codec) + return true; ++#if LIBAVCODEC_BUILD >= AV_VERSION_INT(59, 37, 100) && \ ++ LIBAVUTIL_BUILD >= AV_VERSION_INT(57, 28, 100) ++ int codecparChannels = ++ m_pFormatContext->streams[idx]->codecpar->ch_layout.nb_channels; ++#else ++ int codecparChannels = m_pFormatContext->streams[idx]->codecpar->channels; ++#endif + if (m_pFormatContext->streams[idx]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && +- m_pFormatContext->streams[idx]->codecpar->channels != +- static_cast(stream)->iChannels) ++ codecparChannels != static_cast(stream)->iChannels) + return true; + if (m_pFormatContext->streams[idx]->codecpar->extradata_size != static_cast(stream->ExtraSize)) + return true; +@@ -1564,7 +1601,7 @@ void FFmpegStream::ParsePacket(AVPacket* pkt) + + parser->second->m_parserCtx = av_parser_init(st->codecpar->codec_id); + +- AVCodec* codec = avcodec_find_decoder(st->codecpar->codec_id); ++ FFMPEG_FMT_CONST AVCodec* codec = avcodec_find_decoder(st->codecpar->codec_id); + if (codec == nullptr) + { + Log(LOGLEVEL_ERROR, "%s - can't find decoder", __FUNCTION__); +@@ -1641,7 +1678,11 @@ TRANSPORT_STREAM_STATE FFmpegStream::TransportStreamAudioState() + { + if (!m_startTime) + { ++#if LIBAVFORMAT_BUILD >= AV_VERSION_INT(59, 3, 100) ++ m_startTime = av_rescale(m_pkt.pkt.dts, st->time_base.num, st->time_base.den) - 0.000001; ++#else + m_startTime = av_rescale(st->cur_dts, st->time_base.num, st->time_base.den) - 0.000001; ++#endif + m_seekStream = idx; + } + return TRANSPORT_STREAM_STATE::READY; +@@ -1661,7 +1702,11 @@ TRANSPORT_STREAM_STATE FFmpegStream::TransportStreamAudioState() + { + if (!m_startTime) + { ++#if LIBAVFORMAT_BUILD >= AV_VERSION_INT(59, 3, 100) ++ m_startTime = av_rescale(m_pkt.pkt.dts, st->time_base.num, st->time_base.den) - 0.000001; ++#else + m_startTime = av_rescale(st->cur_dts, st->time_base.num, st->time_base.den) - 0.000001; ++#endif + m_seekStream = i; + } + return TRANSPORT_STREAM_STATE::READY; +@@ -1694,7 +1739,11 @@ TRANSPORT_STREAM_STATE FFmpegStream::TransportStreamVideoState() + { + if (!m_startTime) + { ++#if LIBAVFORMAT_BUILD >= AV_VERSION_INT(59, 3, 100) ++ m_startTime = av_rescale(m_pkt.pkt.dts, st->time_base.num, st->time_base.den) - 0.000001; ++#else + m_startTime = av_rescale(st->cur_dts, st->time_base.num, st->time_base.den) - 0.000001; ++#endif + m_seekStream = idx; + } + return TRANSPORT_STREAM_STATE::READY; +@@ -1714,7 +1763,11 @@ TRANSPORT_STREAM_STATE FFmpegStream::TransportStreamVideoState() + { + if (!m_startTime) + { ++#if LIBAVFORMAT_BUILD >= AV_VERSION_INT(59, 3, 100) ++ m_startTime = av_rescale(m_pkt.pkt.dts, st->time_base.num, st->time_base.den) - 0.000001; ++#else + m_startTime = av_rescale(st->cur_dts, st->time_base.num, st->time_base.den) - 0.000001; ++#endif + m_seekStream = i; + } + return TRANSPORT_STREAM_STATE::READY; +@@ -1824,14 +1877,31 @@ DemuxStream* FFmpegStream::AddStream(int streamIdx) + { + DemuxStreamAudioFFmpeg* st = new DemuxStreamAudioFFmpeg(pStream); + stream = st; +- st->iChannels = pStream->codecpar->channels; ++#if LIBAVCODEC_BUILD >= AV_VERSION_INT(59, 37, 100) && \ ++ LIBAVUTIL_BUILD >= AV_VERSION_INT(57, 28, 100) ++ int codecparChannels = pStream->codecpar->ch_layout.nb_channels; ++ int codecparChannelLayout = pStream->codecpar->ch_layout.u.mask; ++#else ++ int codecparChannels = pStream->codecpar->channels; ++ int codecparChannelLayout = pStream->codecpar->channel_layout; ++#endif ++ st->iChannels = codecparChannels; ++ st->iChannelLayout = codecparChannelLayout; + st->iSampleRate = pStream->codecpar->sample_rate; + st->iBlockAlign = pStream->codecpar->block_align; + st->iBitRate = static_cast(pStream->codecpar->bit_rate); + st->iBitsPerSample = pStream->codecpar->bits_per_raw_sample; +- st->iChannelLayout = pStream->codecpar->channel_layout; + char buf[32] = { 0 }; ++ // https://github.com/FFmpeg/FFmpeg/blob/6ccc3989d15/doc/APIchanges#L50-L53 ++#if LIBAVCODEC_BUILD >= AV_VERSION_INT(59, 37, 100) && \ ++ LIBAVUTIL_BUILD >= AV_VERSION_INT(57, 28, 100) ++ AVChannelLayout layout = {}; ++ av_channel_layout_from_mask(&layout, st->iChannelLayout); ++ av_channel_layout_describe(&layout, buf, sizeof(buf)); ++ av_channel_layout_uninit(&layout); ++#else + av_get_channel_layout_string(buf, 31, st->iChannels, st->iChannelLayout); ++#endif + st->m_channelLayoutName = buf; + if (st->iBitsPerSample == 0) + st->iBitsPerSample = pStream->codecpar->bits_per_coded_sample; +@@ -2070,7 +2140,7 @@ std::string FFmpegStream::GetStreamCodecName(int iStreamId) + return strName; + } + +- AVCodec* codec = avcodec_find_decoder(stream->codec); ++ FFMPEG_FMT_CONST AVCodec* codec = avcodec_find_decoder(stream->codec); + if (codec) + strName = codec->name; + } +diff --git a/src/stream/FFmpegStream.h b/src/stream/FFmpegStream.h +index bf8a50f9..356905dd 100644 +--- a/src/stream/FFmpegStream.h ++++ b/src/stream/FFmpegStream.h +@@ -7,6 +7,7 @@ + + #pragma once + ++#include "../utils/FFmpegCompat.h" + #include "../utils/HttpProxy.h" + #include "../utils/Properties.h" + #include "BaseStream.h" +@@ -33,6 +34,7 @@ extern "C" + #include + #include + #include ++#include + } + + #ifndef __GNUC__ +@@ -117,8 +119,8 @@ class FFmpegStream + + private: + bool Open(bool fileinfo); +- bool OpenWithFFmpeg(AVInputFormat* iformat, const AVIOInterruptCB& int_cb); +- bool OpenWithCURL(AVInputFormat* iformat); ++ bool OpenWithFFmpeg(FFMPEG_FMT_CONST AVInputFormat* iformat, const AVIOInterruptCB& int_cb); ++ bool OpenWithCURL(FFMPEG_FMT_CONST AVInputFormat* iformat); + AVDictionary* GetFFMpegOptionsFromInput(); + void ResetVideoStreams(); + double ConvertTimestamp(int64_t pts, int den, int num); +diff --git a/src/utils/FFmpegCompat.h b/src/utils/FFmpegCompat.h +new file mode 100644 +index 00000000..46cff53f +--- /dev/null ++++ b/src/utils/FFmpegCompat.h +@@ -0,0 +1,20 @@ ++/* ++ * Copyright (C) 2005-2022 Team Kodi ++ * This file is part of Kodi - https://kodi.tv ++ * ++ * SPDX-License-Identifier: GPL-2.0-or-later ++ * See LICENSES/README.md for more information. ++ */ ++ ++#pragma once ++ ++extern "C" { ++#include ++} ++ ++// https://github.com/FFmpeg/FFmpeg/blob/56450a0ee4/doc/APIchanges#L18-L26 ++#if LIBAVFORMAT_BUILD >= AV_VERSION_INT(59, 0, 100) ++#define FFMPEG_FMT_CONST const ++#else ++#define FFMPEG_FMT_CONST ++#endif diff --git a/media-plugins/kodi-inputstream-ffmpegdirect/files/kodi-inputstream-ffmpegdirect-20.5.0-ffmpeg6.patch b/media-plugins/kodi-inputstream-ffmpegdirect/files/kodi-inputstream-ffmpegdirect-20.5.0-ffmpeg6.patch new file mode 100644 index 0000000..ce3b820 --- /dev/null +++ b/media-plugins/kodi-inputstream-ffmpegdirect/files/kodi-inputstream-ffmpegdirect-20.5.0-ffmpeg6.patch @@ -0,0 +1,31 @@ +From 98ccdd2f4263eb1590c65f175c11deeec18fe6c2 Mon Sep 17 00:00:00 2001 +From: Bernd Kuhls +Date: Fri, 3 Mar 2023 19:33:04 +0100 +Subject: [PATCH] Fix build with ffmpeg 6.0 + +This feature was removed from ffmpeg: +http://git.videolan.org/?p=ffmpeg.git;a=commitdiff;h=add33e370d241d947209c914de1bf062fe44d58e +--- + src/stream/FFmpegStream.cpp | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/src/stream/FFmpegStream.cpp b/src/stream/FFmpegStream.cpp +index 341062ed..0996b446 100644 +--- a/src/stream/FFmpegStream.cpp ++++ b/src/stream/FFmpegStream.cpp +@@ -920,7 +920,6 @@ bool FFmpegStream::OpenWithFFmpeg(const AVInputFormat* iformat, const AVIOInterr + // We only process this condition for manifest streams when this setting is disabled + if (!kodi::addon::GetSettingBoolean("useFastOpenForManifestStreams") || m_manifestType.empty()) + { +- m_pFormatContext->flags |= AVFMT_FLAG_PRIV_OPT; + if (avformat_open_input(&m_pFormatContext, strFile.c_str(), iformat, &options) < 0) + { + Log(LOGLEVEL_DEBUG, "Error, could not open file %s", CURL::GetRedacted(strFile).c_str()); +@@ -935,7 +934,6 @@ bool FFmpegStream::OpenWithFFmpeg(const AVInputFormat* iformat, const AVIOInterr + } + + m_pFormatContext->interrupt_callback = int_cb; +- m_pFormatContext->flags &= ~AVFMT_FLAG_PRIV_OPT; + options = GetFFMpegOptionsFromInput(); + av_dict_set_int(&options, "load_all_variants", 0, AV_OPT_SEARCH_CHILDREN); + diff --git a/media-plugins/kodi-inputstream-ffmpegdirect/kodi-inputstream-ffmpegdirect-20.5.0.ebuild b/media-plugins/kodi-inputstream-ffmpegdirect/kodi-inputstream-ffmpegdirect-20.5.0-r1.ebuild similarity index 79% rename from media-plugins/kodi-inputstream-ffmpegdirect/kodi-inputstream-ffmpegdirect-20.5.0.ebuild rename to media-plugins/kodi-inputstream-ffmpegdirect/kodi-inputstream-ffmpegdirect-20.5.0-r1.ebuild index 2a2ac65..966b72e 100644 --- a/media-plugins/kodi-inputstream-ffmpegdirect/kodi-inputstream-ffmpegdirect-20.5.0.ebuild +++ b/media-plugins/kodi-inputstream-ffmpegdirect/kodi-inputstream-ffmpegdirect-20.5.0-r1.ebuild @@ -23,7 +23,7 @@ BDEPEND=" " COMMON_DEPEND=" - media-video/ffmpeg[encode,libxml2,zlib] + media-video/ffmpeg:=[encode,libxml2,zlib] virtual/libiconv app-arch/bzip2 =media-tv/kodi-20* @@ -37,6 +37,12 @@ RDEPEND=" ${COMMON_DEPEND} " +PATCHES=( + "${FILESDIR}"/${P}-ffmpeg5.patch + "${FILESDIR}"/${P}-Get-extradata-with-extract_extradata-BSF.patch + "${FILESDIR}"/${P}-ffmpeg6.patch +) + src_prepare() { [ -d depends ] && rm -rf depends || die cmake_src_prepare