h264dec: add hack to pass profile and level to OMX

This information can be useful to zynqultrascaleplus decoders. They may
use this information to reduce startup latency by configuring itself
before receiving the first frames.

We also have a custom OMX extension allowing the decoder to report the
latency. The profile/level information helps it reporting a more
accurate latency earlier.

https://bugzilla.gnome.org/show_bug.cgi?id=783114
This commit is contained in:
Guillaume Desmottes 2017-03-28 16:27:10 +02:00 committed by Olivier Crête
parent 1e570fed17
commit 0aa4c9db4e
4 changed files with 80 additions and 4 deletions

View file

@ -14,4 +14,4 @@ component-name=OMX.allegro.h264.decoder
in-port-index=0
out-port-index=1
rank=257
hacks=no-disable-outport
hacks=no-disable-outport;pass-profile-to-decoder

View file

@ -2508,6 +2508,8 @@ gst_omx_parse_hacks (gchar ** hacks)
hacks_flags |= GST_OMX_HACK_SIGNALS_PREMATURE_EOS;
else if (g_str_equal (*hacks, "height-multiple-16"))
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
GST_WARNING ("Unknown hack: %s", *hacks);
hacks++;

View file

@ -150,6 +150,13 @@ G_BEGIN_DECLS
*/
#define GST_OMX_HACK_HEIGHT_MULTIPLE_16 G_GUINT64_CONSTANT (0x0000000000000200)
/* If we should pass the profile/level information from upstream to the
* OMX decoder. This is a violation of the OMX spec as
* OMX_IndexParamVideoProfileLevelCurrent is supposed to be r-o so
* do it as a platform specific hack.
*/
#define GST_OMX_HACK_PASS_PROFILE_TO_DECODER G_GUINT64_CONSTANT (0x0000000000000800)
typedef struct _GstOMXCore GstOMXCore;
typedef struct _GstOMXPort GstOMXPort;
typedef enum _GstOMXPortDirection GstOMXPortDirection;

View file

@ -25,6 +25,7 @@
#include <gst/gst.h>
#include "gstomxh264dec.h"
#include "gstomxh264utils.h"
GST_DEBUG_CATEGORY_STATIC (gst_omx_h264_dec_debug_category);
#define GST_CAT_DEFAULT gst_omx_h264_dec_debug_category
@ -110,16 +111,82 @@ gst_omx_h264_dec_is_format_change (GstOMXVideoDec * dec,
return FALSE;
}
static gboolean
set_profile_and_level (GstOMXH264Dec * self, GstVideoCodecState * state)
{
OMX_ERRORTYPE err;
OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
const gchar *profile_string, *level_string;
GstStructure *s;
GST_OMX_INIT_STRUCT (&param);
param.nPortIndex = GST_OMX_VIDEO_DEC (self)->dec_in_port->index;
/* Pass profile and level to the decoder if we have both info from the
* caps. */
s = gst_caps_get_structure (state->caps, 0);
profile_string = gst_structure_get_string (s, "profile");
if (!profile_string)
return TRUE;
param.eProfile = gst_omx_h264_utils_get_profile_from_str (profile_string);
if (param.eProfile == OMX_VIDEO_AVCProfileMax)
goto unsupported_profile;
level_string = gst_structure_get_string (s, "level");
if (!level_string)
return TRUE;
param.eLevel = gst_omx_h264_utils_get_level_from_str (level_string);
if (param.eLevel == OMX_VIDEO_AVCLevelMax)
goto unsupported_level;
GST_DEBUG_OBJECT (self, "Set profile (%s) and level (%s) on decoder",
profile_string, level_string);
err =
gst_omx_component_set_parameter (GST_OMX_VIDEO_DEC (self)->dec,
OMX_IndexParamVideoProfileLevelCurrent, &param);
if (err == OMX_ErrorUnsupportedIndex) {
GST_WARNING_OBJECT (self,
"Setting profile/level not supported by component");
} else if (err != OMX_ErrorNone) {
GST_ERROR_OBJECT (self,
"Error setting profile %u and level %u: %s (0x%08x)",
(guint) param.eProfile, (guint) param.eLevel,
gst_omx_error_to_string (err), err);
return FALSE;
}
return TRUE;
unsupported_profile:
GST_ERROR_OBJECT (self, "Unsupported profile %s", profile_string);
return FALSE;
unsupported_level:
GST_ERROR_OBJECT (self, "Unsupported level %s", level_string);
return FALSE;
}
static gboolean
gst_omx_h264_dec_set_format (GstOMXVideoDec * dec, GstOMXPort * port,
GstVideoCodecState * state)
{
gboolean ret;
GstOMXVideoDecClass *klass = GST_OMX_VIDEO_DEC_GET_CLASS (dec);
OMX_PARAM_PORTDEFINITIONTYPE port_def;
OMX_ERRORTYPE err;
gst_omx_port_get_port_definition (port, &port_def);
port_def.format.video.eCompressionFormat = OMX_VIDEO_CodingAVC;
ret = gst_omx_port_update_port_definition (port, &port_def) == OMX_ErrorNone;
err = gst_omx_port_update_port_definition (port, &port_def);
if (err != OMX_ErrorNone)
return FALSE;
return ret;
if (klass->cdata.hacks & GST_OMX_HACK_PASS_PROFILE_TO_DECODER) {
if (!set_profile_and_level (GST_OMX_H264_DEC (dec), state))
return FALSE;
}
return TRUE;
}