baseaudiosink: protect against ringbuffer disappearing while in a query
authorHavard Graff <havard.graff@tandberg.com>
Thu, 25 Nov 2010 16:01:04 +0000 (17:01 +0100)
committerWim Taymans <wim.taymans@collabora.co.uk>
Wed, 29 Dec 2010 11:29:40 +0000 (12:29 +0100)
Observed a case where the sink went to null-state during the query,
hence the ringbuffer-pointer was NULL, causing a crash.

Moving the ringbuffer-check code until after the query, and hold the
lock during the check and while using the spec-values. It should not matter
to the query wether the ringbuffer is present or not, and it actually
gets a time bit more time to get the ringbuffer set up in this case!

Fixes #635231

gst-libs/gst/audio/gstbaseaudiosink.c

index 8e7760b..b7167b2 100644 (file)
@@ -417,13 +417,6 @@ gst_base_audio_sink_query (GstElement * element, GstQuery * query)
 
       GST_DEBUG_OBJECT (basesink, "latency query");
 
-      if (!basesink->ringbuffer || !basesink->ringbuffer->spec.rate) {
-        GST_DEBUG_OBJECT (basesink,
-            "we are not yet negotiated, can't report latency yet");
-        res = FALSE;
-        goto done;
-      }
-
       /* ask parent first, it will do an upstream query for us. */
       if ((res =
               gst_base_sink_query_latency (GST_BASE_SINK_CAST (basesink), &live,
@@ -434,6 +427,15 @@ gst_base_audio_sink_query (GstElement * element, GstQuery * query)
         if (live && us_live) {
           GstRingBufferSpec *spec;
 
+          GST_OBJECT_LOCK (basesink);
+          if (!basesink->ringbuffer || !basesink->ringbuffer->spec.rate) {
+            GST_OBJECT_UNLOCK (basesink);
+
+            GST_DEBUG_OBJECT (basesink,
+                "we are not yet negotiated, can't report latency yet");
+            res = FALSE;
+            goto done;
+          }
           spec = &basesink->ringbuffer->spec;
 
           basesink->priv->us_latency = min_l;
@@ -441,6 +443,7 @@ gst_base_audio_sink_query (GstElement * element, GstQuery * query)
           min_latency =
               gst_util_uint64_scale_int (spec->seglatency * spec->segsize,
               GST_SECOND, spec->rate * spec->bytes_per_sample);
+          GST_OBJECT_UNLOCK (basesink);
 
           /* we cannot go lower than the buffer size and the min peer latency */
           min_latency = min_latency + min_l;