gstreamer_core/libs/gst/controller/gstinterpolationcontrolsource.c
branchRCL_3
changeset 30 7e817e7e631c
parent 29 567bb019e3e3
equal deleted inserted replaced
29:567bb019e3e3 30:7e817e7e631c
     1 /* GStreamer
     1 /* GStreamer
     2  *
     2  *
     3  * Copyright (C) 2007,2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>
     3  * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
     4  *
     4  *
     5  * gstinterpolationcontrolsource.c: Control source that provides several
     5  * gstinterpolationcontrolsource.c: Control source that provides several
     6  *                                  interpolation methods
     6  *                                  interpolation methods
     7  *
     7  *
     8  * This library is free software; you can redistribute it and/or
     8  * This library is free software; you can redistribute it and/or
    41 #include <gst/gst.h>
    41 #include <gst/gst.h>
    42 
    42 
    43 #include "gstcontrolsource.h"
    43 #include "gstcontrolsource.h"
    44 #include "gstinterpolationcontrolsource.h"
    44 #include "gstinterpolationcontrolsource.h"
    45 #include "gstinterpolationcontrolsourceprivate.h"
    45 #include "gstinterpolationcontrolsourceprivate.h"
       
    46 
    46 #ifdef __SYMBIAN32__
    47 #ifdef __SYMBIAN32__
    47 #include <glib_global.h>
    48 #include <glib_global.h>
    48 #include <gobject_global.h>
    49 #include <gobject_global.h>
    49 #endif
    50 #endif
    50 #define GST_CAT_DEFAULT controller_debug
    51 extern GstInterpolateMethod *interpolation_methods[];
    51 GST_DEBUG_CATEGORY_EXTERN (GST_CAT_DEFAULT);
    52 extern guint num_interpolation_methods;
    52 
    53 
    53 static void gst_interpolation_control_source_init (GstInterpolationControlSource
    54 static void gst_interpolation_control_source_init (GstInterpolationControlSource
    54     * self);
    55     * self);
    55 static void
    56 static void
    56 gst_interpolation_control_source_class_init (GstInterpolationControlSourceClass
    57 gst_interpolation_control_source_class_init (GstInterpolationControlSourceClass
    72 gst_control_point_free (GstControlPoint * cp)
    73 gst_control_point_free (GstControlPoint * cp)
    73 {
    74 {
    74   g_return_if_fail (cp);
    75   g_return_if_fail (cp);
    75 
    76 
    76   g_value_unset (&cp->value);
    77   g_value_unset (&cp->value);
    77   g_slice_free (GstControlPoint, cp);
    78   g_free (cp);
    78 }
    79 }
    79 
    80 
    80 static void
    81 static void
    81 gst_interpolation_control_source_reset (GstInterpolationControlSource * self)
    82 gst_interpolation_control_source_reset (GstInterpolationControlSource * self)
    82 {
    83 {
    93     g_value_unset (&self->priv->minimum_value);
    94     g_value_unset (&self->priv->minimum_value);
    94   if (G_IS_VALUE (&self->priv->maximum_value))
    95   if (G_IS_VALUE (&self->priv->maximum_value))
    95     g_value_unset (&self->priv->maximum_value);
    96     g_value_unset (&self->priv->maximum_value);
    96 
    97 
    97   if (self->priv->values) {
    98   if (self->priv->values) {
    98     g_sequence_free (self->priv->values);
    99     g_list_foreach (self->priv->values, (GFunc) gst_control_point_free, NULL);
       
   100     g_list_free (self->priv->values);
    99     self->priv->values = NULL;
   101     self->priv->values = NULL;
   100   }
   102   }
   101 
   103 
   102   self->priv->nvalues = 0;
   104   self->priv->nvalues = 0;
       
   105   self->priv->last_requested_value = NULL;
   103   self->priv->valid_cache = FALSE;
   106   self->priv->valid_cache = FALSE;
   104 }
   107 }
   105 
   108 
   106 /**
   109 /**
   107  * gst_interpolation_control_source_new:
   110  * gst_interpolation_control_source_new:
   130  * <note><para>User interpolation is not yet available and quadratic interpolation
   133  * <note><para>User interpolation is not yet available and quadratic interpolation
   131  * is deprecated and maps to cubic interpolation.</para></note>
   134  * is deprecated and maps to cubic interpolation.</para></note>
   132  *
   135  *
   133  * Returns: %TRUE if the interpolation mode could be set, %FALSE otherwise
   136  * Returns: %TRUE if the interpolation mode could be set, %FALSE otherwise
   134  */
   137  */
   135 /* *INDENT-OFF* */
       
   136 #ifdef __SYMBIAN32__
   138 #ifdef __SYMBIAN32__
   137 EXPORT_C
   139 EXPORT_C
   138 #endif
   140 #endif
   139 
   141 
   140 gboolean
   142 gboolean
   141 gst_interpolation_control_source_set_interpolation_mode (
   143     gst_interpolation_control_source_set_interpolation_mode
   142     GstInterpolationControlSource * self, GstInterpolateMode mode)
   144     (GstInterpolationControlSource * self, GstInterpolateMode mode) {
   143 /* *INDENT-ON* */
       
   144 {
       
   145   gboolean ret = TRUE;
   145   gboolean ret = TRUE;
   146   GstControlSource *csource = GST_CONTROL_SOURCE (self);
   146   GstControlSource *csource = GST_CONTROL_SOURCE (self);
   147 
   147 
   148   if (mode >= priv_gst_num_interpolation_methods
   148   if (mode >= num_interpolation_methods || interpolation_methods[mode] == NULL) {
   149       || priv_gst_interpolation_methods[mode] == NULL) {
       
   150     GST_WARNING ("interpolation mode %d invalid or not implemented yet", mode);
   149     GST_WARNING ("interpolation mode %d invalid or not implemented yet", mode);
   151     return FALSE;
   150     return FALSE;
   152   }
   151   }
   153 
   152 
   154   if (mode == GST_INTERPOLATE_QUADRATIC) {
   153   if (mode == GST_INTERPOLATE_QUADRATIC) {
   162   }
   161   }
   163 
   162 
   164   g_mutex_lock (self->lock);
   163   g_mutex_lock (self->lock);
   165   switch (self->priv->base) {
   164   switch (self->priv->base) {
   166     case G_TYPE_INT:
   165     case G_TYPE_INT:
   167       csource->get_value = priv_gst_interpolation_methods[mode]->get_int;
   166       csource->get_value = interpolation_methods[mode]->get_int;
   168       csource->get_value_array =
   167       csource->get_value_array =
   169           priv_gst_interpolation_methods[mode]->get_int_value_array;
   168           interpolation_methods[mode]->get_int_value_array;
   170       break;
   169       break;
   171     case G_TYPE_UINT:{
   170     case G_TYPE_UINT:{
   172       csource->get_value = priv_gst_interpolation_methods[mode]->get_uint;
   171       csource->get_value = interpolation_methods[mode]->get_uint;
   173       csource->get_value_array =
   172       csource->get_value_array =
   174           priv_gst_interpolation_methods[mode]->get_uint_value_array;
   173           interpolation_methods[mode]->get_uint_value_array;
   175       break;
   174       break;
   176     }
   175     }
   177     case G_TYPE_LONG:{
   176     case G_TYPE_LONG:{
   178       csource->get_value = priv_gst_interpolation_methods[mode]->get_long;
   177       csource->get_value = interpolation_methods[mode]->get_long;
   179       csource->get_value_array =
   178       csource->get_value_array =
   180           priv_gst_interpolation_methods[mode]->get_long_value_array;
   179           interpolation_methods[mode]->get_long_value_array;
   181       break;
   180       break;
   182     }
   181     }
   183     case G_TYPE_ULONG:{
   182     case G_TYPE_ULONG:{
   184       csource->get_value = priv_gst_interpolation_methods[mode]->get_ulong;
   183       csource->get_value = interpolation_methods[mode]->get_ulong;
   185       csource->get_value_array =
   184       csource->get_value_array =
   186           priv_gst_interpolation_methods[mode]->get_ulong_value_array;
   185           interpolation_methods[mode]->get_ulong_value_array;
   187       break;
   186       break;
   188     }
   187     }
   189     case G_TYPE_INT64:{
   188     case G_TYPE_INT64:{
   190       csource->get_value = priv_gst_interpolation_methods[mode]->get_int64;
   189       csource->get_value = interpolation_methods[mode]->get_int64;
   191       csource->get_value_array =
   190       csource->get_value_array =
   192           priv_gst_interpolation_methods[mode]->get_int64_value_array;
   191           interpolation_methods[mode]->get_int64_value_array;
   193       break;
   192       break;
   194     }
   193     }
   195     case G_TYPE_UINT64:{
   194     case G_TYPE_UINT64:{
   196       csource->get_value = priv_gst_interpolation_methods[mode]->get_uint64;
   195       csource->get_value = interpolation_methods[mode]->get_uint64;
   197       csource->get_value_array =
   196       csource->get_value_array =
   198           priv_gst_interpolation_methods[mode]->get_uint64_value_array;
   197           interpolation_methods[mode]->get_uint64_value_array;
   199       break;
   198       break;
   200     }
   199     }
   201     case G_TYPE_FLOAT:{
   200     case G_TYPE_FLOAT:{
   202       csource->get_value = priv_gst_interpolation_methods[mode]->get_float;
   201       csource->get_value = interpolation_methods[mode]->get_float;
   203       csource->get_value_array =
   202       csource->get_value_array =
   204           priv_gst_interpolation_methods[mode]->get_float_value_array;
   203           interpolation_methods[mode]->get_float_value_array;
   205       break;
   204       break;
   206     }
   205     }
   207     case G_TYPE_DOUBLE:{
   206     case G_TYPE_DOUBLE:{
   208       csource->get_value = priv_gst_interpolation_methods[mode]->get_double;
   207       csource->get_value = interpolation_methods[mode]->get_double;
   209       csource->get_value_array =
   208       csource->get_value_array =
   210           priv_gst_interpolation_methods[mode]->get_double_value_array;
   209           interpolation_methods[mode]->get_double_value_array;
   211       break;
   210       break;
   212     }
   211     }
   213     case G_TYPE_BOOLEAN:{
   212     case G_TYPE_BOOLEAN:{
   214       csource->get_value = priv_gst_interpolation_methods[mode]->get_boolean;
   213       csource->get_value = interpolation_methods[mode]->get_boolean;
   215       csource->get_value_array =
   214       csource->get_value_array =
   216           priv_gst_interpolation_methods[mode]->get_boolean_value_array;
   215           interpolation_methods[mode]->get_boolean_value_array;
   217       break;
   216       break;
   218     }
   217     }
   219     case G_TYPE_ENUM:{
   218     case G_TYPE_ENUM:{
   220       csource->get_value = priv_gst_interpolation_methods[mode]->get_enum;
   219       csource->get_value = interpolation_methods[mode]->get_enum;
   221       csource->get_value_array =
   220       csource->get_value_array =
   222           priv_gst_interpolation_methods[mode]->get_enum_value_array;
   221           interpolation_methods[mode]->get_enum_value_array;
   223       break;
   222       break;
   224     }
   223     }
   225     case G_TYPE_STRING:{
   224     case G_TYPE_STRING:{
   226       csource->get_value = priv_gst_interpolation_methods[mode]->get_string;
   225       csource->get_value = interpolation_methods[mode]->get_string;
   227       csource->get_value_array =
   226       csource->get_value_array =
   228           priv_gst_interpolation_methods[mode]->get_string_value_array;
   227           interpolation_methods[mode]->get_string_value_array;
   229       break;
   228       break;
   230     }
   229     }
   231     default:
   230     default:
   232       ret = FALSE;
   231       ret = FALSE;
   233       break;
   232       break;
   428   GstClockTime ct2 = *(GstClockTime *) p2;
   427   GstClockTime ct2 = *(GstClockTime *) p2;
   429 
   428 
   430   return ((ct1 < ct2) ? -1 : ((ct1 == ct2) ? 0 : 1));
   429   return ((ct1 < ct2) ? -1 : ((ct1 == ct2) ? 0 : 1));
   431 }
   430 }
   432 
   431 
   433 static GstControlPoint *
       
   434 _make_new_cp (GstInterpolationControlSource * self, GstClockTime timestamp,
       
   435     GValue * value)
       
   436 {
       
   437   GstControlPoint *cp;
       
   438 
       
   439   /* create a new GstControlPoint */
       
   440   cp = g_slice_new0 (GstControlPoint);
       
   441   cp->timestamp = timestamp;
       
   442   g_value_init (&cp->value, self->priv->type);
       
   443   g_value_copy (value, &cp->value);
       
   444 
       
   445   return cp;
       
   446 }
       
   447 
       
   448 static void
   432 static void
   449 gst_interpolation_control_source_set_internal (GstInterpolationControlSource *
   433 gst_interpolation_control_source_set_internal (GstInterpolationControlSource *
   450     self, GstClockTime timestamp, GValue * value)
   434     self, GstClockTime timestamp, GValue * value)
   451 {
   435 {
   452   GSequenceIter *iter;
   436   GstControlPoint *cp;
       
   437   GList *node;
   453 
   438 
   454   /* check if a control point for the timestamp already exists */
   439   /* check if a control point for the timestamp already exists */
   455 
   440   if ((node = g_list_find_custom (self->priv->values, &timestamp,
   456   /* iter contains the iter right *after* timestamp */
   441               gst_control_point_find))) {
   457   if (G_LIKELY (self->priv->values)) {
   442     cp = node->data;
   458     iter =
   443     g_value_reset (&cp->value);
   459         g_sequence_search (self->priv->values, &timestamp,
   444     g_value_copy (value, &cp->value);
   460         (GCompareDataFunc) gst_control_point_find, NULL);
       
   461     if (iter) {
       
   462       GSequenceIter *prev = g_sequence_iter_prev (iter);
       
   463       GstControlPoint *cp = g_sequence_get (prev);
       
   464 
       
   465       /* If the timestamp is the same just update the control point value */
       
   466       if (cp->timestamp == timestamp) {
       
   467         /* update control point */
       
   468         g_value_reset (&cp->value);
       
   469         g_value_copy (value, &cp->value);
       
   470         goto done;
       
   471       }
       
   472     }
       
   473   } else {
   445   } else {
       
   446     /* create a new GstControlPoint */
       
   447     cp = g_new0 (GstControlPoint, 1);
       
   448     cp->timestamp = timestamp;
       
   449     g_value_init (&cp->value, self->priv->type);
       
   450     g_value_copy (value, &cp->value);
       
   451     /* and sort it into the prop->values list */
   474     self->priv->values =
   452     self->priv->values =
   475         g_sequence_new ((GDestroyNotify) gst_control_point_free);
   453         g_list_insert_sorted (self->priv->values, cp,
   476   }
   454         gst_control_point_compare);
   477 
   455     self->priv->nvalues++;
   478   /* sort new cp into the prop->values list */
   456   }
   479   g_sequence_insert_sorted (self->priv->values, _make_new_cp (self, timestamp,
       
   480           value), (GCompareDataFunc) gst_control_point_compare, NULL);
       
   481   self->priv->nvalues++;
       
   482 
       
   483 done:
       
   484   self->priv->valid_cache = FALSE;
   457   self->priv->valid_cache = FALSE;
   485 }
   458 }
   486 
       
   487 
   459 
   488 /**
   460 /**
   489  * gst_interpolation_control_source_set:
   461  * gst_interpolation_control_source_set:
   490  * @self: the #GstInterpolationControlSource object
   462  * @self: the #GstInterpolationControlSource object
   491  * @timestamp: the time the control-change is scheduled for
   463  * @timestamp: the time the control-change is scheduled for
   575 
   547 
   576 gboolean
   548 gboolean
   577 gst_interpolation_control_source_unset (GstInterpolationControlSource * self,
   549 gst_interpolation_control_source_unset (GstInterpolationControlSource * self,
   578     GstClockTime timestamp)
   550     GstClockTime timestamp)
   579 {
   551 {
   580   GSequenceIter *iter;
   552   GList *node;
   581   gboolean res = FALSE;
   553   gboolean res = FALSE;
   582 
   554 
   583   g_return_val_if_fail (GST_IS_INTERPOLATION_CONTROL_SOURCE (self), FALSE);
   555   g_return_val_if_fail (GST_IS_INTERPOLATION_CONTROL_SOURCE (self), FALSE);
   584   g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
   556   g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
   585 
   557 
   586   g_mutex_lock (self->lock);
   558   g_mutex_lock (self->lock);
   587   /* check if a control point for the timestamp exists */
   559   /* check if a control point for the timestamp exists */
   588   if ((iter =
   560   if ((node = g_list_find_custom (self->priv->values, &timestamp,
   589           g_sequence_search (self->priv->values, &timestamp,
   561               gst_control_point_find))) {
   590               (GCompareDataFunc) gst_control_point_find, NULL))) {
   562     GstControlPoint *cp = node->data;
   591     GstControlPoint *cp;
   563 
   592 
   564     if (cp->timestamp == 0) {
   593     /* Iter contains the iter right after timestamp, i.e.
   565       /* Restore the default node */
   594      * we need to get the previous one and check the timestamp
   566       g_value_reset (&cp->value);
   595      */
   567       g_value_copy (&self->priv->default_value, &cp->value);
   596     iter = g_sequence_iter_prev (iter);
   568     } else {
   597     cp = g_sequence_get (iter);
   569       if (node == self->priv->last_requested_value)
   598     if (cp->timestamp == timestamp) {
   570         self->priv->last_requested_value = NULL;
   599       g_sequence_remove (iter);
   571       gst_control_point_free (node->data);      /* free GstControlPoint */
       
   572       self->priv->values = g_list_delete_link (self->priv->values, node);
   600       self->priv->nvalues--;
   573       self->priv->nvalues--;
   601       self->priv->valid_cache = FALSE;
   574     }
   602       res = TRUE;
   575     self->priv->valid_cache = FALSE;
   603     }
   576     res = TRUE;
   604   }
   577   }
   605   g_mutex_unlock (self->lock);
   578   g_mutex_unlock (self->lock);
   606 
   579 
   607   return res;
   580   return res;
   608 }
   581 }
   624 {
   597 {
   625   g_return_if_fail (GST_IS_INTERPOLATION_CONTROL_SOURCE (self));
   598   g_return_if_fail (GST_IS_INTERPOLATION_CONTROL_SOURCE (self));
   626 
   599 
   627   g_mutex_lock (self->lock);
   600   g_mutex_lock (self->lock);
   628   /* free GstControlPoint structures */
   601   /* free GstControlPoint structures */
   629   if (self->priv->values) {
   602   g_list_foreach (self->priv->values, (GFunc) gst_control_point_free, NULL);
   630     g_sequence_free (self->priv->values);
   603   g_list_free (self->priv->values);
   631     self->priv->values = NULL;
   604   self->priv->last_requested_value = NULL;
   632   }
   605   self->priv->values = NULL;
   633   self->priv->nvalues = 0;
   606   self->priv->nvalues = 0;
   634   self->priv->valid_cache = FALSE;
   607   self->priv->valid_cache = FALSE;
   635 
   608 
   636   g_mutex_unlock (self->lock);
   609   g_mutex_unlock (self->lock);
   637 }
   610 }
   638 
   611 
   639 static void
       
   640 _append_control_point (GstControlPoint * cp, GList ** l)
       
   641 {
       
   642   *l = g_list_prepend (*l, cp);
       
   643 }
       
   644 
       
   645 /**
   612 /**
   646  * gst_interpolation_control_source_get_all:
   613  * gst_interpolation_control_source_get_all:
   647  * @self: the #GstInterpolationControlSource to get the list from
   614  * @self: the #GstInterpolationControlSource to get the list from
   648  *
   615  *
   649  * Returns a read-only copy of the list of #GstTimedValue for the given property.
   616  * Returns a read-only copy of the list of #GstTimedValue for the given property.
   661   GList *res = NULL;
   628   GList *res = NULL;
   662 
   629 
   663   g_return_val_if_fail (GST_IS_INTERPOLATION_CONTROL_SOURCE (self), NULL);
   630   g_return_val_if_fail (GST_IS_INTERPOLATION_CONTROL_SOURCE (self), NULL);
   664 
   631 
   665   g_mutex_lock (self->lock);
   632   g_mutex_lock (self->lock);
   666   if (G_LIKELY (self->priv->values))
   633   if (self->priv->values)
   667     g_sequence_foreach (self->priv->values, (GFunc) _append_control_point,
   634     res = g_list_copy (self->priv->values);
   668         &res);
       
   669   g_mutex_unlock (self->lock);
   635   g_mutex_unlock (self->lock);
   670 
   636 
   671   return g_list_reverse (res);
   637   return res;
   672 }
   638 }
   673 
   639 
   674 /**
   640 /**
   675  * gst_interpolation_control_source_get_count:
   641  * gst_interpolation_control_source_get_count:
   676  * @self: the #GstInterpolationControlSource to get the number of values from
   642  * @self: the #GstInterpolationControlSource to get the number of values from