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
This commit is contained in:
Guillaume Desmottes 2017-12-29 11:59:36 +01:00 committed by Nicolas Dufresne
parent 0f702d0503
commit 2ca3cf5cfa
4 changed files with 93 additions and 2 deletions

View 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

View 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++;

View 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;

View 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,