From 3c975ed918808d7d38b1b7a045f679c15b088262 Mon Sep 17 00:00:00 2001 From: He Junyan Date: Mon, 26 Jul 2021 16:09:19 +0800 Subject: codecs: h264dec: Add a compliance property to control behavior. 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: --- gst-libs/gst/codecs/gsth264decoder.c | 98 ++++++++++++++++++++++++++++++++++++ gst-libs/gst/codecs/gsth264decoder.h | 44 ++++++++++++++++ 2 files changed, 142 insertions(+) diff --git a/gst-libs/gst/codecs/gsth264decoder.c b/gst-libs/gst/codecs/gsth264decoder.c index 263289688..2ac022b35 100644 --- a/gst-libs/gst/codecs/gsth264decoder.c +++ b/gst-libs/gst/codecs/gsth264decoder.c @@ -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 diff --git a/gst-libs/gst/codecs/gsth264decoder.h b/gst-libs/gst/codecs/gsth264decoder.h index 8015659f7..710b6c9fc 100644 --- a/gst-libs/gst/codecs/gsth264decoder.h +++ b/gst-libs/gst/codecs/gsth264decoder.h @@ -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; /** -- cgit v1.2.1