2 * Copyright (C) 2001 Steve Baker <stevebaker_org@yahoo.co.uk>
4 * gstdparammanager.c: Dynamic Parameter group functionality
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
22 #include "dparammanager.h"
23 #include <gst/gstelement.h>
24 #include <gst/gstinfo.h>
26 static GHashTable *_element_registry = NULL;
27 static gboolean _gst_dpman_init_done = FALSE;
34 static void gst_dpman_class_init (GstDParamManagerClass *klass);
35 static void gst_dpman_init (GstDParamManager *dpman);
36 static void gst_dpman_dispose (GObject *object);
37 static GstDParamWrapper* gst_dpman_new_wrapper(GstDParamManager *dpman, GParamSpec *param_spec, gchar *unit_name, GstDPMUpdateMethod update_method);
38 static GstDParamWrapper* gst_dpman_get_wrapper(GstDParamManager *dpman, gchar *dparam_name);
39 static void gst_dpman_state_change (GstElement *element, gint old_state, gint new_state, GstDParamManager *dpman);
40 static gboolean gst_dpman_preprocess_synchronous(GstDParamManager *dpman, guint frames, gint64 timestamp);
41 static gboolean gst_dpman_preprocess_asynchronous(GstDParamManager *dpman, guint frames, gint64 timestamp);
42 static gboolean gst_dpman_process_asynchronous(GstDParamManager *dpman, guint frame_count);
43 static gboolean gst_dpman_preprocess_noop(GstDParamManager *dpman, guint frames, gint64 timestamp);
44 static gboolean gst_dpman_process_noop(GstDParamManager *dpman, guint frame_count);
45 static void gst_dpman_setup_synchronous(GstDParamManager *dpman);
46 static void gst_dpman_setup_asynchronous(GstDParamManager *dpman);
47 static void gst_dpman_setup_disabled(GstDParamManager *dpman);
48 static void gst_dpman_teardown_synchronous(GstDParamManager *dpman);
49 static void gst_dpman_teardown_asynchronous(GstDParamManager *dpman);
50 static void gst_dpman_teardown_disabled(GstDParamManager *dpman);
52 static GObjectClass *parent_class;
53 static guint gst_dpman_signals[LAST_SIGNAL] = { 0 };
56 _gst_dpman_initialize()
58 if (_gst_dpman_init_done) return;
60 _gst_dpman_init_done = TRUE;
61 _element_registry = g_hash_table_new(NULL,NULL);
65 gst_dpman_get_type (void)
67 static GType dpman_type = 0;
70 static const GTypeInfo dpman_info = {
71 sizeof(GstDParamManagerClass),
74 (GClassInitFunc)gst_dpman_class_init,
77 sizeof(GstDParamManager),
79 (GInstanceInitFunc)gst_dpman_init,
81 dpman_type = g_type_register_static(GST_TYPE_OBJECT, "GstDParamManager", &dpman_info, 0);
87 gst_dpman_class_init (GstDParamManagerClass *klass)
89 GstObjectClass *gstobject_class;
90 GObjectClass *gobject_class;
92 parent_class = g_type_class_peek_parent (klass);
94 gstobject_class = (GstObjectClass*) klass;
95 gobject_class = (GObjectClass*) klass;
96 gobject_class->dispose = gst_dpman_dispose;
98 klass->modes = g_hash_table_new(g_str_hash,g_str_equal);
100 gst_dpman_register_mode (klass, "synchronous",
101 gst_dpman_preprocess_synchronous, gst_dpman_process_noop,
102 gst_dpman_setup_synchronous, gst_dpman_teardown_synchronous);
103 gst_dpman_register_mode (klass, "asynchronous",
104 gst_dpman_preprocess_asynchronous, gst_dpman_process_asynchronous,
105 gst_dpman_setup_asynchronous, gst_dpman_teardown_asynchronous);
106 gst_dpman_register_mode (klass, "disabled",
107 gst_dpman_preprocess_noop, gst_dpman_process_noop,
108 gst_dpman_setup_disabled, gst_dpman_teardown_disabled);
111 gst_dpman_signals[NEW_REQUIRED_DPARAM] =
112 g_signal_new ("new_required_dparam", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
113 G_STRUCT_OFFSET (GstDParamManagerClass, new_required_dparam), NULL, NULL,
114 gst_marshal_VOID__STRING, G_TYPE_NONE, 1,
120 gst_dpman_init (GstDParamManager *dpman)
122 GST_DPMAN_DPARAMS(dpman) = g_hash_table_new(g_str_hash,g_str_equal);
123 GST_DPMAN_DPARAMS_LIST(dpman) = NULL;
124 GST_DPMAN_NAME(dpman) = NULL;
125 GST_DPMAN_PARENT(dpman) = NULL;
126 GST_DPMAN_MODE_NAME(dpman) = NULL;
127 GST_DPMAN_MODE(dpman) = NULL;
128 GST_DPMAN_RATE(dpman) = 0;
133 * @name: name of the GstDParamManager instance
134 * @parent: element which created this instance
136 * Returns: a new instance of GstDParamManager
139 gst_dpman_new (gchar *name, GstElement *parent)
141 GstDParamManager *dpman;
143 g_return_val_if_fail (name != NULL, NULL);
145 dpman = g_object_new (gst_dpman_get_type (), NULL);
146 gst_object_set_name (GST_OBJECT (dpman), name);
147 gst_dpman_set_parent(dpman, parent);
149 gst_dpman_set_mode(dpman, "disabled");
156 gst_dpman_dispose (GObject *object)
158 /* GstDParamManager *dpman = GST_DPMAN(object); */
160 G_OBJECT_CLASS (parent_class)->dispose (object);
164 * gst_dpman_add_required_dparam_callback:
165 * @dpman: GstDParamManager instance
166 * @update_func: callback to update the element with the new value
167 * @update_data: will be included in the call to update_func
169 * Returns: true if it was successfully added
172 gst_dpman_add_required_dparam_callback (GstDParamManager *dpman,
173 GParamSpec *param_spec,
175 GstDPMUpdateFunction update_func,
176 gpointer update_data)
178 GstDParamWrapper* dpwrap;
180 g_return_val_if_fail (dpman != NULL, FALSE);
181 g_return_val_if_fail (GST_IS_DPMAN (dpman), FALSE);
182 g_return_val_if_fail (update_func != NULL, FALSE);
184 dpwrap = gst_dpman_new_wrapper(dpman, param_spec, unit_name, GST_DPMAN_CALLBACK);
186 g_return_val_if_fail (dpwrap != NULL, FALSE);
188 GST_DEBUG(GST_CAT_PARAMS,"adding required callback dparam '%s'", g_param_spec_get_name(param_spec));
190 dpwrap->update_func = update_func;
191 dpwrap->update_data = update_data;
193 g_signal_emit (G_OBJECT (dpman), gst_dpman_signals[NEW_REQUIRED_DPARAM], 0, g_param_spec_get_name(param_spec));
199 * gst_dpman_add_required_dparam_direct:
200 * @dpman: GstDParamManager instance
201 * @update_data: pointer to the member to be updated
203 * Returns: true if it was successfully added
206 gst_dpman_add_required_dparam_direct (GstDParamManager *dpman,
207 GParamSpec *param_spec,
209 gpointer update_data)
211 GstDParamWrapper* dpwrap;
213 g_return_val_if_fail (dpman != NULL, FALSE);
214 g_return_val_if_fail (GST_IS_DPMAN (dpman), FALSE);
215 g_return_val_if_fail (update_data != NULL, FALSE);
217 dpwrap = gst_dpman_new_wrapper(dpman, param_spec, unit_name, GST_DPMAN_DIRECT);
219 g_return_val_if_fail (dpwrap != NULL, FALSE);
221 GST_DEBUG(GST_CAT_PARAMS,"adding required direct dparam '%s'", g_param_spec_get_name(param_spec));
223 dpwrap->update_data = update_data;
225 g_signal_emit (G_OBJECT (dpman), gst_dpman_signals[NEW_REQUIRED_DPARAM], 0, g_param_spec_get_name(param_spec));
231 * gst_dpman_add_required_dparam_array:
232 * @dpman: GstDParamManager instance
233 * @dparam_name: a parameter name unique to this GstDParamManager
234 * @update_data: pointer to where the array will be stored
236 * Returns: true if it was successfully added
239 gst_dpman_add_required_dparam_array (GstDParamManager *dpman,
240 GParamSpec *param_spec,
242 gpointer update_data)
244 GstDParamWrapper* dpwrap;
246 g_return_val_if_fail (dpman != NULL, FALSE);
247 g_return_val_if_fail (GST_IS_DPMAN (dpman), FALSE);
248 g_return_val_if_fail (update_data != NULL, FALSE);
250 dpwrap = gst_dpman_new_wrapper(dpman, param_spec, unit_name, GST_DPMAN_ARRAY);
252 g_return_val_if_fail (dpwrap != NULL, FALSE);
254 GST_DEBUG(GST_CAT_PARAMS,"adding required array dparam '%s'", g_param_spec_get_name(param_spec));
256 dpwrap->update_data = update_data;
258 g_signal_emit (G_OBJECT (dpman), gst_dpman_signals[NEW_REQUIRED_DPARAM], 0, g_param_spec_get_name(param_spec));
264 * gst_dpman_remove_required_dparam:
265 * @dpman: GstDParamManager instance
266 * @dparam_name: the name of an existing parameter
270 gst_dpman_remove_required_dparam (GstDParamManager *dpman, gchar *dparam_name)
272 GstDParamWrapper* dpwrap;
274 g_return_if_fail (dpman != NULL);
275 g_return_if_fail (GST_IS_DPMAN (dpman));
276 g_return_if_fail (dparam_name != NULL);
278 dpwrap = gst_dpman_get_wrapper(dpman, dparam_name);
280 g_return_if_fail(dpwrap != NULL);
281 g_return_if_fail(dpwrap->dparam == NULL);
283 GST_DEBUG(GST_CAT_PARAMS, "removing required dparam: %s", dparam_name);
285 g_hash_table_remove(GST_DPMAN_DPARAMS(dpman), dparam_name);
286 GST_DPMAN_DPARAMS_LIST(dpman) = g_list_remove(GST_DPMAN_DPARAMS_LIST(dpman), dpwrap);
288 g_free(dpwrap->value);
293 * gst_dpman_attach_dparam:
294 * @dpman: GstDParamManager instance
295 * @dparam_name: a name previously added with gst_dpman_add_required_dparam
296 * @dparam: GstDParam instance to attach
298 * Returns: true if it was successfully attached
301 gst_dpman_attach_dparam (GstDParamManager *dpman, gchar *dparam_name, GstDParam *dparam)
303 GstDParamWrapper* dpwrap;
305 g_return_val_if_fail (dpman != NULL, FALSE);
306 g_return_val_if_fail (GST_IS_DPMAN (dpman), FALSE);
307 g_return_val_if_fail (dparam_name != NULL, FALSE);
308 g_return_val_if_fail (dparam != NULL, FALSE);
309 g_return_val_if_fail (GST_IS_DPARAM (dparam), FALSE);
310 g_return_val_if_fail (dparam != NULL, FALSE);
312 dpwrap = gst_dpman_get_wrapper(dpman, dparam_name);
314 g_return_val_if_fail(dpwrap != NULL, FALSE);
315 g_return_val_if_fail(dpwrap->value != NULL, FALSE);
317 dpwrap->dparam = dparam;
318 gst_dparam_attach(dparam, dpman, dpwrap->param_spec, dpwrap->unit_name);
324 * gst_dpman_detach_dparam:
325 * @dpman: GstDParamManager instance
326 * @dparam_name: the name of a parameter with a previously attached GstDParam
330 gst_dpman_detach_dparam (GstDParamManager *dpman, gchar *dparam_name)
332 GstDParamWrapper* dpwrap;
334 g_return_if_fail (dpman != NULL);
335 g_return_if_fail (GST_IS_DPMAN (dpman));
336 g_return_if_fail (dparam_name != NULL);
338 dpwrap = gst_dpman_get_wrapper(dpman, dparam_name);
340 g_return_if_fail(dpwrap);
342 gst_dparam_detach(dpwrap->dparam);
343 dpwrap->dparam = NULL;
348 * gst_dpman_get_dparam:
349 * @dpman: GstDParamManager instance
350 * @name: the name of an existing dparam instance
352 * Returns: the dparam with the given name - or NULL otherwise
355 gst_dpman_get_dparam (GstDParamManager *dpman, gchar *name)
357 GstDParamWrapper* dpwrap;
359 g_return_val_if_fail (dpman != NULL, NULL);
360 g_return_val_if_fail (GST_IS_DPMAN (dpman), NULL);
361 g_return_val_if_fail (name != NULL, NULL);
363 dpwrap = g_hash_table_lookup(GST_DPMAN_DPARAMS(dpman), name);
364 g_return_val_if_fail (dpwrap != NULL, NULL);
366 return dpwrap->dparam;
370 * gst_dpman_get_dparam_type:
371 * @dpman: GstDParamManager instance
372 * @name: the name of dparam
374 * Returns: the type that this dparam requires/uses
377 gst_dpman_get_dparam_type (GstDParamManager *dpman, gchar *name)
379 GstDParamWrapper* dpwrap;
381 g_return_val_if_fail (dpman != NULL, 0);
382 g_return_val_if_fail (GST_IS_DPMAN (dpman), 0);
383 g_return_val_if_fail (name != NULL, 0);
385 dpwrap = g_hash_table_lookup(GST_DPMAN_DPARAMS(dpman), name);
386 g_return_val_if_fail (dpwrap != NULL, 0);
388 return G_VALUE_TYPE(dpwrap->value);
392 gst_dpman_list_dparam_specs(GstDParamManager *dpman)
394 GstDParamWrapper* dpwrap;
396 GParamSpec** param_specs;
399 g_return_val_if_fail (dpman != NULL, NULL);
400 g_return_val_if_fail (GST_IS_DPMAN (dpman), NULL);
402 dwraps = GST_DPMAN_DPARAMS_LIST(dpman);
404 param_specs = g_new0(GParamSpec*, g_list_length(dwraps) + 1);
407 dpwrap = (GstDParamWrapper*)dwraps->data;
408 param_specs[x++] = dpwrap->param_spec;
409 dwraps = g_list_next(dwraps);
415 gst_dpman_get_param_spec (GstDParamManager *dpman, gchar *dparam_name)
417 GstDParamWrapper* dpwrap;
419 g_return_val_if_fail (dpman != NULL, NULL);
420 g_return_val_if_fail (GST_IS_DPMAN (dpman), NULL);
421 g_return_val_if_fail (dparam_name != NULL, NULL);
423 dpwrap = gst_dpman_get_wrapper(dpman, dparam_name);
424 return dpwrap->param_spec;
428 gst_dpman_set_rate (GstDParamManager *dpman, gint rate)
430 g_return_if_fail (GST_IS_DPMAN (dpman));
431 GST_DPMAN_RATE(dpman) = rate;
435 * gst_dpman_register_mode
436 * @klass: GstDParamManagerClass class instance
437 * @modename: the unique name of the new mode
438 * @preprocessfunc: the function which will be called before each buffer is processed
439 * @processfunc: the function which may be called throughout the processing of a buffer
440 * @setupfunc: the function which initialises the mode when activated
441 * @teardownfunc: the function which frees any resources the mode uses
445 gst_dpman_register_mode (GstDParamManagerClass *klass,
447 GstDPMModePreProcessFunction preprocessfunc,
448 GstDPMModeProcessFunction processfunc,
449 GstDPMModeSetupFunction setupfunc,
450 GstDPMModeTeardownFunction teardownfunc)
454 g_return_if_fail (klass != NULL);
455 g_return_if_fail (modename != NULL);
456 g_return_if_fail (GST_IS_DPMAN_CLASS (klass));
458 mode = g_new0(GstDPMMode,1);
460 mode->preprocessfunc = preprocessfunc;
461 mode->processfunc = processfunc;
462 mode->setupfunc = setupfunc;
463 mode->teardownfunc = teardownfunc;
465 g_hash_table_insert(klass->modes, modename, mode);
466 GST_DEBUG(GST_CAT_PARAMS, "mode '%s' registered", modename);
471 * @dpman: GstDParamManager instance
472 * @modename: the name of the mode to use
474 * Returns: TRUE if the mode was set, FALSE otherwise
477 gst_dpman_set_mode(GstDParamManager *dpman, gchar *modename)
479 GstDPMMode *mode=NULL;
480 GstDParamManagerClass *oclass;
482 g_return_val_if_fail (dpman != NULL, FALSE);
483 g_return_val_if_fail (GST_IS_DPMAN (dpman), FALSE);
484 g_return_val_if_fail (modename != NULL, FALSE);
486 oclass = (GstDParamManagerClass*)(G_OBJECT_GET_CLASS(dpman));
488 mode = g_hash_table_lookup(oclass->modes, modename);
489 g_return_val_if_fail (mode != NULL, FALSE);
491 if (GST_DPMAN_MODE(dpman) == mode) {
492 GST_DEBUG(GST_CAT_PARAMS, "mode %s already set", modename);
496 GST_DEBUG(GST_CAT_PARAMS, "setting mode to %s", modename);
497 if (GST_DPMAN_MODE(dpman) && GST_DPMAN_TEARDOWNFUNC(dpman)){
498 GST_DPMAN_TEARDOWNFUNC(dpman)(dpman);
501 GST_DPMAN_MODE(dpman) = mode;
503 if (GST_DPMAN_SETUPFUNC(dpman)){
504 GST_DPMAN_SETUPFUNC(dpman)(dpman);
511 * gst_dpman_set_parent
512 * @dpman: GstDParamManager instance
513 * @parent: the element that this GstDParamManager belongs to
517 gst_dpman_set_parent (GstDParamManager *dpman, GstElement *parent)
519 g_return_if_fail (dpman != NULL);
520 g_return_if_fail (GST_IS_DPMAN (dpman));
521 g_return_if_fail (parent != NULL);
522 g_return_if_fail (GST_IS_ELEMENT (parent));
524 g_hash_table_insert(_element_registry, parent, dpman);
525 gst_object_set_parent (GST_OBJECT (dpman), GST_OBJECT(parent));
526 g_signal_connect(G_OBJECT(parent), "state_change",
527 G_CALLBACK (gst_dpman_state_change), dpman);
531 * gst_dpman_get_manager
532 * @parent: the element that the desired GstDParamManager belongs to
534 * Returns: the GstDParamManager which belongs to this element or NULL
535 * if it doesn't exist
538 gst_dpman_get_manager (GstElement *parent)
540 GstDParamManager *dpman;
541 g_return_val_if_fail (parent != NULL, NULL);
542 g_return_val_if_fail (GST_IS_ELEMENT (parent), NULL);
544 dpman = (GstDParamManager*)g_hash_table_lookup(_element_registry, parent);
549 * gst_dpman_bypass_dparam:
550 * @dpman: GstDParamManager instance
551 * @dparam_name: the name of dparam
553 * If a dparam is attached to this dparam_name, it will be detached
554 * and a warning will be issued. This should be called in the _set_property
555 * function of an element if the value it changes is also changed by a dparam.
559 gst_dpman_bypass_dparam(GstDParamManager *dpman, gchar *dparam_name)
561 GstDParamWrapper* dpwrap;
563 g_return_if_fail (dpman != NULL);
564 g_return_if_fail (GST_IS_DPMAN (dpman));
565 g_return_if_fail (dparam_name != NULL);
567 dpwrap = gst_dpman_get_wrapper(dpman, dparam_name);
568 g_return_if_fail (dpwrap != NULL);
570 if (dpwrap->dparam != NULL){
571 g_warning("Bypassing attached dparam '%s'. It will be detached", dparam_name);
572 gst_dpman_detach_dparam(dpman, dparam_name);
576 static GstDParamWrapper*
577 gst_dpman_get_wrapper(GstDParamManager *dpman, gchar *dparam_name)
579 g_return_val_if_fail (dpman != NULL, NULL);
580 g_return_val_if_fail (GST_IS_DPMAN (dpman), NULL);
581 g_return_val_if_fail (dparam_name != NULL, NULL);
583 return g_hash_table_lookup(GST_DPMAN_DPARAMS(dpman), dparam_name);
586 static GstDParamWrapper*
587 gst_dpman_new_wrapper(GstDParamManager *dpman,
588 GParamSpec *param_spec,
590 GstDPMUpdateMethod update_method)
592 GstDParamWrapper* dpwrap;
595 g_return_val_if_fail (dpman != NULL, NULL);
596 g_return_val_if_fail (GST_IS_DPMAN (dpman), NULL);
597 g_return_val_if_fail (param_spec != NULL, NULL);
598 g_return_val_if_fail (gst_unitconv_unit_exists(unit_name), NULL);
600 dparam_name = g_strdup(g_param_spec_get_name(param_spec));
601 g_return_val_if_fail(gst_dpman_get_wrapper(dpman, dparam_name) == NULL, NULL);
603 dpwrap = g_new0(GstDParamWrapper,1);
604 dpwrap->update_method = update_method;
605 dpwrap->value = g_new0(GValue,1);
606 g_value_init(dpwrap->value, G_PARAM_SPEC_VALUE_TYPE(param_spec));
607 dpwrap->param_spec = param_spec;
608 dpwrap->unit_name = unit_name;
610 g_hash_table_insert(GST_DPMAN_DPARAMS(dpman), dparam_name, dpwrap);
611 GST_DPMAN_DPARAMS_LIST(dpman) = g_list_append(GST_DPMAN_DPARAMS_LIST(dpman), dpwrap);
618 gst_dpman_state_change (GstElement *element, gint old_state, gint new_state, GstDParamManager *dpman)
622 GstDParamWrapper *dpwrap;
624 g_return_if_fail (dpman != NULL);
625 g_return_if_fail (GST_IS_DPMAN (dpman));
627 if (new_state == GST_STATE_PLAYING){
628 GST_DEBUG(GST_CAT_PARAMS, "initialising params");
631 /* force all params to be updated */
632 dwraps = GST_DPMAN_DPARAMS_LIST(dpman);
634 dpwrap = (GstDParamWrapper*)dwraps->data;
635 dparam = dpwrap->dparam;
638 GST_DPARAM_READY_FOR_UPDATE(dparam) = TRUE;
639 GST_DPARAM_NEXT_UPDATE_TIMESTAMP(dparam) = 0LL;
641 /* some dparams treat the first update after the pipeline starts differently */
642 dpwrap->update_info = GST_DPARAM_UPDATE_FIRST;
643 dwraps = g_list_next(dwraps);
649 gst_dpman_inline_direct_update(GValue *value, gpointer data){
650 switch (G_VALUE_TYPE(value)){
652 *(gint*)data = g_value_get_int(value);
655 *(gint64*)data = g_value_get_int64(value);
658 *(gfloat*)data = g_value_get_float(value);
666 gst_dpman_preprocess_synchronous(GstDParamManager *dpman, guint frames, gint64 timestamp)
669 GstDParamWrapper *dpwrap;
671 g_return_val_if_fail (GST_IS_DPMAN (dpman), FALSE);
673 /* this basically means don't call GST_DPMAN_PREPROCESS at all */
674 dpman->next_update_frame = frames;
675 dpman->frames_to_process = frames;
677 /* now check whether any dparams are ready for an update */
678 dwraps = GST_DPMAN_DPARAMS_LIST(dpman);
680 dpwrap = (GstDParamWrapper*)dwraps->data;
682 if (dpwrap->dparam &&
683 GST_DPARAM_READY_FOR_UPDATE(dpwrap->dparam) &&
684 GST_DPARAM_NEXT_UPDATE_TIMESTAMP(dpwrap->dparam) <= timestamp){
686 switch (dpwrap->update_method) {
688 /* direct method - set the value directly in the struct of the element */
689 case GST_DPMAN_DIRECT:
690 GST_DPARAM_DO_UPDATE(dpwrap->dparam, timestamp, dpwrap->value, dpwrap->update_info);
691 GST_DEBUG(GST_CAT_PARAMS, "doing direct update");
693 gst_dpman_inline_direct_update(dpwrap->value, dpwrap->update_data);
696 /* callback method - call the element's callback so it can do what it likes */
697 case GST_DPMAN_CALLBACK:
698 GST_DPARAM_DO_UPDATE(dpwrap->dparam, timestamp, dpwrap->value, dpwrap->update_info);
699 GST_DEBUG(GST_CAT_PARAMS, "doing callback update");
701 GST_DPMAN_CALLBACK_UPDATE(dpwrap, dpwrap->value);
704 case GST_DPMAN_ARRAY:
705 /* FIXME do array method checking here */
711 if (dpwrap->update_info == GST_DPARAM_UPDATE_FIRST){
712 /* it is not the first update anymore */
713 dpwrap->update_info = GST_DPARAM_UPDATE_NORMAL;
716 dwraps = g_list_next(dwraps);
724 gst_dpman_dpwrap_compare (const GstDParamWrapper *a, const GstDParamWrapper *b)
726 if (a->next_update_frame > b->next_update_frame) return 1;
727 return (a->next_update_frame < b->next_update_frame) ? -1 : 0;
731 gst_dpman_preprocess_asynchronous(GstDParamManager *dpman, guint frames, gint64 timestamp)
734 GstDParamWrapper *dpwrap;
736 gboolean updates_pending;
738 g_return_val_if_fail (GST_IS_DPMAN (dpman), FALSE);
741 if (GST_DPMAN_RATE(dpman) == 0){
742 g_warning("The element hasn't given GstDParamManager a frame rate");
745 dpman->rate_ratio = (guint)(1000000000LL / (gint64)GST_DPMAN_RATE(dpman));
747 dpman->time_buffer_starts = timestamp;
748 dpman->time_buffer_ends = timestamp + ((gint64)frames * (gint64)dpman->rate_ratio);
749 dpman->num_frames = frames;
751 updates_pending = FALSE;
753 /* now check whether any dparams are ready for an update */
754 dwraps = GST_DPMAN_DPARAMS_LIST(dpman);
756 dpwrap = (GstDParamWrapper*)dwraps->data;
758 dpwrap->next_update_frame = frames;
760 if (dpwrap->dparam &&
761 GST_DPARAM_READY_FOR_UPDATE(dpwrap->dparam)){
763 current_time = GST_DPARAM_NEXT_UPDATE_TIMESTAMP(dpwrap->dparam);
764 if (current_time > dpman->time_buffer_ends){
765 /* not due for an update in this buffer */
766 dwraps = g_list_next(dwraps);
769 if (current_time < timestamp){
770 current_time = timestamp;
773 if (current_time == timestamp){
774 /* we are overdue for an update. lets do it now */
776 GST_DPARAM_DO_UPDATE(dpwrap->dparam, current_time, dpwrap->value, dpwrap->update_info);
778 if (dpwrap->update_info == GST_DPARAM_UPDATE_FIRST){
779 /* it is not the first update anymore */
780 dpwrap->update_info = GST_DPARAM_UPDATE_NORMAL;
783 switch (dpwrap->update_method) {
785 /* direct method - set the value directly in the struct of the element */
786 case GST_DPMAN_DIRECT:
787 GST_DEBUG(GST_CAT_PARAMS, "doing direct update");
788 gst_dpman_inline_direct_update(dpwrap->value, dpwrap->update_data);
791 /* callback method - call the element's callback so it can do what it likes */
792 case GST_DPMAN_CALLBACK:
793 GST_DEBUG(GST_CAT_PARAMS, "doing callback update");
794 GST_DPMAN_CALLBACK_UPDATE(dpwrap, dpwrap->value);
800 current_time = GST_DPARAM_NEXT_UPDATE_TIMESTAMP(dpwrap->dparam);
802 if (!GST_DPARAM_READY_FOR_UPDATE(dpwrap->dparam) ||
803 current_time > dpman->time_buffer_ends){
804 /* not due for an update in this buffer */
805 dwraps = g_list_next(dwraps);
810 dpwrap->next_update_frame = (guint)(current_time - timestamp) / dpman->rate_ratio;
811 updates_pending = TRUE;
813 GST_DEBUG(GST_CAT_PARAMS, "timestamp start: %"
814 G_GINT64_FORMAT " end: %"
815 G_GINT64_FORMAT " current: %"
817 timestamp, dpman->time_buffer_ends, current_time);
820 dwraps = g_list_next(dwraps);
822 if (updates_pending){
823 GST_DPMAN_DPARAMS_LIST(dpman) = g_list_sort(GST_DPMAN_DPARAMS_LIST(dpman), (GCompareFunc)gst_dpman_dpwrap_compare);
824 dwraps = GST_DPMAN_DPARAMS_LIST(dpman);
825 dpwrap = (GstDParamWrapper*)dwraps->data;
827 dpman->next_update_frame = dpwrap->next_update_frame;
828 dpman->frames_to_process = dpman->next_update_frame;
830 GST_DEBUG(GST_CAT_PARAMS, "next update frame %u, frames to process %u", dpman->next_update_frame, dpman->frames_to_process);
834 dpman->next_update_frame = frames;
835 dpman->frames_to_process = frames;
840 gst_dpman_process_asynchronous(GstDParamManager *dpman, guint frame_count)
842 GstDParamWrapper *dpwrap;
845 gboolean needs_resort = FALSE;
847 dwraps = GST_DPMAN_DPARAMS_LIST(dpman);
848 dpwrap = (GstDParamWrapper*)dwraps->data;
850 GST_DEBUG(GST_CAT_PARAMS, "in gst_dpman_process_asynchronous");
852 if (frame_count >= dpman->num_frames){
853 g_warning("there is no more buffer to process");
854 dpman->next_update_frame = dpman->num_frames;
855 dpman->frames_to_process = 0;
859 if (frame_count != dpwrap->next_update_frame){
860 g_warning("frame count %u does not match update frame %u",
861 frame_count, dpwrap->next_update_frame);
866 current_time = GST_DPARAM_NEXT_UPDATE_TIMESTAMP(dpwrap->dparam);
867 GST_DPARAM_DO_UPDATE(dpwrap->dparam, current_time, dpwrap->value, dpwrap->update_info);
868 switch (dpwrap->update_method) {
870 /* direct method - set the value directly in the struct of the element */
871 case GST_DPMAN_DIRECT:
872 GST_DEBUG(GST_CAT_PARAMS, "doing direct update");
873 gst_dpman_inline_direct_update(dpwrap->value, dpwrap->update_data);
876 /* callback method - call the element's callback so it can do what it likes */
877 case GST_DPMAN_CALLBACK:
878 GST_DEBUG(GST_CAT_PARAMS, "doing callback update");
879 GST_DPMAN_CALLBACK_UPDATE(dpwrap, dpwrap->value);
885 dpwrap->next_update_frame = dpman->num_frames;
888 if(GST_DPARAM_READY_FOR_UPDATE(dpwrap->dparam)){
889 current_time = GST_DPARAM_NEXT_UPDATE_TIMESTAMP(dpwrap->dparam);
890 if (current_time <= dpman->time_buffer_ends){
891 dpwrap->next_update_frame = (guint)(current_time - dpman->time_buffer_starts) / dpman->rate_ratio;
895 if ((dwraps = g_list_next(dwraps))){
896 dpwrap = (GstDParamWrapper*)dwraps->data;
897 if (frame_count == dpwrap->next_update_frame){
904 if (needs_resort && g_list_length(GST_DPMAN_DPARAMS_LIST(dpman)) > 1){
905 GST_DPMAN_DPARAMS_LIST(dpman) = g_list_sort(GST_DPMAN_DPARAMS_LIST(dpman), (GCompareFunc)gst_dpman_dpwrap_compare);
908 dwraps = GST_DPMAN_DPARAMS_LIST(dpman);
909 dpwrap = (GstDParamWrapper*)dwraps->data;
911 if (dpwrap->next_update_frame == dpman->num_frames){
912 dpman->next_update_frame = dpman->num_frames;
913 dpman->frames_to_process = dpman->num_frames - frame_count;
914 GST_DEBUG(GST_CAT_PARAMS, "no more updates, frames to process %u", dpman->frames_to_process);
917 dpman->next_update_frame = dpwrap->next_update_frame;
918 dpman->frames_to_process = dpman->next_update_frame - frame_count;
919 GST_DEBUG(GST_CAT_PARAMS, "next update frame %u, frames to process %u", dpman->next_update_frame, dpman->frames_to_process);
926 gst_dpman_preprocess_noop(GstDParamManager *dpman, guint frames, gint64 timestamp)
928 dpman->next_update_frame = frames;
929 dpman->frames_to_process = frames;
934 gst_dpman_process_noop(GstDParamManager *dpman, guint frame_count)
936 g_warning("gst_dpman_process_noop should never be called - something might be wrong with your processing loop");
941 gst_dpman_setup_synchronous(GstDParamManager *dpman){
942 g_return_if_fail (GST_IS_DPMAN (dpman));
947 gst_dpman_setup_asynchronous(GstDParamManager *dpman){
948 g_return_if_fail (GST_IS_DPMAN (dpman));
953 gst_dpman_setup_disabled(GstDParamManager *dpman){
954 g_return_if_fail (GST_IS_DPMAN (dpman));
959 gst_dpman_teardown_synchronous(GstDParamManager *dpman){
960 g_return_if_fail (GST_IS_DPMAN (dpman));
965 gst_dpman_teardown_asynchronous(GstDParamManager *dpman){
966 g_return_if_fail (GST_IS_DPMAN (dpman));
971 gst_dpman_teardown_disabled(GstDParamManager *dpman){
972 g_return_if_fail (GST_IS_DPMAN (dpman));