gst1-libav: fix compilation with ffmpeg5
authorRosen Penev <rosenp@gmail.com>
Thu, 31 Mar 2022 03:22:15 +0000 (20:22 -0700)
committerRosen Penev <rosenp@gmail.com>
Sat, 30 Apr 2022 18:57:23 +0000 (11:57 -0700)
Upstream backport.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
(cherry picked from commit 1717048598443973df96cc30ec4044591b72718b)

multimedia/gst1-libav/patches/020-ffmpeg5.patch [new file with mode: 0644]

diff --git a/multimedia/gst1-libav/patches/020-ffmpeg5.patch b/multimedia/gst1-libav/patches/020-ffmpeg5.patch
new file mode 100644 (file)
index 0000000..b5bd377
--- /dev/null
@@ -0,0 +1,332 @@
+From 6ea56e7fd39c48e718a10b6e69ec214532789a59 Mon Sep 17 00:00:00 2001
+From: Xi Ruoyao <xry111@mengyan1223.wang>
+Date: Mon, 17 Jan 2022 01:33:47 +0800
+Subject: [PATCH] gst-libav: fix build with ffmpeg-5.0.0
+
+Latest ffmpeg has removed avcodec_get_context_defaults(), and its
+documentation says a new AVCodecContext should be allocated for this
+purpose.  The pointer returned by avcodec_find_decoder() is now
+const-qualified so we also need to adjust for it.  And, AVCOL_RANGE_MPEG
+is now rejected with strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL.
+
+Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/1531>
+---
+ ext/libav/gstavauddec.c | 22 ++++------
+ ext/libav/gstavaudenc.c | 40 +++++++++----------
+ .../gst-libav/ext/libav/gstavcodecmap.c       |  7 ++--
+ ext/libav/gstavutils.c  |  2 +-
+ ext/libav/gstavviddec.c | 28 +++++--------
+ ext/libav/gstavvidenc.c | 21 +++++-----
+ 6 files changed, 54 insertions(+), 66 deletions(-)
+
+--- a/ext/libav/gstavauddec.c
++++ b/ext/libav/gstavauddec.c
+@@ -168,12 +168,7 @@ gst_ffmpegauddec_finalize (GObject * obj
+   GstFFMpegAudDec *ffmpegdec = (GstFFMpegAudDec *) object;
+   av_frame_free (&ffmpegdec->frame);
+-
+-  if (ffmpegdec->context != NULL) {
+-    gst_ffmpeg_avcodec_close (ffmpegdec->context);
+-    av_free (ffmpegdec->context);
+-    ffmpegdec->context = NULL;
+-  }
++  avcodec_free_context (&ffmpegdec->context);
+   G_OBJECT_CLASS (parent_class)->finalize (object);
+ }
+@@ -193,14 +188,12 @@ gst_ffmpegauddec_close (GstFFMpegAudDec
+   gst_ffmpeg_avcodec_close (ffmpegdec->context);
+   ffmpegdec->opened = FALSE;
+-  if (ffmpegdec->context->extradata) {
+-    av_free (ffmpegdec->context->extradata);
+-    ffmpegdec->context->extradata = NULL;
+-  }
++  av_freep (&ffmpegdec->context->extradata);
+   if (reset) {
+-    if (avcodec_get_context_defaults3 (ffmpegdec->context,
+-            oclass->in_plugin) < 0) {
++    avcodec_free_context (&ffmpegdec->context);
++    ffmpegdec->context = avcodec_alloc_context3 (oclass->in_plugin);
++    if (ffmpegdec->context == NULL) {
+       GST_DEBUG_OBJECT (ffmpegdec, "Failed to set context defaults");
+       return FALSE;
+     }
+@@ -219,8 +212,9 @@ gst_ffmpegauddec_start (GstAudioDecoder
+   oclass = (GstFFMpegAudDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec));
+   GST_OBJECT_LOCK (ffmpegdec);
+-  gst_ffmpeg_avcodec_close (ffmpegdec->context);
+-  if (avcodec_get_context_defaults3 (ffmpegdec->context, oclass->in_plugin) < 0) {
++  avcodec_free_context (&ffmpegdec->context);
++  ffmpegdec->context = avcodec_alloc_context3 (oclass->in_plugin);
++  if (ffmpegdec->context == NULL) {
+     GST_DEBUG_OBJECT (ffmpegdec, "Failed to set context defaults");
+     GST_OBJECT_UNLOCK (ffmpegdec);
+     return FALSE;
+--- a/ext/libav/gstavaudenc.c
++++ b/ext/libav/gstavaudenc.c
+@@ -175,10 +175,8 @@ gst_ffmpegaudenc_finalize (GObject * obj
+   /* clean up remaining allocated data */
+   av_frame_free (&ffmpegaudenc->frame);
+-  gst_ffmpeg_avcodec_close (ffmpegaudenc->context);
+-  gst_ffmpeg_avcodec_close (ffmpegaudenc->refcontext);
+-  av_free (ffmpegaudenc->context);
+-  av_free (ffmpegaudenc->refcontext);
++  avcodec_free_context (&ffmpegaudenc->context);
++  avcodec_free_context (&ffmpegaudenc->refcontext);
+   G_OBJECT_CLASS (parent_class)->finalize (object);
+ }
+@@ -193,9 +191,9 @@ gst_ffmpegaudenc_start (GstAudioEncoder
+   ffmpegaudenc->opened = FALSE;
+   ffmpegaudenc->need_reopen = FALSE;
+-  gst_ffmpeg_avcodec_close (ffmpegaudenc->context);
+-  if (avcodec_get_context_defaults3 (ffmpegaudenc->context,
+-          oclass->in_plugin) < 0) {
++  avcodec_free_context (&ffmpegaudenc->context);
++  ffmpegaudenc->context = avcodec_alloc_context3 (oclass->in_plugin);
++  if (ffmpegaudenc->context == NULL) {
+     GST_DEBUG_OBJECT (ffmpegaudenc, "Failed to set context defaults");
+     return FALSE;
+   }
+@@ -241,10 +239,10 @@ gst_ffmpegaudenc_set_format (GstAudioEnc
+   /* close old session */
+   if (ffmpegaudenc->opened) {
+-    gst_ffmpeg_avcodec_close (ffmpegaudenc->context);
++    avcodec_free_context (&ffmpegaudenc->context);
+     ffmpegaudenc->opened = FALSE;
+-    if (avcodec_get_context_defaults3 (ffmpegaudenc->context,
+-            oclass->in_plugin) < 0) {
++    ffmpegaudenc->context = avcodec_alloc_context3 (oclass->in_plugin);
++    if (ffmpegaudenc->context == NULL) {
+       GST_DEBUG_OBJECT (ffmpegaudenc, "Failed to set context defaults");
+       return FALSE;
+     }
+@@ -286,11 +284,11 @@ gst_ffmpegaudenc_set_format (GstAudioEnc
+   /* open codec */
+   if (gst_ffmpeg_avcodec_open (ffmpegaudenc->context, oclass->in_plugin) < 0) {
+     gst_caps_unref (allowed_caps);
+-    gst_ffmpeg_avcodec_close (ffmpegaudenc->context);
++    avcodec_free_context (&ffmpegaudenc->context);
+     GST_DEBUG_OBJECT (ffmpegaudenc, "avenc_%s: Failed to open FFMPEG codec",
+         oclass->in_plugin->name);
+-    if (avcodec_get_context_defaults3 (ffmpegaudenc->context,
+-            oclass->in_plugin) < 0)
++    ffmpegaudenc->context = avcodec_alloc_context3 (oclass->in_plugin);
++    if (ffmpegaudenc->context == NULL)
+       GST_DEBUG_OBJECT (ffmpegaudenc, "Failed to set context defaults");
+     if ((oclass->in_plugin->capabilities & AV_CODEC_CAP_EXPERIMENTAL) &&
+@@ -312,10 +310,10 @@ gst_ffmpegaudenc_set_format (GstAudioEnc
+   if (!other_caps) {
+     gst_caps_unref (allowed_caps);
+-    gst_ffmpeg_avcodec_close (ffmpegaudenc->context);
++    avcodec_free_context (&ffmpegaudenc->context);
+     GST_DEBUG ("Unsupported codec - no caps found");
+-    if (avcodec_get_context_defaults3 (ffmpegaudenc->context,
+-            oclass->in_plugin) < 0)
++    ffmpegaudenc->context = avcodec_alloc_context3 (oclass->in_plugin);
++    if (ffmpegaudenc->context == NULL)
+       GST_DEBUG_OBJECT (ffmpegaudenc, "Failed to set context defaults");
+     return FALSE;
+   }
+@@ -331,10 +329,10 @@ gst_ffmpegaudenc_set_format (GstAudioEnc
+   if (!gst_audio_encoder_set_output_format (GST_AUDIO_ENCODER (ffmpegaudenc),
+           icaps)) {
+-    gst_ffmpeg_avcodec_close (ffmpegaudenc->context);
++    avcodec_free_context (&ffmpegaudenc->context);
+     gst_caps_unref (icaps);
+-    if (avcodec_get_context_defaults3 (ffmpegaudenc->context,
+-            oclass->in_plugin) < 0)
++    ffmpegaudenc->context = avcodec_alloc_context3 (oclass->in_plugin);
++    if (ffmpegaudenc->context == NULL)
+       GST_DEBUG_OBJECT (ffmpegaudenc, "Failed to set context defaults");
+     return FALSE;
+   }
+@@ -403,8 +401,8 @@ buffer_info_free (void *opaque, guint8 *
+     gst_buffer_unmap (info->buffer, &info->map);
+     gst_buffer_unref (info->buffer);
+   } else {
+-    av_free (info->ext_data);
+-    av_free (info->ext_data_array);
++    av_freep (&info->ext_data);
++    av_freep (&info->ext_data_array);
+   }
+   g_slice_free (BufferInfo, info);
+ }
+--- a/ext/libav/gstavcodecmap.c
++++ b/ext/libav/gstavcodecmap.c
+@@ -2331,7 +2331,7 @@ gst_ffmpeg_codecid_to_caps (enum AVCodec
+   }
+   if (buildcaps) {
+-    AVCodec *codec;
++    const AVCodec *codec;
+     if ((codec = avcodec_find_decoder (codec_id)) ||
+         (codec = avcodec_find_encoder (codec_id))) {
+@@ -2975,6 +2975,7 @@ gst_ffmpeg_videoinfo_to_context (GstVide
+     context->color_range = AVCOL_RANGE_JPEG;
+   } else {
+     context->color_range = AVCOL_RANGE_MPEG;
++    context->strict_std_compliance = FF_COMPLIANCE_UNOFFICIAL;
+   }
+ }
+@@ -4330,7 +4331,7 @@ gst_ffmpeg_caps_to_codecid (const GstCap
+     audio = TRUE;
+   } else if (!strncmp (mimetype, "audio/x-gst-av-", 15)) {
+     gchar ext[16];
+-    AVCodec *codec;
++    const AVCodec *codec;
+     if (strlen (mimetype) <= 30 &&
+         sscanf (mimetype, "audio/x-gst-av-%s", ext) == 1) {
+@@ -4342,7 +4343,7 @@ gst_ffmpeg_caps_to_codecid (const GstCap
+     }
+   } else if (!strncmp (mimetype, "video/x-gst-av-", 15)) {
+     gchar ext[16];
+-    AVCodec *codec;
++    const AVCodec *codec;
+     if (strlen (mimetype) <= 30 &&
+         sscanf (mimetype, "video/x-gst-av-%s", ext) == 1) {
+--- a/ext/libav/gstavutils.c
++++ b/ext/libav/gstavutils.c
+@@ -36,7 +36,7 @@
+ const gchar *
+ gst_ffmpeg_get_codecid_longname (enum AVCodecID codec_id)
+ {
+-  AVCodec *codec;
++  const AVCodec *codec;
+   /* Let's use what ffmpeg can provide us */
+   if ((codec = avcodec_find_decoder (codec_id)) ||
+--- a/ext/libav/gstavviddec.c
++++ b/ext/libav/gstavviddec.c
+@@ -320,12 +320,7 @@ gst_ffmpegviddec_finalize (GObject * obj
+   GstFFMpegVidDec *ffmpegdec = (GstFFMpegVidDec *) object;
+   av_frame_free (&ffmpegdec->picture);
+-
+-  if (ffmpegdec->context != NULL) {
+-    gst_ffmpeg_avcodec_close (ffmpegdec->context);
+-    av_free (ffmpegdec->context);
+-    ffmpegdec->context = NULL;
+-  }
++  avcodec_free_context (&ffmpegdec->context);
+   G_OBJECT_CLASS (parent_class)->finalize (object);
+ }
+@@ -363,13 +358,11 @@ gst_ffmpegviddec_close (GstFFMpegVidDec
+   gst_buffer_replace (&ffmpegdec->palette, NULL);
+-  if (ffmpegdec->context->extradata) {
+-    av_free (ffmpegdec->context->extradata);
+-    ffmpegdec->context->extradata = NULL;
+-  }
++  av_freep (&ffmpegdec->context->extradata);
+   if (reset) {
+-    if (avcodec_get_context_defaults3 (ffmpegdec->context,
+-            oclass->in_plugin) < 0) {
++    avcodec_free_context (&ffmpegdec->context);
++    ffmpegdec->context = avcodec_alloc_context3 (oclass->in_plugin);
++    if (ffmpegdec->context == NULL) {
+       GST_DEBUG_OBJECT (ffmpegdec, "Failed to set context defaults");
+       return FALSE;
+     }
+@@ -1704,7 +1697,7 @@ gst_ffmpegviddec_video_frame (GstFFMpegV
+     if (side_data) {
+       GST_LOG_OBJECT (ffmpegdec,
+           "Found CC side data of type AV_FRAME_DATA_A53_CC, size %d",
+-          side_data->size);
++          (int) side_data->size);
+       GST_MEMDUMP ("A53 CC", side_data->data, side_data->size);
+       /* do not add closed caption meta if it already exists */
+@@ -1966,8 +1959,9 @@ gst_ffmpegviddec_start (GstVideoDecoder
+   oclass = (GstFFMpegVidDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec));
+   GST_OBJECT_LOCK (ffmpegdec);
+-  gst_ffmpeg_avcodec_close (ffmpegdec->context);
+-  if (avcodec_get_context_defaults3 (ffmpegdec->context, oclass->in_plugin) < 0) {
++  avcodec_free_context (&ffmpegdec->context);
++  ffmpegdec->context = avcodec_alloc_context3 (oclass->in_plugin);
++  if (ffmpegdec->context == NULL) {
+     GST_DEBUG_OBJECT (ffmpegdec, "Failed to set context defaults");
+     GST_OBJECT_UNLOCK (ffmpegdec);
+     return FALSE;
+@@ -2261,10 +2255,10 @@ gst_ffmpegviddec_get_property (GObject *
+   switch (prop_id) {
+     case PROP_LOWRES:
+-      g_value_set_enum (value, ffmpegdec->context->lowres);
++      g_value_set_enum (value, ffmpegdec->lowres);
+       break;
+     case PROP_SKIPFRAME:
+-      g_value_set_enum (value, ffmpegdec->context->skip_frame);
++      g_value_set_enum (value, ffmpegdec->skip_frame);
+       break;
+     case PROP_DIRECT_RENDERING:
+       g_value_set_boolean (value, ffmpegdec->direct_rendering);
+--- a/ext/libav/gstavvidenc.c
++++ b/ext/libav/gstavvidenc.c
+@@ -224,8 +224,8 @@ gst_ffmpegvidenc_finalize (GObject * obj
+   av_frame_free (&ffmpegenc->picture);
+   gst_ffmpeg_avcodec_close (ffmpegenc->context);
+   gst_ffmpeg_avcodec_close (ffmpegenc->refcontext);
+-  av_free (ffmpegenc->context);
+-  av_free (ffmpegenc->refcontext);
++  av_freep (&ffmpegenc->context);
++  av_freep (&ffmpegenc->refcontext);
+   G_OBJECT_CLASS (parent_class)->finalize (object);
+ }
+@@ -247,10 +247,10 @@ gst_ffmpegvidenc_set_format (GstVideoEnc
+   /* close old session */
+   if (ffmpegenc->opened) {
+-    gst_ffmpeg_avcodec_close (ffmpegenc->context);
++    avcodec_free_context (&ffmpegenc->context);
+     ffmpegenc->opened = FALSE;
+-    if (avcodec_get_context_defaults3 (ffmpegenc->context,
+-            oclass->in_plugin) < 0) {
++    ffmpegenc->context = avcodec_alloc_context3 (oclass->in_plugin);
++    if (ffmpegenc->context == NULL) {
+       GST_DEBUG_OBJECT (ffmpegenc, "Failed to set context defaults");
+       return FALSE;
+     }
+@@ -454,9 +454,9 @@ bad_input_fmt:
+   }
+ close_codec:
+   {
+-    gst_ffmpeg_avcodec_close (ffmpegenc->context);
+-    if (avcodec_get_context_defaults3 (ffmpegenc->context,
+-            oclass->in_plugin) < 0)
++    avcodec_free_context (&ffmpegenc->context);
++    ffmpegenc->context = avcodec_alloc_context3 (oclass->in_plugin);
++    if (ffmpegenc->context == NULL)
+       GST_DEBUG_OBJECT (ffmpegenc, "Failed to set context defaults");
+     goto cleanup_stats_in;
+   }
+@@ -896,8 +896,9 @@ gst_ffmpegvidenc_start (GstVideoEncoder
+   ffmpegenc->need_reopen = FALSE;
+   /* close old session */
+-  gst_ffmpeg_avcodec_close (ffmpegenc->context);
+-  if (avcodec_get_context_defaults3 (ffmpegenc->context, oclass->in_plugin) < 0) {
++  avcodec_free_context (&ffmpegenc->context);
++  ffmpegenc->context = avcodec_alloc_context3 (oclass->in_plugin);
++  if (ffmpegenc->context == NULL) {
+     GST_DEBUG_OBJECT (ffmpegenc, "Failed to set context defaults");
+     return FALSE;
+   }