From 8c743fbc0fb211563e98b1955ae08f374f9c0a25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Thu, 18 Aug 2011 08:02:50 +0000 Subject: [PATCH] basevideo: Fix locking, especially if both pads have different streaming threads --- gst-libs/gst/video/gstbasevideocodec.c | 11 ++- gst-libs/gst/video/gstbasevideocodec.h | 8 ++ gst-libs/gst/video/gstbasevideodecoder.c | 93 +++++++++++++++++++----- gst-libs/gst/video/gstbasevideoencoder.c | 39 +++++++--- 4 files changed, 121 insertions(+), 30 deletions(-) diff --git a/gst-libs/gst/video/gstbasevideocodec.c b/gst-libs/gst/video/gstbasevideocodec.c index 31fa5e5df6..68e203d552 100644 --- a/gst-libs/gst/video/gstbasevideocodec.c +++ b/gst-libs/gst/video/gstbasevideocodec.c @@ -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; } diff --git a/gst-libs/gst/video/gstbasevideocodec.h b/gst-libs/gst/video/gstbasevideocodec.h index c1e37120d9..6471c352f5 100644 --- a/gst-libs/gst/video/gstbasevideocodec.h +++ b/gst-libs/gst/video/gstbasevideocodec.h @@ -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 */ diff --git a/gst-libs/gst/video/gstbasevideodecoder.c b/gst-libs/gst/video/gstbasevideodecoder.c index 0e08a884b2..1b01ed701c 100644 --- a/gst-libs/gst/video/gstbasevideodecoder.c +++ b/gst-libs/gst/video/gstbasevideodecoder.c @@ -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_UNLOCK (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; } diff --git a/gst-libs/gst/video/gstbasevideoencoder.c b/gst-libs/gst/video/gstbasevideoencoder.c index c81dae7f9b..e1c2c77a62 100644 --- a/gst-libs/gst/video/gstbasevideoencoder.c +++ b/gst-libs/gst/video/gstbasevideoencoder.c @@ -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;