mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-29 05:01:23 +00:00
videodecoder: don't take STREAM_LOCK on upstream events
Don't try to take STREAM_LOCK on upstream events such as QOS. Protect qos-related variables with object lock instead. Fixes possible deadlock when shutting down in certain situations. https://bugzilla.gnome.org/show_bug.cgi?id=684658
This commit is contained in:
parent
386206e627
commit
62c111f1e4
1 changed files with 28 additions and 14 deletions
|
@ -382,8 +382,9 @@ struct _GstVideoDecoderPrivate
|
||||||
gboolean output_state_changed;
|
gboolean output_state_changed;
|
||||||
|
|
||||||
/* QoS properties */
|
/* QoS properties */
|
||||||
gdouble proportion;
|
gdouble proportion; /* OBJECT_LOCK */
|
||||||
GstClockTime earliest_time;
|
GstClockTime earliest_time; /* OBJECT_LOCK */
|
||||||
|
GstClockTime qos_frame_duration; /* OBJECT_LOCK */
|
||||||
gboolean discont;
|
gboolean discont;
|
||||||
/* qos messages: frames dropped/processed */
|
/* qos messages: frames dropped/processed */
|
||||||
guint dropped;
|
guint dropped;
|
||||||
|
@ -1261,7 +1262,6 @@ gst_video_decoder_src_event_default (GstVideoDecoder * decoder,
|
||||||
gdouble proportion;
|
gdouble proportion;
|
||||||
GstClockTimeDiff diff;
|
GstClockTimeDiff diff;
|
||||||
GstClockTime timestamp;
|
GstClockTime timestamp;
|
||||||
GstClockTime duration;
|
|
||||||
|
|
||||||
gst_event_parse_qos (event, &type, &proportion, &diff, ×tamp);
|
gst_event_parse_qos (event, &type, &proportion, &diff, ×tamp);
|
||||||
|
|
||||||
|
@ -1269,15 +1269,7 @@ 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)) {
|
||||||
GST_VIDEO_DECODER_STREAM_LOCK (decoder);
|
priv->earliest_time = timestamp + 2 * diff + priv->qos_frame_duration;
|
||||||
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 {
|
} else {
|
||||||
priv->earliest_time = timestamp + diff;
|
priv->earliest_time = timestamp + diff;
|
||||||
}
|
}
|
||||||
|
@ -1614,6 +1606,11 @@ gst_video_decoder_reset (GstVideoDecoder * decoder, gboolean full)
|
||||||
if (priv->output_state)
|
if (priv->output_state)
|
||||||
gst_video_codec_state_unref (priv->output_state);
|
gst_video_codec_state_unref (priv->output_state);
|
||||||
priv->output_state = NULL;
|
priv->output_state = NULL;
|
||||||
|
|
||||||
|
GST_OBJECT_LOCK (decoder);
|
||||||
|
priv->qos_frame_duration = 0;
|
||||||
|
GST_OBJECT_UNLOCK (decoder);
|
||||||
|
|
||||||
priv->min_latency = 0;
|
priv->min_latency = 0;
|
||||||
priv->max_latency = 0;
|
priv->max_latency = 0;
|
||||||
|
|
||||||
|
@ -1652,8 +1649,10 @@ gst_video_decoder_reset (GstVideoDecoder * decoder, gboolean full)
|
||||||
priv->bytes_out = 0;
|
priv->bytes_out = 0;
|
||||||
priv->time = 0;
|
priv->time = 0;
|
||||||
|
|
||||||
|
GST_OBJECT_LOCK (decoder);
|
||||||
priv->earliest_time = GST_CLOCK_TIME_NONE;
|
priv->earliest_time = GST_CLOCK_TIME_NONE;
|
||||||
priv->proportion = 0.5;
|
priv->proportion = 0.5;
|
||||||
|
GST_OBJECT_UNLOCK (decoder);
|
||||||
|
|
||||||
GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
|
GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
|
||||||
}
|
}
|
||||||
|
@ -2226,13 +2225,16 @@ gst_video_decoder_drop_frame (GstVideoDecoder * dec, GstVideoCodecFrame * frame)
|
||||||
dec->priv->dropped++;
|
dec->priv->dropped++;
|
||||||
|
|
||||||
/* post QoS message */
|
/* post QoS message */
|
||||||
timestamp = frame->pts;
|
GST_OBJECT_LOCK (dec);
|
||||||
proportion = dec->priv->proportion;
|
proportion = dec->priv->proportion;
|
||||||
|
earliest_time = dec->priv->earliest_time;
|
||||||
|
GST_OBJECT_UNLOCK (dec);
|
||||||
|
|
||||||
|
timestamp = frame->pts;
|
||||||
segment = &dec->output_segment;
|
segment = &dec->output_segment;
|
||||||
stream_time =
|
stream_time =
|
||||||
gst_segment_to_stream_time (segment, GST_FORMAT_TIME, timestamp);
|
gst_segment_to_stream_time (segment, GST_FORMAT_TIME, timestamp);
|
||||||
qostime = gst_segment_to_running_time (segment, GST_FORMAT_TIME, timestamp);
|
qostime = gst_segment_to_running_time (segment, GST_FORMAT_TIME, timestamp);
|
||||||
earliest_time = dec->priv->earliest_time;
|
|
||||||
jitter = GST_CLOCK_DIFF (qostime, earliest_time);
|
jitter = GST_CLOCK_DIFF (qostime, earliest_time);
|
||||||
qos_msg =
|
qos_msg =
|
||||||
gst_message_new_qos (GST_OBJECT_CAST (dec), FALSE, qostime, stream_time,
|
gst_message_new_qos (GST_OBJECT_CAST (dec), FALSE, qostime, stream_time,
|
||||||
|
@ -2629,6 +2631,7 @@ gst_video_decoder_set_output_state (GstVideoDecoder * decoder,
|
||||||
{
|
{
|
||||||
GstVideoDecoderPrivate *priv = decoder->priv;
|
GstVideoDecoderPrivate *priv = decoder->priv;
|
||||||
GstVideoCodecState *state;
|
GstVideoCodecState *state;
|
||||||
|
GstClockTime qos_frame_duration;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (decoder, "fmt:%d, width:%d, height:%d, reference:%p",
|
GST_DEBUG_OBJECT (decoder, "fmt:%d, width:%d, height:%d, reference:%p",
|
||||||
fmt, width, height, reference);
|
fmt, width, height, reference);
|
||||||
|
@ -2642,9 +2645,20 @@ gst_video_decoder_set_output_state (GstVideoDecoder * decoder,
|
||||||
gst_video_codec_state_unref (priv->output_state);
|
gst_video_codec_state_unref (priv->output_state);
|
||||||
priv->output_state = gst_video_codec_state_ref (state);
|
priv->output_state = gst_video_codec_state_ref (state);
|
||||||
|
|
||||||
|
if (priv->output_state != NULL && priv->output_state->info.fps_n > 0) {
|
||||||
|
qos_frame_duration =
|
||||||
|
gst_util_uint64_scale (GST_SECOND, priv->output_state->info.fps_d,
|
||||||
|
priv->output_state->info.fps_n);
|
||||||
|
} else {
|
||||||
|
qos_frame_duration = 0;
|
||||||
|
}
|
||||||
priv->output_state_changed = TRUE;
|
priv->output_state_changed = TRUE;
|
||||||
GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
|
GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
|
||||||
|
|
||||||
|
GST_OBJECT_LOCK (decoder);
|
||||||
|
priv->qos_frame_duration = qos_frame_duration;
|
||||||
|
GST_OBJECT_UNLOCK (decoder);
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue