omxvideodec: add hack to pass color format from caps to OMX decoder
authorGuillaume Desmottes <guillaume.desmottes@collabora.co.uk>
Fri, 29 Dec 2017 10:59:36 +0000 (11:59 +0100)
committerNicolas Dufresne <nicolas.dufresne@collabora.com>
Tue, 30 Jan 2018 09:23:59 +0000 (09:23 +0000)
This hack tries to pass as much information as possible from caps to the
decoder before it receives any buffer. These information can be used by
the OMX decoder to, for example, pre-allocate its internal buffers
before starting to decode and so reduce its initial latency.

This mechanism is currently supported by the zynqultrascaleplus decoder.

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

config/zynqultrascaleplus/gstomx.conf
omx/gstomx.c
omx/gstomx.h
omx/gstomxvideodec.c

index 3cf179c..57b7622 100644 (file)
@@ -14,7 +14,7 @@ component-name=OMX.allegro.h264.decoder
 in-port-index=0
 out-port-index=1
 rank=257
-hacks=no-disable-outport;pass-profile-to-decoder
+hacks=no-disable-outport;pass-profile-to-decoder;pass-color-format-to-decoder
 
 [omxh265enc]
 type-name=GstOMXH265Enc
@@ -32,4 +32,4 @@ component-name=OMX.allegro.h265.decoder
 in-port-index=0
 out-port-index=1
 rank=257
-hacks=no-disable-outport;pass-profile-to-decoder
+hacks=no-disable-outport;pass-profile-to-decoder;pass-color-format-to-decoder
index 1db1b58..6136089 100644 (file)
@@ -2845,6 +2845,8 @@ gst_omx_parse_hacks (gchar ** hacks)
       hacks_flags |= GST_OMX_HACK_HEIGHT_MULTIPLE_16;
     else if (g_str_equal (*hacks, "pass-profile-to-decoder"))
       hacks_flags |= GST_OMX_HACK_PASS_PROFILE_TO_DECODER;
+    else if (g_str_equal (*hacks, "pass-color-format-to-decoder"))
+      hacks_flags |= GST_OMX_HACK_PASS_COLOR_FORMAT_TO_DECODER;
     else
       GST_WARNING ("Unknown hack: %s", *hacks);
     hacks++;
index bf53444..fecce35 100644 (file)
@@ -166,6 +166,15 @@ G_BEGIN_DECLS
  */
 #define GST_OMX_HACK_PASS_PROFILE_TO_DECODER        G_GUINT64_CONSTANT (0x0000000000000800)
 
+/* If we should pass the color format information from upstream to the
+ * OMX decoder input. This is a violation of the OMX spec as
+ * the eColorFormat field is supposed to only be used if eCompressionFormat is
+ * set to OMX_IMAGE_CodingUnused.
+ * Do this as a platform specific hack for OMX implementation which may use
+ * this information to pre-allocate internal buffers for example.
+ */
+#define GST_OMX_HACK_PASS_COLOR_FORMAT_TO_DECODER        G_GUINT64_CONSTANT (0x0000000000001000)
+
 typedef struct _GstOMXCore GstOMXCore;
 typedef struct _GstOMXPort GstOMXPort;
 typedef enum _GstOMXPortDirection GstOMXPortDirection;
index b53a013..2d97ca5 100644 (file)
@@ -2308,6 +2308,54 @@ gst_omx_video_dec_enable (GstOMXVideoDec * self, GstBuffer * input)
   return TRUE;
 }
 
+static OMX_COLOR_FORMATTYPE
+get_color_format_from_chroma (const gchar * chroma_format,
+    guint bit_depth_luma, guint bit_depth_chroma)
+{
+  if (chroma_format == NULL)
+    goto out;
+
+  if (!g_strcmp0 (chroma_format, "4:0:0") && bit_depth_chroma == 0) {
+    switch (bit_depth_luma) {
+      case 1:
+        return OMX_COLOR_FormatMonochrome;
+      case 2:
+        return OMX_COLOR_FormatL2;
+      case 4:
+        return OMX_COLOR_FormatL4;
+      case 8:
+        return OMX_COLOR_FormatL8;
+      case 16:
+        return OMX_COLOR_FormatL16;
+      case 24:
+        return OMX_COLOR_FormatL24;
+      case 32:
+        return OMX_COLOR_FormatL32;
+    }
+    goto out;
+  }
+
+  if (bit_depth_luma == 8 && bit_depth_chroma == 8) {
+    if (!g_strcmp0 (chroma_format, "4:2:0"))
+      return OMX_COLOR_FormatYUV420SemiPlanar;
+    else if (!g_strcmp0 (chroma_format, "4:2:2"))
+      return OMX_COLOR_FormatYUV422SemiPlanar;
+  }
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+  if (bit_depth_luma == 10 && bit_depth_chroma == 10) {
+    if (!g_strcmp0 (chroma_format, "4:2:0"))
+      return (OMX_COLOR_FORMATTYPE)
+          OMX_ALG_COLOR_FormatYUV420SemiPlanar10bitPacked;
+    else if (!g_strcmp0 (chroma_format, "4:2:2"))
+      return (OMX_COLOR_FORMATTYPE)
+          OMX_ALG_COLOR_FormatYUV422SemiPlanar10bitPacked;
+  }
+#endif
+
+out:
+  return OMX_COLOR_FormatUnused;
+}
+
 static gboolean
 gst_omx_video_dec_set_format (GstVideoDecoder * decoder,
     GstVideoCodecState * state)
@@ -2379,6 +2427,38 @@ gst_omx_video_dec_set_format (GstVideoDecoder * decoder,
   port_def.format.video.nFrameHeight = info->height;
   port_def.format.video.xFramerate = framerate_q16;
 
+  if (klass->cdata.hacks & GST_OMX_HACK_PASS_COLOR_FORMAT_TO_DECODER) {
+    /* Let the decoder know the colar format of the encoded input stream.
+     * It may use it to pre-allocate its internal buffers and so save time when
+     * it will actually start to decode. */
+    GstStructure *s;
+    const gchar *chroma_format;
+    guint bit_depth_luma, bit_depth_chroma;
+
+    s = gst_caps_get_structure (state->caps, 0);
+    chroma_format = gst_structure_get_string (s, "chroma-format");
+    if (s && gst_structure_get_uint (s, "bit-depth-luma", &bit_depth_luma) &&
+        gst_structure_get_uint (s, "bit-depth-chroma", &bit_depth_chroma)) {
+      OMX_COLOR_FORMATTYPE color_format;
+
+      color_format =
+          get_color_format_from_chroma (chroma_format,
+          bit_depth_luma, bit_depth_chroma);
+      if (color_format != OMX_COLOR_FormatUnused) {
+        GST_DEBUG_OBJECT (self, "Setting input eColorFormat to %d",
+            color_format);
+        port_def.format.video.eColorFormat = color_format;
+      } else {
+        GST_WARNING_OBJECT (self,
+            "Unsupported input color format: %s (luma %d bits, chroma %d bits)",
+            chroma_format, bit_depth_luma, bit_depth_chroma);
+      }
+    } else {
+      GST_DEBUG_OBJECT (self,
+          "Input color format info not present in caps, can't pass them to decoder");
+    }
+  }
+
   GST_DEBUG_OBJECT (self, "Setting inport port definition");
 
   if (gst_omx_port_update_port_definition (self->dec_in_port,