mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 12:11:13 +00:00
vaapidecode: fix dead-locks with decoder task.
Review all interactions between the main video decoder stream thread and the decode task to derive a correct sequence of operations for decoding. Also avoid extra atomic operations that become implicit under the GstVideoDecoder stream lock.
This commit is contained in:
parent
6e85f08e33
commit
af4785b722
2 changed files with 34 additions and 18 deletions
|
@ -238,10 +238,6 @@ gst_vaapidecode_decode_frame(GstVideoDecoder *vdec, GstVideoCodecFrame *frame)
|
|||
GstVaapiDecoderStatus status;
|
||||
GstFlowReturn ret;
|
||||
|
||||
ret = g_atomic_int_get(&decode->decoder_loop_status);
|
||||
if (ret != GST_FLOW_OK)
|
||||
return ret;
|
||||
|
||||
/* Decode current frame */
|
||||
for (;;) {
|
||||
status = gst_vaapi_decoder_decode(decode->decoder, frame);
|
||||
|
@ -251,6 +247,8 @@ gst_vaapidecode_decode_frame(GstVideoDecoder *vdec, GstVideoCodecFrame *frame)
|
|||
g_cond_wait(&decode->decoder_ready, &decode->decoder_mutex);
|
||||
g_mutex_unlock(&decode->decoder_mutex);
|
||||
GST_VIDEO_DECODER_STREAM_LOCK(vdec);
|
||||
if (decode->decoder_loop_status < 0)
|
||||
goto error_decode_loop;
|
||||
continue;
|
||||
}
|
||||
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
|
||||
|
@ -259,10 +257,17 @@ gst_vaapidecode_decode_frame(GstVideoDecoder *vdec, GstVideoCodecFrame *frame)
|
|||
}
|
||||
|
||||
/* Try to report back early any error that occured in the decode task */
|
||||
ret = g_atomic_int_get(&decode->decoder_loop_status);
|
||||
return ret;
|
||||
GST_VIDEO_DECODER_STREAM_UNLOCK(vdec);
|
||||
GST_VIDEO_DECODER_STREAM_LOCK(vdec);
|
||||
return decode->decoder_loop_status;
|
||||
|
||||
/* ERRORS */
|
||||
error_decode_loop:
|
||||
{
|
||||
GST_ERROR("decode loop error %d", decode->decoder_loop_status);
|
||||
gst_video_decoder_drop_frame(vdec, frame);
|
||||
return decode->decoder_loop_status;
|
||||
}
|
||||
error_decode:
|
||||
{
|
||||
GST_ERROR("decode error %d", status);
|
||||
|
@ -282,12 +287,11 @@ error_decode:
|
|||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_vaapidecode_push_decoded_frame(GstVideoDecoder *vdec)
|
||||
gst_vaapidecode_push_decoded_frame(GstVideoDecoder *vdec,
|
||||
GstVideoCodecFrame *out_frame)
|
||||
{
|
||||
GstVaapiDecode * const decode = GST_VAAPIDECODE(vdec);
|
||||
GstVaapiSurfaceProxy *proxy;
|
||||
GstVaapiDecoderStatus status;
|
||||
GstVideoCodecFrame *out_frame;
|
||||
GstFlowReturn ret;
|
||||
#if GST_CHECK_VERSION(1,0,0)
|
||||
const GstVaapiRectangle *crop_rect;
|
||||
|
@ -295,11 +299,6 @@ gst_vaapidecode_push_decoded_frame(GstVideoDecoder *vdec)
|
|||
guint flags;
|
||||
#endif
|
||||
|
||||
status = gst_vaapi_decoder_get_frame_with_timeout(decode->decoder,
|
||||
&out_frame, 100000);
|
||||
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
|
||||
return GST_VIDEO_DECODER_FLOW_NEED_DATA;
|
||||
|
||||
if (!GST_VIDEO_CODEC_FRAME_IS_DECODE_ONLY(out_frame)) {
|
||||
proxy = gst_video_codec_frame_get_user_data(out_frame);
|
||||
|
||||
|
@ -407,13 +406,30 @@ static void
|
|||
gst_vaapidecode_decode_loop(GstVaapiDecode *decode)
|
||||
{
|
||||
GstVideoDecoder * const vdec = GST_VIDEO_DECODER(decode);
|
||||
GstVaapiDecoderStatus status;
|
||||
GstVideoCodecFrame *out_frame;
|
||||
GstFlowReturn ret;
|
||||
|
||||
ret = gst_vaapidecode_push_decoded_frame(vdec);
|
||||
status = gst_vaapi_decoder_get_frame_with_timeout(decode->decoder,
|
||||
&out_frame, 100000);
|
||||
|
||||
GST_VIDEO_DECODER_STREAM_LOCK(vdec);
|
||||
switch (status) {
|
||||
case GST_VAAPI_DECODER_STATUS_SUCCESS:
|
||||
ret = gst_vaapidecode_push_decoded_frame(vdec, out_frame);
|
||||
break;
|
||||
case GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA:
|
||||
ret = GST_VIDEO_DECODER_FLOW_NEED_DATA;
|
||||
break;
|
||||
default:
|
||||
ret = GST_FLOW_ERROR;
|
||||
break;
|
||||
}
|
||||
decode->decoder_loop_status = ret;
|
||||
GST_VIDEO_DECODER_STREAM_UNLOCK(vdec);
|
||||
|
||||
if (ret == GST_FLOW_OK)
|
||||
return;
|
||||
g_atomic_int_compare_and_exchange(&decode->decoder_loop_status,
|
||||
GST_FLOW_OK, ret);
|
||||
|
||||
/* If invoked from gst_vaapidecode_finish(), then return right
|
||||
away no matter the errors, or the GstVaapiDecoder needs further
|
||||
|
|
|
@ -72,7 +72,7 @@ struct _GstVaapiDecode {
|
|||
GstVaapiDecoder *decoder;
|
||||
GMutex decoder_mutex;
|
||||
GCond decoder_ready;
|
||||
volatile gint decoder_loop_status;
|
||||
GstFlowReturn decoder_loop_status;
|
||||
volatile gboolean decoder_finish;
|
||||
GCond decoder_finish_done;
|
||||
GstCaps *decoder_caps;
|
||||
|
|
Loading…
Reference in a new issue