From: Mathieu Duponchelle Date: Sat, 30 Jun 2018 21:27:06 +0000 (+0200) Subject: avaudenc: install options generically X-Git-Tag: 1.16.2~75 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=59b9e66542730048cd57610e563c779aea59f54d;p=platform%2Fupstream%2Fgst-libav.git avaudenc: install options generically https://bugzilla.gnome.org/show_bug.cgi?id=792900 --- diff --git a/ext/libav/gstav.c b/ext/libav/gstav.c index facc700..6125662 100644 --- a/ext/libav/gstav.c +++ b/ext/libav/gstav.c @@ -30,6 +30,7 @@ #include "gstav.h" #include "gstavutils.h" +#include "gstavcfg.h" #ifdef GST_LIBAV_ENABLE_GPL #define LICENSE "GPL" @@ -153,6 +154,9 @@ plugin_init (GstPlugin * plugin) gst_ffmpeg_init_pix_fmt_info (); + /* build global ffmpeg param/property info */ + gst_ffmpeg_cfg_init (); + gst_ffmpegaudenc_register (plugin); gst_ffmpegvidenc_register (plugin); gst_ffmpegauddec_register (plugin); diff --git a/ext/libav/gstavaudenc.c b/ext/libav/gstavaudenc.c index f05205c..e7f0422 100644 --- a/ext/libav/gstavaudenc.c +++ b/ext/libav/gstavaudenc.c @@ -31,10 +31,12 @@ #include #include +#include #include #include "gstav.h" +#include "gstavcfg.h" #include "gstavcodecmap.h" #include "gstavutils.h" #include "gstavaudenc.h" @@ -50,9 +52,7 @@ enum enum { PROP_0, - PROP_BIT_RATE, - PROP_RTP_PAYLOAD_SIZE, - PROP_COMPLIANCE, + PROP_CFG_BASE, }; /* A number of function prototypes are given so we can refer to them later. */ @@ -148,16 +148,8 @@ gst_ffmpegaudenc_class_init (GstFFMpegAudEncClass * klass) gobject_class->set_property = gst_ffmpegaudenc_set_property; gobject_class->get_property = gst_ffmpegaudenc_get_property; - /* FIXME: could use -1 for a sensible per-codec defaults */ - g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_BIT_RATE, - 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)); + gst_ffmpeg_cfg_install_properties (gobject_class, klass->in_plugin, + PROP_CFG_BASE, AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM); gobject_class->finalize = gst_ffmpegaudenc_finalize; @@ -180,11 +172,10 @@ gst_ffmpegaudenc_init (GstFFMpegAudEnc * ffmpegaudenc) /* ffmpeg objects */ ffmpegaudenc->context = avcodec_alloc_context3 (klass->in_plugin); + ffmpegaudenc->refcontext = avcodec_alloc_context3 (klass->in_plugin); ffmpegaudenc->opened = FALSE; ffmpegaudenc->frame = av_frame_alloc (); - ffmpegaudenc->compliance = FFMPEG_DEFAULT_COMPLIANCE; - gst_audio_encoder_set_drainable (GST_AUDIO_ENCODER (ffmpegaudenc), TRUE); } @@ -197,6 +188,7 @@ gst_ffmpegaudenc_finalize (GObject * object) av_frame_free (&ffmpegaudenc->frame); gst_ffmpeg_avcodec_close (ffmpegaudenc->context); av_free (ffmpegaudenc->context); + av_free (ffmpegaudenc->refcontext); G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -262,31 +254,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 = ffmpegaudenc->compliance; - - /* user defined properties */ - if (ffmpegaudenc->bitrate > 0) { - GST_INFO_OBJECT (ffmpegaudenc, "Setting avcontext to bitrate %d", - ffmpegaudenc->bitrate); - ffmpegaudenc->context->bit_rate = ffmpegaudenc->bitrate; - ffmpegaudenc->context->bit_rate_tolerance = ffmpegaudenc->bitrate; - } else { - GST_INFO_OBJECT (ffmpegaudenc, - "Using avcontext default bitrate %" G_GINT64_FORMAT, - (gint64) ffmpegaudenc->context->bit_rate); - } - - /* RTP payload used for GOB production (for Asterisk) */ - if (ffmpegaudenc->rtp_payload_size) { - ffmpegaudenc->context->rtp_payload_size = ffmpegaudenc->rtp_payload_size; - } - - /* some other defaults */ - ffmpegaudenc->context->b_frame_strategy = 0; - ffmpegaudenc->context->coder_type = 0; - ffmpegaudenc->context->context_model = 0; - ffmpegaudenc->context->scenechange_threshold = 0; + gst_ffmpeg_cfg_fill_context (G_OBJECT (ffmpegaudenc), ffmpegaudenc->context); /* fetch pix_fmt and so on */ gst_ffmpeg_audioinfo_to_context (info, ffmpegaudenc->context); @@ -330,7 +298,8 @@ gst_ffmpegaudenc_set_format (GstAudioEncoder * encoder, GstAudioInfo * info) GST_DEBUG_OBJECT (ffmpegaudenc, "Failed to set context defaults"); if ((oclass->in_plugin->capabilities & AV_CODEC_CAP_EXPERIMENTAL) && - ffmpegaudenc->compliance != GST_FFMPEG_EXPERIMENTAL) { + ffmpegaudenc->context->strict_std_compliance != + GST_FFMPEG_EXPERIMENTAL) { GST_ELEMENT_ERROR (ffmpegaudenc, LIBRARY, SETTINGS, ("Codec is experimental, but settings don't allow encoders to " "produce output of experimental quality"), @@ -703,7 +672,6 @@ gst_ffmpegaudenc_set_property (GObject * object, { GstFFMpegAudEnc *ffmpegaudenc; - /* Get a pointer of the right type. */ ffmpegaudenc = (GstFFMpegAudEnc *) (object); if (ffmpegaudenc->opened) { @@ -712,46 +680,26 @@ gst_ffmpegaudenc_set_property (GObject * object, return; } - /* Check the argument id to see which argument we're setting. */ switch (prop_id) { - case PROP_BIT_RATE: - ffmpegaudenc->bitrate = g_value_get_int (value); - break; - 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); + if (!gst_ffmpeg_cfg_set_property (ffmpegaudenc->refcontext, value, pspec)) + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } -/* The set function is simply the inverse of the get fuction. */ static void gst_ffmpegaudenc_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { GstFFMpegAudEnc *ffmpegaudenc; - /* It's not null if we got it, but it might not be ours */ ffmpegaudenc = (GstFFMpegAudEnc *) (object); switch (prop_id) { - case PROP_BIT_RATE: - g_value_set_int (value, ffmpegaudenc->bitrate); - break; - break; - 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); + if (!gst_ffmpeg_cfg_get_property (ffmpegaudenc->refcontext, value, pspec)) + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } diff --git a/ext/libav/gstavaudenc.h b/ext/libav/gstavaudenc.h index 8c97d0d..4140856 100644 --- a/ext/libav/gstavaudenc.h +++ b/ext/libav/gstavaudenc.h @@ -37,17 +37,9 @@ struct _GstFFMpegAudEnc GstAudioEncoder parent; AVCodecContext *context; + AVCodecContext *refcontext; gboolean opened; - /* 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 */ - AVCodecContext config; - AVFrame *frame; GstAudioChannelPosition ffmpeg_layout[64]; diff --git a/ext/libav/gstavcfg.c b/ext/libav/gstavcfg.c index 2139e55..0a5baa0 100644 --- a/ext/libav/gstavcfg.c +++ b/ext/libav/gstavcfg.c @@ -33,22 +33,24 @@ #include static GQuark avoption_quark; -static GHashTable *venc_overrides = NULL; +static GHashTable *generic_overrides = NULL; static void -make_venc_overrides (void) +make_generic_overrides (void) { - g_assert (!venc_overrides); - venc_overrides = g_hash_table_new_full (g_str_hash, g_str_equal, + g_assert (!generic_overrides); + generic_overrides = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) gst_structure_free); - g_hash_table_insert (venc_overrides, g_strdup ("b"), + g_hash_table_insert (generic_overrides, g_strdup ("b"), gst_structure_new_empty ("bitrate")); - g_hash_table_insert (venc_overrides, g_strdup ("g"), + g_hash_table_insert (generic_overrides, g_strdup ("ab"), + gst_structure_new_empty ("bitrate")); + g_hash_table_insert (generic_overrides, g_strdup ("g"), gst_structure_new_empty ("gop-size")); - g_hash_table_insert (venc_overrides, g_strdup ("bt"), + g_hash_table_insert (generic_overrides, g_strdup ("bt"), gst_structure_new_empty ("bitrate-tolerance")); - g_hash_table_insert (venc_overrides, g_strdup ("bf"), + g_hash_table_insert (generic_overrides, g_strdup ("bf"), gst_structure_new_empty ("max-bframes")); } @@ -56,7 +58,7 @@ void gst_ffmpeg_cfg_init (void) { avoption_quark = g_quark_from_static_string ("ffmpeg-cfg-param-spec-data"); - make_venc_overrides (); + make_generic_overrides (); } static gint @@ -335,7 +337,8 @@ install_opts (GObjectClass * gobject_class, const AVClass ** obj, guint prop_id, } void -gst_ffmpeg_cfg_install_properties (GstFFMpegVidEncClass * klass, guint base) +gst_ffmpeg_cfg_install_properties (GObjectClass * klass, AVCodec * in_plugin, + guint base, gint flags) { gint prop_id; AVCodecContext *ctx; @@ -343,18 +346,16 @@ gst_ffmpeg_cfg_install_properties (GstFFMpegVidEncClass * klass, guint base) prop_id = base; g_return_if_fail (base > 0); - ctx = avcodec_alloc_context3 (klass->in_plugin); + ctx = avcodec_alloc_context3 (in_plugin); if (!ctx) g_warning ("could not get context"); prop_id = - install_opts ((GObjectClass *) klass, &klass->in_plugin->priv_class, - prop_id, AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_VIDEO_PARAM, + install_opts ((GObjectClass *) klass, &in_plugin->priv_class, prop_id, 0, " (Private codec option)", NULL); prop_id = - install_opts ((GObjectClass *) klass, &ctx->av_class, prop_id, - AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_VIDEO_PARAM, - " (Generic codec option, might have no effect)", venc_overrides); + install_opts ((GObjectClass *) klass, &ctx->av_class, prop_id, flags, + " (Generic codec option, might have no effect)", generic_overrides); if (ctx) { gst_ffmpeg_avcodec_close (ctx); @@ -421,10 +422,9 @@ set_option_value (AVCodecContext * ctx, GParamSpec * pspec, } gboolean -gst_ffmpeg_cfg_set_property (GObject * object, - const GValue * value, GParamSpec * pspec) +gst_ffmpeg_cfg_set_property (AVCodecContext * refcontext, const GValue * value, + GParamSpec * pspec) { - GstFFMpegVidEnc *ffmpegenc = (GstFFMpegVidEnc *) (object); const AVOption *opt; opt = g_param_spec_get_qdata (pspec, avoption_quark); @@ -432,14 +432,13 @@ gst_ffmpeg_cfg_set_property (GObject * object, if (!opt) return FALSE; - return set_option_value (ffmpegenc->refcontext, pspec, value, opt) >= 0; + return set_option_value (refcontext, pspec, value, opt) >= 0; } gboolean -gst_ffmpeg_cfg_get_property (GObject * object, - GValue * value, GParamSpec * pspec) +gst_ffmpeg_cfg_get_property (AVCodecContext * refcontext, GValue * value, + GParamSpec * pspec) { - GstFFMpegVidEnc *ffmpegenc = (GstFFMpegVidEnc *) (object); const AVOption *opt; opt = g_param_spec_get_qdata (pspec, avoption_quark); @@ -455,7 +454,7 @@ gst_ffmpeg_cfg_get_property (GObject * object, case G_TYPE_INT: { int64_t val; - if ((res = av_opt_get_int (ffmpegenc->refcontext, opt->name, + if ((res = av_opt_get_int (refcontext, opt->name, AV_OPT_SEARCH_CHILDREN, &val) >= 0)) g_value_set_int (value, val); break; @@ -463,7 +462,7 @@ gst_ffmpeg_cfg_get_property (GObject * object, case G_TYPE_INT64: { int64_t val; - if ((res = av_opt_get_int (ffmpegenc->refcontext, opt->name, + if ((res = av_opt_get_int (refcontext, opt->name, AV_OPT_SEARCH_CHILDREN, &val) >= 0)) g_value_set_int64 (value, val); break; @@ -471,7 +470,7 @@ gst_ffmpeg_cfg_get_property (GObject * object, case G_TYPE_UINT64: { int64_t val; - if ((res = av_opt_get_int (ffmpegenc->refcontext, opt->name, + if ((res = av_opt_get_int (refcontext, opt->name, AV_OPT_SEARCH_CHILDREN, &val) >= 0)) g_value_set_uint64 (value, val); break; @@ -479,7 +478,7 @@ gst_ffmpeg_cfg_get_property (GObject * object, case G_TYPE_DOUBLE: { gdouble val; - if ((res = av_opt_get_double (ffmpegenc->refcontext, opt->name, + if ((res = av_opt_get_double (refcontext, opt->name, AV_OPT_SEARCH_CHILDREN, &val) >= 0)) g_value_set_double (value, val); break; @@ -487,7 +486,7 @@ gst_ffmpeg_cfg_get_property (GObject * object, case G_TYPE_FLOAT: { gdouble val; - if ((res = av_opt_get_double (ffmpegenc->refcontext, opt->name, + if ((res = av_opt_get_double (refcontext, opt->name, AV_OPT_SEARCH_CHILDREN, &val) >= 0)) g_value_set_float (value, (gfloat) val); break; @@ -495,7 +494,7 @@ gst_ffmpeg_cfg_get_property (GObject * object, case G_TYPE_STRING: { uint8_t *val; - if ((res = av_opt_get (ffmpegenc->refcontext, opt->name, + if ((res = av_opt_get (refcontext, opt->name, AV_OPT_SEARCH_CHILDREN | AV_OPT_ALLOW_NULL, &val) >= 0)) { g_value_set_string (value, (gchar *) val); } @@ -504,7 +503,7 @@ gst_ffmpeg_cfg_get_property (GObject * object, case G_TYPE_BOOLEAN: { int64_t val; - if ((res = av_opt_get_int (ffmpegenc->refcontext, opt->name, + if ((res = av_opt_get_int (refcontext, opt->name, AV_OPT_SEARCH_CHILDREN, &val) >= 0)) g_value_set_boolean (value, val ? TRUE : FALSE); break; @@ -513,13 +512,13 @@ gst_ffmpeg_cfg_get_property (GObject * object, if (G_IS_PARAM_SPEC_ENUM (pspec)) { int64_t val; - if ((res = av_opt_get_int (ffmpegenc->refcontext, opt->name, + if ((res = av_opt_get_int (refcontext, opt->name, AV_OPT_SEARCH_CHILDREN, &val) >= 0)) g_value_set_enum (value, val); } else if (G_IS_PARAM_SPEC_FLAGS (pspec)) { int64_t val; - if ((res = av_opt_get_int (ffmpegenc->refcontext, opt->name, + if ((res = av_opt_get_int (refcontext, opt->name, AV_OPT_SEARCH_CHILDREN, &val) >= 0)) g_value_set_flags (value, val); } else { /* oops, bit lazy we don't cover this case yet */ @@ -534,13 +533,12 @@ gst_ffmpeg_cfg_get_property (GObject * object, } void -gst_ffmpeg_cfg_fill_context (GstFFMpegVidEnc * ffmpegenc, - AVCodecContext * context) +gst_ffmpeg_cfg_fill_context (GObject * object, AVCodecContext * context) { GParamSpec **pspecs; guint num_props, i; - pspecs = g_object_class_list_properties (G_OBJECT_GET_CLASS (ffmpegenc), + pspecs = g_object_class_list_properties (G_OBJECT_GET_CLASS (object), &num_props); for (i = 0; i < num_props; ++i) { @@ -553,15 +551,16 @@ gst_ffmpeg_cfg_fill_context (GstFFMpegVidEnc * ffmpegenc, if (!opt) continue; - g_object_getv (G_OBJECT (ffmpegenc), 1, &pspec->name, &value); + g_object_getv (object, 1, &pspec->name, &value); set_option_value (context, pspec, &value, opt); } g_free (pspecs); } void -gst_ffmpeg_cfg_finalize (GstFFMpegVidEnc * ffmpegenc) +gst_ffmpeg_cfg_finalize (void) { - g_assert (venc_overrides); - g_hash_table_unref (venc_overrides); + GST_ERROR ("Finalizing"); + g_assert (generic_overrides); + g_hash_table_unref (generic_overrides); } diff --git a/ext/libav/gstavcfg.h b/ext/libav/gstavcfg.h index d087d84..e8bc882 100644 --- a/ext/libav/gstavcfg.h +++ b/ext/libav/gstavcfg.h @@ -21,21 +21,23 @@ #ifndef __GST_FFMPEGCFG_H__ #define __GST_FFMPEGCFG_H__ +#include +#include + G_BEGIN_DECLS void gst_ffmpeg_cfg_init (void); -void gst_ffmpeg_cfg_install_properties (GstFFMpegVidEncClass * klass, guint base); +void gst_ffmpeg_cfg_install_properties (GObjectClass * klass, AVCodec *in_plugin, guint base, gint flags); -gboolean gst_ffmpeg_cfg_set_property (GObject * object, +gboolean gst_ffmpeg_cfg_set_property (AVCodecContext *refcontext, const GValue * value, GParamSpec * pspec); -gboolean gst_ffmpeg_cfg_get_property (GObject * object, +gboolean gst_ffmpeg_cfg_get_property (AVCodecContext *refcontext, GValue * value, GParamSpec * pspec); -void gst_ffmpeg_cfg_fill_context (GstFFMpegVidEnc * ffmpegenc, AVCodecContext * context); -void gst_ffmpeg_cfg_set_defaults (GstFFMpegVidEnc * ffmpegenc); -void gst_ffmpeg_cfg_finalize (GstFFMpegVidEnc * ffmpegenc); +void gst_ffmpeg_cfg_fill_context (GObject *object, AVCodecContext * context); +void gst_ffmpeg_cfg_finalize (void); G_END_DECLS diff --git a/ext/libav/gstavvidenc.c b/ext/libav/gstavvidenc.c index 95d19e2..385abc5 100644 --- a/ext/libav/gstavvidenc.c +++ b/ext/libav/gstavvidenc.c @@ -184,7 +184,8 @@ gst_ffmpegvidenc_class_init (GstFFMpegVidEncClass * klass) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT)); /* register additional properties, possibly dependent on the exact CODEC */ - gst_ffmpeg_cfg_install_properties (klass, PROP_CFG_BASE); + gst_ffmpeg_cfg_install_properties (gobject_class, klass->in_plugin, + PROP_CFG_BASE, AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_VIDEO_PARAM); venc_class->start = gst_ffmpegvidenc_start; venc_class->stop = gst_ffmpegvidenc_stop; @@ -217,8 +218,6 @@ gst_ffmpegvidenc_finalize (GObject * object) { GstFFMpegVidEnc *ffmpegenc = (GstFFMpegVidEnc *) object; - gst_ffmpeg_cfg_finalize (ffmpegenc); - /* clean up remaining allocated data */ av_frame_free (&ffmpegenc->picture); gst_ffmpeg_avcodec_close (ffmpegenc->context); @@ -253,7 +252,7 @@ gst_ffmpegvidenc_set_format (GstVideoEncoder * encoder, } /* additional avcodec settings */ - gst_ffmpeg_cfg_fill_context (ffmpegenc, ffmpegenc->context); + gst_ffmpeg_cfg_fill_context (G_OBJECT (ffmpegenc), ffmpegenc->context); /* and last but not least the pass; CBR, 2-pass, etc */ ffmpegenc->context->flags |= ffmpegenc->pass; @@ -737,7 +736,7 @@ gst_ffmpegvidenc_set_property (GObject * object, ffmpegenc->filename = g_value_dup_string (value); break; default: - if (!gst_ffmpeg_cfg_set_property (object, value, pspec)) + if (!gst_ffmpeg_cfg_set_property (ffmpegenc->refcontext, value, pspec)) G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } @@ -762,7 +761,7 @@ gst_ffmpegvidenc_get_property (GObject * object, g_value_take_string (value, g_strdup (ffmpegenc->filename)); break; default: - if (!gst_ffmpeg_cfg_get_property (object, value, pspec)) + if (!gst_ffmpeg_cfg_get_property (ffmpegenc->refcontext, value, pspec)) G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } @@ -839,12 +838,8 @@ gst_ffmpegvidenc_register (GstPlugin * plugin) AVCodec *in_plugin; void *i = 0; - GST_LOG ("Registering encoders"); - /* build global ffmpeg param/property info */ - gst_ffmpeg_cfg_init (); - while ((in_plugin = (AVCodec *) av_codec_iterate (&i))) { gchar *type_name;