videodecoder: Add "discard-corrupted-frames" property
authorSebastian Dröge <sebastian@centricular.com>
Wed, 1 Jul 2020 15:11:25 +0000 (18:11 +0300)
committerGStreamer Merge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Thu, 10 Sep 2020 17:22:14 +0000 (17:22 +0000)
This can be used by applications to configure decoders so that corrupted
frames are directly discarded instead of being forwarded inside the
pipeline. It is a replacement for the "output-corrupt" property of the
ffmpeg decoders.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/-/merge_requests/730>

gst-libs/gst/video/gstvideodecoder.c

index 84d60eb..a16256d 100644 (file)
@@ -290,12 +290,14 @@ GST_DEBUG_CATEGORY (videodecoder_debug);
 /* properties */
 #define DEFAULT_QOS                 TRUE
 #define DEFAULT_MAX_ERRORS          GST_VIDEO_DECODER_MAX_ERRORS
+#define DEFAULT_DISCARD_CORRUPTED_FRAMES FALSE
 
 enum
 {
   PROP_0,
   PROP_QOS,
   PROP_MAX_ERRORS,
+  PROP_DISCARD_CORRUPTED_FRAMES
 };
 
 struct _GstVideoDecoderPrivate
@@ -376,6 +378,8 @@ struct _GstVideoDecoderPrivate
   GstClockTime base_timestamp;
 
   int distance_from_sync;
+  /* Properties */
+  gboolean discard_corrupted_frames;
 
   guint32 system_frame_number;
   guint32 decode_frame_number;
@@ -592,6 +596,21 @@ gst_video_decoder_class_init (GstVideoDecoderClass * klass)
           -1, G_MAXINT, DEFAULT_MAX_ERRORS,
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
+  /**
+   * GstVideoDecoder:discard-corrupted-frames:
+   *
+   * If set to %TRUE the decoder will discard frames that are marked as
+   * corrupted instead of outputting them.
+   *
+   * Since: 1.20
+   */
+  g_object_class_install_property (gobject_class, PROP_DISCARD_CORRUPTED_FRAMES,
+      g_param_spec_boolean ("discard-corrupted-frames",
+          "Discard Corrupted Frames",
+          "Discard frames marked as corrupted instead of outputting them",
+          DEFAULT_DISCARD_CORRUPTED_FRAMES,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
   meta_tag_video_quark = g_quark_from_static_string (GST_META_TAG_VIDEO_STR);
 }
 
@@ -861,6 +880,9 @@ gst_video_decoder_get_property (GObject * object, guint property_id,
     case PROP_MAX_ERRORS:
       g_value_set_int (value, gst_video_decoder_get_max_errors (dec));
       break;
+    case PROP_DISCARD_CORRUPTED_FRAMES:
+      g_value_set_boolean (value, priv->discard_corrupted_frames);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
       break;
@@ -881,6 +903,9 @@ gst_video_decoder_set_property (GObject * object, guint property_id,
     case PROP_MAX_ERRORS:
       gst_video_decoder_set_max_errors (dec, g_value_get_int (value));
       break;
+    case PROP_DISCARD_CORRUPTED_FRAMES:
+      priv->discard_corrupted_frames = g_value_get_boolean (value);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
       break;
@@ -3149,7 +3174,19 @@ gst_video_decoder_finish_frame (GstVideoDecoder * decoder,
 
   /* no buffer data means this frame is skipped */
   if (!frame->output_buffer || GST_VIDEO_CODEC_FRAME_IS_DECODE_ONLY (frame)) {
-    GST_DEBUG_OBJECT (decoder, "skipping frame %" GST_TIME_FORMAT,
+    GST_DEBUG_OBJECT (decoder,
+        "skipping frame %" GST_TIME_FORMAT " because not output was produced",
+        GST_TIME_ARGS (frame->pts));
+    goto done;
+  }
+
+  if (priv->discard_corrupted_frames
+      && (GST_VIDEO_CODEC_FRAME_FLAG_IS_SET (frame,
+              GST_VIDEO_CODEC_FRAME_FLAG_CORRUPTED)
+          || GST_BUFFER_FLAG_IS_SET (frame->output_buffer,
+              GST_BUFFER_FLAG_CORRUPTED))) {
+    GST_DEBUG_OBJECT (decoder,
+        "skipping frame %" GST_TIME_FORMAT " because it is corrupted",
         GST_TIME_ARGS (frame->pts));
     goto done;
   }