From d467eb708af0d4b36f8b8d64dc20959a5033e79a Mon Sep 17 00:00:00 2001 From: Ralph Giles Date: Thu, 13 Jan 2011 15:12:53 -0800 Subject: [PATCH] Set the theoraenc speed-level property from libtheora's defaults. The speed-level property, which allows callers to trade of encoding quality for speed in the libtheora api, has a version-dependent maximum and default values. Instead of hardcoding the acceptable range for the theoraenc element's presentation of this setting, we query the library directly at class initialization time and set the maximum and default values from that. If the query fails, we fall back to the previous default setting. To keep the values reported by gst-inspect (which I'm told use the spec values from the class) with those available on an\ instantiated element, we remove to setting of enc->speed_level from the initializer and instead pass G_PARAM_CONSTRUCT to the property spec flags, asking g_object to set this property when theoraenc objects are constructed. NB in theory the maximum speed-level could depend on the actual video caps. If later versions of libtheoraenc do this, a second call will need to be made from theora_enc_reset to update the property, since this function is mostly useful for realtime adjustment of performance while the pipeline is running. --- ext/theora/gsttheoraenc.c | 76 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 72 insertions(+), 4 deletions(-) diff --git a/ext/theora/gsttheoraenc.c b/ext/theora/gsttheoraenc.c index 03acef8..fe7f1b7 100644 --- a/ext/theora/gsttheoraenc.c +++ b/ext/theora/gsttheoraenc.c @@ -175,6 +175,57 @@ granulepos_to_timestamp (GstTheoraEnc * theoraenc, ogg_int64_t granulepos) theoraenc->info.fps_numerator); } +/* Generate a dummy encoder context for use in th_encode_ctl queries + Release with th_encode_free() + This and the next routine from theora/examples/libtheora_info.c */ +static th_enc_ctx * +dummy_encode_ctx (void) +{ + th_enc_ctx *ctx; + th_info info; + + /* set the minimal video parameters */ + th_info_init (&info); + info.frame_width = 320; + info.frame_height = 240; + info.fps_numerator = 1; + info.fps_denominator = 1; + + /* allocate and initialize a context object */ + ctx = th_encode_alloc (&info); + if (!ctx) + GST_WARNING ("Failed to allocate dummy encoder context."); + + /* clear the info struct */ + th_info_clear (&info); + + return ctx; +} + +/* Query the current and maximum values for the 'speed level' setting. + This can be used to ask the encoder to trade off encoding quality + vs. performance cost, for example to adapt to realtime constraints. */ +static int +check_speed_level (th_enc_ctx * ctx, int *current, int *max) +{ + int ret; + + /* query the current speed level */ + ret = th_encode_ctl (ctx, TH_ENCCTL_GET_SPLEVEL, current, sizeof (int)); + if (ret) { + GST_WARNING ("Error %d getting current speed level.", ret); + return ret; + } + /* query the maximum speed level, which varies by encoder version */ + ret = th_encode_ctl (ctx, TH_ENCCTL_GET_SPLEVEL_MAX, max, sizeof (int)); + if (ret) { + GST_WARNING ("Error %d getting maximum speed level.", ret); + return ret; + } + + return 0; +} + static GstStaticPadTemplate theora_enc_sink_factory = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, @@ -242,6 +293,19 @@ gst_theora_enc_class_init (GstTheoraEncClass * klass) GObjectClass *gobject_class = (GObjectClass *) klass; GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); + /* query runtime encoder properties */ + th_enc_ctx *th_ctx; + int default_speed_level = THEORA_DEF_SPEEDLEVEL; + int max_speed_level = default_speed_level; + + th_ctx = dummy_encode_ctx (); + if (th_ctx) { + if (!check_speed_level (th_ctx, &default_speed_level, &max_speed_level)) + GST_WARNING + ("Failed to determine settings for the speed-level property."); + th_encode_free (th_ctx); + } + gobject_class->set_property = theora_enc_set_property; gobject_class->get_property = theora_enc_get_property; gobject_class->finalize = theora_enc_finalize; @@ -301,9 +365,13 @@ gst_theora_enc_class_init (GstTheoraEncClass * klass) (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (gobject_class, PROP_SPEEDLEVEL, g_param_spec_int ("speed-level", "Speed level", - "Controls the amount of motion vector searching done while " - "encoding", 0, 3, THEORA_DEF_SPEEDLEVEL, - (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + "Controls the amount of analysis performed when encoding." + " Higher values trade compression quality for speed." + " This property requires libtheora version >= 1.0" + ", and the maximum value may vary based on encoder version.", + 0, max_speed_level, default_speed_level, + (GParamFlags) G_PARAM_READWRITE | G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); g_object_class_install_property (gobject_class, PROP_VP3_COMPATIBLE, g_param_spec_boolean ("vp3-compatible", "VP3 Compatible", "Disables non-VP3 compatible features", @@ -371,7 +439,7 @@ gst_theora_enc_init (GstTheoraEnc * enc, GstTheoraEncClass * g_class) enc->expected_ts = GST_CLOCK_TIME_NONE; - enc->speed_level = THEORA_DEF_SPEEDLEVEL; + /* enc->speed_level is set to the libtheora default by the constructor */ enc->vp3_compatible = THEORA_DEF_VP3_COMPATIBLE; enc->drop_frames = THEORA_DEF_DROP_FRAMES; enc->cap_overflow = THEORA_DEF_CAP_OVERFLOW; -- 2.7.4