From 13ffed87b1597fa60ccee293f71c3993ec59d1b2 Mon Sep 17 00:00:00 2001 From: Greg Rutz Date: Mon, 14 Oct 2013 14:50:57 -0600 Subject: [PATCH] avenc: Add compliance property Add a new property to GstFFMpegVidEnc and GstFFMpegAudEnc to supply the "strict compliance" value to AVCodecContext https://bugzilla.gnome.org/show_bug.cgi?id=691617 --- ext/libav/gstavaudenc.c | 16 +++++++++++++++- ext/libav/gstavaudenc.h | 1 + ext/libav/gstavcodecmap.c | 22 ++++++++++++++++++++++ ext/libav/gstavcodecmap.h | 42 ++++++++++++++++++++++++++++++++++++++++++ ext/libav/gstavvidenc.c | 20 +++++++++++++++++--- ext/libav/gstavvidenc.h | 1 + 6 files changed, 98 insertions(+), 4 deletions(-) diff --git a/ext/libav/gstavaudenc.c b/ext/libav/gstavaudenc.c index ee758fa..74c2304 100644 --- a/ext/libav/gstavaudenc.c +++ b/ext/libav/gstavaudenc.c @@ -52,6 +52,7 @@ enum PROP_0, PROP_BIT_RATE, PROP_RTP_PAYLOAD_SIZE, + PROP_COMPLIANCE, }; /* A number of function prototypes are given so we can refer to them later. */ @@ -151,6 +152,11 @@ gst_ffmpegaudenc_class_init (GstFFMpegAudEncClass * klass) g_param_spec_int ("bitrate", "Bit Rate", "Target Audio Bitrate", 0, G_MAXINT, DEFAULT_AUDIO_BITRATE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_COMPLIANCE, + g_param_spec_enum ("compliance", "Compliance", + "Adherence of the encoder to the specifications", + GST_TYPE_FFMPEG_COMPLIANCE, FFMPEG_DEFAULT_COMPLIANCE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); gobject_class->finalize = gst_ffmpegaudenc_finalize; @@ -174,6 +180,8 @@ gst_ffmpegaudenc_init (GstFFMpegAudEnc * ffmpegaudenc) ffmpegaudenc->context = avcodec_alloc_context3 (klass->in_plugin); ffmpegaudenc->opened = FALSE; + ffmpegaudenc->compliance = FFMPEG_DEFAULT_COMPLIANCE; + gst_audio_encoder_set_drainable (GST_AUDIO_ENCODER (ffmpegaudenc), TRUE); } @@ -265,7 +273,7 @@ gst_ffmpegaudenc_set_format (GstAudioEncoder * encoder, GstAudioInfo * info) } /* if we set it in _getcaps we should set it also in _link */ - ffmpegaudenc->context->strict_std_compliance = -1; + ffmpegaudenc->context->strict_std_compliance = ffmpegaudenc->compliance; /* user defined properties */ if (ffmpegaudenc->bitrate > 0) { @@ -641,6 +649,9 @@ gst_ffmpegaudenc_set_property (GObject * object, case PROP_RTP_PAYLOAD_SIZE: ffmpegaudenc->rtp_payload_size = g_value_get_int (value); break; + case PROP_COMPLIANCE: + ffmpegaudenc->compliance = g_value_get_enum (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -665,6 +676,9 @@ gst_ffmpegaudenc_get_property (GObject * object, case PROP_RTP_PAYLOAD_SIZE: g_value_set_int (value, ffmpegaudenc->rtp_payload_size); break; + case PROP_COMPLIANCE: + g_value_set_enum (value, ffmpegaudenc->compliance); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; diff --git a/ext/libav/gstavaudenc.h b/ext/libav/gstavaudenc.h index b01184f..bce0900 100644 --- a/ext/libav/gstavaudenc.h +++ b/ext/libav/gstavaudenc.h @@ -42,6 +42,7 @@ struct _GstFFMpegAudEnc /* cache */ gint bitrate; gint rtp_payload_size; + gint compliance; /* other settings are copied over straight, * include a context here, rather than copy-and-past it from avcodec.h */ diff --git a/ext/libav/gstavcodecmap.c b/ext/libav/gstavcodecmap.c index e13627c..96040a6 100644 --- a/ext/libav/gstavcodecmap.c +++ b/ext/libav/gstavcodecmap.c @@ -66,6 +66,28 @@ static const struct AV_CH_STEREO_RIGHT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT} }; +GType +gst_ffmpeg_compliance_get_type (void) +{ + static GType ffmpeg_compliance_type = 0; + static const GEnumValue compliance_types[] = { + {GST_FFMPEG_VERY_STRICT, "Strictly conform to older spec", + "verystrict"}, + {GST_FFMPEG_STRICT, "Strictly conform to current spec", "strict"}, + {GST_FFMPEG_NORMAL, "Normal behavior", "normal"}, + {GST_FFMPEG_UNOFFICIAL, "Allow unofficial extensions", "unofficial"}, + {GST_FFMPEG_EXPERIMENTAL, "Allow nonstandardized experimental things", + "experimental"}, + {0, NULL, NULL} + }; + + if (!ffmpeg_compliance_type) { + ffmpeg_compliance_type = + g_enum_register_static ("GstFFMpegCompliance", compliance_types); + } + return ffmpeg_compliance_type; +} + static guint64 gst_ffmpeg_channel_positions_to_layout (GstAudioChannelPosition * pos, gint channels) diff --git a/ext/libav/gstavcodecmap.h b/ext/libav/gstavcodecmap.h index 01ce9b1..f392f96 100644 --- a/ext/libav/gstavcodecmap.h +++ b/ext/libav/gstavcodecmap.h @@ -25,6 +25,48 @@ #include #include +/** + * GstFFMpegCompliance: + * @GST_FFMPEG_VERY_STRICT: Strictly conform to an older + * more strict version of the spec or reference software + * @GST_FFMPEG_STRICT: Strictly conform to all the things + * in the spec no matter what consequences. + * @GST_FFMPEG_NORMAL: + * @GST_FFMPEG_UNOFFICIAL: Allow unofficial extensions + * @GST_FFMPEG_EXPERIMENTAL: Allow nonstandardized + * experimental things. + * + * This setting instructs libav on how strictly it should follow the + * associated standard. + * + * From avcodec.h: + * Setting this to STRICT or higher means the encoder and decoder will + * generally do stupid things, whereas setting it to unofficial or lower + * will mean the encoder might produce output that is not supported by all + * spec-compliant decoders. Decoders don't differentiate between normal, + * unofficial and experimental (that is, they always try to decode things + * when they can) unless they are explicitly asked to behave stupidly + * (=strictly conform to the specs) + */ +typedef enum { + GST_FFMPEG_VERY_STRICT = FF_COMPLIANCE_VERY_STRICT, + GST_FFMPEG_STRICT = FF_COMPLIANCE_STRICT, + GST_FFMPEG_NORMAL = FF_COMPLIANCE_NORMAL, + GST_FFMPEG_UNOFFICIAL = FF_COMPLIANCE_UNOFFICIAL, + GST_FFMPEG_EXPERIMENTAL = FF_COMPLIANCE_EXPERIMENTAL, +} GstFFMpegCompliance; + +/* + * _compliance_get_type () Returns an enum type that can be + * used as a property to indicate desired FFMpeg adherence to + * an associated specification + */ + +GType +gst_ffmpeg_compliance_get_type (void); +#define GST_TYPE_FFMPEG_COMPLIANCE (gst_ffmpeg_compliance_get_type ()) +#define FFMPEG_DEFAULT_COMPLIANCE GST_FFMPEG_NORMAL + /* * _codecid_to_caps () gets the GstCaps that belongs to * a certain CodecID for a pad with compressed data. diff --git a/ext/libav/gstavvidenc.c b/ext/libav/gstavvidenc.c index 83e052c..ab570f9 100644 --- a/ext/libav/gstavvidenc.c +++ b/ext/libav/gstavvidenc.c @@ -62,7 +62,8 @@ enum PROP_ME_METHOD, PROP_BUFSIZE, PROP_RTP_PAYLOAD_SIZE, - PROP_CFG_BASE + PROP_CFG_BASE, + PROP_COMPLIANCE, }; #define GST_TYPE_ME_METHOD (gst_ffmpegvidenc_me_method_get_type()) @@ -206,8 +207,14 @@ gst_ffmpegvidenc_class_init (GstFFMpegVidEncClass * klass) "RTP Payload Size", "Target GOB length", 0, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_COMPLIANCE, + g_param_spec_enum ("compliance", "Compliance", + "Adherence of the encoder to the specifications", + GST_TYPE_FFMPEG_COMPLIANCE, FFMPEG_DEFAULT_COMPLIANCE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /* register additional properties, possibly dependent on the exact CODEC */ - gst_ffmpeg_cfg_install_property (klass, PROP_CFG_BASE); + gst_ffmpeg_cfg_install_property (klass, PROP_COMPLIANCE); venc_class->start = gst_ffmpegvidenc_start; venc_class->stop = gst_ffmpegvidenc_stop; @@ -239,6 +246,7 @@ gst_ffmpegvidenc_init (GstFFMpegVidEnc * ffmpegenc) ffmpegenc->buffer_size = 512 * 1024; ffmpegenc->gop_size = DEFAULT_VIDEO_GOP_SIZE; ffmpegenc->rtp_payload_size = 0; + ffmpegenc->compliance = FFMPEG_DEFAULT_COMPLIANCE; ffmpegenc->lmin = 2; ffmpegenc->lmax = 31; @@ -301,7 +309,7 @@ gst_ffmpegvidenc_set_format (GstVideoEncoder * encoder, } /* if we set it in _getcaps we should set it also in _link */ - ffmpegenc->context->strict_std_compliance = -1; + ffmpegenc->context->strict_std_compliance = ffmpegenc->compliance; /* user defined properties */ ffmpegenc->context->bit_rate = ffmpegenc->bitrate; @@ -761,6 +769,9 @@ gst_ffmpegvidenc_set_property (GObject * object, case PROP_RTP_PAYLOAD_SIZE: ffmpegenc->rtp_payload_size = g_value_get_int (value); break; + case PROP_COMPLIANCE: + ffmpegenc->compliance = g_value_get_enum (value); + break; default: if (!gst_ffmpeg_cfg_set_property (object, value, pspec)) G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -794,6 +805,9 @@ gst_ffmpegvidenc_get_property (GObject * object, case PROP_RTP_PAYLOAD_SIZE: g_value_set_int (value, ffmpegenc->rtp_payload_size); break; + case PROP_COMPLIANCE: + g_value_set_enum (value, ffmpegenc->compliance); + break; default: if (!gst_ffmpeg_cfg_get_property (object, value, pspec)) G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); diff --git a/ext/libav/gstavvidenc.h b/ext/libav/gstavvidenc.h index d19dc39..e841d6c 100644 --- a/ext/libav/gstavvidenc.h +++ b/ext/libav/gstavvidenc.h @@ -49,6 +49,7 @@ struct _GstFFMpegVidEnc gint gop_size; gint buffer_size; gint rtp_payload_size; + gint compliance; guint8 *working_buf; gsize working_buf_size; -- 2.7.4