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;
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);
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;
}
/**