mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 12:11:13 +00:00
x264enc: Add speed-preset and [psy-]tuning properties
Use of a rate control method (pass, bitrate, quantizer, etc properties), a preset and possibly a profile and/or tuning are now the recommended way to configure x264 through x264enc. If a preset/tuning are specified then these will define the default values and the property defaults will be ignored. After this the option-string property is applied, followed by the user-set properties, fast first pass restrictions and finally the profile restrictions. Addresses part of bug #607798
This commit is contained in:
parent
f269e0679f
commit
b27ce43ab8
2 changed files with 209 additions and 8 deletions
|
@ -41,6 +41,11 @@
|
|||
* most players and settings, but in some cases (e.g. hardware platforms)
|
||||
* a more restricted profile/level may be necessary.
|
||||
*
|
||||
* If a preset/tuning are specified then these will define the default values and
|
||||
* the property defaults will be ignored. After this the option-string property is
|
||||
* applied, followed by the user-set properties, fast first pass restrictions and
|
||||
* finally the profile restrictions.
|
||||
*
|
||||
* <refsect2>
|
||||
* <title>Example pipeline</title>
|
||||
* |[
|
||||
|
@ -54,6 +59,13 @@
|
|||
* matroskamux ! filesink location=videotestsrc.avi
|
||||
* ]| This example pipeline will encode a test video source to H264 using fixed
|
||||
* quantization, and muxes it in a Matroska container.
|
||||
* |[
|
||||
* gst-launch -v videotestsrc num-buffers=1000 ! x264enc pass=5 quantizer=25 speed-preset=6 profile=1 ! \
|
||||
* qtmux ! filesink location=videotestsrc.mov
|
||||
* ]| This example pipeline will encode a test video source to H264 using
|
||||
* constant quality at around Q25 using the 'medium' speed/quality preset and
|
||||
* restricting the options used so that the output is H.264 Baseline Profile
|
||||
* compliant and finally multiplexing the output in Quicktime mov format.
|
||||
* </refsect2>
|
||||
*/
|
||||
|
||||
|
@ -128,6 +140,9 @@ enum
|
|||
ARG_INTERLACED,
|
||||
ARG_OPTION_STRING,
|
||||
ARG_PROFILE,
|
||||
ARG_SPEED_PRESET,
|
||||
ARG_PSY_TUNE,
|
||||
ARG_TUNE,
|
||||
};
|
||||
|
||||
#define ARG_THREADS_DEFAULT 1
|
||||
|
@ -167,6 +182,9 @@ enum
|
|||
#define ARG_PROFILE_DEFAULT 1 /* Main profile matches current defaults */
|
||||
#define ARG_OPTION_STRING_DEFAULT ""
|
||||
static GString *x264enc_defaults;
|
||||
#define ARG_SPEED_PRESET_DEFAULT 0 /* no preset */
|
||||
#define ARG_PSY_TUNE_DEFAULT 0 /* no psy tuning */
|
||||
#define ARG_TUNE_DEFAULT 0 /* no tuning */
|
||||
|
||||
enum
|
||||
{
|
||||
|
@ -282,6 +300,120 @@ gst_x264_enc_profile_get_type (void)
|
|||
return profile_type;
|
||||
}
|
||||
|
||||
#define GST_X264_ENC_SPEED_PRESET_TYPE (gst_x264_enc_speed_preset_get_type())
|
||||
static GType
|
||||
gst_x264_enc_speed_preset_get_type (void)
|
||||
{
|
||||
static GType speed_preset_type = 0;
|
||||
static GEnumValue *speed_preset_types;
|
||||
int n, i;
|
||||
|
||||
if (speed_preset_type != 0)
|
||||
return speed_preset_type;
|
||||
|
||||
n = 0;
|
||||
while (x264_preset_names[n] != NULL)
|
||||
n++;
|
||||
|
||||
speed_preset_types = g_new0 (GEnumValue, n + 2);
|
||||
|
||||
speed_preset_types[0].value = 0;
|
||||
speed_preset_types[0].value_name = "No preset";
|
||||
speed_preset_types[0].value_nick = "None";
|
||||
|
||||
for (i = 1; i <= n; i++) {
|
||||
speed_preset_types[i].value = i;
|
||||
speed_preset_types[i].value_name = x264_preset_names[i - 1];
|
||||
speed_preset_types[i].value_nick = x264_preset_names[i - 1];
|
||||
}
|
||||
|
||||
speed_preset_type =
|
||||
g_enum_register_static ("GstX264EncPreset", speed_preset_types);
|
||||
|
||||
return speed_preset_type;
|
||||
}
|
||||
|
||||
static const GFlagsValue tune_types[] = {
|
||||
{0x0, "No tuning", "none"},
|
||||
{0x1, "Still image", "stillimage"},
|
||||
{0x2, "Fast decode", "fastdecode"},
|
||||
{0x4, "Zero latency", "zerolatency"},
|
||||
{0, NULL, NULL},
|
||||
};
|
||||
|
||||
#define GST_X264_ENC_TUNE_TYPE (gst_x264_enc_tune_get_type())
|
||||
static GType
|
||||
gst_x264_enc_tune_get_type (void)
|
||||
{
|
||||
static GType tune_type = 0;
|
||||
|
||||
if (!tune_type) {
|
||||
tune_type = g_flags_register_static ("GstX264EncTune", tune_types);
|
||||
}
|
||||
return tune_type;
|
||||
}
|
||||
|
||||
enum
|
||||
{
|
||||
GST_X264_ENC_TUNE_NONE,
|
||||
GST_X264_ENC_TUNE_FILM,
|
||||
GST_X264_ENC_TUNE_ANIMATION,
|
||||
GST_X264_ENC_TUNE_GRAIN,
|
||||
GST_X264_ENC_TUNE_PSNR,
|
||||
GST_X264_ENC_TUNE_SSIM,
|
||||
GST_X264_ENC_TUNE_LAST
|
||||
};
|
||||
|
||||
static const GEnumValue psy_tune_types[] = {
|
||||
{GST_X264_ENC_TUNE_NONE, "No tuning", "none"},
|
||||
{GST_X264_ENC_TUNE_FILM, "Film", "film"},
|
||||
{GST_X264_ENC_TUNE_ANIMATION, "Animation", "animation"},
|
||||
{GST_X264_ENC_TUNE_GRAIN, "Grain", "grain"},
|
||||
{GST_X264_ENC_TUNE_PSNR, "PSNR", "psnr"},
|
||||
{GST_X264_ENC_TUNE_SSIM, "SSIM", "ssim"},
|
||||
{0, NULL, NULL},
|
||||
};
|
||||
|
||||
#define GST_X264_ENC_PSY_TUNE_TYPE (gst_x264_enc_psy_tune_get_type())
|
||||
static GType
|
||||
gst_x264_enc_psy_tune_get_type (void)
|
||||
{
|
||||
static GType psy_tune_type = 0;
|
||||
|
||||
if (!psy_tune_type) {
|
||||
psy_tune_type =
|
||||
g_enum_register_static ("GstX264EncPsyTune", psy_tune_types);
|
||||
}
|
||||
return psy_tune_type;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_x264_enc_build_tunings_string (GstX264Enc * x264enc)
|
||||
{
|
||||
int i = 1;
|
||||
|
||||
if (x264enc->tunings && x264enc->tunings->len)
|
||||
g_string_free (x264enc->tunings, TRUE);
|
||||
|
||||
if (x264enc->psy_tune) {
|
||||
x264enc->tunings =
|
||||
g_string_new (psy_tune_types[x264enc->psy_tune].value_nick);
|
||||
} else {
|
||||
x264enc->tunings = g_string_new (NULL);
|
||||
}
|
||||
|
||||
while (tune_types[i].value_name) {
|
||||
if (x264enc->tune & (1 << (i - 1)))
|
||||
g_string_append_printf (x264enc->tunings, "%s%s",
|
||||
x264enc->tunings->len ? "," : "", tune_types[i].value_nick);
|
||||
i++;
|
||||
}
|
||||
|
||||
if (x264enc->tunings->len)
|
||||
GST_DEBUG_OBJECT (x264enc, "Constructed tunings string: %s",
|
||||
x264enc->tunings->str);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -419,6 +551,20 @@ gst_x264_enc_class_init (GstX264EncClass * klass)
|
|||
300, 10000, ARG_VBV_BUF_CAPACITY_DEFAULT, G_PARAM_READWRITE));
|
||||
|
||||
#ifdef X264_PRESETS
|
||||
g_object_class_install_property (gobject_class, ARG_SPEED_PRESET,
|
||||
g_param_spec_enum ("speed-preset", "Speed/quality preset",
|
||||
"Preset name for speed/quality tradeoff options (can affect decode "
|
||||
"compatibility - impose restrictions separately for your target decoder)",
|
||||
GST_X264_ENC_SPEED_PRESET_TYPE, ARG_SPEED_PRESET_DEFAULT,
|
||||
G_PARAM_READWRITE));
|
||||
g_object_class_install_property (gobject_class, ARG_PSY_TUNE,
|
||||
g_param_spec_enum ("psy-tune", "Psychovisual tuning preset",
|
||||
"Preset name for psychovisual tuning options",
|
||||
GST_X264_ENC_PSY_TUNE_TYPE, ARG_PSY_TUNE_DEFAULT, G_PARAM_READWRITE));
|
||||
g_object_class_install_property (gobject_class, ARG_TUNE,
|
||||
g_param_spec_flags ("tune", "Content tuning preset",
|
||||
"Preset name for non-psychovisual tuning options",
|
||||
GST_X264_ENC_TUNE_TYPE, ARG_TUNE_DEFAULT, G_PARAM_READWRITE));
|
||||
g_object_class_install_property (gobject_class, ARG_PROFILE,
|
||||
g_param_spec_enum ("profile", "H.264 profile",
|
||||
"Apply restrictions to meet H.264 Profile constraints. This will "
|
||||
|
@ -700,6 +846,9 @@ gst_x264_enc_init (GstX264Enc * encoder, GstX264EncClass * klass)
|
|||
encoder->profile = ARG_PROFILE_DEFAULT;
|
||||
encoder->option_string = g_string_new (NULL);
|
||||
encoder->option_string_prop = g_string_new (ARG_OPTION_STRING_DEFAULT);
|
||||
encoder->speed_preset = ARG_SPEED_PRESET_DEFAULT;
|
||||
encoder->psy_tune = ARG_PSY_TUNE_DEFAULT;
|
||||
encoder->tune = ARG_TUNE_DEFAULT;
|
||||
|
||||
/* resources */
|
||||
encoder->delay = g_queue_new ();
|
||||
|
@ -740,6 +889,7 @@ gst_x264_enc_finalize (GObject * object)
|
|||
if (ptr) \
|
||||
ptr = (GString *)g_string_free (ptr, TRUE);
|
||||
|
||||
FREE_STRING (encoder->tunings);
|
||||
FREE_STRING (encoder->option_string);
|
||||
FREE_STRING (encoder->option_string_prop);
|
||||
|
||||
|
@ -822,20 +972,49 @@ gst_x264_enc_init_encoder (GstX264Enc * encoder)
|
|||
|
||||
GST_OBJECT_LOCK (encoder);
|
||||
|
||||
#ifdef X264_PRESETS
|
||||
gst_x264_enc_build_tunings_string (encoder);
|
||||
|
||||
/* set x264 parameters and use preset/tuning if present */
|
||||
GST_DEBUG_OBJECT (encoder, "Applying defaults with preset %s, tunings %s",
|
||||
encoder->speed_preset ? x264_preset_names[encoder->speed_preset - 1] : "",
|
||||
encoder->tunings && encoder->tunings->len ? encoder->tunings->str : "");
|
||||
x264_param_default_preset (&encoder->x264param,
|
||||
encoder->speed_preset ? x264_preset_names[encoder->speed_preset -
|
||||
1] : NULL, encoder->tunings
|
||||
&& encoder->tunings->len ? encoder->tunings->str : NULL);
|
||||
|
||||
/* log callback setup; part of parameters
|
||||
* this needs to be done again after every *param_default* () call */
|
||||
encoder->x264param.pf_log = gst_x264_enc_log_callback;
|
||||
encoder->x264param.p_log_private = encoder;
|
||||
encoder->x264param.i_log_level = X264_LOG_DEBUG;
|
||||
|
||||
/* if no preset nor tuning, use property defaults */
|
||||
if (!encoder->speed_preset && !encoder->tunings->len) {
|
||||
#endif /* X264_PRESETS */
|
||||
GST_DEBUG_OBJECT (encoder, "Applying x264enc_defaults");
|
||||
if (x264enc_defaults->len
|
||||
&& gst_x264_enc_parse_options (encoder,
|
||||
x264enc_defaults->str) == FALSE) {
|
||||
GST_DEBUG_OBJECT (encoder,
|
||||
"x264enc_defaults string contains errors. This is a bug.");
|
||||
goto unlock_and_return;
|
||||
}
|
||||
#ifdef X264_PRESETS
|
||||
} else {
|
||||
/* When using presets we need to respect the default output format */
|
||||
encoder->x264param.b_aud = encoder->au_nalu;
|
||||
encoder->x264param.b_annexb = encoder->byte_stream;
|
||||
}
|
||||
#endif /* X264_PRESETS */
|
||||
|
||||
#if X264_BUILD >= 81
|
||||
/* setup appropriate timebase for gstreamer */
|
||||
encoder->x264param.i_timebase_num = 1;
|
||||
encoder->x264param.i_timebase_den = 1000000000;
|
||||
#endif
|
||||
|
||||
GST_DEBUG_OBJECT (encoder, "Applying x264enc_defaults");
|
||||
if (x264enc_defaults->len
|
||||
&& gst_x264_enc_parse_options (encoder, x264enc_defaults->str) == FALSE) {
|
||||
GST_DEBUG_OBJECT (encoder,
|
||||
"x264enc_defaults string contains errors. This is a bug.");
|
||||
goto unlock_and_return;
|
||||
}
|
||||
|
||||
/* apply user set properties */
|
||||
if (encoder->option_string_prop && encoder->option_string_prop->len
|
||||
&& gst_x264_enc_parse_options (encoder,
|
||||
|
@ -1508,6 +1687,15 @@ gst_x264_enc_set_property (GObject * object, guint prop_id,
|
|||
case ARG_VBV_BUF_CAPACITY:
|
||||
encoder->vbv_buf_capacity = g_value_get_uint (value);
|
||||
break;
|
||||
case ARG_SPEED_PRESET:
|
||||
encoder->speed_preset = g_value_get_enum (value);
|
||||
break;
|
||||
case ARG_PSY_TUNE:
|
||||
encoder->psy_tune = g_value_get_enum (value);
|
||||
break;
|
||||
case ARG_TUNE:
|
||||
encoder->tune = g_value_get_flags (value);
|
||||
break;
|
||||
case ARG_PROFILE:
|
||||
encoder->profile = g_value_get_enum (value);
|
||||
break;
|
||||
|
@ -1790,6 +1978,15 @@ gst_x264_enc_get_property (GObject * object, guint prop_id,
|
|||
case ARG_INTERLACED:
|
||||
g_value_set_boolean (value, encoder->interlaced);
|
||||
break;
|
||||
case ARG_SPEED_PRESET:
|
||||
g_value_set_enum (value, encoder->speed_preset);
|
||||
break;
|
||||
case ARG_PSY_TUNE:
|
||||
g_value_set_enum (value, encoder->psy_tune);
|
||||
break;
|
||||
case ARG_TUNE:
|
||||
g_value_set_flags (value, encoder->tune);
|
||||
break;
|
||||
case ARG_PROFILE:
|
||||
g_value_set_enum (value, encoder->profile);
|
||||
break;
|
||||
|
|
|
@ -87,6 +87,10 @@ struct _GstX264Enc
|
|||
gint rc_lookahead;
|
||||
guint noise_reduction;
|
||||
gboolean interlaced;
|
||||
gint speed_preset;
|
||||
gint psy_tune;
|
||||
guint tune;
|
||||
GString *tunings;
|
||||
gint profile;
|
||||
GString *option_string_prop; /* option-string property */
|
||||
GString *option_string; /* used by set prop */
|
||||
|
|
Loading…
Reference in a new issue