From ebae8ffa71d3dd9cb70b9dced308d8cc3a202444 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Olivier=20Cr=C3=AAte?= Date: Wed, 19 Sep 2012 21:16:01 -0400 Subject: [PATCH] videodecoder: Protect all accesses to priv->output_frame with the stream lock Fixes segfault as queries/events can happen after a reset --- gst-libs/gst/video/gstvideodecoder.c | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/gst-libs/gst/video/gstvideodecoder.c b/gst-libs/gst/video/gstvideodecoder.c index 9c36507..f50f5ac 100644 --- a/gst-libs/gst/video/gstvideodecoder.c +++ b/gst-libs/gst/video/gstvideodecoder.c @@ -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; } /** -- 2.7.4