summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authorSebastian Dröge <sebastian.droege@collabora.co.uk>2012-09-17 09:16:39 +0200
committerSebastian Dröge <sebastian.droege@collabora.co.uk>2012-09-17 09:29:26 +0200
commit481503670836d764a545cb5a32346e8bda5b5f3d (patch)
treef3cf3d3faa127402bb7b621bc4fcc9e64f2e6fe0 /ext
parent8ed85c7538593de6728223a187af0078db64f772 (diff)
vp8enc: Store configuration in the vpx_codec_enc_cfg_t struct instead of duplicating all variables
Also protect encoder with a mutex.
Diffstat (limited to 'ext')
-rw-r--r--ext/vpx/gstvp8enc.c321
-rw-r--r--ext/vpx/gstvp8enc.h54
2 files changed, 181 insertions, 194 deletions
diff --git a/ext/vpx/gstvp8enc.c b/ext/vpx/gstvp8enc.c
index b828ae2c7..804617926 100644
--- a/ext/vpx/gstvp8enc.c
+++ b/ext/vpx/gstvp8enc.c
@@ -700,40 +700,53 @@ gst_vp8_enc_class_init (GstVP8EncClass * klass)
static void
gst_vp8_enc_init (GstVP8Enc * gst_vp8_enc)
{
+ vpx_codec_err_t status;
GST_DEBUG_OBJECT (gst_vp8_enc, "init");
- gst_vp8_enc->rc_end_usage = DEFAULT_RC_END_USAGE;
- gst_vp8_enc->rc_target_bitrate = DEFAULT_RC_TARGET_BITRATE;
+ status =
+ vpx_codec_enc_config_default (&vpx_codec_vp8_cx_algo, &gst_vp8_enc->cfg,
+ 0);
+ if (status != VPX_CODEC_OK) {
+ GST_ERROR_OBJECT (gst_vp8_enc,
+ "Failed to get default encoder configuration: %s",
+ gst_vpx_error_name (status));
+ gst_vp8_enc->have_default_config = FALSE;
+ } else {
+ gst_vp8_enc->have_default_config = TRUE;
+ }
+
+ gst_vp8_enc->cfg.rc_end_usage = DEFAULT_RC_END_USAGE;
+ gst_vp8_enc->cfg.rc_target_bitrate = DEFAULT_RC_TARGET_BITRATE;
gst_vp8_enc->rc_target_bitrate_set = FALSE;
- gst_vp8_enc->rc_min_quantizer = DEFAULT_RC_MIN_QUANTIZER;
- gst_vp8_enc->rc_max_quantizer = DEFAULT_RC_MAX_QUANTIZER;
- gst_vp8_enc->rc_dropframe_thresh = DEFAULT_RC_DROPFRAME_THRESH;
- gst_vp8_enc->rc_resize_allowed = DEFAULT_RC_RESIZE_ALLOWED;
- gst_vp8_enc->rc_resize_up_thresh = DEFAULT_RC_RESIZE_UP_THRESH;
- gst_vp8_enc->rc_resize_down_thresh = DEFAULT_RC_RESIZE_DOWN_THRESH;
- gst_vp8_enc->rc_undershoot_pct = DEFAULT_RC_UNDERSHOOT_PCT;
- gst_vp8_enc->rc_overshoot_pct = DEFAULT_RC_OVERSHOOT_PCT;
- gst_vp8_enc->rc_buf_sz = DEFAULT_RC_BUF_SZ;
- gst_vp8_enc->rc_buf_initial_sz = DEFAULT_RC_BUF_INITIAL_SZ;
- gst_vp8_enc->rc_buf_optimal_sz = DEFAULT_RC_BUF_OPTIMAL_SZ;
- gst_vp8_enc->rc_2pass_vbr_bias_pct = DEFAULT_RC_2PASS_VBR_BIAS_PCT;
- gst_vp8_enc->rc_2pass_vbr_minsection_pct =
+ gst_vp8_enc->cfg.rc_min_quantizer = DEFAULT_RC_MIN_QUANTIZER;
+ gst_vp8_enc->cfg.rc_max_quantizer = DEFAULT_RC_MAX_QUANTIZER;
+ gst_vp8_enc->cfg.rc_dropframe_thresh = DEFAULT_RC_DROPFRAME_THRESH;
+ gst_vp8_enc->cfg.rc_resize_allowed = DEFAULT_RC_RESIZE_ALLOWED;
+ gst_vp8_enc->cfg.rc_resize_up_thresh = DEFAULT_RC_RESIZE_UP_THRESH;
+ gst_vp8_enc->cfg.rc_resize_down_thresh = DEFAULT_RC_RESIZE_DOWN_THRESH;
+ gst_vp8_enc->cfg.rc_undershoot_pct = DEFAULT_RC_UNDERSHOOT_PCT;
+ gst_vp8_enc->cfg.rc_overshoot_pct = DEFAULT_RC_OVERSHOOT_PCT;
+ gst_vp8_enc->cfg.rc_buf_sz = DEFAULT_RC_BUF_SZ;
+ gst_vp8_enc->cfg.rc_buf_initial_sz = DEFAULT_RC_BUF_INITIAL_SZ;
+ gst_vp8_enc->cfg.rc_buf_optimal_sz = DEFAULT_RC_BUF_OPTIMAL_SZ;
+ gst_vp8_enc->cfg.rc_2pass_vbr_bias_pct = DEFAULT_RC_2PASS_VBR_BIAS_PCT;
+ gst_vp8_enc->cfg.rc_2pass_vbr_minsection_pct =
DEFAULT_RC_2PASS_VBR_MINSECTION_PCT;
- gst_vp8_enc->rc_2pass_vbr_maxsection_pct =
+ gst_vp8_enc->cfg.rc_2pass_vbr_maxsection_pct =
DEFAULT_RC_2PASS_VBR_MAXSECTION_PCT;
- gst_vp8_enc->kf_mode = DEFAULT_KF_MODE;
- gst_vp8_enc->kf_max_dist = DEFAULT_KF_MAX_DIST;
- gst_vp8_enc->multipass_mode = DEFAULT_MULTIPASS_MODE;
+ gst_vp8_enc->cfg.kf_mode = DEFAULT_KF_MODE;
+ gst_vp8_enc->cfg.kf_max_dist = DEFAULT_KF_MAX_DIST;
+ gst_vp8_enc->cfg.g_pass = DEFAULT_MULTIPASS_MODE;
gst_vp8_enc->multipass_cache_file = g_strdup (DEFAULT_MULTIPASS_CACHE_FILE);
- gst_vp8_enc->ts_number_layers = DEFAULT_TS_NUMBER_LAYERS;
+ gst_vp8_enc->cfg.ts_number_layers = DEFAULT_TS_NUMBER_LAYERS;
gst_vp8_enc->n_ts_target_bitrate = 0;
gst_vp8_enc->n_ts_rate_decimator = 0;
- gst_vp8_enc->ts_periodicity = DEFAULT_TS_PERIODICITY;
+ gst_vp8_enc->cfg.ts_periodicity = DEFAULT_TS_PERIODICITY;
gst_vp8_enc->n_ts_layer_id = 0;
- gst_vp8_enc->error_resilient = DEFAULT_ERROR_RESILIENT;
- gst_vp8_enc->lag_in_frames = DEFAULT_LAG_IN_FRAMES;
- gst_vp8_enc->threads = DEFAULT_THREADS;
+ gst_vp8_enc->cfg.g_error_resilient = DEFAULT_ERROR_RESILIENT;
+ gst_vp8_enc->cfg.g_lag_in_frames = DEFAULT_LAG_IN_FRAMES;
+ gst_vp8_enc->cfg.g_threads = DEFAULT_THREADS;
gst_vp8_enc->deadline = DEFAULT_DEADLINE;
gst_vp8_enc->h_scaling_mode = DEFAULT_H_SCALING_MODE;
gst_vp8_enc->v_scaling_mode = DEFAULT_V_SCALING_MODE;
@@ -750,7 +763,9 @@ gst_vp8_enc_init (GstVP8Enc * gst_vp8_enc)
gst_vp8_enc->cq_level = DEFAULT_CQ_LEVEL;
gst_vp8_enc->max_intra_bitrate_pct = DEFAULT_MAX_INTRA_BITRATE_PCT;
- gst_vp8_enc->profile = DEFAULT_PROFILE;
+ gst_vp8_enc->cfg.g_profile = DEFAULT_PROFILE;
+
+ g_mutex_init (&gst_vp8_enc->encoder_lock);
}
static void
@@ -769,6 +784,8 @@ gst_vp8_enc_finalize (GObject * object)
if (gst_vp8_enc->input_state)
gst_video_codec_state_unref (gst_vp8_enc->input_state);
+ g_mutex_clear (&gst_vp8_enc->encoder_lock);
+
G_OBJECT_CLASS (parent_class)->finalize (object);
}
@@ -783,64 +800,65 @@ gst_vp8_enc_set_property (GObject * object, guint prop_id,
gst_vp8_enc = GST_VP8_ENC (object);
GST_DEBUG_OBJECT (object, "gst_vp8_enc_set_property");
+ g_mutex_lock (&gst_vp8_enc->encoder_lock);
switch (prop_id) {
case PROP_RC_END_USAGE:
- gst_vp8_enc->rc_end_usage = g_value_get_enum (value);
+ gst_vp8_enc->cfg.rc_end_usage = g_value_get_enum (value);
break;
case PROP_RC_TARGET_BITRATE:
- gst_vp8_enc->rc_target_bitrate = g_value_get_int (value);
+ gst_vp8_enc->cfg.rc_target_bitrate = g_value_get_int (value) / 1000;
gst_vp8_enc->rc_target_bitrate_set = TRUE;
break;
case PROP_RC_MIN_QUANTIZER:
- gst_vp8_enc->rc_min_quantizer = g_value_get_int (value);
+ gst_vp8_enc->cfg.rc_min_quantizer = g_value_get_int (value);
break;
case PROP_RC_MAX_QUANTIZER:
- gst_vp8_enc->rc_max_quantizer = g_value_get_int (value);
+ gst_vp8_enc->cfg.rc_max_quantizer = g_value_get_int (value);
break;
case PROP_RC_DROPFRAME_THRESH:
- gst_vp8_enc->rc_dropframe_thresh = g_value_get_int (value);
+ gst_vp8_enc->cfg.rc_dropframe_thresh = g_value_get_int (value);
break;
case PROP_RC_RESIZE_ALLOWED:
- gst_vp8_enc->rc_resize_allowed = g_value_get_boolean (value);
+ gst_vp8_enc->cfg.rc_resize_allowed = g_value_get_boolean (value);
break;
case PROP_RC_RESIZE_UP_THRESH:
- gst_vp8_enc->rc_resize_up_thresh = g_value_get_int (value);
+ gst_vp8_enc->cfg.rc_resize_up_thresh = g_value_get_int (value);
break;
case PROP_RC_RESIZE_DOWN_THRESH:
- gst_vp8_enc->rc_resize_down_thresh = g_value_get_int (value);
+ gst_vp8_enc->cfg.rc_resize_down_thresh = g_value_get_int (value);
break;
case PROP_RC_UNDERSHOOT_PCT:
- gst_vp8_enc->rc_undershoot_pct = g_value_get_int (value);
+ gst_vp8_enc->cfg.rc_undershoot_pct = g_value_get_int (value);
break;
case PROP_RC_OVERSHOOT_PCT:
- gst_vp8_enc->rc_overshoot_pct = g_value_get_int (value);
+ gst_vp8_enc->cfg.rc_overshoot_pct = g_value_get_int (value);
break;
case PROP_RC_BUF_SZ:
- gst_vp8_enc->rc_buf_sz = g_value_get_int (value);
+ gst_vp8_enc->cfg.rc_buf_sz = g_value_get_int (value);
break;
case PROP_RC_BUF_INITIAL_SZ:
- gst_vp8_enc->rc_buf_initial_sz = g_value_get_int (value);
+ gst_vp8_enc->cfg.rc_buf_initial_sz = g_value_get_int (value);
break;
case PROP_RC_BUF_OPTIMAL_SZ:
- gst_vp8_enc->rc_buf_optimal_sz = g_value_get_int (value);
+ gst_vp8_enc->cfg.rc_buf_optimal_sz = g_value_get_int (value);
break;
case PROP_RC_2PASS_VBR_BIAS_PCT:
- gst_vp8_enc->rc_2pass_vbr_bias_pct = g_value_get_int (value);
+ gst_vp8_enc->cfg.rc_2pass_vbr_bias_pct = g_value_get_int (value);
break;
case PROP_RC_2PASS_VBR_MINSECTION_PCT:
- gst_vp8_enc->rc_2pass_vbr_minsection_pct = g_value_get_int (value);
+ gst_vp8_enc->cfg.rc_2pass_vbr_minsection_pct = g_value_get_int (value);
break;
case PROP_RC_2PASS_VBR_MAXSECTION_PCT:
- gst_vp8_enc->rc_2pass_vbr_maxsection_pct = g_value_get_int (value);
+ gst_vp8_enc->cfg.rc_2pass_vbr_maxsection_pct = g_value_get_int (value);
break;
case PROP_KF_MODE:
- gst_vp8_enc->kf_mode = g_value_get_enum (value);
+ gst_vp8_enc->cfg.kf_mode = g_value_get_enum (value);
break;
case PROP_KF_MAX_DIST:
- gst_vp8_enc->kf_max_dist = g_value_get_int (value);
+ gst_vp8_enc->cfg.kf_max_dist = g_value_get_int (value);
break;
case PROP_MULTIPASS_MODE:
- gst_vp8_enc->multipass_mode = g_value_get_enum (value);
+ gst_vp8_enc->cfg.g_pass = g_value_get_enum (value);
break;
case PROP_MULTIPASS_CACHE_FILE:
if (gst_vp8_enc->multipass_cache_file)
@@ -848,11 +866,13 @@ gst_vp8_enc_set_property (GObject * object, guint prop_id,
gst_vp8_enc->multipass_cache_file = g_value_dup_string (value);
break;
case PROP_TS_NUMBER_LAYERS:
- gst_vp8_enc->ts_number_layers = g_value_get_int (value);
+ gst_vp8_enc->cfg.ts_number_layers = g_value_get_int (value);
break;
case PROP_TS_TARGET_BITRATE:{
GValueArray *va = g_value_get_boxed (value);
+ memset (&gst_vp8_enc->cfg.ts_target_bitrate, 0,
+ sizeof (gst_vp8_enc->cfg.ts_target_bitrate));
if (va->n_values > VPX_TS_MAX_LAYERS) {
g_warning ("%s: Only %d layers allowed at maximum",
GST_ELEMENT_NAME (gst_vp8_enc), VPX_TS_MAX_LAYERS);
@@ -860,7 +880,7 @@ gst_vp8_enc_set_property (GObject * object, guint prop_id,
gint i;
for (i = 0; i < va->n_values; i++)
- gst_vp8_enc->ts_target_bitrate[i] =
+ gst_vp8_enc->cfg.ts_target_bitrate[i] =
g_value_get_int (g_value_array_get_nth (va, i));
gst_vp8_enc->n_ts_target_bitrate = va->n_values;
} else {
@@ -871,6 +891,8 @@ gst_vp8_enc_set_property (GObject * object, guint prop_id,
case PROP_TS_RATE_DECIMATOR:{
GValueArray *va = g_value_get_boxed (value);
+ memset (&gst_vp8_enc->cfg.ts_rate_decimator, 0,
+ sizeof (gst_vp8_enc->cfg.ts_rate_decimator));
if (va->n_values > VPX_TS_MAX_LAYERS) {
g_warning ("%s: Only %d layers allowed at maximum",
GST_ELEMENT_NAME (gst_vp8_enc), VPX_TS_MAX_LAYERS);
@@ -878,7 +900,7 @@ gst_vp8_enc_set_property (GObject * object, guint prop_id,
gint i;
for (i = 0; i < va->n_values; i++)
- gst_vp8_enc->ts_rate_decimator[i] =
+ gst_vp8_enc->cfg.ts_rate_decimator[i] =
g_value_get_int (g_value_array_get_nth (va, i));
gst_vp8_enc->n_ts_rate_decimator = va->n_values;
} else {
@@ -887,11 +909,13 @@ gst_vp8_enc_set_property (GObject * object, guint prop_id,
break;
}
case PROP_TS_PERIODICITY:
- gst_vp8_enc->ts_periodicity = g_value_get_int (value);
+ gst_vp8_enc->cfg.ts_periodicity = g_value_get_int (value);
break;
case PROP_TS_LAYER_ID:{
GValueArray *va = g_value_get_boxed (value);
+ memset (&gst_vp8_enc->cfg.ts_layer_id, 0,
+ sizeof (gst_vp8_enc->cfg.ts_layer_id));
if (va->n_values > VPX_TS_MAX_PERIODICITY) {
g_warning ("%s: Only %d sized layer sequences allowed at maximum",
GST_ELEMENT_NAME (gst_vp8_enc), VPX_TS_MAX_PERIODICITY);
@@ -899,7 +923,7 @@ gst_vp8_enc_set_property (GObject * object, guint prop_id,
gint i;
for (i = 0; i < va->n_values; i++)
- gst_vp8_enc->ts_layer_id[i] =
+ gst_vp8_enc->cfg.ts_layer_id[i] =
g_value_get_int (g_value_array_get_nth (va, i));
gst_vp8_enc->n_ts_layer_id = va->n_values;
} else {
@@ -908,13 +932,13 @@ gst_vp8_enc_set_property (GObject * object, guint prop_id,
break;
}
case PROP_ERROR_RESILIENT:
- gst_vp8_enc->error_resilient = g_value_get_flags (value);
+ gst_vp8_enc->cfg.g_error_resilient = g_value_get_flags (value);
break;
case PROP_LAG_IN_FRAMES:
- gst_vp8_enc->lag_in_frames = g_value_get_int (value);
+ gst_vp8_enc->cfg.g_lag_in_frames = g_value_get_int (value);
break;
case PROP_THREADS:
- gst_vp8_enc->threads = g_value_get_int (value);
+ gst_vp8_enc->cfg.g_threads = g_value_get_int (value);
break;
case PROP_DEADLINE:
gst_vp8_enc->deadline = g_value_get_int64 (value);
@@ -964,6 +988,8 @@ gst_vp8_enc_set_property (GObject * object, guint prop_id,
default:
break;
}
+
+ g_mutex_unlock (&gst_vp8_enc->encoder_lock);
}
static void
@@ -975,69 +1001,70 @@ gst_vp8_enc_get_property (GObject * object, guint prop_id, GValue * value,
g_return_if_fail (GST_IS_VP8_ENC (object));
gst_vp8_enc = GST_VP8_ENC (object);
+ g_mutex_lock (&gst_vp8_enc->encoder_lock);
switch (prop_id) {
case PROP_RC_END_USAGE:
- g_value_set_enum (value, gst_vp8_enc->rc_end_usage);
+ g_value_set_enum (value, gst_vp8_enc->cfg.rc_end_usage);
break;
case PROP_RC_TARGET_BITRATE:
- g_value_set_int (value, gst_vp8_enc->rc_target_bitrate);
+ g_value_set_int (value, gst_vp8_enc->cfg.rc_target_bitrate * 1000);
break;
case PROP_RC_MIN_QUANTIZER:
- g_value_set_int (value, gst_vp8_enc->rc_min_quantizer);
+ g_value_set_int (value, gst_vp8_enc->cfg.rc_min_quantizer);
break;
case PROP_RC_MAX_QUANTIZER:
- g_value_set_int (value, gst_vp8_enc->rc_max_quantizer);
+ g_value_set_int (value, gst_vp8_enc->cfg.rc_max_quantizer);
break;
case PROP_RC_DROPFRAME_THRESH:
- g_value_set_int (value, gst_vp8_enc->rc_dropframe_thresh);
+ g_value_set_int (value, gst_vp8_enc->cfg.rc_dropframe_thresh);
break;
case PROP_RC_RESIZE_ALLOWED:
- g_value_set_boolean (value, gst_vp8_enc->rc_resize_allowed);
+ g_value_set_boolean (value, gst_vp8_enc->cfg.rc_resize_allowed);
break;
case PROP_RC_RESIZE_UP_THRESH:
- g_value_set_int (value, gst_vp8_enc->rc_resize_up_thresh);
+ g_value_set_int (value, gst_vp8_enc->cfg.rc_resize_up_thresh);
break;
case PROP_RC_RESIZE_DOWN_THRESH:
- g_value_set_int (value, gst_vp8_enc->rc_resize_down_thresh);
+ g_value_set_int (value, gst_vp8_enc->cfg.rc_resize_down_thresh);
break;
case PROP_RC_UNDERSHOOT_PCT:
- g_value_set_int (value, gst_vp8_enc->rc_undershoot_pct);
+ g_value_set_int (value, gst_vp8_enc->cfg.rc_undershoot_pct);
break;
case PROP_RC_OVERSHOOT_PCT:
- g_value_set_int (value, gst_vp8_enc->rc_overshoot_pct);
+ g_value_set_int (value, gst_vp8_enc->cfg.rc_overshoot_pct);
break;
case PROP_RC_BUF_SZ:
- g_value_set_int (value, gst_vp8_enc->rc_buf_sz);
+ g_value_set_int (value, gst_vp8_enc->cfg.rc_buf_sz);
break;
case PROP_RC_BUF_INITIAL_SZ:
- g_value_set_int (value, gst_vp8_enc->rc_buf_initial_sz);
+ g_value_set_int (value, gst_vp8_enc->cfg.rc_buf_initial_sz);
break;
case PROP_RC_BUF_OPTIMAL_SZ:
- g_value_set_int (value, gst_vp8_enc->rc_buf_optimal_sz);
+ g_value_set_int (value, gst_vp8_enc->cfg.rc_buf_optimal_sz);
break;
case PROP_RC_2PASS_VBR_BIAS_PCT:
- g_value_set_int (value, gst_vp8_enc->rc_2pass_vbr_bias_pct);
+ g_value_set_int (value, gst_vp8_enc->cfg.rc_2pass_vbr_bias_pct);
break;
case PROP_RC_2PASS_VBR_MINSECTION_PCT:
- g_value_set_int (value, gst_vp8_enc->rc_2pass_vbr_minsection_pct);
+ g_value_set_int (value, gst_vp8_enc->cfg.rc_2pass_vbr_minsection_pct);
break;
case PROP_RC_2PASS_VBR_MAXSECTION_PCT:
- g_value_set_int (value, gst_vp8_enc->rc_2pass_vbr_maxsection_pct);
+ g_value_set_int (value, gst_vp8_enc->cfg.rc_2pass_vbr_maxsection_pct);
break;
case PROP_KF_MODE:
- g_value_set_enum (value, gst_vp8_enc->kf_mode);
+ g_value_set_enum (value, gst_vp8_enc->cfg.kf_mode);
break;
case PROP_KF_MAX_DIST:
- g_value_set_int (value, gst_vp8_enc->kf_max_dist);
+ g_value_set_int (value, gst_vp8_enc->cfg.kf_max_dist);
break;
case PROP_MULTIPASS_MODE:
- g_value_set_enum (value, gst_vp8_enc->multipass_mode);
+ g_value_set_enum (value, gst_vp8_enc->cfg.g_pass);
break;
case PROP_MULTIPASS_CACHE_FILE:
g_value_set_string (value, gst_vp8_enc->multipass_cache_file);
break;
case PROP_TS_NUMBER_LAYERS:
- g_value_set_int (value, gst_vp8_enc->ts_number_layers);
+ g_value_set_int (value, gst_vp8_enc->cfg.ts_number_layers);
break;
case PROP_TS_TARGET_BITRATE:{
GValueArray *va;
@@ -1052,7 +1079,7 @@ gst_vp8_enc_get_property (GObject * object, guint prop_id, GValue * value,
GValue v = { 0, };
g_value_init (&v, G_TYPE_INT);
- g_value_set_int (&v, gst_vp8_enc->ts_target_bitrate[i]);
+ g_value_set_int (&v, gst_vp8_enc->cfg.ts_target_bitrate[i]);
g_value_array_append (va, &v);
g_value_unset (&v);
}
@@ -1074,7 +1101,7 @@ gst_vp8_enc_get_property (GObject * object, guint prop_id, GValue * value,
GValue v = { 0, };
g_value_init (&v, G_TYPE_INT);
- g_value_set_int (&v, gst_vp8_enc->ts_rate_decimator[i]);
+ g_value_set_int (&v, gst_vp8_enc->cfg.ts_rate_decimator[i]);
g_value_array_append (va, &v);
g_value_unset (&v);
}
@@ -1084,7 +1111,7 @@ gst_vp8_enc_get_property (GObject * object, guint prop_id, GValue * value,
break;
}
case PROP_TS_PERIODICITY:
- g_value_set_int (value, gst_vp8_enc->ts_periodicity);
+ g_value_set_int (value, gst_vp8_enc->cfg.ts_periodicity);
break;
case PROP_TS_LAYER_ID:{
GValueArray *va;
@@ -1099,7 +1126,7 @@ gst_vp8_enc_get_property (GObject * object, guint prop_id, GValue * value,
GValue v = { 0, };
g_value_init (&v, G_TYPE_INT);
- g_value_set_int (&v, gst_vp8_enc->ts_layer_id[i]);
+ g_value_set_int (&v, gst_vp8_enc->cfg.ts_layer_id[i]);
g_value_array_append (va, &v);
g_value_unset (&v);
}
@@ -1109,13 +1136,13 @@ gst_vp8_enc_get_property (GObject * object, guint prop_id, GValue * value,
break;
}
case PROP_ERROR_RESILIENT:
- g_value_set_flags (value, gst_vp8_enc->error_resilient);
+ g_value_set_flags (value, gst_vp8_enc->cfg.g_error_resilient);
break;
case PROP_LAG_IN_FRAMES:
- g_value_set_int (value, gst_vp8_enc->lag_in_frames);
+ g_value_set_int (value, gst_vp8_enc->cfg.g_lag_in_frames);
break;
case PROP_THREADS:
- g_value_set_int (value, gst_vp8_enc->threads);
+ g_value_set_int (value, gst_vp8_enc->cfg.g_threads);
break;
case PROP_DEADLINE:
g_value_set_int64 (value, gst_vp8_enc->deadline);
@@ -1166,13 +1193,23 @@ gst_vp8_enc_get_property (GObject * object, guint prop_id, GValue * value,
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
+
+ g_mutex_unlock (&gst_vp8_enc->encoder_lock);
}
static gboolean
gst_vp8_enc_start (GstVideoEncoder * video_encoder)
{
+ GstVP8Enc *encoder = GST_VP8_ENC (video_encoder);
+
GST_DEBUG_OBJECT (video_encoder, "start");
+ if (!encoder->have_default_config) {
+ GST_ELEMENT_ERROR (encoder, LIBRARY, INIT,
+ ("Failed to get default encoder configuration"), (NULL));
+ return FALSE;
+ }
+
return TRUE;
}
@@ -1185,6 +1222,7 @@ gst_vp8_enc_stop (GstVideoEncoder * video_encoder)
encoder = GST_VP8_ENC (video_encoder);
+ g_mutex_lock (&encoder->encoder_lock);
if (encoder->inited) {
vpx_codec_destroy (&encoder->encoder);
encoder->inited = FALSE;
@@ -1195,11 +1233,12 @@ gst_vp8_enc_stop (GstVideoEncoder * video_encoder)
encoder->first_pass_cache_content = NULL;
}
- if (encoder->last_pass_cache_content.buf) {
- g_free (encoder->last_pass_cache_content.buf);
- encoder->last_pass_cache_content.buf = NULL;
- encoder->last_pass_cache_content.sz = 0;
+ if (encoder->cfg.rc_twopass_stats_in.buf) {
+ g_free (encoder->cfg.rc_twopass_stats_in.buf);
+ encoder->cfg.rc_twopass_stats_in.buf = NULL;
+ encoder->cfg.rc_twopass_stats_in.sz = 0;
}
+ g_mutex_unlock (&encoder->encoder_lock);
gst_tag_setter_reset_tags (GST_TAG_SETTER (encoder));
@@ -1250,7 +1289,6 @@ gst_vp8_enc_set_format (GstVideoEncoder * video_encoder,
GstVideoCodecState * state)
{
GstVP8Enc *encoder;
- vpx_codec_enc_cfg_t cfg;
vpx_codec_err_t status;
vpx_image_t *image;
guint8 *data = NULL;
@@ -1268,85 +1306,50 @@ gst_vp8_enc_set_format (GstVideoEncoder * video_encoder,
return FALSE;
}
- status = vpx_codec_enc_config_default (&vpx_codec_vp8_cx_algo, &cfg, 0);
- if (status != VPX_CODEC_OK) {
- GST_ELEMENT_ERROR (encoder, LIBRARY, INIT,
- ("Failed to get default encoder configuration"), ("%s",
- gst_vpx_error_name (status)));
- return FALSE;
- }
-
- encoder->profile = gst_vp8_enc_get_downstream_profile (encoder);
+ g_mutex_lock (&encoder->encoder_lock);
+ encoder->cfg.g_profile = gst_vp8_enc_get_downstream_profile (encoder);
/* Scale default bitrate to our size */
- cfg.rc_target_bitrate = gst_util_uint64_scale (cfg.rc_target_bitrate,
- GST_VIDEO_INFO_WIDTH (info) * GST_VIDEO_INFO_HEIGHT (info),
- cfg.g_w * cfg.g_h);
-
- cfg.g_w = GST_VIDEO_INFO_WIDTH (info);
- cfg.g_h = GST_VIDEO_INFO_HEIGHT (info);
- cfg.g_timebase.num = GST_VIDEO_INFO_FPS_D (info);
- cfg.g_timebase.den = GST_VIDEO_INFO_FPS_N (info);
-
- cfg.rc_end_usage = encoder->rc_end_usage;
- if (encoder->rc_target_bitrate_set)
- cfg.rc_target_bitrate = encoder->rc_target_bitrate / 1000;
- cfg.rc_min_quantizer = encoder->rc_min_quantizer;
- cfg.rc_max_quantizer = encoder->rc_max_quantizer;
- cfg.rc_dropframe_thresh = encoder->rc_dropframe_thresh;
- cfg.rc_resize_allowed = encoder->rc_resize_allowed;
- cfg.rc_resize_up_thresh = encoder->rc_resize_up_thresh;
- cfg.rc_resize_down_thresh = encoder->rc_resize_down_thresh;
- cfg.rc_undershoot_pct = encoder->rc_undershoot_pct;
- cfg.rc_overshoot_pct = encoder->rc_overshoot_pct;
- cfg.rc_buf_sz = encoder->rc_buf_sz;
- cfg.rc_buf_initial_sz = encoder->rc_buf_initial_sz;
- cfg.rc_buf_optimal_sz = encoder->rc_buf_optimal_sz;
- cfg.rc_2pass_vbr_bias_pct = encoder->rc_2pass_vbr_bias_pct;
- cfg.rc_2pass_vbr_minsection_pct = encoder->rc_2pass_vbr_minsection_pct;
- cfg.rc_2pass_vbr_maxsection_pct = encoder->rc_2pass_vbr_maxsection_pct;
- cfg.kf_mode = encoder->kf_mode;
- cfg.kf_max_dist = encoder->kf_max_dist;
- cfg.ts_number_layers = encoder->ts_number_layers;
- memcpy (cfg.ts_target_bitrate, encoder->ts_target_bitrate,
- sizeof (encoder->ts_target_bitrate));
- memcpy (cfg.ts_rate_decimator, encoder->ts_rate_decimator,
- sizeof (encoder->ts_rate_decimator));
- cfg.ts_periodicity = encoder->ts_periodicity;
- memcpy (cfg.ts_layer_id, encoder->ts_layer_id, sizeof (encoder->ts_layer_id));
- cfg.g_error_resilient = encoder->error_resilient;
- cfg.g_lag_in_frames = encoder->lag_in_frames;
- cfg.g_threads = encoder->threads;
-
- cfg.g_pass = encoder->multipass_mode;
- if (encoder->multipass_mode == VPX_RC_FIRST_PASS) {
+ if (!encoder->rc_target_bitrate_set)
+ encoder->cfg.rc_target_bitrate =
+ gst_util_uint64_scale (DEFAULT_RC_TARGET_BITRATE,
+ GST_VIDEO_INFO_WIDTH (info) * GST_VIDEO_INFO_HEIGHT (info), 320 * 240);
+
+ encoder->cfg.g_w = GST_VIDEO_INFO_WIDTH (info);
+ encoder->cfg.g_h = GST_VIDEO_INFO_HEIGHT (info);
+ encoder->cfg.g_timebase.num = GST_VIDEO_INFO_FPS_D (info);
+ encoder->cfg.g_timebase.den = GST_VIDEO_INFO_FPS_N (info);
+
+ if (encoder->cfg.g_pass == VPX_RC_FIRST_PASS) {
encoder->first_pass_cache_content = g_byte_array_sized_new (4096);
- } else if (encoder->multipass_mode == VPX_RC_LAST_PASS) {
+ } else if (encoder->cfg.g_pass == VPX_RC_LAST_PASS) {
GError *err = NULL;
if (!encoder->multipass_cache_file) {
GST_ELEMENT_ERROR (encoder, RESOURCE, OPEN_READ,
("No multipass cache file provided"), (NULL));
+ g_mutex_unlock (&encoder->encoder_lock);
return FALSE;
}
if (!g_file_get_contents (encoder->multipass_cache_file,
- (gchar **) & encoder->last_pass_cache_content.buf,
- &encoder->last_pass_cache_content.sz, &err)) {
+ (gchar **) & encoder->cfg.rc_twopass_stats_in.buf,
+ &encoder->cfg.rc_twopass_stats_in.sz, &err)) {
GST_ELEMENT_ERROR (encoder, RESOURCE, OPEN_READ,
("Failed to read multipass cache file provided"), ("%s",
err->message));
g_error_free (err);
+ g_mutex_unlock (&encoder->encoder_lock);
return FALSE;
}
- cfg.rc_twopass_stats_in = encoder->last_pass_cache_content;
}
status = vpx_codec_enc_init (&encoder->encoder, &vpx_codec_vp8_cx_algo,
- &cfg, 0);
+ &encoder->cfg, 0);
if (status != VPX_CODEC_OK) {
GST_ELEMENT_ERROR (encoder, LIBRARY, INIT,
("Failed to initialize encoder"), ("%s", gst_vpx_error_name (status)));
+ g_mutex_unlock (&encoder->encoder_lock);
return FALSE;
}
@@ -1447,7 +1450,7 @@ gst_vp8_enc_set_format (GstVideoEncoder * video_encoder,
}
gst_video_encoder_set_latency (video_encoder, 0,
- gst_util_uint64_scale (encoder->lag_in_frames,
+ gst_util_uint64_scale (encoder->cfg.g_lag_in_frames,
GST_VIDEO_INFO_FPS_D (info) * GST_SECOND,
GST_VIDEO_INFO_FPS_N (info)));
encoder->inited = TRUE;
@@ -1471,7 +1474,7 @@ gst_vp8_enc_set_format (GstVideoEncoder * video_encoder,
image->stride[VPX_PLANE_U] = GST_VIDEO_INFO_COMP_STRIDE (info, 1);
image->stride[VPX_PLANE_V] = GST_VIDEO_INFO_COMP_STRIDE (info, 2);
- profile_str = g_strdup_printf ("%d", encoder->profile);
+ profile_str = g_strdup_printf ("%d", encoder->cfg.g_profile);
caps = gst_caps_new_simple ("video/x-vp8",
"profile", G_TYPE_STRING, profile_str, NULL);
g_free (profile_str);
@@ -1534,6 +1537,8 @@ gst_vp8_enc_set_format (GstVideoEncoder * video_encoder,
gst_structure_set_value (s, "streamheader", &array);
g_value_unset (&array);
}
+ g_mutex_unlock (&encoder->encoder_lock);
+
output_state =
gst_video_encoder_set_output_state (video_encoder, caps, state);
gst_video_codec_state_unref (output_state);
@@ -1543,6 +1548,13 @@ gst_vp8_enc_set_format (GstVideoEncoder * video_encoder,
return ret;
}
+static void
+_gst_video_codec_frame_unref0 (GstVideoCodecFrame * frame)
+{
+ if (frame)
+ gst_video_codec_frame_unref (frame);
+}
+
static GstFlowReturn
gst_vp8_enc_process (GstVP8Enc * encoder)
{
@@ -1552,9 +1564,11 @@ gst_vp8_enc_process (GstVP8Enc * encoder)
GstVP8EncUserData *user_data;
GstVideoCodecFrame *frame;
GstFlowReturn ret = GST_FLOW_OK;
+ GList *l, *frames = NULL;
video_encoder = GST_VIDEO_ENCODER (encoder);
+ g_mutex_lock (&encoder->encoder_lock);
pkt = vpx_codec_get_cx_data (&encoder->encoder, &iter);
while (pkt != NULL) {
GstBuffer *buffer;
@@ -1564,7 +1578,7 @@ gst_vp8_enc_process (GstVP8Enc * encoder)
pkt->kind);
if (pkt->kind == VPX_CODEC_STATS_PKT
- && encoder->multipass_mode == VPX_RC_FIRST_PASS) {
+ && encoder->cfg.g_pass == VPX_RC_FIRST_PASS) {
GST_LOG_OBJECT (encoder, "handling STATS packet");
g_byte_array_append (encoder->first_pass_cache_content,
@@ -1575,7 +1589,7 @@ gst_vp8_enc_process (GstVP8Enc * encoder)
buffer = gst_buffer_new ();
GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_LIVE);
frame->output_buffer = buffer;
- gst_video_encoder_finish_frame (video_encoder, frame);
+ frames = g_list_prepend (frames, frame);
}
pkt = vpx_codec_get_cx_data (&encoder->encoder, &iter);
@@ -1609,11 +1623,23 @@ gst_vp8_enc_process (GstVP8Enc * encoder)
user_data->invisible = g_list_append (user_data->invisible, buffer);
} else {
frame->output_buffer = buffer;
- ret = gst_video_encoder_finish_frame (video_encoder, frame);
+ frames = g_list_prepend (frames, frame);
}
pkt = vpx_codec_get_cx_data (&encoder->encoder, &iter);
}
+ g_mutex_unlock (&encoder->encoder_lock);
+
+ frames = g_list_reverse (frames);
+ for (l = frames; l; l = l->next) {
+ ret = gst_video_encoder_finish_frame (video_encoder, l->data);
+ l->data = NULL;
+ if (ret != GST_FLOW_OK)
+ break;
+ }
+
+ g_list_foreach (frames, (GFunc) _gst_video_codec_frame_unref0, NULL);
+ g_list_free (frames);
return ret;
}
@@ -1629,9 +1655,11 @@ gst_vp8_enc_finish (GstVideoEncoder * video_encoder)
encoder = GST_VP8_ENC (video_encoder);
+ g_mutex_lock (&encoder->encoder_lock);
status =
vpx_codec_encode (&encoder->encoder, NULL, encoder->n_frames, 1, flags,
encoder->deadline);
+ g_mutex_unlock (&encoder->encoder_lock);
if (status != 0) {
GST_ERROR_OBJECT (encoder, "encode returned %d %s", status,
gst_vpx_error_name (status));
@@ -1641,8 +1669,7 @@ gst_vp8_enc_finish (GstVideoEncoder * video_encoder)
/* dispatch remaining frames */
gst_vp8_enc_process (encoder);
- if (encoder->multipass_mode == VPX_RC_FIRST_PASS
- && encoder->multipass_cache_file) {
+ if (encoder->cfg.g_pass == VPX_RC_FIRST_PASS && encoder->multipass_cache_file) {
GError *err = NULL;
if (!g_file_set_contents (encoder->multipass_cache_file,
@@ -1709,8 +1736,10 @@ gst_vp8_enc_handle_frame (GstVideoEncoder * video_encoder,
flags |= VPX_EFLAG_FORCE_KF;
}
+ g_mutex_lock (&encoder->encoder_lock);
status = vpx_codec_encode (&encoder->encoder, image,
encoder->n_frames, 1, flags, encoder->deadline);
+ g_mutex_unlock (&encoder->encoder_lock);
gst_video_frame_unmap (&vframe);
if (status != 0) {
diff --git a/ext/vpx/gstvp8enc.h b/ext/vpx/gstvp8enc.h
index 7338affeb..a8120677a 100644
--- a/ext/vpx/gstvp8enc.h
+++ b/ext/vpx/gstvp8enc.h
@@ -56,60 +56,18 @@ struct _GstVP8Enc
/* < private > */
vpx_codec_ctx_t encoder;
-
- /* from downstream caps */
- int profile;
+ GMutex encoder_lock;
/* properties */
- /* Rate control options */
- enum vpx_rc_mode rc_end_usage;
- unsigned int rc_target_bitrate;
+ vpx_codec_enc_cfg_t cfg;
+ gboolean have_default_config;
gboolean rc_target_bitrate_set;
- unsigned int rc_min_quantizer, rc_max_quantizer;
-
- unsigned int rc_dropframe_thresh;
- gboolean rc_resize_allowed;
- unsigned int rc_resize_up_thresh;
- unsigned int rc_resize_down_thresh;
- unsigned int rc_undershoot_pct;
- unsigned int rc_overshoot_pct;
- unsigned int rc_buf_sz;
- unsigned int rc_buf_initial_sz;
- unsigned int rc_buf_optimal_sz;
-
- unsigned int rc_2pass_vbr_bias_pct;
- unsigned int rc_2pass_vbr_minsection_pct;
- unsigned int rc_2pass_vbr_maxsection_pct;
-
- /* Global keyframe options */
- enum vpx_kf_mode kf_mode;
- unsigned int kf_max_dist;
-
+ gint n_ts_target_bitrate;
+ gint n_ts_rate_decimator;
+ gint n_ts_layer_id;
/* Global two-pass options */
- enum vpx_enc_pass multipass_mode;
gchar *multipass_cache_file;
GByteArray *first_pass_cache_content;
- vpx_fixed_buf_t last_pass_cache_content;
-
- /* Global temporal scalability options */
- unsigned int ts_number_layers;
- unsigned int ts_target_bitrate[VPX_TS_MAX_LAYERS];
- int n_ts_target_bitrate;
- unsigned int ts_rate_decimator[VPX_TS_MAX_LAYERS];
- int n_ts_rate_decimator;
- unsigned int ts_periodicity;
- unsigned int ts_layer_id[VPX_TS_MAX_PERIODICITY];
- int n_ts_layer_id;
-
- /* Global, other options */
- vpx_codec_er_flags_t error_resilient;
- unsigned int lag_in_frames;
-
- int threads;
-#if 0
- /* Only usage 0 is defined right now */
- int usage;
-#endif
/* Encode parameter */
gint64 deadline;