gst_plugins_base/gst-libs/gst/audio/gstbaseaudiosrc.c
changeset 16 8e837d1bf446
parent 0 0e761a78d257
child 30 7e817e7e631c
equal deleted inserted replaced
15:4b0c6ed43234 16:8e837d1bf446
    40 
    40 
    41 #include "gstbaseaudiosrc.h"
    41 #include "gstbaseaudiosrc.h"
    42 
    42 
    43 #include "gst/gst-i18n-plugin.h"
    43 #include "gst/gst-i18n-plugin.h"
    44 
    44 
    45 #ifdef __SYMBIAN32__
       
    46 #include <glib_global.h>
       
    47 #endif
       
    48 
       
    49 GST_DEBUG_CATEGORY_STATIC (gst_base_audio_src_debug);
    45 GST_DEBUG_CATEGORY_STATIC (gst_base_audio_src_debug);
    50 #define GST_CAT_DEFAULT gst_base_audio_src_debug
    46 #define GST_CAT_DEFAULT gst_base_audio_src_debug
    51 
    47 
       
    48 #ifdef __SYMBIAN32__
       
    49 EXPORT_C
       
    50 #endif
       
    51 
       
    52 GType
       
    53 gst_base_audio_src_slave_method_get_type (void)
       
    54 {
       
    55   static GType slave_method_type = 0;
       
    56   static const GEnumValue slave_method[] = {
       
    57     {GST_BASE_AUDIO_SRC_SLAVE_RESAMPLE, "Resampling slaving", "resample"},
       
    58     {GST_BASE_AUDIO_SRC_SLAVE_RETIMESTAMP, "Re-timestamp", "re-timestamp"},
       
    59     {GST_BASE_AUDIO_SRC_SLAVE_SKEW, "Skew", "skew"},
       
    60     {GST_BASE_AUDIO_SRC_SLAVE_NONE, "No slaving", "none"},
       
    61     {0, NULL, NULL},
       
    62   };
       
    63 
       
    64   if (!slave_method_type) {
       
    65     slave_method_type =
       
    66         g_enum_register_static ("GstBaseAudioSrcSlaveMethod", slave_method);
       
    67   }
       
    68   return slave_method_type;
       
    69 }
       
    70 
    52 #define GST_BASE_AUDIO_SRC_GET_PRIVATE(obj)  \
    71 #define GST_BASE_AUDIO_SRC_GET_PRIVATE(obj)  \
    53    (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_BASE_AUDIO_SRC, GstBaseAudioSrcPrivate))
    72    (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_BASE_AUDIO_SRC, GstBaseAudioSrcPrivate))
    54 
    73 
    55 struct _GstBaseAudioSrcPrivate
    74 struct _GstBaseAudioSrcPrivate
    56 {
    75 {
    57   gboolean provide_clock;
    76   gboolean provide_clock;
       
    77 
       
    78   /* the clock slaving algorithm in use */
       
    79   GstBaseAudioSrcSlaveMethod slave_method;
    58 };
    80 };
    59 
    81 
    60 /* BaseAudioSrc signals and args */
    82 /* BaseAudioSrc signals and args */
    61 enum
    83 enum
    62 {
    84 {
    64   LAST_SIGNAL
    86   LAST_SIGNAL
    65 };
    87 };
    66 
    88 
    67 #define DEFAULT_BUFFER_TIME     ((200 * GST_MSECOND) / GST_USECOND)
    89 #define DEFAULT_BUFFER_TIME     ((200 * GST_MSECOND) / GST_USECOND)
    68 #define DEFAULT_LATENCY_TIME    ((10 * GST_MSECOND) / GST_USECOND)
    90 #define DEFAULT_LATENCY_TIME    ((10 * GST_MSECOND) / GST_USECOND)
       
    91 #define DEFAULT_ACTUAL_BUFFER_TIME     -1
       
    92 #define DEFAULT_ACTUAL_LATENCY_TIME    -1
    69 #define DEFAULT_PROVIDE_CLOCK   TRUE
    93 #define DEFAULT_PROVIDE_CLOCK   TRUE
       
    94 #define DEFAULT_SLAVE_METHOD    GST_BASE_AUDIO_SRC_SLAVE_RETIMESTAMP
    70 
    95 
    71 enum
    96 enum
    72 {
    97 {
    73   PROP_0,
    98   PROP_0,
    74   PROP_BUFFER_TIME,
    99   PROP_BUFFER_TIME,
    75   PROP_LATENCY_TIME,
   100   PROP_LATENCY_TIME,
    76   PROP_PROVIDE_CLOCK
   101   PROP_ACTUAL_BUFFER_TIME,
       
   102   PROP_ACTUAL_LATENCY_TIME,
       
   103   PROP_PROVIDE_CLOCK,
       
   104   PROP_SLAVE_METHOD,
       
   105   PROP_LAST
    77 };
   106 };
    78 
   107 
    79 static void
   108 static void
    80 _do_init (GType type)
   109 _do_init (GType type)
    81 {
   110 {
    84 
   113 
    85 #ifdef ENABLE_NLS
   114 #ifdef ENABLE_NLS
    86   GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE,
   115   GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE,
    87       LOCALEDIR);
   116       LOCALEDIR);
    88   bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
   117   bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
       
   118   bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
    89 #endif /* ENABLE_NLS */
   119 #endif /* ENABLE_NLS */
    90 }
   120 }
    91 
   121 
    92 GST_BOILERPLATE_FULL (GstBaseAudioSrc, gst_base_audio_src, GstPushSrc,
   122 GST_BOILERPLATE_FULL (GstBaseAudioSrc, gst_base_audio_src, GstPushSrc,
    93     GST_TYPE_PUSH_SRC, _do_init);
   123     GST_TYPE_PUSH_SRC, _do_init);
   145   gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_base_audio_src_dispose);
   175   gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_base_audio_src_dispose);
   146 
   176 
   147   g_object_class_install_property (gobject_class, PROP_BUFFER_TIME,
   177   g_object_class_install_property (gobject_class, PROP_BUFFER_TIME,
   148       g_param_spec_int64 ("buffer-time", "Buffer Time",
   178       g_param_spec_int64 ("buffer-time", "Buffer Time",
   149           "Size of audio buffer in microseconds", 1,
   179           "Size of audio buffer in microseconds", 1,
   150           G_MAXINT64, DEFAULT_BUFFER_TIME, G_PARAM_READWRITE));
   180           G_MAXINT64, DEFAULT_BUFFER_TIME,
       
   181           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   151 
   182 
   152   g_object_class_install_property (gobject_class, PROP_LATENCY_TIME,
   183   g_object_class_install_property (gobject_class, PROP_LATENCY_TIME,
   153       g_param_spec_int64 ("latency-time", "Latency Time",
   184       g_param_spec_int64 ("latency-time", "Latency Time",
   154           "Audio latency in microseconds", 1,
   185           "Audio latency in microseconds", 1,
   155           G_MAXINT64, DEFAULT_LATENCY_TIME, G_PARAM_READWRITE));
   186           G_MAXINT64, DEFAULT_LATENCY_TIME,
       
   187           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
       
   188 
       
   189   /**
       
   190    * GstBaseAudioSrc:actual-buffer-time:
       
   191    *
       
   192    * Actual configured size of audio buffer in microseconds.
       
   193    *
       
   194    * Since: 0.10.20
       
   195    **/
       
   196   g_object_class_install_property (gobject_class, PROP_ACTUAL_BUFFER_TIME,
       
   197       g_param_spec_int64 ("actual-buffer-time", "Actual Buffer Time",
       
   198           "Actual configured size of audio buffer in microseconds",
       
   199           DEFAULT_ACTUAL_BUFFER_TIME, G_MAXINT64, DEFAULT_ACTUAL_BUFFER_TIME,
       
   200           G_PARAM_READABLE));
       
   201 
       
   202   /**
       
   203    * GstBaseAudioSrc:actual-latency-time:
       
   204    *
       
   205    * Actual configured audio latency in microseconds.
       
   206    *
       
   207    * Since: 0.10.20
       
   208    **/
       
   209   g_object_class_install_property (gobject_class, PROP_ACTUAL_LATENCY_TIME,
       
   210       g_param_spec_int64 ("actual-latency-time", "Actual Latency Time",
       
   211           "Actual configured audio latency in microseconds",
       
   212           DEFAULT_ACTUAL_LATENCY_TIME, G_MAXINT64, DEFAULT_ACTUAL_LATENCY_TIME,
       
   213           G_PARAM_READABLE));
   156 
   214 
   157   g_object_class_install_property (gobject_class, PROP_PROVIDE_CLOCK,
   215   g_object_class_install_property (gobject_class, PROP_PROVIDE_CLOCK,
   158       g_param_spec_boolean ("provide-clock", "Provide Clock",
   216       g_param_spec_boolean ("provide-clock", "Provide Clock",
   159           "Provide a clock to be used as the global pipeline clock",
   217           "Provide a clock to be used as the global pipeline clock",
   160           DEFAULT_PROVIDE_CLOCK, G_PARAM_READWRITE));
   218           DEFAULT_PROVIDE_CLOCK, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
       
   219 
       
   220   g_object_class_install_property (gobject_class, PROP_SLAVE_METHOD,
       
   221       g_param_spec_enum ("slave-method", "Slave Method",
       
   222           "Algorithm to use to match the rate of the masterclock",
       
   223           GST_TYPE_BASE_AUDIO_SRC_SLAVE_METHOD, DEFAULT_SLAVE_METHOD,
       
   224           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   161 
   225 
   162   gstelement_class->change_state =
   226   gstelement_class->change_state =
   163       GST_DEBUG_FUNCPTR (gst_base_audio_src_change_state);
   227       GST_DEBUG_FUNCPTR (gst_base_audio_src_change_state);
   164   gstelement_class->provide_clock =
   228   gstelement_class->provide_clock =
   165       GST_DEBUG_FUNCPTR (gst_base_audio_src_provide_clock);
   229       GST_DEBUG_FUNCPTR (gst_base_audio_src_provide_clock);
   175   gstbasesrc_class->fixate = GST_DEBUG_FUNCPTR (gst_base_audio_src_fixate);
   239   gstbasesrc_class->fixate = GST_DEBUG_FUNCPTR (gst_base_audio_src_fixate);
   176 
   240 
   177   /* ref class from a thread-safe context to work around missing bit of
   241   /* ref class from a thread-safe context to work around missing bit of
   178    * thread-safety in GObject */
   242    * thread-safety in GObject */
   179   g_type_class_ref (GST_TYPE_AUDIO_CLOCK);
   243   g_type_class_ref (GST_TYPE_AUDIO_CLOCK);
       
   244   g_type_class_ref (GST_TYPE_RING_BUFFER);
   180 }
   245 }
   181 
   246 
   182 static void
   247 static void
   183 gst_base_audio_src_init (GstBaseAudioSrc * baseaudiosrc,
   248 gst_base_audio_src_init (GstBaseAudioSrc * baseaudiosrc,
   184     GstBaseAudioSrcClass * g_class)
   249     GstBaseAudioSrcClass * g_class)
   186   baseaudiosrc->priv = GST_BASE_AUDIO_SRC_GET_PRIVATE (baseaudiosrc);
   251   baseaudiosrc->priv = GST_BASE_AUDIO_SRC_GET_PRIVATE (baseaudiosrc);
   187 
   252 
   188   baseaudiosrc->buffer_time = DEFAULT_BUFFER_TIME;
   253   baseaudiosrc->buffer_time = DEFAULT_BUFFER_TIME;
   189   baseaudiosrc->latency_time = DEFAULT_LATENCY_TIME;
   254   baseaudiosrc->latency_time = DEFAULT_LATENCY_TIME;
   190   baseaudiosrc->priv->provide_clock = DEFAULT_PROVIDE_CLOCK;
   255   baseaudiosrc->priv->provide_clock = DEFAULT_PROVIDE_CLOCK;
       
   256   baseaudiosrc->priv->slave_method = DEFAULT_SLAVE_METHOD;
   191   /* reset blocksize we use latency time to calculate a more useful 
   257   /* reset blocksize we use latency time to calculate a more useful 
   192    * value based on negotiated format. */
   258    * value based on negotiated format. */
   193   GST_BASE_SRC (baseaudiosrc)->blocksize = 0;
   259   GST_BASE_SRC (baseaudiosrc)->blocksize = 0;
   194 
   260 
   195   baseaudiosrc->clock = gst_audio_clock_new ("GstAudioSrcClock",
   261   baseaudiosrc->clock = gst_audio_clock_new ("GstAudioSrcClock",
   206 {
   272 {
   207   GstBaseAudioSrc *src;
   273   GstBaseAudioSrc *src;
   208 
   274 
   209   src = GST_BASE_AUDIO_SRC (object);
   275   src = GST_BASE_AUDIO_SRC (object);
   210 
   276 
       
   277   GST_OBJECT_LOCK (src);
   211   if (src->clock)
   278   if (src->clock)
   212     gst_object_unref (src->clock);
   279     gst_object_unref (src->clock);
   213   src->clock = NULL;
   280   src->clock = NULL;
   214 
   281 
   215   if (src->ringbuffer) {
   282   if (src->ringbuffer) {
   216     gst_object_unparent (GST_OBJECT_CAST (src->ringbuffer));
   283     gst_object_unparent (GST_OBJECT_CAST (src->ringbuffer));
   217     src->ringbuffer = NULL;
   284     src->ringbuffer = NULL;
   218   }
   285   }
       
   286   GST_OBJECT_UNLOCK (src);
   219 
   287 
   220   G_OBJECT_CLASS (parent_class)->dispose (object);
   288   G_OBJECT_CLASS (parent_class)->dispose (object);
   221 }
   289 }
   222 
   290 
   223 static GstClock *
   291 static GstClock *
   348   GST_OBJECT_UNLOCK (src);
   416   GST_OBJECT_UNLOCK (src);
   349 
   417 
   350   return result;
   418   return result;
   351 }
   419 }
   352 
   420 
       
   421 /**
       
   422  * gst_base_audio_src_set_slave_method:
       
   423  * @src: a #GstBaseAudioSrc
       
   424  * @method: the new slave method
       
   425  *
       
   426  * Controls how clock slaving will be performed in @src. 
       
   427  *
       
   428  * Since: 0.10.20
       
   429  */
       
   430 #ifdef __SYMBIAN32__
       
   431 EXPORT_C
       
   432 #endif
       
   433 
       
   434 void
       
   435 gst_base_audio_src_set_slave_method (GstBaseAudioSrc * src,
       
   436     GstBaseAudioSrcSlaveMethod method)
       
   437 {
       
   438   g_return_if_fail (GST_IS_BASE_AUDIO_SRC (src));
       
   439 
       
   440   GST_OBJECT_LOCK (src);
       
   441   src->priv->slave_method = method;
       
   442   GST_OBJECT_UNLOCK (src);
       
   443 }
       
   444 
       
   445 /**
       
   446  * gst_base_audio_src_get_slave_method:
       
   447  * @src: a #GstBaseAudioSrc
       
   448  *
       
   449  * Get the current slave method used by @src.
       
   450  *
       
   451  * Returns: The current slave method used by @src.
       
   452  *
       
   453  * Since: 0.10.20
       
   454  */
       
   455 #ifdef __SYMBIAN32__
       
   456 EXPORT_C
       
   457 #endif
       
   458 
       
   459 GstBaseAudioSrcSlaveMethod
       
   460 gst_base_audio_src_get_slave_method (GstBaseAudioSrc * src)
       
   461 {
       
   462   GstBaseAudioSrcSlaveMethod result;
       
   463 
       
   464   g_return_val_if_fail (GST_IS_BASE_AUDIO_SRC (src), -1);
       
   465 
       
   466   GST_OBJECT_LOCK (src);
       
   467   result = src->priv->slave_method;
       
   468   GST_OBJECT_UNLOCK (src);
       
   469 
       
   470   return result;
       
   471 }
       
   472 
   353 static void
   473 static void
   354 gst_base_audio_src_set_property (GObject * object, guint prop_id,
   474 gst_base_audio_src_set_property (GObject * object, guint prop_id,
   355     const GValue * value, GParamSpec * pspec)
   475     const GValue * value, GParamSpec * pspec)
   356 {
   476 {
   357   GstBaseAudioSrc *src;
   477   GstBaseAudioSrc *src;
   366       src->latency_time = g_value_get_int64 (value);
   486       src->latency_time = g_value_get_int64 (value);
   367       break;
   487       break;
   368     case PROP_PROVIDE_CLOCK:
   488     case PROP_PROVIDE_CLOCK:
   369       gst_base_audio_src_set_provide_clock (src, g_value_get_boolean (value));
   489       gst_base_audio_src_set_provide_clock (src, g_value_get_boolean (value));
   370       break;
   490       break;
       
   491     case PROP_SLAVE_METHOD:
       
   492       gst_base_audio_src_set_slave_method (src, g_value_get_enum (value));
       
   493       break;
   371     default:
   494     default:
   372       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
   495       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
   373       break;
   496       break;
   374   }
   497   }
   375 }
   498 }
   387       g_value_set_int64 (value, src->buffer_time);
   510       g_value_set_int64 (value, src->buffer_time);
   388       break;
   511       break;
   389     case PROP_LATENCY_TIME:
   512     case PROP_LATENCY_TIME:
   390       g_value_set_int64 (value, src->latency_time);
   513       g_value_set_int64 (value, src->latency_time);
   391       break;
   514       break;
       
   515     case PROP_ACTUAL_BUFFER_TIME:
       
   516       GST_OBJECT_LOCK (src);
       
   517       if (src->ringbuffer && src->ringbuffer->acquired)
       
   518         g_value_set_int64 (value, src->ringbuffer->spec.buffer_time);
       
   519       else
       
   520         g_value_set_int64 (value, DEFAULT_ACTUAL_BUFFER_TIME);
       
   521       GST_OBJECT_UNLOCK (src);
       
   522       break;
       
   523     case PROP_ACTUAL_LATENCY_TIME:
       
   524       GST_OBJECT_LOCK (src);
       
   525       if (src->ringbuffer && src->ringbuffer->acquired)
       
   526         g_value_set_int64 (value, src->ringbuffer->spec.latency_time);
       
   527       else
       
   528         g_value_set_int64 (value, DEFAULT_ACTUAL_LATENCY_TIME);
       
   529       GST_OBJECT_UNLOCK (src);
       
   530       break;
   392     case PROP_PROVIDE_CLOCK:
   531     case PROP_PROVIDE_CLOCK:
   393       g_value_set_boolean (value, gst_base_audio_src_get_provide_clock (src));
   532       g_value_set_boolean (value, gst_base_audio_src_get_provide_clock (src));
       
   533       break;
       
   534     case PROP_SLAVE_METHOD:
       
   535       g_value_set_enum (value, gst_base_audio_src_get_slave_method (src));
   394       break;
   536       break;
   395     default:
   537     default:
   396       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
   538       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
   397       break;
   539       break;
   398   }
   540   }
   460   spec->buffer_time =
   602   spec->buffer_time =
   461       spec->segtotal * spec->segsize * GST_MSECOND / (spec->rate *
   603       spec->segtotal * spec->segsize * GST_MSECOND / (spec->rate *
   462       spec->bytes_per_sample);
   604       spec->bytes_per_sample);
   463 
   605 
   464   gst_ring_buffer_debug_spec_buff (spec);
   606   gst_ring_buffer_debug_spec_buff (spec);
       
   607 
       
   608   g_object_notify (G_OBJECT (src), "actual-buffer-time");
       
   609   g_object_notify (G_OBJECT (src), "actual-latency-time");
   465 
   610 
   466   return TRUE;
   611   return TRUE;
   467 
   612 
   468   /* ERRORS */
   613   /* ERRORS */
   469 parse_error:
   614 parse_error:
   536 
   681 
   537 static gboolean
   682 static gboolean
   538 gst_base_audio_src_event (GstBaseSrc * bsrc, GstEvent * event)
   683 gst_base_audio_src_event (GstBaseSrc * bsrc, GstEvent * event)
   539 {
   684 {
   540   GstBaseAudioSrc *src = GST_BASE_AUDIO_SRC (bsrc);
   685   GstBaseAudioSrc *src = GST_BASE_AUDIO_SRC (bsrc);
       
   686   gboolean res;
       
   687 
       
   688   res = TRUE;
   541 
   689 
   542   switch (GST_EVENT_TYPE (event)) {
   690   switch (GST_EVENT_TYPE (event)) {
   543     case GST_EVENT_FLUSH_START:
   691     case GST_EVENT_FLUSH_START:
       
   692       GST_DEBUG_OBJECT (bsrc, "flush-start");
   544       gst_ring_buffer_pause (src->ringbuffer);
   693       gst_ring_buffer_pause (src->ringbuffer);
   545       gst_ring_buffer_clear_all (src->ringbuffer);
   694       gst_ring_buffer_clear_all (src->ringbuffer);
   546       break;
   695       break;
   547     case GST_EVENT_FLUSH_STOP:
   696     case GST_EVENT_FLUSH_STOP:
       
   697       GST_DEBUG_OBJECT (bsrc, "flush-stop");
   548       /* always resync on sample after a flush */
   698       /* always resync on sample after a flush */
   549       src->next_sample = -1;
   699       src->next_sample = -1;
   550       gst_ring_buffer_clear_all (src->ringbuffer);
   700       gst_ring_buffer_clear_all (src->ringbuffer);
   551       break;
   701       break;
       
   702     case GST_EVENT_SEEK:
       
   703       GST_DEBUG_OBJECT (bsrc, "refuse to seek");
       
   704       res = FALSE;
       
   705       break;
   552     default:
   706     default:
   553       break;
   707       GST_DEBUG_OBJECT (bsrc, "dropping event %p", event);
   554   }
   708       break;
   555   return TRUE;
   709   }
       
   710   return res;
   556 }
   711 }
   557 
   712 
   558 /* get the next offset in the ringbuffer for reading samples.
   713 /* get the next offset in the ringbuffer for reading samples.
   559  * If the next sample is too far away, this function will position itself to the
   714  * If the next sample is too far away, this function will position itself to the
   560  * next most recent sample, creating discontinuity */
   715  * next most recent sample, creating discontinuity */
   589    * reading). */
   744    * reading). */
   590   diff = segdone - readseg;
   745   diff = segdone - readseg;
   591   if (diff >= segtotal) {
   746   if (diff >= segtotal) {
   592     GST_DEBUG_OBJECT (src, "dropped, align to segment %d", segdone);
   747     GST_DEBUG_OBJECT (src, "dropped, align to segment %d", segdone);
   593     /* sample would be dropped, position to next playable position */
   748     /* sample would be dropped, position to next playable position */
   594     sample = (segdone - segtotal + 1) * sps;
   749     sample = ((guint64) (segdone)) * sps;
   595   }
   750   }
   596 
   751 
   597   return sample;
   752   return sample;
   598 }
   753 }
   599 
   754 
   675     GST_WARNING_OBJECT (src,
   830     GST_WARNING_OBJECT (src,
   676         "create DISCONT of %" G_GUINT64_FORMAT " samples at sample %"
   831         "create DISCONT of %" G_GUINT64_FORMAT " samples at sample %"
   677         G_GUINT64_FORMAT, sample - src->next_sample, sample);
   832         G_GUINT64_FORMAT, sample - src->next_sample, sample);
   678     GST_ELEMENT_WARNING (src, CORE, CLOCK,
   833     GST_ELEMENT_WARNING (src, CORE, CLOCK,
   679         (_("Can't record audio fast enough")),
   834         (_("Can't record audio fast enough")),
   680         ("dropped %" G_GUINT64_FORMAT " samples", sample - src->next_sample));
   835         ("Dropped %" G_GUINT64_FORMAT " samples. This is most likely because "
       
   836             "downstream can't keep up and is consuming samples too slowly.",
       
   837             sample - src->next_sample));
   681     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
   838     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
   682   }
   839   }
   683 
   840 
   684   src->next_sample = sample + samples;
   841   src->next_sample = sample + samples;
   685 
   842 
   687   timestamp = gst_util_uint64_scale_int (sample, GST_SECOND, spec->rate);
   844   timestamp = gst_util_uint64_scale_int (sample, GST_SECOND, spec->rate);
   688   duration = gst_util_uint64_scale_int (src->next_sample, GST_SECOND,
   845   duration = gst_util_uint64_scale_int (src->next_sample, GST_SECOND,
   689       spec->rate) - timestamp;
   846       spec->rate) - timestamp;
   690 
   847 
   691   GST_OBJECT_LOCK (src);
   848   GST_OBJECT_LOCK (src);
   692   clock = GST_ELEMENT_CLOCK (src);
   849   if (!(clock = GST_ELEMENT_CLOCK (src)))
   693   if (clock != NULL && clock != src->clock) {
   850     goto no_sync;
   694     GstClockTime base_time, latency;
   851 
   695 
   852   if (clock != src->clock) {
   696     /* We are slaved to another clock, take running time of the clock and just
   853     /* we are slaved, check how to handle this */
   697      * timestamp against it. Somebody else in the pipeline should figure out the
   854     switch (src->priv->slave_method) {
   698      * clock drift, for now. We keep the duration we calculated above. */
   855       case GST_BASE_AUDIO_SRC_SLAVE_RESAMPLE:
   699     timestamp = gst_clock_get_time (clock);
   856         /* not implemented, use skew algorithm. This algorithm should
       
   857          * work on the readout pointer and produces more or less samples based
       
   858          * on the clock drift */
       
   859       case GST_BASE_AUDIO_SRC_SLAVE_SKEW:
       
   860       {
       
   861         GstClockTime running_time;
       
   862         GstClockTime base_time;
       
   863         GstClockTime current_time;
       
   864         guint64 running_time_sample;
       
   865         gint running_time_segment;
       
   866         gint current_segment;
       
   867         gint segment_skew;
       
   868         gint sps;
       
   869 
       
   870         /* samples per segment */
       
   871         sps = ringbuffer->samples_per_seg;
       
   872 
       
   873         /* get the current time */
       
   874         current_time = gst_clock_get_time (clock);
       
   875 
       
   876         /* get the basetime */
       
   877         base_time = GST_ELEMENT_CAST (src)->base_time;
       
   878 
       
   879         /* get the running_time */
       
   880         running_time = current_time - base_time;
       
   881 
       
   882         /* the running_time converted to a sample (relative to the ringbuffer) */
       
   883         running_time_sample =
       
   884             gst_util_uint64_scale_int (running_time, spec->rate, GST_SECOND);
       
   885 
       
   886         /* the segmentnr corrensponding to running_time, round down */
       
   887         running_time_segment = running_time_sample / sps;
       
   888 
       
   889         /* the segment currently read from the ringbuffer */
       
   890         current_segment = sample / sps;
       
   891 
       
   892         /* the skew we have between running_time and the ringbuffertime */
       
   893         segment_skew = running_time_segment - current_segment;
       
   894 
       
   895         GST_DEBUG_OBJECT (bsrc, "\n running_time = %" GST_TIME_FORMAT
       
   896             "\n timestamp     = %" GST_TIME_FORMAT
       
   897             "\n running_time_segment = %d"
       
   898             "\n current_segment      = %d"
       
   899             "\n segment_skew         = %d",
       
   900             GST_TIME_ARGS (running_time),
       
   901             GST_TIME_ARGS (timestamp),
       
   902             running_time_segment, current_segment, segment_skew);
       
   903 
       
   904         /* Resync the ringbuffer if:
       
   905          * 1. We get one segment into the future.
       
   906          *    This is clearly a lie, because we can't
       
   907          *    possibly have a buffer with timestamp 1 at
       
   908          *    time 0. (unless it has time-travelled...)
       
   909          *
       
   910          * 2. We are more than the length of the ringbuffer behind.
       
   911          *    The length of the ringbuffer then gets to dictate
       
   912          *    the threshold for what is concidered "too late"
       
   913          *
       
   914          * 3. If this is our first buffer.
       
   915          *    We know that we should catch up to running_time
       
   916          *    the first time we are ran.
       
   917          */
       
   918         if ((segment_skew < 0) ||
       
   919             (segment_skew >= ringbuffer->spec.segtotal) ||
       
   920             (current_segment == 0)) {
       
   921           gint segments_written;
       
   922           gint first_segment;
       
   923           gint last_segment;
       
   924           gint new_last_segment;
       
   925           gint segment_diff;
       
   926           gint new_first_segment;
       
   927           guint64 new_sample;
       
   928 
       
   929           /* we are going to say that the last segment was captured at the current time
       
   930              (running_time), minus one segment of creation-latency in the ringbuffer.
       
   931              This can be thought of as: The segment arrived in the ringbuffer at time X, and
       
   932              that means it was created at time X - (one segment). */
       
   933           new_last_segment = running_time_segment - 1;
       
   934 
       
   935           /* for better readablity */
       
   936           first_segment = current_segment;
       
   937 
       
   938           /* get the amount of segments written from the device by now */
       
   939           segments_written = g_atomic_int_get (&ringbuffer->segdone);
       
   940 
       
   941           /* subtract the base to segments_written to get the number of the
       
   942              last written segment in the ringbuffer (one segment written = segment 0) */
       
   943           last_segment = segments_written - ringbuffer->segbase - 1;
       
   944 
       
   945           /* we see how many segments the ringbuffer was timeshifted */
       
   946           segment_diff = new_last_segment - last_segment;
       
   947 
       
   948           /* we move the first segment an equal amount */
       
   949           new_first_segment = first_segment + segment_diff;
       
   950 
       
   951           /* and we also move the segmentbase the same amount */
       
   952           ringbuffer->segbase -= segment_diff;
       
   953 
       
   954           /* we calculate the new sample value */
       
   955           new_sample = ((guint64) new_first_segment) * sps;
       
   956 
       
   957           /* and get the relative time to this -> our new timestamp */
       
   958           timestamp =
       
   959               gst_util_uint64_scale_int (new_sample, GST_SECOND, spec->rate);
       
   960 
       
   961           /* we update the next sample accordingly */
       
   962           src->next_sample = new_sample + samples;
       
   963 
       
   964           GST_DEBUG_OBJECT (bsrc,
       
   965               "Timeshifted the ringbuffer with %d segments: "
       
   966               "Updating the timestamp to %" GST_TIME_FORMAT ", "
       
   967               "and src->next_sample to %" G_GUINT64_FORMAT, segment_diff,
       
   968               GST_TIME_ARGS (timestamp), src->next_sample);
       
   969         }
       
   970         break;
       
   971       }
       
   972       case GST_BASE_AUDIO_SRC_SLAVE_RETIMESTAMP:
       
   973       {
       
   974         GstClockTime base_time, latency;
       
   975 
       
   976         /* We are slaved to another clock, take running time of the pipeline clock and
       
   977          * timestamp against it. Somebody else in the pipeline should figure out the
       
   978          * clock drift. We keep the duration we calculated above. */
       
   979         timestamp = gst_clock_get_time (clock);
       
   980         base_time = GST_ELEMENT_CAST (src)->base_time;
       
   981 
       
   982         if (timestamp > base_time)
       
   983           timestamp -= base_time;
       
   984         else
       
   985           timestamp = 0;
       
   986 
       
   987         /* subtract latency */
       
   988         latency =
       
   989             gst_util_uint64_scale_int (total_samples, GST_SECOND, spec->rate);
       
   990         if (timestamp > latency)
       
   991           timestamp -= latency;
       
   992         else
       
   993           timestamp = 0;
       
   994       }
       
   995       case GST_BASE_AUDIO_SRC_SLAVE_NONE:
       
   996         break;
       
   997     }
       
   998   } else {
       
   999     GstClockTime base_time;
       
  1000 
       
  1001     /* to get the timestamp against the clock we also need to add our offset */
       
  1002     timestamp = gst_audio_clock_adjust (clock, timestamp);
       
  1003 
       
  1004     /* we are not slaved, subtract base_time */
   700     base_time = GST_ELEMENT_CAST (src)->base_time;
  1005     base_time = GST_ELEMENT_CAST (src)->base_time;
   701 
  1006 
   702     if (timestamp > base_time)
  1007     if (timestamp > base_time) {
   703       timestamp -= base_time;
  1008       timestamp -= base_time;
   704     else
  1009       GST_LOG_OBJECT (src,
       
  1010           "buffer timestamp %" GST_TIME_FORMAT " (base_time %" GST_TIME_FORMAT
       
  1011           ")", GST_TIME_ARGS (timestamp), GST_TIME_ARGS (base_time));
       
  1012     } else {
       
  1013       GST_LOG_OBJECT (src,
       
  1014           "buffer timestamp 0, ts %" GST_TIME_FORMAT " <= base_time %"
       
  1015           GST_TIME_FORMAT, GST_TIME_ARGS (timestamp),
       
  1016           GST_TIME_ARGS (base_time));
   705       timestamp = 0;
  1017       timestamp = 0;
   706 
  1018     }
   707     /* subtract latency */
  1019   }
   708     latency = gst_util_uint64_scale_int (total_samples, GST_SECOND, spec->rate);
  1020 
   709     if (timestamp > latency)
  1021 no_sync:
   710       timestamp -= latency;
       
   711     else
       
   712       timestamp = 0;
       
   713   }
       
   714   GST_OBJECT_UNLOCK (src);
  1022   GST_OBJECT_UNLOCK (src);
   715 
  1023 
   716   GST_BUFFER_TIMESTAMP (buf) = timestamp;
  1024   GST_BUFFER_TIMESTAMP (buf) = timestamp;
   717   GST_BUFFER_DURATION (buf) = duration;
  1025   GST_BUFFER_DURATION (buf) = duration;
   718   GST_BUFFER_OFFSET (buf) = sample;
  1026   GST_BUFFER_OFFSET (buf) = sample;
   719   GST_BUFFER_OFFSET_END (buf) = sample + samples;
  1027   GST_BUFFER_OFFSET_END (buf) = sample + samples;
   720 
       
   721   gst_buffer_set_caps (buf, GST_PAD_CAPS (GST_BASE_SRC_PAD (bsrc)));
       
   722 
  1028 
   723   *outbuf = buf;
  1029   *outbuf = buf;
   724 
  1030 
   725   return GST_FLOW_OK;
  1031   return GST_FLOW_OK;
   726 
  1032 
   783   GstBaseAudioSrc *src = GST_BASE_AUDIO_SRC (element);
  1089   GstBaseAudioSrc *src = GST_BASE_AUDIO_SRC (element);
   784 
  1090 
   785   switch (transition) {
  1091   switch (transition) {
   786     case GST_STATE_CHANGE_NULL_TO_READY:
  1092     case GST_STATE_CHANGE_NULL_TO_READY:
   787       GST_DEBUG_OBJECT (src, "NULL->READY");
  1093       GST_DEBUG_OBJECT (src, "NULL->READY");
       
  1094       GST_OBJECT_LOCK (src);
   788       if (src->ringbuffer == NULL) {
  1095       if (src->ringbuffer == NULL) {
       
  1096         gst_audio_clock_reset (GST_AUDIO_CLOCK (src->clock), 0);
   789         src->ringbuffer = gst_base_audio_src_create_ringbuffer (src);
  1097         src->ringbuffer = gst_base_audio_src_create_ringbuffer (src);
   790       }
  1098       }
       
  1099       GST_OBJECT_UNLOCK (src);
   791       if (!gst_ring_buffer_open_device (src->ringbuffer))
  1100       if (!gst_ring_buffer_open_device (src->ringbuffer))
   792         goto open_failed;
  1101         goto open_failed;
   793       break;
  1102       break;
   794     case GST_STATE_CHANGE_READY_TO_PAUSED:
  1103     case GST_STATE_CHANGE_READY_TO_PAUSED:
   795       GST_DEBUG_OBJECT (src, "READY->PAUSED");
  1104       GST_DEBUG_OBJECT (src, "READY->PAUSED");
   822       gst_ring_buffer_release (src->ringbuffer);
  1131       gst_ring_buffer_release (src->ringbuffer);
   823       break;
  1132       break;
   824     case GST_STATE_CHANGE_READY_TO_NULL:
  1133     case GST_STATE_CHANGE_READY_TO_NULL:
   825       GST_DEBUG_OBJECT (src, "READY->NULL");
  1134       GST_DEBUG_OBJECT (src, "READY->NULL");
   826       gst_ring_buffer_close_device (src->ringbuffer);
  1135       gst_ring_buffer_close_device (src->ringbuffer);
       
  1136       GST_OBJECT_LOCK (src);
   827       gst_object_unparent (GST_OBJECT_CAST (src->ringbuffer));
  1137       gst_object_unparent (GST_OBJECT_CAST (src->ringbuffer));
   828       src->ringbuffer = NULL;
  1138       src->ringbuffer = NULL;
       
  1139       GST_OBJECT_UNLOCK (src);
   829       break;
  1140       break;
   830     default:
  1141     default:
   831       break;
  1142       break;
   832   }
  1143   }
   833 
  1144