v4l2videodec : enable resolution change 28/272928/1
authorMing Qian <ming.qian@nxp.com>
Tue, 19 Oct 2021 08:10:06 +0000 (16:10 +0800)
committerJeongmo Yang <jm80.yang@samsung.com>
Mon, 28 Mar 2022 05:46:14 +0000 (14:46 +0900)
The dynamic resolution changes when
the sequence starts when the decoder detects a coded frame with one or
more of the following parameters different from those previously
established (and reflected by corresponding queries):
1.coded resolution (OUTPUT width and height),
2.visible resolution (selection rectangles),
3.the minimum number of buffers needed for decoding,
4.bit-depth of the bitstream has been changed.

Although gstreamer parser has parsed the stream resolution.
but there are some case that we need to handle resolution change event.
1. bit-depth is different from the negotiated format.
2. the capture buffer count can meet the demand
3. there are some hardware limitations that the decoded resolution may
be larger than the display size. For example, the stream size is
1920x1080, but some vpu may decode it to 1920x1088.

Change-Id: I99c7e973c197490b462b5d3100b413007fc19c39
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/1381>

subprojects/gst-plugins-good/sys/v4l2/gstv4l2videodec.c
subprojects/gst-plugins-good/sys/v4l2/gstv4l2videodec.h

index 91ea03d37b94486d7a53f8238683e6869928cffc..1d18c55435daee4ed62098d434d899c72a7b47c8 100644 (file)
@@ -227,6 +227,7 @@ gst_v4l2_video_dec_start (GstVideoDecoder * decoder)
 
   gst_v4l2_object_unlock (self->v4l2output);
   g_atomic_int_set (&self->active, TRUE);
+  g_atomic_int_set (&self->capture_configuration_change, FALSE);
   self->output_flow = GST_FLOW_OK;
 
   return TRUE;
@@ -676,6 +677,8 @@ gst_v4l2_video_dec_setup_capture (GstVideoDecoder * decoder)
     /* Copy the rest of the information, there might be more in the future */
     output_state->info.interlace_mode = info.interlace_mode;
     gst_video_codec_state_unref (output_state);
+    gst_v4l2_buffer_pool_enable_resolution_change (GST_V4L2_BUFFER_POOL
+        (self->v4l2capture->pool));
 
     if (!gst_video_decoder_negotiate (decoder)) {
       if (GST_PAD_IS_FLUSHING (decoder->srcpad))
@@ -721,15 +724,30 @@ static void
 gst_v4l2_video_dec_loop (GstVideoDecoder * decoder)
 {
   GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (decoder);
-  GstV4l2BufferPool *v4l2_pool = GST_V4L2_BUFFER_POOL (self->v4l2capture->pool);
+  GstV4l2BufferPool *v4l2_pool;
   GstBufferPool *pool;
   GstVideoCodecFrame *frame;
   GstBuffer *buffer = NULL;
   GstFlowReturn ret;
 
+  GST_VIDEO_DECODER_STREAM_LOCK (decoder);
+  if (g_atomic_int_get (&self->capture_configuration_change)) {
+    gst_v4l2_object_stop (self->v4l2capture);
+    ret = gst_v4l2_video_dec_setup_capture (decoder);
+    if (ret != GST_FLOW_OK)
+      return;
+    g_atomic_int_set (&self->capture_configuration_change, FALSE);
+  }
+  GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
+
+  if (G_UNLIKELY (!GST_V4L2_IS_ACTIVE (self->v4l2capture)))
+    return;
+
   GST_LOG_OBJECT (decoder, "Allocate output buffer");
 
+  v4l2_pool = GST_V4L2_BUFFER_POOL (self->v4l2capture->pool);
   self->output_flow = GST_FLOW_OK;
+
   do {
     /* We cannot use the base class allotate helper since it taking the internal
      * stream lock. we know that the acquire may need to poll until more frames
@@ -746,6 +764,12 @@ gst_v4l2_video_dec_loop (GstVideoDecoder * decoder)
     ret = gst_buffer_pool_acquire_buffer (pool, &buffer, NULL);
     g_object_unref (pool);
 
+    if (ret == GST_V4L2_FLOW_RESOLUTION_CHANGE) {
+      GST_WARNING_OBJECT (decoder, "Received resolution change");
+      g_atomic_int_set (&self->capture_configuration_change, TRUE);
+      return;
+    }
+
     if (ret != GST_FLOW_OK)
       goto beach;
 
@@ -837,10 +861,12 @@ gst_v4l2_video_dec_handle_frame (GstVideoDecoder * decoder,
       goto not_negotiated;
   }
 
-  ret = gst_v4l2_video_dec_setup_capture (decoder);
-  if (ret != GST_FLOW_OK) {
-    GST_ERROR_OBJECT (decoder, "setup capture fail\n");
-    goto not_negotiated;
+  if (!g_atomic_int_get (&self->capture_configuration_change)) {
+    ret = gst_v4l2_video_dec_setup_capture (decoder);
+    if (ret != GST_FLOW_OK) {
+      GST_ERROR_OBJECT (decoder, "setup capture fail\n");
+      goto not_negotiated;
+    }
   }
 
   if (G_UNLIKELY (!gst_buffer_pool_is_active (pool))) {
index 6696fcb35e9a9881f1dfcdaab0682ec6d6f15e42..5af08ac9354974b5f94b1dd29139803ea7667f00 100644 (file)
@@ -62,6 +62,9 @@ struct _GstV4l2VideoDec
   GstVideoCodecState *input_state;
   gboolean active;
   GstFlowReturn output_flow;
+
+  /* dynamic resolution change flag */
+  gboolean capture_configuration_change;
 };
 
 struct _GstV4l2VideoDecClass