summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuillaume Desmottes <guillaume.desmottes@collabora.co.uk>2017-12-29 11:59:36 +0100
committerNicolas Dufresne <nicolas.dufresne@collabora.com>2018-01-30 09:23:59 +0000
commit2ca3cf5cfa47ca367bd58005a2303fb6b3a1609a (patch)
tree9d71d22ae0f6e4e1824d9529716ec0285512bb4d
parent0f702d050301f847635f99bd9241852dabedab21 (diff)
downloadgst-omx-2ca3cf5cfa47ca367bd58005a2303fb6b3a1609a.tar.gz
omxvideodec: add hack to pass color format from caps to OMX decoder
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
-rw-r--r--config/zynqultrascaleplus/gstomx.conf4
-rw-r--r--omx/gstomx.c2
-rw-r--r--omx/gstomx.h9
-rw-r--r--omx/gstomxvideodec.c80
4 files changed, 93 insertions, 2 deletions
diff --git a/config/zynqultrascaleplus/gstomx.conf b/config/zynqultrascaleplus/gstomx.conf
index 3cf179c..57b7622 100644
--- a/config/zynqultrascaleplus/gstomx.conf
+++ b/config/zynqultrascaleplus/gstomx.conf
@@ -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
diff --git a/omx/gstomx.c b/omx/gstomx.c
index 1db1b58..6136089 100644
--- a/omx/gstomx.c
+++ b/omx/gstomx.c
@@ -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++;
diff --git a/omx/gstomx.h b/omx/gstomx.h
index bf53444..fecce35 100644
--- a/omx/gstomx.h
+++ b/omx/gstomx.h
@@ -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;
diff --git a/omx/gstomxvideodec.c b/omx/gstomxvideodec.c
index b53a013..2d97ca5 100644
--- a/omx/gstomxvideodec.c
+++ b/omx/gstomxvideodec.c
@@ -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,