diff --git a/libs/gst/control/dparam.c b/libs/gst/control/dparam.c index 203138028b..c0cd33ee73 100644 --- a/libs/gst/control/dparam.c +++ b/libs/gst/control/dparam.c @@ -99,6 +99,7 @@ gst_dparam_init (GstDParam *dparam) g_return_if_fail (dparam != NULL); GST_DPARAM_TYPE(dparam) = 0; GST_DPARAM_NEXT_UPDATE_TIMESTAMP(dparam)=0LL; + GST_DPARAM_LAST_UPDATE_TIMESTAMP(dparam)=0LL; GST_DPARAM_READY_FOR_UPDATE(dparam)=FALSE; dparam->lock = g_mutex_new (); } @@ -150,18 +151,21 @@ gst_dparam_set_property (GObject *object, guint prop_id, const GValue *value, GP GST_DEBUG(GST_CAT_PARAMS, "setting value from %f to %f", dparam->value_float, g_value_get_float (value)); dparam->value_float = g_value_get_float (value); GST_DPARAM_READY_FOR_UPDATE(dparam) = TRUE; + GST_DPARAM_NEXT_UPDATE_TIMESTAMP(dparam) = GST_DPARAM_LAST_UPDATE_TIMESTAMP(dparam); break; case ARG_VALUE_INT: GST_DEBUG(GST_CAT_PARAMS, "setting value from %d to %d", dparam->value_int, g_value_get_int (value)); dparam->value_int = g_value_get_int (value); GST_DPARAM_READY_FOR_UPDATE(dparam) = TRUE; + GST_DPARAM_NEXT_UPDATE_TIMESTAMP(dparam) = GST_DPARAM_LAST_UPDATE_TIMESTAMP(dparam); break; case ARG_VALUE_INT64: GST_DEBUG(GST_CAT_PARAMS, "setting value from %lld to %lld", dparam->value_int64, g_value_get_int64 (value)); dparam->value_int64 = g_value_get_int (value); GST_DPARAM_READY_FOR_UPDATE(dparam) = TRUE; + GST_DPARAM_NEXT_UPDATE_TIMESTAMP(dparam) = GST_DPARAM_LAST_UPDATE_TIMESTAMP(dparam); break; default: @@ -171,7 +175,7 @@ gst_dparam_set_property (GObject *object, guint prop_id, const GValue *value, GP } void -gst_dparam_do_update_default (GstDParam *dparam, gint64 timestamp, GValue *value) +gst_dparam_do_update_default (GstDParam *dparam, gint64 timestamp, GValue *value, GstDParamUpdateInfo update_info) { GST_DPARAM_LOCK(dparam); @@ -196,6 +200,8 @@ gst_dparam_do_update_default (GstDParam *dparam, gint64 timestamp, GValue *value } GST_DPARAM_READY_FOR_UPDATE(dparam) = FALSE; + GST_DPARAM_LAST_UPDATE_TIMESTAMP(dparam) = timestamp; + GST_DPARAM_NEXT_UPDATE_TIMESTAMP(dparam) = timestamp; GST_DPARAM_UNLOCK(dparam); } diff --git a/libs/gst/control/dparam.h b/libs/gst/control/dparam.h index 5b38894005..8f1975e2f9 100644 --- a/libs/gst/control/dparam.h +++ b/libs/gst/control/dparam.h @@ -51,13 +51,20 @@ extern "C" { #define GST_DPARAM_READY_FOR_UPDATE(dparam) ((dparam)->ready_for_update) #define GST_DPARAM_NEXT_UPDATE_TIMESTAMP(dparam) ((dparam)->next_update_timestamp) +#define GST_DPARAM_LAST_UPDATE_TIMESTAMP(dparam) ((dparam)->last_update_timestamp) -#define GST_DPARAM_DO_UPDATE(dparam, timestamp, value) \ - ((dparam->do_update_func)(dparam, timestamp, value)) +#define GST_DPARAM_DO_UPDATE(dparam, timestamp, value, update_info) \ + ((dparam->do_update_func)(dparam, timestamp, value, update_info)) typedef struct _GstDParamClass GstDParamClass; -typedef void (*GstDParamDoUpdateFunction) (GstDParam *dparam, gint64 timestamp, GValue *value); + +typedef enum { + GST_DPARAM_UPDATE_FIRST, + GST_DPARAM_UPDATE_NORMAL, +} GstDParamUpdateInfo; + +typedef void (*GstDParamDoUpdateFunction) (GstDParam *dparam, gint64 timestamp, GValue *value, GstDParamUpdateInfo update_info); struct _GstDParam { GstObject object; @@ -76,6 +83,7 @@ struct _GstDParam { gboolean ready_for_update; gint64 next_update_timestamp; + gint64 last_update_timestamp; gchar *unit_name; gboolean is_log; }; @@ -91,7 +99,7 @@ GType gst_dparam_get_type (void); GstDParam* gst_dparam_new (GType type); void gst_dparam_attach (GstDParam *dparam, GstDParamManager *manager, GParamSpec *param_spec, gchar *unit_name); void gst_dparam_detach (GstDParam *dparam); -void gst_dparam_do_update_default (GstDParam *dparam, gint64 timestamp, GValue *value); +void gst_dparam_do_update_default (GstDParam *dparam, gint64 timestamp, GValue *value, GstDParamUpdateInfo update_info); #ifdef __cplusplus } diff --git a/libs/gst/control/dparam_smooth.c b/libs/gst/control/dparam_smooth.c index c975a6f9d3..9bcfe33f90 100644 --- a/libs/gst/control/dparam_smooth.c +++ b/libs/gst/control/dparam_smooth.c @@ -30,8 +30,7 @@ static void gst_dpsmooth_class_init (GstDParamSmoothClass *klass); static void gst_dpsmooth_init (GstDParamSmooth *dparam); static void gst_dpsmooth_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec); static void gst_dpsmooth_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec); -static gint64 gst_dpsmooth_time_since_last_update(GstDParam *dparam, gint64 timestamp); -static void gst_dpsmooth_do_update_float (GstDParam *dparam, gint64 timestamp, GValue *value); +static void gst_dpsmooth_do_update_float (GstDParam *dparam, gint64 timestamp, GValue *value, GstDParamUpdateInfo update_info); enum { ARG_0, @@ -132,7 +131,6 @@ gst_dpsmooth_new (GType type) dparam->do_update_func = gst_dparam_do_update_default; break; } - dpsmooth->last_update_timestamp = 0LL; return dparam; } @@ -199,35 +197,8 @@ gst_dpsmooth_get_property (GObject *object, guint prop_id, GValue *value, GParam } } -static gint64 -gst_dpsmooth_time_since_last_update(GstDParam *dparam, gint64 timestamp) -{ - gint64 time_diff, last_update_diff, num_update_periods; - GstDParamSmooth *dpsmooth = GST_DPSMOOTH(dparam); - - last_update_diff = timestamp - dpsmooth->last_update_timestamp; - time_diff = MIN(dpsmooth->update_period, last_update_diff); - - GST_DEBUG(GST_CAT_PARAMS, "last_update_diff:%lld",last_update_diff); - GST_DEBUG(GST_CAT_PARAMS, "time_diff:%lld",time_diff); - - dpsmooth->last_update_timestamp = GST_DPARAM_NEXT_UPDATE_TIMESTAMP(dparam); - if(GST_DPARAM_NEXT_UPDATE_TIMESTAMP(dparam) <= timestamp && dpsmooth->update_period > 0LL){ - - GST_DEBUG(GST_CAT_PARAMS, "dpsmooth->update_period:%lld",dpsmooth->update_period); - num_update_periods = last_update_diff / dpsmooth->update_period; - - GST_DEBUG(GST_CAT_PARAMS, "num_update_periods:%lld",num_update_periods); - - GST_DPARAM_NEXT_UPDATE_TIMESTAMP(dparam) = dpsmooth->update_period * (num_update_periods + 1LL); - } - GST_DEBUG(GST_CAT_PARAMS, "last:%lld current:%lld next:%lld", - dpsmooth->last_update_timestamp, timestamp, GST_DPARAM_NEXT_UPDATE_TIMESTAMP(dparam)); - return time_diff; -} - static void -gst_dpsmooth_do_update_float (GstDParam *dparam, gint64 timestamp, GValue *value) +gst_dpsmooth_do_update_float (GstDParam *dparam, gint64 timestamp, GValue *value, GstDParamUpdateInfo update_info) { gint64 time_diff; gfloat time_ratio; @@ -238,9 +209,21 @@ gst_dpsmooth_do_update_float (GstDParam *dparam, gint64 timestamp, GValue *value GST_DPARAM_LOCK(dparam); - time_diff = gst_dpsmooth_time_since_last_update(dparam, timestamp); + if (update_info == GST_DPARAM_UPDATE_FIRST){ + /*this is the first update since the pipeline started. + * the value won't be smoothed, it will be updated immediately + */ + g_value_set_float(value, dparam->value_float); + GST_DPARAM_LAST_UPDATE_TIMESTAMP(dparam) = timestamp; + GST_DPARAM_NEXT_UPDATE_TIMESTAMP(dparam) = timestamp; + + GST_DPARAM_READY_FOR_UPDATE(dparam) = FALSE; + GST_DPARAM_UNLOCK(dparam); + return; + } + + time_diff = timestamp - GST_DPARAM_LAST_UPDATE_TIMESTAMP(dparam); - target = dparam->value_float; current = g_value_get_float(value); @@ -255,7 +238,6 @@ gst_dpsmooth_do_update_float (GstDParam *dparam, gint64 timestamp, GValue *value if (current == 0.0F){ /* this shouldn't happen, so forget about smoothing and just set the value */ final_val = target; - GST_DPARAM_READY_FOR_UPDATE(dparam) = FALSE; } else { gfloat current_log; @@ -265,27 +247,34 @@ gst_dpsmooth_do_update_float (GstDParam *dparam, gint64 timestamp, GValue *value GST_DEBUG(GST_CAT_PARAMS, "current_log:%f",current_log); GST_DEBUG(GST_CAT_PARAMS, "current_diff:%f",current_diff); - if (current_diff > max_change) + if (current_diff > max_change){ final_val = (target < current) ? exp(current_log-max_change) : exp(current_log+max_change); - else - final_val = target; - GST_DPARAM_READY_FOR_UPDATE(dparam) = FALSE; } + else { + final_val = target; + } + } } else { current_diff = ABS (current - target); - if (current_diff > max_change) + if (current_diff > max_change){ final_val = (target < current) ? current-max_change : current+max_change; - else + } + else { final_val = target; - GST_DPARAM_READY_FOR_UPDATE(dparam) = FALSE; + } } - GST_DPARAM_READY_FOR_UPDATE(dparam) = (current_diff > max_change); - g_value_set_float(value, final_val); + GST_DPARAM_READY_FOR_UPDATE(dparam) = (final_val != target); + if (GST_DPARAM_READY_FOR_UPDATE(dparam)){ + GST_DPARAM_NEXT_UPDATE_TIMESTAMP(dparam) = timestamp + dpsmooth->update_period; + } + GST_DPARAM_LAST_UPDATE_TIMESTAMP(dparam) = timestamp; + g_value_set_float(value, final_val); GST_DEBUG(GST_CAT_PARAMS, "target:%f current:%f final:%f actual:%f", target, current, final_val, g_value_get_float(value)); GST_DPARAM_UNLOCK(dparam); } + diff --git a/libs/gst/control/dparam_smooth.h b/libs/gst/control/dparam_smooth.h index f9e8539065..0210e34faf 100644 --- a/libs/gst/control/dparam_smooth.h +++ b/libs/gst/control/dparam_smooth.h @@ -40,7 +40,6 @@ typedef struct _GstDParamSmooth GstDParamSmooth; struct _GstDParamSmooth { GstDParam dparam; - gint64 last_update_timestamp; gint64 update_period; gint64 slope_time; gfloat slope_delta_float; diff --git a/libs/gst/control/dparammanager.c b/libs/gst/control/dparammanager.c index 6a53ad1ae9..a38f1c81cc 100644 --- a/libs/gst/control/dparammanager.c +++ b/libs/gst/control/dparammanager.c @@ -628,6 +628,9 @@ gst_dpman_state_change (GstElement *element, gint old_state, gint new_state, Gst if (new_state == GST_STATE_PLAYING){ GST_DEBUG(GST_CAT_PARAMS, "initialising params"); + + /* some dparams treat the first update after the pipeline starts differently */ + dpman->update_info = GST_DPARAM_UPDATE_FIRST; /* force all params to be updated */ dwraps = GST_DPMAN_DPARAMS_LIST(dpman); @@ -637,9 +640,7 @@ gst_dpman_state_change (GstElement *element, gint old_state, gint new_state, Gst if (dparam){ GST_DPARAM_READY_FOR_UPDATE(dparam) = TRUE; - /*if (dparam->spec){ - g_value_copy(dparam->spec->default_val, dpwrap->value); - }*/ + GST_DPARAM_NEXT_UPDATE_TIMESTAMP(dparam) = 0LL; } dwraps = g_slist_next(dwraps); } @@ -676,7 +677,10 @@ gst_dpman_preprocess_synchronous(GstDParamManager *dpman, guint frames, gint64 t while (dwraps){ dpwrap = (GstDParamWrapper*)dwraps->data; dparam = dpwrap->dparam; - + + /*g_print("timestamp %lld \n", timestamp); + if (dparam) + g_print("next update: %lld \n", GST_DPARAM_NEXT_UPDATE_TIMESTAMP(dparam));*/ if (dparam && (GST_DPARAM_READY_FOR_UPDATE(dparam) && (GST_DPARAM_NEXT_UPDATE_TIMESTAMP(dparam) <= timestamp))){ @@ -684,7 +688,7 @@ gst_dpman_preprocess_synchronous(GstDParamManager *dpman, guint frames, gint64 t /* direct method - set the value directly in the struct of the element */ case GST_DPMAN_DIRECT: - GST_DPARAM_DO_UPDATE(dparam, timestamp, dpwrap->value); + GST_DPARAM_DO_UPDATE(dparam, timestamp, dpwrap->value, dpman->update_info); GST_DEBUG(GST_CAT_PARAMS, "doing direct update"); switch (G_VALUE_TYPE(dpwrap->value)){ case G_TYPE_INT: @@ -703,7 +707,7 @@ gst_dpman_preprocess_synchronous(GstDParamManager *dpman, guint frames, gint64 t /* callback method - call the element's callback so it can do what it likes */ case GST_DPMAN_CALLBACK: - GST_DPARAM_DO_UPDATE(dparam, timestamp, dpwrap->value); + GST_DPARAM_DO_UPDATE(dparam, timestamp, dpwrap->value, dpman->update_info); GST_DEBUG(GST_CAT_PARAMS, "doing callback update"); GST_DPMAN_DO_UPDATE(dpwrap); break; @@ -729,6 +733,12 @@ gst_dpman_preprocess_synchronous(GstDParamManager *dpman, guint frames, gint64 t } dwraps = g_slist_next(dwraps); } + + if (dpman->update_info == GST_DPARAM_UPDATE_FIRST){ + /* it is not the first update anymore */ + dpman->update_info = GST_DPARAM_UPDATE_NORMAL; + } + return frames; } diff --git a/libs/gst/control/dparammanager.h b/libs/gst/control/dparammanager.h index a467a4ceed..ee8bbfa597 100644 --- a/libs/gst/control/dparammanager.h +++ b/libs/gst/control/dparammanager.h @@ -77,6 +77,7 @@ struct _GstDParamManager { gint64 timestamp; guint rate; + GstDParamUpdateInfo update_info; }; struct _GstDParamManagerClass {