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 ();
}
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:
}
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);
}
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);
}
#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;
gboolean ready_for_update;
gint64 next_update_timestamp;
+ gint64 last_update_timestamp;
gchar *unit_name;
gboolean is_log;
};
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
}
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,
dparam->do_update_func = gst_dparam_do_update_default;
break;
}
- dpsmooth->last_update_timestamp = 0LL;
return dparam;
}
}
}
-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;
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);
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;
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
+ }
+ else {
final_val = target;
- GST_DPARAM_READY_FOR_UPDATE(dparam) = FALSE;
}
+ }
}
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);
}
+
struct _GstDParamSmooth {
GstDParam dparam;
- gint64 last_update_timestamp;
gint64 update_period;
gint64 slope_time;
gfloat slope_delta_float;
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);
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);
}
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))){
/* 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:
/* 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;
}
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;
}
gint64 timestamp;
guint rate;
+ GstDParamUpdateInfo update_info;
};
struct _GstDParamManagerClass {