From 842835ce1836d139aabb780b385c2ae2118c3e79 Mon Sep 17 00:00:00 2001
From: Song Bing <b06498@freescale.com>
Date: Tue, 5 Aug 2014 14:40:46 +0800
Subject: [PATCH 01/75] gstrtpmp4gpay: set dafault value for MPEG4 without
 codec data in caps.

https://bugzilla.gnome.org/show_bug.cgi?id=734263

Upstream Status: Submitted

Signed-off-by: Song Bing <b06498@freescale.com>
(cherry picked from commit c16f2f3d415ce86247ea80c838cfaa4a383b69c9)
---
 gst/rtp/gstrtpmp4gpay.c | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/gst/rtp/gstrtpmp4gpay.c b/gst/rtp/gstrtpmp4gpay.c
index 2434d9035..6cd01f113 100644
--- a/gst/rtp/gstrtpmp4gpay.c
+++ b/gst/rtp/gstrtpmp4gpay.c
@@ -394,6 +394,7 @@ gst_rtp_mp4g_pay_setcaps (GstRTPBasePayload * payload, GstCaps * caps)
   const GValue *codec_data;
   const gchar *media_type = NULL;
   gboolean res;
+  const gchar *name;
 
   rtpmp4gpay = GST_RTP_MP4G_PAY (payload);
 
@@ -404,7 +405,6 @@ gst_rtp_mp4g_pay_setcaps (GstRTPBasePayload * payload, GstCaps * caps)
     GST_LOG_OBJECT (rtpmp4gpay, "got codec_data");
     if (G_VALUE_TYPE (codec_data) == GST_TYPE_BUFFER) {
       GstBuffer *buffer;
-      const gchar *name;
 
       buffer = gst_value_get_buffer (codec_data);
       GST_LOG_OBJECT (rtpmp4gpay, "configuring codec_data");
@@ -430,6 +430,23 @@ gst_rtp_mp4g_pay_setcaps (GstRTPBasePayload * payload, GstCaps * caps)
 
       rtpmp4gpay->config = gst_buffer_copy (buffer);
     }
+  } else {
+    name = gst_structure_get_name (structure);
+
+    if (!strcmp (name, "video/mpeg")) {
+      rtpmp4gpay->profile = g_strdup ("1");
+
+      /* fixed rate */
+      rtpmp4gpay->rate = 90000;
+      /* video stream type */
+      rtpmp4gpay->streamtype = "4";
+      /* no params for video */
+      rtpmp4gpay->params = NULL;
+      /* mode */
+      rtpmp4gpay->mode = "generic";
+
+      media_type = "video";
+    }
   }
   if (media_type == NULL)
     goto config_failed;
-- 
2.34.1


From 5530c879c9c367c0f706e879e3c21548cbc6ac60 Mon Sep 17 00:00:00 2001
From: Jian <Jian.Li@freescale.com>
Date: Tue, 3 Feb 2015 17:08:40 +0800
Subject: [PATCH 02/75] Need to check if pa stream is still valid

Fixed the issue that will report pulse server is dead
when doing audio track switching.
Need to check if pa stream is valid as it may be released
by caps change.

Upstream Status: Submitted
https://bugzilla.gnome.org/show_bug.cgi?id=743912

Signed-off-by: Jian <Jian.Li@freescale.com>
(cherry picked from commit 4055d0ce42187a98adab5836bdff6d54c23b4002)
---
 ext/pulse/pulsesink.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/ext/pulse/pulsesink.c b/ext/pulse/pulsesink.c
index 348150dd8..4d00752c1 100644
--- a/ext/pulse/pulsesink.c
+++ b/ext/pulse/pulsesink.c
@@ -2027,6 +2027,13 @@ gst_pulsesink_get_time (GstClock * clock, GstAudioBaseSink * sink)
   }
 
   pa_threaded_mainloop_lock (mainloop);
+
+  /* Need to check if pa stream is valid as it may be released by caps change*/
+  if (!pbuf->stream) {
+    pa_threaded_mainloop_unlock (mainloop);
+    return GST_CLOCK_TIME_NONE;
+  }
+
   if (gst_pulsering_is_dead (psink, pbuf, TRUE))
     goto server_dead;
 
-- 
2.34.1


From b0b511a8786e1d8447bc374a67740e94021e35b8 Mon Sep 17 00:00:00 2001
From: Lyon Wang <lyon.wang@freescale.com>
Date: Fri, 6 Feb 2015 11:27:47 +0800
Subject: [PATCH 03/75] Fix aacpase error tolerance issue

There is no need to check channel configure in adts header.
The channel could be output of decoder.
No need to return fatal error here.

https://bugzilla.gnome.org/show_bug.cgi?id=743332

UpStream Status: Pending

Signed-off-by: Lyon Wang <lyon.wang@freescale.com>
(cherry picked from commit 6bb15b284ced8baddcaffd5cdb399813045bb8ed)
---
 gst/audioparsers/gstaacparse.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gst/audioparsers/gstaacparse.c b/gst/audioparsers/gstaacparse.c
index eb3ee985b..07ef3e9d7 100644
--- a/gst/audioparsers/gstaacparse.c
+++ b/gst/audioparsers/gstaacparse.c
@@ -1012,7 +1012,7 @@ gst_aac_parse_detect_stream (GstAacParse * aacparse,
     gst_aac_parse_parse_adts_header (aacparse, data, &rate, &channels,
         &aacparse->object_type, &aacparse->mpegversion);
 
-    if (!channels || !framesize) {
+    if (!framesize) {
       GST_DEBUG_OBJECT (aacparse, "impossible ADTS configuration");
       return FALSE;
     }
-- 
2.34.1


From 8e97f7dec752dd6645d15a4314445873ec5b1878 Mon Sep 17 00:00:00 2001
From: Lyon Wang <lyon.wang@nxp.com>
Date: Fri, 9 Jun 2017 16:53:11 +0800
Subject: [PATCH 04/75] gstaacparse: Fix adif aac file read channel/progile
 issue

- parser adif program_config_element() to get correct channel
- Fix aacparse src pad caps wrong profile for ADIF file

Upstream status: submitted.
Combined 2 bugzilla ticket:
https://bugzilla.gnome.org/show_bug.cgi?id=783583
https://bugzilla.gnome.org/show_bug.cgi?id=785476

Signed-off-by: Lyon Wang <lyon.wang@nxp.com>
(cherry picked from commit 95bee58109a28ddb650ebe39160c6ee4d321159e)
---
 gst/audioparsers/gstaacparse.c | 203 ++++++++++++++++++++++++---------
 1 file changed, 152 insertions(+), 51 deletions(-)

diff --git a/gst/audioparsers/gstaacparse.c b/gst/audioparsers/gstaacparse.c
index 07ef3e9d7..cf23d2d54 100644
--- a/gst/audioparsers/gstaacparse.c
+++ b/gst/audioparsers/gstaacparse.c
@@ -87,6 +87,35 @@ static const gint loas_channels_table[16] = {
   0, 0, 0, 7, 8, 0, 8, 0
 };
 
+typedef struct
+{
+  guint32 num_ele;
+  guint32 ele_is_cpe[16];
+  guint32 ele_tag[16];
+} GstAacEleList;
+
+typedef struct
+{
+  guint32 present;
+  guint32 ele_tag;
+  guint32 pseudo_enab;
+} GstAacMIXdown;
+
+typedef struct
+{
+  guint32 profile;
+  guint32 sr_idx;
+  GstAacEleList front;
+  GstAacEleList side;
+  GstAacEleList back;
+  GstAacEleList data;
+  GstAacEleList lfe;
+  GstAacEleList coupling;
+  GstAacMIXdown mono_mix;
+  GstAacMIXdown stereo_mix;
+  GstAacMIXdown matrix_mix;
+} GstAacProgConfig;
+
 static gboolean gst_aac_parse_start (GstBaseParse * parse);
 static gboolean gst_aac_parse_stop (GstBaseParse * parse);
 
@@ -106,6 +135,9 @@ static gboolean gst_aac_parse_read_audio_specific_config (GstAacParse *
     aacparse, GstBitReader * br, gint * object_type, gint * sample_rate,
     gint * channels, gint * frame_samples);
 
+static gboolean gst_aac_parse_read_program_config_element (GstAacProgConfig *
+    progConfig, GstBitReader * br);
+
 
 #define gst_aac_parse_parent_class parent_class
 G_DEFINE_TYPE (GstAacParse, gst_aac_parse, GST_TYPE_BASE_PARSE);
@@ -941,6 +973,87 @@ gst_aac_parse_parse_adts_header (GstAacParse * aacparse, const guint8 * data,
     *object = ((data[2] & 0xc0) >> 6) + 1;
 }
 
+static void
+gst_aac_parse_get_ele_list (GstAacEleList * pList, gint32 cpe,
+    GstBitReader * br)
+{
+  guint32 count, num_elem;
+  num_elem = pList->num_ele;
+  for (count = 0; count < num_elem; count++) {
+    if (cpe) {
+      gst_bit_reader_get_bits_uint32 (br, &(pList->ele_is_cpe[count]), 1);
+    } else {
+      pList->ele_is_cpe[count] = 0;
+    }
+    gst_bit_reader_get_bits_uint32 (br, &(pList->ele_tag[count]), 4);
+  }
+}
+
+static gint32
+gst_aac_parse_get_config_channels (GstAacEleList * pList)
+{
+  guint32 count, num_elem, channels = 0;
+  num_elem = pList->num_ele;
+  for (count = 0; count < num_elem; count++) {
+    channels++;
+    if (pList->ele_is_cpe[count] == 1) {
+      /* CPE element channels++ */
+      channels++;
+    }
+  }
+  return channels;
+}
+
+/* Read program config element
+ISO/IEC 14496-3, 4.4.1.1  read program config element */
+static gboolean
+gst_aac_parse_read_program_config_element (GstAacProgConfig *
+    progConfig, GstBitReader * br)
+{
+  guint32 count = 0;
+  guint32 bytes = 0;
+
+  gst_bit_reader_skip (br, 4);  //element_instance_tag
+
+  gst_bit_reader_get_bits_uint32 (br, &progConfig->profile, 2);
+  gst_bit_reader_get_bits_uint32 (br, &progConfig->sr_idx, 4);
+  gst_bit_reader_get_bits_uint32 (br, &(progConfig->front.num_ele), 4);
+  gst_bit_reader_get_bits_uint32 (br, &(progConfig->side.num_ele), 4);
+  gst_bit_reader_get_bits_uint32 (br, &(progConfig->back.num_ele), 4);
+  gst_bit_reader_get_bits_uint32 (br, &(progConfig->lfe.num_ele), 2);
+  gst_bit_reader_get_bits_uint32 (br, &(progConfig->data.num_ele), 3);
+  gst_bit_reader_get_bits_uint32 (br, &(progConfig->coupling.num_ele), 4);
+
+  gst_bit_reader_get_bits_uint32 (br, &(progConfig->mono_mix.present), 1);
+  if (progConfig->mono_mix.present) {
+    gst_bit_reader_get_bits_uint32 (br, &(progConfig->mono_mix.ele_tag), 4);
+  }
+  gst_bit_reader_get_bits_uint32 (br, &(progConfig->stereo_mix.present), 1);
+  if (progConfig->mono_mix.present) {
+    gst_bit_reader_get_bits_uint32 (br, &(progConfig->stereo_mix.ele_tag), 4);
+  }
+  gst_bit_reader_get_bits_uint32 (br, &(progConfig->matrix_mix.present), 1);
+  if (progConfig->mono_mix.present) {
+    gst_bit_reader_get_bits_uint32 (br, &(progConfig->matrix_mix.ele_tag), 2);
+    gst_bit_reader_get_bits_uint32 (br, &(progConfig->matrix_mix.pseudo_enab), 1);
+  }
+
+  gst_aac_parse_get_ele_list (&progConfig->front, 1, br);
+  gst_aac_parse_get_ele_list (&progConfig->side, 1, br);
+  gst_aac_parse_get_ele_list (&progConfig->back, 1, br);
+  gst_aac_parse_get_ele_list (&progConfig->data, 0, br);
+  gst_aac_parse_get_ele_list (&progConfig->lfe, 0, br);
+  gst_aac_parse_get_ele_list (&progConfig->coupling, 1, br);
+
+  gst_bit_reader_skip_to_byte (br);     // byte_alignment
+
+  gst_bit_reader_get_bits_uint32 (br, &bytes, 8);       //comment_field_bytes
+  for (count = 0; count < bytes; count++) {
+    gst_bit_reader_skip (br, 8);        //skip comment data
+  }
+  return TRUE;
+}
+
 /**
  * gst_aac_parse_detect_stream:
  * @aacparse: #GstAacParse.
@@ -1070,68 +1183,56 @@ gst_aac_parse_detect_stream (GstAacParse * aacparse,
     return FALSE;
 
   if (memcmp (data + i, "ADIF", 4) == 0) {
-    const guint8 *adif;
-    int skip_size = 0;
-    int bitstream_type;
+    GstBitReader br;
+    guint8 u8 = 0;
+    guint8 bitstream_type = 0;
+    guint num_elems = 0;
+    guint bitrate = 0;
+    guint count;
     int sr_idx;
     GstCaps *sinkcaps;
-
+    GstAacProgConfig *progConfig;
     aacparse->header_type = DSPAAC_HEADER_ADIF;
     aacparse->mpegversion = 4;
-
-    /* Skip the "ADIF" bytes */
-    adif = data + i + 4;
-
-    /* copyright string */
-    if (adif[0] & 0x80)
-      skip_size += 9;           /* skip 9 bytes */
-
-    bitstream_type = adif[0 + skip_size] & 0x10;
-    aacparse->bitrate =
-        ((unsigned int) (adif[0 + skip_size] & 0x0f) << 19) |
-        ((unsigned int) adif[1 + skip_size] << 11) |
-        ((unsigned int) adif[2 + skip_size] << 3) |
-        ((unsigned int) adif[3 + skip_size] & 0xe0);
-
-    /* CBR */
+    gst_bit_reader_init (&br, data + i, avail - i);
+    /* skip sync word (adif 4 byte ) */
+    gst_bit_reader_skip (&br, 32);
+    gst_bit_reader_get_bits_uint8 (&br, &u8, 1);
+    if (u8) {
+      gst_bit_reader_skip (&br, 72);    //copyright_id
+    }
+    gst_bit_reader_skip (&br, 2);       // original_copy and home
+    gst_bit_reader_get_bits_uint8 (&br, &bitstream_type, 1);
+    gst_bit_reader_get_bits_uint32 (&br, &bitrate, 23);
+    gst_bit_reader_get_bits_uint32 (&br, &num_elems, 4);
     if (bitstream_type == 0) {
-#if 0
-      /* Buffer fullness parsing. Currently not needed... */
-      guint num_elems = 0;
-      guint fullness = 0;
-
-      num_elems = (adif[3 + skip_size] & 0x1e);
-      GST_INFO ("ADIF num_config_elems: %d", num_elems);
-
-      fullness = ((unsigned int) (adif[3 + skip_size] & 0x01) << 19) |
-          ((unsigned int) adif[4 + skip_size] << 11) |
-          ((unsigned int) adif[5 + skip_size] << 3) |
-          ((unsigned int) (adif[6 + skip_size] & 0xe0) >> 5);
-
-      GST_INFO ("ADIF buffer fullness: %d", fullness);
-#endif
-      aacparse->object_type = ((adif[6 + skip_size] & 0x01) << 1) |
-          ((adif[7 + skip_size] & 0x80) >> 7);
-      sr_idx = (adif[7 + skip_size] & 0x78) >> 3;
+      gst_bit_reader_skip (&br, 20);    //adif_buffer_fullness
     }
-    /* VBR */
-    else {
-      aacparse->object_type = (adif[4 + skip_size] & 0x18) >> 3;
-      sr_idx = ((adif[4 + skip_size] & 0x07) << 1) |
-          ((adif[5 + skip_size] & 0x80) >> 7);
+
+    progConfig =
+        (GstAacProgConfig *) g_malloc0 ((num_elems+1) * sizeof (GstAacProgConfig));
+    for ( count = 0; count < num_elems + 1; count++) {
+      gst_aac_parse_read_program_config_element (&progConfig[count], &br);
+      aacparse->channels +=
+          gst_aac_parse_get_config_channels (&(progConfig[count].front));
+      aacparse->channels +=
+          gst_aac_parse_get_config_channels (&(progConfig[count].side));
+      aacparse->channels +=
+          gst_aac_parse_get_config_channels (&(progConfig[count].back));
+      aacparse->channels +=
+          gst_aac_parse_get_config_channels (&(progConfig[count].lfe));
+      aacparse->channels +=
+          gst_aac_parse_get_config_channels (&(progConfig[count].coupling));
     }
 
-    /* FIXME: This gives totally wrong results. Duration calculation cannot
-       be based on this */
+    aacparse->bitrate = (gint)bitrate;
+    aacparse->object_type = progConfig[0].profile + 1;
+    sr_idx = progConfig[0].sr_idx;
+    g_free(progConfig);
+
     aacparse->sample_rate =
         gst_codec_utils_aac_get_sample_rate_from_index (sr_idx);
 
-    /* baseparse is not given any fps,
-     * so it will give up on timestamps, seeking, etc */
-
-    /* FIXME: Can we assume this? */
-    aacparse->channels = 2;
-
     GST_INFO ("ADIF: br=%d, samplerate=%d, objtype=%d",
         aacparse->bitrate, aacparse->sample_rate, aacparse->object_type);
 
-- 
2.34.1


From 6fd1d070e2e1e24963cdd65d405ac397dc93168b Mon Sep 17 00:00:00 2001
From: Haihua Hu <jared.hu@nxp.com>
Date: Mon, 16 Apr 2018 11:27:39 +0800
Subject: [PATCH 05/75] gtkglwidget: fix build error cause by api change in
 base-gl

commit 908c6c5d422ab069b5e642b06e536be2afea1816
Author: Haihua Hu <jared.hu@nxp.com>
Date:   Thu Apr 12 16:22:25 2018 +0800

    gloverlaycompositor: add subtitle rotate support follow video

    upstream status: Pending
    https://bugzilla.gnome.org/show_bug.cgi?id=790470

upsteam status: imx specific

(cherry picked from commit b08bb5bbd607be558a9b0668059890c4a28ab0e3)
---
 ext/gtk/gtkgstglwidget.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/ext/gtk/gtkgstglwidget.c b/ext/gtk/gtkgstglwidget.c
index bb74ce09c..1e1a7ae82 100644
--- a/ext/gtk/gtkgstglwidget.c
+++ b/ext/gtk/gtkgstglwidget.c
@@ -381,7 +381,7 @@ gtk_gst_gl_widget_render (GtkGLArea * widget, GdkGLContext * context)
       base_widget->buffer, context);
 
   _redraw_texture (GTK_GST_GL_WIDGET (widget), priv->current_tex);
-  gst_gl_overlay_compositor_draw_overlays (priv->overlay_compositor);
+  gst_gl_overlay_compositor_draw_overlays (priv->overlay_compositor, NULL);
 
   gst_gl_insert_debug_marker (priv->other_context, "texture %u redrawn",
       priv->current_tex);
-- 
2.34.1


From c1402a6e00ea56ff2898ce84944ebb16804f972b Mon Sep 17 00:00:00 2001
From: Lyon Wang <lyon.wang@nxp.com>
Date: Wed, 11 Jul 2018 16:24:07 +0800
Subject: [PATCH 06/75] pulseaudio: Add print for pulsesink / pulsesrc

- not set NOAUTOSPAWN flag in pulsesink
- Add print to notify current sink / source device

i.MX specific

Signed-off-by: Lyon Wang <lyon.wang@nxp.com>
(cherry picked from commit 1ad050a56e9523fde28c06dd37a66cdfa1526f11)
---
 ext/pulse/pulsesink.c | 10 +++++++---
 ext/pulse/pulsesrc.c  |  2 ++
 2 files changed, 9 insertions(+), 3 deletions(-)
 mode change 100644 => 100755 ext/pulse/pulsesink.c
 mode change 100644 => 100755 ext/pulse/pulsesrc.c

diff --git a/ext/pulse/pulsesink.c b/ext/pulse/pulsesink.c
old mode 100644
new mode 100755
index 4d00752c1..5fea927ab
--- a/ext/pulse/pulsesink.c
+++ b/ext/pulse/pulsesink.c
@@ -546,12 +546,14 @@ gst_pulseringbuffer_open_device (GstAudioRingBuffer * buf)
     pa_context_set_subscribe_callback (pctx->context,
         gst_pulsering_context_subscribe_cb, pctx);
 
-    /* try to connect to the server and wait for completion, we don't want to
-     * autospawn a daemon */
+    /* try to connect to the server and wait for completion, we want to
+     * make pulsesink as default audiosink, so here not set NOAUTOSPAWN flag  */
     GST_LOG_OBJECT (psink, "connect to server %s",
         GST_STR_NULL (psink->server));
+    /* if (pa_context_connect (pctx->context, psink->server,
+            PA_CONTEXT_NOAUTOSPAWN, NULL) < 0) */
     if (pa_context_connect (pctx->context, psink->server,
-            PA_CONTEXT_NOAUTOSPAWN, NULL) < 0)
+            PA_CONTEXT_NOFLAGS, NULL) < 0)
       goto connect_failed;
   } else {
     GST_INFO_OBJECT (psink,
@@ -1017,6 +1019,8 @@ gst_pulseringbuffer_acquire (GstAudioRingBuffer * buf,
   g_free (psink->device);
   psink->device = g_strdup (pa_stream_get_device_name (pbuf->stream));
 
+  g_print ("\n===!!! Current pulsesink device is %s !!!===\n\n", psink->device);
+
 #ifndef GST_DISABLE_GST_DEBUG
   pa_format_info_snprint (print_buf, sizeof (print_buf),
       pa_stream_get_format_info (pbuf->stream));
diff --git a/ext/pulse/pulsesrc.c b/ext/pulse/pulsesrc.c
old mode 100644
new mode 100755
index 41252bdf7..3d9188009
--- a/ext/pulse/pulsesrc.c
+++ b/ext/pulse/pulsesrc.c
@@ -1091,6 +1091,8 @@ gst_pulsesrc_read (GstAudioSrc * asrc, gpointer data, guint length,
     g_object_notify (G_OBJECT (pulsesrc), "volume");
     g_object_notify (G_OBJECT (pulsesrc), "mute");
     g_object_notify (G_OBJECT (pulsesrc), "current-device");
+    g_print ("\n=== !!! Current pulsesrc device is %s !!!===\n",
+      gst_pulsesrc_get_current_device (pulsesrc));
   }
 
   pa_threaded_mainloop_lock (pulsesrc->mainloop);
-- 
2.34.1


From b9dd73c8c8c1e33af80ee81de2c4d2e12c6ec7b7 Mon Sep 17 00:00:00 2001
From: Hou Qi <qi.hou@nxp.com>
Date: Fri, 4 Jan 2019 16:29:41 +0800
Subject: [PATCH 07/75] pulseaudio:[MMFMWK-8268] fix bad state when play audio
 with varying channels

Not to check the state of stream in function gst_pulsesink_get_sink_input_info()
to void the disconnected error when play audio with varying channels.

https://gitlab.freedesktop.org/gstreamer/gst-plugins-good/issues/539

Upstream status: pending

Signed-off-by: Hou Qi <qi.hou@nxp.com>
(cherry picked from commit 17aa490448abcc7d646d6f2883637c236b952e7c)
---
 ext/pulse/pulsesink.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
 mode change 100755 => 100644 ext/pulse/pulsesink.c

diff --git a/ext/pulse/pulsesink.c b/ext/pulse/pulsesink.c
old mode 100755
new mode 100644
index 5fea927ab..1d87d8c51
--- a/ext/pulse/pulsesink.c
+++ b/ext/pulse/pulsesink.c
@@ -2622,7 +2622,7 @@ gst_pulsesink_get_sink_input_info (GstPulseSink * psink, gdouble * volume,
 
   while (pa_operation_get_state (o) == PA_OPERATION_RUNNING) {
     pa_threaded_mainloop_wait (mainloop);
-    if (gst_pulsering_is_dead (psink, pbuf, TRUE))
+    if (gst_pulsering_is_dead (psink, pbuf, FALSE))
       goto unlock;
   }
 
-- 
2.34.1


From 998b56f27fb11e097c66e572d2a7969f77a7f669 Mon Sep 17 00:00:00 2001
From: Lyon Wang <lyon.wang@nxp.com>
Date: Wed, 24 Oct 2018 15:00:07 +0800
Subject: [PATCH 08/75] MMFMWK-7852 v4l2 error log

- When set fmt field to V4L2_FIELD_ANY
  It will print error log, as it is not a critical issue
  Change it to GST_WARNING

Signed-off-by: Lyon Wang <lyon.wang@nxp.com>
(cherry picked from commit 03a5908b4f21aed7340afbf55f8949440909d78c)
---
 sys/v4l2/gstv4l2object.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c
index 0134de475..f975728b5 100644
--- a/sys/v4l2/gstv4l2object.c
+++ b/sys/v4l2/gstv4l2object.c
@@ -2238,7 +2238,7 @@ gst_v4l2_object_get_interlace_mode (enum v4l2_field field,
 {
   switch (field) {
     case V4L2_FIELD_ANY:
-      GST_ERROR
+      GST_WARNING
           ("Driver bug detected - check driver with v4l2-compliance from http://git.linuxtv.org/v4l-utils.git\n");
       return FALSE;
     case V4L2_FIELD_NONE:
-- 
2.34.1


From d4d2b39a338bde2c75abac0cd7ffb444c7b08baf Mon Sep 17 00:00:00 2001
From: Song Bing <bing.song@nxp.com>
Date: Mon, 26 Mar 2018 15:20:54 -0700
Subject: [PATCH 09/75] v4l2videodec: Add Amphion tiled support.

upstream status: imx specific

Signed-off-by: Song Bing <bing.song@nxp.com>
(cherry picked from commit c0036bcf85b1293cabb0994f872cd0e28191733b)

Conflicts:
	sys/v4l2/gstv4l2object.h
---
 sys/v4l2/gstv4l2object.h   |  1 +
 sys/v4l2/gstv4l2videodec.c |  8 ++++++++
 sys/v4l2/v4l2_calls.c      | 13 +++++++++----
 3 files changed, 18 insertions(+), 4 deletions(-)

diff --git a/sys/v4l2/gstv4l2object.h b/sys/v4l2/gstv4l2object.h
index 4716a05c6..895ce7aba 100644
--- a/sys/v4l2/gstv4l2object.h
+++ b/sys/v4l2/gstv4l2object.h
@@ -229,6 +229,7 @@ struct _GstV4l2Object {
    * on slow USB firmwares. When this is set, gst_v4l2_set_format() will modify
    * the caps to reflect what was negotiated during fixation */
   gboolean skip_try_fmt_probes;
+  gboolean is_amphion;
   
   guint max_width;
   guint max_height;
diff --git a/sys/v4l2/gstv4l2videodec.c b/sys/v4l2/gstv4l2videodec.c
index c7f39ddee..924af9c0d 100644
--- a/sys/v4l2/gstv4l2videodec.c
+++ b/sys/v4l2/gstv4l2videodec.c
@@ -28,9 +28,12 @@
 #include <errno.h>
 #include <unistd.h>
 #include <string.h>
+#include <libdrm/drm_fourcc.h>
+#include <gst/allocators/gstdmabufmeta.h>
 
 #include "gstv4l2object.h"
 #include "gstv4l2videodec.h"
+#include "gstimxcommon.h"
 
 #include "gstv4l2h264codec.h"
 #include "gstv4l2h265codec.h"
@@ -845,6 +848,11 @@ gst_v4l2_video_dec_loop (GstVideoDecoder * decoder)
 
     frame->duration = self->v4l2capture->duration;
     frame->output_buffer = buffer;
+    if (IS_AMPHION () && self->v4l2capture->is_amphion) {
+      guint64 drm_modifier = DRM_FORMAT_MOD_AMPHION_TILED;
+      gst_buffer_add_dmabuf_meta (frame->output_buffer, drm_modifier);
+      GST_DEBUG_OBJECT (decoder, "Add drm modifier: %lld\n", drm_modifier);
+    }
     buffer = NULL;
     ret = gst_video_decoder_finish_frame (decoder, frame);
 
diff --git a/sys/v4l2/v4l2_calls.c b/sys/v4l2/v4l2_calls.c
index b2165bc13..672e7233c 100644
--- a/sys/v4l2/v4l2_calls.c
+++ b/sys/v4l2/v4l2_calls.c
@@ -605,6 +605,10 @@ gst_v4l2_open (GstV4l2Object * v4l2object, GstV4l2Error * error)
     v4l2object->never_interlaced = TRUE;
   }
 
+  if (!strcmp ((char *) v4l2object->vcap.driver, "vpu B0")) {
+    v4l2object->is_amphion = TRUE;
+  }
+
   return TRUE;
 
   /* ERRORS */
@@ -692,6 +696,7 @@ gst_v4l2_dup (GstV4l2Object * v4l2object, GstV4l2Object * other)
 
   v4l2object->never_interlaced = other->never_interlaced;
   v4l2object->no_initial_format = other->no_initial_format;
+  v4l2object->is_amphion = other->is_amphion;
 
   return TRUE;
 
@@ -1148,7 +1153,7 @@ input_failed:
 }
 
 gboolean
-gst_v4l2_query_input (GstV4l2Object * obj, struct v4l2_input *input)
+gst_v4l2_query_input (GstV4l2Object * obj, struct v4l2_input * input)
 {
   gint ret;
 
@@ -1279,7 +1284,7 @@ failed:
 }
 
 gboolean
-gst_v4l2_dequeue_event (GstV4l2Object * v4l2object, struct v4l2_event *event)
+gst_v4l2_dequeue_event (GstV4l2Object * v4l2object, struct v4l2_event * event)
 {
   gint ret;
 
@@ -1302,7 +1307,7 @@ gst_v4l2_dequeue_event (GstV4l2Object * v4l2object, struct v4l2_event *event)
 
 gboolean
 gst_v4l2_set_dv_timings (GstV4l2Object * v4l2object,
-    struct v4l2_dv_timings *timings)
+    struct v4l2_dv_timings * timings)
 {
   gint ret;
 
@@ -1322,7 +1327,7 @@ gst_v4l2_set_dv_timings (GstV4l2Object * v4l2object,
 
 gboolean
 gst_v4l2_query_dv_timings (GstV4l2Object * v4l2object,
-    struct v4l2_dv_timings *timings)
+    struct v4l2_dv_timings * timings)
 {
   gint ret;
 
-- 
2.34.1


From e2a38bd5d98cd2c78f855b5c37c4a9460c20cc78 Mon Sep 17 00:00:00 2001
From: Song Bing <bing.song@nxp.com>
Date: Wed, 18 Apr 2018 12:39:19 -0700
Subject: [PATCH 10/75] v4l2videodec: Don't reset decoder when caps change.

VPU can handle resolution change.

upstream status: imx specific

Signed-off-by: Song Bing <bing.song@nxp.com>

Conflicts:
	sys/v4l2/gstv4l2videodec.c
(cherry picked from commit 64a458260076d5a597ed7a222896bc887200a6e0)
---
 sys/v4l2/gstv4l2videodec.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/sys/v4l2/gstv4l2videodec.c b/sys/v4l2/gstv4l2videodec.c
index 924af9c0d..65ed7b192 100644
--- a/sys/v4l2/gstv4l2videodec.c
+++ b/sys/v4l2/gstv4l2videodec.c
@@ -312,6 +312,11 @@ gst_v4l2_video_dec_set_format (GstVideoDecoder * decoder,
   if (!dyn_resolution)
     ret = gst_v4l2_object_set_format (self->v4l2output, state->caps, &error);
 
+  if (GST_V4L2_IS_ACTIVE (self->v4l2output)) {
+    self->input_state = gst_video_codec_state_ref (state);
+    return TRUE;
+  }
+
   if (ret)
     self->input_state = gst_video_codec_state_ref (state);
   else
-- 
2.34.1


From 07426faea49884c3cdcdaeee3656fe3aa6625d69 Mon Sep 17 00:00:00 2001
From: Song Bing <bing.song@nxp.com>
Date: Wed, 23 May 2018 14:15:59 -0700
Subject: [PATCH 11/75] v4l2videodec: needn't unref caps after unref query.

https://bugzilla.gnome.org/show_bug.cgi?id=752962

UpStream Status: Pending

(cherry picked from commit b0d3bde48842d4da1e28a7c4be49477c544d6f7c)
---
 sys/v4l2/gstv4l2videodec.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/sys/v4l2/gstv4l2videodec.c b/sys/v4l2/gstv4l2videodec.c
index 65ed7b192..064c3f3c5 100644
--- a/sys/v4l2/gstv4l2videodec.c
+++ b/sys/v4l2/gstv4l2videodec.c
@@ -300,7 +300,6 @@ gst_v4l2_video_dec_set_format (GstVideoDecoder * decoder,
         GstQuery *query = gst_query_new_allocation (caps, FALSE);
         gst_pad_peer_query (decoder->srcpad, query);
         gst_query_unref (query);
-        gst_caps_unref (caps);
       }
     }
 
-- 
2.34.1


From 990a529b629d5faf695eb749ed813d8f9b2e2076 Mon Sep 17 00:00:00 2001
From: Song Bing <bing.song@nxp.com>
Date: Wed, 23 May 2018 14:18:52 -0700
Subject: [PATCH 12/75] Workaround for driver need wait 2 seconds for CMD_STOP.

upstream status: imx specific

Signed-off-by: Song Bing <bing.song@nxp.com>

(cherry picked from commit 66a80d5d9dee870453b24a53da2803415a6a88bb)
---
 sys/v4l2/gstv4l2videodec.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/sys/v4l2/gstv4l2videodec.c b/sys/v4l2/gstv4l2videodec.c
index 064c3f3c5..f84bc2bf9 100644
--- a/sys/v4l2/gstv4l2videodec.c
+++ b/sys/v4l2/gstv4l2videodec.c
@@ -586,6 +586,12 @@ gst_v4l2_video_dec_finish (GstVideoDecoder * decoder)
   if (gst_v4l2_decoder_cmd (self->v4l2output, V4L2_DEC_CMD_STOP, 0)) {
     GstTask *task;
 
+    // Workaround as CMD_STOP will wait long time.
+    if (gst_pad_get_task_state (decoder->srcpad) != GST_TASK_STARTED) {
+      GST_VIDEO_DECODER_STREAM_LOCK (decoder);
+      goto done;
+    }
+
     GST_OBJECT_LOCK (decoder->srcpad);
     task = GST_PAD_TASK (decoder->srcpad);
     if (task)
-- 
2.34.1


From 8a0b472a3e69093f854ed7363565ac1dd478a8eb Mon Sep 17 00:00:00 2001
From: Song Bing <bing.song@nxp.com>
Date: Thu, 19 Jul 2018 18:14:05 -0700
Subject: [PATCH 13/75] v4l2videodec: Add more video format.

Add RMVB/VP6/AVS/Sorenson SPARK/DivX support
Change divx 3 fourcc according to driver changes.
Add divx 4/5/6 support.
Add xvid support.
Add NV12 10bit support.

https://bugzilla.gnome.org/show_bug.cgi?id=752962

UpStream Status: Pending

(cherry picked from commit f7050e9cccaeffea08a1508603c1436172d9e47f,
commit d50cf240395a2e08b698a6f5781824c8b46e7d07,
commit 6b27d74e288dd71d30c5a7c6a95feb75c277b852,
commit 877ab457b5fe1db48a326b936e5e9b9f219c2c5c,
commit ce70fc86006cd2cd654e2cadaa01b2e55f096d23)

 Conflicts:
	sys/v4l2/ext/videodev2.h
---
 sys/v4l2/ext/videodev2.h   |  7 ++++
 sys/v4l2/gstv4l2object.c   | 78 +++++++++++++++++++++++++++++++++++---
 sys/v4l2/gstv4l2videodec.c | 19 ++++++++++
 3 files changed, 98 insertions(+), 6 deletions(-)

diff --git a/sys/v4l2/ext/videodev2.h b/sys/v4l2/ext/videodev2.h
index 2ceb1ca32..25a0b10cf 100644
--- a/sys/v4l2/ext/videodev2.h
+++ b/sys/v4l2/ext/videodev2.h
@@ -624,6 +624,7 @@ struct v4l2_pix_format {
 #define V4L2_PIX_FMT_NV16M   v4l2_fourcc('N', 'M', '1', '6') /* 16  Y/CbCr 4:2:2  */
 #define V4L2_PIX_FMT_NV61M   v4l2_fourcc('N', 'M', '6', '1') /* 16  Y/CrCb 4:2:2  */
 #define V4L2_PIX_FMT_P012M   v4l2_fourcc('P', 'M', '1', '2') /* 24  Y/CbCr 4:2:0 12-bit per component */
+#define V4L2_PIX_FMT_NV12_10BIT   v4l2_fourcc('N', 'T', '1', '2') /* Y/CbCr 4:2:0 for 10bit  */
 
 /* three planes - Y Cb, Cr */
 #define V4L2_PIX_FMT_YUV410  v4l2_fourcc('Y', 'U', 'V', '9') /*  9  YUV 4:1:0     */
@@ -715,6 +716,12 @@ struct v4l2_pix_format {
 #define V4L2_PIX_FMT_H264     v4l2_fourcc('H', '2', '6', '4') /* H264 with start codes */
 #define V4L2_PIX_FMT_H264_NO_SC v4l2_fourcc('A', 'V', 'C', '1') /* H264 without start codes */
 #define V4L2_PIX_FMT_H264_MVC v4l2_fourcc('M', '2', '6', '4') /* H264 MVC */
+#define V4L2_PIX_FMT_RV       v4l2_fourcc('R', 'V', '0', '0') /* RV8/9/10 */
+#define V4L2_PIX_FMT_VP6      v4l2_fourcc('V', 'P', '6', '0') /* VP6 */
+#define V4L2_PIX_FMT_AVS      v4l2_fourcc('A', 'V', 'S', '0') /* AVS */
+#define V4L2_PIX_FMT_SPK      v4l2_fourcc('S', 'P', 'K', '0') /* Sorenson Spark */
+#define V4L2_PIX_FMT_DIV3     v4l2_fourcc('D', 'I', 'V', '3') /* DivX 3 */
+#define V4L2_PIX_FMT_DIVX     v4l2_fourcc('D', 'I', 'V', 'X') /* DivX 4 5 6 */
 #define V4L2_PIX_FMT_H263     v4l2_fourcc('H', '2', '6', '3') /* H263          */
 #define V4L2_PIX_FMT_MPEG1    v4l2_fourcc('M', 'P', 'G', '1') /* MPEG-1 ES     */
 #define V4L2_PIX_FMT_MPEG2    v4l2_fourcc('M', 'P', 'G', '2') /* MPEG-2 ES     */
diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c
index f975728b5..4228f1b09 100644
--- a/sys/v4l2/gstv4l2object.c
+++ b/sys/v4l2/gstv4l2object.c
@@ -152,6 +152,7 @@ static const GstV4L2FormatDesc gst_v4l2_formats[] = {
 
   /* two planes -- one Y, one Cr + Cb interleaved  */
   {V4L2_PIX_FMT_NV12, TRUE, GST_V4L2_RAW},
+  {V4L2_PIX_FMT_NV12_10BIT, TRUE, GST_V4L2_RAW},
   {V4L2_PIX_FMT_NV12M, TRUE, GST_V4L2_RAW},
   {V4L2_PIX_FMT_NV12MT, TRUE, GST_V4L2_RAW},
   {V4L2_PIX_FMT_NV12MT_16X16, TRUE, GST_V4L2_RAW},
@@ -200,6 +201,12 @@ static const GstV4L2FormatDesc gst_v4l2_formats[] = {
   {V4L2_PIX_FMT_H264_NO_SC, FALSE, GST_V4L2_CODEC},
   {V4L2_PIX_FMT_H264_MVC, FALSE, GST_V4L2_CODEC},
   {V4L2_PIX_FMT_HEVC, FALSE, GST_V4L2_CODEC},
+  {V4L2_PIX_FMT_RV, FALSE, GST_V4L2_CODEC},
+  {V4L2_PIX_FMT_VP6, FALSE, GST_V4L2_CODEC},
+  {V4L2_PIX_FMT_AVS, FALSE, GST_V4L2_CODEC},
+  {V4L2_PIX_FMT_SPK, FALSE, GST_V4L2_CODEC},
+  {V4L2_PIX_FMT_DIV3, FALSE, GST_V4L2_CODEC},
+  {V4L2_PIX_FMT_DIVX, FALSE, GST_V4L2_CODEC},
   {V4L2_PIX_FMT_H263, FALSE, GST_V4L2_CODEC},
   {V4L2_PIX_FMT_MPEG1, FALSE, GST_V4L2_CODEC},
   {V4L2_PIX_FMT_MPEG2, FALSE, GST_V4L2_CODEC},
@@ -1133,6 +1140,7 @@ gst_v4l2_object_format_get_rank (const struct v4l2_fmtdesc *fmt)
       break;
     case V4L2_PIX_FMT_NV12:    /* Y/CbCr 4:2:0, 12 bits per pixel */
     case V4L2_PIX_FMT_NV12M:   /* Same as NV12      */
+    case V4L2_PIX_FMT_NV12_10BIT:      /* 12  Y/CbCr 4:2:0  */
       rank = YUV_BASE_RANK + 8;
       break;
     case V4L2_PIX_FMT_YUYV:    /* YUY2, 16 bits per pixel */
@@ -1409,6 +1417,9 @@ gst_v4l2_object_v4l2fourcc_to_video_format (guint32 fourcc)
     case V4L2_PIX_FMT_NV12M:
       format = GST_VIDEO_FORMAT_NV12;
       break;
+    case V4L2_PIX_FMT_NV12_10BIT:
+      format = GST_VIDEO_FORMAT_NV12_10LE40;
+      break;
     case V4L2_PIX_FMT_NV12MT:
       format = GST_VIDEO_FORMAT_NV12_64Z32;
       break;
@@ -1565,11 +1576,13 @@ gst_v4l2_object_v4l2fourcc_to_bare_struct (guint32 fourcc)
           "mpegversion", G_TYPE_INT, 2, NULL);
       break;
     case V4L2_PIX_FMT_MPEG4:
-    case V4L2_PIX_FMT_XVID:
       structure = gst_structure_new ("video/mpeg",
           "mpegversion", G_TYPE_INT, 4, "systemstream",
           G_TYPE_BOOLEAN, FALSE, NULL);
       break;
+    case V4L2_PIX_FMT_XVID:
+      structure = gst_structure_new_empty ("video/x-xvid");
+      break;
     case V4L2_PIX_FMT_FWHT:
       structure = gst_structure_new_empty ("video/x-fwht");
       break;
@@ -1592,10 +1605,31 @@ gst_v4l2_object_v4l2fourcc_to_bare_struct (guint32 fourcc)
           "stream-format", G_TYPE_STRING, "byte-stream", "alignment",
           G_TYPE_STRING, "au", NULL);
       break;
+    case V4L2_PIX_FMT_RV:
+      structure = gst_structure_new_empty ("video/x-pn-realvideo");
+      break;
+    case V4L2_PIX_FMT_VP6:
+      structure = gst_structure_new_empty ("video/x-vp6-flash");
+      break;
+    case V4L2_PIX_FMT_AVS:
+      structure = gst_structure_new_empty ("video/x-cavs");
+      break;
+    case V4L2_PIX_FMT_SPK:
+      structure = gst_structure_new ("video/x-flash-video",
+          "flvversion", G_TYPE_INT, 1, NULL);
+      break;
+    case V4L2_PIX_FMT_DIV3:
+      structure = gst_structure_new ("video/x-divx",
+          "divxversion", G_TYPE_INT, 3, NULL);
+      break;
+    case V4L2_PIX_FMT_DIVX:
+      structure = gst_structure_new ("video/x-divx",
+          "divxversion", GST_TYPE_INT_RANGE, 4, 6, NULL);
+      break;
     case V4L2_PIX_FMT_VC1_ANNEX_G:
     case V4L2_PIX_FMT_VC1_ANNEX_L:
       structure = gst_structure_new ("video/x-wmv",
-          "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
+          "wmvversion", G_TYPE_INT, 3, NULL);
       break;
     case V4L2_PIX_FMT_VP8:
       structure = gst_structure_new_empty ("video/x-vp8");
@@ -1624,6 +1658,7 @@ gst_v4l2_object_v4l2fourcc_to_bare_struct (guint32 fourcc)
     case V4L2_PIX_FMT_XBGR32:
     case V4L2_PIX_FMT_ABGR32:
     case V4L2_PIX_FMT_NV12:    /* 12  Y/CbCr 4:2:0  */
+    case V4L2_PIX_FMT_NV12_10BIT:      /* 12  Y/CbCr 4:2:0  */
     case V4L2_PIX_FMT_NV12M:
     case V4L2_PIX_FMT_NV12MT:
     case V4L2_PIX_FMT_MM21:
@@ -1806,7 +1841,7 @@ gst_v4l2_object_is_raw (GstV4l2Object * v4l2object)
 
   for (i = 0; i < GST_V4L2_FORMAT_COUNT; i++) {
     if (gst_v4l2_formats[i].format == GST_V4L2_PIXELFORMAT (v4l2object)) {
-      return !!(gst_v4l2_formats[i].flags & GST_V4L2_RAW);
+      return ! !(gst_v4l2_formats[i].flags & GST_V4L2_RAW);
     }
   }
   return FALSE;
@@ -1980,6 +2015,9 @@ gst_v4l2_object_get_caps_info (GstV4l2Object * v4l2object, GstCaps * caps,
         fourcc = V4L2_PIX_FMT_NV12;
         fourcc_nc = V4L2_PIX_FMT_NV12M;
         break;
+      case GST_VIDEO_FORMAT_NV12_10LE40:
+        fourcc = V4L2_PIX_FMT_NV12_10BIT;
+        break;
       case GST_VIDEO_FORMAT_NV12_64Z32:
         fourcc_nc = V4L2_PIX_FMT_NV12MT;
         break;
@@ -2092,6 +2130,8 @@ gst_v4l2_object_get_caps_info (GstV4l2Object * v4l2object, GstCaps * caps,
             break;
         }
       }
+    } else if (g_str_equal (mimetype, "video/x-xvid")) {
+      fourcc = V4L2_PIX_FMT_XVID;
     } else if (g_str_equal (mimetype, "video/x-fwht")) {
       fourcc = V4L2_PIX_FMT_FWHT;
     } else if (g_str_equal (mimetype, "video/x-h263")) {
@@ -2105,6 +2145,31 @@ gst_v4l2_object_get_caps_info (GstV4l2Object * v4l2object, GstCaps * caps,
         fourcc = V4L2_PIX_FMT_H264;
     } else if (g_str_equal (mimetype, "video/x-h265")) {
       fourcc = V4L2_PIX_FMT_HEVC;
+    } else if (g_str_equal (mimetype, "video/x-pn-realvideo")) {
+      fourcc = V4L2_PIX_FMT_RV;
+    } else if (g_str_equal (mimetype, "video/x-vp6-flash")) {
+      fourcc = V4L2_PIX_FMT_VP6;
+    } else if (g_str_equal (mimetype, "video/x-cavs")) {
+      fourcc = V4L2_PIX_FMT_AVS;
+    } else if (g_str_equal (mimetype, "video/x-flash-video")) {
+      fourcc = V4L2_PIX_FMT_SPK;
+    } else if (g_str_equal (mimetype, "video/x-divx")) {
+      gint divxversion;
+      if (gst_structure_get_int (structure, "divxversion", &divxversion)) {
+        if (divxversion == 3) {
+          fourcc = V4L2_PIX_FMT_DIV3;
+        } else {
+          fourcc = V4L2_PIX_FMT_DIVX;
+        }
+      }
+    } else if (g_str_equal (mimetype, "video/x-wmv")) {
+      const gchar *format = gst_structure_get_string (structure, "format");
+      if (format) {
+        if (!g_ascii_strcasecmp (format, "WMV3"))
+          fourcc = V4L2_PIX_FMT_VC1_ANNEX_G;
+        else if (!g_ascii_strcasecmp (format, "WVC1"))
+          fourcc = V4L2_PIX_FMT_VC1_ANNEX_L;
+      }
     } else if (g_str_equal (mimetype, "video/x-vp8")) {
       fourcc = V4L2_PIX_FMT_VP8;
     } else if (g_str_equal (mimetype, "video/x-vp9")) {
@@ -4749,7 +4814,7 @@ unsupported_format:
  * Returns: %TRUE on success, %FALSE on failure.
  */
 gboolean
-gst_v4l2_object_set_crop (GstV4l2Object * obj, struct v4l2_rect *crop_rect)
+gst_v4l2_object_set_crop (GstV4l2Object * obj, struct v4l2_rect * crop_rect)
 {
   struct v4l2_selection sel = { 0 };
   struct v4l2_crop crop = { 0 };
@@ -4872,13 +4937,14 @@ gst_v4l2_object_get_crop_rect (GstV4l2Object * obj, guint target,
 }
 
 gboolean
-gst_v4l2_object_get_crop_bounds (GstV4l2Object * obj, struct v4l2_rect *result)
+gst_v4l2_object_get_crop_bounds (GstV4l2Object * obj, struct v4l2_rect * result)
 {
   return gst_v4l2_object_get_crop_rect (obj, V4L2_SEL_TGT_CROP_BOUNDS, result);
 }
 
 gboolean
-gst_v4l2_object_get_crop_default (GstV4l2Object * obj, struct v4l2_rect *result)
+gst_v4l2_object_get_crop_default (GstV4l2Object * obj,
+    struct v4l2_rect * result)
 {
   return gst_v4l2_object_get_crop_rect (obj, V4L2_SEL_TGT_CROP_DEFAULT, result);
 }
diff --git a/sys/v4l2/gstv4l2videodec.c b/sys/v4l2/gstv4l2videodec.c
index f84bc2bf9..60c4547eb 100644
--- a/sys/v4l2/gstv4l2videodec.c
+++ b/sys/v4l2/gstv4l2videodec.c
@@ -1395,6 +1395,8 @@ G_STMT_START { \
     }
   } else if (gst_structure_has_name (s, "video/x-h263")) {
     SET_META ("H263");
+  } else if (gst_structure_has_name (s, "video/x-xvid")) {
+    SET_META ("XVID");
   } else if (gst_structure_has_name (s, "video/x-fwht")) {
     SET_META ("FWHT");
   } else if (gst_structure_has_name (s, "video/x-h264")) {
@@ -1403,6 +1405,23 @@ G_STMT_START { \
   } else if (gst_structure_has_name (s, "video/x-h265")) {
     SET_META ("H265");
     cdata->codec = gst_v4l2_h265_get_codec ();
+  } else if (gst_structure_has_name (s, "video/x-pn-realvideo")) {
+    SET_META ("RV");
+  } else if (gst_structure_has_name (s, "video/x-vp6-flash")) {
+    SET_META ("VP6");
+  } else if (gst_structure_has_name (s, "video/x-cavs")) {
+    SET_META ("AVS");
+  } else if (gst_structure_has_name (s, "video/x-flash-video")) {
+    SET_META ("SPK");
+  } else if (gst_structure_has_name (s, "video/x-divx")) {
+    gint divxversion = 0;
+    gst_structure_get_int (s, "divxversion", &divxversion);
+
+    if (divxversion == 3) {
+      SET_META ("DIV3");
+    } else {
+      SET_META ("DIVX");
+    }
   } else if (gst_structure_has_name (s, "video/x-wmv")) {
     SET_META ("VC1");
   } else if (gst_structure_has_name (s, "video/x-vp8")) {
-- 
2.34.1


From 1169de808ca214e526c3d739c588d07162513216 Mon Sep 17 00:00:00 2001
From: Song Bing <bing.song@nxp.com>
Date: Thu, 9 Aug 2018 10:21:55 -0700
Subject: [PATCH 14/75] v4l2videoenc: workaround for sink pool dequeue race
 condition

Sink pool dequeue and finish frame has race condition.
Unref input buffer in chain thread to avoid it.

https://bugzilla.gnome.org/show_bug.cgi?id=752962

UpStream Status: Pending

Signed-off-by: Song Bing <bing.song@nxp.com>
(cherry picked from commit 154f5a12656ae888b00810a49fdf5f1f7586ef88)
---
 sys/v4l2/gstv4l2videoenc.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/sys/v4l2/gstv4l2videoenc.c b/sys/v4l2/gstv4l2videoenc.c
index a13f41403..10bf1a7b8 100644
--- a/sys/v4l2/gstv4l2videoenc.c
+++ b/sys/v4l2/gstv4l2videoenc.c
@@ -881,7 +881,10 @@ gst_v4l2_video_enc_handle_frame (GstVideoEncoder * encoder,
     }
   }
 
+  gst_buffer_unref (frame->input_buffer);
+  frame->input_buffer = NULL;
   gst_video_codec_frame_unref (frame);
+
   return ret;
 
   /* ERRORS */
-- 
2.34.1


From afed978c749de8de518dae81bf86374bdeeaaa33 Mon Sep 17 00:00:00 2001
From: Song Bing <bing.song@nxp.com>
Date: Thu, 30 Aug 2018 14:26:11 -0700
Subject: [PATCH 15/75] v4l2videodec: Remove sink event task stop as flush()
 will do the same.

https://bugzilla.gnome.org/show_bug.cgi?id=752962

UpStream Status: Pending

Signed-off-by: Song Bing<bing.song@nxp.com>
(cherry picked from commit 2ebc731916be1fb427a0afb774f517dc67379cf5)
---
 sys/v4l2/gstv4l2videodec.c | 20 --------------------
 1 file changed, 20 deletions(-)

diff --git a/sys/v4l2/gstv4l2videodec.c b/sys/v4l2/gstv4l2videodec.c
index 60c4547eb..ecf6416ab 100644
--- a/sys/v4l2/gstv4l2videodec.c
+++ b/sys/v4l2/gstv4l2videodec.c
@@ -1183,28 +1183,8 @@ gst_v4l2_video_dec_sink_event (GstVideoDecoder * decoder, GstEvent * event)
   gboolean ret;
   GstEventType type = GST_EVENT_TYPE (event);
 
-  switch (type) {
-    case GST_EVENT_FLUSH_START:
-      GST_DEBUG_OBJECT (self, "flush start");
-      gst_v4l2_object_unlock (self->v4l2output);
-      gst_v4l2_object_unlock (self->v4l2capture);
-      break;
-    default:
-      break;
-  }
-
   ret = GST_VIDEO_DECODER_CLASS (parent_class)->sink_event (decoder, event);
 
-  switch (type) {
-    case GST_EVENT_FLUSH_START:
-      /* The processing thread should stop now, wait for it */
-      gst_pad_stop_task (decoder->srcpad);
-      GST_DEBUG_OBJECT (self, "flush start done");
-      break;
-    default:
-      break;
-  }
-
   return ret;
 }
 
-- 
2.34.1


From c7eeab31193c26e87535c59e0407fae6b9ec1b10 Mon Sep 17 00:00:00 2001
From: Song Bing <bing.song@nxp.com>
Date: Tue, 30 Oct 2018 15:37:34 -0700
Subject: [PATCH 16/75] Revert "v4l2transform: Expose BGRA and ARGB formats"

This reverts commit 2676ac90751ff933f4d7e1a286cd304907081166.

(cherry picked from commit 086ee32b1428f2fc708f4f214cc4f90a51813542)
---
 sys/v4l2/gstv4l2.c | 20 +-------------------
 1 file changed, 1 insertion(+), 19 deletions(-)

diff --git a/sys/v4l2/gstv4l2.c b/sys/v4l2/gstv4l2.c
index 2d6070944..a597ece0a 100644
--- a/sys/v4l2/gstv4l2.c
+++ b/sys/v4l2/gstv4l2.c
@@ -94,26 +94,8 @@ gst_v4l2_probe_template_caps (const gchar * device, gint video_fd,
 
     template = gst_v4l2_object_v4l2fourcc_to_structure (format.pixelformat);
 
-    if (template) {
-      GstStructure *alt_t = NULL;
-
-      switch (format.pixelformat) {
-        case V4L2_PIX_FMT_RGB32:
-          alt_t = gst_structure_copy (template);
-          gst_structure_set (alt_t, "format", G_TYPE_STRING, "ARGB", NULL);
-          break;
-        case V4L2_PIX_FMT_BGR32:
-          alt_t = gst_structure_copy (template);
-          gst_structure_set (alt_t, "format", G_TYPE_STRING, "BGRA", NULL);
-        default:
-          break;
-      }
-
+    if (template)
       gst_caps_append_structure (caps, template);
-
-      if (alt_t)
-        gst_caps_append_structure (caps, alt_t);
-    }
   }
 
   return gst_caps_simplify (caps);
-- 
2.34.1


From 2f36642aec1d61a8dbf3ae37c4c8e6bea9d56f3c Mon Sep 17 00:00:00 2001
From: Song Bing <bing.song@nxp.com>
Date: Mon, 26 Nov 2018 16:25:29 -0800
Subject: [PATCH 17/75] v4l2videodec: return error when flush.

Signed-off-by: Song Bing <bing.song@nxp.com>
(cherry picked from commit a73374626d890cc9d3688c0e91dc7ac2994c0671)

Conflicts:
	sys/v4l2/gstv4l2videodec.c
---
 sys/v4l2/gstv4l2videodec.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/sys/v4l2/gstv4l2videodec.c b/sys/v4l2/gstv4l2videodec.c
index ecf6416ab..44d9a121a 100644
--- a/sys/v4l2/gstv4l2videodec.c
+++ b/sys/v4l2/gstv4l2videodec.c
@@ -674,7 +674,8 @@ gst_v4l2_video_dec_drain (GstVideoDecoder * decoder)
 
   GST_DEBUG_OBJECT (self, "Draining...");
   gst_v4l2_video_dec_finish (decoder);
-  gst_v4l2_video_dec_flush (decoder);
+  if (!gst_v4l2_video_dec_flush (decoder))
+    return GST_FLOW_ERROR;
 
   return GST_FLOW_OK;
 }
-- 
2.34.1


From 35675e5e6159fe678f4da4616a3b6fe7e999b348 Mon Sep 17 00:00:00 2001
From: Song Bing <bing.song@nxp.com>
Date: Thu, 16 May 2019 18:13:12 -0700
Subject: [PATCH 18/75] v4l2videodec: extend YUV 24 bit for IMG JPG decoder.

Signed-off-by: Song Bing <bing.song@nxp.com>
(cherry picked from commit 02f8b5c5006b326b8c902491a3677f80121f4f92)
---
 sys/v4l2/gstv4l2object.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c
index 4228f1b09..19eb43db1 100644
--- a/sys/v4l2/gstv4l2object.c
+++ b/sys/v4l2/gstv4l2object.c
@@ -142,6 +142,7 @@ static const GstV4L2FormatDesc gst_v4l2_formats[] = {
   {V4L2_PIX_FMT_YUV444, TRUE, GST_V4L2_RAW},
   {V4L2_PIX_FMT_YUV555, TRUE, GST_V4L2_RAW},
   {V4L2_PIX_FMT_YUV565, TRUE, GST_V4L2_RAW},
+  {V4L2_PIX_FMT_YUV24, TRUE, GST_V4L2_RAW},
   {V4L2_PIX_FMT_YUV32, TRUE, GST_V4L2_RAW},
   {V4L2_PIX_FMT_YUV410, TRUE, GST_V4L2_RAW},
   {V4L2_PIX_FMT_YUV420, TRUE, GST_V4L2_RAW},
@@ -1125,6 +1126,7 @@ gst_v4l2_object_format_get_rank (const struct v4l2_fmtdesc *fmt)
     case V4L2_PIX_FMT_MM21:    /* NV12 Y 16x32, UV 16x16 tile */
     case V4L2_PIX_FMT_NV12M_8L128:
     case V4L2_PIX_FMT_NV12M_10BE_8L128:
+    case V4L2_PIX_FMT_YUV24:   /* 24  YUY 4:4:4     */
       rank = YUV_ODD_BASE_RANK;
       break;
 
@@ -1449,6 +1451,9 @@ gst_v4l2_object_v4l2fourcc_to_video_format (guint32 fourcc)
     case V4L2_PIX_FMT_YUYV:
       format = GST_VIDEO_FORMAT_YUY2;
       break;
+    case V4L2_PIX_FMT_YUV24:
+      format = GST_VIDEO_FORMAT_v308;
+      break;
     case V4L2_PIX_FMT_YVU420:
     case V4L2_PIX_FMT_YVU420M:
       format = GST_VIDEO_FORMAT_YV12;
@@ -1676,6 +1681,7 @@ gst_v4l2_object_v4l2fourcc_to_bare_struct (guint32 fourcc)
     case V4L2_PIX_FMT_YUV420:  /* I420/IYUV */
     case V4L2_PIX_FMT_YUV420M:
     case V4L2_PIX_FMT_YUYV:
+    case V4L2_PIX_FMT_YUV24:
     case V4L2_PIX_FMT_YVU420:
     case V4L2_PIX_FMT_YVU420M:
     case V4L2_PIX_FMT_UYVY:
@@ -1997,6 +2003,9 @@ gst_v4l2_object_get_caps_info (GstV4l2Object * v4l2object, GstCaps * caps,
       case GST_VIDEO_FORMAT_YUY2:
         fourcc = V4L2_PIX_FMT_YUYV;
         break;
+      case GST_VIDEO_FORMAT_v308:
+        fourcc = V4L2_PIX_FMT_YUV24;
+        break;
       case GST_VIDEO_FORMAT_UYVY:
         fourcc = V4L2_PIX_FMT_UYVY;
         break;
-- 
2.34.1


From 62f9df9f75130f02eea854c064d92a16c9f63648 Mon Sep 17 00:00:00 2001
From: Song Bing <bing.song@nxp.com>
Date: Wed, 29 May 2019 16:59:26 -0700
Subject: [PATCH 19/75] v4l2videodec: enable multi-track selection.

Signed-off-by: Song Bing <bing.song@nxp.com>
(cherry picked from commit 03e725101135b407be369e09ba4c34b993cff471)
---
 sys/v4l2/gstv4l2object.c   | 7 +++++++
 sys/v4l2/gstv4l2videodec.c | 2 +-
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c
index 19eb43db1..c333acda5 100644
--- a/sys/v4l2/gstv4l2object.c
+++ b/sys/v4l2/gstv4l2object.c
@@ -5521,6 +5521,13 @@ gst_v4l2_object_decide_allocation (GstV4l2Object * obj, GstQuery * query)
 
   can_share_own_pool = (has_video_meta || !obj->need_video_meta);
 
+  /* aovid copy Amphion tiled frame buffer for un-active video track */
+  if (obj->is_amphion) {
+    can_share_own_pool = TRUE;
+    if (min < GST_V4L2_MIN_BUFFERS (obj))
+      min = GST_V4L2_MIN_BUFFERS (obj);
+  }
+
   gst_v4l2_get_driver_min_buffers (obj);
   /* We can't share our own pool, if it exceed V4L2 capacity */
   if (min + obj->min_buffers + 1 > VIDEO_MAX_FRAME)
diff --git a/sys/v4l2/gstv4l2videodec.c b/sys/v4l2/gstv4l2videodec.c
index 44d9a121a..a4a5b768f 100644
--- a/sys/v4l2/gstv4l2videodec.c
+++ b/sys/v4l2/gstv4l2videodec.c
@@ -867,7 +867,7 @@ gst_v4l2_video_dec_loop (GstVideoDecoder * decoder)
     buffer = NULL;
     ret = gst_video_decoder_finish_frame (decoder, frame);
 
-    if (ret != GST_FLOW_OK)
+    if (!(ret == GST_FLOW_OK || ret == GST_FLOW_NOT_LINKED))
       goto beach;
   } else {
     GST_WARNING_OBJECT (decoder, "Decoder is producing too many buffers");
-- 
2.34.1


From f525d69d9f609f5ed7733b663a0145c9ea291943 Mon Sep 17 00:00:00 2001
From: Song Bing <bing.song@nxp.com>
Date: Wed, 12 Jun 2019 15:16:38 -0700
Subject: [PATCH 20/75] v4l2allocator: avoid map/unmap every frame as
 GstVideoFilter map/unmap video frame every frame.

Signed-off-by: Song Bing <bing.song@nxp.com>
(cherry picked from commit fe4863bc2939e43801fd51502659e4c11582b1bd)
---
 sys/v4l2/gstv4l2allocator.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/sys/v4l2/gstv4l2allocator.c b/sys/v4l2/gstv4l2allocator.c
index aa54b9a0d..d2da938a7 100644
--- a/sys/v4l2/gstv4l2allocator.c
+++ b/sys/v4l2/gstv4l2allocator.c
@@ -932,7 +932,8 @@ gst_v4l2_allocator_alloc_dmabuf (GstV4l2Allocator * allocator,
     mem = (GstV4l2Memory *) group->mem[i];
 
     dma_mem = gst_fd_allocator_alloc (dmabuf_allocator, mem->dmafd,
-        group->planes[i].length, GST_FD_MEMORY_FLAG_DONT_CLOSE);
+        group->planes[i].length,
+        GST_FD_MEMORY_FLAG_DONT_CLOSE | GST_FD_MEMORY_FLAG_KEEP_MAPPED);
     gst_memory_resize (dma_mem, group->planes[i].data_offset,
         group->planes[i].length - group->planes[i].data_offset);
 
-- 
2.34.1


From 300575f83e32a59d6adff7ebcc7e2433b4ed1731 Mon Sep 17 00:00:00 2001
From: Song Bing <bing.song@nxp.com>
Date: Wed, 4 Sep 2019 11:40:16 -0700
Subject: [PATCH 21/75] v4l2src: don't use export dmabuf for UVC as it use
 vmalloc for video

Signed-off-by: Song Bing <bing.song@nxp.com>
(cherry picked from commit c3e6d3746063cf0caf683b4c5255e600233c2215)
---
 sys/v4l2/gstv4l2object.c | 3 +++
 sys/v4l2/gstv4l2object.h | 1 +
 sys/v4l2/v4l2_calls.c    | 2 ++
 3 files changed, 6 insertions(+)

diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c
index c333acda5..cf9e33fa6 100644
--- a/sys/v4l2/gstv4l2object.c
+++ b/sys/v4l2/gstv4l2object.c
@@ -3433,6 +3433,9 @@ gst_v4l2_object_is_dmabuf_supported (GstV4l2Object * v4l2object)
   if (errno == ENOTTY)
     ret = FALSE;
 
+  if (v4l2object->dont_use_dmabuf)
+    ret = FALSE;
+
   return ret;
 }
 
diff --git a/sys/v4l2/gstv4l2object.h b/sys/v4l2/gstv4l2object.h
index 895ce7aba..917168e67 100644
--- a/sys/v4l2/gstv4l2object.h
+++ b/sys/v4l2/gstv4l2object.h
@@ -222,6 +222,7 @@ struct _GstV4l2Object {
   /* Quirks */
   /* Skips interlacing probes */
   gboolean never_interlaced;
+  gboolean dont_use_dmabuf;
   /* Allow to skip reading initial format through G_FMT. Some devices
    * just fails if you don't call S_FMT first. (ex: M2M decoders) */
   gboolean no_initial_format;
diff --git a/sys/v4l2/v4l2_calls.c b/sys/v4l2/v4l2_calls.c
index 672e7233c..00d57ec41 100644
--- a/sys/v4l2/v4l2_calls.c
+++ b/sys/v4l2/v4l2_calls.c
@@ -603,6 +603,7 @@ gst_v4l2_open (GstV4l2Object * v4l2object, GstV4l2Error * error)
   if (!strcmp ((char *) v4l2object->vcap.driver, "uvcusb") ||
       !strcmp ((char *) v4l2object->vcap.driver, "uvcvideo")) {
     v4l2object->never_interlaced = TRUE;
+    v4l2object->dont_use_dmabuf = TRUE;
   }
 
   if (!strcmp ((char *) v4l2object->vcap.driver, "vpu B0")) {
@@ -695,6 +696,7 @@ gst_v4l2_dup (GstV4l2Object * v4l2object, GstV4l2Object * other)
       v4l2object->vcap.card, v4l2object->videodev);
 
   v4l2object->never_interlaced = other->never_interlaced;
+  v4l2object->dont_use_dmabuf = other->dont_use_dmabuf;
   v4l2object->no_initial_format = other->no_initial_format;
   v4l2object->is_amphion = other->is_amphion;
 
-- 
2.34.1


From ddc9591aec5ecf309dffcada081ef907bdb32491 Mon Sep 17 00:00:00 2001
From: Song Bing <bing.song@nxp.com>
Date: Thu, 12 Sep 2019 16:15:20 -0700
Subject: [PATCH 22/75] v4l2videodec: Support seek for resolution change
 stream.

Signed-off-by: Song Bing <bing.song@nxp.com>

Conflicts:
	sys/v4l2/gstv4l2videodec.c
	sys/v4l2/gstv4l2object.c
(cherry picked from commit 8a6ce1f1a2b24b3028550d6cf662a9cbec2a22d5,
commit 2c6db2d07fd4fb8f4f3874f5a5a2b9c574b12463)
---
 sys/v4l2/gstv4l2videodec.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/sys/v4l2/gstv4l2videodec.c b/sys/v4l2/gstv4l2videodec.c
index a4a5b768f..fb0a35f4a 100644
--- a/sys/v4l2/gstv4l2videodec.c
+++ b/sys/v4l2/gstv4l2videodec.c
@@ -504,8 +504,13 @@ use_acquired_caps:
   gst_video_codec_state_unref (output_state);
 
   ret = GST_VIDEO_DECODER_CLASS (parent_class)->negotiate (decoder);
-  if (!ret)
-    goto not_negotiated;
+  if (!ret) {
+    if (GST_PAD_IS_FLUSHING (decoder->sinkpad)
+        || GST_PAD_IS_FLUSHING (decoder->srcpad))
+      goto flushing;
+    else
+      goto not_negotiated;
+  }
 
   /* The pool may be created through gst_video_decoder_negotiate(), so must
    * be kept after */
@@ -521,6 +526,9 @@ use_acquired_caps:
 
   return TRUE;
 
+flushing:
+  gst_v4l2_object_stop (self->v4l2capture);
+  return FALSE;
 not_negotiated:
   GST_ERROR_OBJECT (self, "not negotiated");
   gst_v4l2_error (self, &error);
-- 
2.34.1


From 98d09ed0f711d1944c4b7369c843be69831cdf26 Mon Sep 17 00:00:00 2001
From: Hou Qi <qi.hou@nxp.com>
Date: Thu, 19 Sep 2019 23:16:32 +0800
Subject: [PATCH 23/75] MMFMWK-8625 amrparse: fix AMR audio exit directly with
 eos after fast seek

Need to skip one byte when not find valid frame in gst_amr_parse_handle_frame().
Otherwise, scan frame size will be bigger after each scan and finally return
GST_FLOW_EOS, which cause audio exit directly after fast seek.

https://gitlab.freedesktop.org/gstreamer/gst-plugins-good/merge_requests/333

UpStream Status: Pending

Signed-off-by: Hou Qi <qi.hou@nxp.com>
(cherry picked from commit f640a95fd756129c0aef34fda3649ca9f832eb5e)
---
 gst/audioparsers/gstamrparse.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/gst/audioparsers/gstamrparse.c b/gst/audioparsers/gstamrparse.c
index 0ef612e1a..405237828 100644
--- a/gst/audioparsers/gstamrparse.c
+++ b/gst/audioparsers/gstamrparse.c
@@ -302,17 +302,20 @@ gst_amr_parse_handle_frame (GstBaseParse * parse,
      *       perform this check)
      */
     if (fsize) {
-      *skipsize = 0;
       /* in sync, no further check */
       if (!GST_BASE_PARSE_LOST_SYNC (parse)) {
         found = TRUE;
+        *skipsize = 0;
       } else if (dsize > fsize) {
         /* enough data, check for next sync */
-        if ((map.data[fsize] & 0x83) == 0)
+        if ((map.data[fsize] & 0x83) == 0) {
           found = TRUE;
+          *skipsize = 0;
+        }
       } else if (GST_BASE_PARSE_DRAINING (parse)) {
         /* not enough, but draining, so ok */
         found = TRUE;
+        *skipsize = 0;
       }
     }
   }
-- 
2.34.1


From b4d1bc3e106375b2b353a7deb1443d19b4cdc0a1 Mon Sep 17 00:00:00 2001
From: Bing Song <bing.song@nxp.com>
Date: Thu, 3 Sep 2020 18:30:53 +0800
Subject: [PATCH 24/75] v4l2: remove video frame buffer size and buffer pool
 size limitation.

Hantro video frame buffer size is larger than video frame content size.

Signed-off-by: Bing Song <bing.song@nxp.com>
(cherry picked from commit 12f5aea215f53e0dcfe0220b2628ecf1b9681e4d)
---
 sys/v4l2/gstv4l2bufferpool.c | 12 ------------
 sys/v4l2/gstv4l2object.c     |  7 -------
 2 files changed, 19 deletions(-)

diff --git a/sys/v4l2/gstv4l2bufferpool.c b/sys/v4l2/gstv4l2bufferpool.c
index 67036dcdd..89a173865 100644
--- a/sys/v4l2/gstv4l2bufferpool.c
+++ b/sys/v4l2/gstv4l2bufferpool.c
@@ -1935,10 +1935,6 @@ gst_v4l2_buffer_pool_process (GstV4l2BufferPool * pool, GstBuffer ** buf,
               goto eos;
             }
 
-            if (GST_VIDEO_INFO_FORMAT (&pool->caps_info) !=
-                GST_VIDEO_FORMAT_ENCODED && size < pool->size)
-              goto buffer_truncated;
-
             num_queued = g_atomic_int_get (&pool->num_queued);
             GST_TRACE_OBJECT (pool, "Only %i buffer left in the capture queue.",
                 num_queued);
@@ -2204,14 +2200,6 @@ copy_failed:
     GST_ERROR_OBJECT (pool, "failed to copy buffer");
     return ret;
   }
-buffer_truncated:
-  {
-    GST_WARNING_OBJECT (pool,
-        "Dropping truncated buffer, this is likely a driver bug.");
-    gst_buffer_unref (*buf);
-    *buf = NULL;
-    return GST_V4L2_FLOW_CORRUPTED_BUFFER;
-  }
 eos:
   {
     GST_DEBUG_OBJECT (pool, "end of sequence reached");
diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c
index cf9e33fa6..33b374b56 100644
--- a/sys/v4l2/gstv4l2object.c
+++ b/sys/v4l2/gstv4l2object.c
@@ -3609,13 +3609,6 @@ gst_v4l2_object_extrapolate_info (GstV4l2Object * v4l2object,
         "stride %d, offset %" G_GSIZE_FORMAT, i, stride, info->stride[i],
         info->offset[i]);
   }
-
-  /* Update the image size according the amount of data we are going to
-   * read/write. This workaround bugs in driver where the sizeimage provided
-   * by TRY/S_FMT represent the buffer length (maximum size) rather then the expected
-   * bytesused (buffer size). */
-  if (offs < info->size)
-    info->size = offs;
 }
 
 static void
-- 
2.34.1


From dc65f74d179fb8f1531934bc91612dcfb98abc56 Mon Sep 17 00:00:00 2001
From: Bing Song <bing.song@nxp.com>
Date: Tue, 20 Oct 2020 23:43:59 +0800
Subject: [PATCH 25/75] v4l2videodec: set max buffer count with min count.

Output buffer pool set configure will fail if max diff with min count.

Signed-off-by: Bing Song <bing.song@nxp.com>
(cherry picked from commit fdb5f89c73907722705fe4635af2e2095bf8f2a1)
---
 sys/v4l2/gstv4l2videodec.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sys/v4l2/gstv4l2videodec.c b/sys/v4l2/gstv4l2videodec.c
index fb0a35f4a..b234af9ce 100644
--- a/sys/v4l2/gstv4l2videodec.c
+++ b/sys/v4l2/gstv4l2videodec.c
@@ -945,7 +945,7 @@ gst_v4l2_video_dec_handle_frame (GstVideoDecoder * decoder,
     GstStructure *config = gst_buffer_pool_get_config (pool);
     guint min = MAX (self->v4l2output->min_buffers,
         GST_V4L2_MIN_BUFFERS (self->v4l2output));
-    guint max = VIDEO_MAX_FRAME;
+    guint max = min;
     guint32 dummy_frame_number = 0;
 
     GST_DEBUG_OBJECT (self, "Sending header");
-- 
2.34.1


From 217bb3d7e07d82c69757985435ac1a7537f5c958 Mon Sep 17 00:00:00 2001
From: Bing Song <bing.song@nxp.com>
Date: Wed, 28 Oct 2020 11:15:44 +0800
Subject: [PATCH 26/75] v4l2videodec: make a copy of input caps. Or will have
 critical warning when remove colorimetry.

Signed-off-by: Bing Song <bing.song@nxp.com>

(cherry picked from commit ca2fa62cfa36eeeb5590c46706c071c7cbd1a0fa)
---
 sys/v4l2/gstv4l2videodec.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/sys/v4l2/gstv4l2videodec.c b/sys/v4l2/gstv4l2videodec.c
index b234af9ce..5dd21b8c7 100644
--- a/sys/v4l2/gstv4l2videodec.c
+++ b/sys/v4l2/gstv4l2videodec.c
@@ -267,6 +267,7 @@ gst_v4l2_video_dec_set_format (GstVideoDecoder * decoder,
   gboolean ret = TRUE;
   gboolean dyn_resolution = self->v4l2output->fmtdesc &&
       (self->v4l2output->fmtdesc->flags & V4L2_FMT_FLAG_DYN_RESOLUTION);
+  GstCaps *caps;
 
   GST_DEBUG_OBJECT (self, "Setting format: %" GST_PTR_FORMAT, state->caps);
 
@@ -308,8 +309,11 @@ gst_v4l2_video_dec_set_format (GstVideoDecoder * decoder,
   }
 
   /* No V4L2_FMT_FLAG_DYN_RESOLUTION or no fmtdesc set yet */
-  if (!dyn_resolution)
-    ret = gst_v4l2_object_set_format (self->v4l2output, state->caps, &error);
+  if (!dyn_resolution) {
+    caps = gst_caps_copy (state->caps);
+    ret = gst_v4l2_object_set_format (self->v4l2output, caps, &error);
+    gst_caps_unref (caps);
+  }
 
   if (GST_V4L2_IS_ACTIVE (self->v4l2output)) {
     self->input_state = gst_video_codec_state_ref (state);
-- 
2.34.1


From 744cd6baad029d93953d1817b49cc5a6e519b271 Mon Sep 17 00:00:00 2001
From: Hou Qi <qi.hou@nxp.com>
Date: Tue, 24 Nov 2020 16:57:03 +0800
Subject: [PATCH 27/75] v4l2videodec: Add hantro to use v4l2 buffer pool when
 link videodecoder to fakesink.

https://gitlab.freedesktop.org/gstreamer/gst-plugins-good/-/issues/805

UpStream Status: Pending

Signed-off-by: Hou Qi <qi.hou@nxp.com>
(cherry picked from commit 07be67802a1cf7c2ac965010b9308c2486ff17d2)
---
 sys/v4l2/gstv4l2object.c | 3 ++-
 sys/v4l2/gstv4l2object.h | 1 +
 sys/v4l2/v4l2_calls.c    | 5 +++++
 3 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c
index 33b374b56..602e3430f 100644
--- a/sys/v4l2/gstv4l2object.c
+++ b/sys/v4l2/gstv4l2object.c
@@ -5518,7 +5518,8 @@ gst_v4l2_object_decide_allocation (GstV4l2Object * obj, GstQuery * query)
   can_share_own_pool = (has_video_meta || !obj->need_video_meta);
 
   /* aovid copy Amphion tiled frame buffer for un-active video track */
-  if (obj->is_amphion) {
+  /* also to avoid copy Hantro frame buffer when link v4l2 decoder with fakesink */
+  if (obj->is_amphion || obj->is_hantro) {
     can_share_own_pool = TRUE;
     if (min < GST_V4L2_MIN_BUFFERS (obj))
       min = GST_V4L2_MIN_BUFFERS (obj);
diff --git a/sys/v4l2/gstv4l2object.h b/sys/v4l2/gstv4l2object.h
index 917168e67..0c9f98230 100644
--- a/sys/v4l2/gstv4l2object.h
+++ b/sys/v4l2/gstv4l2object.h
@@ -231,6 +231,7 @@ struct _GstV4l2Object {
    * the caps to reflect what was negotiated during fixation */
   gboolean skip_try_fmt_probes;
   gboolean is_amphion;
+  gboolean is_hantro;
   
   guint max_width;
   guint max_height;
diff --git a/sys/v4l2/v4l2_calls.c b/sys/v4l2/v4l2_calls.c
index 00d57ec41..e273f3285 100644
--- a/sys/v4l2/v4l2_calls.c
+++ b/sys/v4l2/v4l2_calls.c
@@ -610,6 +610,10 @@ gst_v4l2_open (GstV4l2Object * v4l2object, GstV4l2Error * error)
     v4l2object->is_amphion = TRUE;
   }
 
+  if (!strcmp ((char *) v4l2object->vcap.driver, "vsi_v4l2")) {
+    v4l2object->is_hantro = TRUE;
+  }
+
   return TRUE;
 
   /* ERRORS */
@@ -699,6 +703,7 @@ gst_v4l2_dup (GstV4l2Object * v4l2object, GstV4l2Object * other)
   v4l2object->dont_use_dmabuf = other->dont_use_dmabuf;
   v4l2object->no_initial_format = other->no_initial_format;
   v4l2object->is_amphion = other->is_amphion;
+  v4l2object->is_hantro = other->is_hantro;
 
   return TRUE;
 
-- 
2.34.1


From 8b1e980f02e7d59533814fae44e136d0abb46dcb Mon Sep 17 00:00:00 2001
From: Haihua Hu <jared.hu@nxp.com>
Date: Fri, 18 Dec 2020 17:35:19 +0800
Subject: [PATCH 28/75] Revert "matroska-mux: Fix incorrect rounding of
 timestamps"

this commit will cause our mkv parser dead loop while seeking keyframe

This reverts commit ce802f033c8cee4f923c0d893dda0efd0d003689.

(cherry picked from commit fdf888b4af97dd779d77ffa3f18e740842989532)
---
 gst/matroska/matroska-mux.c | 32 +++++---------------------------
 1 file changed, 5 insertions(+), 27 deletions(-)

diff --git a/gst/matroska/matroska-mux.c b/gst/matroska/matroska-mux.c
index f6f49a44b..7c1706004 100644
--- a/gst/matroska/matroska-mux.c
+++ b/gst/matroska/matroska-mux.c
@@ -4002,7 +4002,6 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad,
   GstBuffer *hdr;
   guint64 blockgroup;
   gboolean write_duration;
-  guint64 cluster_time_scaled;
   gint16 relative_timestamp;
   gint64 relative_timestamp64;
   guint64 block_duration, duration_diff = 0;
@@ -4119,8 +4118,6 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad,
         gst_pad_push_event (mux->srcpad, mux->force_key_unit_event);
         mux->force_key_unit_event = NULL;
       }
-      cluster_time_scaled =
-          gst_util_uint64_scale (buffer_timestamp, 1, mux->time_scale);
 
       mux->prev_cluster_size = ebml->pos - mux->cluster_pos;
       mux->cluster_pos = ebml->pos;
@@ -4128,44 +4125,25 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad,
       mux->cluster =
           gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_CLUSTER);
       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_CLUSTERTIMECODE,
-          cluster_time_scaled);
+          gst_util_uint64_scale (buffer_timestamp, 1, mux->time_scale));
       GST_LOG_OBJECT (mux, "cluster timestamp %" G_GUINT64_FORMAT,
           gst_util_uint64_scale (buffer_timestamp, 1, mux->time_scale));
       gst_ebml_write_flush_cache (ebml, is_video_keyframe
           || is_audio_only, buffer_timestamp);
+      mux->cluster_time = buffer_timestamp;
       gst_ebml_write_uint (ebml, GST_MATROSKA_ID_PREVSIZE,
           mux->prev_cluster_size);
-      /* cluster_time needs to be identical in value to what's stored in the
-       * matroska so we need to have it with the same precision as what's
-       * possible with the set timecodescale rather than just using the
-       * buffer_timestamp.
-       * If this is not done the rounding of relative_timestamp will be
-       * incorrect and possibly making the timestamps get out of order if tw
-       * buffers arrive at the same millisecond (assuming default timecodescale
-       * of 1ms) */
-      mux->cluster_time =
-          gst_util_uint64_scale (cluster_time_scaled, mux->time_scale, 1);
     }
   } else {
     /* first cluster */
-    cluster_time_scaled =
-        gst_util_uint64_scale (buffer_timestamp, 1, mux->time_scale);
+
     mux->cluster_pos = ebml->pos;
     gst_ebml_write_set_cache (ebml, 0x20);
     mux->cluster = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_CLUSTER);
     gst_ebml_write_uint (ebml, GST_MATROSKA_ID_CLUSTERTIMECODE,
-        cluster_time_scaled);
+        gst_util_uint64_scale (buffer_timestamp, 1, mux->time_scale));
     gst_ebml_write_flush_cache (ebml, TRUE, buffer_timestamp);
-    /* cluster_time needs to be identical in value to what's stored in the
-     * matroska so we need to have it with the same precision as what's
-     * possible with the set timecodescale rather than just using the
-     * buffer_timestamp.
-     * If this is not done the rounding of relative_timestamp will be
-     * incorrect and possibly making the timestamps get out of order if tw
-     * buffers arrive at the same millisecond (assuming default timecodescale
-     * of 1ms) */
-    mux->cluster_time =
-        gst_util_uint64_scale (cluster_time_scaled, mux->time_scale, 1);
+    mux->cluster_time = buffer_timestamp;
   }
 
   /* We currently write index entries for all video tracks or for the audio
-- 
2.34.1


From 4434bb32cf401d52fefd63392882cb6aaf1838ed Mon Sep 17 00:00:00 2001
From: Hou Qi <qi.hou@nxp.com>
Date: Mon, 18 Jan 2021 17:23:52 +0800
Subject: [PATCH 29/75] MMFMWK-8930 v4l2videodec: exchange
 V4L2_PIX_FMT_VC1_ANNEX_G and V4L2_PIX_FMT_VC1_ANNEX_L

VC1_L and VC1_G are reversed in driver and v4l2 plugin for amphion.
Driver has exchanged them, so we also need to modify accordingly here.

(cherry picked from commit ad235c60d33c4b15cf92dd7e99a688e1b3e471de)
---
 sys/v4l2/gstv4l2object.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c
index 602e3430f..4b81beead 100644
--- a/sys/v4l2/gstv4l2object.c
+++ b/sys/v4l2/gstv4l2object.c
@@ -2174,9 +2174,9 @@ gst_v4l2_object_get_caps_info (GstV4l2Object * v4l2object, GstCaps * caps,
     } else if (g_str_equal (mimetype, "video/x-wmv")) {
       const gchar *format = gst_structure_get_string (structure, "format");
       if (format) {
-        if (!g_ascii_strcasecmp (format, "WMV3"))
+        if (!g_ascii_strcasecmp (format, "WVC1"))
           fourcc = V4L2_PIX_FMT_VC1_ANNEX_G;
-        else if (!g_ascii_strcasecmp (format, "WVC1"))
+        else if (!g_ascii_strcasecmp (format, "WMV3"))
           fourcc = V4L2_PIX_FMT_VC1_ANNEX_L;
       }
     } else if (g_str_equal (mimetype, "video/x-vp8")) {
-- 
2.34.1


From 37ae2ed04b0a8c039fef8684692c686861b7c62d Mon Sep 17 00:00:00 2001
From: Hou Qi <qi.hou@nxp.com>
Date: Tue, 29 Dec 2020 11:05:27 +0800
Subject: [PATCH 30/75] v4l2videoenc: Add BGR16 format support.

Signed-off-by: Hou Qi <qi.hou@nxp.com>
(cherry picked from commit 0ab8138a859b9b82e928dfc96285dc8d26c80b6a)
---
 sys/v4l2/ext/videodev2.h |  1 +
 sys/v4l2/gstv4l2object.c | 10 ++++++++++
 2 files changed, 11 insertions(+)

diff --git a/sys/v4l2/ext/videodev2.h b/sys/v4l2/ext/videodev2.h
index 25a0b10cf..6dd5fbd9b 100644
--- a/sys/v4l2/ext/videodev2.h
+++ b/sys/v4l2/ext/videodev2.h
@@ -530,6 +530,7 @@ struct v4l2_pix_format {
 #define V4L2_PIX_FMT_BGRA555 v4l2_fourcc('B', 'A', '1', '5') /* 16  BGRA-5-5-5-1  */
 #define V4L2_PIX_FMT_BGRX555 v4l2_fourcc('B', 'X', '1', '5') /* 16  BGRX-5-5-5-1  */
 #define V4L2_PIX_FMT_RGB565  v4l2_fourcc('R', 'G', 'B', 'P') /* 16  RGB-5-6-5     */
+#define V4L2_PIX_FMT_BGR565	 v4l2_fourcc('B', 'G', 'R', 'P') /* 16  BGR-5-6-5     */
 #define V4L2_PIX_FMT_RGB555X v4l2_fourcc('R', 'G', 'B', 'Q') /* 16  RGB-5-5-5 BE  */
 #define V4L2_PIX_FMT_ARGB555X v4l2_fourcc_be('A', 'R', '1', '5') /* 16  ARGB-5-5-5 BE */
 #define V4L2_PIX_FMT_XRGB555X v4l2_fourcc_be('X', 'R', '1', '5') /* 16  XRGB-5-5-5 BE */
diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c
index 4b81beead..958994777 100644
--- a/sys/v4l2/gstv4l2object.c
+++ b/sys/v4l2/gstv4l2object.c
@@ -89,6 +89,7 @@ static const GstV4L2FormatDesc gst_v4l2_formats[] = {
   {V4L2_PIX_FMT_XRGB555, TRUE, GST_V4L2_RAW},
   {V4L2_PIX_FMT_ARGB555X, TRUE, GST_V4L2_RAW},
   {V4L2_PIX_FMT_XRGB555X, TRUE, GST_V4L2_RAW},
+  {V4L2_PIX_FMT_BGR565, TRUE, GST_V4L2_RAW},
   {V4L2_PIX_FMT_RGB565, TRUE, GST_V4L2_RAW},
   {V4L2_PIX_FMT_RGB565X, TRUE, GST_V4L2_RAW},
   {V4L2_PIX_FMT_BGR666, TRUE, GST_V4L2_RAW},
@@ -1073,6 +1074,7 @@ gst_v4l2_object_format_get_rank (const struct v4l2_fmtdesc *fmt)
     case V4L2_PIX_FMT_ARGB555X:
     case V4L2_PIX_FMT_XRGB555X:
     case V4L2_PIX_FMT_RGB555X:
+    case V4L2_PIX_FMT_BGR565:
     case V4L2_PIX_FMT_BGR666:
     case V4L2_PIX_FMT_RGB565:
     case V4L2_PIX_FMT_RGB565X:
@@ -1380,6 +1382,9 @@ gst_v4l2_object_v4l2fourcc_to_video_format (guint32 fourcc)
     case V4L2_PIX_FMT_RGB555X:
       format = GST_VIDEO_FORMAT_BGR15;
       break;
+    case V4L2_PIX_FMT_BGR565:
+      format = GST_VIDEO_FORMAT_BGR16;
+      break;
     case V4L2_PIX_FMT_RGB565:
       format = GST_VIDEO_FORMAT_RGB16;
       break;
@@ -1500,6 +1505,7 @@ gst_v4l2_object_v4l2fourcc_is_rgb (guint32 fourcc)
     case V4L2_PIX_FMT_RGB555:
     case V4L2_PIX_FMT_XRGB555X:
     case V4L2_PIX_FMT_RGB555X:
+    case V4L2_PIX_FMT_BGR565:
     case V4L2_PIX_FMT_RGB565:
     case V4L2_PIX_FMT_RGB24:
     case V4L2_PIX_FMT_BGR24:
@@ -1649,6 +1655,7 @@ gst_v4l2_object_v4l2fourcc_to_bare_struct (guint32 fourcc)
     case V4L2_PIX_FMT_RGB555:
     case V4L2_PIX_FMT_XRGB555X:
     case V4L2_PIX_FMT_RGB555X:
+    case V4L2_PIX_FMT_BGR565:
     case V4L2_PIX_FMT_RGB565:
     case V4L2_PIX_FMT_RGB24:
     case V4L2_PIX_FMT_BGR24:
@@ -2061,6 +2068,9 @@ gst_v4l2_object_get_caps_info (GstV4l2Object * v4l2object, GstCaps * caps,
         fourcc = V4L2_PIX_FMT_RGB555;
         fourcc_nc = V4L2_PIX_FMT_XRGB555;
         break;
+      case GST_VIDEO_FORMAT_BGR16:
+        fourcc = V4L2_PIX_FMT_BGR565;
+        break;
       case GST_VIDEO_FORMAT_RGB16:
         fourcc = V4L2_PIX_FMT_RGB565;
         break;
-- 
2.34.1


From 44c5d5a3ae1302891c099808640111ce8850d18b Mon Sep 17 00:00:00 2001
From: Hou Qi <qi.hou@nxp.com>
Date: Fri, 29 Jan 2021 15:47:24 +0800
Subject: [PATCH 31/75] v4l2videodec: Add hantro 10bit support

For 10bit stream on 8MM and 8MP, need to skip NV12X format when
probe capture supported caps.
(cherry picked from commit 11b6e0eb617be8cc3ed6027c18f5356fe589e40e,
commit 63f281dfff8851b3e8847183052749c82e92dce3,
commit b3146d4746f53f47371a3428993a2143d2b30ac5)

 Conflicts:
	sys/v4l2/ext/videodev2.h
---
 sys/v4l2/ext/videodev2.h |  1 +
 sys/v4l2/gstv4l2object.c | 18 +++++++++++++++++-
 2 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/sys/v4l2/ext/videodev2.h b/sys/v4l2/ext/videodev2.h
index 6dd5fbd9b..4bd9c3f92 100644
--- a/sys/v4l2/ext/videodev2.h
+++ b/sys/v4l2/ext/videodev2.h
@@ -625,6 +625,7 @@ struct v4l2_pix_format {
 #define V4L2_PIX_FMT_NV16M   v4l2_fourcc('N', 'M', '1', '6') /* 16  Y/CbCr 4:2:2  */
 #define V4L2_PIX_FMT_NV61M   v4l2_fourcc('N', 'M', '6', '1') /* 16  Y/CrCb 4:2:2  */
 #define V4L2_PIX_FMT_P012M   v4l2_fourcc('P', 'M', '1', '2') /* 24  Y/CbCr 4:2:0 12-bit per component */
+#define V4L2_PIX_FMT_NV12X	 v4l2_fourcc('N', 'V', 'X', '2') /* Y/CbCr 4:2:0 for 10bit  */
 #define V4L2_PIX_FMT_NV12_10BIT   v4l2_fourcc('N', 'T', '1', '2') /* Y/CbCr 4:2:0 for 10bit  */
 
 /* three planes - Y Cb, Cr */
diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c
index 958994777..ae16045e5 100644
--- a/sys/v4l2/gstv4l2object.c
+++ b/sys/v4l2/gstv4l2object.c
@@ -155,6 +155,7 @@ static const GstV4L2FormatDesc gst_v4l2_formats[] = {
   /* two planes -- one Y, one Cr + Cb interleaved  */
   {V4L2_PIX_FMT_NV12, TRUE, GST_V4L2_RAW},
   {V4L2_PIX_FMT_NV12_10BIT, TRUE, GST_V4L2_RAW},
+  {V4L2_PIX_FMT_NV12X, TRUE, GST_V4L2_RAW},
   {V4L2_PIX_FMT_NV12M, TRUE, GST_V4L2_RAW},
   {V4L2_PIX_FMT_NV12MT, TRUE, GST_V4L2_RAW},
   {V4L2_PIX_FMT_NV12MT_16X16, TRUE, GST_V4L2_RAW},
@@ -1145,6 +1146,7 @@ gst_v4l2_object_format_get_rank (const struct v4l2_fmtdesc *fmt)
     case V4L2_PIX_FMT_NV12:    /* Y/CbCr 4:2:0, 12 bits per pixel */
     case V4L2_PIX_FMT_NV12M:   /* Same as NV12      */
     case V4L2_PIX_FMT_NV12_10BIT:      /* 12  Y/CbCr 4:2:0  */
+    case V4L2_PIX_FMT_NV12X:
       rank = YUV_BASE_RANK + 8;
       break;
     case V4L2_PIX_FMT_YUYV:    /* YUY2, 16 bits per pixel */
@@ -1425,6 +1427,7 @@ gst_v4l2_object_v4l2fourcc_to_video_format (guint32 fourcc)
       format = GST_VIDEO_FORMAT_NV12;
       break;
     case V4L2_PIX_FMT_NV12_10BIT:
+    case V4L2_PIX_FMT_NV12X:
       format = GST_VIDEO_FORMAT_NV12_10LE40;
       break;
     case V4L2_PIX_FMT_NV12MT:
@@ -1671,6 +1674,7 @@ gst_v4l2_object_v4l2fourcc_to_bare_struct (guint32 fourcc)
     case V4L2_PIX_FMT_ABGR32:
     case V4L2_PIX_FMT_NV12:    /* 12  Y/CbCr 4:2:0  */
     case V4L2_PIX_FMT_NV12_10BIT:      /* 12  Y/CbCr 4:2:0  */
+    case V4L2_PIX_FMT_NV12X:
     case V4L2_PIX_FMT_NV12M:
     case V4L2_PIX_FMT_NV12MT:
     case V4L2_PIX_FMT_MM21:
@@ -2032,7 +2036,10 @@ gst_v4l2_object_get_caps_info (GstV4l2Object * v4l2object, GstCaps * caps,
         fourcc_nc = V4L2_PIX_FMT_NV12M;
         break;
       case GST_VIDEO_FORMAT_NV12_10LE40:
-        fourcc = V4L2_PIX_FMT_NV12_10BIT;
+        if (v4l2object->is_amphion)
+          fourcc = V4L2_PIX_FMT_NV12_10BIT;
+        else
+          fourcc = V4L2_PIX_FMT_NV12X;
         break;
       case GST_VIDEO_FORMAT_NV12_64Z32:
         fourcc_nc = V4L2_PIX_FMT_NV12MT;
@@ -4702,6 +4709,9 @@ gst_v4l2_object_acquire_format (GstV4l2Object * v4l2object, GstVideoInfo * info)
   if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_G_FMT, &fmt) < 0)
     goto get_fmt_failed;
 
+  if (!IS_IMX8MQ () && fmt.fmt.pix.pixelformat == V4L2_PIX_FMT_NV12X)
+    fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_NV12;
+
   fmtdesc = gst_v4l2_object_get_format_from_fourcc (v4l2object,
       fmt.fmt.pix.pixelformat);
   if (fmtdesc == NULL)
@@ -5169,6 +5179,12 @@ gst_v4l2_object_probe_caps (GstV4l2Object * v4l2object, GstCaps * filter)
     GstCaps *tmp;
 
     format = (struct v4l2_fmtdesc *) walk->data;
+    if (!IS_IMX8MQ () && format->pixelformat == V4L2_PIX_FMT_NV12X) {
+      GST_DEBUG_OBJECT (v4l2object->dbg_obj,
+          "skip format %" GST_FOURCC_FORMAT,
+          GST_FOURCC_ARGS (format->pixelformat));
+      continue;
+    }
 
     template = gst_v4l2_object_v4l2fourcc_to_bare_struct (format->pixelformat);
 
-- 
2.34.1


From 55c339467d3ffd9260a57eae1a8cf1ec91829299 Mon Sep 17 00:00:00 2001
From: Hou Qi <qi.hou@nxp.com>
Date: Thu, 28 Jan 2021 12:04:32 +0800
Subject: [PATCH 32/75] v4l2videodec: Add hantro tiled output support

(cherry picked from commit e1899b66986b9c7bc2ede0e4a953bd37066900d8,
commit d3051d2ab731cea96b3060bbba6d0c89ec5becbe)

Signed-off-by: Hou Qi <qi.hou@nxp.com>

 Conflicts:
	sys/v4l2/gstv4l2bufferpool.c
---
 sys/v4l2/ext/videodev2.h     |   2 +
 sys/v4l2/gstv4l2bufferpool.c |  10 ++++
 sys/v4l2/gstv4l2object.c     | 102 +++++++++++++++++++++++++++++++++++
 sys/v4l2/gstv4l2object.h     |   2 +
 sys/v4l2/gstv4l2videodec.c   |  12 ++++-
 5 files changed, 126 insertions(+), 2 deletions(-)

diff --git a/sys/v4l2/ext/videodev2.h b/sys/v4l2/ext/videodev2.h
index 4bd9c3f92..a60be032c 100644
--- a/sys/v4l2/ext/videodev2.h
+++ b/sys/v4l2/ext/videodev2.h
@@ -627,6 +627,8 @@ struct v4l2_pix_format {
 #define V4L2_PIX_FMT_P012M   v4l2_fourcc('P', 'M', '1', '2') /* 24  Y/CbCr 4:2:0 12-bit per component */
 #define V4L2_PIX_FMT_NV12X	 v4l2_fourcc('N', 'V', 'X', '2') /* Y/CbCr 4:2:0 for 10bit  */
 #define V4L2_PIX_FMT_NV12_10BIT   v4l2_fourcc('N', 'T', '1', '2') /* Y/CbCr 4:2:0 for 10bit  */
+#define V4L2_PIX_FMT_RFC	 v4l2_fourcc('R', 'F', 'C', '0') /* 8bit tile output, with rfc*/
+#define V4L2_PIX_FMT_RFCX	 v4l2_fourcc('R', 'F', 'C', 'X') /* 10 bit tile output, with rfc */
 
 /* three planes - Y Cb, Cr */
 #define V4L2_PIX_FMT_YUV410  v4l2_fourcc('Y', 'U', 'V', '9') /*  9  YUV 4:1:0     */
diff --git a/sys/v4l2/gstv4l2bufferpool.c b/sys/v4l2/gstv4l2bufferpool.c
index 89a173865..65042b51f 100644
--- a/sys/v4l2/gstv4l2bufferpool.c
+++ b/sys/v4l2/gstv4l2bufferpool.c
@@ -39,6 +39,8 @@
 #include "gst/video/gstvideometa.h"
 #include "gst/video/gstvideopool.h"
 #include "gst/allocators/gstdmabuf.h"
+#include "gst/allocators/gstphymemmeta.h"
+#include "gstimxcommon.h"
 
 #include <gstv4l2bufferpool.h>
 
@@ -1245,6 +1247,7 @@ gst_v4l2_buffer_pool_dqbuf (GstV4l2BufferPool * pool, GstBuffer ** buffer,
   GstClockTime timestamp;
   GstV4l2MemoryGroup *group;
   const GstVideoInfo *info = &obj->info;
+  GstPhyMemMeta *pmeta = { 0 };
   gint i;
   gint old_buffer_state;
 
@@ -1422,6 +1425,13 @@ gst_v4l2_buffer_pool_dqbuf (GstV4l2BufferPool * pool, GstBuffer ** buffer,
   GST_BUFFER_OFFSET (outbuf) = group->buffer.sequence;
   GST_BUFFER_OFFSET_END (outbuf) = group->buffer.sequence + 1;
 
+  if (IS_IMX8MQ () && obj->drm_modifier != 0
+      && !V4L2_TYPE_IS_OUTPUT (obj->type)) {
+    pmeta = GST_PHY_MEM_META_ADD (outbuf);
+    pmeta->rfc_luma_offset = group->buffer.reserved;
+    pmeta->rfc_chroma_offset = group->buffer.reserved2;
+  }
+
 done:
   *buffer = outbuf;
 
diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c
index ae16045e5..e1828248b 100644
--- a/sys/v4l2/gstv4l2object.c
+++ b/sys/v4l2/gstv4l2object.c
@@ -38,11 +38,14 @@
 #include "gstv4l2object.h"
 #include "gstv4l2tuner.h"
 #include "gstv4l2colorbalance.h"
+#include "gstimxcommon.h"
 
 #include <glib/gi18n-lib.h>
 
 #include <gst/video/video.h>
 #include <gst/allocators/gstdmabuf.h>
+#include <gst/allocators/gstdmabufmeta.h>
+#include <libdrm/drm_fourcc.h>
 
 GST_DEBUG_CATEGORY_EXTERN (v4l2_debug);
 #define GST_CAT_DEFAULT v4l2_debug
@@ -156,6 +159,8 @@ static const GstV4L2FormatDesc gst_v4l2_formats[] = {
   {V4L2_PIX_FMT_NV12, TRUE, GST_V4L2_RAW},
   {V4L2_PIX_FMT_NV12_10BIT, TRUE, GST_V4L2_RAW},
   {V4L2_PIX_FMT_NV12X, TRUE, GST_V4L2_RAW},
+  {V4L2_PIX_FMT_RFC, TRUE, GST_V4L2_RAW},
+  {V4L2_PIX_FMT_RFCX, TRUE, GST_V4L2_RAW},
   {V4L2_PIX_FMT_NV12M, TRUE, GST_V4L2_RAW},
   {V4L2_PIX_FMT_NV12MT, TRUE, GST_V4L2_RAW},
   {V4L2_PIX_FMT_NV12MT_16X16, TRUE, GST_V4L2_RAW},
@@ -546,6 +551,9 @@ gst_v4l2_object_new (GstElement * element,
   v4l2object->channels = NULL;
   v4l2object->colors = NULL;
 
+  v4l2object->drm_modifier = 0;
+  v4l2object->is_g2 = FALSE;
+
   v4l2object->keep_aspect = TRUE;
 
   v4l2object->n_v4l2_planes = 0;
@@ -1116,6 +1124,8 @@ gst_v4l2_object_format_get_rank (const struct v4l2_fmtdesc *fmt)
       rank = GREY_BASE_RANK;
       break;
 
+    case V4L2_PIX_FMT_RFC:     /* 8-bit tile output  */
+    case V4L2_PIX_FMT_RFCX:    /* 10-bit tile output  */
     case V4L2_PIX_FMT_NV12MT:  /* NV12 64x32 tile   */
     case V4L2_PIX_FMT_NV21:    /* 12  Y/CrCb 4:2:0  */
     case V4L2_PIX_FMT_NV21M:   /* Same as NV21      */
@@ -1424,10 +1434,12 @@ gst_v4l2_object_v4l2fourcc_to_video_format (guint32 fourcc)
       break;
     case V4L2_PIX_FMT_NV12:
     case V4L2_PIX_FMT_NV12M:
+    case V4L2_PIX_FMT_RFC:
       format = GST_VIDEO_FORMAT_NV12;
       break;
     case V4L2_PIX_FMT_NV12_10BIT:
     case V4L2_PIX_FMT_NV12X:
+    case V4L2_PIX_FMT_RFCX:
       format = GST_VIDEO_FORMAT_NV12_10LE40;
       break;
     case V4L2_PIX_FMT_NV12MT:
@@ -1675,6 +1687,8 @@ gst_v4l2_object_v4l2fourcc_to_bare_struct (guint32 fourcc)
     case V4L2_PIX_FMT_NV12:    /* 12  Y/CbCr 4:2:0  */
     case V4L2_PIX_FMT_NV12_10BIT:      /* 12  Y/CbCr 4:2:0  */
     case V4L2_PIX_FMT_NV12X:
+    case V4L2_PIX_FMT_RFC:
+    case V4L2_PIX_FMT_RFCX:
     case V4L2_PIX_FMT_NV12M:
     case V4L2_PIX_FMT_NV12MT:
     case V4L2_PIX_FMT_MM21:
@@ -3930,6 +3944,9 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
     goto invalid_caps;
 
   pixelformat = fmtdesc->pixelformat;
+  if (V4L2_TYPE_IS_OUTPUT (v4l2object->type)
+      && (pixelformat == V4L2_PIX_FMT_HEVC || pixelformat == V4L2_PIX_FMT_VP9))
+    v4l2object->is_g2 = TRUE;
   width = GST_VIDEO_INFO_WIDTH (&info);
   height = GST_VIDEO_INFO_FIELD_HEIGHT (&info);
   /* if caps has no width and height info, use default value */
@@ -5496,6 +5513,8 @@ gst_v4l2_object_decide_allocation (GstV4l2Object * obj, GstQuery * query)
   GstAllocator *allocator = NULL;
   GstAllocationParams params = { 0 };
   guint video_idx;
+  gboolean alloc_has_meta = FALSE;
+  guint alloc_index;
 
   GST_DEBUG_OBJECT (obj->dbg_obj, "decide allocation");
 
@@ -5529,6 +5548,89 @@ gst_v4l2_object_decide_allocation (GstV4l2Object * obj, GstQuery * query)
   GST_DEBUG_OBJECT (obj->dbg_obj, "allocation: size:%u min:%u max:%u pool:%"
       GST_PTR_FORMAT, size, min, max, pool);
 
+  alloc_has_meta =
+      gst_query_find_allocation_meta (query, GST_DMABUF_META_API_TYPE,
+      &alloc_index);
+
+  if (IS_IMX8MQ () || IS_AMPHION ()) {
+    if (alloc_has_meta) {
+      const GstStructure *params;
+      gint j, len;
+
+      gst_query_parse_nth_allocation_meta (query, alloc_index, &params);
+      GST_DEBUG_OBJECT (obj->dbg_obj,
+          "Expected field 'GstDmabufMeta' in structure: %" GST_PTR_FORMAT,
+          params);
+      if (params) {
+        const GValue *vdrm_modifier =
+            gst_structure_get_value (params, "dmabuf.drm_modifier");
+        gchar *meta = gst_structure_to_string (params);
+        if (GST_VALUE_HOLDS_LIST (vdrm_modifier)) {
+          len = gst_value_list_get_size (vdrm_modifier);
+          for (j = 0; j < len; j++) {
+            const GValue *val;
+            val = gst_value_list_get_value (vdrm_modifier, j);
+            guint64 drm_modifier = g_value_get_uint64 (val);
+            GST_DEBUG_OBJECT (obj->dbg_obj,
+                "dmabuf meta has modifier: %" G_GUINT64_FORMAT, drm_modifier);
+            if (IS_AMPHION () && drm_modifier == DRM_FORMAT_MOD_AMPHION_TILED) {
+              obj->drm_modifier = drm_modifier;
+            } else if (IS_IMX8MQ ()
+                && drm_modifier == DRM_FORMAT_MOD_VSI_G2_TILED_COMPRESSED
+                && obj->is_g2 == TRUE) {
+              obj->drm_modifier = drm_modifier;
+              if (obj->format.fmt.pix.pixelformat == V4L2_PIX_FMT_NV12X)
+                obj->format.fmt.pix.pixelformat = V4L2_PIX_FMT_RFCX;
+              /* Hdr10 video does renegotiation to transfer hdr10 metadata. Capture pixelformat has been
+               * changed from NV12X to RFCX at the first time, so just keep the RFCX format here. */
+              else if (obj->format.fmt.pix.pixelformat != V4L2_PIX_FMT_RFCX)
+                obj->format.fmt.pix.pixelformat = V4L2_PIX_FMT_RFC;
+            } else {
+              GST_WARNING_OBJECT (obj->dbg_obj,
+                  "video sink can't support modifier: %lld",
+                  DRM_FORMAT_MOD_AMPHION_TILED);
+            }
+          }
+        } else if (meta) {
+          guint64 drm_modifier;
+          GST_DEBUG_OBJECT (obj->dbg_obj, "dmabuf meta has modifier: %s", meta);
+          sscanf (meta,
+              "GstDmabufMeta, dmabuf.drm_modifier=(guint64){ %" G_GUINT64_FORMAT
+              " };", &drm_modifier);
+          GST_DEBUG_OBJECT (obj->dbg_obj,
+              "dmabuf meta has modifier: %" G_GUINT64_FORMAT, drm_modifier);
+          if (IS_AMPHION () && drm_modifier == DRM_FORMAT_MOD_AMPHION_TILED) {
+            GST_DEBUG_OBJECT (obj->dbg_obj,
+                "video sink support modifier: %" G_GUINT64_FORMAT,
+                drm_modifier);
+            obj->drm_modifier = drm_modifier;
+          } else if (IS_IMX8MQ ()
+              && drm_modifier == DRM_FORMAT_MOD_VSI_G2_TILED_COMPRESSED
+              && obj->is_g2 == TRUE) {
+            GST_DEBUG_OBJECT (obj->dbg_obj,
+                "video sink support modifier: %" G_GUINT64_FORMAT,
+                drm_modifier);
+            obj->drm_modifier = drm_modifier;
+            if (obj->format.fmt.pix.pixelformat == V4L2_PIX_FMT_NV12X)
+              obj->format.fmt.pix.pixelformat = V4L2_PIX_FMT_RFCX;
+            else if (obj->format.fmt.pix.pixelformat != V4L2_PIX_FMT_RFCX)
+              obj->format.fmt.pix.pixelformat = V4L2_PIX_FMT_RFC;
+          } else {
+            GST_WARNING_OBJECT (obj->dbg_obj,
+                "video sink can't support modifier: %lld",
+                DRM_FORMAT_MOD_AMPHION_TILED);
+          }
+        }
+        if (obj->ioctl (obj->video_fd, VIDIOC_S_FMT, &obj->format) < 0)
+          GST_WARNING_OBJECT (obj->dbg_obj, "VIDIOC_S_FMT failed");
+        else
+          GST_DEBUG_OBJECT (obj->dbg_obj,
+              "Set tiled output format %" GST_FOURCC_FORMAT,
+              GST_FOURCC_ARGS (obj->format.fmt.pix.pixelformat));
+      }
+    }
+  }
+
   has_video_meta =
       gst_query_find_allocation_meta (query, GST_VIDEO_META_API_TYPE,
       &video_idx);
diff --git a/sys/v4l2/gstv4l2object.h b/sys/v4l2/gstv4l2object.h
index 0c9f98230..229f1c00e 100644
--- a/sys/v4l2/gstv4l2object.h
+++ b/sys/v4l2/gstv4l2object.h
@@ -154,6 +154,8 @@ struct _GstV4l2Object {
   /* Features */
   gboolean need_video_meta;
   gboolean has_alpha_component;
+  guint64 drm_modifier;
+  gboolean is_g2;
 
   /* only used if the device supports MPLANE
    * nb planes is meaning of v4l2 planes
diff --git a/sys/v4l2/gstv4l2videodec.c b/sys/v4l2/gstv4l2videodec.c
index 5dd21b8c7..f233b3948 100644
--- a/sys/v4l2/gstv4l2videodec.c
+++ b/sys/v4l2/gstv4l2videodec.c
@@ -429,6 +429,8 @@ gst_v4l2_video_dec_negotiate (GstVideoDecoder * decoder)
   self->v4l2capture->info.fps_d = self->v4l2output->info.fps_d;
   self->v4l2capture->info.fps_n = self->v4l2output->info.fps_n;
 
+  self->v4l2capture->is_g2 = self->v4l2output->is_g2;
+
   /* For decoders G_FMT returns coded size, G_SELECTION returns visible size
    * in the compose rectangle. gst_v4l2_object_acquire_format() checks both
    * and returns the visible size as with/height and the coded size as
@@ -871,10 +873,16 @@ gst_v4l2_video_dec_loop (GstVideoDecoder * decoder)
 
     frame->duration = self->v4l2capture->duration;
     frame->output_buffer = buffer;
-    if (IS_AMPHION () && self->v4l2capture->is_amphion) {
+    if (IS_IMX8MQ () && self->v4l2capture->is_hantro) {
+      guint64 drm_modifier = self->v4l2capture->drm_modifier;
+      gst_buffer_add_dmabuf_meta (frame->output_buffer, drm_modifier);
+      GST_DEBUG_OBJECT (decoder, "Add drm modifier: %" G_GUINT64_FORMAT,
+          drm_modifier);
+    } else if (IS_AMPHION () && self->v4l2capture->is_amphion) {
       guint64 drm_modifier = DRM_FORMAT_MOD_AMPHION_TILED;
       gst_buffer_add_dmabuf_meta (frame->output_buffer, drm_modifier);
-      GST_DEBUG_OBJECT (decoder, "Add drm modifier: %lld\n", drm_modifier);
+      GST_DEBUG_OBJECT (decoder, "Add drm modifier: %" G_GUINT64_FORMAT,
+          drm_modifier);
     }
     buffer = NULL;
     ret = gst_video_decoder_finish_frame (decoder, frame);
-- 
2.34.1


From a37a71e52d2e263ddda28548720c258fb981da42 Mon Sep 17 00:00:00 2001
From: Hou Qi <qi.hou@nxp.com>
Date: Mon, 22 Feb 2021 10:51:01 +0800
Subject: [PATCH 33/75] v4l2videodec: Add hdr metadata into src caps

Signed-off-by: Hou Qi <qi.hou@nxp.com>

 Conflicts:
	sys/v4l2/gstv4l2videodec.c
(cherry picked from commit adf9da22db8233ab543521b48fa73902f2a5df23,
commit d41df7c548d66ed580f9b0b589fc04e6572b7f71)
---
 sys/v4l2/ext/v4l2-controls.h |  3 ++
 sys/v4l2/ext/videodev2.h     | 13 +++++
 sys/v4l2/gstv4l2videodec.c   | 96 ++++++++++++++++++++++++++++++++++--
 sys/v4l2/gstv4l2videodec.h   |  1 +
 4 files changed, 110 insertions(+), 3 deletions(-)

diff --git a/sys/v4l2/ext/v4l2-controls.h b/sys/v4l2/ext/v4l2-controls.h
index 151dc2c2f..968bc4d73 100644
--- a/sys/v4l2/ext/v4l2-controls.h
+++ b/sys/v4l2/ext/v4l2-controls.h
@@ -207,6 +207,9 @@ enum v4l2_colorfx {
 #define V4L2_CID_CODEC_BASE			(V4L2_CTRL_CLASS_CODEC | 0x900)
 #define V4L2_CID_CODEC_CLASS			(V4L2_CTRL_CLASS_CODEC | 1)
 
+/* ctrls & extension ctrls definitions */
+#define V4L2_CID_HDR10META			(V4L2_CID_USER_IMX_BASE + 6)
+
 /*  MPEG streams, specific to multiplexed streams */
 #define V4L2_CID_MPEG_STREAM_TYPE		(V4L2_CID_CODEC_BASE+0)
 enum v4l2_mpeg_stream_type {
diff --git a/sys/v4l2/ext/videodev2.h b/sys/v4l2/ext/videodev2.h
index a60be032c..da0000a81 100644
--- a/sys/v4l2/ext/videodev2.h
+++ b/sys/v4l2/ext/videodev2.h
@@ -282,6 +282,7 @@ enum v4l2_xfer_func {
 	V4L2_XFER_FUNC_NONE        = 5,
 	V4L2_XFER_FUNC_DCI_P3      = 6,
 	V4L2_XFER_FUNC_SMPTE2084   = 7,
+	V4L2_XFER_FUNC_HLG         = 8,
 };
 
 /*
@@ -1809,6 +1810,18 @@ struct v4l2_ext_controls {
 	struct v4l2_ext_control *controls;
 };
 
+struct v4l2_hdr10_meta {
+	__u32 hasHdr10Meta;
+	__u32 redPrimary[2];
+	__u32 greenPrimary[2];
+	__u32 bluePrimary[2];
+	__u32 whitePoint[2];
+	__u32 maxMasteringLuminance;
+	__u32 minMasteringLuminance;
+	__u32 maxContentLightLevel;
+	__u32 maxFrameAverageLightLevel;
+};
+
 #define V4L2_CTRL_ID_MASK	  (0x0fffffff)
 #define V4L2_CTRL_ID2CLASS(id)    ((id) & 0x0fff0000UL)
 #define V4L2_CTRL_ID2WHICH(id)    ((id) & 0x0fff0000UL)
diff --git a/sys/v4l2/gstv4l2videodec.c b/sys/v4l2/gstv4l2videodec.c
index f233b3948..737c2de6b 100644
--- a/sys/v4l2/gstv4l2videodec.c
+++ b/sys/v4l2/gstv4l2videodec.c
@@ -225,6 +225,10 @@ gst_v4l2_video_dec_stop (GstVideoDecoder * decoder)
     self->input_state = NULL;
   }
 
+  if (self->output_state) {
+    gst_video_codec_state_unref (self->output_state);
+    self->output_state = NULL;
+  }
   GST_DEBUG_OBJECT (self, "Stopped");
 
   return TRUE;
@@ -403,6 +407,55 @@ gst_v4l2_video_remove_padding (GstCapsFeatures * features,
   return TRUE;
 }
 
+static gboolean
+get_hdr10_meta (GstV4l2Object * v4l2object, struct v4l2_hdr10_meta *Hdr10Meta)
+{
+  struct v4l2_ext_control ctrl;
+  struct v4l2_ext_controls ctrls;
+  struct v4l2_hdr10_meta hdr10_meta;
+
+  memset (&ctrls, 0, sizeof (ctrls));
+  memset (&ctrl, 0, sizeof (ctrl));
+  memset (&hdr10_meta, 0, sizeof (hdr10_meta));
+
+  ctrls.controls = &ctrl;
+  ctrls.count = 1;
+
+  ctrl.id = V4L2_CID_HDR10META;
+  ctrl.ptr = (void *) &hdr10_meta;
+  ctrl.size = sizeof (hdr10_meta);
+
+  if (ioctl (v4l2object->video_fd, VIDIOC_G_EXT_CTRLS, &ctrls) < 0) {
+    GST_WARNING_OBJECT (v4l2object->dbg_obj, "Failed to get hdr10 meta\n");
+    return FALSE;
+  }
+
+  *Hdr10Meta = hdr10_meta;
+  if (!hdr10_meta.hasHdr10Meta) {
+    GST_INFO_OBJECT (v4l2object->dbg_obj, "Has no HDR meta");
+    return FALSE;
+  }
+
+  GST_INFO_OBJECT (v4l2object->dbg_obj, "redPrimary(%d, %d)",
+      hdr10_meta.redPrimary[0], hdr10_meta.redPrimary[1]);
+  GST_INFO_OBJECT (v4l2object->dbg_obj, "greenPrimary(%d, %d)",
+      hdr10_meta.greenPrimary[0], hdr10_meta.greenPrimary[1]);
+  GST_INFO_OBJECT (v4l2object->dbg_obj, "bluePrimary(%d, %d)",
+      hdr10_meta.bluePrimary[0], hdr10_meta.bluePrimary[1]);
+  GST_INFO_OBJECT (v4l2object->dbg_obj, "whitePoint(%d, %d)",
+      hdr10_meta.whitePoint[0], hdr10_meta.whitePoint[1]);
+  GST_INFO_OBJECT (v4l2object->dbg_obj, "maxMasteringLuminance %d",
+      hdr10_meta.maxMasteringLuminance);
+  GST_INFO_OBJECT (v4l2object->dbg_obj, "minMasteringLuminance %d",
+      hdr10_meta.minMasteringLuminance);
+  GST_INFO_OBJECT (v4l2object->dbg_obj, "maxContentLightLevel %d",
+      hdr10_meta.maxContentLightLevel);
+  GST_INFO_OBJECT (v4l2object->dbg_obj, "maxFrameAverageLightLevel %d",
+      hdr10_meta.maxFrameAverageLightLevel);
+
+  return TRUE;
+}
+
 static gboolean
 gst_v4l2_video_dec_negotiate (GstVideoDecoder * decoder)
 {
@@ -415,6 +468,7 @@ gst_v4l2_video_dec_negotiate (GstVideoDecoder * decoder)
   gboolean active;
   GstBufferPool *cpool;
   gboolean ret;
+  struct v4l2_hdr10_meta Hdr10Meta = { 0 };
 
   /* We don't allow renegotiation without careful disabling the pool */
   cpool = gst_v4l2_object_get_buffer_pool (self->v4l2capture);
@@ -501,13 +555,15 @@ use_acquired_caps:
   if (!self->v4l2capture->fmtdesc)
     goto not_negotiated;
 
-  output_state = gst_video_decoder_set_output_state (decoder,
-      info.finfo->format, info.width, info.height, self->input_state);
+  if (self->output_state)
+    gst_video_codec_state_unref (self->output_state);
+  self->output_state = output_state =
+      gst_video_decoder_set_output_state (decoder, info.finfo->format,
+      info.width, info.height, self->input_state);
 
   /* Copy the rest of the information, there might be more in the future */
   output_state->info.interlace_mode = info.interlace_mode;
   output_state->info.colorimetry = info.colorimetry;
-  gst_video_codec_state_unref (output_state);
 
   ret = GST_VIDEO_DECODER_CLASS (parent_class)->negotiate (decoder);
   if (!ret) {
@@ -523,6 +579,40 @@ use_acquired_caps:
   cpool = gst_v4l2_object_get_buffer_pool (self->v4l2capture);
   gst_v4l2_buffer_pool_enable_resolution_change (GST_V4L2_BUFFER_POOL (cpool));
 
+  get_hdr10_meta (self->v4l2capture, &Hdr10Meta);
+  if ((self->v4l2capture->format.fmt.pix.xfer_func == V4L2_XFER_FUNC_SMPTE2084
+          || self->v4l2capture->format.fmt.pix.xfer_func == V4L2_XFER_FUNC_HLG)
+      && info.finfo->format == GST_VIDEO_FORMAT_NV12_10LE40) {
+    GstVideoMasteringDisplayInfo minfo;
+    GstVideoContentLightLevel cll;
+    minfo.display_primaries[0].x = Hdr10Meta.redPrimary[0];
+    minfo.display_primaries[0].y = Hdr10Meta.redPrimary[1];
+    minfo.display_primaries[1].x = Hdr10Meta.greenPrimary[0];
+    minfo.display_primaries[1].y = Hdr10Meta.greenPrimary[1];
+    minfo.display_primaries[2].x = Hdr10Meta.bluePrimary[0];
+    minfo.display_primaries[2].y = Hdr10Meta.bluePrimary[1];
+    minfo.white_point.x = Hdr10Meta.whitePoint[0];
+    minfo.white_point.y = Hdr10Meta.whitePoint[1];
+    minfo.max_display_mastering_luminance = Hdr10Meta.maxMasteringLuminance;
+    minfo.min_display_mastering_luminance = Hdr10Meta.minMasteringLuminance;
+    cll.max_content_light_level = Hdr10Meta.maxContentLightLevel;
+    cll.max_frame_average_light_level = Hdr10Meta.maxFrameAverageLightLevel;
+    if (output_state->caps) {
+      output_state->caps = gst_caps_make_writable (output_state->caps);
+      gst_video_mastering_display_info_add_to_caps (&minfo, output_state->caps);
+      gst_video_content_light_level_add_to_caps (&cll, output_state->caps);
+    }
+
+    /* allow renegotiation for hdr10 video */
+    if (!GST_VIDEO_DECODER_CLASS (parent_class)->negotiate (decoder)) {
+      if (GST_PAD_IS_FLUSHING (decoder->sinkpad)
+          || GST_PAD_IS_FLUSHING (decoder->srcpad))
+        goto flushing;
+      else
+        goto not_negotiated;
+    }
+  }
+
   /* Ensure our internal pool is activated */
   active = gst_buffer_pool_set_active (cpool, TRUE);
   if (cpool)
diff --git a/sys/v4l2/gstv4l2videodec.h b/sys/v4l2/gstv4l2videodec.h
index fbbfb60b0..0ab90fa9d 100644
--- a/sys/v4l2/gstv4l2videodec.h
+++ b/sys/v4l2/gstv4l2videodec.h
@@ -60,6 +60,7 @@ struct _GstV4l2VideoDec
 
   /* State */
   GstVideoCodecState *input_state;
+  GstVideoCodecState *output_state;
   gboolean active;
   GstFlowReturn output_flow;
 
-- 
2.34.1


From 3b942c8bdeeb394c2f06ff0da1552422fc559193 Mon Sep 17 00:00:00 2001
From: Hou Qi <qi.hou@nxp.com>
Date: Thu, 25 Mar 2021 12:27:34 +0800
Subject: [PATCH 34/75] v4l2: Add v4l2 plugin print information

Below information will be printed before v4l2 decoding and encoding.
====== V4L2DEC: 1.18.0 build on Mar 25 2021 04:14:21. ======
====== V4L2ENC: 1.18.0 build on Mar 25 2021 04:14:21. ======

(cherry picked from commit b14975f1be11be6c7106fb284f643b2e484e3b37)
---
 sys/v4l2/gstv4l2videodec.c | 3 +++
 sys/v4l2/gstv4l2videoenc.c | 3 +++
 2 files changed, 6 insertions(+)

diff --git a/sys/v4l2/gstv4l2videodec.c b/sys/v4l2/gstv4l2videodec.c
index 737c2de6b..21c24120f 100644
--- a/sys/v4l2/gstv4l2videodec.c
+++ b/sys/v4l2/gstv4l2videodec.c
@@ -125,6 +125,9 @@ gst_v4l2_video_dec_open (GstVideoDecoder * decoder)
   GstV4l2Error error = GST_V4L2_ERROR_INIT;
   GstCaps *codec_caps;
 
+  g_print ("\n====== V4L2DEC: %s build on %s %s. ======\n", (VERSION), __DATE__,
+      __TIME__);
+
   GST_DEBUG_OBJECT (self, "Opening");
 
   if (!gst_v4l2_object_open (self->v4l2output, &error))
diff --git a/sys/v4l2/gstv4l2videoenc.c b/sys/v4l2/gstv4l2videoenc.c
index 10bf1a7b8..e6b277ddd 100644
--- a/sys/v4l2/gstv4l2videoenc.c
+++ b/sys/v4l2/gstv4l2videoenc.c
@@ -113,6 +113,9 @@ gst_v4l2_video_enc_open (GstVideoEncoder * encoder)
   GstV4l2Error error = GST_V4L2_ERROR_INIT;
   GstCaps *codec_caps;
 
+  g_print ("\n====== V4L2ENC: %s build on %s %s. ======\n", (VERSION), __DATE__,
+      __TIME__);
+
   GST_DEBUG_OBJECT (self, "Opening");
 
   if (!gst_v4l2_object_open (self->v4l2output, &error))
-- 
2.34.1


From e0bc2ffdf0c4a971c66153d50e15742182a82ffe Mon Sep 17 00:00:00 2001
From: Hou Qi <qi.hou@nxp.com>
Date: Mon, 26 Apr 2021 16:35:44 +0800
Subject: [PATCH 35/75] v4l2object: Improve colorspace handling to support uvc
 device

v4l2 encoder won't probe all colorspace, range, matrix and transfer combination
to save initialization time for low-speed devices. Unfortunately uvc driver
default colorimetry is not in the colorimetry list of v4l2 encoder and it causes
not-negotiated. If desired colorspace is 1:4:7:1, uvc driver will produce 1:4:5:1.

To fix this, need to allow colorimetry 1:4:5:1 produced by uvc driver if desired
colorspace is 1:4:7:1. This workaround should be removed later like discussion in
https://gitlab.freedesktop.org/gstreamer/gst-plugins-good/-/merge_requests/969.

(cherry picked from commit c2e178e8a1dedbac6c34b75077165c3443018f5b)
---
 sys/v4l2/gstv4l2object.c | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c
index e1828248b..98c0ee703 100644
--- a/sys/v4l2/gstv4l2object.c
+++ b/sys/v4l2/gstv4l2object.c
@@ -3810,6 +3810,14 @@ gst_v4l2_video_colorimetry_matches (const GstVideoColorimetry * cinfo,
     GST_VIDEO_COLOR_RANGE_0_255, GST_VIDEO_COLOR_MATRIX_BT601,
     GST_VIDEO_TRANSFER_SRGB, GST_VIDEO_COLOR_PRIMARIES_BT709
   };
+  static const GstVideoColorimetry ci_likely_uvc = {
+    GST_VIDEO_COLOR_RANGE_0_255, GST_VIDEO_COLOR_MATRIX_BT601,
+    GST_VIDEO_TRANSFER_SRGB, GST_VIDEO_COLOR_PRIMARIES_BT709
+  };
+  static const GstVideoColorimetry ci_uvc = {
+    GST_VIDEO_COLOR_RANGE_0_255, GST_VIDEO_COLOR_MATRIX_BT601,
+    GST_VIDEO_TRANSFER_BT709, GST_VIDEO_COLOR_PRIMARIES_BT709
+  };
 
   if (!gst_video_info_from_caps (&info, caps))
     return FALSE;
@@ -3828,8 +3836,11 @@ gst_v4l2_video_colorimetry_matches (const GstVideoColorimetry * cinfo,
     return TRUE;
 
   /* Allow 1:4:0:0 (produced by jpegdec) if the device expects 1:4:7:1 */
-  if (gst_video_colorimetry_is_equal (&info.colorimetry, &ci_likely_jpeg)
-      && gst_video_colorimetry_is_equal (cinfo, &ci_jpeg))
+  /* Allow 1:4:5:1 (produced by uvc driver) if desired colorspace is 1:4:7:1) */
+  if ((gst_video_colorimetry_is_equal (&info.colorimetry, &ci_likely_jpeg)
+          && gst_video_colorimetry_is_equal (cinfo, &ci_jpeg))
+      || (gst_video_colorimetry_is_equal (&info.colorimetry, &ci_likely_uvc)
+          && gst_video_colorimetry_is_equal (cinfo, &ci_uvc)))
     return TRUE;
 
   /* bypass check the below GST_VIDEO_TRANSFER_ARIB_STD_B67 type, 
-- 
2.34.1


From a224ec48fbc298c4be77249b4f2bfe01618c0b98 Mon Sep 17 00:00:00 2001
From: Haihua Hu <jared.hu@nxp.com>
Date: Thu, 25 Nov 2021 16:17:38 +0800
Subject: [PATCH 36/75] LF-4959 rtpjitterbuffer: fix wait completion of timer
 waiting

For some platform with low performance, the eos event here is
later than previous call of wait_next_time() on eos, it will
wait in that thread, so wait here will cause completion, need
signal that thread first

https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/1390

(cherry picked from commit 723dedafc7ecc52188bc44e434bc9adaa498efd5)
---
 gst/rtpmanager/gstrtpjitterbuffer.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/gst/rtpmanager/gstrtpjitterbuffer.c b/gst/rtpmanager/gstrtpjitterbuffer.c
index 7efdf2d0d..7b8d93c98 100644
--- a/gst/rtpmanager/gstrtpjitterbuffer.c
+++ b/gst/rtpmanager/gstrtpjitterbuffer.c
@@ -3948,6 +3948,11 @@ pop_and_push_next (GstRtpJitterBuffer * jitterbuffer, guint seqnum)
   if (type == ITEM_TYPE_EVENT && outevent &&
       GST_EVENT_TYPE (outevent) == GST_EVENT_EOS) {
     g_assert (priv->eos);
+    /* For some platform with low performance, the eos event here is
+     * later than previous call of wait_next_time() on eos, it will
+     * wait in that thread, so wait here will cause completion, need
+     * signal that thread first */
+    JBUF_SIGNAL_TIMER (priv);
     while (rtp_timer_queue_length (priv->timers) > 0) {
       /* Stopping timers */
       unschedule_current_timer (jitterbuffer);
-- 
2.34.1


From 8d3e0d2cf87f77f203336777a343bfb081eac47a Mon Sep 17 00:00:00 2001
From: Hou Qi <qi.hou@nxp.com>
Date: Thu, 17 Mar 2022 15:46:00 +0800
Subject: [PATCH 37/75] v4l2: Use warning log instead of error log and
 g_warning

Amphion encoder will dequeue one more buffer with bytesused=0 to user as it uses
ringbuffer. Timestamp manager is kept in amphion driver. So this last buffer's
timestamp is marked as last index plus frame->duration, which cannot satisfy
GST_BUFFER_TIMESTAMP (buffer) % GST_SECOND == 0. So use warning log instead.

There is one case that frame[1] and frame[2] have the same timestamp. frame[1]
is decoded but cannot be output, while frame[2] can both be decoded and output.
Then frame list will always has the oldest frame with this timestamp and index
[1] until current frame number becomes 102. At this time, v4l2 decoder drops
frame[1] as (102-1 = 101) >100. This is not a real bug, so use GST_WARNING
instead of g_warning.

Signed-off-by: Hou Qi <qi.hou@nxp.com>
---
 sys/v4l2/gstv4l2videodec.c | 9 +++++----
 sys/v4l2/gstv4l2videoenc.c | 4 ++--
 2 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/sys/v4l2/gstv4l2videodec.c b/sys/v4l2/gstv4l2videodec.c
index 21c24120f..4fca1f0c4 100644
--- a/sys/v4l2/gstv4l2videodec.c
+++ b/sys/v4l2/gstv4l2videodec.c
@@ -762,7 +762,7 @@ gst_v4l2_video_dec_finish (GstVideoDecoder * decoder)
       gst_video_decoder_drop_frame (decoder, frame);
     }
     if (self->output_flow == GST_FLOW_OK) {
-      g_warning ("%s: %i frames %u-%u left undrained after CMD_STOP, "
+      GST_WARNING ("%s: %i frames %u-%u left undrained after CMD_STOP, "
           "eos sent too early: bug in decoder -- please file a bug",
           GST_ELEMENT_NAME (decoder), counter, first, last);
     }
@@ -912,7 +912,7 @@ gst_v4l2_video_dec_loop (GstVideoDecoder * decoder)
     goto beach;
 
   if (GST_BUFFER_TIMESTAMP (buffer) % GST_SECOND != 0)
-    GST_ERROR_OBJECT (decoder,
+    GST_WARNING_OBJECT (decoder,
         "Driver bug detected - check driver with v4l2-compliance from http://git.linuxtv.org/v4l-utils.git");
   GST_LOG_OBJECT (decoder, "Got buffer for frame number %u",
       (guint32) (GST_BUFFER_TIMESTAMP (buffer) / GST_SECOND));
@@ -933,7 +933,8 @@ gst_v4l2_video_dec_loop (GstVideoDecoder * decoder)
         oldest_frame = NULL;
 
         if (!warned) {
-          g_warning ("%s: Too old frames, bug in decoder -- please file a bug",
+          GST_WARNING
+              ("%s: Too old frames, bug in decoder -- please file a bug",
               GST_ELEMENT_NAME (decoder));
           warned = TRUE;
         }
@@ -956,7 +957,7 @@ gst_v4l2_video_dec_loop (GstVideoDecoder * decoder)
             oldest_frame = NULL;
           }
         }
-        g_warning
+        GST_WARNING
             ("%s: %i initial frames were not dequeued: bug in decoder -- please file a bug",
             GST_ELEMENT_NAME (decoder), counter);
       }
diff --git a/sys/v4l2/gstv4l2videoenc.c b/sys/v4l2/gstv4l2videoenc.c
index e6b277ddd..4ab0a6ddd 100644
--- a/sys/v4l2/gstv4l2videoenc.c
+++ b/sys/v4l2/gstv4l2videoenc.c
@@ -683,7 +683,7 @@ gst_v4l2_video_enc_loop (GstVideoEncoder * encoder)
     goto beach;
 
   if (GST_BUFFER_TIMESTAMP (buffer) % GST_SECOND != 0)
-    GST_ERROR_OBJECT (encoder,
+    GST_WARNING_OBJECT (encoder,
         "Driver bug detected - check driver with v4l2-compliance from http://git.linuxtv.org/v4l-utils.git");
   GST_LOG_OBJECT (encoder, "Got buffer for frame number %u",
       (guint32) (GST_BUFFER_PTS (buffer) / GST_SECOND));
@@ -703,7 +703,7 @@ gst_v4l2_video_enc_loop (GstVideoEncoder * encoder)
       oldest_frame = NULL;
 
       if (!warned) {
-        g_warning ("%s: Too old frames, bug in encoder -- please file a bug",
+        GST_WARNING ("%s: Too old frames, bug in encoder -- please file a bug",
             GST_ELEMENT_NAME (encoder));
         warned = TRUE;
       }
-- 
2.34.1


From 2c603b6523a1bc3a1a463513be562be419b2851b Mon Sep 17 00:00:00 2001
From: Song Bing <bing.song@nxp.com>
Date: Thu, 30 Aug 2018 14:26:11 -0700
Subject: [PATCH 38/75] v4l2videodec: Add lock for queue and stream off

Add lock for queue and stream off, or v4l2 core will complain it.

https://bugzilla.gnome.org/show_bug.cgi?id=752962

UpStream Status: Pending

Signed-off-by: Song Bing<bing.song@nxp.com>

Conflicts:
	sys/v4l2/gstv4l2bufferpool.c
(cherry picked from commit 6c5aa754ce667133ea3b11a6ebb67ed913763e41)
---
 sys/v4l2/gstv4l2bufferpool.c | 19 +++++++++++++++----
 1 file changed, 15 insertions(+), 4 deletions(-)

diff --git a/sys/v4l2/gstv4l2bufferpool.c b/sys/v4l2/gstv4l2bufferpool.c
index 65042b51f..5f6dfdef5 100644
--- a/sys/v4l2/gstv4l2bufferpool.c
+++ b/sys/v4l2/gstv4l2bufferpool.c
@@ -733,6 +733,8 @@ gst_v4l2_buffer_pool_streamoff (GstV4l2BufferPool * pool)
   if (!pool->streaming)
     return;
 
+  GST_OBJECT_LOCK (pool);
+
   switch (obj->mode) {
     case GST_V4L2_IO_MMAP:
     case GST_V4L2_IO_USERPTR:
@@ -774,6 +776,8 @@ gst_v4l2_buffer_pool_streamoff (GstV4l2BufferPool * pool)
       g_atomic_int_add (&pool->num_queued, -1);
     }
   }
+
+  GST_OBJECT_UNLOCK (pool);
 }
 
 static gboolean
@@ -1053,11 +1057,12 @@ gst_v4l2_buffer_pool_orphan (GstV4l2Object * v4l2object)
   GST_DEBUG_OBJECT (pool, "orphaning pool");
   gst_buffer_pool_set_active (bpool, FALSE);
 
+  gst_v4l2_buffer_pool_streamoff (pool);
+
   /* We lock to prevent racing with a return buffer in QBuf, and has a
    * workaround of not being able to use the pool hidden activation lock. */
   GST_OBJECT_LOCK (pool);
 
-  gst_v4l2_buffer_pool_streamoff (pool);
   ret = gst_v4l2_allocator_orphan (pool->vallocator);
   if (ret)
     pool->orphaned = TRUE;
@@ -1266,9 +1271,13 @@ gst_v4l2_buffer_pool_dqbuf (GstV4l2BufferPool * pool, GstBuffer ** buffer,
 
   GST_LOG_OBJECT (pool, "dequeueing a buffer");
 
+  GST_OBJECT_LOCK (pool);
+
   res = gst_v4l2_allocator_dqbuf (pool->vallocator, &group);
-  if (res == GST_V4L2_FLOW_LAST_BUFFER)
+  if (res == GST_V4L2_FLOW_LAST_BUFFER) {
+    GST_OBJECT_UNLOCK (pool);
     goto eos;
+  }
   if (res != GST_FLOW_OK)
     goto dqbuf_failed;
 
@@ -1291,11 +1300,11 @@ gst_v4l2_buffer_pool_dqbuf (GstV4l2BufferPool * pool, GstBuffer ** buffer,
 
   pool->buffers[group->buffer.index] = NULL;
   if (g_atomic_int_dec_and_test (&pool->num_queued)) {
-    GST_OBJECT_LOCK (pool);
     pool->empty = TRUE;
-    GST_OBJECT_UNLOCK (pool);
   }
 
+  GST_OBJECT_UNLOCK (pool);
+
   if (group->buffer.flags & V4L2_BUF_FLAG_LAST &&
       group->planes[0].bytesused == 0) {
     GST_DEBUG_OBJECT (pool, "Empty last buffer, signalling eos.");
@@ -1449,10 +1458,12 @@ eos:
   }
 dqbuf_failed:
   {
+    GST_OBJECT_UNLOCK (pool);
     return GST_FLOW_ERROR;
   }
 no_buffer:
   {
+    GST_OBJECT_UNLOCK (pool);
     GST_ERROR_OBJECT (pool, "No free buffer found in the pool at index %d.",
         group->buffer.index);
     return GST_FLOW_ERROR;
-- 
2.34.1


From d43ff7aff4343519e542a872c8a5fc1ff812e90d Mon Sep 17 00:00:00 2001
From: Hou Qi <qi.hou@nxp.com>
Date: Thu, 16 Jun 2022 14:38:24 +0800
Subject: [PATCH 39/75] MMFMWK-9092 v4l2: Fix race condition between orphaning
 and stopping allocator

allocator_stop() may be called when allocator is orphaning. It causes dmafd
leak as capture buffers cannot be freed. So needs to fix the race condition
between orphaning and stopping allocator.

Signed-off-by: Hou Qi <qi.hou@nxp.com>
---
 sys/v4l2/gstv4l2bufferpool.c | 12 +++++-------
 1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/sys/v4l2/gstv4l2bufferpool.c b/sys/v4l2/gstv4l2bufferpool.c
index 5f6dfdef5..5be845fe4 100644
--- a/sys/v4l2/gstv4l2bufferpool.c
+++ b/sys/v4l2/gstv4l2bufferpool.c
@@ -733,8 +733,6 @@ gst_v4l2_buffer_pool_streamoff (GstV4l2BufferPool * pool)
   if (!pool->streaming)
     return;
 
-  GST_OBJECT_LOCK (pool);
-
   switch (obj->mode) {
     case GST_V4L2_IO_MMAP:
     case GST_V4L2_IO_USERPTR:
@@ -776,8 +774,6 @@ gst_v4l2_buffer_pool_streamoff (GstV4l2BufferPool * pool)
       g_atomic_int_add (&pool->num_queued, -1);
     }
   }
-
-  GST_OBJECT_UNLOCK (pool);
 }
 
 static gboolean
@@ -1023,8 +1019,11 @@ gst_v4l2_buffer_pool_stop (GstBufferPool * bpool)
     pool->other_pool = NULL;
   }
 
-  if (!pool->orphaned)
+  if (!pool->orphaned) {
+    GST_OBJECT_LOCK (pool);
     gst_v4l2_buffer_pool_streamoff (pool);
+    GST_OBJECT_UNLOCK (pool);
+  }
 
   ret = GST_BUFFER_POOL_CLASS (parent_class)->stop (bpool);
 
@@ -1057,12 +1056,11 @@ gst_v4l2_buffer_pool_orphan (GstV4l2Object * v4l2object)
   GST_DEBUG_OBJECT (pool, "orphaning pool");
   gst_buffer_pool_set_active (bpool, FALSE);
 
-  gst_v4l2_buffer_pool_streamoff (pool);
-
   /* We lock to prevent racing with a return buffer in QBuf, and has a
    * workaround of not being able to use the pool hidden activation lock. */
   GST_OBJECT_LOCK (pool);
 
+  gst_v4l2_buffer_pool_streamoff (pool);
   ret = gst_v4l2_allocator_orphan (pool->vallocator);
   if (ret)
     pool->orphaned = TRUE;
-- 
2.34.1


From 1a3fb4da2f5d4256e47dbe914babd8b9293aff2c Mon Sep 17 00:00:00 2001
From: Elliot Chen <elliot.chen@nxp.com>
Date: Tue, 19 Jul 2022 15:15:01 +0800
Subject: [PATCH 40/75] LF-6531 v4l2: support stream with V4L2_FIELD_SEQ_TB
 field

Add function to detect upstream amphion, upstream amphion vpu
driver use V4L2_FIELD_SEQ_TB instead of V4L2_FIELD_INTERLACED
and gst_v4l2_object_acquire_format will report unsupported field.
So need to convert V4L2_FIELD_SEQ_TB to V4L2_FIELD_INTERLACED

Signed-off-by: Elliot Chen <elliot.chen@nxp.com>
---
 sys/v4l2/gstv4l2object.c | 13 +++++++++++--
 sys/v4l2/v4l2_calls.c    |  3 ++-
 2 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c
index 98c0ee703..95936933b 100644
--- a/sys/v4l2/gstv4l2object.c
+++ b/sys/v4l2/gstv4l2object.c
@@ -2352,6 +2352,7 @@ gst_v4l2_object_get_interlace_mode (enum v4l2_field field,
     case V4L2_FIELD_INTERLACED:
     case V4L2_FIELD_INTERLACED_TB:
     case V4L2_FIELD_INTERLACED_BT:
+    case V4L2_FIELD_SEQ_TB:
       *interlace_mode = GST_VIDEO_INTERLACE_MODE_INTERLEAVED;
       return TRUE;
     case V4L2_FIELD_ALTERNATE:
@@ -4383,8 +4384,15 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
   if (gst_v4l2_object_get_interlace_mode (format.fmt.pix.field,
           &info.interlace_mode)) {
     if (gst_structure_has_field (s, "interlace-mode")) {
-      if (format.fmt.pix.field != field)
-        goto invalid_field;
+      if ((format.fmt.pix.field == V4L2_FIELD_SEQ_TB)
+          && (field == V4L2_FIELD_INTERLACED)) {
+        GST_DEBUG_OBJECT (v4l2object->dbg_obj,
+            "bypass field check if field from driver: %s and current field: %s",
+            field_to_str (format.fmt.pix.field), field_to_str (field));
+      } else {
+        if (format.fmt.pix.field != field)
+          goto invalid_field;
+      }
     }
   } else {
     /* The driver (or libv4l2) is miss-behaving, just ignore interlace-mode from
@@ -4788,6 +4796,7 @@ gst_v4l2_object_acquire_format (GstV4l2Object * v4l2object, GstVideoInfo * info)
     case V4L2_FIELD_INTERLACED:
     case V4L2_FIELD_INTERLACED_TB:
     case V4L2_FIELD_INTERLACED_BT:
+    case V4L2_FIELD_SEQ_TB:
       interlace_mode = GST_VIDEO_INTERLACE_MODE_INTERLEAVED;
       break;
     case V4L2_FIELD_ALTERNATE:
diff --git a/sys/v4l2/v4l2_calls.c b/sys/v4l2/v4l2_calls.c
index e273f3285..3e9b1b737 100644
--- a/sys/v4l2/v4l2_calls.c
+++ b/sys/v4l2/v4l2_calls.c
@@ -606,7 +606,8 @@ gst_v4l2_open (GstV4l2Object * v4l2object, GstV4l2Error * error)
     v4l2object->dont_use_dmabuf = TRUE;
   }
 
-  if (!strcmp ((char *) v4l2object->vcap.driver, "vpu B0")) {
+  if ((!strcmp ((char *) v4l2object->vcap.driver, "vpu B0")) ||
+      (!strcmp ((char *) v4l2object->vcap.driver, "amphion-vpu"))) {
     v4l2object->is_amphion = TRUE;
   }
 
-- 
2.34.1


From 46a8952e3091d8422fc95ef7c8b4419fff5cc45c Mon Sep 17 00:00:00 2001
From: Elliot Chen <elliot.chen@nxp.com>
Date: Fri, 22 Jul 2022 13:24:58 +0800
Subject: [PATCH 41/75] LF-6577 v4l2: add capture buffer check and resize to
 avoid deadlock issue when seek

in some cases, the total size of buffer is greater than
the pool configured size. Need to resize it to avoid free
buffer when release it.

Signed-off-by: Elliot Chen <elliot.chen@nxp.com>
---
 sys/v4l2/gstv4l2bufferpool.c | 20 +++++++++++++++++++-
 1 file changed, 19 insertions(+), 1 deletion(-)

diff --git a/sys/v4l2/gstv4l2bufferpool.c b/sys/v4l2/gstv4l2bufferpool.c
index 5be845fe4..5c275387e 100644
--- a/sys/v4l2/gstv4l2bufferpool.c
+++ b/sys/v4l2/gstv4l2bufferpool.c
@@ -766,9 +766,27 @@ gst_v4l2_buffer_pool_streamoff (GstV4l2BufferPool * pool)
       if (!(old_buffer_state & BUFFER_STATE_OUTSTANDING)) {
         if (V4L2_TYPE_IS_OUTPUT (pool->obj->type))
           gst_v4l2_buffer_pool_complete_release_buffer (bpool, buffer, FALSE);
+        else {
+          /* in some cases, the total size of buffer is
+          greater than the pool configured size. Need to
+          resize it to avoid free buffer when release it */
+          gsize buf_size;
+          gsize offset;
+
+          buf_size = gst_buffer_get_size(buffer);
+          if (obj->info.size < buf_size) {
+            gst_buffer_get_sizes (buffer, &offset, NULL);
+            gst_buffer_resize (buffer, -offset, obj->info.size);
+
+            GST_DEBUG_OBJECT (pool, "pool size: %" G_GSIZE_FORMAT
+            ", capture buffer size: %" G_GSIZE_FORMAT
+            ", need to resize capture buffer to avoid free it",
+            obj->info.size, buf_size);
+          }
 
-        else                    /* Don't re-enqueue capture buffer on stop */
+          /* Don't re-enqueue capture buffer on stop */
           pclass->release_buffer (bpool, buffer);
+        }
       }
 
       g_atomic_int_add (&pool->num_queued, -1);
-- 
2.34.1


From fae08356a95351010f467276ecac31d4e578ae0c Mon Sep 17 00:00:00 2001
From: Marek Vasut <marex@denx.de>
Date: Sat, 23 Apr 2022 19:02:36 +0200
Subject: [PATCH 42/75] jpegdec: Do not use SIMD for unaligned buffers

In case the output buffer width requires more padding than available,
disable SIMD acceleration and go with slower indirect decoding.
---
 ext/jpeg/gstjpegdec.c | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/ext/jpeg/gstjpegdec.c b/ext/jpeg/gstjpegdec.c
index 51bc2d14b..9a0cfbf9e 100644
--- a/ext/jpeg/gstjpegdec.c
+++ b/ext/jpeg/gstjpegdec.c
@@ -1023,13 +1023,27 @@ gst_jpeg_turbo_parse_ext_fmt_convert (GstJpegDec * dec, gint * clrspc)
 {
   GstCaps *peer_caps, *dec_caps;
 
+  dec->format_convert = FALSE;
+
+  /*
+   * For some widths jpeglib requires more horizontal padding than I420
+   * provides. In those cases libjpeg-turbo SIMD optimization is not an
+   * option.
+   */
+  if (G_UNLIKELY (dec->cinfo.output_width % (dec->cinfo.max_h_samp_factor *
+              DCTSIZE) != 0
+          || dec->cinfo.comp_info[0].h_samp_factor != 2
+          || dec->cinfo.comp_info[1].h_samp_factor != 1
+          || dec->cinfo.comp_info[2].h_samp_factor != 1)) {
+    return;
+  }
+
   dec_caps = gst_static_caps_get (&gst_jpeg_dec_src_pad_template.static_caps);
   peer_caps =
       gst_pad_peer_query_caps (GST_VIDEO_DECODER_SRC_PAD (dec), dec_caps);
   gst_caps_unref (dec_caps);
 
   GST_DEBUG ("Received caps from peer: %" GST_PTR_FORMAT, peer_caps);
-  dec->format_convert = FALSE;
   if (!gst_caps_is_empty (peer_caps)) {
     GstStructure *peerstruct;
     const gchar *peerformat;
-- 
2.34.1


From 57d6d71fdcdcc1e4e41fcabfb161bef9d7c06192 Mon Sep 17 00:00:00 2001
From: Hou Qi <qi.hou@nxp.com>
Date: Tue, 15 Nov 2022 09:01:25 +0800
Subject: [PATCH 43/75] v4l2videoenc: Set encoder output mode to DMABUF_IMPORT
 if receive dmabuf

When output-io-mode is none auto, set output mode to DMABUF_IMPORT to avoid
memory copy if encoder receives dmabuf. Check buffer type for each input
buffer and drop non-dmabuf in DMABUF_IMPORT mode.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-good/-/merge_requests/1095>
---
 sys/v4l2/gstv4l2videoenc.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/sys/v4l2/gstv4l2videoenc.c b/sys/v4l2/gstv4l2videoenc.c
index 4ab0a6ddd..40e0251fb 100644
--- a/sys/v4l2/gstv4l2videoenc.c
+++ b/sys/v4l2/gstv4l2videoenc.c
@@ -771,6 +771,25 @@ gst_v4l2_video_enc_handle_frame (GstVideoEncoder * encoder,
   if (G_UNLIKELY (!g_atomic_int_get (&self->active)))
     goto flushing;
 
+  if (self->v4l2output->req_mode == GST_V4L2_IO_AUTO) {
+    GstV4l2IOMode mode = self->v4l2output->mode;
+
+    if (gst_is_dmabuf_memory (gst_buffer_peek_memory (frame->input_buffer, 0))
+        && (frame->system_frame_number == 0)) {
+      self->v4l2output->mode = GST_V4L2_IO_DMABUF_IMPORT;
+      if (!gst_v4l2_object_try_import (self->v4l2output, frame->input_buffer))
+        self->v4l2output->mode = mode;
+    }
+  }
+  /* It is possible that a system buffer is received when the number of
+   * buffers runs low. */
+  if (self->v4l2output->mode == GST_V4L2_IO_DMABUF_IMPORT
+      && !gst_is_dmabuf_memory (gst_buffer_peek_memory (frame->input_buffer,
+              0))) {
+    frame->output_buffer = NULL;
+    goto drop;
+  }
+
   task_state = gst_pad_get_task_state (GST_VIDEO_ENCODER_SRC_PAD (self));
   if (task_state == GST_TASK_STOPPED || task_state == GST_TASK_PAUSED) {
     /* It is possible that the processing thread stopped due to an error or
-- 
2.34.1


From 6e53d0f1e9d51965ea3970f9a49fe3338fd51a12 Mon Sep 17 00:00:00 2001
From: Hou Qi <qi.hou@nxp.com>
Date: Tue, 15 Nov 2022 09:16:55 +0800
Subject: [PATCH 44/75] v4l2allocator: allow to import single dmabuf with multi
 planes

This is to be compatible with the case where multi planes share
one fd. Also fix MMFMWK-9312.

For pipeline "v4l2h264dec ! video/x-raw,format=I420 ! v4l2h264enc"
run on imx95, decoded I420 buffer is 3 planes sharing one fd.
Need to set plane length to maxsize to avoid below critical log
when resize buffer.

GStreamer-CRITICAL **: 05:28:46.900: gst_memory_resize:
assertion 'size + mem->offset + offset <= mem->maxsize' failed

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-good/-/merge_requests/1096>
---
 sys/v4l2/gstv4l2allocator.c  | 114 +++++++++++++++++++++++++++++------
 sys/v4l2/gstv4l2allocator.h  |   3 +-
 sys/v4l2/gstv4l2bufferpool.c |   5 +-
 sys/v4l2/gstv4l2videoenc.h   |   1 +
 4 files changed, 101 insertions(+), 22 deletions(-)

diff --git a/sys/v4l2/gstv4l2allocator.c b/sys/v4l2/gstv4l2allocator.c
index d2da938a7..ffa5dc85d 100644
--- a/sys/v4l2/gstv4l2allocator.c
+++ b/sys/v4l2/gstv4l2allocator.c
@@ -31,6 +31,7 @@
 #include "gstv4l2allocator.h"
 
 #include <gst/allocators/gstdmabuf.h>
+#include <gst/video/gstvideometa.h>
 
 #include <fcntl.h>
 #include <string.h>
@@ -1096,44 +1097,117 @@ gst_v4l2_allocator_alloc_userptr (GstV4l2Allocator * allocator)
 
 gboolean
 gst_v4l2_allocator_import_dmabuf (GstV4l2Allocator * allocator,
-    GstV4l2MemoryGroup * group, gint n_mem, GstMemory ** dma_mem)
+    GstV4l2MemoryGroup * group, gint n_mem, GstMemory ** dma_mem,
+    GstVideoMeta * vmeta)
 {
   GstV4l2Object *obj = allocator->obj;
   GstV4l2Memory *mem;
-  gint i;
+  gint i = 0;
+  gint dmafd;
+  gsize size, offset, maxsize;
 
   g_return_val_if_fail (allocator->memory == V4L2_MEMORY_DMABUF, FALSE);
 
-  if (group->n_mem != n_mem)
-    goto n_mem_missmatch;
+  if (vmeta) {
+    if (group->n_mem != vmeta->n_planes)
+      goto n_mem_missmatch;
+  } else {
+    if (group->n_mem != n_mem)
+      goto n_mem_missmatch;
+  }
 
-  for (i = 0; i < group->n_mem; i++) {
-    gint dmafd;
-    gsize size, offset, maxsize;
+  if (group->n_mem == n_mem) {
+    for (i = 0; i < group->n_mem; i++) {
+      if (!gst_is_dmabuf_memory (dma_mem[i]))
+        goto not_dmabuf;
 
-    if (!gst_is_dmabuf_memory (dma_mem[i]))
-      goto not_dmabuf;
+      size = gst_memory_get_sizes (dma_mem[i], &offset, &maxsize);
+      dmafd = gst_dmabuf_memory_get_fd (dma_mem[i]);
 
-    size = gst_memory_get_sizes (dma_mem[i], &offset, &maxsize);
+      GST_LOG_OBJECT (allocator, "[%i] imported DMABUF as fd %i plane %d",
+          group->buffer.index, dmafd, i);
 
-    dmafd = gst_dmabuf_memory_get_fd (dma_mem[i]);
+      mem = (GstV4l2Memory *) group->mem[i];
 
-    GST_LOG_OBJECT (allocator, "[%i] imported DMABUF as fd %i plane %d",
-        group->buffer.index, dmafd, i);
+      /* Update memory */
+      mem->mem.maxsize = maxsize;
+      mem->mem.offset = offset;
+      mem->mem.size = size;
+      mem->dmafd = dmafd;
 
-    mem = (GstV4l2Memory *) group->mem[i];
+      /* Update v4l2 structure */
+      group->planes[i].length = maxsize;
+      group->planes[i].bytesused = size + offset;
+      group->planes[i].m.fd = dmafd;
+      group->planes[i].data_offset = offset;
+    }
+  } else if (n_mem == 1) {      // in case all planes are in one memory block
+    if (!gst_is_dmabuf_memory (dma_mem[0]))
+      goto not_dmabuf;
+
+    size = gst_memory_get_sizes (dma_mem[0], &offset, &maxsize);
+    dmafd = gst_dmabuf_memory_get_fd (dma_mem[0]);
+
+    GST_LOG_OBJECT (allocator, "%d planes are in 1 memory block",
+        vmeta->n_planes);
+
+    mem = (GstV4l2Memory *) group->mem[0];
 
     /* Update memory */
     mem->mem.maxsize = maxsize;
-    mem->mem.offset = offset;
-    mem->mem.size = size;
+    mem->mem.offset = vmeta->offset[0];
+    mem->mem.size = vmeta->offset[1];
     mem->dmafd = dmafd;
 
     /* Update v4l2 structure */
-    group->planes[i].length = maxsize;
-    group->planes[i].bytesused = size + offset;
-    group->planes[i].m.fd = dmafd;
-    group->planes[i].data_offset = offset;
+    group->planes[0].length = mem->mem.maxsize;
+    group->planes[0].bytesused = mem->mem.size;
+    group->planes[0].m.fd = dmafd;
+    group->planes[0].data_offset = mem->mem.offset;
+
+    if (group->n_mem == 2) {
+      mem = (GstV4l2Memory *) group->mem[1];
+
+      /* Update memory */
+      mem->mem.maxsize = maxsize;
+      mem->mem.offset = vmeta->offset[1];
+      mem->mem.size = size;
+      mem->dmafd = dmafd;
+
+      /* Update v4l2 structure */
+      group->planes[1].length = mem->mem.maxsize;
+      group->planes[1].bytesused = mem->mem.size;
+      group->planes[1].m.fd = dmafd;
+      group->planes[1].data_offset = mem->mem.offset;
+    } else if (group->n_mem == 3) {
+      mem = (GstV4l2Memory *) group->mem[1];
+
+      /* Update memory */
+      mem->mem.maxsize = maxsize;
+      mem->mem.offset = vmeta->offset[1];
+      mem->mem.size = vmeta->offset[2];
+      mem->dmafd = dmafd;
+
+      /* Update v4l2 structure */
+      group->planes[1].length = mem->mem.maxsize;
+      group->planes[1].bytesused = mem->mem.size;
+      group->planes[1].m.fd = dmafd;
+      group->planes[1].data_offset = mem->mem.offset;
+
+      mem = (GstV4l2Memory *) group->mem[2];
+
+      /* Update memory */
+      mem->mem.maxsize = maxsize;
+      mem->mem.offset = vmeta->offset[2];
+      mem->mem.size = size;
+      mem->dmafd = dmafd;
+
+      /* Update v4l2 structure */
+      group->planes[2].length = mem->mem.maxsize;
+      group->planes[2].bytesused = mem->mem.size;
+      group->planes[2].m.fd = dmafd;
+      group->planes[2].data_offset = mem->mem.offset;
+    }
   }
 
   /* Copy into buffer structure if not using planes */
diff --git a/sys/v4l2/gstv4l2allocator.h b/sys/v4l2/gstv4l2allocator.h
index eb515245a..7977d66ed 100644
--- a/sys/v4l2/gstv4l2allocator.h
+++ b/sys/v4l2/gstv4l2allocator.h
@@ -141,7 +141,8 @@ GstV4l2MemoryGroup * gst_v4l2_allocator_alloc_userptr  (GstV4l2Allocator * alloc
 
 gboolean             gst_v4l2_allocator_import_dmabuf  (GstV4l2Allocator * allocator,
                                                         GstV4l2MemoryGroup *group,
-                                                        gint n_mem, GstMemory ** dma_mem);
+                                                        gint n_mem, GstMemory ** dma_mem,
+                                                        GstVideoMeta *vmeta);
 
 gboolean             gst_v4l2_allocator_import_userptr (GstV4l2Allocator * allocator,
                                                         GstV4l2MemoryGroup *group,
diff --git a/sys/v4l2/gstv4l2bufferpool.c b/sys/v4l2/gstv4l2bufferpool.c
index 5c275387e..05e0a7dcf 100644
--- a/sys/v4l2/gstv4l2bufferpool.c
+++ b/sys/v4l2/gstv4l2bufferpool.c
@@ -354,6 +354,7 @@ gst_v4l2_buffer_pool_import_dmabuf (GstV4l2BufferPool * pool,
   GstV4l2MemoryGroup *group = NULL;
   GstMemory *dma_mem[GST_VIDEO_MAX_PLANES] = { 0 };
   guint n_mem = gst_buffer_n_memory (src);
+  GstVideoMeta *vmeta;
   gint i;
 
   GST_LOG_OBJECT (pool, "importing dmabuf");
@@ -361,6 +362,8 @@ gst_v4l2_buffer_pool_import_dmabuf (GstV4l2BufferPool * pool,
   if (!gst_v4l2_is_buffer_valid (dest, &group, TRUE))
     goto not_our_buffer;
 
+  vmeta = gst_buffer_get_video_meta (src);
+
   if (n_mem > GST_VIDEO_MAX_PLANES)
     goto too_many_mems;
 
@@ -368,7 +371,7 @@ gst_v4l2_buffer_pool_import_dmabuf (GstV4l2BufferPool * pool,
     dma_mem[i] = gst_buffer_peek_memory (src, i);
 
   if (!gst_v4l2_allocator_import_dmabuf (pool->vallocator, group, n_mem,
-          dma_mem))
+          dma_mem, vmeta))
     goto import_failed;
 
   gst_mini_object_set_qdata (GST_MINI_OBJECT (dest), GST_V4L2_IMPORT_QUARK,
diff --git a/sys/v4l2/gstv4l2videoenc.h b/sys/v4l2/gstv4l2videoenc.h
index 3659cb51d..529c9accc 100644
--- a/sys/v4l2/gstv4l2videoenc.h
+++ b/sys/v4l2/gstv4l2videoenc.h
@@ -26,6 +26,7 @@
 #include <gst/video/video.h>
 #include <gst/video/gstvideoencoder.h>
 #include <gst/video/gstvideometa.h>
+#include <gst/allocators/gstdmabuf.h>
 
 #include <gstv4l2object.h>
 #include <gstv4l2bufferpool.h>
-- 
2.34.1


From cb91cfcb0b6a6dcfae8c7fb45432b65e281deaf4 Mon Sep 17 00:00:00 2001
From: Ming Qian <ming.qian@nxp.com>
Date: Wed, 8 Jun 2022 10:09:19 +0800
Subject: [PATCH 45/75] MMFMWK-9186-5 v4l2: Add support for
 P012,Y212,Y312,BGR_12LE,BGRA_12LE,Y012_LE

These foramtd are used by imx-jpeg
---
 sys/v4l2/ext/videodev2.h |  3 ++
 sys/v4l2/gstv4l2object.c | 60 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 63 insertions(+)

diff --git a/sys/v4l2/ext/videodev2.h b/sys/v4l2/ext/videodev2.h
index da0000a81..f55d4caea 100644
--- a/sys/v4l2/ext/videodev2.h
+++ b/sys/v4l2/ext/videodev2.h
@@ -558,6 +558,8 @@ struct v4l2_pix_format {
 /* RGB formats (6 or 8 bytes per pixel) */
 #define V4L2_PIX_FMT_BGR48_12    v4l2_fourcc('B', '3', '1', '2') /* 48  BGR 12-bit per component */
 #define V4L2_PIX_FMT_ABGR64_12   v4l2_fourcc('B', '4', '1', '2') /* 64  BGRA 12-bit per component */
+#define V4L2_PIX_FMT_B312    v4l2_fourcc('B', '3', '1', '2') /* 48  BGR 12-bit per component */
+#define V4L2_PIX_FMT_B412    v4l2_fourcc('B', '4', '1', '2') /* 64  BGRA 12-bit per component */
 
 /* Grey formats */
 #define V4L2_PIX_FMT_GREY    v4l2_fourcc('G', 'R', 'E', 'Y') /*  8  Greyscale     */
@@ -609,6 +611,7 @@ struct v4l2_pix_format {
 #define V4L2_PIX_FMT_Y210    v4l2_fourcc('Y', '2', '1', '0') /* 32  YUYV 4:2:2 */
 #define V4L2_PIX_FMT_Y212    v4l2_fourcc('Y', '2', '1', '2') /* 32  YUYV 4:2:2 */
 #define V4L2_PIX_FMT_Y216    v4l2_fourcc('Y', '2', '1', '6') /* 32  YUYV 4:2:2 */
+#define V4L2_PIX_FMT_Y312    v4l2_fourcc('Y', '3', '1', '2') /* 48  YUV 4:4:4 12-bit per component */
 
 /* two planes -- one Y, one Cr + Cb interleaved  */
 #define V4L2_PIX_FMT_NV12    v4l2_fourcc('N', 'V', '1', '2') /* 12  Y/CbCr 4:2:0  */
diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c
index 95936933b..7ae13ad83 100644
--- a/sys/v4l2/gstv4l2object.c
+++ b/sys/v4l2/gstv4l2object.c
@@ -106,6 +106,8 @@ static const GstV4L2FormatDesc gst_v4l2_formats[] = {
   {V4L2_PIX_FMT_RGBX32, TRUE, GST_V4L2_RAW},
   {V4L2_PIX_FMT_ARGB32, TRUE, GST_V4L2_RAW},
   {V4L2_PIX_FMT_XRGB32, TRUE, GST_V4L2_RAW},
+  {V4L2_PIX_FMT_B312, TRUE, GST_V4L2_RAW},
+  {V4L2_PIX_FMT_B412, TRUE, GST_V4L2_RAW},
 
   /* Deprecated Packed RGB Image Formats (alpha ambiguity) */
   {V4L2_PIX_FMT_RGB444, TRUE, GST_V4L2_RAW},
@@ -120,6 +122,7 @@ static const GstV4L2FormatDesc gst_v4l2_formats[] = {
   {V4L2_PIX_FMT_Y6, TRUE, GST_V4L2_RAW},
   {V4L2_PIX_FMT_Y10, TRUE, GST_V4L2_RAW},
   {V4L2_PIX_FMT_Y12, TRUE, GST_V4L2_RAW},
+  {V4L2_PIX_FMT_Y012, TRUE, GST_V4L2_RAW},
   {V4L2_PIX_FMT_Y16, TRUE, GST_V4L2_RAW},
   {V4L2_PIX_FMT_Y16_BE, TRUE, GST_V4L2_RAW},
   {V4L2_PIX_FMT_Y10BPACK, TRUE, GST_V4L2_RAW},
@@ -154,6 +157,8 @@ static const GstV4L2FormatDesc gst_v4l2_formats[] = {
   {V4L2_PIX_FMT_HI240, TRUE, GST_V4L2_RAW},
   {V4L2_PIX_FMT_HM12, TRUE, GST_V4L2_RAW},
   {V4L2_PIX_FMT_M420, TRUE, GST_V4L2_RAW},
+  {V4L2_PIX_FMT_Y212, TRUE, GST_V4L2_RAW},
+  {V4L2_PIX_FMT_Y312, TRUE, GST_V4L2_RAW},
 
   /* two planes -- one Y, one Cr + Cb interleaved  */
   {V4L2_PIX_FMT_NV12, TRUE, GST_V4L2_RAW},
@@ -175,6 +180,8 @@ static const GstV4L2FormatDesc gst_v4l2_formats[] = {
   {V4L2_PIX_FMT_NV24, TRUE, GST_V4L2_RAW},
   {V4L2_PIX_FMT_NV42, TRUE, GST_V4L2_RAW},
   {V4L2_PIX_FMT_MM21, TRUE, GST_V4L2_RAW},
+  {V4L2_PIX_FMT_P012, TRUE, GST_V4L2_RAW},
+  {V4L2_PIX_FMT_P012M, TRUE, GST_V4L2_RAW},
 
   /* Bayer formats - see http://www.siliconimaging.com/RGB%20Bayer.htm */
   {V4L2_PIX_FMT_SBGGR8, TRUE, GST_V4L2_RAW},
@@ -1117,6 +1124,8 @@ gst_v4l2_object_format_get_rank (const struct v4l2_fmtdesc *fmt)
     case V4L2_PIX_FMT_RGBX32:
     case V4L2_PIX_FMT_ARGB32:
     case V4L2_PIX_FMT_XRGB32:
+    case V4L2_PIX_FMT_B312:
+    case V4L2_PIX_FMT_B412:
       rank = RGB_BASE_RANK;
       break;
 
@@ -1140,6 +1149,10 @@ gst_v4l2_object_format_get_rank (const struct v4l2_fmtdesc *fmt)
     case V4L2_PIX_FMT_NV12M_8L128:
     case V4L2_PIX_FMT_NV12M_10BE_8L128:
     case V4L2_PIX_FMT_YUV24:   /* 24  YUY 4:4:4     */
+    case V4L2_PIX_FMT_P012:
+    case V4L2_PIX_FMT_P012M:
+    case V4L2_PIX_FMT_Y212:
+    case V4L2_PIX_FMT_Y312:
       rank = YUV_ODD_BASE_RANK;
       break;
 
@@ -1380,6 +1393,9 @@ gst_v4l2_object_v4l2fourcc_to_video_format (guint32 fourcc)
     case V4L2_PIX_FMT_GREY:    /*  8  Greyscale     */
       format = GST_VIDEO_FORMAT_GRAY8;
       break;
+    case V4L2_PIX_FMT_Y012:
+      format = GST_VIDEO_FORMAT_Y012_LE;
+      break;
     case V4L2_PIX_FMT_Y16:
       format = GST_VIDEO_FORMAT_GRAY16_LE;
       break;
@@ -1458,6 +1474,10 @@ gst_v4l2_object_v4l2fourcc_to_video_format (guint32 fourcc)
     case V4L2_PIX_FMT_NV21M:
       format = GST_VIDEO_FORMAT_NV21;
       break;
+    case V4L2_PIX_FMT_P012:
+    case V4L2_PIX_FMT_P012M:
+      format = GST_VIDEO_FORMAT_P012_LE;
+      break;
     case V4L2_PIX_FMT_YVU410:
       format = GST_VIDEO_FORMAT_YVU9;
       break;
@@ -1502,6 +1522,18 @@ gst_v4l2_object_v4l2fourcc_to_video_format (guint32 fourcc)
     case V4L2_PIX_FMT_NV24:
       format = GST_VIDEO_FORMAT_NV24;
       break;
+    case V4L2_PIX_FMT_Y212:
+      format = GST_VIDEO_FORMAT_Y212_LE;
+      break;
+    case V4L2_PIX_FMT_Y312:
+      format = GST_VIDEO_FORMAT_Y312_LE;
+      break;
+    case V4L2_PIX_FMT_B312:
+      format = GST_VIDEO_FORMAT_BGR_12LE;
+      break;
+    case V4L2_PIX_FMT_B412:
+      format = GST_VIDEO_FORMAT_BGRA_12LE;
+      break;
     default:
       format = GST_VIDEO_FORMAT_UNKNOWN;
       break;
@@ -1538,6 +1570,8 @@ gst_v4l2_object_v4l2fourcc_is_rgb (guint32 fourcc)
     case V4L2_PIX_FMT_SGBRG8:
     case V4L2_PIX_FMT_SGRBG8:
     case V4L2_PIX_FMT_SRGGB8:
+    case V4L2_PIX_FMT_B312:
+    case V4L2_PIX_FMT_B412:
     case V4L2_PIX_FMT_SBGGR10:
     case V4L2_PIX_FMT_SGBRG10:
     case V4L2_PIX_FMT_SGRBG10:
@@ -1664,6 +1698,7 @@ gst_v4l2_object_v4l2fourcc_to_bare_struct (guint32 fourcc)
       structure = gst_structure_new_empty ("video/x-vp9");
       break;
     case V4L2_PIX_FMT_GREY:    /*  8  Greyscale     */
+    case V4L2_PIX_FMT_Y012:
     case V4L2_PIX_FMT_Y16:
     case V4L2_PIX_FMT_Y16_BE:
     case V4L2_PIX_FMT_XRGB555:
@@ -1684,6 +1719,8 @@ gst_v4l2_object_v4l2fourcc_to_bare_struct (guint32 fourcc)
     case V4L2_PIX_FMT_BGRA32:
     case V4L2_PIX_FMT_XBGR32:
     case V4L2_PIX_FMT_ABGR32:
+    case V4L2_PIX_FMT_B312:
+    case V4L2_PIX_FMT_B412:
     case V4L2_PIX_FMT_NV12:    /* 12  Y/CbCr 4:2:0  */
     case V4L2_PIX_FMT_NV12_10BIT:      /* 12  Y/CbCr 4:2:0  */
     case V4L2_PIX_FMT_NV12X:
@@ -1701,6 +1738,10 @@ gst_v4l2_object_v4l2fourcc_to_bare_struct (guint32 fourcc)
     case V4L2_PIX_FMT_NV61:    /* 16  Y/CrCb 4:2:2  */
     case V4L2_PIX_FMT_NV61M:
     case V4L2_PIX_FMT_NV24:    /* 24  Y/CrCb 4:4:4  */
+    case V4L2_PIX_FMT_P012:
+    case V4L2_PIX_FMT_P012M:
+    case V4L2_PIX_FMT_Y212:
+    case V4L2_PIX_FMT_Y312:
     case V4L2_PIX_FMT_YVU410:
     case V4L2_PIX_FMT_YUV410:
     case V4L2_PIX_FMT_YUV420:  /* I420/IYUV */
@@ -2082,9 +2123,19 @@ gst_v4l2_object_get_caps_info (GstV4l2Object * v4l2object, GstCaps * caps,
       case GST_VIDEO_FORMAT_NV24:
         fourcc = V4L2_PIX_FMT_NV24;
         break;
+      case GST_VIDEO_FORMAT_P012_LE:
+        fourcc = V4L2_PIX_FMT_P012;
+        fourcc_nc = V4L2_PIX_FMT_P012M;
+        break;
       case GST_VIDEO_FORMAT_YVYU:
         fourcc = V4L2_PIX_FMT_YVYU;
         break;
+      case GST_VIDEO_FORMAT_Y212_LE:
+        fourcc = V4L2_PIX_FMT_Y212;
+        break;
+      case GST_VIDEO_FORMAT_Y312_LE:
+        fourcc = V4L2_PIX_FMT_Y312;
+        break;
       case GST_VIDEO_FORMAT_RGB15:
         fourcc = V4L2_PIX_FMT_RGB555;
         fourcc_nc = V4L2_PIX_FMT_XRGB555;
@@ -2132,6 +2183,15 @@ gst_v4l2_object_get_caps_info (GstV4l2Object * v4l2object, GstCaps * caps,
       case GST_VIDEO_FORMAT_GRAY8:
         fourcc = V4L2_PIX_FMT_GREY;
         break;
+      case GST_VIDEO_FORMAT_BGR_12LE:
+        fourcc = V4L2_PIX_FMT_B312;
+        break;
+      case GST_VIDEO_FORMAT_BGRA_12LE:
+        fourcc = V4L2_PIX_FMT_B412;
+        break;
+      case GST_VIDEO_FORMAT_Y012_LE:
+        fourcc = V4L2_PIX_FMT_Y012;
+        break;
       case GST_VIDEO_FORMAT_GRAY16_LE:
         fourcc = V4L2_PIX_FMT_Y16;
         break;
-- 
2.34.1


From 836ac3734569cae2bdc6eb48ae70ba2cdffa7b8d Mon Sep 17 00:00:00 2001
From: Elliot Chen <elliot.chen@nxp.com>
Date: Tue, 21 Feb 2023 11:12:37 +0800
Subject: [PATCH 46/75] MMFMWK-9195 adaptivedemux2: fix the issue with setting
 range start during download

For adaptivedemux2,the range start value is fixed to 0 if it within the first KB of the file.
Need fix it to avoid downloading the header and index data repeatedly.

Signed-off-by: Elliot Chen <elliot.chen@nxp.com>
---
 ext/adaptivedemux2/downloadhelper.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/ext/adaptivedemux2/downloadhelper.c b/ext/adaptivedemux2/downloadhelper.c
index ebf9dc078..6019b8f55 100644
--- a/ext/adaptivedemux2/downloadhelper.c
+++ b/ext/adaptivedemux2/downloadhelper.c
@@ -877,12 +877,14 @@ downloadhelper_submit_request (DownloadHelper * dh,
     return FALSE;
   }
 
+#if 0
   /* NOTE: There was a bug where Akamai servers return the
    * wrong result for a range request on small files. To avoid
    * it if the range starts within the first KB of the file, just
    * start at 0 instead */
   if (request->range_start < 1024)
     request->range_start = 0;
+#endif
 
   msg_headers = _soup_message_get_request_headers (msg);
 
-- 
2.34.1


From 6d97688f5c755e55ee3be2b98fa06308cd243944 Mon Sep 17 00:00:00 2001
From: Elliot Chen <elliot.chen@nxp.com>
Date: Tue, 21 Feb 2023 13:41:05 +0800
Subject: [PATCH 47/75] MMFMWK-9194 dashdemux2: support adaptive playback for
 webm stream

add matroska parser for webm stream

Signed-off-by: Elliot Chen <elliot.chen@nxp.com>
---
 ext/adaptivedemux2/dash/gstdashdemux.c | 270 ++++++++++++++
 ext/adaptivedemux2/dash/gstdashdemux.h |   3 +
 ext/adaptivedemux2/dash/gstmpdhelper.c |   4 +
 ext/adaptivedemux2/gstmatroska.c       | 463 +++++++++++++++++++++++++
 ext/adaptivedemux2/gstmatroska.h       | 104 ++++++
 ext/adaptivedemux2/meson.build         |   1 +
 6 files changed, 845 insertions(+)
 create mode 100755 ext/adaptivedemux2/gstmatroska.c
 create mode 100755 ext/adaptivedemux2/gstmatroska.h

diff --git a/ext/adaptivedemux2/dash/gstdashdemux.c b/ext/adaptivedemux2/dash/gstdashdemux.c
index 063c5a276..ea8640c0d 100644
--- a/ext/adaptivedemux2/dash/gstdashdemux.c
+++ b/ext/adaptivedemux2/dash/gstdashdemux.c
@@ -373,6 +373,9 @@ static GstClockTime
 gst_dash_demux_stream_get_fragment_waiting_time (GstAdaptiveDemux2Stream *
     stream);
 static GstFlowReturn
+gst_dash_demux_handle_matroska (GstAdaptiveDemux2Stream * stream,
+    GstAdapter * adapter);
+static GstFlowReturn
 gst_dash_demux_stream_data_received (GstAdaptiveDemux2Stream * stream,
     GstBuffer * buffer);
 static gboolean gst_dash_demux_stream_fragment_start (GstAdaptiveDemux2Stream *
@@ -444,6 +447,7 @@ gst_dash_demux_stream_init (GstDashDemux2Stream * stream)
   stream->average_download_time = 250 * GST_MSECOND;
 
   gst_isoff_sidx_parser_init (&stream->sidx_parser);
+  gst_matroska_parser_init (&stream->matroska_parser);
 }
 
 static void
@@ -1702,6 +1706,7 @@ gst_dash_demux_stream_seek (GstAdaptiveDemux2Stream * stream, gboolean forward,
         last_repeat != dashstream->active_stream->segment_repeat_index) {
       GST_LOG_OBJECT (stream, "Segment index was changed, reset sidx parser");
       gst_isoff_sidx_parser_clear (&dashstream->sidx_parser);
+      gst_matroska_parser_clear (&dashstream->matroska_parser);
       dashstream->sidx_base_offset = 0;
       dashstream->allow_sidx = TRUE;
     }
@@ -1712,6 +1717,7 @@ gst_dash_demux_stream_seek (GstAdaptiveDemux2Stream * stream, gboolean forward,
         GST_ERROR_OBJECT (stream, "Couldn't find position in sidx");
         dashstream->sidx_position = GST_CLOCK_TIME_NONE;
         gst_isoff_sidx_parser_clear (&dashstream->sidx_parser);
+        gst_matroska_parser_clear (&dashstream->matroska_parser);
       }
       if (final_rt)
         *final_rt = final_ts;
@@ -2476,6 +2482,7 @@ gst_dash_demux_stream_select_bitrate (GstAdaptiveDemux2Stream * stream,
     }
 
     gst_isoff_sidx_parser_clear (&dashstream->sidx_parser);
+    gst_matroska_parser_clear (&dashstream->matroska_parser);
     dashstream->sidx_base_offset = 0;
     dashstream->allow_sidx = TRUE;
 
@@ -3675,6 +3682,263 @@ gst_dash_demux_stream_handle_isobmff (GstAdaptiveDemux2Stream * stream)
   return ret;
 }
 
+static GstFlowReturn
+gst_dash_demux_update_sidx_parser_by_matroska_parser (GstAdaptiveDemux * demux,
+    GstAdaptiveDemux2Stream * stream)
+{
+  guint64 index = 0;
+  GstDashDemux2Stream *dash_stream = (GstDashDemux2Stream *) stream;
+  GstMatroskaParser *matroska_parser = &(dash_stream->matroska_parser);
+  GstSidxParser *sidx_parser = &dash_stream->sidx_parser;
+  GstFlowReturn res = GST_FLOW_OK;
+  GstSidxBox *sidx = NULL;
+
+  /* Check matroska cues information list */
+  if (!matroska_parser->array) {
+    GST_DEBUG_OBJECT (stream, "the cues information array list is null ");
+    return res;
+  }
+
+  /* update sidx parser */
+  sidx_parser->sidx.first_offset = matroska_parser->segment_head_offset;
+  /* sidx base offset used in check subfragment boundary */
+  dash_stream->sidx_base_offset = matroska_parser->segment_head_offset;
+  sidx_parser->sidx.entry_index = 0;
+  sidx_parser->sidx.entries_count = matroska_parser->cue_point_num;
+  sidx_parser->sidx.entries =
+      g_malloc (sizeof (GstSidxBoxEntry) * sidx_parser->sidx.entries_count);
+  GST_DEBUG_OBJECT (stream,
+      "matroska parser: segment_head_offset = %" G_GUINT64_FORMAT,
+      matroska_parser->segment_head_offset);
+
+  /* Update sidx box information */
+  while (index < sidx_parser->sidx.entries_count) {
+    GstSidxBoxEntry *sidx_entry = &sidx_parser->sidx.entries[index];
+    GstMatroskaPointData *cue_entry = &g_array_index (matroska_parser->array,
+        GstMatroskaPointData, index);
+    sidx_entry->size = 0;
+    sidx_entry->offset = cue_entry->track_pos.cluster_pos;
+    sidx_entry->pts = cue_entry->cue_time * matroska_parser->time_scale;
+    sidx_entry->duration = -1;
+
+    if (index >= 1) {
+      GstSidxBoxEntry *prev_sidx_entry = &sidx_parser->sidx.entries[index - 1];
+      prev_sidx_entry->duration = (sidx_entry->pts - prev_sidx_entry->pts);
+      prev_sidx_entry->size = (sidx_entry->offset - prev_sidx_entry->offset);
+      GST_DEBUG_OBJECT (stream,
+          "sidx_entry[%" G_GUINT64_FORMAT "]: duration = %" G_GUINT64_FORMAT
+          ", size = %" G_GUINT32_FORMAT, index - 1, prev_sidx_entry->duration,
+          prev_sidx_entry->size);
+    }
+
+    GST_DEBUG_OBJECT (stream,
+        "sidx_entry[%" G_GUINT64_FORMAT "]: offset = %" G_GUINT64_FORMAT
+        ", pts = %" G_GUINT64_FORMAT, index, sidx_entry->offset,
+        sidx_entry->pts);
+    index++;
+  }
+
+  GST_DEBUG_OBJECT (stream, "free array, addr = %p", matroska_parser->array);
+  g_array_free (matroska_parser->array, TRUE);
+  matroska_parser->array = NULL;
+
+  /* We might've cleared the index above */
+  sidx = SIDX (dash_stream);
+  if (sidx->entries_count > 0) {
+    if (GST_CLOCK_TIME_IS_VALID (dash_stream->pending_seek_ts)) {
+      /* FIXME, preserve seek flags */
+      if (gst_dash_demux_stream_sidx_seek (dash_stream,
+              demux->segment.rate >= 0, 0, dash_stream->pending_seek_ts,
+              NULL) != GST_FLOW_OK) {
+        GST_ERROR_OBJECT (stream,
+            "pending_seek_ts is valid, stream seek error");
+        /* select fragment position */
+        dash_stream->sidx_position = GST_CLOCK_TIME_NONE;
+        gst_isoff_sidx_parser_clear (&dash_stream->sidx_parser);
+      } else {
+        GST_DEBUG_OBJECT (stream, "pending_seek_ts is valid, stream seek ok");
+      }
+      dash_stream->pending_seek_ts = GST_CLOCK_TIME_NONE;
+    } else {
+      /* sidx seek */
+      if (dash_stream->sidx_position == GST_CLOCK_TIME_NONE) {
+        SIDX (dash_stream)->entry_index = 0;
+      } else {
+        /* update sidx entry_index */
+        if (gst_dash_demux_stream_sidx_seek (dash_stream,
+                demux->segment.rate >= 0, GST_SEEK_FLAG_SNAP_BEFORE,
+                dash_stream->sidx_position, NULL) != GST_FLOW_OK) {
+          GST_ERROR_OBJECT (stream, "Couldn't find position in sidx");
+          dash_stream->sidx_position = GST_CLOCK_TIME_NONE;
+          gst_isoff_sidx_parser_clear (&dash_stream->sidx_parser);
+        } else {
+          GST_DEBUG_OBJECT (stream,
+              "stream sidx seek ok, sidx index = %d, sidx_position = %"
+              G_GUINT64_FORMAT, sidx_parser->sidx.entry_index,
+              dash_stream->sidx_position);
+        }
+      }
+      dash_stream->sidx_position =
+          SIDX (dash_stream)->entries[SIDX (dash_stream)->entry_index].pts;
+    }
+  }
+
+  sidx_parser->status = GST_ISOFF_SIDX_PARSER_FINISHED;
+  return res;
+}
+
+static GstFlowReturn
+gst_dash_demux_handle_matroska (GstAdaptiveDemux2Stream * stream,
+    GstAdapter * adapter)
+{
+  GstAdaptiveDemux *demux = stream->demux;
+  GstBuffer *buffer = NULL;
+  GstDashDemux2Stream *dash_stream = (GstDashDemux2Stream *) stream;
+  GstMatroskaParser *matroska_parser = &(dash_stream->matroska_parser);
+  GstFlowReturn ret = GST_FLOW_OK;
+  GstMatroskaParserResult res = GST_MATROSKA_PARSER_OK;
+
+  guint index_header_or_data = 0;
+  if (stream->downloading_index)
+    index_header_or_data = 1;
+  else if (stream->downloading_header)
+    index_header_or_data = 2;
+  else
+    index_header_or_data = 3;
+
+  GST_DEBUG_OBJECT (stream, "index_header_or_data = %d, rep idx = %d,"
+      "sid index = %d, sidx_base_offset = %" G_GINT64_FORMAT
+      ", stream current_offset = %" G_GUINT64_FORMAT ", adapter length = %"
+      G_GSIZE_FORMAT, index_header_or_data,
+      dash_stream->active_stream->representation_idx,
+      dash_stream->sidx_parser.sidx.entry_index, dash_stream->sidx_base_offset,
+      dash_stream->current_offset, gst_adapter_available (adapter));
+
+  /* entry matroska parser */
+  res = gst_matroska_parser_entry (matroska_parser, adapter);
+  if (res == GST_MATROSKA_PARSER_NOT_SUPPORTED) {
+    /* Not matroska format */
+    return GST_FLOW_NOT_SUPPORTED;
+  } else {
+    if (res == GST_MATROSKA_PARSER_DONE) {
+      gst_dash_demux_update_sidx_parser_by_matroska_parser (demux, stream);
+      GST_DEBUG_OBJECT (stream,
+          "update sidx parser, consume = %" G_GUINT64_FORMAT,
+          matroska_parser->consume);
+    }
+  }
+
+  if ((dash_stream->sidx_parser.status == GST_ISOFF_SIDX_PARSER_FINISHED) &&
+      (index_header_or_data == 3)) {
+    gsize available;
+    GST_DEBUG_OBJECT (stream, "cluster data");
+
+    /* Not ISOBMFF but had a SIDX index. Does this even exist or work? */
+    while (ret == GST_FLOW_OK
+        && ((available = gst_adapter_available (dash_stream->adapter)) > 0)) {
+
+      gboolean advance = FALSE;
+      guint64 sidx_end_offset =
+          dash_stream->sidx_base_offset +
+          SIDX_CURRENT_ENTRY (dash_stream)->offset +
+          SIDX_CURRENT_ENTRY (dash_stream)->size;
+      gboolean has_next = gst_dash_demux_stream_has_next_subfragment (stream);
+
+      if (dash_stream->current_offset + available < sidx_end_offset) {
+        buffer = gst_adapter_take_buffer (dash_stream->adapter, available);
+      } else {
+        if (!has_next && sidx_end_offset <= dash_stream->current_offset) {
+          /* Drain all bytes, since there might be trailing bytes at the end of subfragment */
+          buffer = gst_adapter_take_buffer (dash_stream->adapter, available);
+          GST_DEBUG_OBJECT (stream, "drain data");
+        } else {
+          if (sidx_end_offset <= dash_stream->current_offset) {
+            /* This means a corrupted stream or a bug: ignoring bugs, it
+             * should only happen if the SIDX index is corrupt */
+            GST_ERROR_OBJECT (stream, "Invalid SIDX state");
+            gst_adapter_clear (dash_stream->adapter);
+            ret = GST_FLOW_ERROR;
+            break;
+          } else {
+            buffer =
+                gst_adapter_take_buffer (dash_stream->adapter,
+                sidx_end_offset - dash_stream->current_offset);
+            advance = TRUE;
+          }
+        }
+      }
+
+      GST_BUFFER_OFFSET (buffer) = dash_stream->current_offset;
+      GST_BUFFER_OFFSET_END (buffer) =
+          GST_BUFFER_OFFSET (buffer) + gst_buffer_get_size (buffer);
+      dash_stream->current_offset = GST_BUFFER_OFFSET_END (buffer);
+
+      GST_DEBUG_OBJECT (stream,
+          "rep idx = %d, sidx idx = %d, sidx_end_offset = %" G_GUINT64_FORMAT
+          ", " "current_offset = %" G_GUINT64_FORMAT ", buffer offset end = %"
+          G_GUINT64_FORMAT, dash_stream->active_stream->representation_idx,
+          dash_stream->sidx_parser.sidx.entry_index, sidx_end_offset,
+          GST_BUFFER_OFFSET (buffer), GST_BUFFER_OFFSET_END (buffer));
+
+      ret = gst_adaptive_demux2_stream_push_buffer (stream, buffer);
+      if (advance) {
+        if (has_next) {
+          GstFlowReturn new_ret;
+          GST_DEBUG_OBJECT (stream, "has next subfragment, advance");
+          new_ret =
+              gst_adaptive_demux2_stream_advance_fragment (stream,
+              SIDX_CURRENT_ENTRY (dash_stream)->duration);
+
+          /* only overwrite if it was OK before */
+          if (ret == GST_FLOW_OK) {
+            ret = new_ret;
+
+            /* check whether need to change representation index */
+            if (ret != GST_FLOW_OK) {
+              GST_DEBUG_OBJECT (stream, "stop send data");
+              return ret;
+            }
+          }
+        }
+      } else {
+        /* reach the last sub fragment boundary */
+        break;
+      }
+    }
+  } else {
+    guint64 avail_len = gst_adapter_available (dash_stream->adapter);
+
+    GST_DEBUG_OBJECT (stream, "main header = %d: matroska parser offset = %"
+        G_GUINT64_FORMAT ", avail_len = %" G_GUINT64_FORMAT,
+        index_header_or_data, matroska_parser->offset, avail_len);
+
+    /* If have parsed data, can only send parsed data */
+    if (matroska_parser->offset) {
+      if (matroska_parser->offset > avail_len) {
+        GST_ERROR_OBJECT (stream, "need to return, matroska parser offset: %"
+            G_GUINT64_FORMAT "> avail_len: %" G_GUINT64_FORMAT,
+            matroska_parser->offset, avail_len);
+        return ret;
+      } else {
+        avail_len = matroska_parser->offset;
+        /* Clear parser offset */
+        matroska_parser->offset = 0;
+      }
+    }
+
+    /* this should be the main header, just push it all */
+    buffer = gst_adapter_take_buffer (dash_stream->adapter, avail_len);
+
+    GST_BUFFER_OFFSET (buffer) = dash_stream->current_offset;
+    GST_BUFFER_OFFSET_END (buffer) =
+        GST_BUFFER_OFFSET (buffer) + gst_buffer_get_size (buffer);
+    dash_stream->current_offset = GST_BUFFER_OFFSET_END (buffer);
+    ret = gst_adaptive_demux2_stream_push_buffer (stream, buffer);
+  }
+
+  return ret;
+}
+
 static GstFlowReturn
 gst_dash_demux_stream_data_received (GstAdaptiveDemux2Stream * stream,
     GstBuffer * buffer)
@@ -3707,6 +3971,12 @@ gst_dash_demux_stream_data_received (GstAdaptiveDemux2Stream * stream,
   gst_adapter_push (dash_stream->adapter, buffer);
   buffer = NULL;
 
+  /* matroska stream */
+  if ((ret = gst_dash_demux_handle_matroska (stream,
+              dash_stream->adapter)) != GST_FLOW_NOT_SUPPORTED) {
+    return ret;
+  }
+
   if (dash_stream->is_isobmff || stream->downloading_index) {
     /* SIDX index is also ISOBMMF */
     ret = gst_dash_demux_stream_handle_isobmff (stream);
diff --git a/ext/adaptivedemux2/dash/gstdashdemux.h b/ext/adaptivedemux2/dash/gstdashdemux.h
index 425967ef2..c64a19379 100644
--- a/ext/adaptivedemux2/dash/gstdashdemux.h
+++ b/ext/adaptivedemux2/dash/gstdashdemux.h
@@ -39,6 +39,7 @@
 #include <gst/base/gstdataqueue.h>
 
 #include "gstisoff.h"
+#include <gstmatroska.h>
 #include "gstadaptivedemux.h"
 
 #include "gstmpdclient.h"
@@ -104,6 +105,8 @@ struct _GstDashDemux2Stream
     guint64 current_start_offset;
     guint64 current_size;
   } isobmff_parser;
+  /* matroska parsing */
+  GstMatroskaParser matroska_parser;
 
   GstMoofBox *moof;
   guint64 moof_offset, moof_size;
diff --git a/ext/adaptivedemux2/dash/gstmpdhelper.c b/ext/adaptivedemux2/dash/gstmpdhelper.c
index 4ccdd343f..b8bb44d66 100644
--- a/ext/adaptivedemux2/dash/gstmpdhelper.c
+++ b/ext/adaptivedemux2/dash/gstmpdhelper.c
@@ -93,6 +93,10 @@ gst_mpd_helper_mimetype_to_caps (const gchar * mimeType)
     return "video/quicktime";
   } else if (strcmp (mimeType, "audio/mp4") == 0) {
     return "audio/x-m4a";
+  } else if (strcmp (mimeType, "video/webm") == 0) {
+    return "video/webm";
+  } else if (strcmp (mimeType, "audio/webm") == 0) {
+    return "audio/webm";
   } else if (strcmp (mimeType, "text/vtt") == 0) {
     return "application/x-subtitle-vtt";
   } else
diff --git a/ext/adaptivedemux2/gstmatroska.c b/ext/adaptivedemux2/gstmatroska.c
new file mode 100755
index 000000000..739cdda69
--- /dev/null
+++ b/ext/adaptivedemux2/gstmatroska.c
@@ -0,0 +1,463 @@
+/* GStreamer
+ * Copyright 2021-2022 NXP
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "gstmatroska.h"
+#include "stdio.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_matroska_debug);
+#define GST_CAT_DEFAULT gst_matroska_debug
+
+static gboolean initialized = FALSE;
+
+#define INITIALIZE_DEBUG_CATEGORY \
+  if (!initialized) { \
+  GST_DEBUG_CATEGORY_INIT (gst_matroska_debug, "matroska", 0, \
+      "Matroska Format parsing library"); \
+    initialized = TRUE; \
+  }
+
+/* log definition */
+#define GST_MATROSKA_PARSER_DEBUG                  GST_INFO
+
+/* L0: EMBL header */
+#define GST_EBML_ID_HEADER                         0x1A45DFA3
+/* L0: toplevel Segment */
+#define GST_MATROSKA_ID_SEGMENT                    0x18538067
+#define GST_MATROSKA_ID_CLUSTER                    0x1F43B675
+
+/* L1: matroska top-level master IDs, childs of Segment */
+#define GST_MATROSKA_ID_SEEKHEAD                   0x114D9B74
+#define GST_MATROSKA_ID_SEGMENTINFO                0x1549A966
+#define GST_MATROSKA_ID_TRACKS                     0x1654AE6B
+#define GST_MATROSKA_ID_CUES                       0x1C53BB6B
+#define GST_MATROSKA_ID_TAGS                       0x1254C367
+#define GST_MATROSKA_ID_ATTACHMENTS                0x1941A469
+#define GST_MATROSKA_ID_CHAPTERS                   0x1043A770
+
+/* L2: time scale, child of segment information  */
+#define GST_MATROSKA_ID_TIMECODESCALE              0x2AD7B1
+#define GST_MATROSKA_ID_DURATION                   0x4489
+/* L2: cue point, child of cues */
+#define GST_MATROSKA_ID_POINTENTRY                 0xBB
+/* L3: cue time, child of cue point */
+#define GST_MATROSKA_ID_CUETIME                    0xB3
+/* L3: cue track position , child of cue point */
+#define GST_MATROSKA_ID_CUETRACKPOSITION           0xB7
+/* L4: cue track, child of track position */
+#define GST_MATROSKA_ID_CUETRACK                   0xF7
+/* L4: cue cluster position, child of track position */
+#define GST_MATROSKA_ID_CUECLUSTERPOSITION         0xF1
+#define GST_MATROSKA_ID_CUEBLOCKNUMBER             0x5378
+
+void
+gst_matroska_parser_init (GstMatroskaParser * parser)
+{
+  if (parser->array) {
+    GST_ERROR ("array list has not free yet, addr = %p", parser->array);
+  }
+  memset (parser, 0, sizeof (GstMatroskaParser));
+}
+
+void
+gst_matroska_parser_clear (GstMatroskaParser * parser)
+{
+  if (parser->array) {
+    GST_ERROR ("free array list, addr = %p", parser->array);
+    g_array_free (parser->array, TRUE);
+  }
+  memset (parser, 0, sizeof (GstMatroskaParser));
+}
+
+static gint32
+gst_matroska_parser_read_len (guint8 data)
+{
+  guint i = 0;
+
+  for (i = 0; i < 8; i++) {
+    if ((data & (0x80 >> i)) != 0)
+      break;
+  }
+  return (i + 1);
+}
+
+static guint64
+gst_matroska_parser_read_data (guint8 * p, gint64 len)
+{
+  guint64 data = 0;
+
+  if (!p || !len || (len > 8)) {
+    GST_ERROR ("param error, p = %p, len = %" G_GINT64_FORMAT, p, len);
+    return 0;
+  }
+
+  while (len--) {
+    data <<= 8;
+    data |= *p++;
+  }
+
+  return data;
+}
+
+static guint64
+gst_matroska_parser_read_data_len (guint8 * p_buf, guint64 len)
+{
+  guint64 data = 0;
+  guint8 *p8 = p_buf;
+
+  if (!p8 || !len || len > 8) {
+    GST_ERROR ("param error, p8 = %p, len = %" G_GUINT64_FORMAT, p8, len);
+    return 0;
+  }
+
+  data = *p8++;
+  data -= (guint64) 1 << (8 - len);
+  while (--len) {
+    data = (data << 8) | (*p8++);
+  }
+
+  return data;
+}
+
+static guint64
+gst_matroska_read_one_ebml_info (guint8 * buf, gint64 size,
+    GstMatroskaEbmlInfo * p_info)
+{
+  gint64 len = 0;
+  gint64 bytes = 0;
+  guint64 rem_size = 0;
+  guint8 *p8 = NULL;
+  guint64 unknown_length[8] = { 0x7F, 0x3FFF, 0x1FFFFF,
+    0x0FFFFFFF, 0x07FFFFFFFFLL, 0x03FFFFFFFFFFLL,
+    0x01FFFFFFFFFFFFLL, 0x00FFFFFFFFFFFFFFLL
+  };
+
+  if (!buf || !size || !p_info) {
+    GST_MATROSKA_PARSER_DEBUG
+        ("read ebml info, buf = %p, size = %" G_GINT64_FORMAT ", p_info = %p",
+        buf, size, p_info);
+    return 0;
+  }
+
+  rem_size = size;
+  p8 = buf;
+
+  /* extract id field */
+  len = gst_matroska_parser_read_len (*p8);
+  if ((rem_size <= len) || (len > 8)) {
+    if (len > 8) {
+      GST_ERROR ("id field error, size = %" G_GINT64_FORMAT, len);
+    }
+    return 0;
+  } else {
+    p_info->id = gst_matroska_parser_read_data (p8, len);
+    p8 += len;
+    bytes += len;
+    rem_size -= len;
+  }
+
+  /* extract size field */
+  len = gst_matroska_parser_read_len (*p8);
+  if ((rem_size <= len) || (len > 8)) {
+    if (len > 8) {
+      GST_ERROR ("data size field error, size = %" G_GUINT64_FORMAT ", id = 0x%"
+          G_GUINT32_FORMAT, len, p_info->id);
+    }
+    return 0;
+  } else {
+    p_info->size = gst_matroska_parser_read_data_len (p8, len);
+  }
+  /* check unknown length */
+  if (unknown_length[len - 1] == p_info->size) {
+    p_info->size = 0x7FFFFFFFFFFFFFFFULL;
+  }
+  p8 += len;
+  bytes += len;
+  rem_size -= len;
+
+  /* extract data field */
+  p_info->data_buf = p8;
+  p_info->data_offset = (gint64) (p8 - buf);
+  bytes += p_info->size;
+
+  return bytes;
+}
+
+static GstMatroskaParserResult
+gst_matroska_parser_check_id (GstMatroskaParser * parser, guint64 id,
+    guint32 len, GstAdapter * adapter)
+{
+  GstMatroskaParserResult res = GST_MATROSKA_PARSER_OK;
+  guint64 avail = gst_adapter_available (adapter);
+
+  /* Check buffer length */
+  if (avail < len) {
+    GST_MATROSKA_PARSER_DEBUG ("insufficient data, len = %" G_GUINT64_FORMAT,
+        avail);
+    return GST_MATROSKA_PARSER_INSUFFICIENT_DATA;
+  }
+
+  /* Check id */
+  if (gst_matroska_parser_read_data ((guint8 *) gst_adapter_map (adapter, len),
+          len) != id) {
+    res = GST_MATROSKA_PARSER_NOT_SUPPORTED;
+  }
+
+  gst_adapter_unmap (adapter);
+  return res;
+}
+
+static GstMatroskaParserResult
+gst_matroska_parser_extract_data (GstMatroskaParser * parser,
+    GstAdapter * adapter)
+{
+  GstMatroskaPointData point_data;
+  GstMatroskaEbmlInfo embl_info;
+  guint64 consume = 0;
+  guint64 offset = parser->offset;
+  GstMatroskaPointData *entry = NULL;
+  GstMatroskaParserResult res = GST_MATROSKA_PARSER_OK;
+  guint64 len = 0;
+  guint8 *p_buf = 0;
+
+  INITIALIZE_DEBUG_CATEGORY;
+  len = gst_adapter_available (adapter);
+  p_buf = (guint8 *) gst_adapter_map (adapter, len);
+  while (TRUE) {
+    /* Read one ebml */
+    consume = gst_matroska_read_one_ebml_info (p_buf + offset, len, &embl_info);
+
+    /* Adjust some element type to parse sub element information */
+    if (consume) {
+      if ((embl_info.id == GST_MATROSKA_ID_SEGMENT) ||
+          (embl_info.id == GST_MATROSKA_ID_CUES) ||
+          (embl_info.id == GST_MATROSKA_ID_CLUSTER)) {
+        if (consume > embl_info.size) {
+          consume -= embl_info.size;
+        }
+      }
+    }
+
+    /* Check data integrity */
+    if (!consume || (len < consume)) {
+      if (offset) {
+        parser->offset = offset;
+      }
+      gst_adapter_unmap (adapter);
+
+      GST_MATROSKA_PARSER_DEBUG
+          ("insufficient data, offset = %" G_GUINT64_FORMAT ", remain len = %"
+          G_GUINT64_FORMAT ", consume = %" G_GUINT64_FORMAT, offset, len,
+          consume);
+      return GST_MATROSKA_PARSER_OK;
+    }
+
+    /* Get current cue to fill array list */
+    if (parser->array && parser->cue_point_num) {
+      entry = &g_array_index (parser->array,
+          GstMatroskaPointData, (parser->cue_point_num - 1));
+    }
+
+    switch (embl_info.id) {
+      case GST_EBML_ID_HEADER:
+      {
+        parser->consume = 0;
+        GST_MATROSKA_PARSER_DEBUG ("id: embl header, size = %" G_GUINT64_FORMAT,
+            embl_info.size);
+        break;
+      }
+      case GST_MATROSKA_ID_SEGMENT:
+      {
+        parser->segment_offset = parser->consume;
+        /* update consume, need to parse childs id */
+        consume = embl_info.data_offset;
+        GST_MATROSKA_PARSER_DEBUG ("id: segment, size = %" G_GUINT64_FORMAT,
+            embl_info.size);
+        break;
+      }
+      case GST_MATROSKA_ID_SEEKHEAD:
+      {
+        parser->segment_head_offset = parser->consume;
+        GST_MATROSKA_PARSER_DEBUG
+            ("id: segment seek head, offset = %" G_GUINT64_FORMAT ", size = %"
+            G_GUINT64_FORMAT, parser->segment_head_offset, embl_info.size);
+        break;
+      }
+      case GST_MATROSKA_ID_SEGMENTINFO:
+      {
+        /* update consume, need to parse childs id */
+        consume = embl_info.data_offset;
+        GST_MATROSKA_PARSER_DEBUG ("id: segment information, size = %"
+            G_GUINT64_FORMAT, embl_info.size);
+        break;
+      }
+      case GST_MATROSKA_ID_TIMECODESCALE:
+      {
+        parser->time_scale =
+            gst_matroska_parser_read_data (embl_info.data_buf, embl_info.size);
+        break;
+      }
+      case GST_MATROSKA_ID_DURATION:
+      {
+        parser->duration =
+            gst_matroska_parser_read_data (embl_info.data_buf, embl_info.size);
+        break;
+      }
+      case GST_MATROSKA_ID_CUES:
+      {
+        /* update consume, need to parse childs id */
+        consume = embl_info.data_offset;
+        parser->len = parser->consume + consume + embl_info.size;
+        break;
+      }
+      case GST_MATROSKA_ID_POINTENTRY:
+      {
+        if (!parser->array) {
+          parser->array =
+              g_array_new (FALSE, TRUE, sizeof (GstMatroskaPointData));
+        }
+
+        memset (&point_data, 0, sizeof (GstMatroskaPointData));
+        g_array_append_val (parser->array, point_data);
+        parser->cue_point_num++;
+        /* need to parse childs id */
+        consume = embl_info.data_offset;
+        GST_MATROSKA_PARSER_DEBUG ("id: cue point, num = %" G_GUINT64_FORMAT
+            ", size = %" G_GUINT64_FORMAT, parser->cue_point_num,
+            embl_info.size);
+        break;
+      }
+      case GST_MATROSKA_ID_CUETIME:
+      {
+        if (entry) {
+          entry->cue_time =
+              gst_matroska_parser_read_data (embl_info.data_buf,
+              embl_info.size);
+        }
+        break;
+      }
+      case GST_MATROSKA_ID_CUETRACKPOSITION:
+      {
+        /* need to parse childs id */
+        consume = embl_info.data_offset;
+        GST_MATROSKA_PARSER_DEBUG ("id: track position, num = %"
+            G_GUINT64_FORMAT ", size = %" G_GUINT64_FORMAT,
+            parser->cue_point_num, embl_info.size);
+        break;
+      }
+      case GST_MATROSKA_ID_CUECLUSTERPOSITION:
+      {
+        if (entry) {
+          entry->track_pos.cluster_pos =
+              gst_matroska_parser_read_data (embl_info.data_buf,
+              embl_info.size);
+        }
+        break;
+      }
+      case GST_MATROSKA_ID_CUETRACK:
+      {
+        if (entry) {
+          entry->track_pos.track =
+              gst_matroska_parser_read_data (embl_info.data_buf,
+              embl_info.size);
+        }
+        break;
+      }
+      case GST_MATROSKA_ID_CLUSTER:
+      {
+        GST_MATROSKA_PARSER_DEBUG ("id: cluster, offset = %" G_GUINT64_FORMAT,
+            parser->consume);
+        gst_adapter_unmap (adapter);
+        return GST_MATROSKA_PARSER_DONE;
+      }
+      default:
+      {
+        GST_MATROSKA_PARSER_DEBUG
+            ("unhandled id = 0x%" G_GUINT32_FORMAT ", size = %" G_GUINT64_FORMAT
+            ", data_offset = %" G_GINT64_FORMAT ", conume = %" G_GUINT64_FORMAT,
+            embl_info.id, embl_info.size, embl_info.data_offset,
+            parser->consume);
+        break;
+      }
+    }
+    len -= consume;
+    offset += consume;
+    parser->consume += consume;
+
+    /* Get all cues information */
+    if (parser->len) {
+      if (parser->consume >= parser->len) {
+        parser->offset = offset;
+        GST_MATROSKA_PARSER_DEBUG
+            ("get all cues data, offset in adapter = %" G_GUINT64_FORMAT
+            ", conume = %" G_GUINT64_FORMAT ", len = %" G_GUINT64_FORMAT,
+            parser->offset, parser->consume, parser->len);
+        res = GST_MATROSKA_PARSER_DONE;
+        break;
+      }
+    }
+  }
+
+  gst_adapter_unmap (adapter);
+  return res;
+}
+
+GstMatroskaParserResult
+gst_matroska_parser_entry (GstMatroskaParser * parser, GstAdapter * adapter)
+{
+  GstMatroskaParserResult res = GST_MATROSKA_PARSER_OK;
+
+  INITIALIZE_DEBUG_CATEGORY;
+  if (!parser || !adapter) {
+    GST_MATROSKA_PARSER_DEBUG ("gst_matroska_parser_entry: error param");
+    return GST_MATROSKA_PARSER_NOT_SUPPORTED;
+  }
+
+  switch (parser->status) {
+    case GST_MATROSKA_PARSER_STATUS_INIT:
+    {
+      gst_matroska_parser_init (parser);
+      parser->status = GST_MATROSKA_PARSER_STATUS_HEADER;
+    }
+    case GST_MATROSKA_PARSER_STATUS_HEADER:
+    {
+      res =
+          gst_matroska_parser_check_id (parser, GST_EBML_ID_HEADER, 4, adapter);
+      if (res != GST_MATROSKA_PARSER_OK) {
+        return res;
+      }
+      parser->status = GST_MATROSKA_PARSER_STATUS_DATA;
+    }
+    case GST_MATROSKA_PARSER_STATUS_DATA:
+    {
+      res = gst_matroska_parser_extract_data (parser, adapter);
+      if (res != GST_MATROSKA_PARSER_DONE) {
+        return res;
+      }
+      parser->status = GST_MATROSKA_PARSER_STATUS_FINISHED;
+    }
+    case GST_MATROSKA_PARSER_STATUS_FINISHED:
+      break;
+    default:
+      break;
+  }
+  return res;
+}
diff --git a/ext/adaptivedemux2/gstmatroska.h b/ext/adaptivedemux2/gstmatroska.h
new file mode 100755
index 000000000..ac8c85530
--- /dev/null
+++ b/ext/adaptivedemux2/gstmatroska.h
@@ -0,0 +1,104 @@
+/* GStreamer
+ * Copyright 2021-2022 NXP
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+#ifndef __GST_MATROSKA_H__
+#define __GST_MATROSKA_H__
+#include <gst/gst.h>
+#include <gst/gstinfo.h>
+#include <gst/base/gstadapter.h>
+
+G_BEGIN_DECLS
+#ifndef GST_MATROSKA_API
+# ifdef BUILDING_GST_MATROSKA
+#  define GST_MATROSKA_API GST_API_EXPORT       /* from config.h */
+# else
+#  define GST_MATROSKA_API GST_API_IMPORT
+# endif
+#endif
+    typedef struct
+{
+  guint32 id;
+  guint64 size;
+  gint64 data_offset;
+  guint8 *data_buf;
+} GstMatroskaEbmlInfo;
+
+typedef enum
+{
+  GST_MATROSKA_PARSER_OK,
+  GST_MATROSKA_PARSER_DONE,
+  GST_MATROSKA_PARSER_NOT_SUPPORTED,
+  GST_MATROSKA_PARSER_ERROR_PARAM,
+  GST_MATROSKA_PARSER_INSUFFICIENT_DATA,
+  GST_MATROSKA_PARSER_ERROR
+} GstMatroskaParserResult;
+
+typedef enum
+{
+  GST_MATROSKA_PARSER_STATUS_INIT,
+  GST_MATROSKA_PARSER_STATUS_HEADER,
+  GST_MATROSKA_PARSER_STATUS_DATA,
+  GST_MATROSKA_PARSER_STATUS_FINISHED
+} GstMatroskaParserStatus;
+
+typedef struct
+{
+  guint64 track;
+  guint64 cluster_pos;
+} GstMatroskaTrackPosType;
+
+typedef struct
+{
+  guint64 cue_time;
+  GstMatroskaTrackPosType track_pos;
+} GstMatroskaPointData;
+
+typedef struct _GstMatroskaParser
+{
+  /* total length before first cluster */
+  guint64 len;
+  /* segment offset */
+  guint64 segment_offset;
+  /* cluster address = segment_head_offset + cue cluster position */
+  guint64 segment_head_offset;
+  /* unit of time scale is nanosecond */
+  guint64 time_scale;
+  guint64 duration;
+  /* parsed length in adapter */
+  guint64 offset;
+  /* current consume length */
+  guint64 consume;
+  /* number of cue point */
+  guint64 cue_point_num;
+  /* cue point data list */
+  GArray *array;
+  GstMatroskaParserStatus status;
+  gboolean is_discard_ebml_header;
+  guint64 total_length;
+} GstMatroskaParser;
+
+GST_MATROSKA_API void gst_matroska_parser_init (GstMatroskaParser * parser);
+
+GST_MATROSKA_API void gst_matroska_parser_clear (GstMatroskaParser * parser);
+
+GST_MATROSKA_API
+    GstMatroskaParserResult gst_matroska_parser_entry (GstMatroskaParser *
+    parser, GstAdapter * adapter);
+
+G_END_DECLS
+#endif /* __GST_MATROSKA_H__ */
diff --git a/ext/adaptivedemux2/meson.build b/ext/adaptivedemux2/meson.build
index 711b38a2a..cea8bb54f 100644
--- a/ext/adaptivedemux2/meson.build
+++ b/ext/adaptivedemux2/meson.build
@@ -40,6 +40,7 @@ smoothstreaming_sources = [
 plugin_sources = [
   'plugin.c',
   'gstisoff.c',
+  'gstmatroska.c',
   'gstadaptivedemux.c',
   'gstadaptivedemuxelement.c',
   'gstadaptivedemuxutils.c',
-- 
2.34.1


From 87f9c6a34db7eef8ec37eed207a8acbcc25a12e7 Mon Sep 17 00:00:00 2001
From: Elliot Chen <elliot.chen@nxp.com>
Date: Mon, 9 Jan 2023 16:27:07 +0800
Subject: [PATCH 48/75] MMFMWK-9190 ac3parse: collect all eac3 substream and
 send it with independent stream

For eac3 audio of more than 5.1 channels, it will has substream.
Need collect all eac3 substream and send it with dependent stream to fix timestamp issue.

Signed-off-by: Elliot Chen <elliot.chen@nxp.com>
---
 gst/audioparsers/gstac3parse.c | 32 ++++++++++++++++++++++++++++++++
 gst/audioparsers/gstac3parse.h |  2 ++
 2 files changed, 34 insertions(+)

diff --git a/gst/audioparsers/gstac3parse.c b/gst/audioparsers/gstac3parse.c
index 44e75ff5c..01b437135 100644
--- a/gst/audioparsers/gstac3parse.c
+++ b/gst/audioparsers/gstac3parse.c
@@ -213,6 +213,8 @@ gst_ac3_parse_reset (GstAc3Parse * ac3parse)
   ac3parse->sample_rate = -1;
   ac3parse->blocks = -1;
   ac3parse->eac = FALSE;
+  ac3parse->sub_stream_idx = 0;
+  ac3parse->sub_stream_num = 0;
   ac3parse->sent_codec_tag = FALSE;
   g_atomic_int_set (&ac3parse->align, GST_AC3_PARSE_ALIGN_NONE);
 }
@@ -396,6 +398,11 @@ gst_ac3_parse_frame_header_eac3 (GstAc3Parse * ac3parse, GstBuffer * buf,
   if (G_UNLIKELY (strmtyp == 3)) {
     GST_DEBUG_OBJECT (ac3parse, "bad strmtyp %d", strmtyp);
     goto cleanup;
+  } else if (strmtyp == 1) {
+    ac3parse->sub_stream_idx++;
+  } else if (strmtyp == 0) {
+    ac3parse->sub_stream_num = ac3parse->sub_stream_idx;
+    ac3parse->sub_stream_idx = 0;
   }
 
   strmid = gst_bit_reader_get_bits_uint8_unchecked (&bits, 3);  /* substreamid */
@@ -592,6 +599,31 @@ gst_ac3_parse_handle_frame (GstBaseParse * parse,
       } while (sid);
     }
 
+    /* We're now at the next frame, so no need to skip if resyncing */
+    frmsiz = 0;
+  } else {
+    if ((sid == 0) && (ac3parse->sub_stream_num)) {
+      GST_LOG_OBJECT (ac3parse, "has substream, total number %d", ac3parse->sub_stream_num);
+      framesize = 0;
+
+      /* Loop till we get all substream */
+      gint loop = ac3parse->sub_stream_num;
+      do {
+        framesize += frmsiz;
+
+        if (!gst_byte_reader_skip (&reader, frmsiz)
+            || map.size < (framesize + 6)) {
+          more = TRUE;
+          break;
+        }
+
+        if (!gst_ac3_parse_frame_header (ac3parse, buf, framesize, &frmsiz,
+                NULL, NULL, NULL, &sid, &eac)) {
+          *skipsize = off + 2;
+          goto cleanup;
+        }
+      } while (loop--);
+    }
     /* We're now at the next frame, so no need to skip if resyncing */
     frmsiz = 0;
   }
diff --git a/gst/audioparsers/gstac3parse.h b/gst/audioparsers/gstac3parse.h
index 81e2104d5..6de74dbbf 100644
--- a/gst/audioparsers/gstac3parse.h
+++ b/gst/audioparsers/gstac3parse.h
@@ -64,6 +64,8 @@ struct _GstAc3Parse {
   gboolean              sent_codec_tag;
   gint                  align;
   GstPadChainFunction   baseparse_chainfunc;
+  gint                  sub_stream_idx;
+  gint                  sub_stream_num;
 };
 
 /**
-- 
2.34.1


From 7d9e3e3cb261e9cd3edab66296238f485c32ba2c Mon Sep 17 00:00:00 2001
From: Elliot Chen <elliot.chen@nxp.com>
Date: Tue, 18 Apr 2023 15:02:13 +0800
Subject: [PATCH 49/75] MMFMWK-9227 v4l2: update real video format

use the specific fourcc V4L2_PIX_FMT_RV30 and V4L2_PIX_FMT_RV40
instead of the inappropriate general fourcc V4L2_PIX_FMT_RV.

Signed-off-by: Elliot Chen <elliot.chen@nxp.com>
---
 sys/v4l2/ext/videodev2.h |  1 -
 sys/v4l2/gstv4l2object.c | 26 ++++++++++++++++++++++----
 2 files changed, 22 insertions(+), 5 deletions(-)

diff --git a/sys/v4l2/ext/videodev2.h b/sys/v4l2/ext/videodev2.h
index f55d4caea..8a78bcb8b 100644
--- a/sys/v4l2/ext/videodev2.h
+++ b/sys/v4l2/ext/videodev2.h
@@ -724,7 +724,6 @@ struct v4l2_pix_format {
 #define V4L2_PIX_FMT_H264     v4l2_fourcc('H', '2', '6', '4') /* H264 with start codes */
 #define V4L2_PIX_FMT_H264_NO_SC v4l2_fourcc('A', 'V', 'C', '1') /* H264 without start codes */
 #define V4L2_PIX_FMT_H264_MVC v4l2_fourcc('M', '2', '6', '4') /* H264 MVC */
-#define V4L2_PIX_FMT_RV       v4l2_fourcc('R', 'V', '0', '0') /* RV8/9/10 */
 #define V4L2_PIX_FMT_VP6      v4l2_fourcc('V', 'P', '6', '0') /* VP6 */
 #define V4L2_PIX_FMT_AVS      v4l2_fourcc('A', 'V', 'S', '0') /* AVS */
 #define V4L2_PIX_FMT_SPK      v4l2_fourcc('S', 'P', 'K', '0') /* Sorenson Spark */
diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c
index 7ae13ad83..638dfa429 100644
--- a/sys/v4l2/gstv4l2object.c
+++ b/sys/v4l2/gstv4l2object.c
@@ -216,7 +216,6 @@ static const GstV4L2FormatDesc gst_v4l2_formats[] = {
   {V4L2_PIX_FMT_H264_NO_SC, FALSE, GST_V4L2_CODEC},
   {V4L2_PIX_FMT_H264_MVC, FALSE, GST_V4L2_CODEC},
   {V4L2_PIX_FMT_HEVC, FALSE, GST_V4L2_CODEC},
-  {V4L2_PIX_FMT_RV, FALSE, GST_V4L2_CODEC},
   {V4L2_PIX_FMT_VP6, FALSE, GST_V4L2_CODEC},
   {V4L2_PIX_FMT_AVS, FALSE, GST_V4L2_CODEC},
   {V4L2_PIX_FMT_SPK, FALSE, GST_V4L2_CODEC},
@@ -231,6 +230,8 @@ static const GstV4L2FormatDesc gst_v4l2_formats[] = {
   {V4L2_PIX_FMT_VC1_ANNEX_L, FALSE, GST_V4L2_CODEC},
   {V4L2_PIX_FMT_VP8, FALSE, GST_V4L2_CODEC | GST_V4L2_NO_PARSE},
   {V4L2_PIX_FMT_VP9, FALSE, GST_V4L2_CODEC | GST_V4L2_NO_PARSE},
+  {V4L2_PIX_FMT_RV30, FALSE, GST_V4L2_CODEC},
+  {V4L2_PIX_FMT_RV40, FALSE, GST_V4L2_CODEC},
 
   /*  Vendor-specific formats   */
   {V4L2_PIX_FMT_WNVA, TRUE, GST_V4L2_CODEC},
@@ -1665,8 +1666,13 @@ gst_v4l2_object_v4l2fourcc_to_bare_struct (guint32 fourcc)
           "stream-format", G_TYPE_STRING, "byte-stream", "alignment",
           G_TYPE_STRING, "au", NULL);
       break;
-    case V4L2_PIX_FMT_RV:
-      structure = gst_structure_new_empty ("video/x-pn-realvideo");
+    case V4L2_PIX_FMT_RV30:
+      structure = gst_structure_new ("video/x-pn-realvideo",
+          "version", G_TYPE_INT, 3, NULL);
+      break;
+    case V4L2_PIX_FMT_RV40:
+      structure = gst_structure_new ("video/x-pn-realvideo",
+          "version", G_TYPE_INT, 4, NULL);
       break;
     case V4L2_PIX_FMT_VP6:
       structure = gst_structure_new_empty ("video/x-vp6-flash");
@@ -2246,7 +2252,19 @@ gst_v4l2_object_get_caps_info (GstV4l2Object * v4l2object, GstCaps * caps,
     } else if (g_str_equal (mimetype, "video/x-h265")) {
       fourcc = V4L2_PIX_FMT_HEVC;
     } else if (g_str_equal (mimetype, "video/x-pn-realvideo")) {
-      fourcc = V4L2_PIX_FMT_RV;
+      gint version;
+      if (gst_structure_get_int (structure, "version", &version)) {
+        switch (version) {
+          case 3:
+            fourcc = V4L2_PIX_FMT_RV30;
+            break;
+          case 4:
+            fourcc = V4L2_PIX_FMT_RV40;
+            break;
+          default:
+            break;
+        }
+      }
     } else if (g_str_equal (mimetype, "video/x-vp6-flash")) {
       fourcc = V4L2_PIX_FMT_VP6;
     } else if (g_str_equal (mimetype, "video/x-cavs")) {
-- 
2.34.1


From 2d5fa2a840f97d257d2147fb92bd35608aec4d6d Mon Sep 17 00:00:00 2001
From: Hou Qi <qi.hou@nxp.com>
Date: Wed, 26 Jul 2023 17:21:36 +0800
Subject: [PATCH 50/75] LF-9135 [8mq] fix one stream with all corrupted video
 frames cannot play

When there are over 50 continuous video frames that cannot be
decoded from start or after seek, send gap event to finish preroll.

Signed-off-by: Hou Qi <qi.hou@nxp.com>
---
 sys/v4l2/gstv4l2allocator.c |  7 +++++++
 sys/v4l2/gstv4l2allocator.h |  2 ++
 sys/v4l2/gstv4l2object.c    |  2 ++
 sys/v4l2/gstv4l2object.h    |  2 ++
 sys/v4l2/gstv4l2videodec.c  | 15 +++++++++++++++
 5 files changed, 28 insertions(+)

diff --git a/sys/v4l2/gstv4l2allocator.c b/sys/v4l2/gstv4l2allocator.c
index ffa5dc85d..73da32428 100644
--- a/sys/v4l2/gstv4l2allocator.c
+++ b/sys/v4l2/gstv4l2allocator.c
@@ -1434,6 +1434,13 @@ gst_v4l2_allocator_dqbuf (GstV4l2Allocator * allocator,
   /* And update memory size */
   if (V4L2_TYPE_IS_OUTPUT (obj->type)) {
     gst_v4l2_allocator_reset_size (allocator, group);
+    if (group->buffer.flags & V4L2_BUF_FLAG_ERROR) {    //output buffer cannot be decoded
+      if (!obj->frame_decoded)
+        obj->err_cnt++;
+    } else {
+      obj->err_cnt = 0;
+      obj->frame_decoded = TRUE;
+    }
   } else {
     /* for capture, simply read the size */
     for (i = 0; i < group->n_mem; i++) {
diff --git a/sys/v4l2/gstv4l2allocator.h b/sys/v4l2/gstv4l2allocator.h
index 7977d66ed..11e9a793b 100644
--- a/sys/v4l2/gstv4l2allocator.h
+++ b/sys/v4l2/gstv4l2allocator.h
@@ -48,6 +48,8 @@ G_BEGIN_DECLS
 
 #define GST_V4L2_MEMORY_QUARK gst_v4l2_memory_quark ()
 
+#define MAX_OUTPUT_ERROR_COUNT 50
+
 typedef struct _GstV4l2Allocator GstV4l2Allocator;
 typedef struct _GstV4l2AllocatorClass GstV4l2AllocatorClass;
 typedef struct _GstV4l2MemoryGroup GstV4l2MemoryGroup;
diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c
index 638dfa429..8a40c97fc 100644
--- a/sys/v4l2/gstv4l2object.c
+++ b/sys/v4l2/gstv4l2object.c
@@ -561,6 +561,8 @@ gst_v4l2_object_new (GstElement * element,
 
   v4l2object->drm_modifier = 0;
   v4l2object->is_g2 = FALSE;
+  v4l2object->frame_decoded = FALSE;
+  v4l2object->err_cnt = 0;
 
   v4l2object->keep_aspect = TRUE;
 
diff --git a/sys/v4l2/gstv4l2object.h b/sys/v4l2/gstv4l2object.h
index 229f1c00e..6c6bc7eaf 100644
--- a/sys/v4l2/gstv4l2object.h
+++ b/sys/v4l2/gstv4l2object.h
@@ -156,6 +156,8 @@ struct _GstV4l2Object {
   gboolean has_alpha_component;
   guint64 drm_modifier;
   gboolean is_g2;
+  gboolean frame_decoded;
+  guint32 err_cnt;
 
   /* only used if the device supports MPLANE
    * nb planes is meaning of v4l2 planes
diff --git a/sys/v4l2/gstv4l2videodec.c b/sys/v4l2/gstv4l2videodec.c
index 4fca1f0c4..574cb76c8 100644
--- a/sys/v4l2/gstv4l2videodec.c
+++ b/sys/v4l2/gstv4l2videodec.c
@@ -358,6 +358,8 @@ gst_v4l2_video_dec_flush (GstVideoDecoder * decoder)
     return TRUE;
 
   self->output_flow = GST_FLOW_OK;
+  self->v4l2output->frame_decoded = FALSE;
+  self->v4l2output->err_cnt = 0;
 
   gst_v4l2_object_unlock_stop (self->v4l2output);
   gst_v4l2_object_unlock_stop (self->v4l2capture);
@@ -1143,6 +1145,19 @@ gst_v4l2_video_dec_handle_frame (GstVideoDecoder * decoder,
         &frame->input_buffer, &frame->system_frame_number);
     GST_VIDEO_DECODER_STREAM_LOCK (decoder);
 
+    if (self->v4l2output->err_cnt > MAX_OUTPUT_ERROR_COUNT) {
+      if (!self->v4l2output->frame_decoded) {
+        self->v4l2output->frame_decoded = TRUE;
+
+        /* If there are over 50 continuous frames that cannot be decoded from start
+         * or after seek, send gap event to finish preroll */
+        gst_pad_push_event (decoder->srcpad, gst_event_new_gap (0,
+                GST_CLOCK_TIME_NONE));
+      }
+      ret = GST_FLOW_EOS;
+      goto drop;
+    }
+
     if (ret == GST_FLOW_FLUSHING) {
       if (gst_pad_get_task_state (GST_VIDEO_DECODER_SRC_PAD (self)) !=
           GST_TASK_STARTED)
-- 
2.34.1


From 6bec62997c30482cb220c16fc167597be736d12d Mon Sep 17 00:00:00 2001
From: Elliot Chen <elliot.chen@nxp.com>
Date: Mon, 18 Sep 2023 13:42:09 +0800
Subject: [PATCH 51/75] MMFMWK-9286 pulsesink: clear stream writeable size if
 exceeds the target buffer length

For some cases such as EOS, there is no audio data
to write but the stream writeable size keeps increasing.
Should clear it when the play is paused.

Signed-off-by: Elliot Chen <elliot.chen@nxp.com>
---
 ext/pulse/pulsesink.c | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/ext/pulse/pulsesink.c b/ext/pulse/pulsesink.c
index 1d87d8c51..3ba891c0b 100644
--- a/ext/pulse/pulsesink.c
+++ b/ext/pulse/pulsesink.c
@@ -1268,6 +1268,33 @@ gst_pulseringbuffer_pause (GstAudioRingBuffer * buf)
   psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (pbuf));
 
   pa_threaded_mainloop_lock (mainloop);
+
+  /* For some cases such as EOS, there is no audio data
+   * to write but the stream writeable size keeps increasing.
+   * Should clear it if it exceeds the target buffer length
+   * when the play is paused. */
+  size_t writeable = pa_stream_writable_size (pbuf->stream);
+  if (writeable != (size_t) - 1) {
+    guint bufsize = buf->spec.segsize * buf->spec.segtotal;
+
+    if (writeable > bufsize && !pbuf->in_commit) {
+      size_t towrite = buf->spec.segsize;
+      gint64 m_offset = writeable - towrite;
+      gint bpf = GST_AUDIO_INFO_BPF (&buf->spec.info);
+
+      m_offset /= bpf;
+      m_offset *= bpf;
+      pa_stream_begin_write (pbuf->stream, &pbuf->m_data, &towrite);
+      memset (pbuf->m_data, 0, towrite);
+      pa_stream_write (pbuf->stream, (uint8_t *) pbuf->m_data,
+                towrite, NULL, m_offset, PA_SEEK_RELATIVE);
+
+      GST_INFO_OBJECT (psink, "writeable length %" G_GSIZE_FORMAT
+          ", flush %" G_GSIZE_FORMAT "samples at relative offset %" G_GINT64_FORMAT,
+        writeable, towrite / bpf, m_offset);
+    }
+  }
+
   GST_DEBUG_OBJECT (psink, "pausing and corking");
   /* make sure the commit method stops writing */
   pbuf->paused = TRUE;
-- 
2.34.1


From a310ce94c1770f35c88b177f87d1d924ce49da0f Mon Sep 17 00:00:00 2001
From: Elliot Chen <elliot.chen@nxp.com>
Date: Mon, 18 Sep 2023 13:57:27 +0800
Subject: [PATCH 52/75] MMFMWK-9286 pulsesink: Prevent data from being written
 beyond the maximum buffer length

Check the position of the data to be written.
If it's greater than the maximum buffer length,
need write silent data firstly in the current
write index to avoid overflow.

Signed-off-by: Elliot Chen <elliot.chen@nxp.com>
---
 ext/pulse/pulsesink.c | 57 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 57 insertions(+)

diff --git a/ext/pulse/pulsesink.c b/ext/pulse/pulsesink.c
index 3ba891c0b..1353a1e0a 100644
--- a/ext/pulse/pulsesink.c
+++ b/ext/pulse/pulsesink.c
@@ -1589,6 +1589,63 @@ gst_pulseringbuffer_commit (GstAudioRingBuffer * buf, guint64 * sample,
       pbuf->m_towrite = 0;
       pbuf->m_offset = offset;  /* keep track of current offset */
 
+      if (offset != pbuf->m_lastoffset) {
+        /* Check the position of the data to be written. If it's
+        * greater than the buffer boundary, need write silent data
+        * firstly in the current write index to avoid overflow */
+        const pa_buffer_attr *actual = pa_stream_get_buffer_attr (pbuf->stream);
+
+        while (TRUE) {
+          const pa_timing_info *info;
+          if ((info = pa_stream_get_timing_info (pbuf->stream))) {
+            /* Check read index is up-to-date */
+            if (!pbuf->corked && info->read_index_corrupt) {
+              continue;
+            }
+
+            if (pbuf->corked) {
+              /* we uncork when the read_index is too far behind write_index */
+              if (info->read_index + bufsize <= info->write_index) {
+                if (!gst_pulsering_set_corked (pbuf, FALSE, FALSE))
+                  goto uncork_failed;
+              }
+            }
+
+            size_t writeable = pa_stream_writable_size (pbuf->stream);
+            if (writeable == (size_t) - 1)
+              goto writable_size_failed;
+
+            writeable /= bpf;
+            writeable *= bpf;
+            if (writeable < actual->minreq) {
+              GST_LOG_OBJECT (psink, "waiting for free space");
+              pa_threaded_mainloop_wait (mainloop);
+            }
+
+            if ((offset + out_samples * bpf) <= (info->read_index + actual->maxlength)) {
+              /* The actual audio data that we need to write is not
+              * greater than the buffer boundary and we can write it */
+              break;
+            }
+
+            if (g_atomic_int_get (&psink->format_lost)) {
+              /* Sink format changed, give up and hope upstream renegotiates */
+              goto fake_done;
+            }
+
+            /* The actula audio data that we need to write is greater
+            * than the buffer boundary, write silent data instead */
+            pa_stream_begin_write (pbuf->stream, &pbuf->m_data, &writeable);
+            memset (pbuf->m_data, 0, writeable);
+            pa_stream_write (pbuf->stream, (uint8_t *) pbuf->m_data,
+                      writeable, NULL, 0, PA_SEEK_RELATIVE);
+            GST_LOG_OBJECT (psink,
+                "flushing silent %u samples at offset %" G_GINT64_FORMAT,
+                (guint) writeable / bpf, info->write_index);
+          }
+        }
+      }
+
       /* get a buffer to write in for now on */
       for (;;) {
         pbuf->m_writable = pa_stream_writable_size (pbuf->stream);
-- 
2.34.1


From 7706cf3e0fb2a26c859f0a38ff79335013f6f088 Mon Sep 17 00:00:00 2001
From: Hou Qi <qi.hou@nxp.com>
Date: Wed, 11 Oct 2023 12:44:47 +0800
Subject: [PATCH 53/75] LF-10264 v4l2: drop frames for decoded buffer with
 error flag

For streams with some frames that cannot be decoded, these frames'
timestamps should not participate in sorting and should be dropped.
Otherwise, it may cause pts of capture buffer smaller than the real
pts, and further cause AV unsync.

Also, imx95 return all capture buffers and some of them may have
error flag. Need to drop these buffers to avoid being showed and
pass below test.

Enter video-test-suite/subtree/fluster, run
./fluster.py run -ts JCT-VC-HEVC_V1 -tv BUMPING_A_ericsson_1 -d GStreamer-H.265-V4L2-Gst1.0 -j1

UpStream Status: Pending
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5479>
---
 sys/v4l2/gstv4l2allocator.c |  8 ++++++++
 sys/v4l2/gstv4l2object.c    |  7 +++++++
 sys/v4l2/gstv4l2object.h    |  2 ++
 sys/v4l2/gstv4l2videodec.c  | 25 +++++++++++++++++++++++++
 4 files changed, 42 insertions(+)

diff --git a/sys/v4l2/gstv4l2allocator.c b/sys/v4l2/gstv4l2allocator.c
index 73da32428..c4058f9ca 100644
--- a/sys/v4l2/gstv4l2allocator.c
+++ b/sys/v4l2/gstv4l2allocator.c
@@ -1435,6 +1435,8 @@ gst_v4l2_allocator_dqbuf (GstV4l2Allocator * allocator,
   if (V4L2_TYPE_IS_OUTPUT (obj->type)) {
     gst_v4l2_allocator_reset_size (allocator, group);
     if (group->buffer.flags & V4L2_BUF_FLAG_ERROR) {    //output buffer cannot be decoded
+      obj->drop_frames =
+          g_list_append (obj->drop_frames, &group->buffer.timestamp);
       if (!obj->frame_decoded)
         obj->err_cnt++;
     } else {
@@ -1442,6 +1444,12 @@ gst_v4l2_allocator_dqbuf (GstV4l2Allocator * allocator,
       obj->frame_decoded = TRUE;
     }
   } else {
+    if (group->buffer.flags & V4L2_BUF_FLAG_ERROR) {    //capture buffer has error flag
+      GST_INFO_OBJECT (allocator, "CAPTURE error flag for frame %u",
+          (guint32) group->buffer.timestamp.tv_sec);
+      obj->drop_frames =
+          g_list_append (obj->drop_frames, &group->buffer.timestamp);
+    }
     /* for capture, simply read the size */
     for (i = 0; i < group->n_mem; i++) {
       gsize size, offset;
diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c
index 8a40c97fc..81250e3ae 100644
--- a/sys/v4l2/gstv4l2object.c
+++ b/sys/v4l2/gstv4l2object.c
@@ -558,6 +558,7 @@ gst_v4l2_object_new (GstElement * element,
   v4l2object->norms = NULL;
   v4l2object->channels = NULL;
   v4l2object->colors = NULL;
+  v4l2object->drop_frames = NULL;
 
   v4l2object->drm_modifier = 0;
   v4l2object->is_g2 = FALSE;
@@ -619,6 +620,7 @@ gst_v4l2_object_destroy (GstV4l2Object * v4l2object)
   g_free (v4l2object->videodev);
   g_free (v4l2object->par);
   g_free (v4l2object->channel);
+  g_free (v4l2object->drop_frames);
 
   gst_poll_free (v4l2object->poll);
 
@@ -1018,6 +1020,11 @@ gst_v4l2_object_close (GstV4l2Object * v4l2object)
   if (v4l2object->poll)
     gst_poll_remove_fd (v4l2object->poll, &v4l2object->pollfd);
 
+  if (v4l2object->drop_frames) {
+    g_free (v4l2object->drop_frames);
+    v4l2object->drop_frames = NULL;
+  }
+
   return TRUE;
 }
 
diff --git a/sys/v4l2/gstv4l2object.h b/sys/v4l2/gstv4l2object.h
index 6c6bc7eaf..1868d4336 100644
--- a/sys/v4l2/gstv4l2object.h
+++ b/sys/v4l2/gstv4l2object.h
@@ -200,6 +200,8 @@ struct _GstV4l2Object {
   GList *channels;
   GData *controls;
 
+  GList *drop_frames;
+
   /* properties */
   v4l2_std_id tv_norm;
   gchar *channel;
diff --git a/sys/v4l2/gstv4l2videodec.c b/sys/v4l2/gstv4l2videodec.c
index 574cb76c8..62eba6698 100644
--- a/sys/v4l2/gstv4l2videodec.c
+++ b/sys/v4l2/gstv4l2videodec.c
@@ -907,6 +907,15 @@ gst_v4l2_video_dec_loop (GstVideoDecoder * decoder)
       ret = gst_v4l2_buffer_pool_process (cpool, &buffer, NULL);
       if (cpool)
         gst_object_unref (cpool);
+
+      while (self->v4l2capture->drop_frames) {
+        guint32 *tmp = self->v4l2capture->drop_frames->data;
+        GstVideoCodecFrame *frame = gst_video_decoder_get_frame (decoder, *tmp);
+        if (frame)
+          gst_video_decoder_drop_frame (decoder, frame);
+        self->v4l2capture->drop_frames =
+            g_list_remove (self->v4l2capture->drop_frames, tmp);
+      }
     }
   } while (ret == GST_V4L2_FLOW_CORRUPTED_BUFFER);
 
@@ -1103,6 +1112,14 @@ gst_v4l2_video_dec_handle_frame (GstVideoDecoder * decoder,
     ret =
         gst_v4l2_buffer_pool_process (GST_V4L2_BUFFER_POOL (pool), &codec_data,
         processed ? &frame->system_frame_number : &dummy_frame_number);
+    while (self->v4l2output->drop_frames) {
+      guint32 *tmp = self->v4l2output->drop_frames->data;
+      GstVideoCodecFrame *frame = gst_video_decoder_get_frame (decoder, *tmp);
+      if (frame)
+        gst_video_decoder_drop_frame (decoder, frame);
+      self->v4l2output->drop_frames =
+          g_list_remove (self->v4l2output->drop_frames, tmp);
+    }
     GST_VIDEO_DECODER_STREAM_LOCK (decoder);
 
     gst_buffer_unref (codec_data);
@@ -1143,6 +1160,14 @@ gst_v4l2_video_dec_handle_frame (GstVideoDecoder * decoder,
     ret =
         gst_v4l2_buffer_pool_process (GST_V4L2_BUFFER_POOL (pool),
         &frame->input_buffer, &frame->system_frame_number);
+    while (self->v4l2output->drop_frames) {
+      guint32 *tmp = self->v4l2output->drop_frames->data;
+      GstVideoCodecFrame *frame = gst_video_decoder_get_frame (decoder, *tmp);
+      if (frame)
+        gst_video_decoder_drop_frame (decoder, frame);
+      self->v4l2output->drop_frames =
+          g_list_remove (self->v4l2output->drop_frames, tmp);
+    }
     GST_VIDEO_DECODER_STREAM_LOCK (decoder);
 
     if (self->v4l2output->err_cnt > MAX_OUTPUT_ERROR_COUNT) {
-- 
2.34.1


From e09977abe9e4d00221dc99b21dcbe0e7b5a8b993 Mon Sep 17 00:00:00 2001
From: Haihua Hu <jared.hu@nxp.com>
Date: Tue, 17 Oct 2023 14:59:42 +0900
Subject: [PATCH 54/75] MMFMWK-9280 pulsesink: need break the slient data loop
 when flushing

if there is no enough audio data send to pulsesink, it will entry
a slient data loop and cannot been broken when flushing pipeline
we need check if pulse has been paused and skip the loop

upstreamer status: imx specific
---
 ext/pulse/pulsesink.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/ext/pulse/pulsesink.c b/ext/pulse/pulsesink.c
index 1353a1e0a..478e639a4 100644
--- a/ext/pulse/pulsesink.c
+++ b/ext/pulse/pulsesink.c
@@ -1603,6 +1603,10 @@ gst_pulseringbuffer_commit (GstAudioRingBuffer * buf, guint64 * sample,
               continue;
             }
 
+            /* check if we was paused when pipeline flushing */
+            if (pbuf->paused)
+              goto was_paused;
+
             if (pbuf->corked) {
               /* we uncork when the read_index is too far behind write_index */
               if (info->read_index + bufsize <= info->write_index) {
-- 
2.34.1


From c75d24d53a4351612ab4b8eaa2428d8a1a1d053e Mon Sep 17 00:00:00 2001
From: Hou Qi <qi.hou@nxp.com>
Date: Tue, 26 Sep 2023 16:25:00 +0800
Subject: [PATCH 55/75] v4l2: Add support for P010_10LE

This format is used for imx95 encoding.

Signed-off-by: Hou Qi <qi.hou@nxp.com>
---
 sys/v4l2/ext/videodev2.h | 1 +
 sys/v4l2/gstv4l2object.c | 9 +++++++++
 2 files changed, 10 insertions(+)

diff --git a/sys/v4l2/ext/videodev2.h b/sys/v4l2/ext/videodev2.h
index 8a78bcb8b..3c256c5dc 100644
--- a/sys/v4l2/ext/videodev2.h
+++ b/sys/v4l2/ext/videodev2.h
@@ -622,6 +622,7 @@ struct v4l2_pix_format {
 #define V4L2_PIX_FMT_NV42    v4l2_fourcc('N', 'V', '4', '2') /* 24  Y/CrCb 4:4:4  */
 #define V4L2_PIX_FMT_P010    v4l2_fourcc('P', '0', '1', '0') /* 24  Y/CbCr 4:2:0 10-bit per component */
 #define V4L2_PIX_FMT_P012    v4l2_fourcc('P', '0', '1', '2') /* 24  Y/CbCr 4:2:0 12-bit per component */
+#define V4L2_PIX_FMT_P010    v4l2_fourcc('P', '0', '1', '0') /* 24  Y/CbCr 4:2:0 10-bit per component */
 
 /* two non contiguous planes - one Y, one Cr + Cb interleaved  */
 #define V4L2_PIX_FMT_NV12M   v4l2_fourcc('N', 'M', '1', '2') /* 12  Y/CbCr 4:2:0  */
diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c
index 81250e3ae..e00b00f37 100644
--- a/sys/v4l2/gstv4l2object.c
+++ b/sys/v4l2/gstv4l2object.c
@@ -182,6 +182,7 @@ static const GstV4L2FormatDesc gst_v4l2_formats[] = {
   {V4L2_PIX_FMT_MM21, TRUE, GST_V4L2_RAW},
   {V4L2_PIX_FMT_P012, TRUE, GST_V4L2_RAW},
   {V4L2_PIX_FMT_P012M, TRUE, GST_V4L2_RAW},
+  {V4L2_PIX_FMT_P010, TRUE, GST_V4L2_RAW},
 
   /* Bayer formats - see http://www.siliconimaging.com/RGB%20Bayer.htm */
   {V4L2_PIX_FMT_SBGGR8, TRUE, GST_V4L2_RAW},
@@ -1161,6 +1162,7 @@ gst_v4l2_object_format_get_rank (const struct v4l2_fmtdesc *fmt)
     case V4L2_PIX_FMT_YUV24:   /* 24  YUY 4:4:4     */
     case V4L2_PIX_FMT_P012:
     case V4L2_PIX_FMT_P012M:
+    case V4L2_PIX_FMT_P010:
     case V4L2_PIX_FMT_Y212:
     case V4L2_PIX_FMT_Y312:
       rank = YUV_ODD_BASE_RANK;
@@ -1488,6 +1490,9 @@ gst_v4l2_object_v4l2fourcc_to_video_format (guint32 fourcc)
     case V4L2_PIX_FMT_P012M:
       format = GST_VIDEO_FORMAT_P012_LE;
       break;
+    case V4L2_PIX_FMT_P010:
+      format = GST_VIDEO_FORMAT_P010_10LE;
+      break;
     case V4L2_PIX_FMT_YVU410:
       format = GST_VIDEO_FORMAT_YVU9;
       break;
@@ -1755,6 +1760,7 @@ gst_v4l2_object_v4l2fourcc_to_bare_struct (guint32 fourcc)
     case V4L2_PIX_FMT_NV24:    /* 24  Y/CrCb 4:4:4  */
     case V4L2_PIX_FMT_P012:
     case V4L2_PIX_FMT_P012M:
+    case V4L2_PIX_FMT_P010:
     case V4L2_PIX_FMT_Y212:
     case V4L2_PIX_FMT_Y312:
     case V4L2_PIX_FMT_YVU410:
@@ -2142,6 +2148,9 @@ gst_v4l2_object_get_caps_info (GstV4l2Object * v4l2object, GstCaps * caps,
         fourcc = V4L2_PIX_FMT_P012;
         fourcc_nc = V4L2_PIX_FMT_P012M;
         break;
+      case GST_VIDEO_FORMAT_P010_10LE:
+        fourcc = V4L2_PIX_FMT_P010;
+        break;
       case GST_VIDEO_FORMAT_YVYU:
         fourcc = V4L2_PIX_FMT_YVYU;
         break;
-- 
2.34.1


From 0b78957d4280b2a7b7b8a23ef5d272d04b574949 Mon Sep 17 00:00:00 2001
From: Hou Qi <qi.hou@nxp.com>
Date: Wed, 27 Sep 2023 14:33:56 +0900
Subject: [PATCH 56/75] v4l2videodec: support negotiation for downscale when
 sink getcaps

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5397>
---
 sys/v4l2/gstv4l2videodec.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/sys/v4l2/gstv4l2videodec.c b/sys/v4l2/gstv4l2videodec.c
index 62eba6698..8e0e2291c 100644
--- a/sys/v4l2/gstv4l2videodec.c
+++ b/sys/v4l2/gstv4l2videodec.c
@@ -1323,8 +1323,15 @@ gst_v4l2_video_dec_sink_getcaps (GstVideoDecoder * decoder, GstCaps * filter)
   GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (decoder);
   GstCaps *result;
 
-  result = gst_video_decoder_proxy_getcaps (decoder, self->probed_sinkcaps,
-      filter);
+  if (self->probed_sinkcaps) {
+    if (filter)
+      result = gst_caps_intersect_full (filter, self->probed_sinkcaps,
+          GST_CAPS_INTERSECT_FIRST);
+    else
+      result = gst_caps_ref (self->probed_sinkcaps);
+  } else {
+    result = gst_video_decoder_proxy_getcaps (decoder, NULL, filter);
+  }
 
   GST_DEBUG_OBJECT (self, "Returning sink caps %" GST_PTR_FORMAT, result);
 
@@ -1334,9 +1341,7 @@ gst_v4l2_video_dec_sink_getcaps (GstVideoDecoder * decoder, GstCaps * filter)
 static gboolean
 gst_v4l2_video_dec_sink_event (GstVideoDecoder * decoder, GstEvent * event)
 {
-  GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (decoder);
   gboolean ret;
-  GstEventType type = GST_EVENT_TYPE (event);
 
   ret = GST_VIDEO_DECODER_CLASS (parent_class)->sink_event (decoder, event);
 
-- 
2.34.1


From b432ad9d76f68f8e7d8fac1d86d317d04478946d Mon Sep 17 00:00:00 2001
From: Hou Qi <qi.hou@nxp.com>
Date: Wed, 27 Sep 2023 15:29:30 +0800
Subject: [PATCH 57/75] v4l2: add downscale support for imx95 wave6 vpu dec

Wave6 driver sets mimimum downscale size to align up with 4,
and sets downscale size to align up with 4 if selection flag
is set as V4L2_SEL_FLAG_GE.

For a 3840x2160 stream, if caps require 1/8th downscale size
480x270, driver reports 480x272. There will be a crop 2 at bottom.

upstreamer status: imx specific
---
 sys/v4l2/gstv4l2object.c   | 21 ++++++++-----
 sys/v4l2/gstv4l2object.h   |  4 ++-
 sys/v4l2/gstv4l2videodec.c | 64 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 81 insertions(+), 8 deletions(-)

diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c
index e00b00f37..e524c6e72 100644
--- a/sys/v4l2/gstv4l2object.c
+++ b/sys/v4l2/gstv4l2object.c
@@ -574,6 +574,8 @@ gst_v4l2_object_new (GstElement * element,
 
   v4l2object->poll = gst_poll_new (TRUE);
   v4l2object->can_poll_device = TRUE;
+  v4l2object->crop_width = 0;
+  v4l2object->crop_height = 0;
 
   /* We now disable libv4l2 by default, but have an env to enable it. */
 #ifdef HAVE_LIBV4L2
@@ -3661,7 +3663,7 @@ gst_v4l2_object_reset_compose_region (GstV4l2Object * obj)
   GST_V4L2_CHECK_OPEN (obj);
 
   sel.type = obj->type;
-  sel.target = V4L2_SEL_TGT_COMPOSE_DEFAULT;
+  sel.target = V4L2_SEL_TGT_COMPOSE;
 
   if (obj->ioctl (obj->video_fd, VIDIOC_G_SELECTION, &sel) < 0) {
     if (errno == ENOTTY) {
@@ -4865,7 +4867,7 @@ gst_v4l2_object_acquire_format (GstV4l2Object * v4l2object, GstVideoInfo * info)
   /* Use the default compose rectangle */
   memset (&sel, 0, sizeof (struct v4l2_selection));
   sel.type = v4l2object->type;
-  sel.target = V4L2_SEL_TGT_COMPOSE_DEFAULT;
+  sel.target = V4L2_SEL_TGT_COMPOSE;
   if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_G_SELECTION, &sel) >= 0) {
     r = &sel.r;
   } else {
@@ -4878,10 +4880,15 @@ gst_v4l2_object_acquire_format (GstV4l2Object * v4l2object, GstVideoInfo * info)
   if (r) {
     align.padding_left = r->left;
     align.padding_top = r->top;
-    align.padding_right = width - r->width - r->left;
-    align.padding_bottom = height - r->height - r->top;
-    width = r->width;
-    height = r->height;
+    align.padding_right =
+        (gint) width - (gint) r->width - r->left - v4l2object->crop_width;
+    align.padding_bottom =
+        (gint) height - (gint) r->height - r->top - v4l2object->crop_height;
+    width = (gint) r->width + v4l2object->crop_width;
+    height = (gint) r->height + v4l2object->crop_height;
+    GST_INFO_OBJECT (v4l2object->dbg_obj,
+        "caps size: %ux%u, padding size: %ux%u", width, height,
+        align.padding_right, align.padding_bottom);
   }
 
   switch (fmt.fmt.pix.field) {
@@ -5763,7 +5770,7 @@ gst_v4l2_object_decide_allocation (GstV4l2Object * obj, GstQuery * query)
 
   /* aovid copy Amphion tiled frame buffer for un-active video track */
   /* also to avoid copy Hantro frame buffer when link v4l2 decoder with fakesink */
-  if (obj->is_amphion || obj->is_hantro) {
+  if (obj->is_amphion || obj->is_hantro || IS_IMX95 ()) {
     can_share_own_pool = TRUE;
     if (min < GST_V4L2_MIN_BUFFERS (obj))
       min = GST_V4L2_MIN_BUFFERS (obj);
diff --git a/sys/v4l2/gstv4l2object.h b/sys/v4l2/gstv4l2object.h
index 1868d4336..7e3f44f58 100644
--- a/sys/v4l2/gstv4l2object.h
+++ b/sys/v4l2/gstv4l2object.h
@@ -238,7 +238,9 @@ struct _GstV4l2Object {
   gboolean skip_try_fmt_probes;
   gboolean is_amphion;
   gboolean is_hantro;
-  
+  gint crop_width;
+  gint crop_height;
+
   guint max_width;
   guint max_height;
 };
diff --git a/sys/v4l2/gstv4l2videodec.c b/sys/v4l2/gstv4l2videodec.c
index 8e0e2291c..e725819b4 100644
--- a/sys/v4l2/gstv4l2videodec.c
+++ b/sys/v4l2/gstv4l2videodec.c
@@ -834,6 +834,68 @@ gst_v4l2_video_dec_wait_for_src_ch (GstV4l2VideoDec * self)
   return flowret;
 }
 
+static void
+gst_v4l2_video_dec_set_selection (GstVideoDecoder * decoder)
+{
+  GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (decoder);
+  GstV4l2Object *v4l2object = self->v4l2capture;
+  struct v4l2_selection sel = { 0 };
+  GstCaps *filter, *caps;
+  GstStructure *structure;
+  const GValue *value;
+  gint width = 0, height = 0;
+  gint src_width, src_height;
+
+  src_width = self->v4l2output->info.width;
+  src_height = self->v4l2output->info.height;
+
+  // get the downscale width/height from caps if have
+  filter = gst_caps_new_empty_simple ("video/x-raw");
+  caps = gst_pad_peer_query_caps (decoder->srcpad, filter);
+  structure = gst_caps_get_structure (caps, 0);
+  GST_INFO_OBJECT (v4l2object->dbg_obj, "queried caps: %" GST_PTR_FORMAT, caps);
+
+  value = gst_structure_get_value (structure, "width");
+  if (value && G_VALUE_TYPE (value) == G_TYPE_INT)
+    width = g_value_get_int (value);
+
+  value = gst_structure_get_value (structure, "height");
+  if (value && G_VALUE_TYPE (value) == G_TYPE_INT)
+    height = g_value_get_int (value);
+
+  if (width >= src_width / 8 && width <= src_width &&
+      height >= src_height / 8 && height <= src_height) {
+    GST_INFO_OBJECT (v4l2object->dbg_obj, "want to s_selection %dx%d", width,
+        height);
+
+    // set selection with downscale size
+    sel.type = v4l2object->type;
+    sel.target = V4L2_SEL_TGT_COMPOSE;
+    sel.flags = V4L2_SEL_FLAG_GE;
+    sel.r.left = 0;
+    sel.r.top = 0;
+    sel.r.width = width;
+    sel.r.height = height;
+
+    if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_S_SELECTION, &sel) < 0) {
+      GST_WARNING_OBJECT (v4l2object->dbg_obj,
+          "Failed to set downscale size with VIDIOC_S_SELECTION: %s",
+          g_strerror (errno));
+      goto out;
+    }
+    v4l2object->crop_width = width - (gint) sel.r.width;
+    v4l2object->crop_height = height - (gint) sel.r.height;
+
+    GST_INFO_OBJECT (v4l2object->dbg_obj, "got downscale size %dx%d",
+        sel.r.width, sel.r.height);
+  }
+
+out:
+  gst_caps_unref (filter);
+  gst_caps_unref (caps);
+  return;
+}
+
 static void
 gst_v4l2_video_dec_loop (GstVideoDecoder * decoder)
 {
@@ -854,6 +916,8 @@ gst_v4l2_video_dec_loop (GstVideoDecoder * decoder)
       goto beach;
     }
 
+    gst_v4l2_video_dec_set_selection (decoder);
+
     GST_DEBUG_OBJECT (decoder, "Setup the capture queue");
     if (G_UNLIKELY (!GST_V4L2_IS_ACTIVE (self->v4l2capture))) {
       if (!gst_video_decoder_negotiate (decoder)) {
-- 
2.34.1


From cd9f5a076c188efedd2842a70f04ed72a46b6bbb Mon Sep 17 00:00:00 2001
From: Hou Qi <qi.hou@nxp.com>
Date: Fri, 8 Dec 2023 09:37:14 +0800
Subject: [PATCH 58/75] LF-10870 v4l2: support encoding after decoder
 downscaling

When encoder is connect to decoder which has downscale, encoder's
padding_bottom will be overwriten by decoder's padding_bottom.

"video/x-raw,width=1280,height=720 ! v4l2h264enc ! v4l2h264dec ! video/x-raw,width=320,height=240 ! v4l2h264enc"
This command causes final encoder's padding_bottom to be 480
instead of 0, which causes encoded file is 320x720 instead of
correct 320x240. So encoder needs to set correct padding_bottom.

upstreamer status: imx specific
---
 sys/v4l2/gstv4l2object.c   | 13 +++----------
 sys/v4l2/gstv4l2videoenc.c | 11 ++++++++---
 2 files changed, 11 insertions(+), 13 deletions(-)

diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c
index e524c6e72..f40a82187 100644
--- a/sys/v4l2/gstv4l2object.c
+++ b/sys/v4l2/gstv4l2object.c
@@ -5454,16 +5454,9 @@ gst_v4l2_object_match_buffer_layout (GstV4l2Object * obj, guint n_planes,
 
     format = obj->format;
 
-    if (padded_height) {
-      GST_DEBUG_OBJECT (obj->dbg_obj, "Padded height %u", padded_height);
-
-      obj->align.padding_bottom =
-          padded_height - GST_VIDEO_INFO_FIELD_HEIGHT (&obj->info);
-    } else {
-      GST_WARNING_OBJECT (obj->dbg_obj,
-          "Failed to compute padded height; keep the default one");
-      padded_height = format.fmt.pix_mp.height;
-    }
+    /* This is to avoid encode's padding_bottom is overwritten by decoder's
+     * padding_bottom in vmeta after downscaling */
+    padded_height = format.fmt.pix_mp.height;
 
     /* update the current format with the stride we want to import from */
     if (V4L2_TYPE_IS_MULTIPLANAR (obj->type)) {
diff --git a/sys/v4l2/gstv4l2videoenc.c b/sys/v4l2/gstv4l2videoenc.c
index 40e0251fb..f886150f8 100644
--- a/sys/v4l2/gstv4l2videoenc.c
+++ b/sys/v4l2/gstv4l2videoenc.c
@@ -771,14 +771,19 @@ gst_v4l2_video_enc_handle_frame (GstVideoEncoder * encoder,
   if (G_UNLIKELY (!g_atomic_int_get (&self->active)))
     goto flushing;
 
-  if (self->v4l2output->req_mode == GST_V4L2_IO_AUTO) {
+  if (self->v4l2output->req_mode == GST_V4L2_IO_AUTO ||
+      self->v4l2output->req_mode == GST_V4L2_IO_DMABUF_IMPORT) {
     GstV4l2IOMode mode = self->v4l2output->mode;
 
     if (gst_is_dmabuf_memory (gst_buffer_peek_memory (frame->input_buffer, 0))
         && (frame->system_frame_number == 0)) {
       self->v4l2output->mode = GST_V4L2_IO_DMABUF_IMPORT;
-      if (!gst_v4l2_object_try_import (self->v4l2output, frame->input_buffer))
-        self->v4l2output->mode = mode;
+      if (!gst_v4l2_object_try_import (self->v4l2output, frame->input_buffer)) {
+        if (mode == GST_V4L2_IO_DMABUF_IMPORT)
+          self->v4l2output->mode = GST_V4L2_IO_MMAP;
+        else
+          self->v4l2output->mode = mode;
+      }
     }
   }
   /* It is possible that a system buffer is received when the number of
-- 
2.34.1


From f6e618103461bbe6e34f4ae39d6661478a2493b3 Mon Sep 17 00:00:00 2001
From: Hou Qi <qi.hou@nxp.com>
Date: Tue, 26 Dec 2023 16:53:18 +0800
Subject: [PATCH 59/75] MMFMWK-9315 v4l2src: recalculate timestamp to avoid
 getting multiple 0 timestamps

When encoding with v4l2src and muxing the encoded file, baseparse
will mark current buffer's pts as GST_CLOCK_TIME_NONE if it is equal
to prev_pts, which causes muxer to report error "Buffer has no PTS".
To avoid this, need to retry calculating pts if clock running time
is lower than the buffer timestamp delay.

upstreamer status: pending
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5869>
---
 sys/v4l2/gstv4l2src.c | 32 ++++++++++----------------------
 1 file changed, 10 insertions(+), 22 deletions(-)

diff --git a/sys/v4l2/gstv4l2src.c b/sys/v4l2/gstv4l2src.c
index 3272480f7..ae479c38d 100644
--- a/sys/v4l2/gstv4l2src.c
+++ b/sys/v4l2/gstv4l2src.c
@@ -1151,7 +1151,6 @@ gst_v4l2src_create (GstPushSrc * src, GstBuffer ** buf)
   GstV4l2Src *v4l2src = GST_V4L2SRC (src);
   GstV4l2Object *obj = v4l2src->v4l2object;
   GstFlowReturn ret;
-  GstClock *clock;
   GstClockTime abs_time, base_time, timestamp, duration;
   GstClockTime delay;
   GstMessage *qos_msg;
@@ -1197,26 +1196,9 @@ gst_v4l2src_create (GstPushSrc * src, GstBuffer ** buf)
   timestamp = GST_BUFFER_TIMESTAMP (*buf);
   duration = obj->duration;
 
-  /* timestamps, LOCK to get clock and base time. */
+  /* timestamps, get base time. */
   /* FIXME: element clock and base_time is rarely changing */
-  GST_OBJECT_LOCK (v4l2src);
-  if ((clock = GST_ELEMENT_CLOCK (v4l2src))) {
-    /* we have a clock, get base time and ref clock */
-    base_time = GST_ELEMENT (v4l2src)->base_time;
-    gst_object_ref (clock);
-  } else {
-    /* no clock, can't set timestamps */
-    base_time = GST_CLOCK_TIME_NONE;
-  }
-  GST_OBJECT_UNLOCK (v4l2src);
-
-  /* sample pipeline clock */
-  if (clock) {
-    abs_time = gst_clock_get_time (clock);
-    gst_object_unref (clock);
-  } else {
-    abs_time = GST_CLOCK_TIME_NONE;
-  }
+  base_time = gst_element_get_base_time (GST_ELEMENT (v4l2src));
 
 retry:
   if (!v4l2src->has_bad_timestamp && timestamp != GST_CLOCK_TIME_NONE) {
@@ -1280,6 +1262,9 @@ retry:
 
   /* set buffer metadata */
 
+  /* sample pipeline clock, reget it if retry */
+  abs_time = gst_element_get_current_clock_time (GST_ELEMENT (v4l2src));
+
   if (G_LIKELY (abs_time != GST_CLOCK_TIME_NONE)) {
     /* the time now is the time of the clock minus the base time */
     timestamp = abs_time - base_time;
@@ -1287,8 +1272,11 @@ retry:
     /* adjust for delay in the device */
     if (timestamp > delay)
       timestamp -= delay;
-    else
-      timestamp = 0;
+    else {
+      /* This is to avoid generating duplicated 0 timestamps. Otherwise baseparse will mark
+         pts as invalid if it's the same with prev_ts, further cause qtmux to report error */
+      goto retry;
+    }
   } else {
     timestamp = GST_CLOCK_TIME_NONE;
   }
-- 
2.34.1


From 439cca7dd9211f13678706f228bbd95c5114bd90 Mon Sep 17 00:00:00 2001
From: Hou Qi <qi.hou@nxp.com>
Date: Wed, 24 Jan 2024 13:30:54 +0800
Subject: [PATCH 60/75] LF-11398 v4l2: set crop meta for decoded buffer

Set crop meta for decoded buffer to make buffers with left and
top padding show correctly. For cases that need to set capture
format, get right crop size and set corret align padding.

upstreamer status: imx specific
---
 sys/v4l2/gstv4l2object.c   | 48 ++++++--------------------------------
 sys/v4l2/gstv4l2videodec.c | 11 +++++++++
 2 files changed, 18 insertions(+), 41 deletions(-)

diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c
index f40a82187..18a9b184b 100644
--- a/sys/v4l2/gstv4l2object.c
+++ b/sys/v4l2/gstv4l2object.c
@@ -3655,40 +3655,6 @@ no_supported_capture_method:
   }
 }
 
-static gboolean
-gst_v4l2_object_reset_compose_region (GstV4l2Object * obj)
-{
-  struct v4l2_selection sel = { 0 };
-
-  GST_V4L2_CHECK_OPEN (obj);
-
-  sel.type = obj->type;
-  sel.target = V4L2_SEL_TGT_COMPOSE;
-
-  if (obj->ioctl (obj->video_fd, VIDIOC_G_SELECTION, &sel) < 0) {
-    if (errno == ENOTTY) {
-      /* No-op when selection API is not supported */
-      return TRUE;
-    } else {
-      GST_WARNING_OBJECT (obj->dbg_obj,
-          "Failed to get default compose rectangle with VIDIOC_G_SELECTION: %s",
-          g_strerror (errno));
-      return FALSE;
-    }
-  }
-
-  sel.target = V4L2_SEL_TGT_COMPOSE;
-
-  if (obj->ioctl (obj->video_fd, VIDIOC_S_SELECTION, &sel) < 0) {
-    GST_WARNING_OBJECT (obj->dbg_obj,
-        "Failed to set default compose rectangle with VIDIOC_S_SELECTION: %s",
-        g_strerror (errno));
-    return FALSE;
-  }
-
-  return TRUE;
-}
-
 static void
 gst_v4l2_object_set_stride (GstVideoInfo * info, GstVideoAlignment * align,
     gint plane, gint stride)
@@ -4464,15 +4430,18 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
    * in ASF mode for example, there is also not reason for a driver to
    * change the size. */
   if (info.finfo->format != GST_VIDEO_FORMAT_ENCODED) {
+    struct v4l2_rect def_crop = { 0 };
     /* We can crop larger images */
     if (format.fmt.pix.width < width || format.fmt.pix.height < height)
       goto invalid_dimensions;
 
+    gst_v4l2_object_get_crop_default (v4l2object, &def_crop);
+
     /* Note, this will be adjusted if upstream has non-centered cropping. */
-    align.padding_top = 0;
-    align.padding_bottom = format.fmt.pix.height - height;
-    align.padding_left = 0;
-    align.padding_right = format.fmt.pix.width - width;
+    align.padding_top = def_crop.top;
+    align.padding_bottom = format.fmt.pix.height - height - def_crop.top;
+    align.padding_left = def_crop.left;
+    align.padding_right = format.fmt.pix.width - width - def_crop.left;
   }
 
   if (is_mplane && format.fmt.pix_mp.num_planes != n_v4l_planes)
@@ -4648,9 +4617,6 @@ done:
   /* add boolean return, so we can fail on drivers bugs */
   gst_v4l2_object_save_format (v4l2object, fmtdesc, &format, &info, &align);
 
-  /* reset composition region to match the S_FMT size */
-  gst_v4l2_object_reset_compose_region (v4l2object);
-
   /* now configure the pool */
   if (!gst_v4l2_object_setup_pool (v4l2object, caps))
     goto pool_failed;
diff --git a/sys/v4l2/gstv4l2videodec.c b/sys/v4l2/gstv4l2videodec.c
index e725819b4..fa82eaf9f 100644
--- a/sys/v4l2/gstv4l2videodec.c
+++ b/sys/v4l2/gstv4l2videodec.c
@@ -1042,6 +1042,17 @@ gst_v4l2_video_dec_loop (GstVideoDecoder * decoder)
 
     frame->duration = self->v4l2capture->duration;
     frame->output_buffer = buffer;
+
+    /* set crop info for none-tiled format */
+    if (!GST_VIDEO_FORMAT_INFO_IS_TILED (self->v4l2capture->info.finfo)) {
+      GstVideoCropMeta *cmeta =
+          gst_buffer_add_video_crop_meta (frame->output_buffer);
+      cmeta->x = self->v4l2capture->align.padding_left;
+      cmeta->y = self->v4l2capture->align.padding_top;
+      cmeta->width = self->v4l2capture->info.width;
+      cmeta->height = self->v4l2capture->info.height;
+    }
+
     if (IS_IMX8MQ () && self->v4l2capture->is_hantro) {
       guint64 drm_modifier = self->v4l2capture->drm_modifier;
       gst_buffer_add_dmabuf_meta (frame->output_buffer, drm_modifier);
-- 
2.34.1


From 6dee89e18632b04f837df6359c15bf5d26d51312 Mon Sep 17 00:00:00 2001
From: Hou Qi <qi.hou@nxp.com>
Date: Thu, 21 Mar 2024 17:18:18 +0800
Subject: [PATCH 61/75] v4l2: limit the encoded buffer size between 256k and 4M

Upstream status: imx specific
---
 sys/v4l2/gstv4l2object.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c
index 18a9b184b..16bd7bcba 100644
--- a/sys/v4l2/gstv4l2object.c
+++ b/sys/v4l2/gstv4l2object.c
@@ -57,6 +57,7 @@ GST_DEBUG_CATEGORY_EXTERN (v4l2_debug);
 #define DEFAULT_PROP_IO_MODE            GST_V4L2_IO_AUTO
 
 #define ENCODED_BUFFER_MIN_SIZE         (256 * 1024)
+#define ENCODED_BUFFER_MAX_SIZE         (4 * 1024 * 1024)
 #define GST_V4L2_DEFAULT_WIDTH          320
 #define GST_V4L2_DEFAULT_HEIGHT         240
 
@@ -3974,7 +3975,7 @@ calculate_max_sizeimage (GstV4l2Object * v4l2object, guint pixel_bitdepth)
   max_height = v4l2object->max_height;
   sizeimage = max_width * max_height * pixel_bitdepth / 8 / 2;
 
-  return MAX (ENCODED_BUFFER_MIN_SIZE, sizeimage);
+  return CLAMP (sizeimage, ENCODED_BUFFER_MIN_SIZE, ENCODED_BUFFER_MAX_SIZE);
 }
 
 static gboolean
-- 
2.34.1


From d0b42d2797906a4bbf7f36362853fc9c5c5018bf Mon Sep 17 00:00:00 2001
From: Hou Qi <qi.hou@nxp.com>
Date: Tue, 26 Mar 2024 08:36:42 +0800
Subject: [PATCH 62/75] v4l2: fix critical warning when playing 10bit stream

This commit is needed to fix the side effect of commit
3387751fcf196bdd7e5cceff62710785f352f7d6. Otherwise planes
of 10 bit stream will be recalculated with padding size.

Upstream status: imx specific
---
 sys/v4l2/gstv4l2bufferpool.c | 26 ++++++++++++++------------
 sys/v4l2/gstv4l2object.c     | 10 ++++++++--
 2 files changed, 22 insertions(+), 14 deletions(-)

diff --git a/sys/v4l2/gstv4l2bufferpool.c b/sys/v4l2/gstv4l2bufferpool.c
index 05e0a7dcf..278593251 100644
--- a/sys/v4l2/gstv4l2bufferpool.c
+++ b/sys/v4l2/gstv4l2bufferpool.c
@@ -771,20 +771,20 @@ gst_v4l2_buffer_pool_streamoff (GstV4l2BufferPool * pool)
           gst_v4l2_buffer_pool_complete_release_buffer (bpool, buffer, FALSE);
         else {
           /* in some cases, the total size of buffer is
-          greater than the pool configured size. Need to
-          resize it to avoid free buffer when release it */
+             greater than the pool configured size. Need to
+             resize it to avoid free buffer when release it */
           gsize buf_size;
           gsize offset;
 
-          buf_size = gst_buffer_get_size(buffer);
+          buf_size = gst_buffer_get_size (buffer);
           if (obj->info.size < buf_size) {
             gst_buffer_get_sizes (buffer, &offset, NULL);
             gst_buffer_resize (buffer, -offset, obj->info.size);
 
             GST_DEBUG_OBJECT (pool, "pool size: %" G_GSIZE_FORMAT
-            ", capture buffer size: %" G_GSIZE_FORMAT
-            ", need to resize capture buffer to avoid free it",
-            obj->info.size, buf_size);
+                ", capture buffer size: %" G_GSIZE_FORMAT
+                ", need to resize capture buffer to avoid free it",
+                obj->info.size, buf_size);
           }
 
           /* Don't re-enqueue capture buffer on stop */
@@ -1337,8 +1337,6 @@ gst_v4l2_buffer_pool_dqbuf (GstV4l2BufferPool * pool, GstBuffer ** buffer,
   timestamp = GST_TIMEVAL_TO_TIME (group->buffer.timestamp);
 
   for (i = 0; i < group->n_mem; i++) {
-    const GstVideoFormatInfo *finfo = info->finfo;
-
     GST_LOG_OBJECT (pool,
         "dequeued buffer %p seq:%d (ix=%d), mem %p used %d, plane=%d, flags %08x, ts %"
         GST_TIME_FORMAT ", pool-queued=%d, buffer=%p, previous-state=%i",
@@ -1354,12 +1352,16 @@ gst_v4l2_buffer_pool_dqbuf (GstV4l2BufferPool * pool, GstBuffer ** buffer,
       /* Ensure our offset matches the expected plane size, or image size if
        * there is only one memory */
       if (group->n_mem == 1) {
-        gst_memory_resize (group->mem[0], 0, info->size + info->offset[0]);
+        if (G_LIKELY (info->size + info->offset[0] <= group->mem[0]->maxsize))
+          gst_memory_resize (group->mem[0], 0, info->size + info->offset[0]);
+        else {
+          GST_WARNING_OBJECT (pool,
+              "v4l2 provided buffer that is too big for the memory it was "
+              "writing into.");
+          gst_memory_resize (group->mem[0], 0, group->mem[0]->maxsize);
+        }
         break;
       }
-
-      if (!GST_VIDEO_FORMAT_INFO_IS_TILED (finfo))
-        gst_memory_resize (group->mem[i], 0, obj->plane_size[i]);
     }
   }
 
diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c
index 16bd7bcba..c6b23325a 100644
--- a/sys/v4l2/gstv4l2object.c
+++ b/sys/v4l2/gstv4l2object.c
@@ -3803,8 +3803,14 @@ gst_v4l2_object_save_format (GstV4l2Object * v4l2object,
           "Left and top padding is not permitted for tiled formats");
     memset (v4l2object->plane_size, 0, sizeof (v4l2object->plane_size));
   } else {
-    if (!gst_video_info_align_full (info, align, v4l2object->plane_size)) {
-      GST_WARNING_OBJECT (v4l2object->dbg_obj, "Failed to align video info");
+    for (i = 0; i < finfo->n_planes; i++) {
+      gint vedge, hedge;
+
+      hedge = GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (finfo, i, align->padding_left);
+      vedge = GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (finfo, i, align->padding_top);
+
+      info->offset[i] += (vedge * info->stride[i]) +
+          (hedge * GST_VIDEO_INFO_COMP_PSTRIDE (info, i));
     }
   }
 
-- 
2.34.1


From d955addeaf3ed673382a6bf6576b92d9ad4b7021 Mon Sep 17 00:00:00 2001
From: Hou Qi <qi.hou@nxp.com>
Date: Wed, 10 Apr 2024 15:21:29 +0800
Subject: [PATCH 63/75] MMFMWK-9360 [imx95]v4l2: return OK instead of EOS when
 sending gap event

For below  2 streams, there is no IDR frames queued after seek to 20%,
normal I and P frames before next IDR after seek will be skipped. Decoder
will send gap event if over 50 output frames cannot be decoded. So need
to return GST_FLOW_OK instead of GST_FLOW_EOS limited to one multiqueue
commit 77919cbf33ea2eaa854a8764e9c5deaed35ae4ce on gst1.24.

/mnt/streams/ttVector/SHAVectors/H264Dec/Conformance/BP/H264_BP20_352x288_24_1887_MP3_24_56_2_ray.avi
/mnt/streams/ttVector/SHAVectors/H264Dec/Conformance/MP/H264_MP21_704x352_30_305_MP3_48_69_1_vbr.avi

upstream status: imx specific
---
 sys/v4l2/gstv4l2allocator.c |  6 +++---
 sys/v4l2/gstv4l2object.c    |  1 -
 sys/v4l2/gstv4l2object.h    |  1 -
 sys/v4l2/gstv4l2videodec.c  | 22 +++++++++++-----------
 4 files changed, 14 insertions(+), 16 deletions(-)

diff --git a/sys/v4l2/gstv4l2allocator.c b/sys/v4l2/gstv4l2allocator.c
index c4058f9ca..15d7bb969 100644
--- a/sys/v4l2/gstv4l2allocator.c
+++ b/sys/v4l2/gstv4l2allocator.c
@@ -1435,13 +1435,13 @@ gst_v4l2_allocator_dqbuf (GstV4l2Allocator * allocator,
   if (V4L2_TYPE_IS_OUTPUT (obj->type)) {
     gst_v4l2_allocator_reset_size (allocator, group);
     if (group->buffer.flags & V4L2_BUF_FLAG_ERROR) {    //output buffer cannot be decoded
+      GST_INFO_OBJECT (allocator, "OUTPUT error flag for frame %u",
+          (guint32) group->buffer.timestamp.tv_sec);
       obj->drop_frames =
           g_list_append (obj->drop_frames, &group->buffer.timestamp);
-      if (!obj->frame_decoded)
-        obj->err_cnt++;
+      obj->err_cnt++;
     } else {
       obj->err_cnt = 0;
-      obj->frame_decoded = TRUE;
     }
   } else {
     if (group->buffer.flags & V4L2_BUF_FLAG_ERROR) {    //capture buffer has error flag
diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c
index c6b23325a..cca4f3820 100644
--- a/sys/v4l2/gstv4l2object.c
+++ b/sys/v4l2/gstv4l2object.c
@@ -564,7 +564,6 @@ gst_v4l2_object_new (GstElement * element,
 
   v4l2object->drm_modifier = 0;
   v4l2object->is_g2 = FALSE;
-  v4l2object->frame_decoded = FALSE;
   v4l2object->err_cnt = 0;
 
   v4l2object->keep_aspect = TRUE;
diff --git a/sys/v4l2/gstv4l2object.h b/sys/v4l2/gstv4l2object.h
index 7e3f44f58..b5b22d73b 100644
--- a/sys/v4l2/gstv4l2object.h
+++ b/sys/v4l2/gstv4l2object.h
@@ -156,7 +156,6 @@ struct _GstV4l2Object {
   gboolean has_alpha_component;
   guint64 drm_modifier;
   gboolean is_g2;
-  gboolean frame_decoded;
   guint32 err_cnt;
 
   /* only used if the device supports MPLANE
diff --git a/sys/v4l2/gstv4l2videodec.c b/sys/v4l2/gstv4l2videodec.c
index fa82eaf9f..f59a11052 100644
--- a/sys/v4l2/gstv4l2videodec.c
+++ b/sys/v4l2/gstv4l2videodec.c
@@ -358,7 +358,6 @@ gst_v4l2_video_dec_flush (GstVideoDecoder * decoder)
     return TRUE;
 
   self->output_flow = GST_FLOW_OK;
-  self->v4l2output->frame_decoded = FALSE;
   self->v4l2output->err_cnt = 0;
 
   gst_v4l2_object_unlock_stop (self->v4l2output);
@@ -1245,17 +1244,17 @@ gst_v4l2_video_dec_handle_frame (GstVideoDecoder * decoder,
     }
     GST_VIDEO_DECODER_STREAM_LOCK (decoder);
 
+    /* If there are over 50 continuous frames that cannot be decoded from start
+      * or after seek, send gap event to finish preroll */
     if (self->v4l2output->err_cnt > MAX_OUTPUT_ERROR_COUNT) {
-      if (!self->v4l2output->frame_decoded) {
-        self->v4l2output->frame_decoded = TRUE;
-
-        /* If there are over 50 continuous frames that cannot be decoded from start
-         * or after seek, send gap event to finish preroll */
-        gst_pad_push_event (decoder->srcpad, gst_event_new_gap (0,
-                GST_CLOCK_TIME_NONE));
-      }
-      ret = GST_FLOW_EOS;
-      goto drop;
+      gst_pad_push_event (decoder->srcpad, gst_event_new_gap (0,
+              GST_CLOCK_TIME_NONE));
+      ret = GST_FLOW_OK;
+
+      /* If OUTPUT buffer is dequeued immediately after queuing, it means this frame
+       * has been dropped, so just unref the pool and return */
+      if (!frame)
+        goto out;
     }
 
     if (ret == GST_FLOW_FLUSHING) {
@@ -1277,6 +1276,7 @@ gst_v4l2_video_dec_handle_frame (GstVideoDecoder * decoder,
   gst_buffer_unref (tmp);
 
   gst_video_codec_frame_unref (frame);
+out:
   if (pool)
     gst_object_unref (pool);
   return ret;
-- 
2.34.1


From 4b443620053ac10128c7c78202664ee4d4de607e Mon Sep 17 00:00:00 2001
From: Hou Qi <qi.hou@nxp.com>
Date: Mon, 29 Apr 2024 15:14:15 +0800
Subject: [PATCH 64/75] MMFMWK-9374 v4l2: Adjust encoded buffer size

Enlarge encoded buffer size to
[max_width * max_height * (pixel_bitdepth / 8) * (3 / 2)],
and limit it between 256kB and 4MB.

upstream status: imx-specific
---
 sys/v4l2/gstv4l2object.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c
index cca4f3820..7c1de6162 100644
--- a/sys/v4l2/gstv4l2object.c
+++ b/sys/v4l2/gstv4l2object.c
@@ -3978,7 +3978,7 @@ calculate_max_sizeimage (GstV4l2Object * v4l2object, guint pixel_bitdepth)
 
   max_width = v4l2object->max_width;
   max_height = v4l2object->max_height;
-  sizeimage = max_width * max_height * pixel_bitdepth / 8 / 2;
+  sizeimage = max_width * max_height * (pixel_bitdepth / 8) * (3 / 2);
 
   return CLAMP (sizeimage, ENCODED_BUFFER_MIN_SIZE, ENCODED_BUFFER_MAX_SIZE);
 }
-- 
2.34.1


From 2e05d5f8dca322a2b1089327db937d2963bbab60 Mon Sep 17 00:00:00 2001
From: Hou Qi <qi.hou@nxp.com>
Date: Tue, 30 Apr 2024 11:05:05 +0800
Subject: [PATCH 65/75] MMFMWK-9375 v4l2videodec: avoid race condition between
 drain and source change

When do "c -4" for res-chaneg stream, decoder first dequeue
a source change event, set the draining flag to TRUE which
will be used to do capture steamoff and capture streamon.

At this time, decoder drains and set draining flag to FALSE,
It causes decoder cannot finish source change. Then do seek,
the last capture streamon is ignored by driver as source change
is not finished and reschange_notified is still TRUE. Driver
doesn't send capture streamon command to daemon, which makes
daemon wait for more buffers to be queued but gstreamer think
it has finished seek.

To fix this hang issue, need to clear draining flag after
source change is finished.

upstream status: imx-specific
---
 sys/v4l2/gstv4l2videodec.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

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)
-- 
2.34.1


From e231b029c2b4eb23f8ebedd6f10062a9091f9fef Mon Sep 17 00:00:00 2001
From: Hou Qi <qi.hou@nxp.com>
Date: Fri, 31 May 2024 15:16:48 +0800
Subject: [PATCH 66/75] LF-12547 v4l2videodec: fix webcamera fail when imx95
 servers as receiver

With webcamera, v4l2decoder received caps may have no width
and height info. Then decoder will use 0x0 to do downscale,
which further causes negotiation issue. Need to fixed by:

1. If queried size is a range, not downscale.
2. If width and height in caps is missing, still can downscale as
   actual size has been parsed after source change.

upstream status: imx-specific
---
 sys/v4l2/gstv4l2videodec.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/sys/v4l2/gstv4l2videodec.c b/sys/v4l2/gstv4l2videodec.c
index 1e6343244..48e96b3e8 100644
--- a/sys/v4l2/gstv4l2videodec.c
+++ b/sys/v4l2/gstv4l2videodec.c
@@ -860,8 +860,15 @@ gst_v4l2_video_dec_set_selection (GstVideoDecoder * decoder)
   if (value && G_VALUE_TYPE (value) == G_TYPE_INT)
     height = g_value_get_int (value);
 
-  if (width >= src_width / 8 && width <= src_width &&
-      height >= src_height / 8 && height <= src_height) {
+  /* not downscale if queried size is a range */
+  if (!width || !height)
+    goto out;
+
+  /* still downscale if size info is missing in caps as actual
+   * size has been parsed after source change */
+  if ((!src_width && !src_height) || (width >= src_width / 8
+          && width <= src_width && height >= src_height / 8
+          && height <= src_height)) {
     GST_INFO_OBJECT (v4l2object->dbg_obj, "want to s_selection %dx%d", width,
         height);
 
-- 
2.34.1


From 8028c77873752b809afb0f1c4e321a6d00de4584 Mon Sep 17 00:00:00 2001
From: Hou Qi <qi.hou@nxp.com>
Date: Thu, 23 May 2024 08:43:01 +0800
Subject: [PATCH 67/75] LF-12431 v4l2: Enlarge maximum encoded buffer size to
 6MB

For below stream, original 4MB encoded buffer size is not enough.
/mnt/src/mm_public/WebM/Conformance/4K/Hubble_Realms_of_Light_in_4k_UHD__VO_2160p.webm

upstream status: imx-specific
---
 sys/v4l2/gstv4l2object.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c
index 7c1de6162..6315f74ca 100644
--- a/sys/v4l2/gstv4l2object.c
+++ b/sys/v4l2/gstv4l2object.c
@@ -57,7 +57,7 @@ GST_DEBUG_CATEGORY_EXTERN (v4l2_debug);
 #define DEFAULT_PROP_IO_MODE            GST_V4L2_IO_AUTO
 
 #define ENCODED_BUFFER_MIN_SIZE         (256 * 1024)
-#define ENCODED_BUFFER_MAX_SIZE         (4 * 1024 * 1024)
+#define ENCODED_BUFFER_MAX_SIZE         (6 * 1024 * 1024)
 #define GST_V4L2_DEFAULT_WIDTH          320
 #define GST_V4L2_DEFAULT_HEIGHT         240
 
-- 
2.34.1


From bc44d5a73da13ffba50a240ff528c2fd6c03dfdc Mon Sep 17 00:00:00 2001
From: Hou Qi <qi.hou@nxp.com>
Date: Thu, 9 May 2024 15:08:21 +0800
Subject: [PATCH 68/75] MMFMWK-9338 v4l2: Make sure output is queued before
 starting src task

For streams that need orphaning after first seek, capture buffer
pool is streamoff and inactive, while output is streamon. After
second seek, output streamoff and has no chance to queue buffer
before starting src task as output buffer pool is still active.
Then capture queue try to poll when both queues are empty, which
causes poll error.

To fix this, need to make sure output buffer is queued before
starting src task, but not to wait source change event after seek
to avoid hang.

upstream status: pending
Part-of: https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6236
---
 sys/v4l2/gstv4l2bufferpool.c |  8 ++++++
 sys/v4l2/gstv4l2object.c     |  1 +
 sys/v4l2/gstv4l2object.h     |  1 +
 sys/v4l2/gstv4l2videodec.c   | 49 ++++++++++++++++++++----------------
 4 files changed, 37 insertions(+), 22 deletions(-)

diff --git a/sys/v4l2/gstv4l2bufferpool.c b/sys/v4l2/gstv4l2bufferpool.c
index 278593251..6d82d6d78 100644
--- a/sys/v4l2/gstv4l2bufferpool.c
+++ b/sys/v4l2/gstv4l2bufferpool.c
@@ -707,6 +707,10 @@ gst_v4l2_buffer_pool_streamon (GstV4l2BufferPool * pool)
       if (obj->ioctl (pool->video_fd, VIDIOC_STREAMON, &obj->type) < 0)
         goto streamon_failed;
 
+      /* finish seek via OUTPUT streamon */
+      if (V4L2_TYPE_IS_OUTPUT (obj->type))
+        g_atomic_int_set (&obj->seek, FALSE);
+
       pool->streaming = TRUE;
 
       GST_DEBUG_OBJECT (pool, "Started streaming");
@@ -746,6 +750,10 @@ gst_v4l2_buffer_pool_streamoff (GstV4l2BufferPool * pool)
         GST_WARNING_OBJECT (pool, "STREAMOFF failed with errno %d (%s)",
             errno, g_strerror (errno));
 
+      /* start seek via OUTPUT streamoff */
+      if (V4L2_TYPE_IS_OUTPUT (obj->type))
+        g_atomic_int_set (&obj->seek, TRUE);
+
       pool->streaming = FALSE;
 
       GST_DEBUG_OBJECT (pool, "Stopped streaming");
diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c
index 6315f74ca..42bdd0476 100644
--- a/sys/v4l2/gstv4l2object.c
+++ b/sys/v4l2/gstv4l2object.c
@@ -576,6 +576,7 @@ gst_v4l2_object_new (GstElement * element,
   v4l2object->can_poll_device = TRUE;
   v4l2object->crop_width = 0;
   v4l2object->crop_height = 0;
+  g_atomic_int_set (&v4l2object->seek, FALSE);
 
   /* We now disable libv4l2 by default, but have an env to enable it. */
 #ifdef HAVE_LIBV4L2
diff --git a/sys/v4l2/gstv4l2object.h b/sys/v4l2/gstv4l2object.h
index b5b22d73b..114349988 100644
--- a/sys/v4l2/gstv4l2object.h
+++ b/sys/v4l2/gstv4l2object.h
@@ -239,6 +239,7 @@ struct _GstV4l2Object {
   gboolean is_hantro;
   gint crop_width;
   gint crop_height;
+  gboolean seek;
 
   guint max_width;
   guint max_height;
diff --git a/sys/v4l2/gstv4l2videodec.c b/sys/v4l2/gstv4l2videodec.c
index 48e96b3e8..146598400 100644
--- a/sys/v4l2/gstv4l2videodec.c
+++ b/sys/v4l2/gstv4l2videodec.c
@@ -1121,6 +1121,7 @@ gst_v4l2_video_dec_handle_frame (GstVideoDecoder * decoder,
   gboolean processed = FALSE;
   GstBuffer *tmp;
   GstTaskState task_state;
+  gboolean seek = g_atomic_int_get (&self->v4l2output->seek);
 
   GST_DEBUG_OBJECT (self, "Handling frame %d", frame->system_frame_number);
 
@@ -1136,7 +1137,8 @@ gst_v4l2_video_dec_handle_frame (GstVideoDecoder * decoder,
   }
 
   pool = gst_v4l2_object_get_buffer_pool (self->v4l2output);
-  if (G_UNLIKELY (!gst_buffer_pool_is_active (pool))) {
+  if (G_UNLIKELY (!gst_buffer_pool_is_active (pool)
+          || !GST_V4L2_BUFFER_POOL_IS_STREAMING (pool))) {
     GstBuffer *codec_data;
     GstStructure *config = gst_buffer_pool_get_config (pool);
     guint min = MAX (self->v4l2output->min_buffers,
@@ -1159,32 +1161,34 @@ gst_v4l2_video_dec_handle_frame (GstVideoDecoder * decoder,
     }
 
     /* Ensure input internal pool is active */
+    if (!gst_buffer_pool_is_active (pool)) {
+      gst_buffer_pool_config_set_params (config, self->input_state->caps,
+          self->v4l2output->info.size, min, max);
+
+      /* There is no reason to refuse this config */
+      if (!gst_buffer_pool_set_config (pool, config)) {
+        config = gst_buffer_pool_get_config (pool);
+
+        if (!gst_buffer_pool_config_validate_params (config,
+                self->input_state->caps, self->v4l2output->info.size, min,
+                max)) {
+          gst_structure_free (config);
+          goto activate_failed;
+        }
 
-    gst_buffer_pool_config_set_params (config, self->input_state->caps,
-        self->v4l2output->info.size, min, max);
-
-    /* There is no reason to refuse this config */
-    if (!gst_buffer_pool_set_config (pool, config)) {
-      config = gst_buffer_pool_get_config (pool);
-
-      if (!gst_buffer_pool_config_validate_params (config,
-              self->input_state->caps, self->v4l2output->info.size, min, max)) {
-        gst_structure_free (config);
-        goto activate_failed;
+        if (!gst_buffer_pool_set_config (pool, config))
+          goto activate_failed;
       }
 
-      if (!gst_buffer_pool_set_config (pool, config))
+      /* Ensure to unlock capture, as it may be flushing due to previous
+      * unlock/stop calls */
+      gst_v4l2_object_unlock_stop (self->v4l2output);
+      gst_v4l2_object_unlock_stop (self->v4l2capture);
+
+      if (!gst_buffer_pool_set_active (pool, TRUE))
         goto activate_failed;
     }
 
-    /* Ensure to unlock capture, as it may be flushing due to previous
-     * unlock/stop calls */
-    gst_v4l2_object_unlock_stop (self->v4l2output);
-    gst_v4l2_object_unlock_stop (self->v4l2capture);
-
-    if (!gst_buffer_pool_set_active (pool, TRUE))
-      goto activate_failed;
-
     GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
     GST_LOG_OBJECT (decoder, "Passing buffer with system frame number %u",
         processed ? frame->system_frame_number : 0);
@@ -1204,7 +1208,8 @@ gst_v4l2_video_dec_handle_frame (GstVideoDecoder * decoder,
     gst_buffer_unref (codec_data);
 
     /* Only wait for source change if the formats supports it */
-    if (!GST_V4L2_IS_ACTIVE (self->v4l2capture) &&
+    /* No need to wait for source change after seek */
+    if (!GST_V4L2_IS_ACTIVE (self->v4l2capture) && !seek &&
         self->v4l2output->fmtdesc->flags & V4L2_FMT_FLAG_DYN_RESOLUTION) {
       gst_v4l2_object_unlock_stop (self->v4l2capture);
       self->wait_for_source_change = TRUE;
-- 
2.34.1


From 75e2ec6c8cea1f302ac2a254262cd1a0e2a54441 Mon Sep 17 00:00:00 2001
From: Hou Qi <qi.hou@nxp.com>
Date: Mon, 2 Sep 2024 15:58:46 +0800
Subject: [PATCH 69/75] MMFMWK-9415 v4l2videoenc: unref buffer pool after usage
 properly

upstream status: pending
part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7435>
---
 sys/v4l2/gstv4l2videoenc.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/sys/v4l2/gstv4l2videoenc.c b/sys/v4l2/gstv4l2videoenc.c
index f886150f8..2e5bde0b1 100644
--- a/sys/v4l2/gstv4l2videoenc.c
+++ b/sys/v4l2/gstv4l2videoenc.c
@@ -845,9 +845,9 @@ gst_v4l2_video_enc_handle_frame (GstVideoEncoder * encoder,
           gst_object_unref (opool);
         goto activate_failed;
       }
-      if (opool)
-        gst_object_unref (opool);
     }
+    if (opool)
+      gst_object_unref (opool);
   }
 
   if (task_state == GST_TASK_STOPPED || task_state == GST_TASK_PAUSED) {
-- 
2.34.1


From a56cd091b67d02697d10022a679f47a1ed82301d Mon Sep 17 00:00:00 2001
From: Hou Qi <qi.hou@nxp.com>
Date: Wed, 21 Aug 2024 10:10:35 +0800
Subject: [PATCH 70/75] LF-13239 v4l2bufferpool: decrease copy_threshold to
 avoid buffer copy

When transcoding, encodebin doesn't provide allocation parameter, then
decoder enable copy threshold. If driver is running low on buffers,
which means the number of buffers queued in driver is less than this
threshold, decoder needs to allocate one new capture buffer.

For drivers that support CREATE_BUFS, decoder allocates one DMA buffer
and queue it to driver. For drivers that doesn't support CREATE_BUFS
such as 8MP, decoder allocates one MMAP buffer and copy the dequeued
DMA buffer to it, then requeue DMA buffer to driver. Encoder will drop
this MMAP buffer as it's already in dmabuf_import mode when do
transcoding, which causes low performance.

To fix it, need to decrease the copy_threshold to avoid buffer copy.
---
 sys/v4l2/gstv4l2bufferpool.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sys/v4l2/gstv4l2bufferpool.c b/sys/v4l2/gstv4l2bufferpool.c
index 6d82d6d78..3fa35344d 100644
--- a/sys/v4l2/gstv4l2bufferpool.c
+++ b/sys/v4l2/gstv4l2bufferpool.c
@@ -884,7 +884,7 @@ gst_v4l2_buffer_pool_start (GstBufferPool * bpool)
         GST_WARNING_OBJECT (pool,
             "Uncertain or not enough buffers, enabling copy threshold");
         min_buffers = count;
-        copy_threshold = min_latency;
+        copy_threshold = GST_V4L2_MIN_BUFFERS (obj);
       }
 
       break;
-- 
2.34.1


From d5342e6d01c5c77d3c4a7743b965ad4eee1e5c83 Mon Sep 17 00:00:00 2001
From: Haihua Hu <jared.hu@nxp.com>
Date: Fri, 13 Sep 2024 16:55:34 +0900
Subject: [PATCH 71/75] LF-13494 v4l2: set min_buffers to 2 if driver didn't
 provide this value

This is workaround to fix camera preview performance issue on imx95
currently isi capture driver didn't implement below cid which can
provide this value to userspace, if use default 0, our plugin only
will add 4 extra buffers, it is not enough to run stream at 60fps.
waylandsink will hold 2 buffers, one for showing and one for last
buffer, only left 2 buffer inside capture driver.

So set the default min_buffers to 2 to avoid performance drop

V4L2_CID_MIN_BUFFERS_FOR_CAPTURE  //get min_buffers via this cid
---
 sys/v4l2/gstv4l2object.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c
index 42bdd0476..2d831b0ff 100644
--- a/sys/v4l2/gstv4l2object.c
+++ b/sys/v4l2/gstv4l2object.c
@@ -894,7 +894,7 @@ gst_v4l2_get_driver_min_buffers (GstV4l2Object * v4l2object)
         "driver requires a minimum of %d buffers", control.value);
     v4l2object->min_buffers = control.value;
   } else {
-    v4l2object->min_buffers = 0;
+    v4l2object->min_buffers = 2;
   }
 }
 
-- 
2.34.1


From 202336fd655c8c48e2e30cac4085a8875250d840 Mon Sep 17 00:00:00 2001
From: Haihua Hu <jared.hu@nxp.com>
Date: Thu, 26 Sep 2024 17:31:26 +0900
Subject: [PATCH 72/75] Add SCR.txt and LICENSE.txt for gstreamer 1.24.7

---
 LICENSE.txt | 503 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 SCR.txt     |   9 +
 2 files changed, 512 insertions(+)
 create mode 100644 LICENSE.txt
 create mode 100644 SCR.txt

diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 000000000..efce2a87c
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,503 @@
+		  GNU LESSER GENERAL PUBLIC LICENSE
+		       Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+     51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+		  GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+  
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+			    NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
+
diff --git a/SCR.txt b/SCR.txt
new file mode 100644
index 000000000..38d1325ca
--- /dev/null
+++ b/SCR.txt
@@ -0,0 +1,9 @@
+Package:                     gst-plugins-good.git
+Version:                     1.24.7.imx
+Outgoing License:            LGPL-2.1
+License File:                LICENSE.txt
+Type of Content:             source
+Description and comments:    Open Source Multimedia Farmework
+Release Location:            https://github.com/nxp-imx/gstreamer -b lf-6.6.36-2.1.0
+Origin:                      NXP (LGPL-2.1)
+                             GStreamer (LGPL-2.1+) - http://gstreamer.freedesktop.org/src/gstreamer/
-- 
2.34.1


From e48e8164f711e3eb3f9e93d68869b9ec7f16d8ec Mon Sep 17 00:00:00 2001
From: Hou Qi <qi.hou@nxp.com>
Date: Thu, 17 Oct 2024 14:01:49 +0800
Subject: [PATCH 73/75] Update release branch in SCR.txt to lf-6.6.52-2.2.0

---
 SCR.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/SCR.txt b/SCR.txt
index 38d1325ca..6be4119bb 100644
--- a/SCR.txt
+++ b/SCR.txt
@@ -4,6 +4,6 @@ Outgoing License:            LGPL-2.1
 License File:                LICENSE.txt
 Type of Content:             source
 Description and comments:    Open Source Multimedia Farmework
-Release Location:            https://github.com/nxp-imx/gstreamer -b lf-6.6.36-2.1.0
+Release Location:            https://github.com/nxp-imx/gstreamer -b lf-6.6.52-2.2.0
 Origin:                      NXP (LGPL-2.1)
                              GStreamer (LGPL-2.1+) - http://gstreamer.freedesktop.org/src/gstreamer/
-- 
2.34.1


From 06f77d9de9225738b54c9ae7632a24029a1cff42 Mon Sep 17 00:00:00 2001
From: Hou Qi <qi.hou@nxp.com>
Date: Tue, 22 Oct 2024 08:35:01 +0800
Subject: [PATCH 74/75] LF-13169 v4l2: skip pollerr if capture queue has not
 set up

For streams whose video formats are xvid and mpeg4, there is no
corresponding parser to drop the non-I frames before first IDR
frame. Before parsing the sequence header in first IDR, capture
is polling to wait source change event with capture off and capture
queue empty. Output queue may be empty if buffer is consumed before
more buffers queued. Driver reports pollerr if both queues are
empty or off, then gstreamer exits unexpectedly.

Since driver reverts "LF-13169: mxc: vpu: hantro_v4l2: avoid pollerr
before sequence header parsed", gstreamer needs to skip pollerr if
capture queue has not setup yet.

/mnt/streams/ttVector/SHAVectors/XvidDec/Conformance/ASP/Xvid_ASP5_624x352_23.976_2191_a_mp3_44_743_2_1st-key-frame-is-the-42th-frame_16.Alias5x01ProphetFive.avi
/mnt/streams/ttVector/SHAVectors/SOWT/Conformance/Mpeg4_ASP3_1280x720_30_4958_SOWT_48_1536_2_Kaleidoscope.mov
/mnt/streams/ttVector/SHAVectors/Metadata/MP4/MP4/AAC_44_224kbps_LoveAndTheCity_ARTWORK.mp4
---
 sys/v4l2/gstv4l2object.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c
index 2d831b0ff..492fb3fa0 100644
--- a/sys/v4l2/gstv4l2object.c
+++ b/sys/v4l2/gstv4l2object.c
@@ -6192,8 +6192,18 @@ again:
     }
   }
 
-  if (gst_poll_fd_has_error (v4l2object->poll, &v4l2object->pollfd))
-    goto select_error;
+  if (gst_poll_fd_has_error (v4l2object->poll, &v4l2object->pollfd)) {
+    GstBufferPool *pool = gst_v4l2_object_get_buffer_pool (v4l2object);
+    if (V4L2_TYPE_IS_OUTPUT (v4l2object->type) || (pool && GST_V4L2_BUFFER_POOL_IS_STREAMING (pool))) {
+      if (pool)
+        gst_object_unref (pool);
+      goto select_error;
+    } else {
+      if (pool)
+        gst_object_unref (pool);
+      goto again;
+    }
+  }
 
   /* PRI is used to signal that events are available */
   if (gst_poll_fd_has_pri (v4l2object->poll, &v4l2object->pollfd)) {
-- 
2.34.1


From 33b2732b873758a302064818b35dcad41b5bbc14 Mon Sep 17 00:00:00 2001
From: Hou Qi <qi.hou@nxp.com>
Date: Tue, 22 Oct 2024 13:33:02 +0800
Subject: [PATCH 75/75] MMFMWK-9434 v4l2allocator: respect v4l2 plane's
 bytesused calculated by import_dmabuf

When libcamerasrc is connected to v4l2 encoder, gstreamer first update
encoder sink's v4l2 planes by import_dmabuf, then queue buffer to vpu
driver. Current code always updates v4l2 plane's bytesused according to
memory block when qbuf.

For ap1302 libcamerasrc on imx95, if setting format as NV12, buffer
has 2 memory blocks but shares 1 fd. v4l2 plane's bytesused is updated
to a different value when qbuf. So need to respect v4l2 plane's
bytesused calculated by import_dmabuf.
---
 sys/v4l2/gstv4l2allocator.c | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/sys/v4l2/gstv4l2allocator.c b/sys/v4l2/gstv4l2allocator.c
index 15d7bb969..a37dc4c7e 100644
--- a/sys/v4l2/gstv4l2allocator.c
+++ b/sys/v4l2/gstv4l2allocator.c
@@ -1336,12 +1336,14 @@ gst_v4l2_allocator_qbuf (GstV4l2Allocator * allocator,
   g_return_val_if_fail (g_atomic_int_get (&allocator->active), FALSE);
 
   /* update sizes */
-  if (V4L2_TYPE_IS_MULTIPLANAR (obj->type)) {
-    for (i = 0; i < group->n_mem; i++)
-      group->planes[i].bytesused =
-          gst_memory_get_sizes (group->mem[i], NULL, NULL);
-  } else {
-    group->buffer.bytesused = gst_memory_get_sizes (group->mem[0], NULL, NULL);
+  if (obj->mode != GST_V4L2_IO_DMABUF_IMPORT) {
+    if (V4L2_TYPE_IS_MULTIPLANAR (obj->type)) {
+      for (i = 0; i < group->n_mem; i++)
+        group->planes[i].bytesused =
+            gst_memory_get_sizes (group->mem[i], NULL, NULL);
+    } else {
+      group->buffer.bytesused = gst_memory_get_sizes (group->mem[0], NULL, NULL);
+    }
   }
 
   /* Ensure the memory will stay around and is RO */
-- 
2.34.1

