diff options
author | He Junyan <junyan.he@intel.com> | 2021-06-23 16:23:00 +0800 |
---|---|---|
committer | GStreamer Marge Bot <gitlab-merge-bot@gstreamer-foundation.org> | 2021-07-01 11:57:10 +0000 |
commit | 677d1e01051e2ee47439cff7cc7f527bb71afbb8 (patch) | |
tree | 4835ac6c7ed4fd441ae84fb525eb7cb99db20f1e | |
parent | d152ab1d3734e285f3b79ad61bd5facb2364a3af (diff) | |
download | gstreamer-vaapi-677d1e01051e2ee47439cff7cc7f527bb71afbb8.tar.gz |
plugins: encode: fix a deadlock because of _drain()
We call gst_vaapiencode_drain() in gst_vaapiencode_change_state(),
whose context does not hold the stream lock of the encoder. The
current gst_vaapiencode_drain inside unlock/lock pair adds a extra
lock count to the stream lock of encoder and causes hang later.
We just remove the gst_vaapiencode_drain() and expand its logic
correctly according to the lock/unlock context.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer-vaapi/-/merge_requests/433>
-rw-r--r-- | gst/vaapi/gstvaapiencode.c | 49 |
1 files changed, 24 insertions, 25 deletions
diff --git a/gst/vaapi/gstvaapiencode.c b/gst/vaapi/gstvaapiencode.c index b17a81e5..e86d55b9 100644 --- a/gst/vaapi/gstvaapiencode.c +++ b/gst/vaapi/gstvaapiencode.c @@ -558,28 +558,10 @@ set_codec_state (GstVaapiEncode * encode, GstVideoCodecState * state) } static gboolean -gst_vaapiencode_drain (GstVaapiEncode * encode) -{ - GstVaapiEncoderStatus status; - - if (!encode->encoder) - return TRUE; - - GST_VIDEO_ENCODER_STREAM_UNLOCK (encode); - status = gst_vaapi_encoder_flush (encode->encoder); - GST_VIDEO_ENCODER_STREAM_LOCK (encode); - - if (status != GST_VAAPI_ENCODER_STATUS_SUCCESS) - return FALSE; - gst_vaapiencode_purge (encode); - - return TRUE; -} - -static gboolean gst_vaapiencode_set_format (GstVideoEncoder * venc, GstVideoCodecState * state) { GstVaapiEncode *const encode = GST_VAAPIENCODE_CAST (venc); + GstVaapiEncoderStatus status; g_return_val_if_fail (state->caps != NULL, FALSE); @@ -590,9 +572,14 @@ gst_vaapiencode_set_format (GstVideoEncoder * venc, GstVideoCodecState * state) state->caps, NULL)) return FALSE; - if (!gst_vaapiencode_drain (encode)) + GST_VIDEO_ENCODER_STREAM_UNLOCK (encode); + status = gst_vaapi_encoder_flush (encode->encoder); + GST_VIDEO_ENCODER_STREAM_LOCK (encode); + if (status != GST_VAAPI_ENCODER_STATUS_SUCCESS) return FALSE; + gst_vaapiencode_purge (encode); + if (encode->input_state) gst_video_codec_state_unref (encode->input_state); encode->input_state = gst_video_codec_state_ref (state); @@ -745,13 +732,19 @@ static GstStateChangeReturn gst_vaapiencode_change_state (GstElement * element, GstStateChange transition) { GstVaapiEncode *const encode = GST_VAAPIENCODE_CAST (element); + GstVaapiEncoderStatus status; switch (transition) { case GST_STATE_CHANGE_PAUSED_TO_READY: gst_pad_stop_task (GST_VAAPI_PLUGIN_BASE_SRC_PAD (encode)); - if (!gst_vaapiencode_drain (encode)) - goto drain_error; + status = gst_vaapi_encoder_flush (encode->encoder); + if (status != GST_VAAPI_ENCODER_STATUS_SUCCESS) + goto flush_error; + + GST_VIDEO_ENCODER_STREAM_LOCK (encode); + gst_vaapiencode_purge (encode); + GST_VIDEO_ENCODER_STREAM_UNLOCK (encode); break; default: break; @@ -760,9 +753,9 @@ gst_vaapiencode_change_state (GstElement * element, GstStateChange transition) GST_ELEMENT_CLASS (gst_vaapiencode_parent_class)->change_state (element, transition); -drain_error: +flush_error: { - GST_ERROR ("failed to drain pending encoded frames"); + GST_ERROR ("failed to flush pending encoded frames"); return GST_STATE_CHANGE_FAILURE; } } @@ -808,15 +801,21 @@ static gboolean gst_vaapiencode_flush (GstVideoEncoder * venc) { GstVaapiEncode *const encode = GST_VAAPIENCODE_CAST (venc); + GstVaapiEncoderStatus status; if (!encode->encoder) return FALSE; GST_LOG_OBJECT (encode, "flushing"); - if (!gst_vaapiencode_drain (encode)) + GST_VIDEO_ENCODER_STREAM_UNLOCK (encode); + status = gst_vaapi_encoder_flush (encode->encoder); + GST_VIDEO_ENCODER_STREAM_LOCK (encode); + if (status != GST_VAAPI_ENCODER_STATUS_SUCCESS) return FALSE; + gst_vaapiencode_purge (encode); + gst_vaapi_encoder_replace (&encode->encoder, NULL); if (!ensure_encoder (encode)) return FALSE; |