audiobasesink: make _get_time more threadsafe
authorWim Taymans <wtaymans@redhat.com>
Tue, 21 Jan 2014 10:21:56 +0000 (11:21 +0100)
committerWim Taymans <wtaymans@redhat.com>
Tue, 21 Jan 2014 10:25:18 +0000 (11:25 +0100)
We call the _get_time function from the provided clock and we don't lock
the sink object for performance reasons. Make sure we only read and
check variables once so that they don't change while we are executing
the code.

Fixes https://bugzilla.gnome.org/show_bug.cgi?id=720661

gst-libs/gst/audio/gstaudiobasesink.c

index 61d5db4..6efb84c 100644 (file)
@@ -513,30 +513,36 @@ done:
 }
 
 
+/* we call this function without holding the lock on sink for performance
+ * reasons. Try hard to not deal with and invalid ringbuffer and rate. */
 static GstClockTime
 gst_audio_base_sink_get_time (GstClock * clock, GstAudioBaseSink * sink)
 {
   guint64 raw, samples;
   guint delay;
   GstClockTime result;
+  GstAudioRingBuffer *ringbuffer;
+  gint rate;
+
+  if ((ringbuffer = sink->ringbuffer) == NULL)
+    return GST_CLOCK_TIME_NONE;
 
-  if (sink->ringbuffer == NULL || sink->ringbuffer->spec.info.rate == 0)
+  if ((rate = ringbuffer->spec.info.rate) == 0)
     return GST_CLOCK_TIME_NONE;
 
   /* our processed samples are always increasing */
-  raw = samples = gst_audio_ring_buffer_samples_done (sink->ringbuffer);
+  raw = samples = gst_audio_ring_buffer_samples_done (ringbuffer);
 
   /* the number of samples not yet processed, this is still queued in the
    * device (not played for playback). */
-  delay = gst_audio_ring_buffer_delay (sink->ringbuffer);
+  delay = gst_audio_ring_buffer_delay (ringbuffer);
 
   if (G_LIKELY (samples >= delay))
     samples -= delay;
   else
     samples = 0;
 
-  result = gst_util_uint64_scale_int (samples, GST_SECOND,
-      sink->ringbuffer->spec.info.rate);
+  result = gst_util_uint64_scale_int (samples, GST_SECOND, rate);
 
   GST_DEBUG_OBJECT (sink,
       "processed samples: raw %" G_GUINT64_FORMAT ", delay %u, real %"