basevideocodec: Protect access to the list of pending frames with the object lock
authorSebastian Dröge <sebastian.droege@collabora.co.uk>
Mon, 11 Jul 2011 09:28:40 +0000 (11:28 +0200)
committerSebastian Dröge <sebastian.droege@collabora.co.uk>
Tue, 12 Jul 2011 06:36:00 +0000 (08:36 +0200)
This is required if ::finish_frame() and all buffer output happens
on a different thread than the sinkpad streaming thread.

omx/gstbasevideocodec.c
omx/gstbasevideocodec.h
omx/gstbasevideodecoder.c

index ea35b01..31fa5e5 100644 (file)
@@ -106,11 +106,13 @@ gst_base_video_codec_reset (GstBaseVideoCodec * base_video_codec)
 
   GST_DEBUG_OBJECT (base_video_codec, "reset");
 
+  GST_OBJECT_LOCK (base_video_codec);
   for (g = base_video_codec->frames; g; g = g_list_next (g)) {
     gst_base_video_codec_free_frame ((GstVideoFrame *) g->data);
   }
   g_list_free (base_video_codec->frames);
   base_video_codec->frames = NULL;
+  GST_OBJECT_UNLOCK (base_video_codec);
 
   base_video_codec->bytes = 0;
   base_video_codec->time = 0;
index 9fc2cb2..c1e3712 100644 (file)
@@ -147,7 +147,7 @@ struct _GstBaseVideoCodec
 
   guint64 system_frame_number;
 
-  GList *frames;
+  GList *frames;  /* Protected with OBJECT_LOCK */
   GstVideoState state;
   GstSegment segment;
 
index 8b6c344..95cf991 100644 (file)
@@ -1359,10 +1359,14 @@ gst_base_video_decoder_finish_frame (GstBaseVideoDecoder * base_video_decoder,
   GList *l;
 
   GST_LOG_OBJECT (base_video_decoder, "finish frame");
+#ifndef GST_DISABLE_GST_DEBUG
+  GST_OBJECT_LOCK (base_video_decoder);
   GST_LOG_OBJECT (base_video_decoder, "n %d in %d out %d",
       g_list_length (GST_BASE_VIDEO_CODEC (base_video_decoder)->frames),
       gst_adapter_available (base_video_decoder->input_adapter),
       gst_adapter_available (base_video_decoder->output_adapter));
+  GST_OBJECT_UNLOCK (base_video_decoder);
+#endif
 
   GST_LOG_OBJECT (base_video_decoder,
       "finish frame sync=%d pts=%" GST_TIME_FORMAT, frame->is_sync_point,
@@ -1553,8 +1557,10 @@ gst_base_video_decoder_finish_frame (GstBaseVideoDecoder * base_video_decoder,
   }
 
 done:
+  GST_OBJECT_LOCK (base_video_decoder);
   GST_BASE_VIDEO_CODEC (base_video_decoder)->frames =
       g_list_remove (GST_BASE_VIDEO_CODEC (base_video_decoder)->frames, frame);
+  GST_OBJECT_UNLOCK (base_video_decoder);
   gst_base_video_codec_free_frame (frame);
 
   return ret;
@@ -1718,8 +1724,10 @@ gst_base_video_decoder_have_frame_2 (GstBaseVideoDecoder * base_video_decoder)
       GST_TIME_ARGS (frame->decode_timestamp));
   GST_LOG_OBJECT (base_video_decoder, "dist %d", frame->distance_from_sync);
 
+  GST_OBJECT_LOCK (base_video_decoder);
   GST_BASE_VIDEO_CODEC (base_video_decoder)->frames =
       g_list_append (GST_BASE_VIDEO_CODEC (base_video_decoder)->frames, frame);
+  GST_OBJECT_UNLOCK (base_video_decoder);
 
   frame->deadline =
       gst_segment_to_running_time (&GST_BASE_VIDEO_CODEC
@@ -1801,7 +1809,9 @@ gst_base_video_decoder_get_oldest_frame (GstBaseVideoDecoder *
 {
   GList *g;
 
+  GST_OBJECT_LOCK (base_video_decoder);
   g = g_list_first (GST_BASE_VIDEO_CODEC (base_video_decoder)->frames);
+  GST_OBJECT_UNLOCK (base_video_decoder);
 
   if (g == NULL)
     return NULL;
@@ -1820,17 +1830,21 @@ gst_base_video_decoder_get_frame (GstBaseVideoDecoder * base_video_decoder,
     int frame_number)
 {
   GList *g;
+  GstVideoFrame *frame = NULL;
 
+  GST_OBJECT_LOCK (base_video_decoder);
   for (g = g_list_first (GST_BASE_VIDEO_CODEC (base_video_decoder)->frames);
       g; g = g_list_next (g)) {
-    GstVideoFrame *frame = g->data;
+    GstVideoFrame *tmp = g->data;
 
     if (frame->system_frame_number == frame_number) {
-      return frame;
+      frame = tmp;
+      break;
     }
   }
+  GST_OBJECT_UNLOCK (base_video_decoder);
 
-  return NULL;
+  return frame;
 }
 
 /**