gst_plugins_base/gst-libs/gst/audio/gstbaseaudiosink.c
branchRCL_3
changeset 30 7e817e7e631c
parent 29 567bb019e3e3
equal deleted inserted replaced
29:567bb019e3e3 30:7e817e7e631c
    33  */
    33  */
    34 
    34 
    35 #include <string.h>
    35 #include <string.h>
    36 
    36 
    37 #include "gstbaseaudiosink.h"
    37 #include "gstbaseaudiosink.h"
       
    38 
       
    39 #ifdef __SYMBIAN32__
       
    40 #include <glib_global.h>
       
    41 #endif
    38 
    42 
    39 GST_DEBUG_CATEGORY_STATIC (gst_base_audio_sink_debug);
    43 GST_DEBUG_CATEGORY_STATIC (gst_base_audio_sink_debug);
    40 #define GST_CAT_DEFAULT gst_base_audio_sink_debug
    44 #define GST_CAT_DEFAULT gst_base_audio_sink_debug
    41 
    45 
    42 #define GST_BASE_AUDIO_SINK_GET_PRIVATE(obj)  \
    46 #define GST_BASE_AUDIO_SINK_GET_PRIVATE(obj)  \
    50   GstBaseAudioSinkSlaveMethod slave_method;
    54   GstBaseAudioSinkSlaveMethod slave_method;
    51   /* running average of clock skew */
    55   /* running average of clock skew */
    52   GstClockTimeDiff avg_skew;
    56   GstClockTimeDiff avg_skew;
    53   /* the number of samples we aligned last time */
    57   /* the number of samples we aligned last time */
    54   gint64 last_align;
    58   gint64 last_align;
    55 
       
    56   gboolean sync_latency;
       
    57 
       
    58   GstClockTime eos_time;
       
    59 };
    59 };
    60 
    60 
    61 /* BaseAudioSink signals and args */
    61 /* BaseAudioSink signals and args */
    62 enum
    62 enum
    63 {
    63 {
    78 #define DEFAULT_BUFFER_TIME     ((200 * GST_MSECOND) / GST_USECOND)
    78 #define DEFAULT_BUFFER_TIME     ((200 * GST_MSECOND) / GST_USECOND)
    79 #define DEFAULT_LATENCY_TIME    ((10 * GST_MSECOND) / GST_USECOND)
    79 #define DEFAULT_LATENCY_TIME    ((10 * GST_MSECOND) / GST_USECOND)
    80 #define DEFAULT_PROVIDE_CLOCK   TRUE
    80 #define DEFAULT_PROVIDE_CLOCK   TRUE
    81 #define DEFAULT_SLAVE_METHOD    GST_BASE_AUDIO_SINK_SLAVE_SKEW
    81 #define DEFAULT_SLAVE_METHOD    GST_BASE_AUDIO_SINK_SLAVE_SKEW
    82 
    82 
    83 /* FIXME, enable pull mode when clock slaving and trick modes are figured out */
       
    84 #define DEFAULT_CAN_ACTIVATE_PULL FALSE
       
    85 
       
    86 enum
    83 enum
    87 {
    84 {
    88   PROP_0,
    85   PROP_0,
    89   PROP_BUFFER_TIME,
    86   PROP_BUFFER_TIME,
    90   PROP_LATENCY_TIME,
    87   PROP_LATENCY_TIME,
    91   PROP_PROVIDE_CLOCK,
    88   PROP_PROVIDE_CLOCK,
    92   PROP_SLAVE_METHOD,
    89   PROP_SLAVE_METHOD
    93   PROP_CAN_ACTIVATE_PULL
       
    94 };
    90 };
    95 #ifdef __SYMBIAN32__
    91 
    96 EXPORT_C
    92 #define GST_TYPE_SLAVE_METHOD (slave_method_get_type ())
    97 #endif
    93 
    98 
    94 static GType
    99 
    95 slave_method_get_type (void)
   100 GType
       
   101 gst_base_audio_sink_slave_method_get_type (void)
       
   102 {
    96 {
   103   static GType slave_method_type = 0;
    97   static GType slave_method_type = 0;
   104   static const GEnumValue slave_method[] = {
    98   static const GEnumValue slave_method[] = {
   105     {GST_BASE_AUDIO_SINK_SLAVE_RESAMPLE, "Resampling slaving", "resample"},
    99     {GST_BASE_AUDIO_SINK_SLAVE_RESAMPLE, "Resampling slaving", "resample"},
   106     {GST_BASE_AUDIO_SINK_SLAVE_SKEW, "Skew slaving", "skew"},
   100     {GST_BASE_AUDIO_SINK_SLAVE_SKEW, "Skew slaving", "skew"},
   154     GstBuffer * buffer, GstClockTime * start, GstClockTime * end);
   148     GstBuffer * buffer, GstClockTime * start, GstClockTime * end);
   155 static gboolean gst_base_audio_sink_setcaps (GstBaseSink * bsink,
   149 static gboolean gst_base_audio_sink_setcaps (GstBaseSink * bsink,
   156     GstCaps * caps);
   150     GstCaps * caps);
   157 static void gst_base_audio_sink_fixate (GstBaseSink * bsink, GstCaps * caps);
   151 static void gst_base_audio_sink_fixate (GstBaseSink * bsink, GstCaps * caps);
   158 
   152 
   159 static gboolean gst_base_audio_sink_query_pad (GstPad * pad, GstQuery * query);
       
   160 
       
   161 
       
   162 /* static guint gst_base_audio_sink_signals[LAST_SIGNAL] = { 0 }; */
   153 /* static guint gst_base_audio_sink_signals[LAST_SIGNAL] = { 0 }; */
   163 
   154 
   164 static void
   155 static void
   165 gst_base_audio_sink_base_init (gpointer g_class)
   156 gst_base_audio_sink_base_init (gpointer g_class)
   166 {
   157 {
   186   gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_base_audio_sink_dispose);
   177   gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_base_audio_sink_dispose);
   187 
   178 
   188   g_object_class_install_property (gobject_class, PROP_BUFFER_TIME,
   179   g_object_class_install_property (gobject_class, PROP_BUFFER_TIME,
   189       g_param_spec_int64 ("buffer-time", "Buffer Time",
   180       g_param_spec_int64 ("buffer-time", "Buffer Time",
   190           "Size of audio buffer in microseconds", 1,
   181           "Size of audio buffer in microseconds", 1,
   191           G_MAXINT64, DEFAULT_BUFFER_TIME,
   182           G_MAXINT64, DEFAULT_BUFFER_TIME, G_PARAM_READWRITE));
   192           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
       
   193 
   183 
   194   g_object_class_install_property (gobject_class, PROP_LATENCY_TIME,
   184   g_object_class_install_property (gobject_class, PROP_LATENCY_TIME,
   195       g_param_spec_int64 ("latency-time", "Latency Time",
   185       g_param_spec_int64 ("latency-time", "Latency Time",
   196           "Audio latency in microseconds", 1,
   186           "Audio latency in microseconds", 1,
   197           G_MAXINT64, DEFAULT_LATENCY_TIME,
   187           G_MAXINT64, DEFAULT_LATENCY_TIME, G_PARAM_READWRITE));
   198           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
       
   199 
   188 
   200   g_object_class_install_property (gobject_class, PROP_PROVIDE_CLOCK,
   189   g_object_class_install_property (gobject_class, PROP_PROVIDE_CLOCK,
   201       g_param_spec_boolean ("provide-clock", "Provide Clock",
   190       g_param_spec_boolean ("provide-clock", "Provide Clock",
   202           "Provide a clock to be used as the global pipeline clock",
   191           "Provide a clock to be used as the global pipeline clock",
   203           DEFAULT_PROVIDE_CLOCK, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   192           DEFAULT_PROVIDE_CLOCK, G_PARAM_READWRITE));
   204 
   193 
   205   g_object_class_install_property (gobject_class, PROP_SLAVE_METHOD,
   194   g_object_class_install_property (gobject_class, PROP_SLAVE_METHOD,
   206       g_param_spec_enum ("slave-method", "Slave Method",
   195       g_param_spec_enum ("slave-method", "Slave Method",
   207           "Algorithm to use to match the rate of the masterclock",
   196           "Algorithm to use to match the rate of the masterclock",
   208           GST_TYPE_BASE_AUDIO_SINK_SLAVE_METHOD, DEFAULT_SLAVE_METHOD,
   197           GST_TYPE_SLAVE_METHOD, DEFAULT_SLAVE_METHOD, G_PARAM_READWRITE));
   209           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
       
   210 
       
   211   g_object_class_install_property (gobject_class, PROP_CAN_ACTIVATE_PULL,
       
   212       g_param_spec_boolean ("can-activate-pull", "Allow Pull Scheduling",
       
   213           "Allow pull-based scheduling", DEFAULT_CAN_ACTIVATE_PULL,
       
   214           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
       
   215 
   198 
   216   gstelement_class->change_state =
   199   gstelement_class->change_state =
   217       GST_DEBUG_FUNCPTR (gst_base_audio_sink_change_state);
   200       GST_DEBUG_FUNCPTR (gst_base_audio_sink_change_state);
   218   gstelement_class->provide_clock =
   201   gstelement_class->provide_clock =
   219       GST_DEBUG_FUNCPTR (gst_base_audio_sink_provide_clock);
   202       GST_DEBUG_FUNCPTR (gst_base_audio_sink_provide_clock);
   232       GST_DEBUG_FUNCPTR (gst_base_audio_sink_activate_pull);
   215       GST_DEBUG_FUNCPTR (gst_base_audio_sink_activate_pull);
   233 
   216 
   234   /* ref class from a thread-safe context to work around missing bit of
   217   /* ref class from a thread-safe context to work around missing bit of
   235    * thread-safety in GObject */
   218    * thread-safety in GObject */
   236   g_type_class_ref (GST_TYPE_AUDIO_CLOCK);
   219   g_type_class_ref (GST_TYPE_AUDIO_CLOCK);
   237   g_type_class_ref (GST_TYPE_RING_BUFFER);
       
   238 }
   220 }
   239 
   221 
   240 static void
   222 static void
   241 gst_base_audio_sink_init (GstBaseAudioSink * baseaudiosink,
   223 gst_base_audio_sink_init (GstBaseAudioSink * baseaudiosink,
   242     GstBaseAudioSinkClass * g_class)
   224     GstBaseAudioSinkClass * g_class)
   250 
   232 
   251   baseaudiosink->provided_clock = gst_audio_clock_new ("GstAudioSinkClock",
   233   baseaudiosink->provided_clock = gst_audio_clock_new ("GstAudioSinkClock",
   252       (GstAudioClockGetTimeFunc) gst_base_audio_sink_get_time, baseaudiosink);
   234       (GstAudioClockGetTimeFunc) gst_base_audio_sink_get_time, baseaudiosink);
   253 
   235 
   254   GST_BASE_SINK (baseaudiosink)->can_activate_push = TRUE;
   236   GST_BASE_SINK (baseaudiosink)->can_activate_push = TRUE;
   255   GST_BASE_SINK (baseaudiosink)->can_activate_pull = DEFAULT_CAN_ACTIVATE_PULL;
   237   /* FIXME, enable pull mode when segments, latency, state changes, negotiation
   256 
   238    * and clock slaving are figured out */
   257   /* install some custom pad_query functions */
   239   GST_BASE_SINK (baseaudiosink)->can_activate_pull = FALSE;
   258   gst_pad_set_query_function (GST_BASE_SINK_PAD (baseaudiosink),
       
   259       GST_DEBUG_FUNCPTR (gst_base_audio_sink_query_pad));
       
   260 }
   240 }
   261 
   241 
   262 static void
   242 static void
   263 gst_base_audio_sink_dispose (GObject * object)
   243 gst_base_audio_sink_dispose (GObject * object)
   264 {
   244 {
   275     sink->ringbuffer = NULL;
   255     sink->ringbuffer = NULL;
   276   }
   256   }
   277 
   257 
   278   G_OBJECT_CLASS (parent_class)->dispose (object);
   258   G_OBJECT_CLASS (parent_class)->dispose (object);
   279 }
   259 }
   280 
       
   281 
   260 
   282 static GstClock *
   261 static GstClock *
   283 gst_base_audio_sink_provide_clock (GstElement * elem)
   262 gst_base_audio_sink_provide_clock (GstElement * elem)
   284 {
   263 {
   285   GstBaseAudioSink *sink;
   264   GstBaseAudioSink *sink;
   316     return NULL;
   295     return NULL;
   317   }
   296   }
   318 }
   297 }
   319 
   298 
   320 static gboolean
   299 static gboolean
   321 gst_base_audio_sink_query_pad (GstPad * pad, GstQuery * query)
   300 gst_base_audio_sink_query (GstElement * element, GstQuery * query)
   322 {
   301 {
   323   gboolean res = FALSE;
   302   gboolean res = FALSE;
   324   GstBaseAudioSink *basesink;
   303 
   325 
   304   GstBaseAudioSink *basesink = GST_BASE_AUDIO_SINK (element);
   326   basesink = GST_BASE_AUDIO_SINK (gst_pad_get_parent (pad));
       
   327 
       
   328   switch (GST_QUERY_TYPE (query)) {
       
   329     case GST_QUERY_CONVERT:
       
   330     {
       
   331       GstFormat src_fmt, dest_fmt;
       
   332       gint64 src_val, dest_val;
       
   333 
       
   334       GST_LOG_OBJECT (pad, "query convert");
       
   335 
       
   336       if (basesink->ringbuffer) {
       
   337         gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, NULL);
       
   338         res = gst_ring_buffer_convert (basesink->ringbuffer, src_fmt, src_val,
       
   339             dest_fmt, &dest_val);
       
   340         if (res) {
       
   341           gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
       
   342         }
       
   343       }
       
   344       break;
       
   345     }
       
   346     default:
       
   347       break;
       
   348   }
       
   349 
       
   350   gst_object_unref (basesink);
       
   351 
       
   352   return res;
       
   353 }
       
   354 
       
   355 static gboolean
       
   356 gst_base_audio_sink_query (GstElement * element, GstQuery * query)
       
   357 {
       
   358   gboolean res = FALSE;
       
   359   GstBaseAudioSink *basesink;
       
   360 
       
   361   basesink = GST_BASE_AUDIO_SINK (element);
       
   362 
   305 
   363   switch (GST_QUERY_TYPE (query)) {
   306   switch (GST_QUERY_TYPE (query)) {
   364     case GST_QUERY_LATENCY:
   307     case GST_QUERY_LATENCY:
   365     {
   308     {
   366       gboolean live, us_live;
   309       gboolean live, us_live;
   388           spec = &basesink->ringbuffer->spec;
   331           spec = &basesink->ringbuffer->spec;
   389 
   332 
   390           basesink->priv->us_latency = min_l;
   333           basesink->priv->us_latency = min_l;
   391 
   334 
   392           min_latency =
   335           min_latency =
   393               gst_util_uint64_scale_int (spec->seglatency * spec->segsize,
   336               gst_util_uint64_scale_int (spec->segtotal * spec->segsize,
   394               GST_SECOND, spec->rate * spec->bytes_per_sample);
   337               GST_SECOND, spec->rate * spec->bytes_per_sample);
   395 
   338 
   396           /* we cannot go lower than the buffer size and the min peer latency */
   339           /* we cannot go lower than the buffer size and the min peer latency */
   397           min_latency = min_latency + min_l;
   340           min_latency = min_latency + min_l;
   398           /* the max latency is the max of the peer, we can delay an infinite
   341           /* the max latency is the max of the peer, we can delay an infinite
   404               GST_TIME_FORMAT, GST_TIME_ARGS (min_l),
   347               GST_TIME_FORMAT, GST_TIME_ARGS (min_l),
   405               GST_TIME_ARGS (min_latency));
   348               GST_TIME_ARGS (min_latency));
   406         } else {
   349         } else {
   407           GST_DEBUG_OBJECT (basesink,
   350           GST_DEBUG_OBJECT (basesink,
   408               "peer or we are not live, don't care about latency");
   351               "peer or we are not live, don't care about latency");
   409           min_latency = min_l;
   352           min_latency = 0;
   410           max_latency = max_l;
   353           max_latency = -1;
   411         }
   354         }
   412         gst_query_set_latency (query, live, min_latency, max_latency);
   355         gst_query_set_latency (query, live, min_latency, max_latency);
   413       }
   356       }
   414       break;
   357       break;
   415     }
   358     }
   416     case GST_QUERY_CONVERT:
       
   417     {
       
   418       GstFormat src_fmt, dest_fmt;
       
   419       gint64 src_val, dest_val;
       
   420 
       
   421       GST_LOG_OBJECT (basesink, "query convert");
       
   422 
       
   423       if (basesink->ringbuffer) {
       
   424         gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, NULL);
       
   425         res = gst_ring_buffer_convert (basesink->ringbuffer, src_fmt, src_val,
       
   426             dest_fmt, &dest_val);
       
   427         if (res) {
       
   428           gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
       
   429         }
       
   430       }
       
   431       break;
       
   432     }
       
   433     default:
   359     default:
   434       res = GST_ELEMENT_CLASS (parent_class)->query (element, query);
   360       res = GST_ELEMENT_CLASS (parent_class)->query (element, query);
   435       break;
   361       break;
   436   }
   362   }
   437 
   363 
   443 static GstClockTime
   369 static GstClockTime
   444 gst_base_audio_sink_get_time (GstClock * clock, GstBaseAudioSink * sink)
   370 gst_base_audio_sink_get_time (GstClock * clock, GstBaseAudioSink * sink)
   445 {
   371 {
   446   guint64 raw, samples;
   372   guint64 raw, samples;
   447   guint delay;
   373   guint delay;
   448   GstClockTime result;
   374   GstClockTime result, us_latency;
   449 
   375 
   450   if (sink->ringbuffer == NULL || sink->ringbuffer->spec.rate == 0)
   376   if (sink->ringbuffer == NULL || sink->ringbuffer->spec.rate == 0)
   451     return GST_CLOCK_TIME_NONE;
   377     return GST_CLOCK_TIME_NONE;
   452 
   378 
   453   /* our processed samples are always increasing */
   379   /* our processed samples are always increasing */
   463     samples = 0;
   389     samples = 0;
   464 
   390 
   465   result = gst_util_uint64_scale_int (samples, GST_SECOND,
   391   result = gst_util_uint64_scale_int (samples, GST_SECOND,
   466       sink->ringbuffer->spec.rate);
   392       sink->ringbuffer->spec.rate);
   467 
   393 
       
   394   /* latency before starting the clock */
       
   395   us_latency = sink->priv->us_latency;
       
   396 
       
   397   result += us_latency;
       
   398 
   468   GST_DEBUG_OBJECT (sink,
   399   GST_DEBUG_OBJECT (sink,
   469       "processed samples: raw %" G_GUINT64_FORMAT ", delay %u, real %"
   400       "processed samples: raw %llu, delay %u, real %llu, time %"
   470       G_GUINT64_FORMAT ", time %" GST_TIME_FORMAT,
   401       GST_TIME_FORMAT ", upstream latency %" GST_TIME_FORMAT, raw, delay,
   471       raw, delay, samples, GST_TIME_ARGS (result));
   402       samples, GST_TIME_ARGS (result), GST_TIME_ARGS (us_latency));
   472 
   403 
   473   return result;
   404   return result;
   474 }
   405 }
   475 
   406 
   476 /**
   407 /**
   599       gst_base_audio_sink_set_provide_clock (sink, g_value_get_boolean (value));
   530       gst_base_audio_sink_set_provide_clock (sink, g_value_get_boolean (value));
   600       break;
   531       break;
   601     case PROP_SLAVE_METHOD:
   532     case PROP_SLAVE_METHOD:
   602       gst_base_audio_sink_set_slave_method (sink, g_value_get_enum (value));
   533       gst_base_audio_sink_set_slave_method (sink, g_value_get_enum (value));
   603       break;
   534       break;
   604     case PROP_CAN_ACTIVATE_PULL:
       
   605       GST_BASE_SINK (sink)->can_activate_pull = g_value_get_boolean (value);
       
   606       break;
       
   607     default:
   535     default:
   608       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
   536       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
   609       break;
   537       break;
   610   }
   538   }
   611 }
   539 }
   629       g_value_set_boolean (value, gst_base_audio_sink_get_provide_clock (sink));
   557       g_value_set_boolean (value, gst_base_audio_sink_get_provide_clock (sink));
   630       break;
   558       break;
   631     case PROP_SLAVE_METHOD:
   559     case PROP_SLAVE_METHOD:
   632       g_value_set_enum (value, gst_base_audio_sink_get_slave_method (sink));
   560       g_value_set_enum (value, gst_base_audio_sink_get_slave_method (sink));
   633       break;
   561       break;
   634     case PROP_CAN_ACTIVATE_PULL:
       
   635       g_value_set_boolean (value, GST_BASE_SINK (sink)->can_activate_pull);
       
   636       break;
       
   637     default:
   562     default:
   638       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
   563       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
   639       break;
   564       break;
   640   }
   565   }
   641 }
   566 }
   652   spec = &sink->ringbuffer->spec;
   577   spec = &sink->ringbuffer->spec;
   653 
   578 
   654   GST_DEBUG_OBJECT (sink, "release old ringbuffer");
   579   GST_DEBUG_OBJECT (sink, "release old ringbuffer");
   655 
   580 
   656   /* release old ringbuffer */
   581   /* release old ringbuffer */
   657   gst_ring_buffer_pause (sink->ringbuffer);
       
   658   gst_ring_buffer_activate (sink->ringbuffer, FALSE);
       
   659   gst_ring_buffer_release (sink->ringbuffer);
   582   gst_ring_buffer_release (sink->ringbuffer);
   660 
   583 
   661   GST_DEBUG_OBJECT (sink, "parse caps");
   584   GST_DEBUG_OBJECT (sink, "parse caps");
   662 
   585 
   663   spec->buffer_time = sink->buffer_time;
   586   spec->buffer_time = sink->buffer_time;
   667   if (!gst_ring_buffer_parse_caps (spec, caps))
   590   if (!gst_ring_buffer_parse_caps (spec, caps))
   668     goto parse_error;
   591     goto parse_error;
   669 
   592 
   670   gst_ring_buffer_debug_spec_buff (spec);
   593   gst_ring_buffer_debug_spec_buff (spec);
   671 
   594 
   672   GST_DEBUG_OBJECT (sink, "acquire ringbuffer");
   595   GST_DEBUG_OBJECT (sink, "acquire new ringbuffer");
       
   596 
   673   if (!gst_ring_buffer_acquire (sink->ringbuffer, spec))
   597   if (!gst_ring_buffer_acquire (sink->ringbuffer, spec))
   674     goto acquire_error;
   598     goto acquire_error;
   675 
       
   676   if (bsink->pad_mode == GST_ACTIVATE_PUSH) {
       
   677     GST_DEBUG_OBJECT (sink, "activate ringbuffer");
       
   678     gst_ring_buffer_activate (sink->ringbuffer, TRUE);
       
   679   }
       
   680 
   599 
   681   /* calculate actual latency and buffer times. 
   600   /* calculate actual latency and buffer times. 
   682    * FIXME: In 0.11, store the latency_time internally in ns */
   601    * FIXME: In 0.11, store the latency_time internally in ns */
   683   spec->latency_time = gst_util_uint64_scale (spec->segsize,
   602   spec->latency_time = gst_util_uint64_scale (spec->segsize,
   684       (GST_SECOND / GST_USECOND), spec->rate * spec->bytes_per_sample);
   603       (GST_SECOND / GST_USECOND), spec->rate * spec->bytes_per_sample);
   742 
   661 
   743 /* This waits for the drain to happen and can be canceled */
   662 /* This waits for the drain to happen and can be canceled */
   744 static gboolean
   663 static gboolean
   745 gst_base_audio_sink_drain (GstBaseAudioSink * sink)
   664 gst_base_audio_sink_drain (GstBaseAudioSink * sink)
   746 {
   665 {
       
   666   GstClockTime base_time;
       
   667 
   747   if (!sink->ringbuffer)
   668   if (!sink->ringbuffer)
   748     return TRUE;
   669     return TRUE;
   749   if (!sink->ringbuffer->spec.rate)
   670   if (!sink->ringbuffer->spec.rate)
   750     return TRUE;
   671     return TRUE;
   751 
   672 
   753    * we have successfully negotiated a format and thus acquired the
   674    * we have successfully negotiated a format and thus acquired the
   754    * ringbuffer. */
   675    * ringbuffer. */
   755   if (gst_ring_buffer_is_acquired (sink->ringbuffer))
   676   if (gst_ring_buffer_is_acquired (sink->ringbuffer))
   756     gst_ring_buffer_start (sink->ringbuffer);
   677     gst_ring_buffer_start (sink->ringbuffer);
   757 
   678 
   758   if (sink->priv->eos_time != -1) {
   679   if (sink->next_sample != -1) {
       
   680     GstClockTime time;
       
   681 
       
   682     /* convert next expected sample to time */
       
   683     time =
       
   684         gst_util_uint64_scale_int (sink->next_sample, GST_SECOND,
       
   685         sink->ringbuffer->spec.rate);
       
   686 
   759     GST_DEBUG_OBJECT (sink,
   687     GST_DEBUG_OBJECT (sink,
   760         "last sample time %" GST_TIME_FORMAT,
   688         "last sample %" G_GUINT64_FORMAT ", time %" GST_TIME_FORMAT,
   761         GST_TIME_ARGS (sink->priv->eos_time));
   689         sink->next_sample, GST_TIME_ARGS (time));
       
   690 
       
   691     /* our time already includes the base_time, _wait_eos() wants a running_time
       
   692      * so we have to subtract the base_time again here. FIXME, store an
       
   693      * unadjusted EOS time so that we don't have to do this. */
       
   694     GST_OBJECT_LOCK (sink);
       
   695     base_time = GST_ELEMENT_CAST (sink)->base_time;
       
   696     GST_OBJECT_UNLOCK (sink);
       
   697 
       
   698     if (time > base_time)
       
   699       time -= base_time;
       
   700     else
       
   701       time = 0;
   762 
   702 
   763     /* wait for the EOS time to be reached, this is the time when the last
   703     /* wait for the EOS time to be reached, this is the time when the last
   764      * sample is played. */
   704      * sample is played. */
   765     gst_base_sink_wait_eos (GST_BASE_SINK (sink), sink->priv->eos_time, NULL);
   705     gst_base_sink_wait_eos (GST_BASE_SINK (sink), time, NULL);
   766 
   706 
   767     GST_DEBUG_OBJECT (sink, "drained audio");
   707     sink->next_sample = -1;
   768   }
   708   }
   769   return TRUE;
   709   return TRUE;
   770 }
   710 }
   771 
   711 
   772 static gboolean
   712 static gboolean
   781       break;
   721       break;
   782     case GST_EVENT_FLUSH_STOP:
   722     case GST_EVENT_FLUSH_STOP:
   783       /* always resync on sample after a flush */
   723       /* always resync on sample after a flush */
   784       sink->priv->avg_skew = -1;
   724       sink->priv->avg_skew = -1;
   785       sink->next_sample = -1;
   725       sink->next_sample = -1;
   786       sink->priv->eos_time = -1;
       
   787       if (sink->ringbuffer)
   726       if (sink->ringbuffer)
   788         gst_ring_buffer_set_flushing (sink->ringbuffer, FALSE);
   727         gst_ring_buffer_set_flushing (sink->ringbuffer, FALSE);
   789       break;
   728       break;
   790     case GST_EVENT_EOS:
   729     case GST_EVENT_EOS:
   791       /* now wait till we played everything */
   730       /* now wait till we played everything */
   862   return sample;
   801   return sample;
   863 }
   802 }
   864 
   803 
   865 static GstClockTime
   804 static GstClockTime
   866 clock_convert_external (GstClockTime external, GstClockTime cinternal,
   805 clock_convert_external (GstClockTime external, GstClockTime cinternal,
   867     GstClockTime cexternal, GstClockTime crate_num, GstClockTime crate_denom)
   806     GstClockTime cexternal, GstClockTime crate_num, GstClockTime crate_denom,
       
   807     GstClockTime us_latency)
   868 {
   808 {
   869   /* adjust for rate and speed */
   809   /* adjust for rate and speed */
   870   if (external >= cexternal) {
   810   if (external >= cexternal) {
   871     external =
   811     external =
   872         gst_util_uint64_scale (external - cexternal, crate_denom, crate_num);
   812         gst_util_uint64_scale (external - cexternal, crate_denom, crate_num);
   873     external += cinternal;
   813     external += cinternal;
   874   } else {
   814   } else {
   875     external =
   815     external = gst_util_uint64_scale (cexternal - external,
   876         gst_util_uint64_scale (cexternal - external, crate_denom, crate_num);
   816         crate_denom, crate_num);
   877     if (cinternal > external)
   817     if (cinternal > external)
   878       external = cinternal - external;
   818       external = cinternal - external;
   879     else
   819     else
   880       external = 0;
   820       external = 0;
   881   }
   821   }
       
   822   /* adjust for offset when slaving started */
       
   823   if (external > us_latency)
       
   824     external -= us_latency;
       
   825   else
       
   826     external = 0;
       
   827 
   882   return external;
   828   return external;
   883 }
   829 }
   884 
   830 
   885 /* algorithm to calculate sample positions that will result in resampling to
   831 /* algorithm to calculate sample positions that will result in resampling to
   886  * match the clock rate of the master */
   832  * match the clock rate of the master */
   890     GstClockTime * srender_start, GstClockTime * srender_stop)
   836     GstClockTime * srender_start, GstClockTime * srender_stop)
   891 {
   837 {
   892   GstClockTime cinternal, cexternal;
   838   GstClockTime cinternal, cexternal;
   893   GstClockTime crate_num, crate_denom;
   839   GstClockTime crate_num, crate_denom;
   894 
   840 
   895   /* FIXME, we can sample and add observations here or use the timeouts on the
       
   896    * clock. No idea which one is better or more stable. The timeout seems more
       
   897    * arbitrary but this one seems more demanding and does not work when there is
       
   898    * no data comming in to the sink. */
       
   899 #if 0
       
   900   GstClockTime etime, itime;
       
   901   gdouble r_squared;
       
   902 
       
   903   /* sample clocks and figure out clock skew */
       
   904   etime = gst_clock_get_time (GST_ELEMENT_CLOCK (sink));
       
   905   itime = gst_audio_clock_get_time (sink->provided_clock);
       
   906 
       
   907   /* add new observation */
       
   908   gst_clock_add_observation (sink->provided_clock, itime, etime, &r_squared);
       
   909 #endif
       
   910 
       
   911   /* get calibration parameters to compensate for speed and offset differences
   841   /* get calibration parameters to compensate for speed and offset differences
   912    * when we are slaved */
   842    * when we are slaved */
   913   gst_clock_get_calibration (sink->provided_clock, &cinternal, &cexternal,
   843   gst_clock_get_calibration (sink->provided_clock, &cinternal, &cexternal,
   914       &crate_num, &crate_denom);
   844       &crate_num, &crate_denom);
   915 
   845 
   922   if (crate_num == 0)
   852   if (crate_num == 0)
   923     crate_denom = crate_num = 1;
   853     crate_denom = crate_num = 1;
   924 
   854 
   925   /* bring external time to internal time */
   855   /* bring external time to internal time */
   926   render_start = clock_convert_external (render_start, cinternal, cexternal,
   856   render_start = clock_convert_external (render_start, cinternal, cexternal,
   927       crate_num, crate_denom);
   857       crate_num, crate_denom, sink->priv->us_latency);
   928   render_stop = clock_convert_external (render_stop, cinternal, cexternal,
   858   render_stop = clock_convert_external (render_stop, cinternal, cexternal,
   929       crate_num, crate_denom);
   859       crate_num, crate_denom, sink->priv->us_latency);
   930 
   860 
   931   GST_DEBUG_OBJECT (sink,
   861   GST_DEBUG_OBJECT (sink,
   932       "after slaving: start %" GST_TIME_FORMAT " - stop %" GST_TIME_FORMAT,
   862       "after slaving: start %" GST_TIME_FORMAT " - stop %" GST_TIME_FORMAT,
   933       GST_TIME_ARGS (render_start), GST_TIME_ARGS (render_stop));
   863       GST_TIME_ARGS (render_start), GST_TIME_ARGS (render_stop));
   934 
   864 
   953   gst_clock_get_calibration (sink->provided_clock, &cinternal, &cexternal,
   883   gst_clock_get_calibration (sink->provided_clock, &cinternal, &cexternal,
   954       &crate_num, &crate_denom);
   884       &crate_num, &crate_denom);
   955 
   885 
   956   /* sample clocks and figure out clock skew */
   886   /* sample clocks and figure out clock skew */
   957   etime = gst_clock_get_time (GST_ELEMENT_CLOCK (sink));
   887   etime = gst_clock_get_time (GST_ELEMENT_CLOCK (sink));
   958   itime = gst_audio_clock_get_time (sink->provided_clock);
   888   itime = gst_clock_get_internal_time (sink->provided_clock);
   959 
   889 
   960   GST_DEBUG_OBJECT (sink,
   890   etime -= cexternal;
   961       "internal %" GST_TIME_FORMAT " external %" GST_TIME_FORMAT
   891   itime -= cinternal;
   962       " cinternal %" GST_TIME_FORMAT " cexternal %" GST_TIME_FORMAT,
   892 
   963       GST_TIME_ARGS (itime), GST_TIME_ARGS (etime),
       
   964       GST_TIME_ARGS (cinternal), GST_TIME_ARGS (cexternal));
       
   965 
       
   966   /* make sure we never go below 0 */
       
   967   etime = etime > cexternal ? etime - cexternal : 0;
       
   968   itime = itime > cinternal ? itime - cinternal : 0;
       
   969 
       
   970   /* do itime - etime.
       
   971    * positive value means external clock goes slower
       
   972    * negative value means external clock goes faster */
       
   973   skew = GST_CLOCK_DIFF (etime, itime);
   893   skew = GST_CLOCK_DIFF (etime, itime);
   974   if (sink->priv->avg_skew == -1) {
   894   if (sink->priv->avg_skew == -1) {
   975     /* first observation */
   895     /* first observation */
   976     sink->priv->avg_skew = skew;
   896     sink->priv->avg_skew = skew;
   977   } else {
   897   } else {
   991   if (sink->priv->avg_skew > segtime2) {
   911   if (sink->priv->avg_skew > segtime2) {
   992     /* master is running slower, move internal time forward */
   912     /* master is running slower, move internal time forward */
   993     GST_WARNING_OBJECT (sink,
   913     GST_WARNING_OBJECT (sink,
   994         "correct clock skew %" G_GINT64_FORMAT " > %" G_GINT64_FORMAT,
   914         "correct clock skew %" G_GINT64_FORMAT " > %" G_GINT64_FORMAT,
   995         sink->priv->avg_skew, segtime2);
   915         sink->priv->avg_skew, segtime2);
   996     cexternal = cexternal > segtime ? cexternal - segtime : 0;
   916     cinternal += segtime;
   997     sink->priv->avg_skew -= segtime;
   917     sink->priv->avg_skew -= segtime;
   998 
   918 
   999     segsamples =
   919     segsamples =
  1000         sink->ringbuffer->spec.segsize /
   920         sink->ringbuffer->spec.segsize /
  1001         sink->ringbuffer->spec.bytes_per_sample;
   921         sink->ringbuffer->spec.bytes_per_sample;
  1038         crate_num, crate_denom);
   958         crate_num, crate_denom);
  1039   }
   959   }
  1040 
   960 
  1041   /* convert, ignoring speed */
   961   /* convert, ignoring speed */
  1042   render_start = clock_convert_external (render_start, cinternal, cexternal,
   962   render_start = clock_convert_external (render_start, cinternal, cexternal,
  1043       crate_num, crate_denom);
   963       crate_num, crate_denom, sink->priv->us_latency);
  1044   render_stop = clock_convert_external (render_stop, cinternal, cexternal,
   964   render_stop = clock_convert_external (render_stop, cinternal, cexternal,
  1045       crate_num, crate_denom);
   965       crate_num, crate_denom, sink->priv->us_latency);
  1046 
   966 
  1047   *srender_start = render_start;
   967   *srender_start = render_start;
  1048   *srender_stop = render_stop;
   968   *srender_stop = render_stop;
  1049 }
   969 }
  1050 
   970 
  1060   gst_clock_get_calibration (sink->provided_clock, &cinternal, &cexternal,
   980   gst_clock_get_calibration (sink->provided_clock, &cinternal, &cexternal,
  1061       &crate_num, &crate_denom);
   981       &crate_num, &crate_denom);
  1062 
   982 
  1063   /* convert, ignoring speed */
   983   /* convert, ignoring speed */
  1064   render_start = clock_convert_external (render_start, cinternal, cexternal,
   984   render_start = clock_convert_external (render_start, cinternal, cexternal,
  1065       crate_num, crate_denom);
   985       crate_num, crate_denom, sink->priv->us_latency);
  1066   render_stop = clock_convert_external (render_stop, cinternal, cexternal,
   986   render_stop = clock_convert_external (render_stop, cinternal, cexternal,
  1067       crate_num, crate_denom);
   987       crate_num, crate_denom, sink->priv->us_latency);
  1068 
   988 
  1069   *srender_start = render_start;
   989   *srender_start = render_start;
  1070   *srender_stop = render_stop;
   990   *srender_stop = render_stop;
  1071 }
   991 }
  1072 
   992 
  1093       g_warning ("unknown slaving method %d", sink->priv->slave_method);
  1013       g_warning ("unknown slaving method %d", sink->priv->slave_method);
  1094       break;
  1014       break;
  1095   }
  1015   }
  1096 }
  1016 }
  1097 
  1017 
  1098 /* must be called with LOCK */
       
  1099 static GstFlowReturn
       
  1100 gst_base_audio_sink_sync_latency (GstBaseSink * bsink, GstMiniObject * obj)
       
  1101 {
       
  1102   GstClock *clock;
       
  1103   GstClockReturn status;
       
  1104   GstClockTime time;
       
  1105   GstFlowReturn ret;
       
  1106   GstBaseAudioSink *sink;
       
  1107   GstClockTime itime, etime;
       
  1108   GstClockTime rate_num, rate_denom;
       
  1109   GstClockTimeDiff jitter;
       
  1110 
       
  1111   sink = GST_BASE_AUDIO_SINK (bsink);
       
  1112 
       
  1113   clock = GST_ELEMENT_CLOCK (sink);
       
  1114   if (G_UNLIKELY (clock == NULL))
       
  1115     goto no_clock;
       
  1116 
       
  1117   /* we provided the global clock, don't need to do anything special */
       
  1118   if (clock == sink->provided_clock)
       
  1119     goto no_slaving;
       
  1120 
       
  1121   GST_OBJECT_UNLOCK (sink);
       
  1122 
       
  1123   do {
       
  1124     GST_DEBUG_OBJECT (sink, "checking preroll");
       
  1125 
       
  1126     ret = gst_base_sink_do_preroll (bsink, obj);
       
  1127     if (ret != GST_FLOW_OK)
       
  1128       goto flushing;
       
  1129 
       
  1130     GST_OBJECT_LOCK (sink);
       
  1131     time = sink->priv->us_latency;
       
  1132     GST_OBJECT_UNLOCK (sink);
       
  1133 
       
  1134     /* preroll done, we can sync since we are in PLAYING now. */
       
  1135     GST_DEBUG_OBJECT (sink, "possibly waiting for clock to reach %"
       
  1136         GST_TIME_FORMAT, GST_TIME_ARGS (time));
       
  1137 
       
  1138     /* wait for the clock, this can be interrupted because we got shut down or 
       
  1139      * we PAUSED. */
       
  1140     status = gst_base_sink_wait_clock (bsink, time, &jitter);
       
  1141 
       
  1142     GST_DEBUG_OBJECT (sink, "clock returned %d %" GST_TIME_FORMAT, status,
       
  1143         GST_TIME_ARGS (jitter));
       
  1144 
       
  1145     /* invalid time, no clock or sync disabled, just continue then */
       
  1146     if (status == GST_CLOCK_BADTIME)
       
  1147       break;
       
  1148 
       
  1149     /* waiting could have been interrupted and we can be flushing now */
       
  1150     if (G_UNLIKELY (bsink->flushing))
       
  1151       goto flushing;
       
  1152 
       
  1153     /* retry if we got unscheduled, which means we did not reach the timeout
       
  1154      * yet. if some other error occures, we continue. */
       
  1155   } while (status == GST_CLOCK_UNSCHEDULED);
       
  1156 
       
  1157   GST_OBJECT_LOCK (sink);
       
  1158   GST_DEBUG_OBJECT (sink, "latency synced");
       
  1159 
       
  1160   /* when we prerolled in time, we can accurately set the calibration,
       
  1161    * our internal clock should exactly have been the latency (== the running
       
  1162    * time of the external clock) */
       
  1163   etime = GST_ELEMENT_CAST (sink)->base_time + time;
       
  1164   itime = gst_audio_clock_get_time (sink->provided_clock);
       
  1165 
       
  1166   if (status == GST_CLOCK_EARLY) {
       
  1167     /* when we prerolled late, we have to take into account the lateness */
       
  1168     GST_DEBUG_OBJECT (sink, "late preroll, adding jitter");
       
  1169     etime += jitter;
       
  1170   }
       
  1171 
       
  1172   /* start ringbuffer so we can start slaving right away when we need to */
       
  1173   gst_ring_buffer_start (sink->ringbuffer);
       
  1174 
       
  1175   GST_DEBUG_OBJECT (sink,
       
  1176       "internal time: %" GST_TIME_FORMAT " external time: %" GST_TIME_FORMAT,
       
  1177       GST_TIME_ARGS (itime), GST_TIME_ARGS (etime));
       
  1178 
       
  1179   /* copy the original calibrated rate but update the internal and external
       
  1180    * times. */
       
  1181   gst_clock_get_calibration (sink->provided_clock, NULL, NULL, &rate_num,
       
  1182       &rate_denom);
       
  1183   gst_clock_set_calibration (sink->provided_clock, itime, etime,
       
  1184       rate_num, rate_denom);
       
  1185 
       
  1186   switch (sink->priv->slave_method) {
       
  1187     case GST_BASE_AUDIO_SINK_SLAVE_RESAMPLE:
       
  1188       /* only set as master when we are resampling */
       
  1189       GST_DEBUG_OBJECT (sink, "Setting clock as master");
       
  1190       gst_clock_set_master (sink->provided_clock, clock);
       
  1191       break;
       
  1192     case GST_BASE_AUDIO_SINK_SLAVE_SKEW:
       
  1193     case GST_BASE_AUDIO_SINK_SLAVE_NONE:
       
  1194     default:
       
  1195       break;
       
  1196   }
       
  1197 
       
  1198   sink->priv->avg_skew = -1;
       
  1199   sink->next_sample = -1;
       
  1200   sink->priv->eos_time = -1;
       
  1201 
       
  1202   return GST_FLOW_OK;
       
  1203 
       
  1204   /* ERRORS */
       
  1205 no_clock:
       
  1206   {
       
  1207     GST_DEBUG_OBJECT (sink, "we have no clock");
       
  1208     return GST_FLOW_OK;
       
  1209   }
       
  1210 no_slaving:
       
  1211   {
       
  1212     GST_DEBUG_OBJECT (sink, "we are not slaved");
       
  1213     return GST_FLOW_OK;
       
  1214   }
       
  1215 flushing:
       
  1216   {
       
  1217     GST_DEBUG_OBJECT (sink, "we are flushing");
       
  1218     GST_OBJECT_LOCK (sink);
       
  1219     return GST_FLOW_WRONG_STATE;
       
  1220   }
       
  1221 }
       
  1222 
       
  1223 static GstFlowReturn
  1018 static GstFlowReturn
  1224 gst_base_audio_sink_render (GstBaseSink * bsink, GstBuffer * buf)
  1019 gst_base_audio_sink_render (GstBaseSink * bsink, GstBuffer * buf)
  1225 {
  1020 {
  1226   guint64 in_offset;
  1021   guint64 in_offset;
  1227   GstClockTime time, stop, render_start, render_stop, sample_offset;
  1022   GstClockTime time, stop, render_start, render_stop, sample_offset;
  1228   GstClockTimeDiff sync_offset, ts_offset;
       
  1229   GstBaseAudioSink *sink;
  1023   GstBaseAudioSink *sink;
  1230   GstRingBuffer *ringbuf;
  1024   GstRingBuffer *ringbuf;
  1231   gint64 diff, align, ctime, cstop;
  1025   gint64 diff, align, ctime, cstop;
  1232   guint8 *data;
  1026   guint8 *data;
  1233   guint size;
  1027   guint size;
  1234   guint samples, written;
  1028   guint samples, written;
  1235   gint bps;
  1029   gint bps;
  1236   gint accum;
  1030   gint accum;
  1237   gint out_samples;
  1031   gint out_samples;
  1238   GstClockTime base_time, render_delay, latency;
  1032   GstClockTime base_time = GST_CLOCK_TIME_NONE, latency;
  1239   GstClock *clock;
  1033   GstClock *clock;
  1240   gboolean sync, slaved, align_next;
  1034   gboolean sync, slaved, align_next;
  1241   GstFlowReturn ret;
       
  1242   GstSegment clip_seg;
       
  1243 
  1035 
  1244   sink = GST_BASE_AUDIO_SINK (bsink);
  1036   sink = GST_BASE_AUDIO_SINK (bsink);
  1245 
  1037 
  1246   ringbuf = sink->ringbuffer;
  1038   ringbuf = sink->ringbuffer;
  1247 
  1039 
  1248   /* can't do anything when we don't have the device */
  1040   /* can't do anything when we don't have the device */
  1249   if (G_UNLIKELY (!gst_ring_buffer_is_acquired (ringbuf)))
  1041   if (G_UNLIKELY (!gst_ring_buffer_is_acquired (ringbuf)))
  1250     goto wrong_state;
  1042     goto wrong_state;
  1251 
  1043 
  1252   /* Wait for upstream latency before starting the ringbuffer, we do this so
       
  1253    * that we can align the first sample of the ringbuffer to the base_time +
       
  1254    * latency. */
       
  1255   GST_OBJECT_LOCK (sink);
       
  1256   base_time = GST_ELEMENT_CAST (sink)->base_time;
       
  1257   if (G_UNLIKELY (sink->priv->sync_latency)) {
       
  1258     ret = gst_base_audio_sink_sync_latency (bsink, GST_MINI_OBJECT_CAST (buf));
       
  1259     GST_OBJECT_UNLOCK (sink);
       
  1260     if (G_UNLIKELY (ret != GST_FLOW_OK))
       
  1261       goto sync_latency_failed;
       
  1262     /* only do this once until we are set back to PLAYING */
       
  1263     sink->priv->sync_latency = FALSE;
       
  1264   } else {
       
  1265     GST_OBJECT_UNLOCK (sink);
       
  1266   }
       
  1267 
       
  1268   bps = ringbuf->spec.bytes_per_sample;
  1044   bps = ringbuf->spec.bytes_per_sample;
  1269 
  1045 
  1270   size = GST_BUFFER_SIZE (buf);
  1046   size = GST_BUFFER_SIZE (buf);
  1271   if (G_UNLIKELY (size % bps) != 0)
  1047   if (G_UNLIKELY (size % bps) != 0)
  1272     goto wrong_size;
  1048     goto wrong_size;
  1274   samples = size / bps;
  1050   samples = size / bps;
  1275   out_samples = samples;
  1051   out_samples = samples;
  1276 
  1052 
  1277   in_offset = GST_BUFFER_OFFSET (buf);
  1053   in_offset = GST_BUFFER_OFFSET (buf);
  1278   time = GST_BUFFER_TIMESTAMP (buf);
  1054   time = GST_BUFFER_TIMESTAMP (buf);
       
  1055   stop = time + gst_util_uint64_scale_int (samples, GST_SECOND,
       
  1056       ringbuf->spec.rate);
  1279 
  1057 
  1280   GST_DEBUG_OBJECT (sink,
  1058   GST_DEBUG_OBJECT (sink,
  1281       "time %" GST_TIME_FORMAT ", offset %" G_GUINT64_FORMAT ", start %"
  1059       "time %" GST_TIME_FORMAT ", offset %llu, start %" GST_TIME_FORMAT
  1282       GST_TIME_FORMAT ", samples %u", GST_TIME_ARGS (time), in_offset,
  1060       ", samples %u", GST_TIME_ARGS (time), in_offset,
  1283       GST_TIME_ARGS (bsink->segment.start), samples);
  1061       GST_TIME_ARGS (bsink->segment.start), samples);
  1284 
  1062 
  1285   data = GST_BUFFER_DATA (buf);
  1063   data = GST_BUFFER_DATA (buf);
  1286 
  1064 
  1287   /* if not valid timestamp or we can't clip or sync, try to play
  1065   /* if not valid timestamp or we can't clip or sync, try to play
  1290     render_start = gst_base_audio_sink_get_offset (sink);
  1068     render_start = gst_base_audio_sink_get_offset (sink);
  1291     render_stop = render_start + samples;
  1069     render_stop = render_start + samples;
  1292     GST_DEBUG_OBJECT (sink,
  1070     GST_DEBUG_OBJECT (sink,
  1293         "Buffer of size %u has no time. Using render_start=%" G_GUINT64_FORMAT,
  1071         "Buffer of size %u has no time. Using render_start=%" G_GUINT64_FORMAT,
  1294         GST_BUFFER_SIZE (buf), render_start);
  1072         GST_BUFFER_SIZE (buf), render_start);
  1295     /* we don't have a start so we don't know stop either */
       
  1296     stop = -1;
       
  1297     goto no_sync;
  1073     goto no_sync;
  1298   }
       
  1299 
       
  1300   /* let's calc stop based on the number of samples in the buffer instead
       
  1301    * of trusting the DURATION */
       
  1302   stop = time + gst_util_uint64_scale_int (samples, GST_SECOND,
       
  1303       ringbuf->spec.rate);
       
  1304 
       
  1305   /* prepare the clipping segment. Since we will be subtracting ts-offset and
       
  1306    * device-delay later we scale the start and stop with those values so that we
       
  1307    * can correctly clip them */
       
  1308   clip_seg.format = GST_FORMAT_TIME;
       
  1309   clip_seg.start = bsink->segment.start;
       
  1310   clip_seg.stop = bsink->segment.stop;
       
  1311   clip_seg.duration = -1;
       
  1312 
       
  1313   /* the sync offset is the combination of ts-offset and device-delay */
       
  1314   latency = gst_base_sink_get_latency (bsink);
       
  1315   ts_offset = gst_base_sink_get_ts_offset (bsink);
       
  1316   render_delay = gst_base_sink_get_render_delay (bsink);
       
  1317   sync_offset = ts_offset - render_delay + latency;
       
  1318 
       
  1319   GST_DEBUG_OBJECT (sink,
       
  1320       "sync-offset %" G_GINT64_FORMAT ", render-delay %" GST_TIME_FORMAT
       
  1321       ", ts-offset %" G_GINT64_FORMAT, sync_offset,
       
  1322       GST_TIME_ARGS (render_delay), ts_offset);
       
  1323 
       
  1324   /* compensate for ts-offset and device-delay when negative we need to
       
  1325    * clip. */
       
  1326   if (sync_offset < 0) {
       
  1327     clip_seg.start += -sync_offset;
       
  1328     if (clip_seg.stop != -1)
       
  1329       clip_seg.stop += -sync_offset;
       
  1330   }
  1074   }
  1331 
  1075 
  1332   /* samples should be rendered based on their timestamp. All samples
  1076   /* samples should be rendered based on their timestamp. All samples
  1333    * arriving before the segment.start or after segment.stop are to be 
  1077    * arriving before the segment.start or after segment.stop are to be 
  1334    * thrown away. All samples should also be clipped to the segment 
  1078    * thrown away. All samples should also be clipped to the segment 
  1335    * boundaries */
  1079    * boundaries */
  1336   if (!gst_segment_clip (&clip_seg, GST_FORMAT_TIME, time, stop, &ctime,
  1080   /* let's calc stop based on the number of samples in the buffer instead
       
  1081    * of trusting the DURATION */
       
  1082   if (!gst_segment_clip (&bsink->segment, GST_FORMAT_TIME, time, stop, &ctime,
  1337           &cstop))
  1083           &cstop))
  1338     goto out_of_segment;
  1084     goto out_of_segment;
  1339 
  1085 
  1340   /* see if some clipping happened */
  1086   /* see if some clipping happened */
  1341   diff = ctime - time;
  1087   diff = ctime - time;
  1381 
  1127 
  1382   GST_DEBUG_OBJECT (sink,
  1128   GST_DEBUG_OBJECT (sink,
  1383       "running: start %" GST_TIME_FORMAT " - stop %" GST_TIME_FORMAT,
  1129       "running: start %" GST_TIME_FORMAT " - stop %" GST_TIME_FORMAT,
  1384       GST_TIME_ARGS (render_start), GST_TIME_ARGS (render_stop));
  1130       GST_TIME_ARGS (render_start), GST_TIME_ARGS (render_stop));
  1385 
  1131 
  1386   /* store the time of the last sample, we'll use this to perform sync on the
  1132   base_time = gst_element_get_base_time (GST_ELEMENT_CAST (bsink));
  1387    * last sample when draining the buffer */
  1133 
  1388   if (bsink->segment.rate >= 0.0) {
  1134   GST_DEBUG_OBJECT (sink, "base_time %" GST_TIME_FORMAT,
  1389     sink->priv->eos_time = render_stop;
       
  1390   } else {
       
  1391     sink->priv->eos_time = render_start;
       
  1392   }
       
  1393 
       
  1394   /* compensate for ts-offset and delay we know this will not underflow because we
       
  1395    * clipped above. */
       
  1396   GST_DEBUG_OBJECT (sink,
       
  1397       "compensating for sync-offset %" GST_TIME_FORMAT,
       
  1398       GST_TIME_ARGS (sync_offset));
       
  1399   render_start += sync_offset;
       
  1400   render_stop += sync_offset;
       
  1401 
       
  1402   GST_DEBUG_OBJECT (sink, "adding base_time %" GST_TIME_FORMAT,
       
  1403       GST_TIME_ARGS (base_time));
  1135       GST_TIME_ARGS (base_time));
  1404 
  1136 
  1405   /* add base time to sync against the clock */
  1137   /* add base time to sync against the clock */
  1406   render_start += base_time;
  1138   render_start += base_time;
  1407   render_stop += base_time;
  1139   render_stop += base_time;
  1408 
  1140 
       
  1141   /* compensate for latency */
       
  1142   latency = gst_base_sink_get_latency (bsink);
  1409   GST_DEBUG_OBJECT (sink,
  1143   GST_DEBUG_OBJECT (sink,
  1410       "after compensation: start %" GST_TIME_FORMAT " - stop %" GST_TIME_FORMAT,
  1144       "compensating for latency %" GST_TIME_FORMAT, GST_TIME_ARGS (latency));
       
  1145 
       
  1146   /* add latency to get the timestamp to sync against the pipeline clock */
       
  1147   render_start += latency;
       
  1148   render_stop += latency;
       
  1149 
       
  1150   GST_DEBUG_OBJECT (sink,
       
  1151       "after latency: start %" GST_TIME_FORMAT " - stop %" GST_TIME_FORMAT,
  1411       GST_TIME_ARGS (render_start), GST_TIME_ARGS (render_stop));
  1152       GST_TIME_ARGS (render_start), GST_TIME_ARGS (render_stop));
  1412 
  1153 
  1413   if ((slaved = clock != sink->provided_clock)) {
  1154   if ((slaved = clock != sink->provided_clock)) {
  1414     /* handle clock slaving */
  1155     /* handle clock slaving */
  1415     gst_base_audio_sink_handle_slaving (sink, render_start, render_stop,
  1156     gst_base_audio_sink_handle_slaving (sink, render_start, render_stop,
  1416         &render_start, &render_stop);
       
  1417   } else {
       
  1418     /* no slaving needed but we need to adapt to the clock calibration
       
  1419      * parameters */
       
  1420     gst_base_audio_sink_none_slaving (sink, render_start, render_stop,
       
  1421         &render_start, &render_stop);
  1157         &render_start, &render_stop);
  1422   }
  1158   }
  1423 
  1159 
  1424   /* and bring the time to the rate corrected offset in the buffer */
  1160   /* and bring the time to the rate corrected offset in the buffer */
  1425   render_start = gst_util_uint64_scale_int (render_start,
  1161   render_start = gst_util_uint64_scale_int (render_start,
  1426       ringbuf->spec.rate, GST_SECOND);
  1162       ringbuf->spec.rate, GST_SECOND);
  1427   render_stop = gst_util_uint64_scale_int (render_stop,
  1163   render_stop = gst_util_uint64_scale_int (render_stop,
  1428       ringbuf->spec.rate, GST_SECOND);
  1164       ringbuf->spec.rate, GST_SECOND);
  1429 
  1165 
  1430   /* positive playback rate, first sample is render_start, negative rate, first
       
  1431    * sample is render_stop. When no rate conversion is active, render exactly
       
  1432    * the amount of input samples to avoid aligning to rounding errors. */
       
  1433   if (bsink->segment.rate >= 0.0) {
       
  1434     sample_offset = render_start;
       
  1435     if (bsink->segment.rate == 1.0)
       
  1436       render_stop = sample_offset + samples;
       
  1437   } else {
       
  1438     sample_offset = render_stop;
       
  1439     if (bsink->segment.rate == -1.0)
       
  1440       render_start = sample_offset + samples;
       
  1441   }
       
  1442 
       
  1443   /* always resync after a discont */
  1166   /* always resync after a discont */
  1444   if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DISCONT))) {
  1167   if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DISCONT))) {
  1445     GST_DEBUG_OBJECT (sink, "resync after discont");
  1168     GST_DEBUG_OBJECT (sink, "resync after discont");
  1446     goto no_align;
  1169     goto no_align;
  1447   }
  1170   }
  1448 
  1171 
  1449   /* resync when we don't know what to align the sample with */
       
  1450   if (G_UNLIKELY (sink->next_sample == -1)) {
  1172   if (G_UNLIKELY (sink->next_sample == -1)) {
  1451     GST_DEBUG_OBJECT (sink,
  1173     GST_DEBUG_OBJECT (sink,
  1452         "no align possible: no previous sample position known");
  1174         "no align possible: no previous sample position known");
  1453     goto no_align;
  1175     goto no_align;
  1454   }
  1176   }
  1455 
  1177 
  1456   /* now try to align the sample to the previous one, first see how big the
  1178   /* positive playback rate, first sample is render_start, negative rate, first
  1457    * difference is. */
  1179    * sample is render_stop */
       
  1180   if (bsink->segment.rate >= 1.0)
       
  1181     sample_offset = render_start;
       
  1182   else
       
  1183     sample_offset = render_stop;
       
  1184 
       
  1185   /* now try to align the sample to the previous one */
  1458   if (sample_offset >= sink->next_sample)
  1186   if (sample_offset >= sink->next_sample)
  1459     diff = sample_offset - sink->next_sample;
  1187     diff = sample_offset - sink->next_sample;
  1460   else
  1188   else
  1461     diff = sink->next_sample - sample_offset;
  1189     diff = sink->next_sample - sample_offset;
  1462 
  1190 
  1498   /* number of target samples is difference between start and stop */
  1226   /* number of target samples is difference between start and stop */
  1499   out_samples = render_stop - render_start;
  1227   out_samples = render_stop - render_start;
  1500 
  1228 
  1501 no_sync:
  1229 no_sync:
  1502   /* we render the first or last sample first, depending on the rate */
  1230   /* we render the first or last sample first, depending on the rate */
  1503   if (bsink->segment.rate >= 0.0)
  1231   if (bsink->segment.rate >= 1.0)
  1504     sample_offset = render_start;
  1232     sample_offset = render_start;
  1505   else
  1233   else
  1506     sample_offset = render_stop;
  1234     sample_offset = render_stop;
  1507 
  1235 
  1508   GST_DEBUG_OBJECT (sink, "rendering at %" G_GUINT64_FORMAT " %d/%d",
  1236   GST_DEBUG_OBJECT (sink, "rendering at %" G_GUINT64_FORMAT " %d/%d",
  1520     /* if we wrote all, we're done */
  1248     /* if we wrote all, we're done */
  1521     if (written == samples)
  1249     if (written == samples)
  1522       break;
  1250       break;
  1523 
  1251 
  1524     /* else something interrupted us and we wait for preroll. */
  1252     /* else something interrupted us and we wait for preroll. */
  1525     if ((ret = gst_base_sink_wait_preroll (bsink)) != GST_FLOW_OK)
  1253     if (gst_base_sink_wait_preroll (bsink) != GST_FLOW_OK)
  1526       goto stopping;
  1254       goto stopping;
  1527 
  1255 
  1528     /* if we got interrupted, we cannot assume that the next sample should
  1256     /* if we got interrupted, we cannot assume that the next sample should
  1529      * be aligned to this one */
  1257      * be aligned to this one */
  1530     align_next = FALSE;
  1258     align_next = FALSE;
  1531 
       
  1532     /* update the output samples. FIXME, this will just skip them when pausing
       
  1533      * during trick mode */
       
  1534     if (out_samples > written) {
       
  1535       out_samples -= written;
       
  1536       accum = 0;
       
  1537     } else
       
  1538       break;
       
  1539 
  1259 
  1540     samples -= written;
  1260     samples -= written;
  1541     data += written * bps;
  1261     data += written * bps;
  1542   } while (TRUE);
  1262   } while (TRUE);
  1543 
  1263 
  1580         (NULL), ("sink received buffer of wrong size."));
  1300         (NULL), ("sink received buffer of wrong size."));
  1581     return GST_FLOW_ERROR;
  1301     return GST_FLOW_ERROR;
  1582   }
  1302   }
  1583 stopping:
  1303 stopping:
  1584   {
  1304   {
  1585     GST_DEBUG_OBJECT (sink, "preroll got interrupted: %d (%s)", ret,
  1305     GST_DEBUG_OBJECT (sink, "ringbuffer is stopping");
  1586         gst_flow_get_name (ret));
  1306     return GST_FLOW_WRONG_STATE;
  1587     return ret;
       
  1588   }
       
  1589 sync_latency_failed:
       
  1590   {
       
  1591     GST_DEBUG_OBJECT (sink, "failed waiting for latency");
       
  1592     return ret;
       
  1593   }
  1307   }
  1594 }
  1308 }
  1595 
  1309 
  1596 /**
  1310 /**
  1597  * gst_base_audio_sink_create_ringbuffer:
  1311  * gst_base_audio_sink_create_ringbuffer:
  1621     gst_object_set_parent (GST_OBJECT (buffer), GST_OBJECT (sink));
  1335     gst_object_set_parent (GST_OBJECT (buffer), GST_OBJECT (sink));
  1622 
  1336 
  1623   return buffer;
  1337   return buffer;
  1624 }
  1338 }
  1625 
  1339 
       
  1340 static gboolean
       
  1341 gst_base_audio_sink_activate_pull (GstBaseSink * basesink, gboolean active)
       
  1342 {
       
  1343   gboolean ret;
       
  1344   GstBaseAudioSink *sink = GST_BASE_AUDIO_SINK (basesink);
       
  1345 
       
  1346   if (active) {
       
  1347     gst_ring_buffer_set_callback (sink->ringbuffer,
       
  1348         gst_base_audio_sink_callback, sink);
       
  1349     ret = gst_ring_buffer_start (sink->ringbuffer);
       
  1350   } else {
       
  1351     gst_ring_buffer_set_callback (sink->ringbuffer, NULL, NULL);
       
  1352     /* stop thread */
       
  1353     ret = gst_ring_buffer_release (sink->ringbuffer);
       
  1354   }
       
  1355 
       
  1356   return ret;
       
  1357 }
       
  1358 
  1626 static void
  1359 static void
  1627 gst_base_audio_sink_callback (GstRingBuffer * rbuf, guint8 * data, guint len,
  1360 gst_base_audio_sink_callback (GstRingBuffer * rbuf, guint8 * data, guint len,
  1628     gpointer user_data)
  1361     gpointer user_data)
  1629 {
  1362 {
  1630   GstBaseSink *basesink;
  1363   GstBaseSink *basesink;
  1633   GstFlowReturn ret;
  1366   GstFlowReturn ret;
  1634 
  1367 
  1635   basesink = GST_BASE_SINK (user_data);
  1368   basesink = GST_BASE_SINK (user_data);
  1636   sink = GST_BASE_AUDIO_SINK (user_data);
  1369   sink = GST_BASE_AUDIO_SINK (user_data);
  1637 
  1370 
  1638   GST_PAD_STREAM_LOCK (basesink->sinkpad);
       
  1639 
       
  1640   /* would be nice to arrange for pad_alloc_buffer to return data -- as it is we
  1371   /* would be nice to arrange for pad_alloc_buffer to return data -- as it is we
  1641      will copy twice, once into data, once into DMA */
  1372      will copy twice, once into data, once into DMA */
  1642   GST_LOG_OBJECT (basesink, "pulling %d bytes offset %" G_GUINT64_FORMAT
  1373   GST_LOG_OBJECT (basesink, "pulling %d bytes offset %" G_GUINT64_FORMAT
  1643       " to fill audio buffer", len, basesink->offset);
  1374       " to fill audio buffer", len, basesink->offset);
  1644   ret =
  1375   ret = gst_pad_pull_range (basesink->sinkpad, basesink->offset, len, &buf);
  1645       gst_pad_pull_range (basesink->sinkpad, basesink->segment.last_stop, len,
       
  1646       &buf);
       
  1647 
  1376 
  1648   if (ret != GST_FLOW_OK) {
  1377   if (ret != GST_FLOW_OK) {
  1649     if (ret == GST_FLOW_UNEXPECTED)
  1378     if (ret == GST_FLOW_UNEXPECTED)
  1650       goto eos;
  1379       goto eos;
  1651     else
  1380     else
  1652       goto error;
  1381       goto error;
  1653   }
  1382   }
  1654 
  1383 
  1655   GST_PAD_PREROLL_LOCK (basesink->sinkpad);
       
  1656   if (basesink->flushing)
       
  1657     goto flushing;
       
  1658 
       
  1659   /* complete preroll and wait for PLAYING */
       
  1660   ret = gst_base_sink_do_preroll (basesink, GST_MINI_OBJECT_CAST (buf));
       
  1661   if (ret != GST_FLOW_OK)
       
  1662     goto preroll_error;
       
  1663 
       
  1664   if (len != GST_BUFFER_SIZE (buf)) {
  1384   if (len != GST_BUFFER_SIZE (buf)) {
  1665     GST_INFO_OBJECT (basesink,
  1385     GST_INFO_OBJECT (basesink, "short read pulling from sink pad: %d<%d",
  1666         "got different size than requested from sink pad: %u != %u", len,
  1386         len, GST_BUFFER_SIZE (buf));
  1667         GST_BUFFER_SIZE (buf));
       
  1668     len = MIN (GST_BUFFER_SIZE (buf), len);
  1387     len = MIN (GST_BUFFER_SIZE (buf), len);
  1669   }
  1388   }
  1670 
  1389 
  1671   basesink->segment.last_stop += len;
  1390   basesink->offset += len;
  1672 
  1391 
  1673   memcpy (data, GST_BUFFER_DATA (buf), len);
  1392   memcpy (data, GST_BUFFER_DATA (buf), len);
  1674   GST_PAD_PREROLL_UNLOCK (basesink->sinkpad);
       
  1675 
       
  1676   GST_PAD_STREAM_UNLOCK (basesink->sinkpad);
       
  1677 
  1393 
  1678   return;
  1394   return;
  1679 
  1395 
  1680 error:
  1396 error:
  1681   {
  1397   {
  1682     GST_WARNING_OBJECT (basesink, "Got flow '%s' but can't return it: %d",
  1398     GST_WARNING_OBJECT (basesink, "Got flow error but can't return it: %d",
  1683         gst_flow_get_name (ret), ret);
  1399         ret);
  1684     gst_ring_buffer_pause (rbuf);
       
  1685     GST_PAD_STREAM_UNLOCK (basesink->sinkpad);
       
  1686     return;
  1400     return;
  1687   }
  1401   }
  1688 eos:
  1402 eos:
  1689   {
  1403   {
  1690     /* FIXME: this is not quite correct; we'll be called endlessly until
  1404     /* FIXME: this is not quite correct; we'll be called endlessly until
  1691      * the sink gets shut down; maybe we should set a flag somewhere, or
  1405      * the sink gets shut down; maybe we should set a flag somewhere, or
  1692      * set segment.stop and segment.duration to the last sample or so */
  1406      * set segment.stop and segment.duration to the last sample or so */
  1693     GST_DEBUG_OBJECT (sink, "EOS");
  1407     GST_DEBUG_OBJECT (sink, "EOS");
  1694     gst_base_audio_sink_drain (sink);
       
  1695     gst_ring_buffer_pause (rbuf);
       
  1696     gst_element_post_message (GST_ELEMENT_CAST (sink),
  1408     gst_element_post_message (GST_ELEMENT_CAST (sink),
  1697         gst_message_new_eos (GST_OBJECT_CAST (sink)));
  1409         gst_message_new_eos (GST_OBJECT_CAST (sink)));
  1698     GST_PAD_STREAM_UNLOCK (basesink->sinkpad);
  1410     gst_base_audio_sink_drain (sink);
  1699   }
  1411   }
  1700 flushing:
       
  1701   {
       
  1702     GST_DEBUG_OBJECT (sink, "we are flushing");
       
  1703     gst_ring_buffer_pause (rbuf);
       
  1704     GST_PAD_PREROLL_UNLOCK (basesink->sinkpad);
       
  1705     GST_PAD_STREAM_UNLOCK (basesink->sinkpad);
       
  1706     return;
       
  1707   }
       
  1708 preroll_error:
       
  1709   {
       
  1710     GST_DEBUG_OBJECT (sink, "error %s", gst_flow_get_name (ret));
       
  1711     gst_ring_buffer_pause (rbuf);
       
  1712     GST_PAD_PREROLL_UNLOCK (basesink->sinkpad);
       
  1713     GST_PAD_STREAM_UNLOCK (basesink->sinkpad);
       
  1714     return;
       
  1715   }
       
  1716 }
       
  1717 
       
  1718 static gboolean
       
  1719 gst_base_audio_sink_activate_pull (GstBaseSink * basesink, gboolean active)
       
  1720 {
       
  1721   gboolean ret;
       
  1722   GstBaseAudioSink *sink = GST_BASE_AUDIO_SINK (basesink);
       
  1723 
       
  1724   if (active) {
       
  1725     GST_DEBUG_OBJECT (basesink, "activating pull");
       
  1726 
       
  1727     gst_ring_buffer_set_callback (sink->ringbuffer,
       
  1728         gst_base_audio_sink_callback, sink);
       
  1729 
       
  1730     ret = gst_ring_buffer_activate (sink->ringbuffer, TRUE);
       
  1731   } else {
       
  1732     GST_DEBUG_OBJECT (basesink, "deactivating pull");
       
  1733     gst_ring_buffer_set_callback (sink->ringbuffer, NULL, NULL);
       
  1734     ret = gst_ring_buffer_activate (sink->ringbuffer, FALSE);
       
  1735   }
       
  1736 
       
  1737   return ret;
       
  1738 }
  1412 }
  1739 
  1413 
  1740 /* should be called with the LOCK */
  1414 /* should be called with the LOCK */
  1741 static GstStateChangeReturn
  1415 static GstStateChangeReturn
  1742 gst_base_audio_sink_async_play (GstBaseSink * basesink)
  1416 gst_base_audio_sink_async_play (GstBaseSink * basesink)
  1743 {
  1417 {
       
  1418   GstClock *clock;
  1744   GstBaseAudioSink *sink;
  1419   GstBaseAudioSink *sink;
       
  1420   GstClockTime itime, etime;
       
  1421   GstClockTime rate_num, rate_denom;
  1745 
  1422 
  1746   sink = GST_BASE_AUDIO_SINK (basesink);
  1423   sink = GST_BASE_AUDIO_SINK (basesink);
  1747 
  1424 
  1748   GST_DEBUG_OBJECT (sink, "ringbuffer may start now");
  1425   GST_DEBUG_OBJECT (sink, "ringbuffer may start now");
  1749   sink->priv->sync_latency = TRUE;
       
  1750   gst_ring_buffer_may_start (sink->ringbuffer, TRUE);
  1426   gst_ring_buffer_may_start (sink->ringbuffer, TRUE);
  1751   if (basesink->pad_mode == GST_ACTIVATE_PULL) {
  1427 
  1752     /* we always start the ringbuffer in pull mode immediatly */
  1428   clock = GST_ELEMENT_CLOCK (sink);
  1753     gst_ring_buffer_start (sink->ringbuffer);
  1429   if (clock == NULL)
  1754   }
  1430     goto done;
  1755 
  1431 
       
  1432   /* we provided the global clock, don't need to do anything special */
       
  1433   if (clock == sink->provided_clock)
       
  1434     goto done;
       
  1435 
       
  1436   /* if we are slaved to a clock, we need to set the initial
       
  1437    * calibration */
       
  1438   /* get external and internal time to set as calibration params */
       
  1439   etime = gst_clock_get_time (clock);
       
  1440   itime = gst_clock_get_internal_time (sink->provided_clock);
       
  1441 
       
  1442   sink->priv->avg_skew = -1;
       
  1443   sink->next_sample = -1;
       
  1444 
       
  1445   GST_DEBUG_OBJECT (sink,
       
  1446       "internal time: %" GST_TIME_FORMAT " external time: %" GST_TIME_FORMAT,
       
  1447       GST_TIME_ARGS (itime), GST_TIME_ARGS (etime));
       
  1448 
       
  1449   gst_clock_get_calibration (sink->provided_clock, NULL, NULL, &rate_num,
       
  1450       &rate_denom);
       
  1451   gst_clock_set_calibration (sink->provided_clock, itime, etime,
       
  1452       rate_num, rate_denom);
       
  1453 
       
  1454   switch (sink->priv->slave_method) {
       
  1455     case GST_BASE_AUDIO_SINK_SLAVE_RESAMPLE:
       
  1456       /* only set as master if we need to resample */
       
  1457       GST_DEBUG_OBJECT (sink, "Setting clock as master");
       
  1458       gst_clock_set_master (sink->provided_clock, clock);
       
  1459       break;
       
  1460     default:
       
  1461       break;
       
  1462   }
       
  1463 
       
  1464   /* start ringbuffer so we can start slaving right away when we need to */
       
  1465   gst_ring_buffer_start (sink->ringbuffer);
       
  1466 
       
  1467 done:
  1756   return GST_STATE_CHANGE_SUCCESS;
  1468   return GST_STATE_CHANGE_SUCCESS;
       
  1469 }
       
  1470 
       
  1471 static GstStateChangeReturn
       
  1472 gst_base_audio_sink_do_play (GstBaseAudioSink * sink)
       
  1473 {
       
  1474   GstStateChangeReturn ret;
       
  1475 
       
  1476   GST_OBJECT_LOCK (sink);
       
  1477   ret = gst_base_audio_sink_async_play (GST_BASE_SINK_CAST (sink));
       
  1478   GST_OBJECT_UNLOCK (sink);
       
  1479 
       
  1480   return ret;
  1757 }
  1481 }
  1758 
  1482 
  1759 static GstStateChangeReturn
  1483 static GstStateChangeReturn
  1760 gst_base_audio_sink_change_state (GstElement * element,
  1484 gst_base_audio_sink_change_state (GstElement * element,
  1761     GstStateChange transition)
  1485     GstStateChange transition)
  1764   GstBaseAudioSink *sink = GST_BASE_AUDIO_SINK (element);
  1488   GstBaseAudioSink *sink = GST_BASE_AUDIO_SINK (element);
  1765 
  1489 
  1766   switch (transition) {
  1490   switch (transition) {
  1767     case GST_STATE_CHANGE_NULL_TO_READY:
  1491     case GST_STATE_CHANGE_NULL_TO_READY:
  1768       if (sink->ringbuffer == NULL) {
  1492       if (sink->ringbuffer == NULL) {
  1769         gst_audio_clock_reset (GST_AUDIO_CLOCK (sink->provided_clock), 0);
       
  1770         sink->ringbuffer = gst_base_audio_sink_create_ringbuffer (sink);
  1493         sink->ringbuffer = gst_base_audio_sink_create_ringbuffer (sink);
  1771       }
  1494       }
  1772       if (!gst_ring_buffer_open_device (sink->ringbuffer))
  1495       if (!gst_ring_buffer_open_device (sink->ringbuffer))
  1773         goto open_failed;
  1496         goto open_failed;
  1774       break;
  1497       break;
  1775     case GST_STATE_CHANGE_READY_TO_PAUSED:
  1498     case GST_STATE_CHANGE_READY_TO_PAUSED:
  1776       sink->next_sample = -1;
  1499       sink->next_sample = -1;
  1777       sink->priv->last_align = -1;
  1500       sink->priv->last_align = -1;
  1778       sink->priv->eos_time = -1;
       
  1779       gst_ring_buffer_set_flushing (sink->ringbuffer, FALSE);
  1501       gst_ring_buffer_set_flushing (sink->ringbuffer, FALSE);
  1780       gst_ring_buffer_may_start (sink->ringbuffer, FALSE);
  1502       gst_ring_buffer_may_start (sink->ringbuffer, FALSE);
  1781       break;
  1503       break;
  1782     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
  1504     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
       
  1505       gst_base_audio_sink_do_play (sink);
       
  1506       break;
       
  1507     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
       
  1508       /* need to take the lock so we don't interfere with an
       
  1509        * async play */
  1783       GST_OBJECT_LOCK (sink);
  1510       GST_OBJECT_LOCK (sink);
  1784       GST_DEBUG_OBJECT (sink, "ringbuffer may start now");
       
  1785       sink->priv->sync_latency = TRUE;
       
  1786       GST_OBJECT_UNLOCK (sink);
       
  1787 
       
  1788       gst_ring_buffer_may_start (sink->ringbuffer, TRUE);
       
  1789       if (GST_BASE_SINK_CAST (sink)->pad_mode == GST_ACTIVATE_PULL) {
       
  1790         /* we always start the ringbuffer in pull mode immediatly */
       
  1791         gst_ring_buffer_start (sink->ringbuffer);
       
  1792       }
       
  1793       break;
       
  1794     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
       
  1795       /* ringbuffer cannot start anymore */
  1511       /* ringbuffer cannot start anymore */
  1796       gst_ring_buffer_may_start (sink->ringbuffer, FALSE);
  1512       gst_ring_buffer_may_start (sink->ringbuffer, FALSE);
  1797       gst_ring_buffer_pause (sink->ringbuffer);
  1513       gst_ring_buffer_pause (sink->ringbuffer);
  1798 
       
  1799       GST_OBJECT_LOCK (sink);
       
  1800       sink->priv->sync_latency = FALSE;
       
  1801       GST_OBJECT_UNLOCK (sink);
  1514       GST_OBJECT_UNLOCK (sink);
  1802       break;
  1515       break;
  1803     case GST_STATE_CHANGE_PAUSED_TO_READY:
  1516     case GST_STATE_CHANGE_PAUSED_TO_READY:
  1804       /* make sure we unblock before calling the parent state change
  1517       /* make sure we unblock before calling the parent state change
  1805        * so it can grab the STREAM_LOCK */
  1518        * so it can grab the STREAM_LOCK */
  1815     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
  1528     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
  1816       /* stop slaving ourselves to the master, if any */
  1529       /* stop slaving ourselves to the master, if any */
  1817       gst_clock_set_master (sink->provided_clock, NULL);
  1530       gst_clock_set_master (sink->provided_clock, NULL);
  1818       break;
  1531       break;
  1819     case GST_STATE_CHANGE_PAUSED_TO_READY:
  1532     case GST_STATE_CHANGE_PAUSED_TO_READY:
  1820       gst_ring_buffer_activate (sink->ringbuffer, FALSE);
       
  1821       gst_ring_buffer_release (sink->ringbuffer);
  1533       gst_ring_buffer_release (sink->ringbuffer);
  1822       break;
  1534       break;
  1823     case GST_STATE_CHANGE_READY_TO_NULL:
  1535     case GST_STATE_CHANGE_READY_TO_NULL:
  1824       /* we release again here because the aqcuire happens when setting the
  1536       /* we release again here because the aqcuire happens when setting the
  1825        * caps, which happens before we commit the state to PAUSED and thus the
  1537        * caps, which happens before we commit the state to PAUSED and thus the
  1826        * PAUSED->READY state change (see above, where we release the ringbuffer)
  1538        * PAUSED->READY state change (see above, where we release the ringbuffer)
  1827        * might not be called when we get here. */
  1539        * might not be called when we get here. */
  1828       gst_ring_buffer_activate (sink->ringbuffer, FALSE);
       
  1829       gst_ring_buffer_release (sink->ringbuffer);
  1540       gst_ring_buffer_release (sink->ringbuffer);
  1830       gst_ring_buffer_close_device (sink->ringbuffer);
  1541       gst_ring_buffer_close_device (sink->ringbuffer);
  1831       GST_OBJECT_LOCK (sink);
       
  1832       gst_object_unparent (GST_OBJECT_CAST (sink->ringbuffer));
       
  1833       sink->ringbuffer = NULL;
       
  1834       GST_OBJECT_UNLOCK (sink);
       
  1835       break;
  1542       break;
  1836     default:
  1543     default:
  1837       break;
  1544       break;
  1838   }
  1545   }
  1839 
  1546