From 2ca3cf5cfa47ca367bd58005a2303fb6b3a1609a Mon Sep 17 00:00:00 2001 From: Guillaume Desmottes Date: Fri, 29 Dec 2017 11:59:36 +0100 Subject: [PATCH] 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 --- config/zynqultrascaleplus/gstomx.conf | 4 +- omx/gstomx.c | 2 + omx/gstomx.h | 9 +++ omx/gstomxvideodec.c | 80 +++++++++++++++++++++++++++ 4 files changed, 93 insertions(+), 2 deletions(-) diff --git a/config/zynqultrascaleplus/gstomx.conf b/config/zynqultrascaleplus/gstomx.conf index 3cf179c38b..57b7622525 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 1db1b58384..6136089e74 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 bf5344440f..fecce35699 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 b53a0132b2..2d97ca53b0 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,