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: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/2432>
This commit is contained in:
He Junyan 2021-07-26 16:09:19 +08:00 committed by Víctor Manuel Jáquez Leal
parent a61d038cb6
commit 3c975ed918
2 changed files with 142 additions and 0 deletions

View 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

View 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;
/**