# HG changeset patch # User Torsten Jager # Date 1715025355 -7200 # Mon May 06 21:55:55 2024 +0200 # Node ID 1e7b184008860c8be2289c3cefd9dee57f06193a # Parent d1954d852980ddc887a67a9f1a26626909561ff5 ffmpeg compatibility update 1. diff -r d1954d852980 -r 1e7b18400886 src/combined/ffmpeg/ff_audio_decoder.c --- a/src/combined/ffmpeg/ff_audio_decoder.c Mon Apr 08 13:25:10 2024 +0200 +++ b/src/combined/ffmpeg/ff_audio_decoder.c Mon May 06 21:55:55 2024 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2001-2023 the xine project + * Copyright (C) 2001-2024 the xine project * * This file is part of xine, a free video player. * @@ -67,6 +67,7 @@ xine_t *xine; float gain; + int bitexact; } ff_audio_class_t; typedef struct ff_audio_decoder_s { @@ -188,14 +189,25 @@ xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "ffmpeg_audio_dec: found AAC ADTS syncword after %d bytes\n", i); if (this->buftype == BUF_AUDIO_AAC_LATM) { + uint8_t *ed = NULL; + int es = 0; xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "ffmpeg_audio_dec: stream says LATM but is ADTS -> switching decoders\n"); - if (this->decoder_ok) { - pthread_mutex_lock (&ffmpeg_lock); - avcodec_close (this->context); - pthread_mutex_unlock (&ffmpeg_lock); - this->decoder_ok = 0; + pthread_mutex_lock (&ffmpeg_lock); + if (this->context) { + ed = this->context->extradata; + es = this->context->extradata_size; + this->context->extradata = NULL; + this->context->extradata_size = 0; + XFF_FREE_CONTEXT (this->context); } + this->decoder_ok = 0; + this->context = XFF_ALLOC_CONTEXT (); + if (this->context) { + this->context->extradata = ed; + this->context->extradata_size = es; + } + pthread_mutex_unlock (&ffmpeg_lock); this->codec = NULL; ff_audio_open_codec (this, BUF_AUDIO_AAC); } @@ -349,6 +361,11 @@ return -1; } + if (this->class->bitexact) + this->context->flags |= CODEC_FLAG_BITEXACT; + else + this->context->flags &= ~CODEC_FLAG_BITEXACT; + pthread_mutex_lock (&ffmpeg_lock); if (XFF_AVCODEC_OPEN (this->context, this->codec) < 0) { pthread_mutex_unlock (&ffmpeg_lock); @@ -1377,9 +1394,21 @@ } #endif pthread_mutex_lock (&ffmpeg_lock); - avcodec_close (this->context); - if (XFF_AVCODEC_OPEN (this->context, this->codec) < 0) + { + uint8_t *ed = this->context->extradata; + int es = this->context->extradata_size; + this->context->extradata = NULL; + this->context->extradata_size = 0; + XFF_FREE_CONTEXT (this->context); this->decoder_ok = 0; + this->context = XFF_ALLOC_CONTEXT (); + if (this->context) { + this->context->extradata = ed; + this->context->extradata_size = es; + } + } + if (XFF_AVCODEC_OPEN (this->context, this->codec) >= 0) + this->decoder_ok = 1; pthread_mutex_unlock (&ffmpeg_lock); } @@ -1418,20 +1447,20 @@ XFF_FREE_FRAME (this->av_frame); } #endif - pthread_mutex_lock (&ffmpeg_lock); - avcodec_close (this->context); - pthread_mutex_unlock (&ffmpeg_lock); } + pthread_mutex_lock (&ffmpeg_lock); + if (this->context) { + _x_freep (&this->context->extradata); + this->context->extradata_size = 0; + XFF_FREE_CONTEXT (this->context); + } + pthread_mutex_unlock (&ffmpeg_lock); ff_audio_output_close(this); xine_free_aligned (this->buf); xine_free_aligned (this->decode_buffer); - _x_freep (&this->context->extradata); - this->context->extradata_size = 0; - XFF_FREE_CONTEXT (this->context); - XFF_PACKET_UNREF (this->avpkt); xine_pts_queue_delete (&this->pts_queue); @@ -1513,6 +1542,12 @@ free (this); } +static void ff_bitexact_cb (void *user_data, xine_cfg_entry_t *entry) { + ff_audio_class_t *class = (ff_audio_class_t *)user_data; + + class->bitexact = entry->num_value; +} + void *init_audio_plugin (xine_t *xine, const void *data) { ff_audio_class_t *this ; @@ -1540,5 +1575,12 @@ 10, ff_gain_cb, this) / (float)20); + this->bitexact = xine->config->register_bool (xine->config, + "audio.processing.ffmpeg_bitexact", 0, + _("Let FFmpeg use precise but slower math"), + _("Get slightly better sound, at the expense of speed.\n" + "Takes effect with next stream."), + 10, ff_bitexact_cb, this); + return this; } diff -r d1954d852980 -r 1e7b18400886 src/combined/ffmpeg/ff_video_decoder.c --- a/src/combined/ffmpeg/ff_video_decoder.c Mon Apr 08 13:25:10 2024 +0200 +++ b/src/combined/ffmpeg/ff_video_decoder.c Mon May 06 21:55:55 2024 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2001-2022 the xine project + * Copyright (C) 2001-2024 the xine project * * This file is part of xine, a free video player. * @@ -128,6 +128,7 @@ int64_t pts; int64_t last_pts; + int64_t tagged_pts; int video_step; int reported_video_step; uint8_t pts_tag_pass; @@ -551,7 +552,9 @@ # ifdef XFF_FRAME_AGE av_frame->age = 1; # endif +#ifdef XFF_AVCODEC_REORDERED_OPAQUE av_frame->reordered_opaque = context->reordered_opaque; +#endif ffsf = ffsf_new (this); if (!ffsf) @@ -862,7 +865,9 @@ # endif /* take over pts for this frame to have it reordered */ +#ifdef XFF_AVCODEC_REORDERED_OPAQUE av_frame->reordered_opaque = context->reordered_opaque; +#endif return 0; } @@ -1142,9 +1147,13 @@ if (this->codec->id == CODEC_ID_VC1 && (!this->bih.biWidth || !this->bih.biHeight)) { /* VC1 codec must be re-opened with correct width and height. */ - avcodec_close(this->context); - - if (XFF_AVCODEC_OPEN (this->context, this->codec) < 0) { + if (this->context) { + _x_freep (&this->context->extradata); + this->context->extradata_size = 0; + XFF_FREE_CONTEXT (this->context); + } + this->context = XFF_ALLOC_CONTEXT (); + if (!(this->context && XFF_AVCODEC_OPEN (this->context, this->codec) >= 0)) { pthread_mutex_unlock(&ffmpeg_lock); xprintf (this->stream->xine, XINE_VERBOSITY_LOG, _("ffmpeg_video_dec: couldn't open decoder (pass 2)\n")); @@ -1211,6 +1220,11 @@ /* dont want initial AV_NOPTS_VALUE here */ this->context->reordered_opaque = 0; #endif + +#ifdef XFF_AVCODEC_FRAME_PTS + this->context->time_base.num = 1; + this->context->time_base.den = 90000 << 8; +#endif } #ifdef ENABLE_VAAPI @@ -1959,7 +1973,26 @@ return (pts * 256) | this->pts_tag_pass; } -static int64_t ff_untag_pts (ff_video_decoder_t *this, int64_t pts) { +static int64_t ff_untag_pts (ff_video_decoder_t *this, AVFrame *av_frame) { + int64_t pts; +#if defined(XFF_AVCODEC_FRAME_PTS) + pts = (av_frame->pts != AV_NOPTS_VALUE) ? av_frame->pts : 0; +# if defined(XFF_AVCODEC_REORDERED_OPAQUE) + /* paranoia !!! */ + if (pts != av_frame->reordered_opaque) { + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, + LOG_MODULE ": WARNING: frame pts %" PRId64 " != reordered_opaque %" PRId64 ".\n", + pts, av_frame->reordered_opaque); + pts = av_frame->reordered_opaque; + } + av_frame->reordered_opaque = 0; +# endif +#elif defined(XFF_AVCODEC_REORDERED_OPAQUE) + pts = av_frame->reordered_opaque; + av_frame->reordered_opaque = 0; +#else + pts = this->tagged_pts; +#endif if ((uint8_t)(pts & 0xff) == this->pts_tag_pass) { /* restore sign. */ return pts >> 8; @@ -1984,7 +2017,9 @@ this->avpkt->data = buf; this->avpkt->size = buf_size; this->avpkt->flags = AV_PKT_FLAG_KEY; - +# ifdef XFF_AVCODEC_FRAME_PTS + this->avpkt->pts = this->tagged_pts; +# endif # if XFF_PALETTE == 2 || XFF_PALETTE == 3 if (buf && this->palette_changed) { uint8_t *sd = av_packet_new_side_data (this->avpkt, AV_PKT_DATA_PALETTE, 256 * 4); @@ -2094,9 +2129,14 @@ #endif /* apply valid pts to first frame _starting_ thereafter only */ - if (this->pts && !this->context->reordered_opaque) { - this->context->reordered_opaque = - this->av_frame->reordered_opaque = ff_tag_pts (this, this->pts); + if (this->pts && !this->tagged_pts) { + this->tagged_pts = ff_tag_pts (this, this->pts); +#ifdef XFF_AVCODEC_REORDERED_OPAQUE + this->context->reordered_opaque = this->av_frame->reordered_opaque = this->tagged_pts; +#endif +#ifdef XFF_AVCODEC_FRAME_PTS + this->av_frame->pts = this->tagged_pts; +#endif this->pts = 0; } @@ -2207,9 +2247,11 @@ img->top_field_first = this->av_frame->top_field_first; /* get back reordered pts */ - img->pts = ff_untag_pts (this, this->av_frame->reordered_opaque); - this->av_frame->reordered_opaque = 0; + img->pts = ff_untag_pts (this, this->av_frame); + this->tagged_pts = 0; +#ifdef XFF_AVCODEC_REORDERED_OPAQUE this->context->reordered_opaque = 0; +#endif if (this->av_frame->repeat_pict) img->duration = this->video_step * 3 / 2; @@ -2330,9 +2372,14 @@ } if (this->size == 0) { + this->tagged_pts = ff_tag_pts (this, this->pts); /* take over pts when we are about to buffer a frame */ - this->av_frame->reordered_opaque = ff_tag_pts(this, this->pts); - this->context->reordered_opaque = ff_tag_pts(this, this->pts); +#ifdef XFF_AVCODEC_REORDERED_OPAQUE + this->av_frame->reordered_opaque = this->context->reordered_opaque = this->tagged_pts; +#endif +#ifdef XFF_AVCODEC_FRAME_PTS + this->av_frame->pts = this->tagged_pts; +#endif this->pts = 0; } @@ -2405,7 +2452,10 @@ need_unref = 1; #endif /* reset consumed pts value */ - this->context->reordered_opaque = ff_tag_pts(this, 0); + this->tagged_pts = ff_tag_pts (this, 0); +#ifdef XFF_AVCODEC_REORDERED_OPAQUE + this->context->reordered_opaque = this->tagged_pts; +#endif if (err) { @@ -2439,10 +2489,14 @@ ff_check_bufsize(this, this->size); memmove (this->buf, &chunk_buf[offset], this->size); chunk_buf = this->buf; - /* take over pts for next access unit */ - this->av_frame->reordered_opaque = ff_tag_pts(this, this->pts); - this->context->reordered_opaque = ff_tag_pts(this, this->pts); + this->tagged_pts = ff_tag_pts (this, this->pts); +#ifdef XFF_AVCODEC_REORDERED_OPAQUE + this->av_frame->reordered_opaque = this->context->reordered_opaque = this->tagged_pts; +#endif +#ifdef XFF_AVCODEC_FRAME_PTS + this->av_frame->pts = this->tagged_pts; +#endif this->pts = 0; } } @@ -2559,8 +2613,7 @@ ff_convert_frame(this, img, this->av_frame); } - img->pts = ff_untag_pts(this, this->av_frame->reordered_opaque); - this->av_frame->reordered_opaque = 0; + img->pts = ff_untag_pts(this, this->av_frame); /* workaround for weird 120fps streams */ if( video_step_to_use == 750 ) { @@ -2600,8 +2653,7 @@ this->output_format, VO_BOTH_FIELDS|this->frame_flags); /* set PTS to allow early syncing */ - img->pts = ff_untag_pts(this, this->av_frame->reordered_opaque); - this->av_frame->reordered_opaque = 0; + img->pts = ff_untag_pts(this, this->av_frame); img->duration = video_step_to_use; @@ -2783,7 +2835,7 @@ ff_convert_frame (this, img, this->av_frame2); } - img->pts = ff_untag_pts (this, this->av_frame2->reordered_opaque); + img->pts = ff_untag_pts (this, this->av_frame2); if (video_step_to_use == 750) video_step_to_use = 0; @@ -2903,7 +2955,9 @@ if (this->decoder_ok) { pthread_mutex_lock(&ffmpeg_lock); - avcodec_close (this->context); + _x_freep (&this->context->extradata); + this->context->extradata_size = 0; + XFF_FREE_CONTEXT (this->context); pthread_mutex_unlock(&ffmpeg_lock); #ifdef ENABLE_DIRECT_RENDERING @@ -2912,16 +2966,15 @@ this->stream->video_out->close(this->stream->video_out, this->stream); this->decoder_ok = 0; + } else if (this->context) { + _x_freep (&this->context->extradata); + this->context->extradata_size = 0; + XFF_FREE_CONTEXT (this->context); } if (this->slice_offset_table) free (this->slice_offset_table); - if (this->context) { - _x_freep (&this->context->extradata); - this->context->extradata_size = 0; - XFF_FREE_CONTEXT (this->context); - } #if XFF_VIDEO > 1 XFF_PACKET_UNREF (this->avpkt); diff -r d1954d852980 -r 1e7b18400886 src/combined/ffmpeg/ffmpeg_compat.h --- a/src/combined/ffmpeg/ffmpeg_compat.h Mon Apr 08 13:25:10 2024 +0200 +++ b/src/combined/ffmpeg/ffmpeg_compat.h Mon May 06 21:55:55 2024 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000-2022 the xine project + * Copyright (C) 2000-2024 the xine project * * This file is part of xine, a unix video player. * @@ -54,9 +54,16 @@ #endif /* reordered_opaque appeared in libavcodec 51.68.0 */ -#define XFF_AVCODEC_REORDERED_OPAQUE -#if LIBAVCODEC_VERSION_INT < XFF_INT_VERSION(51,68,0) -# undef XFF_AVCODEC_REORDERED_OPAQUE +#if LIBAVCODEC_VERSION_INT >= XFF_INT_VERSION(51,68,0) && LIBAVCODEC_VERSION_INT < XFF_INT_VERSION(60,0,0) +# define XFF_AVCODEC_REORDERED_OPAQUE +#else +# undef XFF_AVCODEC_REORDERED_OPAQUE +#endif + +#if LIBAVCODEC_VERSION_INT >= XFF_INT_VERSION(58,33,100) +# define XFF_AVCODEC_FRAME_PTS +#else +# undef XFF_AVCODEC_FRAME_PTS #endif /* colorspace and color_range were added before 52.29.0 */ @@ -210,9 +217,11 @@ #endif #if LIBAVCODEC_VERSION_INT < XFF_INT_VERSION(55,63,100) -# define XFF_FREE_CONTEXT(pp) do {av_free(pp); pp = NULL;} while (0) +# define XFF_FREE_CONTEXT(pp) do {if (pp) avcodec_close (pp); av_free (pp); pp = NULL;} while (0) +#elif LIBAVCODEC_VERSION_INT < XFF_INT_VERSION(58,33,100) +# define XFF_FREE_CONTEXT(pp) do {if (pp) avcodec_close (pp); avcodec_free_context (&(pp));} while (0) #else -# define XFF_FREE_CONTEXT(pp) avcodec_free_context(&(pp)) +# define XFF_FREE_CONTEXT(pp) avcodec_free_context (&(pp)) #endif #if LIBAVCODEC_VERSION_INT < XFF_INT_VERSION(54,59,100) @@ -303,4 +312,3 @@ #endif /* defined(LIBAVCODEC_VERSION_INT) */ #endif /* XINE_AVCODEC_COMPAT_H */ - diff -r d1954d852980 -r 1e7b18400886 src/dxr3/ffmpeg_encoder.c --- a/src/dxr3/ffmpeg_encoder.c Mon Apr 08 13:25:10 2024 +0200 +++ b/src/dxr3/ffmpeg_encoder.c Mon May 06 21:55:55 2024 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000-2022 the xine project + * Copyright (C) 2000-2024 the xine project * * This file is part of xine, a unix video player. * @@ -127,10 +127,8 @@ unsigned char use_quantizer; if (this->context) { - avcodec_close(this->context); - free(this->context); + XFF_FREE_CONTEXT (this->context); free(this->picture); - this->context = NULL; this->picture = NULL; } @@ -344,10 +342,8 @@ #if XFF_ENCVIDEO > 1 XFF_PACKET_UNREF (this->pkt); #endif - avcodec_close(this->context); XFF_FREE_CONTEXT (this->context); free(this->picture); - this->context = NULL; this->picture = NULL; } return 1;