query: v4l2videodec: race condition between drain and source change
This is the commit to cancel source change when drain.
Author: Nicolas Dufresne <nicolas.dufresne@collabora.com>
Date: Wed Apr 19 14:19:13 2023 -0400
v4l2: videodec: Don't forcibly drain on resolution changes
Let the driver detects the change and reconfigure the capture side
transparently from there. This avoid reallocation of the output buffers,
and eliminates the need to stop and restart the capture task. This is
only happening if the driver have support for this, otherwise the old
behaviour is maintained.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4437>
But it may cause decoder hang when do fast backward for resolution change streams. Here is the steps:
- decoder first dequeue a source change event, set self->draining flag to TRUE, which will be used to do capture streamoff and capture streamon.
- At this time, decoder drains and set self->draining flag to FALSE, it cancels above source change.
- Then do seek (output/capture streamoff -> ... -> output/capture streamon).
In this case, source change is canceled before seek. But some drivers need to handle source change first and then handle the seek, otherwise decoder cannot finish capture streamon and hang.
I would like to ask if this commit by default all drivers support canceling source change. If not, is below change feasible?
diff --git a/sys/v4l2/gstv4l2videodec.c b/sys/v4l2/gstv4l2videodec.c
index f59a11052..1e6343244 100644
--- a/sys/v4l2/gstv4l2videodec.c
+++ b/sys/v4l2/gstv4l2videodec.c
@@ -688,9 +688,6 @@ gst_v4l2_video_dec_finish (GstVideoDecoder * decoder)
GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
- /* If we are in the middle of a source change, cancel it */
- self->draining = FALSE;
-
if (gst_v4l2_decoder_cmd (self->v4l2output, V4L2_DEC_CMD_STOP, 0)) {
GstTask *task;
@@ -737,6 +734,7 @@ gst_v4l2_video_dec_finish (GstVideoDecoder * decoder)
* occurred. */
gst_v4l2_object_unlock (self->v4l2capture);
gst_pad_stop_task (decoder->srcpad);
+ self->draining = FALSE;
GST_VIDEO_DECODER_STREAM_LOCK (decoder);
if (ret == GST_FLOW_FLUSHING)