basevideo: Fix locking, especially if both pads have different streaming threads
authorSebastian Dröge <sebastian.droege@collabora.co.uk>
Thu, 18 Aug 2011 08:02:50 +0000 (10:02 +0200)
committerSebastian Dröge <sebastian.droege@collabora.co.uk>
Thu, 18 Aug 2011 08:02:50 +0000 (10:02 +0200)
omx/gstbasevideocodec.c
omx/gstbasevideocodec.h
omx/gstbasevideodecoder.c
omx/gstbasevideoencoder.c

index 31fa5e5..68e203d 100644 (file)
@@ -97,6 +97,7 @@ gst_base_video_codec_init (GstBaseVideoCodec * base_video_codec,
 
   gst_segment_init (&base_video_codec->segment, GST_FORMAT_TIME);
 
+  g_static_rec_mutex_init (&base_video_codec->stream_lock);
 }
 
 static void
@@ -106,24 +107,28 @@ gst_base_video_codec_reset (GstBaseVideoCodec * base_video_codec)
 
   GST_DEBUG_OBJECT (base_video_codec, "reset");
 
-  GST_OBJECT_LOCK (base_video_codec);
+  GST_BASE_VIDEO_CODEC_STREAM_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;
 
   gst_buffer_replace (&base_video_codec->state.codec_data, NULL);
   gst_caps_replace (&base_video_codec->state.caps, NULL);
+  GST_BASE_VIDEO_CODEC_STREAM_UNLOCK (base_video_codec);
 }
 
 static void
 gst_base_video_codec_finalize (GObject * object)
 {
+  GstBaseVideoCodec *base_video_codec = GST_BASE_VIDEO_CODEC (object);
+
+  g_static_rec_mutex_free (&base_video_codec->stream_lock);
+
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
@@ -170,8 +175,10 @@ gst_base_video_codec_new_frame (GstBaseVideoCodec * base_video_codec)
 
   frame = g_slice_new0 (GstVideoFrame);
 
+  GST_BASE_VIDEO_CODEC_STREAM_LOCK (base_video_codec);
   frame->system_frame_number = base_video_codec->system_frame_number;
   base_video_codec->system_frame_number++;
+  GST_BASE_VIDEO_CODEC_STREAM_UNLOCK (base_video_codec);
 
   return frame;
 }
index c1e3712..6471c35 100644 (file)
@@ -79,6 +79,9 @@ G_BEGIN_DECLS
  */
 #define GST_BASE_VIDEO_CODEC_FLOW_NEED_DATA GST_FLOW_CUSTOM_SUCCESS
 
+#define GST_BASE_VIDEO_CODEC_STREAM_LOCK(codec) g_static_rec_mutex_lock (&GST_BASE_VIDEO_CODEC (codec)->stream_lock)
+#define GST_BASE_VIDEO_CODEC_STREAM_UNLOCK(codec) g_static_rec_mutex_unlock (&GST_BASE_VIDEO_CODEC (codec)->stream_lock)
+
 typedef struct _GstVideoState GstVideoState;
 typedef struct _GstVideoFrame GstVideoFrame;
 typedef struct _GstBaseVideoCodec GstBaseVideoCodec;
@@ -145,6 +148,11 @@ struct _GstBaseVideoCodec
   GstPad *sinkpad;
   GstPad *srcpad;
 
+  /* protects all data processing, i.e. is locked
+   * in the chain function, finish_frame and when
+   * processing serialized events */
+  GStaticRecMutex stream_lock;
+
   guint64 system_frame_number;
 
   GList *frames;  /* Protected with OBJECT_LOCK */
index 0e08a88..ad707cb 100644 (file)
@@ -255,8 +255,10 @@ gst_base_video_decoder_push_src_event (GstBaseVideoDecoder * decoder,
       || GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_STOP)
     return gst_pad_push_event (decoder->base_video_codec.srcpad, event);
 
+  GST_BASE_VIDEO_CODEC_STREAM_LOCK (decoder);
   decoder->current_frame_events =
       g_list_prepend (decoder->current_frame_events, event);
+  GST_BASE_VIDEO_CODEC_STREAM_UNLOCK (decoder);
 
   return TRUE;
 }
@@ -277,6 +279,8 @@ gst_base_video_decoder_sink_setcaps (GstPad * pad, GstCaps * caps)
 
   GST_DEBUG_OBJECT (base_video_decoder, "setcaps %" GST_PTR_FORMAT, caps);
 
+  GST_BASE_VIDEO_CODEC_STREAM_LOCK (base_video_decoder);
+
   memset (&state, 0, sizeof (state));
 
   state.caps = gst_caps_ref (caps);
@@ -320,6 +324,7 @@ gst_base_video_decoder_sink_setcaps (GstPad * pad, GstCaps * caps)
     gst_caps_replace (&state.caps, NULL);
   }
 
+  GST_BASE_VIDEO_CODEC_STREAM_UNLOCK (base_video_decoder);
   g_object_unref (base_video_decoder);
 
   return ret;
@@ -402,7 +407,8 @@ gst_base_video_decoder_sink_event (GstPad * pad, GstEvent * event)
     case GST_EVENT_EOS:
     {
       GstFlowReturn flow_ret;
-      ;
+
+      GST_BASE_VIDEO_CODEC_STREAM_LOCK (base_video_decoder);
       if (!base_video_decoder->packetized) {
         do {
           flow_ret =
@@ -418,8 +424,9 @@ gst_base_video_decoder_sink_event (GstPad * pad, GstEvent * event)
 
       if (flow_ret == GST_FLOW_OK)
         ret = gst_base_video_decoder_push_src_event (base_video_decoder, event);
-    }
+      GST_BASE_VIDEO_CODEC_STREAM_UNLOCK (base_video_decoder);
       break;
+    }
     case GST_EVENT_NEWSEGMENT:
     {
       gboolean update;
@@ -430,6 +437,7 @@ gst_base_video_decoder_sink_event (GstPad * pad, GstEvent * event)
       gint64 pos;
       GstSegment *segment = &GST_BASE_VIDEO_CODEC (base_video_decoder)->segment;
 
+      GST_BASE_VIDEO_CODEC_STREAM_LOCK (base_video_decoder);
       gst_event_parse_new_segment_full (event, &update, &rate,
           &arate, &format, &start, &stop, &pos);
 
@@ -466,6 +474,7 @@ gst_base_video_decoder_sink_event (GstPad * pad, GstEvent * event)
           event = gst_event_new_new_segment_full (update, rate, arate,
               GST_FORMAT_TIME, start, stop, pos);
         } else {
+          GST_BASE_VIDEO_CODEC_STREAM_UNLOCK (base_video_decoder);
           goto newseg_wrong_format;
         }
       }
@@ -480,12 +489,15 @@ gst_base_video_decoder_sink_event (GstPad * pad, GstEvent * event)
           update, rate, arate, format, start, stop, pos);
 
       ret = gst_base_video_decoder_push_src_event (base_video_decoder, event);
+      GST_BASE_VIDEO_CODEC_STREAM_UNLOCK (base_video_decoder);
       break;
     }
     case GST_EVENT_FLUSH_STOP:
     {
+      GST_BASE_VIDEO_CODEC_STREAM_LOCK (base_video_decoder);
       /* well, this is kind of worse than a DISCONT */
       gst_base_video_decoder_flush (base_video_decoder, TRUE);
+      GST_BASE_VIDEO_CODEC_STREAM_UNLOCK (base_video_decoder);
     }
     default:
       /* FIXME this changes the order of events */
@@ -928,6 +940,8 @@ gst_base_video_decoder_reset (GstBaseVideoDecoder * base_video_decoder,
 {
   GST_DEBUG_OBJECT (base_video_decoder, "reset full %d", full);
 
+  GST_BASE_VIDEO_CODEC_STREAM_LOCK (base_video_decoder);
+
   if (full) {
     gst_segment_init (&GST_BASE_VIDEO_CODEC (base_video_decoder)->segment,
         GST_FORMAT_UNDEFINED);
@@ -963,6 +977,7 @@ gst_base_video_decoder_reset (GstBaseVideoDecoder * base_video_decoder,
       GST_CLOCK_TIME_NONE;
   GST_BASE_VIDEO_CODEC (base_video_decoder)->proportion = 0.5;
   GST_OBJECT_UNLOCK (base_video_decoder);
+  GST_BASE_VIDEO_CODEC_STREAM_UNLOCK (base_video_decoder);
 }
 
 static GstFlowReturn
@@ -1209,6 +1224,7 @@ static GstFlowReturn
 gst_base_video_decoder_chain (GstPad * pad, GstBuffer * buf)
 {
   GstBaseVideoDecoder *base_video_decoder;
+  GstFlowReturn ret = GST_FLOW_OK;
 
   base_video_decoder = GST_BASE_VIDEO_DECODER (GST_PAD_PARENT (pad));
 
@@ -1217,6 +1233,8 @@ gst_base_video_decoder_chain (GstPad * pad, GstBuffer * buf)
       GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
       GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_BUFFER_SIZE (buf));
 
+  GST_BASE_VIDEO_CODEC_STREAM_LOCK (base_video_decoder);
+
   /* NOTE:
    * requiring the pad to be negotiated makes it impossible to use
    * oggdemux or filesrc ! decoder */
@@ -1240,7 +1258,8 @@ gst_base_video_decoder_chain (GstPad * pad, GstBuffer * buf)
     ret = gst_base_video_decoder_push_src_event (base_video_decoder, event);
     if (!ret) {
       GST_ERROR_OBJECT (base_video_decoder, "new segment event ret=%d", ret);
-      return GST_FLOW_ERROR;
+      ret = GST_FLOW_ERROR;
+      goto done;
     }
   }
 
@@ -1268,9 +1287,13 @@ gst_base_video_decoder_chain (GstPad * pad, GstBuffer * buf)
   }
 
   if (GST_BASE_VIDEO_CODEC (base_video_decoder)->segment.rate > 0.0)
-    return gst_base_video_decoder_chain_forward (base_video_decoder, buf);
+    ret = gst_base_video_decoder_chain_forward (base_video_decoder, buf);
   else
-    return gst_base_video_decoder_chain_reverse (base_video_decoder, buf);
+    ret = gst_base_video_decoder_chain_reverse (base_video_decoder, buf);
+
+done:
+  GST_BASE_VIDEO_CODEC_STREAM_LOCK (base_video_decoder);
+  return ret;
 }
 
 static GstStateChangeReturn
@@ -1300,11 +1323,14 @@ gst_base_video_decoder_change_state (GstElement * element,
       if (base_video_decoder_class->stop) {
         base_video_decoder_class->stop (base_video_decoder);
       }
+
+      GST_BASE_VIDEO_CODEC_STREAM_LOCK (base_video_decoder);
       gst_base_video_decoder_reset (base_video_decoder, TRUE);
       g_list_foreach (base_video_decoder->current_frame_events,
           (GFunc) gst_event_unref, NULL);
       g_list_free (base_video_decoder->current_frame_events);
       base_video_decoder->current_frame_events = NULL;
+      GST_BASE_VIDEO_CODEC_STREAM_UNLOCK (base_video_decoder);
       break;
     default:
       break;
@@ -1318,6 +1344,7 @@ gst_base_video_decoder_new_frame (GstBaseVideoDecoder * base_video_decoder)
 {
   GstVideoFrame *frame;
 
+  GST_BASE_VIDEO_CODEC_STREAM_LOCK (base_video_decoder);
   frame =
       gst_base_video_codec_new_frame (GST_BASE_VIDEO_CODEC
       (base_video_decoder));
@@ -1333,6 +1360,8 @@ gst_base_video_decoder_new_frame (GstBaseVideoDecoder * base_video_decoder)
   frame->events = base_video_decoder->current_frame_events;
   base_video_decoder->current_frame_events = NULL;
 
+  GST_BASE_VIDEO_CODEC_STREAM_UNLOCK (base_video_decoder);
+
   return frame;
 }
 
@@ -1358,13 +1387,13 @@ gst_base_video_decoder_finish_frame (GstBaseVideoDecoder * base_video_decoder,
   GList *l, *events = NULL;
 
   GST_LOG_OBJECT (base_video_decoder, "finish frame");
+  GST_BASE_VIDEO_CODEC_STREAM_LOCK (base_video_decoder);
+
 #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,
@@ -1372,7 +1401,6 @@ gst_base_video_decoder_finish_frame (GstBaseVideoDecoder * base_video_decoder,
       GST_TIME_ARGS (frame->presentation_timestamp));
 
   /* Push all pending events that arrived before this frame */
-  GST_OBJECT_LOCK (base_video_decoder);
   for (l = base_video_decoder->base_video_codec.frames; l; l = l->next) {
     GstVideoFrame *tmp = l->data;
 
@@ -1388,7 +1416,6 @@ gst_base_video_decoder_finish_frame (GstBaseVideoDecoder * base_video_decoder,
     if (tmp == frame)
       break;
   }
-  GST_OBJECT_UNLOCK (base_video_decoder);
 
   for (l = g_list_last (events); l; l = l->next)
     gst_pad_push_event (GST_BASE_VIDEO_CODEC_SRC_PAD (base_video_decoder),
@@ -1542,7 +1569,8 @@ gst_base_video_decoder_finish_frame (GstBaseVideoDecoder * base_video_decoder,
           GST_TIME_ARGS (segment->start),
           GST_TIME_ARGS (segment->stop), GST_TIME_ARGS (segment->time));
       gst_buffer_unref (src_buffer);
-      return GST_FLOW_OK;
+      ret = GST_FLOW_OK;
+      goto done;
     }
   }
 
@@ -1560,12 +1588,12 @@ 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);
 
+  GST_BASE_VIDEO_CODEC_STREAM_UNLOCK (base_video_decoder);
+
   return ret;
 }
 
@@ -1587,6 +1615,7 @@ gst_base_video_decoder_add_to_frame (GstBaseVideoDecoder * base_video_decoder,
   if (n_bytes == 0)
     return;
 
+  GST_BASE_VIDEO_CODEC_STREAM_LOCK (base_video_decoder);
   if (gst_adapter_available (base_video_decoder->output_adapter) == 0) {
     base_video_decoder->frame_offset = base_video_decoder->input_offset -
         gst_adapter_available (base_video_decoder->input_adapter);
@@ -1594,6 +1623,7 @@ gst_base_video_decoder_add_to_frame (GstBaseVideoDecoder * base_video_decoder,
   buf = gst_adapter_take_buffer (base_video_decoder->input_adapter, n_bytes);
 
   gst_adapter_push (base_video_decoder->output_adapter, buf);
+  GST_BASE_VIDEO_CODEC_STREAM_UNLOCK (base_video_decoder);
 }
 
 static guint64
@@ -1668,9 +1698,12 @@ gst_base_video_decoder_have_frame (GstBaseVideoDecoder * base_video_decoder)
   int n_available;
   GstClockTime timestamp;
   GstClockTime duration;
+  GstFlowReturn ret = GST_FLOW_OK;
 
   GST_LOG_OBJECT (base_video_decoder, "have_frame");
 
+  GST_BASE_VIDEO_CODEC_STREAM_LOCK (base_video_decoder);
+
   n_available = gst_adapter_available (base_video_decoder->output_adapter);
   if (n_available) {
     buffer = gst_adapter_take_buffer (base_video_decoder->output_adapter,
@@ -1691,7 +1724,11 @@ gst_base_video_decoder_have_frame (GstBaseVideoDecoder * base_video_decoder)
       "ts %" GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT,
       n_available, GST_TIME_ARGS (timestamp), GST_TIME_ARGS (duration));
 
-  return gst_base_video_decoder_have_frame_2 (base_video_decoder);
+  ret = gst_base_video_decoder_have_frame_2 (base_video_decoder);
+
+  GST_BASE_VIDEO_CODEC_STREAM_UNLOCK (base_video_decoder);
+
+  return ret;
 }
 
 static GstFlowReturn
@@ -1727,10 +1764,8 @@ 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
@@ -1777,11 +1812,14 @@ gst_base_video_decoder_lost_sync (GstBaseVideoDecoder * base_video_decoder)
 
   GST_DEBUG_OBJECT (base_video_decoder, "lost_sync");
 
+  GST_BASE_VIDEO_CODEC_STREAM_LOCK (base_video_decoder);
+
   if (gst_adapter_available (base_video_decoder->input_adapter) >= 1) {
     gst_adapter_flush (base_video_decoder->input_adapter, 1);
   }
 
   base_video_decoder->have_sync = FALSE;
+  GST_BASE_VIDEO_CODEC_STREAM_UNLOCK (base_video_decoder);
 }
 
 /* FIXME not quite exciting; get rid of this ? */
@@ -1796,8 +1834,10 @@ gst_base_video_decoder_set_sync_point (GstBaseVideoDecoder * base_video_decoder)
 {
   GST_DEBUG_OBJECT (base_video_decoder, "set_sync_point");
 
+  GST_BASE_VIDEO_CODEC_STREAM_LOCK (base_video_decoder);
   base_video_decoder->current_frame->is_sync_point = TRUE;
   base_video_decoder->distance_from_sync = 0;
+  GST_BASE_VIDEO_CODEC_STREAM_UNLOCK (base_video_decoder);
 }
 
 /**
@@ -1812,9 +1852,9 @@ gst_base_video_decoder_get_oldest_frame (GstBaseVideoDecoder *
 {
   GList *g;
 
-  GST_OBJECT_LOCK (base_video_decoder);
+  GST_BASE_VIDEO_CODEC_STREAM_LOCK (base_video_decoder);
   g = g_list_first (GST_BASE_VIDEO_CODEC (base_video_decoder)->frames);
-  GST_OBJECT_UNLOCK (base_video_decoder);
+  GST_BASE_VIDEO_CODEC_STREAM_UNLOCK (base_video_decoder);
 
   if (g == NULL)
     return NULL;
@@ -1835,7 +1875,7 @@ gst_base_video_decoder_get_frame (GstBaseVideoDecoder * base_video_decoder,
   GList *g;
   GstVideoFrame *frame = NULL;
 
-  GST_OBJECT_LOCK (base_video_decoder);
+  GST_BASE_VIDEO_CODEC_STREAM_LOCK (base_video_decoder);
   for (g = g_list_first (GST_BASE_VIDEO_CODEC (base_video_decoder)->frames);
       g; g = g_list_next (g)) {
     GstVideoFrame *tmp = g->data;
@@ -1845,7 +1885,7 @@ gst_base_video_decoder_get_frame (GstBaseVideoDecoder * base_video_decoder,
       break;
     }
   }
-  GST_OBJECT_UNLOCK (base_video_decoder);
+  GST_BASE_VIDEO_CODEC_STREAM_UNLOCK (base_video_decoder);
 
   return frame;
 }
@@ -1869,6 +1909,8 @@ gst_base_video_decoder_set_src_caps (GstBaseVideoDecoder * base_video_decoder)
   g_return_val_if_fail (state->width != 0, FALSE);
   g_return_val_if_fail (state->height != 0, FALSE);
 
+  GST_BASE_VIDEO_CODEC_STREAM_LOCK (base_video_decoder);
+
   /* sanitize */
   if (state->fps_n == 0 || state->fps_d == 0) {
     state->fps_n = 0;
@@ -1896,6 +1938,8 @@ gst_base_video_decoder_set_src_caps (GstBaseVideoDecoder * base_video_decoder)
   state->bytes_per_picture =
       gst_video_format_get_size (state->format, state->width, state->height);
 
+  GST_BASE_VIDEO_CODEC_STREAM_UNLOCK (base_video_decoder);
+
   return ret;
 }
 
@@ -1920,6 +1964,9 @@ gst_base_video_decoder_alloc_src_buffer (GstBaseVideoDecoder *
 
   GST_DEBUG ("alloc src buffer caps=%" GST_PTR_FORMAT,
       GST_PAD_CAPS (GST_BASE_VIDEO_CODEC_SRC_PAD (base_video_decoder)));
+
+  GST_BASE_VIDEO_CODEC_STREAM_LOCK (base_video_decoder);
+
   flow_ret =
       gst_pad_alloc_buffer_and_set_caps (GST_BASE_VIDEO_CODEC_SRC_PAD
       (base_video_decoder), GST_BUFFER_OFFSET_NONE, num_bytes,
@@ -1932,6 +1979,7 @@ gst_base_video_decoder_alloc_src_buffer (GstBaseVideoDecoder *
         GST_PAD_CAPS (GST_BASE_VIDEO_CODEC_SRC_PAD (base_video_decoder)));
   }
 
+  GST_BASE_VIDEO_CODEC_STREAM_UNLOCK (base_video_decoder);
   return buffer;
 }
 
@@ -1960,6 +2008,8 @@ gst_base_video_decoder_alloc_src_frame (GstBaseVideoDecoder *
           (base_video_decoder)) != NULL, GST_FLOW_ERROR);
 
   GST_LOG_OBJECT (base_video_decoder, "alloc buffer size %d", num_bytes);
+  GST_BASE_VIDEO_CODEC_STREAM_LOCK (base_video_decoder);
+
   flow_ret =
       gst_pad_alloc_buffer_and_set_caps (GST_BASE_VIDEO_CODEC_SRC_PAD
       (base_video_decoder), GST_BUFFER_OFFSET_NONE, num_bytes,
@@ -1971,6 +2021,8 @@ gst_base_video_decoder_alloc_src_frame (GstBaseVideoDecoder *
         gst_flow_get_name (flow_ret));
   }
 
+  GST_BASE_VIDEO_CODEC_STREAM_UNLOCK (base_video_decoder);
+
   return flow_ret;
 }
 
@@ -1993,6 +2045,7 @@ gst_base_video_decoder_get_max_decode_time (GstBaseVideoDecoder *
   GstClockTimeDiff deadline;
   GstClockTime earliest_time;
 
+  GST_OBJECT_LOCK (base_video_decoder);
   earliest_time = GST_BASE_VIDEO_CODEC (base_video_decoder)->earliest_time;
   if (GST_CLOCK_TIME_IS_VALID (earliest_time))
     deadline = GST_CLOCK_DIFF (earliest_time, frame->deadline);
@@ -2004,6 +2057,8 @@ gst_base_video_decoder_get_max_decode_time (GstBaseVideoDecoder *
       GST_TIME_ARGS (earliest_time), GST_TIME_ARGS (frame->deadline),
       GST_TIME_ARGS (deadline));
 
+  GST_OBJECT_UNLOCK (base_video_decoder);
+
   return deadline;
 }
 
index c81dae7..e1c2c77 100644 (file)
@@ -174,6 +174,8 @@ gst_base_video_encoder_class_init (GstBaseVideoEncoderClass * klass)
 static void
 gst_base_video_encoder_reset (GstBaseVideoEncoder * base_video_encoder)
 {
+  GST_BASE_VIDEO_CODEC_STREAM_LOCK (base_video_encoder);
+
   base_video_encoder->presentation_frame_number = 0;
   base_video_encoder->distance_from_sync = 0;
   base_video_encoder->force_keyframe = FALSE;
@@ -191,6 +193,8 @@ gst_base_video_encoder_reset (GstBaseVideoEncoder * base_video_encoder)
       (GFunc) gst_event_unref, NULL);
   g_list_free (base_video_encoder->current_frame_events);
   base_video_encoder->current_frame_events = NULL;
+
+  GST_BASE_VIDEO_CODEC_STREAM_UNLOCK (base_video_encoder);
 }
 
 static void
@@ -283,6 +287,8 @@ gst_base_video_encoder_sink_setcaps (GstPad * pad, GstCaps * caps)
 
   GST_DEBUG_OBJECT (base_video_encoder, "setcaps %" GST_PTR_FORMAT, caps);
 
+  GST_BASE_VIDEO_CODEC_STREAM_LOCK (base_video_encoder);
+
   state = &GST_BASE_VIDEO_CODEC (base_video_encoder)->state;
   memset (&tmp_state, 0, sizeof (tmp_state));
 
@@ -349,13 +355,15 @@ gst_base_video_encoder_sink_setcaps (GstPad * pad, GstCaps * caps)
   }
 
 exit:
-  g_object_unref (base_video_encoder);
+  GST_BASE_VIDEO_CODEC_STREAM_UNLOCK (base_video_encoder);
 
   if (!ret) {
     GST_WARNING_OBJECT (base_video_encoder, "rejected caps %" GST_PTR_FORMAT,
         caps);
   }
 
+  g_object_unref (base_video_encoder);
+
   return ret;
 }
 
@@ -450,6 +458,7 @@ gst_base_video_encoder_sink_eventfunc (GstBaseVideoEncoder * base_video_encoder,
     {
       GstFlowReturn flow_ret;
 
+      GST_BASE_VIDEO_CODEC_STREAM_LOCK (base_video_encoder);
       base_video_encoder->a.at_eos = TRUE;
 
       if (base_video_encoder_class->finish) {
@@ -459,6 +468,7 @@ gst_base_video_encoder_sink_eventfunc (GstBaseVideoEncoder * base_video_encoder,
       }
 
       ret = (flow_ret == GST_BASE_VIDEO_ENCODER_FLOW_DROPPED);
+      GST_BASE_VIDEO_CODEC_STREAM_UNLOCK (base_video_encoder);
       break;
     }
     case GST_EVENT_NEWSEGMENT:
@@ -471,6 +481,7 @@ gst_base_video_encoder_sink_eventfunc (GstBaseVideoEncoder * base_video_encoder,
       gint64 stop;
       gint64 position;
 
+      GST_BASE_VIDEO_CODEC_STREAM_LOCK (base_video_encoder);
       gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate,
           &format, &start, &stop, &position);
 
@@ -482,6 +493,7 @@ gst_base_video_encoder_sink_eventfunc (GstBaseVideoEncoder * base_video_encoder,
 
       if (format != GST_FORMAT_TIME) {
         GST_DEBUG_OBJECT (base_video_encoder, "received non TIME newsegment");
+        GST_BASE_VIDEO_CODEC_STREAM_UNLOCK (base_video_encoder);
         break;
       }
 
@@ -490,6 +502,7 @@ gst_base_video_encoder_sink_eventfunc (GstBaseVideoEncoder * base_video_encoder,
       gst_segment_set_newsegment_full (&GST_BASE_VIDEO_CODEC
           (base_video_encoder)->segment, update, rate, applied_rate, format,
           start, stop, position);
+      GST_BASE_VIDEO_CODEC_STREAM_UNLOCK (base_video_encoder);
       break;
     }
     case GST_EVENT_CUSTOM_DOWNSTREAM:
@@ -554,8 +567,10 @@ gst_base_video_encoder_sink_event (GstPad * pad, GstEvent * event)
         || GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_STOP) {
       ret = gst_pad_push_event (enc->base_video_codec.srcpad, event);
     } else {
+      GST_BASE_VIDEO_CODEC_STREAM_LOCK (enc);
       enc->current_frame_events =
           g_list_prepend (enc->current_frame_events, event);
+      GST_BASE_VIDEO_CODEC_STREAM_UNLOCK (enc);
     }
   }
 
@@ -697,8 +712,11 @@ gst_base_video_encoder_chain (GstPad * pad, GstBuffer * buf)
 
   g_return_val_if_fail (klass->handle_frame != NULL, GST_FLOW_ERROR);
 
+  GST_BASE_VIDEO_CODEC_STREAM_LOCK (base_video_encoder);
+
   if (!GST_PAD_CAPS (pad)) {
-    return GST_FLOW_NOT_NEGOTIATED;
+    ret = GST_FLOW_NOT_NEGOTIATED;
+    goto done;
   }
 
   GST_LOG_OBJECT (base_video_encoder,
@@ -708,7 +726,8 @@ gst_base_video_encoder_chain (GstPad * pad, GstBuffer * buf)
       GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
 
   if (base_video_encoder->a.at_eos) {
-    return GST_FLOW_UNEXPECTED;
+    ret = GST_FLOW_UNEXPECTED;
+    goto done;
   }
 
   if (base_video_encoder->sink_clipping) {
@@ -744,10 +763,8 @@ gst_base_video_encoder_chain (GstPad * pad, GstBuffer * buf)
   frame->force_keyframe = base_video_encoder->force_keyframe;
   base_video_encoder->force_keyframe = FALSE;
 
-  GST_OBJECT_LOCK (base_video_encoder);
   GST_BASE_VIDEO_CODEC (base_video_encoder)->frames =
       g_list_append (GST_BASE_VIDEO_CODEC (base_video_encoder)->frames, frame);
-  GST_OBJECT_UNLOCK (base_video_encoder);
 
   /* new data, more finish needed */
   base_video_encoder->drained = FALSE;
@@ -758,6 +775,8 @@ gst_base_video_encoder_chain (GstPad * pad, GstBuffer * buf)
   ret = klass->handle_frame (base_video_encoder, frame);
 
 done:
+  GST_BASE_VIDEO_CODEC_STREAM_UNLOCK (base_video_encoder);
+
   g_object_unref (base_video_encoder);
 
   return ret;
@@ -829,6 +848,8 @@ gst_base_video_encoder_finish_frame (GstBaseVideoEncoder * base_video_encoder,
   GST_LOG_OBJECT (base_video_encoder,
       "finish frame fpn %d", frame->presentation_frame_number);
 
+  GST_BASE_VIDEO_CODEC_STREAM_LOCK (base_video_encoder);
+
   /* Push all pending events that arrived before this frame */
   for (l = base_video_encoder->base_video_codec.frames; l; l = l->next) {
     GstVideoFrame *tmp = l->data;
@@ -943,13 +964,13 @@ gst_base_video_encoder_finish_frame (GstBaseVideoEncoder * base_video_encoder,
 
 done:
   /* handed out */
-  GST_OBJECT_LOCK (base_video_encoder);
   GST_BASE_VIDEO_CODEC (base_video_encoder)->frames =
       g_list_remove (GST_BASE_VIDEO_CODEC (base_video_encoder)->frames, frame);
-  GST_OBJECT_UNLOCK (base_video_encoder);
 
   gst_base_video_codec_free_frame (frame);
 
+  GST_BASE_VIDEO_CODEC_STREAM_UNLOCK (base_video_encoder);
+
   return ret;
 }
 
@@ -1023,9 +1044,9 @@ gst_base_video_encoder_get_oldest_frame (GstBaseVideoEncoder *
 {
   GList *g;
 
-  GST_OBJECT_LOCK (base_video_encoder);
+  GST_BASE_VIDEO_CODEC_STREAM_LOCK (base_video_encoder);
   g = g_list_first (GST_BASE_VIDEO_CODEC (base_video_encoder)->frames);
-  GST_OBJECT_UNLOCK (base_video_encoder);
+  GST_BASE_VIDEO_CODEC_STREAM_UNLOCK (base_video_encoder);
 
   if (g == NULL)
     return NULL;