Fix build error due to upgrade to ffmpeg 7.1 36/321036/2 accepted/tizen_unified accepted/tizen_unified_x tizen tizen_gst_1.24.9 accepted/tizen/unified/20241202.132936 accepted/tizen/unified/x/20241218.032649
authorhjkim <backto.kim@samsung.com>
Wed, 27 Nov 2024 01:18:33 +0000 (10:18 +0900)
committerhjkim <backto.kim@samsung.com>
Thu, 28 Nov 2024 08:17:35 +0000 (17:17 +0900)
All patches are from gst-libav-1.24.9

Change-Id: I02fdb4e79ad3a5a47948a67f1164a763dcc41b42

12 files changed:
packaging/gstreamer.spec
subprojects/gst-libav/ext/libav/gstavauddec.c
subprojects/gst-libav/ext/libav/gstavaudenc.c
subprojects/gst-libav/ext/libav/gstavcfg.c
subprojects/gst-libav/ext/libav/gstavcodecmap.c
subprojects/gst-libav/ext/libav/gstavcodecmap.h
subprojects/gst-libav/ext/libav/gstavdemux.c
subprojects/gst-libav/ext/libav/gstavmux.c
subprojects/gst-libav/ext/libav/gstavprotocol.c
subprojects/gst-libav/ext/libav/gstavviddec.c
subprojects/gst-libav/ext/libav/gstavviddec.h
subprojects/gst-libav/ext/libav/gstavvidenc.c

index bcec5b1f7708664b59d68b4ce7ba6180f35b73c8..efad099e1dedff27e0f5aea74d25e6dbb84f7178 100644 (file)
@@ -62,7 +62,7 @@
 
 Name:           %{_name}
 Version:        1.22.8
-Release:        16
+Release:        17
 Summary:        Streaming-Media Framework Runtime
 License:        LGPL-2.0+
 Group:          Multimedia/Framework
index 597cb547bc4bbf7287c04c97692a52d6de3d040b..3f711d8a296975fcc3eb040f4a68b70a2a937d0a 100644 (file)
@@ -364,10 +364,14 @@ settings_changed (GstFFMpegAudDec * ffmpegdec, AVFrame * frame)
 {
   GstAudioFormat format;
   GstAudioLayout layout;
+#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100)
+  const gint channels = frame->ch_layout.nb_channels;
+#else
   gint channels = av_get_channel_layout_nb_channels (frame->channel_layout);
 
   if (channels == 0)
     channels = frame->channels;
+#endif
 
   format = gst_ffmpeg_smpfmt_to_audioformat (frame->format, &layout);
   if (format == GST_AUDIO_FORMAT_UNKNOWN)
@@ -394,9 +398,13 @@ gst_ffmpegauddec_negotiate (GstFFMpegAudDec * ffmpegdec,
   format = gst_ffmpeg_smpfmt_to_audioformat (frame->format, &layout);
   if (format == GST_AUDIO_FORMAT_UNKNOWN)
     goto no_caps;
+#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100)
+  channels = frame->ch_layout.nb_channels;
+#else
   channels = av_get_channel_layout_nb_channels (frame->channel_layout);
   if (channels == 0)
     channels = frame->channels;
+#endif
   if (channels == 0)
     goto no_caps;
 
@@ -412,7 +420,11 @@ gst_ffmpegauddec_negotiate (GstFFMpegAudDec * ffmpegdec,
       frame->sample_rate, channels, format,
       layout == GST_AUDIO_LAYOUT_INTERLEAVED);
 
+#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100)
+  gst_ffmpeg_channel_layout_to_gst (&frame->ch_layout, channels, pos);
+#else
   gst_ffmpeg_channel_layout_to_gst (frame->channel_layout, channels, pos);
+#endif
   memcpy (ffmpegdec->ffmpeg_layout, pos,
       sizeof (GstAudioChannelPosition) * channels);
 
@@ -578,7 +590,11 @@ gst_ffmpegauddec_frame (GstFFMpegAudDec * ffmpegdec, GstFlowReturn * ret,
     goto no_codec;
 
   *ret = GST_FLOW_OK;
+#if LIBAVCODEC_VERSION_MAJOR >= 60
+  ffmpegdec->context->frame_num++;
+#else
   ffmpegdec->context->frame_number++;
+#endif
 
   oclass = (GstFFMpegAudDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec));
 
index 05e04aa063364c65adfb0f3cf458fcbb97868f3e..cf85fa826e6143a1c7e0c207f7ced078c341fdad 100644 (file)
@@ -258,7 +258,17 @@ gst_ffmpegaudenc_set_format (GstAudioEncoder * encoder, GstAudioInfo * info)
     ffmpegaudenc->context->time_base.num = 1;
     ffmpegaudenc->context->ticks_per_frame = 1;
   }
-
+#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100)
+  if (ffmpegaudenc->context->ch_layout.order != AV_CHANNEL_ORDER_UNSPEC) {
+    gst_ffmpeg_channel_layout_to_gst (&ffmpegaudenc->context->ch_layout,
+        ffmpegaudenc->context->ch_layout.nb_channels,
+        ffmpegaudenc->ffmpeg_layout);
+    ffmpegaudenc->needs_reorder =
+        (memcmp (ffmpegaudenc->ffmpeg_layout, info->position,
+            sizeof (GstAudioChannelPosition) *
+            ffmpegaudenc->context->ch_layout.nb_channels) != 0);
+  }
+#else
   if (ffmpegaudenc->context->channel_layout) {
     gst_ffmpeg_channel_layout_to_gst (ffmpegaudenc->context->channel_layout,
         ffmpegaudenc->context->channels, ffmpegaudenc->ffmpeg_layout);
@@ -267,6 +277,7 @@ gst_ffmpegaudenc_set_format (GstAudioEncoder * encoder, GstAudioInfo * info)
             sizeof (GstAudioChannelPosition) *
             ffmpegaudenc->context->channels) != 0);
   }
+#endif
 
   /* some codecs support more than one format, first auto-choose one */
   GST_DEBUG_OBJECT (ffmpegaudenc, "picking an output format ...");
@@ -441,8 +452,13 @@ gst_ffmpegaudenc_send_frame (GstFFMpegAudEnc * ffmpegaudenc, GstBuffer * buffer)
     planar = av_sample_fmt_is_planar (ffmpegaudenc->context->sample_fmt);
     frame->format = ffmpegaudenc->context->sample_fmt;
     frame->sample_rate = ffmpegaudenc->context->sample_rate;
+#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100)
+    av_channel_layout_copy (&frame->ch_layout,
+        &ffmpegaudenc->context->ch_layout);
+#else
     frame->channels = ffmpegaudenc->context->channels;
     frame->channel_layout = ffmpegaudenc->context->channel_layout;
+#endif
 
     if (planar && info->channels > 1) {
       gint channels;
index d3deb12b7b98c68087a11d7791ccc42a8edb8029..29ecdae810860b5f33042f87cd54a45ce8a32327 100644 (file)
@@ -391,7 +391,9 @@ install_opts (GObjectClass * gobject_class, const AVClass ** obj, guint prop_id,
         break;
         /* TODO: didn't find options for the video encoders with
          * the following type, add support if needed */
+#if LIBAVUTIL_VERSION_MAJOR < 59
       case AV_OPT_TYPE_CHANNEL_LAYOUT:
+#endif
       case AV_OPT_TYPE_COLOR:
       case AV_OPT_TYPE_VIDEO_RATE:
       case AV_OPT_TYPE_SAMPLE_FMT:
index bc2becbd612dd2dac1548ba246d97297f5c8280a..a4d4af6d76ecb7140afa0e8630baf2188cfda650 100644 (file)
@@ -66,19 +66,39 @@ static const struct
   AV_CH_STEREO_RIGHT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT}
 };
 
+#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100)
+static void
+gst_ffmpeg_channel_positions_to_layout (const GstAudioChannelPosition *
+    const pos, gint channels, AVChannelLayout * layout)
+#else
 static guint64
-gst_ffmpeg_channel_positions_to_layout (GstAudioChannelPosition * pos,
-    gint channels)
+gst_ffmpeg_channel_positions_to_layout (const GstAudioChannelPosition *
+    const pos, gint channels)
+#endif
 {
   gint i, j;
   guint64 ret = 0;
   gint channels_found = 0;
 
+#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100)
+  g_assert (layout);
+
+  if (!pos) {
+    memset (layout, 0, sizeof (AVChannelLayout));
+    return;
+  }
+
+  if (channels == 1 && pos[0] == GST_AUDIO_CHANNEL_POSITION_MONO) {
+    *layout = (AVChannelLayout) AV_CHANNEL_LAYOUT_MONO;
+    return;
+  }
+#else
   if (!pos)
     return 0;
 
   if (channels == 1 && pos[0] == GST_AUDIO_CHANNEL_POSITION_MONO)
     return AV_CH_LAYOUT_MONO;
+#endif
 
   for (i = 0; i < channels; i++) {
     for (j = 0; j < G_N_ELEMENTS (_ff_to_gst_layout); j++) {
@@ -90,19 +110,42 @@ gst_ffmpeg_channel_positions_to_layout (GstAudioChannelPosition * pos,
     }
   }
 
+#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100)
+  if (channels_found != channels && av_channel_layout_check (layout)) {
+    memset (layout, 0, sizeof (AVChannelLayout));
+    return;
+  }
+
+  layout->u.mask = ret;
+  layout->nb_channels = channels_found;
+  layout->order = AV_CHANNEL_ORDER_NATIVE;
+#else
   if (channels_found != channels)
     return 0;
   return ret;
+#endif
 }
 
+#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100)
+gboolean
+gst_ffmpeg_channel_layout_to_gst (const AVChannelLayout * channel_layout,
+    gint channels, GstAudioChannelPosition * pos)
+#else
 gboolean
 gst_ffmpeg_channel_layout_to_gst (guint64 channel_layout, gint channels,
     GstAudioChannelPosition * pos)
+#endif
 {
   guint nchannels = 0;
   gboolean none_layout = FALSE;
 
+#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100)
+  g_assert (channel_layout);
+
+  if (channel_layout->nb_channels == 0 || channels > 64) {
+#else
   if (channel_layout == 0 || channels > 64) {
+#endif
     nchannels = channels;
     none_layout = TRUE;
   } else {
@@ -112,16 +155,25 @@ gst_ffmpeg_channel_layout_to_gst (guint64 channel_layout, gint channels,
      * as FRONT_CENTER but we distinguish between the two in
      * GStreamer
      */
+#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100)
+    static const AVChannelLayout mono = AV_CHANNEL_LAYOUT_MONO;
+    if (channels == 1
+        && (av_channel_layout_compare (channel_layout, &mono) == 0)) {
+#else
     if (channels == 1 && channel_layout == AV_CH_LAYOUT_MONO) {
+#endif
       pos[0] = GST_AUDIO_CHANNEL_POSITION_MONO;
       return TRUE;
     }
-
+#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100)
+    nchannels = channel_layout->nb_channels;
+#else
     for (i = 0; i < 64; i++) {
       if ((channel_layout & (G_GUINT64_CONSTANT (1) << i)) != 0) {
         nchannels++;
       }
     }
+#endif
 
     if (nchannels != channels) {
       GST_ERROR ("Number of channels is different (%u != %u)", channels,
@@ -131,12 +183,30 @@ gst_ffmpeg_channel_layout_to_gst (guint64 channel_layout, gint channels,
     } else {
 
       for (i = 0, j = 0; i < G_N_ELEMENTS (_ff_to_gst_layout); i++) {
+#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100)
+        if (channel_layout->order == AV_CHANNEL_ORDER_NATIVE) {
+          if ((channel_layout->u.mask & _ff_to_gst_layout[i].ff) != 0) {
+            pos[j++] = _ff_to_gst_layout[i].gst;
+
+            if (_ff_to_gst_layout[i].gst == GST_AUDIO_CHANNEL_POSITION_NONE)
+              none_layout = TRUE;
+          }
+        } else if (channel_layout->order == AV_CHANNEL_ORDER_CUSTOM) {
+          if (_ff_to_gst_layout[i].ff == (1ULL << channel_layout->u.map[i].id)) {
+            pos[j++] = _ff_to_gst_layout[i].gst;
+
+            if (_ff_to_gst_layout[i].gst == GST_AUDIO_CHANNEL_POSITION_NONE)
+              none_layout = TRUE;
+          }
+        }
+#else
         if ((channel_layout & _ff_to_gst_layout[i].ff) != 0) {
           pos[j++] = _ff_to_gst_layout[i].gst;
 
           if (_ff_to_gst_layout[i].gst == GST_AUDIO_CHANNEL_POSITION_NONE)
             none_layout = TRUE;
         }
+#endif
       }
 
       if (j != nchannels) {
@@ -149,8 +219,13 @@ gst_ffmpeg_channel_layout_to_gst (guint64 channel_layout, gint channels,
 
   if (!none_layout
       && !gst_audio_check_valid_channel_positions (pos, nchannels, FALSE)) {
+#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100)
+    GST_ERROR ("Invalid channel layout %" G_GUINT64_FORMAT
+        " - assuming NONE layout", channel_layout->u.mask);
+#else
     GST_ERROR ("Invalid channel layout %" G_GUINT64_FORMAT
         " - assuming NONE layout", channel_layout);
+#endif
     none_layout = TRUE;
   }
 
@@ -548,10 +623,32 @@ gst_ff_aud_caps_new (AVCodecContext * context, AVCodec * codec,
   va_list var_args;
 
   /* fixed, non-probing context */
+#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100)
+  if (context != NULL && context->ch_layout.nb_channels > 0) {
+#else
   if (context != NULL && context->channels != -1) {
+#endif
     GstAudioChannelPosition pos[64];
     guint64 mask;
 
+#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100)
+    caps = gst_caps_new_simple (mimetype,
+        "rate", G_TYPE_INT, context->sample_rate,
+        "channels", G_TYPE_INT, context->ch_layout.nb_channels, NULL);
+
+    static const AVChannelLayout mono = AV_CHANNEL_LAYOUT_MONO;
+    const gboolean needs_mask = (context->ch_layout.nb_channels == 1 &&
+        av_channel_layout_compare (&context->ch_layout, &mono) != 0)
+        || (context->ch_layout.nb_channels > 1
+        && gst_ffmpeg_channel_layout_to_gst (&context->ch_layout,
+            context->ch_layout.nb_channels, pos));
+
+    if (needs_mask &&
+        gst_audio_channel_positions_to_mask (pos,
+            context->ch_layout.nb_channels, FALSE, &mask)) {
+      gst_caps_set_simple (caps, "channel-mask", GST_TYPE_BITMASK, mask, NULL);
+    }
+#else
     caps = gst_caps_new_simple (mimetype,
         "rate", G_TYPE_INT, context->sample_rate,
         "channels", G_TYPE_INT, context->channels, NULL);
@@ -563,6 +660,7 @@ gst_ff_aud_caps_new (AVCodecContext * context, AVCodec * codec,
             &mask)) {
       gst_caps_set_simple (caps, "channel-mask", GST_TYPE_BITMASK, mask, NULL);
     }
+#endif
   } else if (encode) {
     gint maxchannels = 2;
     const gint *rates = NULL;
@@ -654,15 +752,30 @@ gst_ff_aud_caps_new (AVCodecContext * context, AVCodec * codec,
         break;
     }
 
+#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100)
+    if (codec && codec->ch_layouts) {
+      const AVChannelLayout *layouts = codec->ch_layouts;
+#else
     if (codec && codec->channel_layouts) {
       const uint64_t *layouts = codec->channel_layouts;
+#endif
       GstAudioChannelPosition pos[64];
 
       caps = gst_caps_new_empty ();
+#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100)
+      // Layout array is terminated with a zeroed layout.
+      AVChannelLayout zero;
+      memset (&zero, 0, sizeof (AVChannelLayout));
+      while (av_channel_layout_compare (layouts, &zero) != 0) {
+        const gint nbits_set = layouts->nb_channels;
+
+        if (gst_ffmpeg_channel_layout_to_gst (layouts, nbits_set, pos)) {
+#else
       while (*layouts) {
         gint nbits_set = get_nbits_set (*layouts);
 
         if (gst_ffmpeg_channel_layout_to_gst (*layouts, nbits_set, pos)) {
+#endif
           guint64 mask;
 
           if (gst_audio_channel_positions_to_mask (pos, nbits_set, FALSE,
@@ -2605,7 +2718,12 @@ gst_ffmpeg_caps_to_smpfmt (const GstCaps * caps,
 
   structure = gst_caps_get_structure (caps, 0);
 
+#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100)
+  gst_structure_get_int (structure, "channels",
+      &context->ch_layout.nb_channels);
+#else
   gst_structure_get_int (structure, "channels", &context->channels);
+#endif
   gst_structure_get_int (structure, "rate", &context->sample_rate);
   gst_structure_get_int (structure, "block_align", &context->block_align);
   if (gst_structure_get_int (structure, "bitrate", &bitrate))
@@ -3015,10 +3133,15 @@ gst_ffmpeg_audioinfo_to_context (GstAudioInfo * info, AVCodecContext * context)
   const enum AVSampleFormat *smpl_fmts;
   enum AVSampleFormat smpl_fmt = -1;
 
-  context->channels = info->channels;
   context->sample_rate = info->rate;
+#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100)
+  gst_ffmpeg_channel_positions_to_layout (info->position, info->channels,
+      &context->ch_layout);
+#else
+  context->channels = info->channels;
   context->channel_layout =
       gst_ffmpeg_channel_positions_to_layout (info->position, info->channels);
+#endif
 
   codec = context->codec;
 
@@ -3457,7 +3580,11 @@ gst_ffmpeg_caps_with_codecid (enum AVCodecID codec_id,
       if ((layout = gst_structure_get_string (str, "layout"))) {
         if (!strcmp (layout, "g721")) {
           context->sample_rate = 8000;
+#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100)
+          context->ch_layout = (AVChannelLayout) AV_CHANNEL_LAYOUT_MONO;
+#else
           context->channels = 1;
+#endif
           context->bit_rate = 32000;
         }
       }
@@ -3499,7 +3626,11 @@ gst_ffmpeg_caps_with_codecid (enum AVCodecID codec_id,
   switch (codec_id) {
     case AV_CODEC_ID_QCELP:
       /* QCELP is always mono, no matter what the caps say */
+#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100)
+      context->ch_layout = (AVChannelLayout) AV_CHANNEL_LAYOUT_MONO;
+#else
       context->channels = 1;
+#endif
       break;
     case AV_CODEC_ID_ADPCM_G726:
       if (context->sample_rate && context->bit_rate)
index b7f1f203227c8c846405f68d7122f31a82e8caca..aa4c0423bb53e5bb4791131797f9ba54445f1f7b 100644 (file)
@@ -126,8 +126,14 @@ gst_ffmpeg_formatid_get_codecids (const gchar *format_name,
                                  AVOutputFormat * plugin);
 
 
+#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100)
+gboolean
+gst_ffmpeg_channel_layout_to_gst (const AVChannelLayout * channel_layout, gint channels,
+    GstAudioChannelPosition * pos);
+#else
 gboolean
 gst_ffmpeg_channel_layout_to_gst (guint64 channel_layout, gint channels,
     GstAudioChannelPosition * pos);
+#endif
 
 #endif /* __GST_FFMPEG_CODECMAP_H__ */
index 63c7e7b098b79008cafae7676951b3134432c0bc..f959419e89277883750e05eb046533ec47e0f65f 100644 (file)
@@ -1371,63 +1371,6 @@ beach:
   }
 }
 
-#define GST_FFMPEG_TYPE_FIND_SIZE 4096
-#define GST_FFMPEG_TYPE_FIND_MIN_SIZE 256
-
-static void
-gst_ffmpegdemux_type_find (GstTypeFind * tf, gpointer priv)
-{
-  const guint8 *data;
-  AVInputFormat *in_plugin = (AVInputFormat *) priv;
-  gint res = 0;
-  guint64 length;
-  GstCaps *sinkcaps;
-
-  /* We want GST_FFMPEG_TYPE_FIND_SIZE bytes, but if the file is shorter than
-   * that we'll give it a try... */
-  length = gst_type_find_get_length (tf);
-  if (length == 0 || length > GST_FFMPEG_TYPE_FIND_SIZE)
-    length = GST_FFMPEG_TYPE_FIND_SIZE;
-
-  /* The ffmpeg typefinders assume there's a certain minimum amount of data
-   * and will happily do invalid memory access if there isn't, so let's just
-   * skip the ffmpeg typefinders if the data available is too short
-   * (in which case it's unlikely to be a media file anyway) */
-  if (length < GST_FFMPEG_TYPE_FIND_MIN_SIZE) {
-    GST_LOG ("not typefinding %" G_GUINT64_FORMAT " bytes, too short", length);
-    return;
-  }
-
-  GST_LOG ("typefinding %" G_GUINT64_FORMAT " bytes", length);
-  if (in_plugin->read_probe &&
-      (data = gst_type_find_peek (tf, 0, length)) != NULL) {
-    AVProbeData probe_data;
-
-    probe_data.filename = "";
-    probe_data.buf = (guint8 *) data;
-    probe_data.buf_size = length;
-
-    res = in_plugin->read_probe (&probe_data);
-    if (res > 0) {
-      res = MAX (1, res * GST_TYPE_FIND_MAXIMUM / AVPROBE_SCORE_MAX);
-      /* Restrict the probability for MPEG-TS streams, because there is
-       * probably a better version in plugins-base, if the user has a recent
-       * plugins-base (in fact we shouldn't even get here for ffmpeg mpegts or
-       * mpegtsraw typefinders, since we blacklist them) */
-      if (g_str_has_prefix (in_plugin->name, "mpegts"))
-        res = MIN (res, GST_TYPE_FIND_POSSIBLE);
-
-      sinkcaps = gst_ffmpeg_formatid_to_caps (in_plugin->name);
-
-      GST_LOG ("libav typefinder '%s' suggests %" GST_PTR_FORMAT ", p=%u%%",
-          in_plugin->name, sinkcaps, res);
-
-      gst_type_find_suggest (tf, res, sinkcaps);
-      gst_caps_unref (sinkcaps);
-    }
-  }
-}
-
 /* Task */
 static void
 gst_ffmpegdemux_loop (GstFFMpegDemux * demux)
@@ -2182,11 +2125,7 @@ gst_ffmpegdemux_register (GstPlugin * plugin)
     else
       extensions = NULL;
 
-    if (!gst_element_register (plugin, type_name, rank, type) ||
-        (register_typefind_func == TRUE &&
-            !gst_type_find_register (plugin, typefind_name, rank,
-                gst_ffmpegdemux_type_find, extensions, NULL,
-                (gpointer) in_plugin, NULL))) {
+    if (!gst_element_register (plugin, type_name, rank, type)) {
       g_warning ("Registration of type %s failed", type_name);
       g_free (type_name);
       g_free (typefind_name);
index bcbafd510d89d234dd8e043734b88ec5eb186138..b5814bcdaaee37c57c813023dcbbcba3284e457d 100644 (file)
@@ -266,14 +266,14 @@ update_expected_trailer_size (GstFFMpegMux * ffmpegmux)
     sti = ffstream(ffmpegmux->context->streams[i]);
     codec_context = ffmpegmux->context->streams[i]->codecpar;
     if (codec_context->codec_type == AVMEDIA_TYPE_VIDEO) {
-      nb_video_frames += sti->avctx->frame_number;
+      nb_video_frames += sti->avctx->frame_num;
       nb_video_i_frames += codec_context->i_frame_number;
       nb_video_stts_entry += codec_context->stts_count;
 
       video_stream = TRUE;
       video_codec_id = codec_context->codec_id;
     } else if (codec_context->codec_type == AVMEDIA_TYPE_AUDIO) {
-      nb_audio_frames += sti->avctx->frame_number;
+      nb_audio_frames += sti->avctx->frame_num;
       nb_audio_stts_entry += codec_context->stts_count;
 
       audio_stream = TRUE;
index 249b24064275b964ad2e42c1b6f627553ef3824f..cb607d30129996f07b252a259060c58e75e9ab72 100644 (file)
@@ -102,7 +102,11 @@ gst_ffmpegdata_read (void *priv_data, unsigned char *buf, int size)
 }
 
 static int
+#if LIBAVUTIL_VERSION_MAJOR >= 59
+gst_ffmpegdata_write (void *priv_data, const uint8_t * buf, int size)
+#else
 gst_ffmpegdata_write (void *priv_data, uint8_t * buf, int size)
+#endif
 {
   GstProtocolInfo *info;
   GstBuffer *outbuf;
index 0e8a6a8f1e7244300d712ce51639a2f02afd7027..92d1bc67b6d46ee178dfa68d27deb1cc8ab2f41c 100644 (file)
@@ -337,14 +337,7 @@ gst_ffmpegviddec_init (GstFFMpegVidDec * ffmpegdec)
 static void
 gst_ffmpegviddec_subinit (GstFFMpegVidDec * ffmpegdec)
 {
-  GstFFMpegVidDecClass *klass =
-      (GstFFMpegVidDecClass *) G_OBJECT_GET_CLASS (ffmpegdec);
-
   /* some ffmpeg data */
-  ffmpegdec->context = avcodec_alloc_context3 (klass->in_plugin);
-  ffmpegdec->context->opaque = ffmpegdec;
-  ffmpegdec->picture = av_frame_alloc ();
-  ffmpegdec->opened = FALSE;
   ffmpegdec->skip_frame = ffmpegdec->lowres = 0;
   ffmpegdec->direct_rendering = DEFAULT_DIRECT_RENDERING;
   ffmpegdec->max_threads = DEFAULT_MAX_THREADS;
@@ -365,6 +358,8 @@ gst_ffmpegviddec_finalize (GObject * object)
   GstFFMpegVidDec *ffmpegdec = GST_FFMPEGVIDDEC (object);
 
   av_frame_free (&ffmpegdec->picture);
+  if (ffmpegdec->context)
+    av_freep (&ffmpegdec->context->extradata);
   avcodec_free_context (&ffmpegdec->context);
 
   G_OBJECT_CLASS (parent_class)->finalize (object);
@@ -395,37 +390,23 @@ gst_ffmpegviddec_context_set_flags2 (AVCodecContext * context, guint flags,
 }
 
 /* with LOCK */
-static gboolean
-gst_ffmpegviddec_close (GstFFMpegVidDec * ffmpegdec, gboolean reset)
+static void
+gst_ffmpegviddec_close (GstFFMpegVidDec * ffmpegdec)
 {
-  GstFFMpegVidDecClass *oclass;
   guint i;
 
-  oclass = GST_FFMPEGVIDDEC_GET_CLASS (ffmpegdec);
-
   GST_LOG_OBJECT (ffmpegdec, "closing ffmpeg codec");
 
   gst_caps_replace (&ffmpegdec->last_caps, NULL);
 
-  gst_ffmpeg_avcodec_close (ffmpegdec->context);
-  ffmpegdec->opened = FALSE;
+  if (ffmpegdec->context)
+    av_freep (&ffmpegdec->context->extradata);
+  avcodec_free_context (&ffmpegdec->context);
 
   for (i = 0; i < G_N_ELEMENTS (ffmpegdec->stride); i++)
     ffmpegdec->stride[i] = -1;
 
   gst_buffer_replace (&ffmpegdec->palette, NULL);
-
-  av_freep (&ffmpegdec->context->extradata);
-  if (reset) {
-    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;
-    }
-    ffmpegdec->context->opaque = ffmpegdec;
-  }
-  return TRUE;
 }
 
 /* with LOCK */
@@ -443,20 +424,22 @@ gst_ffmpegviddec_open (GstFFMpegVidDec * ffmpegdec)
   for (i = 0; i < G_N_ELEMENTS (ffmpegdec->stride); i++)
     ffmpegdec->stride[i] = -1;
 
-  ffmpegdec->opened = TRUE;
-
   GST_LOG_OBJECT (ffmpegdec, "Opened libav codec %s, id %d",
       oclass->in_plugin->name, oclass->in_plugin->id);
 
   gst_ffmpegviddec_context_set_flags (ffmpegdec->context,
       AV_CODEC_FLAG_OUTPUT_CORRUPT, ffmpegdec->output_corrupt);
+#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT (60, 31, 100)
+  gst_ffmpegviddec_context_set_flags (ffmpegdec->context,
+      AV_CODEC_FLAG_COPY_OPAQUE, TRUE);
+#endif
 
   return TRUE;
 
   /* ERRORS */
 could_not_open:
   {
-    gst_ffmpegviddec_close (ffmpegdec, TRUE);
+    gst_ffmpegviddec_close (ffmpegdec);
     GST_DEBUG_OBJECT (ffmpegdec, "avdec_%s: Failed to open libav codec",
         oclass->in_plugin->name);
     return FALSE;
@@ -533,14 +516,11 @@ gst_ffmpegviddec_set_format (GstVideoDecoder * decoder,
   }
 
   /* close old session */
-  if (ffmpegdec->opened) {
+  if (ffmpegdec->context) {
     GST_OBJECT_UNLOCK (ffmpegdec);
     gst_ffmpegviddec_finish (decoder);
     GST_OBJECT_LOCK (ffmpegdec);
-    if (!gst_ffmpegviddec_close (ffmpegdec, TRUE)) {
-      GST_OBJECT_UNLOCK (ffmpegdec);
-      return FALSE;
-    }
+    gst_ffmpegviddec_close (ffmpegdec);
     ffmpegdec->pic_pix_fmt = 0;
     ffmpegdec->pic_width = 0;
     ffmpegdec->pic_height = 0;
@@ -556,6 +536,14 @@ gst_ffmpegviddec_set_format (GstVideoDecoder * decoder,
     ffmpegdec->cur_multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
   }
 
+  ffmpegdec->context = avcodec_alloc_context3 (oclass->in_plugin);
+  if (ffmpegdec->context == NULL) {
+    GST_DEBUG_OBJECT (ffmpegdec, "Failed to allocate context");
+    GST_OBJECT_UNLOCK (ffmpegdec);
+    return FALSE;
+  }
+  ffmpegdec->context->opaque = ffmpegdec;
+
   gst_caps_replace (&ffmpegdec->last_caps, state->caps);
 
   /* set buffer functions */
@@ -673,10 +661,23 @@ update_state:
   /* Use the framerate values stored in the decoder for calculating latency. The
    * upstream framerate might not be set but we still want to report a latency
    * if needed. */
+#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(60, 31, 100)
+  if (ffmpegdec->context->time_base.den && ffmpegdec->context->codec_descriptor
+      && ffmpegdec->context->codec_descriptor->props) {
+#else
   if (ffmpegdec->context->time_base.den && ffmpegdec->context->ticks_per_frame) {
-    gint fps_n = ffmpegdec->context->time_base.den;
-    gint fps_d =
-        ffmpegdec->context->time_base.num * ffmpegdec->context->ticks_per_frame;
+#endif
+    const gint fps_n = ffmpegdec->context->time_base.den;
+#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(60, 31, 100)
+    const gint ticks_per_frame =
+        (GST_VIDEO_INFO_IS_INTERLACED (&ffmpegdec->input_state->info)
+        && ffmpegdec->context->codec_descriptor
+        && ffmpegdec->context->
+        codec_descriptor->props & AV_CODEC_PROP_FIELDS) ? 2 : 1;
+#else
+    const gint ticks_per_frame = ffmpegdec->context->ticks_per_frame;
+#endif
+    const gint fps_d = ffmpegdec->context->time_base.num * ticks_per_frame;
     if (fps_n) {
       latency = gst_util_uint64_scale_ceil (
           (ffmpegdec->context->has_b_frames) * GST_SECOND, fps_d, fps_n);
@@ -703,12 +704,18 @@ done:
 open_failed:
   {
     GST_DEBUG_OBJECT (ffmpegdec, "Failed to open");
+    if (ffmpegdec->context)
+      av_freep (&ffmpegdec->context->extradata);
+    avcodec_free_context (&ffmpegdec->context);
     goto done;
   }
 nal_only_slice:
   {
     GST_ERROR_OBJECT (ffmpegdec,
         "Can't do NAL aligned H.264 with frame threading.");
+    if (ffmpegdec->context)
+      av_freep (&ffmpegdec->context->extradata);
+    avcodec_free_context (&ffmpegdec->context);
     goto done;
   }
 }
@@ -729,11 +736,12 @@ gst_ffmpegviddec_video_frame_new (GstFFMpegVidDec * ffmpegdec,
 {
   GstFFMpegVidDecVideoFrame *dframe;
 
-  dframe = g_slice_new0 (GstFFMpegVidDecVideoFrame);
+  dframe = g_new0 (GstFFMpegVidDecVideoFrame, 1);
   dframe->ffmpegdec = ffmpegdec;
   dframe->frame = frame;
 
-  GST_DEBUG_OBJECT (ffmpegdec, "new video frame %p", dframe);
+  GST_DEBUG_OBJECT (ffmpegdec, "new video frame %p for sfn # %d", dframe,
+      frame->system_frame_number);
 
   return dframe;
 }
@@ -742,7 +750,8 @@ static void
 gst_ffmpegviddec_video_frame_free (GstFFMpegVidDec * ffmpegdec,
     GstFFMpegVidDecVideoFrame * frame)
 {
-  GST_DEBUG_OBJECT (ffmpegdec, "free video frame %p", frame);
+  GST_DEBUG_OBJECT (ffmpegdec, "free video frame %p for sfn # %d", frame,
+      frame->frame->system_frame_number);
 
   if (frame->mapped)
     gst_video_frame_unmap (&frame->vframe);
@@ -753,7 +762,7 @@ gst_ffmpegviddec_video_frame_free (GstFFMpegVidDec * ffmpegdec,
   if (frame->avbuffer) {
     av_buffer_unref (&frame->avbuffer);
   }
-  g_slice_free (GstFFMpegVidDecVideoFrame, frame);
+  g_free (frame);
 }
 
 static void
@@ -910,6 +919,18 @@ gst_ffmpegviddec_can_direct_render (GstFFMpegVidDec * ffmpegdec)
       AV_CODEC_CAP_DR1);
 }
 
+#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT (60, 31, 100)
+static void
+gst_ffmpeg_opaque_free (void *opaque, guint8 * data)
+{
+  GstVideoCodecFrame *frame = (GstVideoCodecFrame *) opaque;
+
+  GST_DEBUG ("Releasing frame %p", frame);
+
+  gst_video_codec_frame_unref (frame);
+}
+#endif
+
 /* called when ffmpeg wants us to allocate a buffer to write the decoded frame
  * into. We try to give it memory from our pool */
 static int
@@ -922,20 +943,36 @@ gst_ffmpegviddec_get_buffer2 (AVCodecContext * context, AVFrame * picture,
   guint c;
   GstFlowReturn ret;
   int create_buffer_flags = 0;
+  gint system_frame_number = 0;
 
   ffmpegdec = GST_FFMPEGVIDDEC (context->opaque);
 
+  GST_DEBUG_OBJECT (ffmpegdec, "flags %d", flags);
   GST_DEBUG_OBJECT (ffmpegdec, "getting buffer picture %p", picture);
 
   /* apply the last info we have seen to this picture, when we get the
    * picture back from ffmpeg we can use this to correctly timestamp the output
    * buffer */
-  GST_DEBUG_OBJECT (ffmpegdec, "opaque value SN %d",
-      (gint32) picture->reordered_opaque);
+#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT (60, 31, 100)
+  {
+    GstVideoCodecFrame *input_frame =
+        av_buffer_get_opaque (picture->opaque_ref);
+    g_assert (input_frame != NULL);
+
+    GST_DEBUG_OBJECT (ffmpegdec, "input_frame %p", input_frame);
+    /* ******************************* */
+    /* Test if the stored frame in the opaque matches the one video decoder has for that ref ! */
+    system_frame_number = input_frame->system_frame_number;
+  }
+#else
+  system_frame_number = (gint) picture->reordered_opaque;
+#endif
+  GST_DEBUG_OBJECT (ffmpegdec, "opaque value SN %d", system_frame_number);
 
   frame =
       gst_video_decoder_get_frame (GST_VIDEO_DECODER (ffmpegdec),
-      picture->reordered_opaque);
+      system_frame_number);
+
   if (G_UNLIKELY (frame == NULL))
     goto no_frame;
 
@@ -951,15 +988,15 @@ gst_ffmpegviddec_get_buffer2 (AVCodecContext * context, AVFrame * picture,
 
   /* GstFFMpegVidDecVideoFrame receives the frame ref */
   if (picture->opaque) {
+    GST_DEBUG_OBJECT (ffmpegdec, "Re-using opaque %p", picture->opaque);
     dframe = picture->opaque;
     dframe->frame = frame;
   } else {
     picture->opaque = dframe =
         gst_ffmpegviddec_video_frame_new (ffmpegdec, frame);
+    GST_DEBUG_OBJECT (ffmpegdec, "storing opaque %p", dframe);
   }
 
-  GST_DEBUG_OBJECT (ffmpegdec, "storing opaque %p", dframe);
-
   if (!gst_ffmpegviddec_can_direct_render (ffmpegdec))
     goto no_dr;
 
@@ -1085,10 +1122,18 @@ picture_changed (GstFFMpegVidDec * ffmpegdec, AVFrame * picture,
 
   if (one_field) {
     pic_field_order = ffmpegdec->pic_field_order;
+#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(60, 31, 100)
+  } else if (picture->flags & AV_FRAME_FLAG_INTERLACED) {
+#else
   } else if (picture->interlaced_frame) {
+#endif
     if (picture->repeat_pict)
       pic_field_order |= GST_VIDEO_BUFFER_FLAG_RFF;
+#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(60, 31, 100)
+    if (picture->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST)
+#else
     if (picture->top_field_first)
+#endif
       pic_field_order |= GST_VIDEO_BUFFER_FLAG_TFF;
   }
 
@@ -1097,7 +1142,12 @@ picture_changed (GstFFMpegVidDec * ffmpegdec, AVFrame * picture,
       && ffmpegdec->pic_pix_fmt == picture->format
       && ffmpegdec->pic_par_n == picture->sample_aspect_ratio.num
       && ffmpegdec->pic_par_d == picture->sample_aspect_ratio.den
+#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(60, 31, 100)
+      && ffmpegdec->pic_interlaced ==
+      (picture->flags & AV_FRAME_FLAG_INTERLACED)
+#else
       && ffmpegdec->pic_interlaced == picture->interlaced_frame
+#endif
       && ffmpegdec->pic_field_order == pic_field_order
       && ffmpegdec->cur_multiview_mode == ffmpegdec->picture_multiview_mode
       && ffmpegdec->cur_multiview_flags == ffmpegdec->picture_multiview_flags);
@@ -1106,7 +1156,16 @@ picture_changed (GstFFMpegVidDec * ffmpegdec, AVFrame * picture,
 static gboolean
 context_changed (GstFFMpegVidDec * ffmpegdec, AVCodecContext * context)
 {
-  return !(ffmpegdec->ctx_ticks == context->ticks_per_frame
+#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(60, 31, 100)
+  const gint ticks_per_frame =
+      (GST_VIDEO_INFO_IS_INTERLACED (&ffmpegdec->input_state->info)
+      && ffmpegdec->context->codec_descriptor
+      && ffmpegdec->context->
+      codec_descriptor->props & AV_CODEC_PROP_FIELDS) ? 2 : 1;
+#else
+  const gint ticks_per_frame = context->ticks_per_frame;
+#endif
+  return !(ffmpegdec->ctx_ticks == ticks_per_frame
       && ffmpegdec->ctx_time_n == context->time_base.num
       && ffmpegdec->ctx_time_d == context->time_base.den);
 }
@@ -1117,10 +1176,18 @@ update_video_context (GstFFMpegVidDec * ffmpegdec, AVCodecContext * context,
 {
   gint pic_field_order = 0;
 
+#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(60, 31, 100)
+  if (picture->flags & AV_FRAME_FLAG_INTERLACED) {
+#else
   if (picture->interlaced_frame) {
+#endif
     if (picture->repeat_pict)
       pic_field_order |= GST_VIDEO_BUFFER_FLAG_RFF;
+#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(60, 31, 100)
+    if (picture->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST)
+#else
     if (picture->top_field_first)
+#endif
       pic_field_order |= GST_VIDEO_BUFFER_FLAG_TFF;
   }
 
@@ -1156,12 +1223,25 @@ update_video_context (GstFFMpegVidDec * ffmpegdec, AVCodecContext * context,
     ffmpegdec->pic_field_order_changed = TRUE;
 
   ffmpegdec->pic_field_order = pic_field_order;
+#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(60, 31, 100)
+  ffmpegdec->pic_interlaced = picture->flags & AV_FRAME_FLAG_INTERLACED;
+#else
   ffmpegdec->pic_interlaced = picture->interlaced_frame;
+#endif
 
   if (!ffmpegdec->pic_interlaced)
     ffmpegdec->pic_field_order_changed = FALSE;
 
-  ffmpegdec->ctx_ticks = context->ticks_per_frame;
+#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(60, 31, 100)
+  const gint ticks_per_frame =
+      (GST_VIDEO_INFO_IS_INTERLACED (&ffmpegdec->input_state->info)
+      && ffmpegdec->context->codec_descriptor
+      && ffmpegdec->context->
+      codec_descriptor->props & AV_CODEC_PROP_FIELDS) ? 2 : 1;
+#else
+  const gint ticks_per_frame = context->ticks_per_frame;
+#endif
+  ffmpegdec->ctx_ticks = ticks_per_frame;
   ffmpegdec->ctx_time_n = context->time_base.num;
   ffmpegdec->ctx_time_d = context->time_base.den;
 
@@ -1350,7 +1430,7 @@ gst_ffmpegviddec_negotiate (GstFFMpegVidDec * ffmpegdec,
   GstStructure *in_s;
   GstVideoInterlaceMode interlace_mode;
   gint caps_height;
-  gboolean one_field = ! !(flags & GST_VIDEO_BUFFER_FLAG_ONEFIELD);
+  gboolean one_field = !!(flags & GST_VIDEO_BUFFER_FLAG_ONEFIELD);
 
   if (!update_video_context (ffmpegdec, context, picture, one_field))
     return TRUE;
@@ -1723,7 +1803,9 @@ get_output_buffer (GstFFMpegVidDec * ffmpegdec, GstVideoCodecFrame * frame)
 
   gst_video_frame_unmap (&vframe);
 
+#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT (60, 31, 100)
   ffmpegdec->picture->reordered_opaque = -1;
+#endif
 
   return ret;
 
@@ -1750,28 +1832,29 @@ not_negotiated:
   }
 }
 
-static void
-gst_avpacket_init (AVPacket * packet, guint8 * data, guint size)
-{
-  memset (packet, 0, sizeof (AVPacket));
-  packet->data = data;
-  packet->size = size;
-}
-
 /*
  * Returns: whether a frame was decoded
  */
 static gboolean
 gst_ffmpegviddec_video_frame (GstFFMpegVidDec * ffmpegdec,
-    GstVideoCodecFrame * frame, GstFlowReturn * ret)
+    GstVideoCodecFrame * input_frame, GstFlowReturn * ret)
 {
   gint res;
   gboolean got_frame = FALSE;
   gboolean mode_switch;
-  GstVideoCodecFrame *out_frame;
+  GstVideoCodecFrame *output_frame;
   GstFFMpegVidDecVideoFrame *out_dframe;
   GstBufferPool *pool;
 
+  if (G_UNLIKELY (!ffmpegdec->context))
+    goto no_codec;
+
+#if LIBAVCODEC_VERSION_MAJOR >= 60
+  ffmpegdec->context->frame_num++;
+#else
+  ffmpegdec->context->frame_number++;
+#endif
+
   *ret = GST_FLOW_OK;
 
   /* in case we skip frames */
@@ -1779,7 +1862,7 @@ gst_ffmpegviddec_video_frame (GstFFMpegVidDec * ffmpegdec,
 
   /* run QoS code, we don't stop decoding the frame when we are late because
    * else we might skip a reference frame */
-  gst_ffmpegviddec_do_qos (ffmpegdec, frame, &mode_switch);
+  gst_ffmpegviddec_do_qos (ffmpegdec, input_frame, &mode_switch);
 
   /* FFmpeg might request new buffer from other threads.
    * Release lock here */
@@ -1805,11 +1888,20 @@ gst_ffmpegviddec_video_frame (GstFFMpegVidDec * ffmpegdec,
 
   /* get the output picture timing info again */
   out_dframe = ffmpegdec->picture->opaque;
-  out_frame = gst_video_codec_frame_ref (out_dframe->frame);
+#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT (60, 31, 100)
+  output_frame =
+      gst_video_codec_frame_ref (av_buffer_get_opaque (ffmpegdec->
+          picture->opaque_ref));
+#else
+  g_assert (out_dframe);
+  output_frame = gst_video_codec_frame_ref (out_dframe->frame);
+#endif
 
   /* also give back a buffer allocated by the frame, if any */
-  gst_buffer_replace (&out_frame->output_buffer, out_dframe->buffer);
-  gst_buffer_replace (&out_dframe->buffer, NULL);
+  if (out_dframe) {
+    gst_buffer_replace (&output_frame->output_buffer, out_dframe->buffer);
+    gst_buffer_replace (&out_dframe->buffer, NULL);
+  }
 
   /* Extract auxilliary info not stored in the main AVframe */
   {
@@ -1838,38 +1930,46 @@ gst_ffmpegviddec_video_frame (GstFFMpegVidDec * ffmpegdec,
 
   GST_DEBUG_OBJECT (ffmpegdec,
       "pts %" G_GUINT64_FORMAT " duration %" G_GUINT64_FORMAT,
-      out_frame->pts, out_frame->duration);
+      output_frame->pts, output_frame->duration);
   GST_DEBUG_OBJECT (ffmpegdec, "picture: pts %" G_GUINT64_FORMAT,
       (guint64) ffmpegdec->picture->pts);
+#if LIBAVUTIL_VERSION_MAJOR < 58
   GST_DEBUG_OBJECT (ffmpegdec, "picture: num %d",
       ffmpegdec->picture->coded_picture_number);
   GST_DEBUG_OBJECT (ffmpegdec, "picture: display %d",
       ffmpegdec->picture->display_picture_number);
-  GST_DEBUG_OBJECT (ffmpegdec, "picture: opaque %p",
-      ffmpegdec->picture->opaque);
+#endif
+#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT (60, 31, 100)
+  GST_DEBUG_OBJECT (ffmpegdec, "picture: opaque_ref %p",
+      ffmpegdec->picture->opaque_ref);
+#else
   GST_DEBUG_OBJECT (ffmpegdec, "picture: reordered opaque %" G_GUINT64_FORMAT,
       (guint64) ffmpegdec->picture->reordered_opaque);
+#endif
+  GST_DEBUG_OBJECT (ffmpegdec, "picture: opaque %p",
+      ffmpegdec->picture->opaque);
   GST_DEBUG_OBJECT (ffmpegdec, "repeat_pict:%d",
       ffmpegdec->picture->repeat_pict);
   GST_DEBUG_OBJECT (ffmpegdec, "corrupted frame: %d",
-      ! !(ffmpegdec->picture->flags & AV_FRAME_FLAG_CORRUPT));
+      !!(ffmpegdec->picture->flags & AV_FRAME_FLAG_CORRUPT));
 
   if (!gst_ffmpegviddec_negotiate (ffmpegdec, ffmpegdec->context,
-          ffmpegdec->picture, GST_BUFFER_FLAGS (out_frame->input_buffer)))
+          ffmpegdec->picture, GST_BUFFER_FLAGS (output_frame->input_buffer)))
     goto negotiation_error;
 
   pool = gst_video_decoder_get_buffer_pool (GST_VIDEO_DECODER (ffmpegdec));
-  if (G_UNLIKELY (out_frame->output_buffer == NULL)) {
-    *ret = get_output_buffer (ffmpegdec, out_frame);
-  } else if (G_UNLIKELY (out_frame->output_buffer->pool != pool)) {
-    GstBuffer *tmp = out_frame->output_buffer;
-    out_frame->output_buffer = NULL;
-    *ret = get_output_buffer (ffmpegdec, out_frame);
+  if (G_UNLIKELY (output_frame->output_buffer == NULL)) {
+    *ret = get_output_buffer (ffmpegdec, output_frame);
+  } else if (G_UNLIKELY (output_frame->output_buffer->pool != pool)) {
+    GstBuffer *tmp = output_frame->output_buffer;
+    output_frame->output_buffer = NULL;
+    *ret = get_output_buffer (ffmpegdec, output_frame);
     gst_buffer_unref (tmp);
   }
 #ifndef G_DISABLE_ASSERT
   else {
-    GstVideoMeta *vmeta = gst_buffer_get_video_meta (out_frame->output_buffer);
+    GstVideoMeta *vmeta =
+        gst_buffer_get_video_meta (output_frame->output_buffer);
     if (vmeta) {
       GstVideoInfo *info = &ffmpegdec->output_state->info;
       g_assert ((gint) vmeta->width == GST_VIDEO_INFO_WIDTH (info));
@@ -1884,16 +1984,27 @@ gst_ffmpegviddec_video_frame (GstFFMpegVidDec * ffmpegdec,
 
   /* Mark corrupted frames as corrupted */
   if (ffmpegdec->picture->flags & AV_FRAME_FLAG_CORRUPT)
-    GST_BUFFER_FLAG_SET (out_frame->output_buffer, GST_BUFFER_FLAG_CORRUPTED);
+    GST_BUFFER_FLAG_SET (output_frame->output_buffer,
+        GST_BUFFER_FLAG_CORRUPTED);
 
   if (ffmpegdec->pic_interlaced) {
     /* set interlaced flags */
     if (ffmpegdec->picture->repeat_pict)
-      GST_BUFFER_FLAG_SET (out_frame->output_buffer, GST_VIDEO_BUFFER_FLAG_RFF);
+      GST_BUFFER_FLAG_SET (output_frame->output_buffer,
+          GST_VIDEO_BUFFER_FLAG_RFF);
+#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(60, 31, 100)
+    if (ffmpegdec->picture->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST)
+#else
     if (ffmpegdec->picture->top_field_first)
-      GST_BUFFER_FLAG_SET (out_frame->output_buffer, GST_VIDEO_BUFFER_FLAG_TFF);
+#endif
+      GST_BUFFER_FLAG_SET (output_frame->output_buffer,
+          GST_VIDEO_BUFFER_FLAG_TFF);
+#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(60, 31, 100)
+    if (ffmpegdec->picture->flags & AV_FRAME_FLAG_INTERLACED)
+#else
     if (ffmpegdec->picture->interlaced_frame)
-      GST_BUFFER_FLAG_SET (out_frame->output_buffer,
+#endif
+      GST_BUFFER_FLAG_SET (output_frame->output_buffer,
           GST_VIDEO_BUFFER_FLAG_INTERLACED);
   }
 
@@ -1907,11 +2018,11 @@ gst_ffmpegviddec_video_frame (GstFFMpegVidDec * ffmpegdec,
       GST_MEMDUMP ("A53 CC", side_data->data, side_data->size);
 
       /* do not add closed caption meta if it already exists */
-      if (!gst_buffer_get_meta (out_frame->input_buffer,
+      if (!gst_buffer_get_meta (output_frame->input_buffer,
               GST_VIDEO_CAPTION_META_API_TYPE)) {
-        out_frame->output_buffer =
-            gst_buffer_make_writable (out_frame->output_buffer);
-        gst_buffer_add_video_caption_meta (out_frame->output_buffer,
+        output_frame->output_buffer =
+            gst_buffer_make_writable (output_frame->output_buffer);
+        gst_buffer_add_video_caption_meta (output_frame->output_buffer,
             GST_VIDEO_CAPTION_TYPE_CEA708_RAW, side_data->data,
             side_data->size);
       } else {
@@ -1937,7 +2048,7 @@ gst_ffmpegviddec_video_frame (GstFFMpegVidDec * ffmpegdec,
     while (l) {
       GstVideoCodecFrame *tmp = l->data;
 
-      if (tmp == frame)
+      if (tmp == output_frame)
         old = FALSE;
 
       if (old && GST_VIDEO_CODEC_FRAME_IS_DECODE_ONLY (tmp)) {
@@ -1960,43 +2071,52 @@ gst_ffmpegviddec_video_frame (GstFFMpegVidDec * ffmpegdec,
 
   av_frame_unref (ffmpegdec->picture);
 
-  if (frame)
-    GST_VIDEO_CODEC_FRAME_FLAG_UNSET (frame,
+  if (input_frame)
+    GST_VIDEO_CODEC_FRAME_FLAG_UNSET (input_frame,
         GST_FFMPEG_VIDEO_CODEC_FRAME_FLAG_ALLOCATED);
 
   if (gst_video_decoder_get_subframe_mode (GST_VIDEO_DECODER (ffmpegdec)))
     gst_video_decoder_have_last_subframe (GST_VIDEO_DECODER (ffmpegdec),
-        out_frame);
+        output_frame);
 
   /* FIXME: Ideally we would remap the buffer read-only now before pushing but
    * libav might still have a reference to it!
    */
-  if (GST_BUFFER_FLAG_IS_SET (out_frame->input_buffer,
+  if (GST_BUFFER_FLAG_IS_SET (output_frame->input_buffer,
           GST_VIDEO_BUFFER_FLAG_ONEFIELD)) {
-    GST_BUFFER_FLAG_SET (out_frame->output_buffer,
+    GST_BUFFER_FLAG_SET (output_frame->output_buffer,
         GST_VIDEO_BUFFER_FLAG_ONEFIELD);
-    if (GST_BUFFER_FLAG_IS_SET (out_frame->input_buffer,
+    if (GST_BUFFER_FLAG_IS_SET (output_frame->input_buffer,
             GST_VIDEO_BUFFER_FLAG_TFF)) {
-      GST_BUFFER_FLAG_SET (out_frame->output_buffer, GST_VIDEO_BUFFER_FLAG_TFF);
+      GST_BUFFER_FLAG_SET (output_frame->output_buffer,
+          GST_VIDEO_BUFFER_FLAG_TFF);
     }
   }
 #ifdef TIZEN_FEATURE_LIBAV_VIDEODECODER_ADD_VIDEOMETA
   {
-    GstVideoMeta *vmeta = gst_buffer_get_video_meta (out_frame->output_buffer);
+    GstVideoMeta *vmeta = gst_buffer_get_video_meta (output_frame->output_buffer);
     if (!vmeta) {
       GstVideoInfo *out_info = &ffmpegdec->output_state->info;
 
       GST_DEBUG_OBJECT (ffmpegdec, "add videometa for output buffer");
 
-      gst_buffer_add_video_meta_full (out_frame->output_buffer, GST_VIDEO_FRAME_FLAG_NONE,
+      gst_buffer_add_video_meta_full (output_frame->output_buffer, GST_VIDEO_FRAME_FLAG_NONE,
           GST_VIDEO_INFO_FORMAT (out_info),
           GST_VIDEO_INFO_WIDTH (out_info), GST_VIDEO_INFO_HEIGHT (out_info),
           GST_VIDEO_INFO_N_PLANES (out_info), out_info->offset, out_info->stride);
     }
   }
 #endif /* TIZEN_FEATURE_LIBAV_VIDEODECODER_ADD_VIDEOMETA */
+
+  /* Temporarily release the video decoder stream lock so that other
+   * threads can continue decoding (e.g. call get_frame()) while data
+   * is being pushed downstream.
+   */
+  GST_VIDEO_DECODER_STREAM_UNLOCK (ffmpegdec);
   *ret =
-      gst_video_decoder_finish_frame (GST_VIDEO_DECODER (ffmpegdec), out_frame);
+      gst_video_decoder_finish_frame (GST_VIDEO_DECODER (ffmpegdec),
+      output_frame);
+  GST_VIDEO_DECODER_STREAM_LOCK (ffmpegdec);
 
 beach:
   GST_DEBUG_OBJECT (ffmpegdec, "return flow %s, got frame: %d",
@@ -2007,15 +2127,15 @@ beach:
 no_output:
   {
     GST_DEBUG_OBJECT (ffmpegdec, "no output buffer");
-    GST_VIDEO_CODEC_FRAME_FLAG_UNSET (frame,
+    GST_VIDEO_CODEC_FRAME_FLAG_UNSET (input_frame,
         GST_FFMPEG_VIDEO_CODEC_FRAME_FLAG_ALLOCATED);
-    gst_video_decoder_drop_frame (GST_VIDEO_DECODER (ffmpegdec), out_frame);
+    gst_video_decoder_drop_frame (GST_VIDEO_DECODER (ffmpegdec), output_frame);
     goto beach;
   }
 
 negotiation_error:
   {
-    gst_video_decoder_drop_frame (GST_VIDEO_DECODER (ffmpegdec), out_frame);
+    gst_video_decoder_drop_frame (GST_VIDEO_DECODER (ffmpegdec), output_frame);
     if (GST_PAD_IS_FLUSHING (GST_VIDEO_DECODER_SRC_PAD (ffmpegdec))) {
       *ret = GST_FLOW_FLUSHING;
       goto beach;
@@ -2024,35 +2144,16 @@ negotiation_error:
     *ret = GST_FLOW_NOT_NEGOTIATED;
     goto beach;
   }
-}
-
-
- /* Returns: Whether a frame was decoded */
-static gboolean
-gst_ffmpegviddec_frame (GstFFMpegVidDec * ffmpegdec, GstVideoCodecFrame * frame,
-    GstFlowReturn * ret)
-{
-  gboolean got_frame = FALSE;
 
-  if (G_UNLIKELY (ffmpegdec->context->codec == NULL))
-    goto no_codec;
-
-  *ret = GST_FLOW_OK;
-  ffmpegdec->context->frame_number++;
-
-  got_frame = gst_ffmpegviddec_video_frame (ffmpegdec, frame, ret);
-
-  return got_frame;
-
-  /* ERRORS */
 no_codec:
   {
     GST_ERROR_OBJECT (ffmpegdec, "no codec context");
     *ret = GST_FLOW_NOT_NEGOTIATED;
-    return -1;
+    goto beach;
   }
 }
 
+
 static GstFlowReturn
 gst_ffmpegviddec_drain (GstVideoDecoder * decoder)
 {
@@ -2060,7 +2161,7 @@ gst_ffmpegviddec_drain (GstVideoDecoder * decoder)
   GstFlowReturn ret = GST_FLOW_OK;
   gboolean got_frame = FALSE;
 
-  if (!ffmpegdec->opened)
+  if (!ffmpegdec->context)
     return GST_FLOW_OK;
 
   GST_VIDEO_DECODER_STREAM_UNLOCK (ffmpegdec);
@@ -2071,7 +2172,7 @@ gst_ffmpegviddec_drain (GstVideoDecoder * decoder)
   GST_VIDEO_DECODER_STREAM_LOCK (ffmpegdec);
 
   do {
-    got_frame = gst_ffmpegviddec_frame (ffmpegdec, NULL, &ret);
+    got_frame = gst_ffmpegviddec_video_frame (ffmpegdec, NULL, &ret);
   } while (got_frame && ret == GST_FLOW_OK);
 
   GST_VIDEO_DECODER_STREAM_UNLOCK (ffmpegdec);
@@ -2104,7 +2205,13 @@ gst_ffmpegviddec_handle_frame (GstVideoDecoder * decoder,
   gboolean got_frame;
   GstMapInfo minfo;
   GstFlowReturn ret = GST_FLOW_OK;
-  AVPacket packet;
+  AVPacket *packet;
+
+  if (G_UNLIKELY (!ffmpegdec->context)) {
+    gst_video_codec_frame_unref (frame);
+    GST_ERROR_OBJECT (ffmpegdec, "no codec context");
+    return GST_FLOW_NOT_NEGOTIATED;
+  }
 
   GST_LOG_OBJECT (ffmpegdec,
       "Received new data of size %" G_GSIZE_FORMAT ", dts %" GST_TIME_FORMAT
@@ -2115,9 +2222,13 @@ gst_ffmpegviddec_handle_frame (GstVideoDecoder * decoder,
   if (!gst_buffer_map (frame->input_buffer, &minfo, GST_MAP_READ)) {
     GST_ELEMENT_ERROR (ffmpegdec, STREAM, DECODE, ("Decoding problem"),
         ("Failed to map buffer for reading"));
+    gst_video_codec_frame_unref (frame);
     return GST_FLOW_ERROR;
   }
 
+  if (minfo.size == 0)
+    goto done;
+
   /* treat frame as void until a buffer is requested for it */
   if (!GST_VIDEO_CODEC_FRAME_FLAG_IS_SET (frame,
           GST_FFMPEG_VIDEO_CODEC_FRAME_FLAG_ALLOCATED))
@@ -2144,45 +2255,56 @@ gst_ffmpegviddec_handle_frame (GstVideoDecoder * decoder,
     data = ffmpegdec->padded;
   }
 
-  /* now decode the frame */
-  gst_avpacket_init (&packet, data, size);
+  /* Note: We use `av_packet_alloc()` so that it is properly initialized by
+   * FFmpeg and it can be properly cleaned-up (via `av_packet_unref()`) by
+   * FFmpeg also. */
+  packet = av_packet_alloc ();
+  packet->data = data;
+  packet->size = size;
 
-  if (!packet.size)
-    goto done;
+  /* Store a reference to the input frame. This will be carried along by FFmpeg
+   * to the resulting AVPicture */
+#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT (60, 31, 100)
+  {
+    packet->opaque_ref =
+        av_buffer_create (NULL, 0, gst_ffmpeg_opaque_free,
+        gst_video_codec_frame_ref (frame), 0);
+    GST_DEBUG_OBJECT (ffmpegdec,
+        "Store incoming frame # %u (%p) on AVPacket opaque",
+        frame->system_frame_number, frame);
+  }
+#else
+  ffmpegdec->context->reordered_opaque = (gint64) frame->system_frame_number;
+  ffmpegdec->picture->reordered_opaque = (gint64) frame->system_frame_number;
+  GST_DEBUG_OBJECT (ffmpegdec, "stored opaque values idx %u",
+      frame->system_frame_number);
+#endif
 
   if (ffmpegdec->palette) {
     guint8 *pal;
 
-    pal = av_packet_new_side_data (&packet, AV_PKT_DATA_PALETTE,
-        AVPALETTE_SIZE);
+    pal = av_packet_new_side_data (packet, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE);
     gst_buffer_extract (ffmpegdec->palette, 0, pal, AVPALETTE_SIZE);
     GST_DEBUG_OBJECT (ffmpegdec, "copy pal %p %p", &packet, pal);
   }
 
-  /* save reference to the timing info */
-  ffmpegdec->context->reordered_opaque = (gint64) frame->system_frame_number;
-  ffmpegdec->picture->reordered_opaque = (gint64) frame->system_frame_number;
-
-  GST_DEBUG_OBJECT (ffmpegdec, "stored opaque values idx %d",
-      frame->system_frame_number);
-
   /* This might call into get_buffer() from another thread,
    * which would cause a deadlock. Release the lock here
    * and taking it again later seems safe
    * See https://bugzilla.gnome.org/show_bug.cgi?id=726020
    */
   GST_VIDEO_DECODER_STREAM_UNLOCK (ffmpegdec);
-  if (avcodec_send_packet (ffmpegdec->context, &packet) < 0) {
+  if (avcodec_send_packet (ffmpegdec->context, packet) < 0) {
     GST_VIDEO_DECODER_STREAM_LOCK (ffmpegdec);
-    av_packet_free_side_data (&packet);
+    av_packet_free (&packet);
     goto send_packet_failed;
   }
-  av_packet_free_side_data (&packet);
+  av_packet_free (&packet);
   GST_VIDEO_DECODER_STREAM_LOCK (ffmpegdec);
 
   do {
     /* decode a frame of audio/video now */
-    got_frame = gst_ffmpegviddec_frame (ffmpegdec, frame, &ret);
+    got_frame = gst_ffmpegviddec_video_frame (ffmpegdec, frame, &ret);
 
     if (ret != GST_FLOW_OK) {
       GST_LOG_OBJECT (ffmpegdec, "breaking because of flow ret %s",
@@ -2209,19 +2331,13 @@ static gboolean
 gst_ffmpegviddec_start (GstVideoDecoder * decoder)
 {
   GstFFMpegVidDec *ffmpegdec = GST_FFMPEGVIDDEC (decoder);
-  GstFFMpegVidDecClass *oclass;
-
-  oclass = GST_FFMPEGVIDDEC_GET_CLASS (ffmpegdec);
 
   GST_OBJECT_LOCK (ffmpegdec);
+  av_frame_free (&ffmpegdec->picture);
+  if (ffmpegdec->context)
+    av_freep (&ffmpegdec->context->extradata);
   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;
-  }
-  ffmpegdec->context->opaque = ffmpegdec;
+  ffmpegdec->picture = av_frame_alloc ();
   GST_OBJECT_UNLOCK (ffmpegdec);
 
   return TRUE;
@@ -2233,7 +2349,8 @@ gst_ffmpegviddec_stop (GstVideoDecoder * decoder)
   GstFFMpegVidDec *ffmpegdec = GST_FFMPEGVIDDEC (decoder);
 
   GST_OBJECT_LOCK (ffmpegdec);
-  gst_ffmpegviddec_close (ffmpegdec, FALSE);
+  av_frame_free (&ffmpegdec->picture);
+  gst_ffmpegviddec_close (ffmpegdec);
   GST_OBJECT_UNLOCK (ffmpegdec);
   g_free (ffmpegdec->padded);
   ffmpegdec->padded = NULL;
@@ -2287,7 +2404,7 @@ gst_ffmpegviddec_flush (GstVideoDecoder * decoder)
 {
   GstFFMpegVidDec *ffmpegdec = GST_FFMPEGVIDDEC (decoder);
 
-  if (ffmpegdec->opened) {
+  if (ffmpegdec->context) {
     GST_LOG_OBJECT (decoder, "flushing buffers");
     GST_VIDEO_DECODER_STREAM_UNLOCK (ffmpegdec);
     avcodec_flush_buffers (ffmpegdec->context);
@@ -2476,11 +2593,10 @@ gst_ffmpegviddec_set_property (GObject * object,
 
   switch (prop_id) {
     case PROP_LOWRES:
-      ffmpegdec->lowres = ffmpegdec->context->lowres = g_value_get_enum (value);
+      ffmpegdec->lowres = g_value_get_enum (value);
       break;
     case PROP_SKIPFRAME:
-      ffmpegdec->skip_frame = ffmpegdec->context->skip_frame =
-          g_value_get_enum (value);
+      ffmpegdec->skip_frame = g_value_get_enum (value);
       break;
     case PROP_DIRECT_RENDERING:
       ffmpegdec->direct_rendering = g_value_get_boolean (value);
@@ -2583,9 +2699,10 @@ gst_ffmpegviddec_register (GstPlugin * plugin)
         in_plugin->id == AV_CODEC_ID_V210X ||
         in_plugin->id == AV_CODEC_ID_V308 ||
         in_plugin->id == AV_CODEC_ID_V408 ||
-        in_plugin->id == AV_CODEC_ID_V410 ||
-        in_plugin->id == AV_CODEC_ID_R210
+        in_plugin->id == AV_CODEC_ID_V410 || in_plugin->id == AV_CODEC_ID_R210
+#if LIBAVCODEC_VERSION_MAJOR < 61
         || in_plugin->id == AV_CODEC_ID_AYUV
+#endif
         || in_plugin->id == AV_CODEC_ID_Y41P
         || in_plugin->id == AV_CODEC_ID_012V
         || in_plugin->id == AV_CODEC_ID_YUV4
index 0f713de5691c5c7c2b0ca40bf6a499a3478661e3..14d5a9aff352d82fd1d9ab6c20e89972f84cdf37 100644 (file)
@@ -54,7 +54,6 @@ struct _GstFFMpegVidDec
   GstVideoMultiviewMode picture_multiview_mode;
   GstVideoMultiviewFlags picture_multiview_flags;
   gint stride[AV_NUM_DATA_POINTERS];
-  gboolean opened;
 
   /* current output pictures */
   enum AVPixelFormat pic_pix_fmt;
index 46899590663fbdafad6977b056e4b971780dedce..cb8e9145ee5fe4c44054dfcd1d2e28d373adb831 100644 (file)
@@ -996,9 +996,10 @@ gst_ffmpegvidenc_register (GstPlugin * plugin)
         in_plugin->id == AV_CODEC_ID_V210X ||
         in_plugin->id == AV_CODEC_ID_V308 ||
         in_plugin->id == AV_CODEC_ID_V408 ||
-        in_plugin->id == AV_CODEC_ID_V410 ||
-        in_plugin->id == AV_CODEC_ID_R210
+        in_plugin->id == AV_CODEC_ID_V410 || in_plugin->id == AV_CODEC_ID_R210
+#if LIBAVCODEC_VERSION_MAJOR < 61
         || in_plugin->id == AV_CODEC_ID_AYUV
+#endif
         || in_plugin->id == AV_CODEC_ID_Y41P
         || in_plugin->id == AV_CODEC_ID_012V
         || in_plugin->id == AV_CODEC_ID_YUV4