videodecoder: Protect all accesses to priv->output_frame with the stream lock

Fixes segfault as queries/events can happen after a reset
This commit is contained in:
Olivier Crête 2012-09-19 21:16:01 -04:00
parent 6dd8302029
commit ebae8ffa71

View File

@ -1254,12 +1254,14 @@ gst_video_decoder_src_event_default (GstVideoDecoder * decoder,
priv->proportion = proportion; priv->proportion = proportion;
if (G_LIKELY (GST_CLOCK_TIME_IS_VALID (timestamp))) { if (G_LIKELY (GST_CLOCK_TIME_IS_VALID (timestamp))) {
if (G_UNLIKELY (diff > 0)) { 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 = duration =
gst_util_uint64_scale (GST_SECOND, gst_util_uint64_scale (GST_SECOND,
priv->output_state->info.fps_d, priv->output_state->info.fps_n); priv->output_state->info.fps_d, priv->output_state->info.fps_n);
else else
duration = 0; duration = 0;
GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
priv->earliest_time = timestamp + 2 * diff + duration; priv->earliest_time = timestamp + 2 * diff + duration;
} else { } else {
priv->earliest_time = timestamp + diff; 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_DEBUG_OBJECT (dec, "convert query");
gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val); gst_query_parse_convert (query, &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, res = gst_video_rawvideo_convert (dec->priv->output_state,
src_fmt, src_val, &dest_fmt, &dest_val); src_fmt, src_val, &dest_fmt, &dest_val);
else
res = FALSE;
GST_VIDEO_DECODER_STREAM_UNLOCK (dec);
if (!res) if (!res)
goto error; goto error;
gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val); 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); res = gst_pad_peer_query (dec->sinkpad, query);
if (res) { if (res) {
gst_query_parse_latency (query, &live, &min_latency, &max_latency); 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_FORMAT " max %" GST_TIME_FORMAT, live,
GST_TIME_ARGS (min_latency), GST_TIME_ARGS (max_latency)); GST_TIME_ARGS (min_latency), GST_TIME_ARGS (max_latency));
@ -2944,13 +2951,24 @@ gst_video_decoder_allocate_output_frame (GstVideoDecoder *
decoder, GstVideoCodecFrame * frame) decoder, GstVideoCodecFrame * frame)
{ {
GstFlowReturn flow_ret; GstFlowReturn flow_ret;
GstVideoCodecState *state = decoder->priv->output_state; GstVideoCodecState *state;
int num_bytes = GST_VIDEO_INFO_SIZE (&state->info); 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); g_return_val_if_fail (frame->output_buffer == NULL, GST_FLOW_ERROR);
GST_VIDEO_DECODER_STREAM_LOCK (decoder); 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 if (G_UNLIKELY (decoder->priv->output_state_changed
|| (decoder->priv->output_state || (decoder->priv->output_state
&& gst_pad_check_reconfigure (decoder->srcpad)))) && gst_pad_check_reconfigure (decoder->srcpad))))
@ -2964,6 +2982,10 @@ gst_video_decoder_allocate_output_frame (GstVideoDecoder *
GST_VIDEO_DECODER_STREAM_UNLOCK (decoder); GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
return flow_ret; return flow_ret;
error:
GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
return GST_FLOW_ERROR;
} }
/** /**