codecs: h264dec: Add a compliance property to control behavior.
authorHe Junyan <junyan.he@intel.com>
Mon, 26 Jul 2021 08:09:19 +0000 (16:09 +0800)
committerVíctor Manuel Jáquez Leal <vjaquez@igalia.com>
Mon, 13 Sep 2021 06:37:28 +0000 (06:37 +0000)
Some features such as the low-latency DPB bumping and mapping the
baseline profile as the constrained-baseline profile do not conform
to the H264 offical spec. But in practice, they are very useful and
are widely needed. We add this compliance property to control the
behavior of the decoder, make it fit more requirement.

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

gst-libs/gst/codecs/gsth264decoder.c
gst-libs/gst/codecs/gsth264decoder.h

index 2632896886290a230ac0dce997fa362ed8bfcbc5..2ac022b35e498f09049433d7b153248aa6b176b3 100644 (file)
@@ -80,6 +80,8 @@ typedef enum
 
 struct _GstH264DecoderPrivate
 {
+  GstH264DecoderCompliance compliance;
+
   gint width, height;
 
   /* input codec_data, if any */
@@ -210,6 +212,84 @@ static GstH264Picture *gst_h264_decoder_new_field_picture (GstH264Decoder *
 static void
 gst_h264_decoder_clear_output_frame (GstH264DecoderOutputFrame * output_frame);
 
+enum
+{
+  PROP_0,
+  PROP_COMPLIANCE,
+};
+
+/**
+ * gst_h264_decoder_compliance_get_type:
+ *
+ * Get the compliance type of the h264 decoder.
+ *
+ * Since: 1.20
+ */
+GType
+gst_h264_decoder_compliance_get_type (void)
+{
+  static gsize h264_decoder_compliance_type = 0;
+  static const GEnumValue compliances[] = {
+    {GST_H264_DECODER_COMPLIANCE_AUTO, "GST_H264_DECODER_COMPLIANCE_AUTO",
+        "auto"},
+    {GST_H264_DECODER_COMPLIANCE_STRICT, "GST_H264_DECODER_COMPLIANCE_STRICT",
+        "strict"},
+    {GST_H264_DECODER_COMPLIANCE_NORMAL, "GST_H264_DECODER_COMPLIANCE_NORMAL",
+        "normal"},
+    {GST_H264_DECODER_COMPLIANCE_FLEXIBLE,
+        "GST_H264_DECODER_COMPLIANCE_FLEXIBLE", "flexible"},
+    {0, NULL, NULL},
+  };
+
+
+  if (g_once_init_enter (&h264_decoder_compliance_type)) {
+    GType _type;
+
+    _type = g_enum_register_static ("GstH264DecoderCompliance", compliances);
+    g_once_init_leave (&h264_decoder_compliance_type, _type);
+  }
+
+  return (GType) h264_decoder_compliance_type;
+}
+
+static void
+gst_h264_decoder_get_property (GObject * object, guint property_id,
+    GValue * value, GParamSpec * pspec)
+{
+  GstH264Decoder *self = GST_H264_DECODER (object);
+  GstH264DecoderPrivate *priv = self->priv;
+
+  switch (property_id) {
+    case PROP_COMPLIANCE:
+      GST_OBJECT_LOCK (self);
+      g_value_set_enum (value, priv->compliance);
+      GST_OBJECT_UNLOCK (self);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_h264_decoder_set_property (GObject * object, guint property_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstH264Decoder *self = GST_H264_DECODER (object);
+  GstH264DecoderPrivate *priv = self->priv;
+
+  switch (property_id) {
+    case PROP_COMPLIANCE:
+      GST_OBJECT_LOCK (self);
+      priv->compliance = g_value_get_enum (value);
+      GST_OBJECT_UNLOCK (self);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+  }
+}
+
 static void
 gst_h264_decoder_class_init (GstH264DecoderClass * klass)
 {
@@ -217,6 +297,8 @@ gst_h264_decoder_class_init (GstH264DecoderClass * klass)
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
   object_class->finalize = GST_DEBUG_FUNCPTR (gst_h264_decoder_finalize);
+  object_class->get_property = gst_h264_decoder_get_property;
+  object_class->set_property = gst_h264_decoder_set_property;
 
   decoder_class->start = GST_DEBUG_FUNCPTR (gst_h264_decoder_start);
   decoder_class->stop = GST_DEBUG_FUNCPTR (gst_h264_decoder_stop);
@@ -226,6 +308,22 @@ gst_h264_decoder_class_init (GstH264DecoderClass * klass)
   decoder_class->drain = GST_DEBUG_FUNCPTR (gst_h264_decoder_drain);
   decoder_class->handle_frame =
       GST_DEBUG_FUNCPTR (gst_h264_decoder_handle_frame);
+
+  /**
+   * GstH264Decoder:compliance:
+   *
+   * The compliance controls the behavior of the decoder to handle some
+   * subtle cases and contexts, such as the low-latency DPB bumping or
+   * mapping the baseline profile as the constrained-baseline profile,
+   * etc.
+   *
+   * Since: 1.20
+   */
+  g_object_class_install_property (object_class, PROP_COMPLIANCE,
+      g_param_spec_enum ("compliance", "Decoder Compliance",
+          "The decoder's behavior in compliance with the h264 spec.",
+          GST_TYPE_H264_DECODER_COMPLIANCE, GST_H264_DECODER_COMPLIANCE_AUTO,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT));
 }
 
 static void
index 8015659f74143fdd33664ff4e436fd8e2a2b9b03..710b6c9fc6568de2f1f303a0e9b5cddc0b5cd637 100644 (file)
@@ -36,6 +36,49 @@ G_BEGIN_DECLS
 #define GST_IS_H264_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_H264_DECODER))
 #define GST_H264_DECODER_CAST(obj)       ((GstH264Decoder*)obj)
 
+/**
+ * GstH264DecoderCompliance:
+ * @GST_H264_DECODER_COMPLIANCE_AUTO: The decoder behavior is
+ *     automatically choosen.
+ * @GST_H264_DECODER_COMPLIANCE_STRICT: The decoder behavior strictly
+ *     conforms to the SPEC. All the decoder behaviors conform to the
+ *     SPEC, not including any nonstandard behavior which is not
+ *     mentioned in the SPEC.
+ * @GST_H264_DECODER_COMPLIANCE_NORMAL: The decoder behavior normally
+ *     conforms to the SPEC. Most behaviors conform to the SPEC but
+ *     including some nonstandard features which are widely used or
+ *     often used in the industry practice. This meets the request of
+ *     real streams and usages, but may not 100% conform to the
+ *     SPEC. It has very low risk. E.g., we will output pictures
+ *     without waiting DPB being full for the lower latency, which may
+ *     cause B frame disorder when there are reference frames with
+ *     smaller POC after it in decoder order. And the baseline profile
+ *     may be mapped to the constrained-baseline profile, but it may
+ *     have problems when a real baseline stream comes with FMO or
+ *     ASO.
+ * @GST_H264_DECODER_COMPLIANCE_FLEXIBLE: The decoder behavior
+ *     flexibly conforms to the SPEC. It uses the nonstandard features
+ *     more aggressively in order to get better performance(for
+ *     example, lower latency). It may change the result of the
+ *     decoder and should be used carefully. Besides including all
+ *     risks in *normal* mode, it has more risks, such as frames
+ *     disorder when reference frames POC decrease in decoder order.
+ *
+ * Since: 1.20
+ */
+typedef enum
+{
+  GST_H264_DECODER_COMPLIANCE_AUTO,
+  GST_H264_DECODER_COMPLIANCE_STRICT,
+  GST_H264_DECODER_COMPLIANCE_NORMAL,
+  GST_H264_DECODER_COMPLIANCE_FLEXIBLE
+} GstH264DecoderCompliance;
+
+#define GST_TYPE_H264_DECODER_COMPLIANCE (gst_h264_decoder_compliance_get_type())
+
+GST_CODECS_API
+GType gst_h264_decoder_compliance_get_type (void);
+
 typedef struct _GstH264Decoder GstH264Decoder;
 typedef struct _GstH264DecoderClass GstH264DecoderClass;
 typedef struct _GstH264DecoderPrivate GstH264DecoderPrivate;
@@ -65,6 +108,7 @@ struct _GstH264Decoder
  */
 struct _GstH264DecoderClass
 {
+  /*< private >*/
   GstVideoDecoderClass parent_class;
 
   /**