📄 gstcontroller.c
字号:
g_list_free (prop->values); prop->last_requested_value = NULL; prop->values = NULL; res = TRUE; } g_mutex_unlock (self->lock); return (res);}/** * gst_controller_get: * @self: the controller object which handles the properties * @property_name: the name of the property to get * @timestamp: the time the control-change should be read from * * Gets the value for the given controller-handled property at the requested * time. * * Returns: the GValue of the property at the given time, or %NULL if the property isn't handled by the controller */GValue *gst_controller_get (GstController * self, gchar * property_name, GstClockTime timestamp){ GstControlledProperty *prop; GValue *val = NULL; g_return_val_if_fail (GST_IS_CONTROLLER (self), NULL); g_return_val_if_fail (property_name, NULL); g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), NULL); g_mutex_lock (self->lock); if ((prop = gst_controller_find_controlled_property (self, property_name))) { /* get current value via interpolator */ val = prop->get (prop, timestamp); } g_mutex_unlock (self->lock); return (val);}/** * gst_controller_get_all: * @self: the controller to get the list from * @property_name: the name of the property to get the list for * * Returns a read-only copy of the list of GstTimedValue for the given property. * Free the list after done with it. * * Returns: a copy of the list, or %NULL if the property isn't handled by the controller */const GList *gst_controller_get_all (GstController * self, gchar * property_name){ GList *res = NULL; GstControlledProperty *prop; g_return_val_if_fail (GST_IS_CONTROLLER (self), NULL); g_return_val_if_fail (property_name, NULL); g_mutex_lock (self->lock); if ((prop = gst_controller_find_controlled_property (self, property_name))) { res = g_list_copy (prop->values); } g_mutex_unlock (self->lock); return (res);}/** * gst_controller_suggest_next_sync: * @self: the controller that handles the values * * Returns a suggestion for timestamps where buffers should be split * to get best controller results. * * Returns: Returns the suggested timestamp or %GST_CLOCK_TIME_NONE * if no control-rate was set. * * Since: 0.10.13 */GstClockTimegst_controller_suggest_next_sync (GstController * self){ GstClockTime ret; g_return_val_if_fail (GST_IS_CONTROLLER (self), GST_CLOCK_TIME_NONE); g_return_val_if_fail (self->priv->control_rate != GST_CLOCK_TIME_NONE, GST_CLOCK_TIME_NONE); g_mutex_lock (self->lock); /* TODO: Implement more logic, depending on interpolation mode * and control points */ ret = self->priv->last_sync + self->priv->control_rate; g_mutex_unlock (self->lock); return ret;}/** * gst_controller_sync_values: * @self: the controller that handles the values * @timestamp: the time that should be processed * * Sets the properties of the element, according to the controller that (maybe) * handles them and for the given timestamp. * * Returns: %TRUE if the controller values could be applied to the object * properties, %FALSE otherwise */gbooleangst_controller_sync_values (GstController * self, GstClockTime timestamp){ GstControlledProperty *prop; GList *node; GValue *value; gboolean live = FALSE; g_return_val_if_fail (GST_IS_CONTROLLER (self), FALSE); g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE); GST_LOG ("sync_values"); g_mutex_lock (self->lock); /* go over the controlled properties of the controller */ for (node = self->properties; node; node = g_list_next (node)) { prop = node->data; GST_DEBUG (" property '%s' at ts=%" G_GUINT64_FORMAT, prop->name, timestamp); live = FALSE; if (G_UNLIKELY (G_IS_VALUE (&prop->live_value.value))) { GList *lnode = gst_controlled_property_find_control_point_node (prop, timestamp); if (G_UNLIKELY (!lnode)) { GST_DEBUG (" no control changes in the queue"); live = TRUE; } else { GstControlPoint *cp = lnode->data; if (prop->live_value.timestamp < cp->timestamp) { g_value_unset (&prop->live_value.value); GST_DEBUG (" live value resetted"); } else if (prop->live_value.timestamp < timestamp) { live = TRUE; } } } if (G_LIKELY (!live)) { /* get current value via interpolator */ value = prop->get (prop, timestamp); prop->last_value.timestamp = timestamp; g_value_copy (value, &prop->last_value.value); g_object_set_property (self->object, prop->name, value); } } if (G_LIKELY (!live)) self->priv->last_sync = timestamp; g_mutex_unlock (self->lock); /* TODO what can here go wrong, to return FALSE ? BilboEd : Nothing I guess, as long as all the checks are made when creating the controller, adding/removing controlled properties, etc... */ return (TRUE);}/** * gst_controller_get_value_arrays: * @self: the controller that handles the values * @timestamp: the time that should be processed * @value_arrays: list to return the control-values in * * Function to be able to get an array of values for one or more given element * properties. * * All fields of the %GstValueArray in the list must be filled correctly. * Especially the GstValueArray->values arrays must be big enough to keep * the requested amount of values. * * The types of the values in the array are the same as the property's type. * * Returns: %TRUE if the given array(s) could be filled, %FALSE otherwise */gbooleangst_controller_get_value_arrays (GstController * self, GstClockTime timestamp, GSList * value_arrays){ gboolean res = TRUE; GSList *node; g_return_val_if_fail (GST_IS_CONTROLLER (self), FALSE); g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE); g_return_val_if_fail (value_arrays, FALSE); for (node = value_arrays; (res && node); node = g_slist_next (node)) { res = gst_controller_get_value_array (self, timestamp, node->data); } return (res);}/** * gst_controller_get_value_array: * @self: the controller that handles the values * @timestamp: the time that should be processed * @value_array: array to put control-values in * * Function to be able to get an array of values for one element property. * * All fields of @value_array must be filled correctly. Especially the * @value_array->values array must be big enough to keep the requested amount * of values. * * The type of the values in the array is the same as the property's type. * * Returns: %TRUE if the given array could be filled, %FALSE otherwise */gbooleangst_controller_get_value_array (GstController * self, GstClockTime timestamp, GstValueArray * value_array){ gboolean res = FALSE; GstControlledProperty *prop; g_return_val_if_fail (GST_IS_CONTROLLER (self), FALSE); g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE); g_return_val_if_fail (value_array, FALSE); g_return_val_if_fail (value_array->property_name, FALSE); g_return_val_if_fail (value_array->values, FALSE); g_mutex_lock (self->lock); if ((prop = gst_controller_find_controlled_property (self, value_array->property_name))) { /* get current value_array via interpolator */ res = prop->get_value_array (prop, timestamp, value_array); } g_mutex_unlock (self->lock); return (res);}/** * gst_controller_set_interpolation_mode: * @self: the controller object * @property_name: the name of the property for which to change the interpolation * @mode: interpolation mode * * Sets the given interpolation mode on the given property. * * <note><para>Quadratic, cubic and user interpolation is not yet available. * </para></note> * * Returns: %TRUE if the property is handled by the controller, %FALSE otherwise */gbooleangst_controller_set_interpolation_mode (GstController * self, gchar * property_name, GstInterpolateMode mode){ gboolean res = FALSE; GstControlledProperty *prop; g_return_val_if_fail (GST_IS_CONTROLLER (self), FALSE); g_return_val_if_fail (property_name, FALSE); g_mutex_lock (self->lock); if ((prop = gst_controller_find_controlled_property (self, property_name))) { /* TODO shouldn't this also get a GstInterpolateMethod *user_method for the case mode==GST_INTERPOLATE_USER */ res = gst_controlled_property_set_interpolation_mode (prop, mode); } g_mutex_unlock (self->lock); return (res);}/* gobject handling */static void_gst_controller_get_property (GObject * object, guint property_id, GValue * value, GParamSpec * pspec){ GstController *self = GST_CONTROLLER (object); switch (property_id) { case PROP_CONTROL_RATE:{ /* FIXME: don't change if element is playing, controller works for GObject so this wont work GstState c_state, p_state; GstStateChangeReturn ret; ret = gst_element_get_state (self->object, &c_state, &p_state, 0); if ((ret == GST_STATE_CHANGE_SUCCESS && (c_state == GST_STATE_NULL || c_state == GST_STATE_READY)) || (ret == GST_STATE_CHANGE_ASYNC && (p_state == GST_STATE_NULL || p_state == GST_STATE_READY))) { */ g_value_set_uint64 (value, self->priv->control_rate); /* } else { GST_WARNING ("Changing the control rate is only allowed if the elemnt" " is in NULL or READY"); } */ } break; default:{ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } break; }}/* sets the given properties for this object */static void_gst_controller_set_property (GObject * object, guint property_id, const GValue * value, GParamSpec * pspec){ GstController *self = GST_CONTROLLER (object); switch (property_id) { case PROP_CONTROL_RATE:{ self->priv->control_rate = g_value_get_uint64 (value); } break; default:{ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } break; }}static void_gst_controller_dispose (GObject * object){ GstController *self = GST_CONTROLLER (object); if (self->object != NULL) { g_mutex_lock (self->lock); /* free list of properties */ if (self->properties) { GList *node; for (node = self->properties; node; node = g_list_next (node)) { GstControlledProperty *prop = node->data; g_signal_handler_disconnect (self->object, prop->notify_handler_id); gst_controlled_property_free (prop); } g_list_free (self->properties); self->properties = NULL; } /* remove controller from object's qdata list */ g_object_set_qdata (self->object, __gst_controller_key, NULL); g_object_unref (self->object); self->object = NULL; g_mutex_unlock (self->lock); } if (G_OBJECT_CLASS (parent_class)->dispose) (G_OBJECT_CLASS (parent_class)->dispose) (object);}static void_gst_controller_finalize (GObject * object){ GstController *self = GST_CONTROLLER (object); g_mutex_free (self->lock); if (G_OBJECT_CLASS (parent_class)->finalize) (G_OBJECT_CLASS (parent_class)->finalize) (object);}static void_gst_controller_init (GTypeInstance * instance, gpointer g_class){ GstController *self = GST_CONTROLLER (instance); self->lock = g_mutex_new (); self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GST_TYPE_CONTROLLER, GstControllerPrivate); self->priv->last_sync = GST_CLOCK_TIME_NONE; self->priv->control_rate = 100 * GST_MSECOND;}static void_gst_controller_class_init (GstControllerClass * klass){ GObjectClass *gobject_class = G_OBJECT_CLASS (klass); parent_class = g_type_class_peek_parent (klass); g_type_class_add_private (klass, sizeof (GstControllerPrivate)); gobject_class->set_property = _gst_controller_set_property; gobject_class->get_property = _gst_controller_get_property; gobject_class->dispose = _gst_controller_dispose; gobject_class->finalize = _gst_controller_finalize; __gst_controller_key = g_quark_from_string ("gst::controller"); /* register properties */ g_object_class_install_property (gobject_class, PROP_CONTROL_RATE, g_param_spec_uint64 ("control-rate", "control rate", "Controlled properties will be updated at least every control-rate nanoseconds", 1, G_MAXUINT, 100 * GST_MSECOND, G_PARAM_READWRITE)); /* register signals */ /* set defaults for overridable methods */}GTypegst_controller_get_type (void){ static GType type = 0; if (type == 0) { static const GTypeInfo info = { sizeof (GstControllerClass), NULL, /* base_init */ NULL, /* base_finalize */ (GClassInitFunc) _gst_controller_class_init, /* class_init */ NULL, /* class_finalize */ NULL, /* class_data */ sizeof (GstController), 0, /* n_preallocs */ (GInstanceInitFunc) _gst_controller_init, /* instance_init */ NULL /* value_table */ }; type = g_type_register_static (G_TYPE_OBJECT, "GstController", &info, 0); } return type;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -