videodecoder: Protect all accesses to priv->output_frame with the stream lock
authorOlivier Crête <olivier.crete@collabora.com>
Thu, 20 Sep 2012 01:16:01 +0000 (21:16 -0400)
committerOlivier Crête <olivier.crete@collabora.com>
Thu, 20 Sep 2012 01:16:01 +0000 (21:16 -0400)
Fixes segfault as queries/events can happen after a reset

gst-libs/gst/video/gstvideodecoder.c

index 9c36507..f50f5ac 100644 (file)
@@ -1254,12 +1254,14 @@ gst_video_decoder_src_event_default (GstVideoDecoder * decoder,
       priv->proportion = proportion;
       if (G_LIKELY (GST_CLOCK_TIME_IS_VALID (timestamp))) {
         if (G_UNLIKELY (diff > 0)) {
-          if (priv->output_state->info.fps_n > 0)
+          GST_VIDEO_DECODER_STREAM_LOCK (decoder);
+          if (priv->output_state != NULL && priv->output_state->info.fps_n > 0)
             duration =
                 gst_util_uint64_scale (GST_SECOND,
                 priv->output_state->info.fps_d, priv->output_state->info.fps_n);
           else
             duration = 0;
+          GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
           priv->earliest_time = timestamp + 2 * diff + duration;
         } else {
           priv->earliest_time = timestamp + diff;
@@ -1384,8 +1386,13 @@ gst_video_decoder_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
       GST_DEBUG_OBJECT (dec, "convert query");
 
       gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
-      res = gst_video_rawvideo_convert (dec->priv->output_state,
-          src_fmt, src_val, &dest_fmt, &dest_val);
+      GST_VIDEO_DECODER_STREAM_LOCK (dec);
+      if (dec->priv->output_state != NULL)
+        res = gst_video_rawvideo_convert (dec->priv->output_state,
+            src_fmt, src_val, &dest_fmt, &dest_val);
+      else
+        res = FALSE;
+      GST_VIDEO_DECODER_STREAM_UNLOCK (dec);
       if (!res)
         goto error;
       gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
@@ -1399,7 +1406,7 @@ gst_video_decoder_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
       res = gst_pad_peer_query (dec->sinkpad, query);
       if (res) {
         gst_query_parse_latency (query, &live, &min_latency, &max_latency);
-        GST_DEBUG_OBJECT (dec, "Peer latency: live %d, min %"
+        GST_DEBUG_OBJECT (dec, "Peer qlatency: live %d, min %"
             GST_TIME_FORMAT " max %" GST_TIME_FORMAT, live,
             GST_TIME_ARGS (min_latency), GST_TIME_ARGS (max_latency));
 
@@ -2944,13 +2951,24 @@ gst_video_decoder_allocate_output_frame (GstVideoDecoder *
     decoder, GstVideoCodecFrame * frame)
 {
   GstFlowReturn flow_ret;
-  GstVideoCodecState *state = decoder->priv->output_state;
-  int num_bytes = GST_VIDEO_INFO_SIZE (&state->info);
+  GstVideoCodecState *state;
+  int num_bytes;
 
-  g_return_val_if_fail (num_bytes != 0, GST_FLOW_ERROR);
   g_return_val_if_fail (frame->output_buffer == NULL, GST_FLOW_ERROR);
 
   GST_VIDEO_DECODER_STREAM_LOCK (decoder);
+
+  state = decoder->priv->output_state;
+  if (state == NULL) {
+    g_warning ("Output state should be set before allocating frame");
+    goto error;
+  }
+  num_bytes = GST_VIDEO_INFO_SIZE (&state->info);
+  if (num_bytes == 0) {
+    g_warning ("Frame size should not be 0");
+    goto error;
+  }
+
   if (G_UNLIKELY (decoder->priv->output_state_changed
           || (decoder->priv->output_state
               && gst_pad_check_reconfigure (decoder->srcpad))))
@@ -2964,6 +2982,10 @@ gst_video_decoder_allocate_output_frame (GstVideoDecoder *
   GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
 
   return flow_ret;
+
+error:
+  GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
+  return GST_FLOW_ERROR;
 }
 
 /**