git: 14fa97f2f662 - main - multimedia/libxine: incorporate more ffmpeg patches

From: Baptiste Daroussin <bapt_at_FreeBSD.org>
Date: Fri, 19 Dec 2025 16:09:02 UTC
The branch main has been updated by bapt:

URL: https://cgit.FreeBSD.org/ports/commit/?id=14fa97f2f6622f568908ae501c9a390641115a7e

commit 14fa97f2f6622f568908ae501c9a390641115a7e
Author:     Baptiste Daroussin <bapt@FreeBSD.org>
AuthorDate: 2025-12-19 16:06:51 +0000
Commit:     Baptiste Daroussin <bapt@FreeBSD.org>
CommitDate: 2025-12-19 16:08:47 +0000

    multimedia/libxine: incorporate more ffmpeg patches
    
    Incorporate more patches from upstream to address compatibility with
    ffmpeg7 and 8.
    
    Directly export them from upstream mercurial to ease tracking
---
 multimedia/libxine/Makefile                        |  11 +-
 .../0a786d63bbdb2d780a9231f6772e84e743c72014.patch |  67 +++
 .../1e7b184008860c8be2289c3cefd9dee57f06193a.patch | 475 +++++++++++++++++++++
 .../6f1000084f6084f49c95c202d12593e49916f58b.patch | 161 +++++++
 .../73b833e7fe356cd2d9490dda4ebc9bfe16fce958.patch | 318 ++++++++++++++
 ...771f4ae27e582123ff3500444718fc8f96186d74.patch} |  70 ++-
 ...9bb3977ea7e2b652742b3cdd200b0a4a72eb48bc.patch} |  14 +
 ...a8fffd1193b2247c7f732d4df83dcc03fce96dbe.patch} |   0
 .../patch-src_combined_ffmpeg_demux__avformat.c    |  35 --
 9 files changed, 1101 insertions(+), 50 deletions(-)

diff --git a/multimedia/libxine/Makefile b/multimedia/libxine/Makefile
index e3f6a2d82ad7..b8ca9980f6d7 100644
--- a/multimedia/libxine/Makefile
+++ b/multimedia/libxine/Makefile
@@ -32,8 +32,15 @@ LIB_DEPENDS=	libFLAC.so:audio/flac \
 		libogg.so:audio/libogg \
 		libdvdnav.so:multimedia/libdvdnav
 
-EXTRA_PATCHES=	${FILESDIR}/ffmpeg8-1.patch:-p1 \
-		${FILESDIR}/ffmpeg8-2.patch:-p1
+# patch obtain via hg export -r <rev>
+EXTRA_PATCHES=	\
+		${FILESDIR}/771f4ae27e582123ff3500444718fc8f96186d74.patch:-p1 \
+		${FILESDIR}/0a786d63bbdb2d780a9231f6772e84e743c72014.patch:-p1 \
+		${FILESDIR}/6f1000084f6084f49c95c202d12593e49916f58b.patch:-p1 \
+		${FILESDIR}/1e7b184008860c8be2289c3cefd9dee57f06193a.patch:-p1 \
+		${FILESDIR}/73b833e7fe356cd2d9490dda4ebc9bfe16fce958.patch:-p1 \
+		${FILESDIR}/9bb3977ea7e2b652742b3cdd200b0a4a72eb48bc.patch:-p1 \
+		${FILESDIR}/a8fffd1193b2247c7f732d4df83dcc03fce96dbe.patch:-p1
 
 USES=		compiler cpe gl gmake gnome iconv libtool:keepla jpeg \
 		localbase pathfix perl5 pkgconfig tar:xz xorg
diff --git a/multimedia/libxine/files/0a786d63bbdb2d780a9231f6772e84e743c72014.patch b/multimedia/libxine/files/0a786d63bbdb2d780a9231f6772e84e743c72014.patch
new file mode 100644
index 000000000000..d792fbc858df
--- /dev/null
+++ b/multimedia/libxine/files/0a786d63bbdb2d780a9231f6772e84e743c72014.patch
@@ -0,0 +1,67 @@
+# HG changeset patch
+# User Torsten Jager <t.jager@gmx.de>
+# Date 1675683900 -3600
+#      Mon Feb 06 12:45:00 2023 +0100
+# Node ID 0a786d63bbdb2d780a9231f6772e84e743c72014
+# Parent  b0a36ed8ec8f3f2de545502b93ec846561168b64
+Try to silence some cast align warnings 4.
+
+diff -r b0a36ed8ec8f -r 0a786d63bbdb src/combined/ffmpeg/ff_video_decoder.c
+--- a/src/combined/ffmpeg/ff_video_decoder.c	Mon Feb 06 12:44:55 2023 +0100
++++ b/src/combined/ffmpeg/ff_video_decoder.c	Mon Feb 06 12:45:00 2023 +0100
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (C) 2001-2022 the xine project
++ * Copyright (C) 2001-2023 the xine project
+  *
+  * This file is part of xine, a free video player.
+  *
+@@ -1398,7 +1398,7 @@
+ #if defined(AV_PIX_FMT_YUV420P9) || defined(AV_PIX_FMT_YUV420P10)
+ static void ff_get_deep_color (uint8_t *src, int sstride, uint8_t *dest, int dstride,
+   int width, int height, uint8_t *tab) {
+-  uint16_t *p = (uint16_t *) src;
++  uint16_t *p = (uint16_t *)ASSUME_ALIGNED_2 (src, 2);
+   uint8_t  *q = dest;
+   int       spad = sstride / 2 - width;
+   int       dpad = dstride - width;
+@@ -1804,22 +1804,24 @@
+ #ifdef XFF_AVCODEC_SUB_ID
+         this->context->sub_id = _X_BE_32(&this->buf[30]);
+ #endif
+-        this->context->extradata_size = this->size - 26;
+-	if (this->context->extradata_size < 8) {
+-	  this->context->extradata_size= 8;
+-	  this->context->extradata = calloc(1, this->context->extradata_size +
+-                                            AV_INPUT_BUFFER_PADDING_SIZE);
+-          ((uint32_t *)this->context->extradata)[0] = 0;
+-	  if (codec_type == BUF_VIDEO_RV10)
+-	     ((uint32_t *)this->context->extradata)[1] = 0x10000000;
+-	  else
+-	     ((uint32_t *)this->context->extradata)[1] = 0x10003001;
++        if (this->size < 8 + 26) {
++          uint32_t *b = calloc (1, 8 + AV_INPUT_BUFFER_PADDING_SIZE);
++          if (b) {
++            this->context->extradata_size = 8;
++            this->context->extradata = (uint8_t *)b;
++            b[0] = 0;
++            if (codec_type == BUF_VIDEO_RV10)
++              b[1] = 0x10000000;
++            else
++              b[1] = 0x10003001;
++          }
+ 	} else {
+-          this->context->extradata = malloc(this->context->extradata_size +
+-                                            AV_INPUT_BUFFER_PADDING_SIZE);
+-	  memcpy(this->context->extradata, this->buf + 26,
+-	         this->context->extradata_size);
+-          memset(this->context->extradata + this->context->extradata_size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
++          this->context->extradata = malloc (this->size - 26 + AV_INPUT_BUFFER_PADDING_SIZE);
++          if (this->context->extradata) {
++            this->context->extradata_size = this->size - 26;
++            memcpy (this->context->extradata, this->buf + 26, this->context->extradata_size);
++            memset (this->context->extradata + this->context->extradata_size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
++          }
+ 	}
+ 
+ 	xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
diff --git a/multimedia/libxine/files/1e7b184008860c8be2289c3cefd9dee57f06193a.patch b/multimedia/libxine/files/1e7b184008860c8be2289c3cefd9dee57f06193a.patch
new file mode 100644
index 000000000000..b6b4040a8478
--- /dev/null
+++ b/multimedia/libxine/files/1e7b184008860c8be2289c3cefd9dee57f06193a.patch
@@ -0,0 +1,475 @@
+# HG changeset patch
+# User Torsten Jager <t.jager@gmx.de>
+# 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-2023 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;
diff --git a/multimedia/libxine/files/6f1000084f6084f49c95c202d12593e49916f58b.patch b/multimedia/libxine/files/6f1000084f6084f49c95c202d12593e49916f58b.patch
new file mode 100644
index 000000000000..36b07bb7e0a0
--- /dev/null
+++ b/multimedia/libxine/files/6f1000084f6084f49c95c202d12593e49916f58b.patch
@@ -0,0 +1,161 @@
+# HG changeset patch
+# User Torsten Jager <t.jager@gmx.de>
+# Date 1675683905 -3600
+#      Mon Feb 06 12:45:05 2023 +0100
+# Node ID 6f1000084f6084f49c95c202d12593e49916f58b
+# Parent  0a786d63bbdb2d780a9231f6772e84e743c72014
+Try to silence some cast align warnings 5.
+
+diff -r 0a786d63bbdb -r 6f1000084f60 src/combined/ffmpeg/ff_audio_decoder.c
+--- a/src/combined/ffmpeg/ff_audio_decoder.c	Mon Feb 06 12:45:00 2023 +0100
++++ b/src/combined/ffmpeg/ff_audio_decoder.c	Mon Feb 06 12:45:05 2023 +0100
+@@ -796,7 +796,7 @@
+ #define CLIP_16(v) ((v + 0x8000) & ~0xffff ? (v >> 31) ^ 0x7fff : v)
+ 
+ static int ff_audio_decode (ff_audio_decoder_t *this) {
+-  int16_t *decode_buffer = (int16_t *)this->send.buf;
++  int16_t *decode_buffer = (int16_t *)ASSUME_ALIGNED_2 (this->send.buf, 2);
+   int consumed, got_frame = 0;
+ #if XFF_AUDIO >= 4
+   float gain = this->class->gain;
+@@ -871,13 +871,13 @@
+     const stype *p1, *p2, *p3, *p4;\
+     int i, sstep;\
+     int8_t *x = idx;\
+-    int16_t *dptr = (int16_t *)decode_buffer + dindx;\
++    int16_t *dptr = decode_buffer + dindx;\
+     if (planar) {\
+-      p1 = (stype *)this->av_frame->extended_data[x[0]];\
++      p1 = (stype *)ASSUME_ALIGNED_2 (this->av_frame->extended_data[x[0]], sizeof (stype));\
+       if (!p1) break;\
+       sstep = 1;\
+     } else {\
+-      p1 = (stype *)this->av_frame->extended_data[0];\
++      p1 = (stype *)ASSUME_ALIGNED_2 (this->av_frame->extended_data[0], sizeof (stype));\
+       if (!p1) break;\
+       p1 += x[0];\
+       sstep = this->ff_channels;\
+@@ -893,10 +893,10 @@
+       break;\
+     }\
+     if (planar) {\
+-      p2 = (stype *)this->av_frame->extended_data[x[1]];\
++      p2 = (stype *)ASSUME_ALIGNED_2 (this->av_frame->extended_data[x[1]], sizeof (stype));\
+       if (!p2) break;\
+     } else\
+-      p2 = (stype *)this->av_frame->extended_data[0] + x[1];\
++      p2 = (stype *)ASSUME_ALIGNED_2 (this->av_frame->extended_data[0], sizeof (stype)) + x[1];\
+     if (num == 2) {\
+       for (i = 0; i < samples; i++) {\
+         int32_t v = MIX_FIX(*p2);\
+@@ -911,10 +911,10 @@
+       break;\
+     }\
+     if (planar) {\
+-      p3 = (stype *)this->av_frame->extended_data[x[2]];\
++      p3 = (stype *)ASSUME_ALIGNED_2 (this->av_frame->extended_data[x[2]], sizeof (stype));\
+       if (!p3) break;\
+     } else\
+-      p3 = (stype *)this->av_frame->extended_data[0] + x[2];\
++      p3 = (stype *)ASSUME_ALIGNED_2 (this->av_frame->extended_data[0], sizeof (stype)) + x[2];\
+     if (num == 3) {\
+       for (i = 0; i < samples; i++) {\
+         int32_t v = MIX_FIX(*p2);\
+@@ -931,10 +931,10 @@
+       break;\
+     }\
+     if (planar) {\
+-      p4 = (stype *)this->av_frame->extended_data[x[3]];\
++      p4 = (stype *)ASSUME_ALIGNED_2 (this->av_frame->extended_data[x[3]], sizeof (stype));\
+       if (!p4) break;\
+     } else\
+-      p4 = (stype *)this->av_frame->extended_data[0] + x[3];\
++      p4 = (stype *)ASSUME_ALIGNED_2 (this->av_frame->extended_data[0], sizeof (stype)) + x[3];\
+     for (i = 0; i < samples; i++) {\
+       int32_t v = MIX_FIX(*p2);\
+       p2       += sstep;\
+@@ -1003,13 +1003,13 @@
+     int i, sstep;\
+     float gain3;\
+     int8_t *x = idx;\
+-    int16_t *dptr = (int16_t *)decode_buffer + dindx;\
++    int16_t *dptr = decode_buffer + dindx;\
+     if (planar) {\
+-      p1 = (stype *)this->av_frame->extended_data[x[0]];\
++      p1 = (stype *)ASSUME_ALIGNED_2 (this->av_frame->extended_data[x[0]], sizeof (stype));\
+       if (!p1) break;\
+       sstep = 1;\
+     } else {\
+-      p1 = (stype *)this->av_frame->extended_data[0];\
++      p1 = (stype *)ASSUME_ALIGNED_2 (this->av_frame->extended_data[0], sizeof (stype));\
+       if (!p1) break;\
+       p1 += x[0];\
+       sstep = this->ff_channels;\
+@@ -1025,10 +1025,10 @@
+     }\
+     gain3 = gain * 0.7071;\
+     if (planar) {\
+-      p2 = (stype *)this->av_frame->extended_data[x[1]];\
++      p2 = (stype *)ASSUME_ALIGNED_2 (this->av_frame->extended_data[x[1]], sizeof (stype));\
+       if (!p2) break;\
+     } else\
+-      p2 = (stype *)this->av_frame->extended_data[0] + x[1];\
++      p2 = (stype *)ASSUME_ALIGNED_2 (this->av_frame->extended_data[0], sizeof (stype)) + x[1];\
+     if (num == 2) {\
+       for (i = 0; i < samples; i++) {\
+         int32_t v = (*p1) * gain + (*p2) * gain3;\
+@@ -1040,10 +1040,10 @@
+       break;\
+     }\
+     if (planar) {\
+-      p3 = (stype *)this->av_frame->extended_data[x[2]];\
++      p3 = (stype *)ASSUME_ALIGNED_2 (this->av_frame->extended_data[x[2]], sizeof (stype));\
+       if (!p3) break;\
+     } else\
+-      p3 = (stype *)this->av_frame->extended_data[0] + x[2];\
++      p3 = (stype *)ASSUME_ALIGNED_2 (this->av_frame->extended_data[0], sizeof (stype)) + x[2];\
+     if (num == 3) {\
+       for (i = 0; i < samples; i++) {\
+         int32_t v = (*p1) * gain + (*p2 + *p3) * gain3;\
+@@ -1056,10 +1056,10 @@
+       break;\
+     }\
+     if (planar) {\
+-      p4 = (stype *)this->av_frame->extended_data[x[3]];\
++      p4 = (stype *)ASSUME_ALIGNED_2 (this->av_frame->extended_data[x[3]], sizeof (stype));\
+       if (!p4) break;\
+     } else\
+-      p4 = (stype *)this->av_frame->extended_data[0] + x[3];\
++      p4 = (stype *)ASSUME_ALIGNED_2 (this->av_frame->extended_data[0], sizeof (stype)) + x[3];\
+     for (i = 0; i < samples; i++) {\
+       int32_t v = (*p1) * gain + (*p2 + *p3 + *p4) * gain3;\
+       p1       += sstep;\
+@@ -1240,8 +1240,8 @@
+             /* the above codecs output float samples, not 16-bit integers */
+             int samples = this->send.len / sizeof(float);
+             float gain  = this->class->gain;
+-            float *p    = (float *)this->decode_buffer;
+-            int16_t *q  = (int16_t *)this->decode_buffer;
++            float *p    = (float *)ASSUME_ALIGNED_2 (this->decode_buffer, 4);
++            int16_t *q  = (int16_t *)ASSUME_ALIGNED_2 (this->decode_buffer, 2);
+             int i;
+             for (i = samples; i; i--) {
+               int v = *p++ * gain;
+@@ -1255,7 +1255,7 @@
+             int samples     = this->send.len / (this->ff_channels * 2);
+             int channels    = this->ao_channels;
+             int ff_channels = this->ff_channels;
+-            int16_t *p      = (int16_t *)this->decode_buffer;
++            int16_t *p      = (int16_t *)ASSUME_ALIGNED_2 (this->decode_buffer, 2);
+             int16_t *q      = p;
+             int shift       = this->downmix_shift, i, j;
+             /* downmix mono output to stereo first */
+@@ -1300,7 +1300,7 @@
+             }
+             /* final mono downmix */
+             if (channels > this->ao_channels) {
+-              p = (int16_t *)this->decode_buffer;
++              p = (int16_t *)ASSUME_ALIGNED_2 (this->decode_buffer, 2);
+               q = p;
+               for (i = samples; i; i--) {
+                 int v = *p++;
diff --git a/multimedia/libxine/files/73b833e7fe356cd2d9490dda4ebc9bfe16fce958.patch b/multimedia/libxine/files/73b833e7fe356cd2d9490dda4ebc9bfe16fce958.patch
new file mode 100644
index 000000000000..136750404be2
--- /dev/null
+++ b/multimedia/libxine/files/73b833e7fe356cd2d9490dda4ebc9bfe16fce958.patch
@@ -0,0 +1,318 @@
+# HG changeset patch
+# User Torsten Jager <t.jager@gmx.de>
+# Date 1715160885 -7200
+#      Wed May 08 11:34:45 2024 +0200
+# Node ID 73b833e7fe356cd2d9490dda4ebc9bfe16fce958
+# Parent  1e7b184008860c8be2289c3cefd9dee57f06193a
+ffmpeg compatibility update 2.
+
+diff -r 1e7b18400886 -r 73b833e7fe35 src/combined/ffmpeg/ff_audio_decoder.c
+--- a/src/combined/ffmpeg/ff_audio_decoder.c	Mon May 06 21:55:55 2024 +0200
++++ b/src/combined/ffmpeg/ff_audio_decoder.c	Wed May 08 11:34:45 2024 +0200
+@@ -1393,6 +1393,9 @@
+       XFF_FREE_FRAME (this->av_frame);
+     }
+ #endif
++#if 1
++    avcodec_flush_buffers (this->context);
++#else
+     pthread_mutex_lock (&ffmpeg_lock);
+     {
+       uint8_t *ed = this->context->extradata;
+@@ -1410,6 +1413,7 @@
+     if (XFF_AVCODEC_OPEN (this->context, this->codec) >= 0)
+       this->decoder_ok = 1;
+     pthread_mutex_unlock (&ffmpeg_lock);
++#endif
+   }
+ 
+   ff_audio_reset_parser(this);
+diff -r 1e7b18400886 -r 73b833e7fe35 src/combined/ffmpeg/ff_video_decoder.c
+--- a/src/combined/ffmpeg/ff_video_decoder.c	Mon May 06 21:55:55 2024 +0200
++++ b/src/combined/ffmpeg/ff_video_decoder.c	Wed May 08 11:34:45 2024 +0200
+@@ -89,6 +89,11 @@
+ # define ENABLE_EMMS
+ #endif
+ 
++/*
++#undef XFF_AVCODEC_SLICE_TABLE
++#define XFF_AVCODEC_SLICE_TABLE 1
++*/
++
+ #define VIDEOBUFSIZE        (128*1024)
+ #define SLICE_BUFFER_SIZE   (1194*1024)
+ 
+@@ -148,11 +153,11 @@
+   int               bufsize;
+   int               size;
+   int               skipframes;
+-
++#if XFF_AVCODEC_SLICE_TABLE == 1
+   int              *slice_offset_table;
+   int               slice_offset_size;
+   int               slice_offset_pos;
+-
++#endif
+   AVFrame          *av_frame;
+   AVFrame          *av_frame2;
+   AVCodecContext   *context;
+@@ -238,6 +243,13 @@
+ #if XFF_VIDEO > 1
+   XFF_PACKET_DECL (avpkt);
+ #endif
++
++#if XFF_AVCODEC_SLICE_TABLE == 2
++  uint8_t          *temp_buf;
++  uint32_t          temp_size;
++  int               slice_num;
++  uint8_t           slice_table[1 + 256 * 8];
++#endif
+ };
+ 
+ /* import color matrix names */
+@@ -1783,10 +1795,9 @@
+   this->size += buf->size;
+ 
+   if (buf->decoder_flags & BUF_FLAG_FRAME_END) {
+-    int codec_type;
++    uint32_t codec_type = buf->type & 0xFFFF0000;
+ 
+     lprintf ("header complete\n");
+-    codec_type = buf->type & 0xFFFF0000;
+ 
+     if (buf->decoder_flags & BUF_FLAG_STDHEADER) {
+ 
+@@ -1912,33 +1923,44 @@
+ #endif
+   }
+   else if (buf->decoder_info[1] == BUF_SPECIAL_RV_CHUNK_TABLE) {
+-    /* o dear. Multiple decoding threads use individual contexts.
+-      av_decode_video2 () does only copy the _pointer_ to the offsets,
+-      not the offsets themselves. So we must not overwrite anything
+-      that another thread has not yet read. */
+-    int i, l, total;
+-
+-    lprintf("BUF_SPECIAL_RV_CHUNK_TABLE\n");
+-    l = buf->decoder_info[2] + 1;
+-
+-    total = l * this->class->thread_count;
+-    if (total < SLICE_OFFSET_SIZE)
+-      total = SLICE_OFFSET_SIZE;
+-    if (total > this->slice_offset_size) {
+-      this->slice_offset_table = realloc (this->slice_offset_table, total * sizeof (int));
+-      this->slice_offset_size = total;
+-    }
+-
+-    if (this->slice_offset_pos + l > this->slice_offset_size)
+-      this->slice_offset_pos = 0;
+-    this->context->slice_offset = this->slice_offset_table + this->slice_offset_pos;
+-    this->context->slice_count = l;
+-
+-    lprintf ("slice_count=%d\n", l);
+-    for (i = 0; i < l; i++) {
+-      this->slice_offset_table[this->slice_offset_pos++] =
+-        ((uint32_t *)buf->decoder_info_ptr[2])[(2 * i) + 1];
+-      lprintf("slice_offset[%d]=%d\n", i, this->context->slice_offset[i]);
++    {
++#if XFF_AVCODEC_SLICE_TABLE == 1
++      /* o dear. Multiple decoding threads use individual contexts.
++       * av_decode_video2 () does only copy the _pointer_ to the offsets,
++       * not the offsets themselves. So we must not overwrite anything
++       * that another thread has not yet read. */
++      int i, l, total;
++
++      lprintf("BUF_SPECIAL_RV_CHUNK_TABLE\n");
++      l = buf->decoder_info[2] + 1;
++
++      total = l * this->class->thread_count;
++      if (total < SLICE_OFFSET_SIZE)
++        total = SLICE_OFFSET_SIZE;
++      if (total > this->slice_offset_size) {
++        this->slice_offset_table = realloc (this->slice_offset_table, total * sizeof (int));
++        this->slice_offset_size = total;
++      }
++
++      if (this->slice_offset_pos + l > this->slice_offset_size)
++        this->slice_offset_pos = 0;
++      this->context->slice_offset = this->slice_offset_table + this->slice_offset_pos;
++      this->context->slice_count = l;
++
++      lprintf ("slice_count=%d\n", l);
++      for (i = 0; i < l; i++) {
++        this->slice_offset_table[this->slice_offset_pos++] =
++          ((uint32_t *)buf->decoder_info_ptr[2])[(2 * i) + 1];
++        lprintf("slice_offset[%d]=%d\n", i, this->context->slice_offset[i]);
++      }
++#elif XFF_AVCODEC_SLICE_TABLE == 2
++      /* (count-1):1, 1:4, (offs[0]):4, 1:4, (offs[1]:4, ... just in front of the frame bitstream.
++       * reverse engineered from ffmpeg/libavcodec/rv34.c. they seem to expect no
++       * external use of rv decoders, and did not document this. */
++      this->slice_table[0] = buf->decoder_info[2];
++      this->slice_num = this->slice_table[0] + 1;
++      memcpy (this->slice_table + 1, buf->decoder_info_ptr[2], 8 * this->slice_num);
++#endif
+     }
+   }
+ }
+@@ -2004,6 +2026,7 @@
+ 
+ static int decode_video_wrapper (ff_video_decoder_t *this,
+   AVFrame *av_frame, int *err, void *buf, size_t buf_size) {
++  uint32_t tsize = 0;
+   int len;
+ 
+ #if ENABLE_VAAPI
+@@ -2013,9 +2036,32 @@
+   }
+ #endif /* ENABLE_VAAPI */
+ 
++#if XFF_AVCODEC_SLICE_TABLE == 2
++  if ((this->slice_num > 0) && buf) {
++    uint32_t nsize;
++    tsize = 1 + this->slice_num * 8;
++    nsize = tsize + buf_size + AV_INPUT_BUFFER_PADDING_SIZE;
++    if (this->temp_size < nsize) {
++      nsize = nsize * 3 / 2;
++      free (this->temp_buf);
++      this->temp_buf = malloc (nsize);
++      if (!this->temp_buf)
++        nsize = 0;
++      this->temp_size = nsize;
++      nsize = tsize + buf_size + AV_INPUT_BUFFER_PADDING_SIZE;
++    }
++    if (this->temp_size >= nsize) {
++      memcpy (this->temp_buf, this->slice_table, tsize);
++      memcpy (this->temp_buf + tsize, buf, buf_size + AV_INPUT_BUFFER_PADDING_SIZE);
++      buf = this->temp_buf;
++    }
++    this->slice_num = 0;
++  }
++#endif
++
+ #if XFF_VIDEO > 1
+   this->avpkt->data = buf;
+-  this->avpkt->size = buf_size;
++  this->avpkt->size = buf_size + tsize;
+   this->avpkt->flags = AV_PKT_FLAG_KEY;
+ # ifdef XFF_AVCODEC_FRAME_PTS
+   this->avpkt->pts = this->tagged_pts;
+@@ -2486,7 +2532,6 @@
+           this->size -= len;
+ 
+           if (this->size > 0) {
+-            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 */
+@@ -2615,8 +2660,8 @@
+ 
+         img->pts  = ff_untag_pts(this, this->av_frame);
+ 
*** 315 LINES SKIPPED ***