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;
|
||||
|
||||
/* QoS properties */
|
||||
gdouble proportion;
|
||||
GstClockTime earliest_time;
|
||||
gdouble proportion; /* OBJECT_LOCK */
|
||||
GstClockTime earliest_time; /* OBJECT_LOCK */
|
||||
GstClockTime qos_frame_duration; /* OBJECT_LOCK */
|
||||
gboolean discont;
|
||||
/* qos messages: frames dropped/processed */
|
||||
guint dropped;
|
||||
|
@ -1261,7 +1262,6 @@ gst_video_decoder_src_event_default (GstVideoDecoder * decoder,
|
|||
gdouble proportion;
|
||||
GstClockTimeDiff diff;
|
||||
GstClockTime timestamp;
|
||||
GstClockTime duration;
|
||||
|
||||
gst_event_parse_qos (event, &type, &proportion, &diff, ×tamp);
|
||||
|
||||
|
@ -1269,15 +1269,7 @@ 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)) {
|
||||
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;
|
||||
priv->earliest_time = timestamp + 2 * diff + priv->qos_frame_duration;
|
||||
} else {
|
||||
priv->earliest_time = timestamp + diff;
|
||||
}
|
||||
|
@ -1614,6 +1606,11 @@ gst_video_decoder_reset (GstVideoDecoder * decoder, gboolean full)
|
|||
if (priv->output_state)
|
||||
gst_video_codec_state_unref (priv->output_state);
|
||||
priv->output_state = NULL;
|
||||
|
||||
GST_OBJECT_LOCK (decoder);
|
||||
priv->qos_frame_duration = 0;
|
||||
GST_OBJECT_UNLOCK (decoder);
|
||||
|
||||
priv->min_latency = 0;
|
||||
priv->max_latency = 0;
|
||||
|
||||
|
@ -1652,8 +1649,10 @@ gst_video_decoder_reset (GstVideoDecoder * decoder, gboolean full)
|
|||
priv->bytes_out = 0;
|
||||
priv->time = 0;
|
||||
|
||||
GST_OBJECT_LOCK (decoder);
|
||||
priv->earliest_time = GST_CLOCK_TIME_NONE;
|
||||
priv->proportion = 0.5;
|
||||
GST_OBJECT_UNLOCK (decoder);
|
||||
|
||||
GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
|
||||
}
|
||||
|
@ -2226,13 +2225,16 @@ gst_video_decoder_drop_frame (GstVideoDecoder * dec, GstVideoCodecFrame * frame)
|
|||
dec->priv->dropped++;
|
||||
|
||||
/* post QoS message */
|
||||
timestamp = frame->pts;
|
||||
GST_OBJECT_LOCK (dec);
|
||||
proportion = dec->priv->proportion;
|
||||
earliest_time = dec->priv->earliest_time;
|
||||
GST_OBJECT_UNLOCK (dec);
|
||||
|
||||
timestamp = frame->pts;
|
||||
segment = &dec->output_segment;
|
||||
stream_time =
|
||||
gst_segment_to_stream_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);
|
||||
qos_msg =
|
||||
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;
|
||||
GstVideoCodecState *state;
|
||||
GstClockTime qos_frame_duration;
|
||||
|
||||
GST_DEBUG_OBJECT (decoder, "fmt:%d, width:%d, height:%d, reference:%p",
|
||||
fmt, width, height, reference);
|
||||
|
@ -2642,9 +2645,20 @@ gst_video_decoder_set_output_state (GstVideoDecoder * decoder,
|
|||
gst_video_codec_state_unref (priv->output_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;
|
||||
GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
|
||||
|
||||
GST_OBJECT_LOCK (decoder);
|
||||
priv->qos_frame_duration = qos_frame_duration;
|
||||
GST_OBJECT_UNLOCK (decoder);
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue