summaryrefslogtreecommitdiff
path: root/omx/gstomxvideoenc.c
diff options
context:
space:
mode:
Diffstat (limited to 'omx/gstomxvideoenc.c')
-rw-r--r--omx/gstomxvideoenc.c484
1 files changed, 385 insertions, 99 deletions
diff --git a/omx/gstomxvideoenc.c b/omx/gstomxvideoenc.c
index a399c07..1e5ddea 100644
--- a/omx/gstomxvideoenc.c
+++ b/omx/gstomxvideoenc.c
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
* Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
+ * Copyright (c) 2013-2015, NVIDIA CORPORATION. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -31,28 +32,28 @@
GST_DEBUG_CATEGORY_STATIC (gst_omx_video_enc_debug_category);
#define GST_CAT_DEFAULT gst_omx_video_enc_debug_category
-#define GST_TYPE_OMX_VIDEO_ENC_CONTROL_RATE (gst_omx_video_enc_control_rate_get_type ())
+#define GST_TYPE_OMX_VID_ENC_RCMODE (gst_omx_videnc_rc_mode_get_type ())
static GType
-gst_omx_video_enc_control_rate_get_type (void)
+gst_omx_videnc_rc_mode_get_type (void)
{
- static GType qtype = 0;
-
- if (qtype == 0) {
- static const GEnumValue values[] = {
- {OMX_Video_ControlRateDisable, "Disable", "disable"},
- {OMX_Video_ControlRateVariable, "Variable", "variable"},
- {OMX_Video_ControlRateConstant, "Constant", "constant"},
- {OMX_Video_ControlRateVariableSkipFrames, "Variable Skip Frames",
- "variable-skip-frames"},
- {OMX_Video_ControlRateConstantSkipFrames, "Constant Skip Frames",
- "constant-skip-frames"},
- {0xffffffff, "Component Default", "default"},
- {0, NULL, NULL}
- };
-
- qtype = g_enum_register_static ("GstOMXVideoEncControlRate", values);
+ static volatile gsize rcmode_type_type = 0;
+ static const GEnumValue rcmode_type[] = {
+ {NVX_VIDEO_RateControlMode_CBR, "GST_OMX_VIDENC_RCMODE_TYPE_CONSTANT",
+ "cbr"},
+ {NVX_VIDEO_RateControlMode_VBR, "GST_OMX_VIDENC_RCMODE_TYPE_VARIABLE",
+ "vbr"},
+ {NVX_VIDEO_RateControlMode_VBR2, "GST_OMX_VIDENC_RCMODE_TYPE_VARIABLE2",
+ "vbr2"},
+ {0, NULL, NULL}
+ };
+
+ if (g_once_init_enter (&rcmode_type_type)) {
+ GType tmp =
+ g_enum_register_static ("GstOmxVideoEncRCModeType", rcmode_type);
+ g_once_init_leave (&rcmode_type_type, tmp);
}
- return qtype;
+
+ return (GType) rcmode_type_type;
}
typedef struct _BufferIdentification BufferIdentification;
@@ -101,22 +102,35 @@ static GstFlowReturn gst_omx_video_enc_drain (GstOMXVideoEnc * self,
static GstFlowReturn gst_omx_video_enc_handle_output_frame (GstOMXVideoEnc *
self, GstOMXPort * port, GstOMXBuffer * buf, GstVideoCodecFrame * frame);
+static GstCaps *gst_omx_video_enc_negotiate_caps (GstVideoEncoder * encoder,
+ GstCaps * caps, GstCaps * filter);
+
+static void
+gst_omx_video_enc_check_nvfeatures (GstOMXVideoEnc * self,
+ GstVideoCodecState * state);
+
enum
{
PROP_0,
- PROP_CONTROL_RATE,
- PROP_TARGET_BITRATE,
+ PROP_RC_MODE,
+ PROP_BITRATE,
PROP_QUANT_I_FRAMES,
PROP_QUANT_P_FRAMES,
- PROP_QUANT_B_FRAMES
+ PROP_QUANT_B_FRAMES,
+ PROP_INTRA_FRAME_INTERVAL
};
/* FIXME: Better defaults */
-#define GST_OMX_VIDEO_ENC_CONTROL_RATE_DEFAULT (0xffffffff)
-#define GST_OMX_VIDEO_ENC_TARGET_BITRATE_DEFAULT (0xffffffff)
+#define DEFAULT_RC_MODE NVX_VIDEO_RateControlMode_VBR2
+#define GST_OMX_VIDEO_ENC_BITRATE_DEFAULT (4000000)
#define GST_OMX_VIDEO_ENC_QUANT_I_FRAMES_DEFAULT (0xffffffff)
#define GST_OMX_VIDEO_ENC_QUANT_P_FRAMES_DEFAULT (0xffffffff)
#define GST_OMX_VIDEO_ENC_QUANT_B_FRAMES_DEFAULT (0xffffffff)
+#define DEFAULT_INTRA_FRAME_INTERVAL 60
+
+#ifdef USE_OMX_TARGET_TEGRA
+#define ENCODER_CONF_LOCATION "/etc/enctune.conf"
+#endif
/* class initialization */
@@ -127,6 +141,10 @@ enum
G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GstOMXVideoEnc, gst_omx_video_enc,
GST_TYPE_VIDEO_ENCODER, DEBUG_INIT);
+#ifdef USE_OMX_TARGET_TEGRA
+#define FORMATS "I420, NV12"
+#endif
+
static void
gst_omx_video_enc_class_init (GstOMXVideoEncClass * klass)
{
@@ -139,18 +157,17 @@ gst_omx_video_enc_class_init (GstOMXVideoEncClass * klass)
gobject_class->set_property = gst_omx_video_enc_set_property;
gobject_class->get_property = gst_omx_video_enc_get_property;
- g_object_class_install_property (gobject_class, PROP_CONTROL_RATE,
- g_param_spec_enum ("control-rate", "Control Rate",
- "Bitrate control method",
- GST_TYPE_OMX_VIDEO_ENC_CONTROL_RATE,
- GST_OMX_VIDEO_ENC_CONTROL_RATE_DEFAULT,
+ g_object_class_install_property (gobject_class, PROP_RC_MODE,
+ g_param_spec_enum ("rc-mode", "rc-mode",
+ "Encoding rate control mode",
+ GST_TYPE_OMX_VID_ENC_RCMODE, DEFAULT_RC_MODE,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
GST_PARAM_MUTABLE_READY));
- g_object_class_install_property (gobject_class, PROP_TARGET_BITRATE,
- g_param_spec_uint ("target-bitrate", "Target Bitrate",
- "Target bitrate (0xffffffff=component default)",
- 0, G_MAXUINT, GST_OMX_VIDEO_ENC_TARGET_BITRATE_DEFAULT,
+ g_object_class_install_property (gobject_class, PROP_BITRATE,
+ g_param_spec_uint ("bitrate", "Target Bitrate",
+ "Target bitrate",
+ 0, G_MAXUINT, GST_OMX_VIDEO_ENC_BITRATE_DEFAULT,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
GST_PARAM_MUTABLE_PLAYING));
@@ -175,6 +192,13 @@ gst_omx_video_enc_class_init (GstOMXVideoEncClass * klass)
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
GST_PARAM_MUTABLE_READY));
+ g_object_class_install_property (gobject_class, PROP_INTRA_FRAME_INTERVAL,
+ g_param_spec_uint ("iframeinterval", "Intra Frame interval",
+ "Encoding Intra Frame occurance frequency",
+ 0, G_MAXUINT, DEFAULT_INTRA_FRAME_INTERVAL,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+ GST_PARAM_MUTABLE_READY));
+
element_class->change_state =
GST_DEBUG_FUNCPTR (gst_omx_video_enc_change_state);
@@ -193,7 +217,16 @@ gst_omx_video_enc_class_init (GstOMXVideoEncClass * klass)
video_encoder_class->getcaps = GST_DEBUG_FUNCPTR (gst_omx_video_enc_getcaps);
klass->cdata.type = GST_OMX_COMPONENT_TYPE_FILTER;
- klass->cdata.default_sink_template_caps = "video/x-raw, "
+ klass->cdata.default_sink_template_caps = "video/x-raw(memory:NVMM), "
+#ifdef USE_OMX_TARGET_TEGRA
+ "format = (string) { " FORMATS " }, "
+#endif
+ "width = " GST_VIDEO_SIZE_RANGE ", "
+ "height = " GST_VIDEO_SIZE_RANGE ", " "framerate = " GST_VIDEO_FPS_RANGE
+ ";" "video/x-raw, "
+#ifdef USE_OMX_TARGET_TEGRA
+ "format = (string) { " FORMATS " }, "
+#endif
"width = " GST_VIDEO_SIZE_RANGE ", "
"height = " GST_VIDEO_SIZE_RANGE ", " "framerate = " GST_VIDEO_FPS_RANGE;
@@ -204,11 +237,12 @@ gst_omx_video_enc_class_init (GstOMXVideoEncClass * klass)
static void
gst_omx_video_enc_init (GstOMXVideoEnc * self)
{
- self->control_rate = GST_OMX_VIDEO_ENC_CONTROL_RATE_DEFAULT;
- self->target_bitrate = GST_OMX_VIDEO_ENC_TARGET_BITRATE_DEFAULT;
+ self->bitrate = GST_OMX_VIDEO_ENC_BITRATE_DEFAULT;
+ self->rc_mode = DEFAULT_RC_MODE;
self->quant_i_frames = GST_OMX_VIDEO_ENC_QUANT_I_FRAMES_DEFAULT;
self->quant_p_frames = GST_OMX_VIDEO_ENC_QUANT_P_FRAMES_DEFAULT;
self->quant_b_frames = GST_OMX_VIDEO_ENC_QUANT_B_FRAMES_DEFAULT;
+ self->hw_path = FALSE;
g_mutex_init (&self->drain_lock);
g_cond_init (&self->drain_cond);
@@ -270,50 +304,36 @@ gst_omx_video_enc_open (GstVideoEncoder * encoder)
{
OMX_ERRORTYPE err;
- if (self->control_rate != 0xffffffff || self->target_bitrate != 0xffffffff) {
- OMX_VIDEO_PARAM_BITRATETYPE bitrate_param;
+#ifdef USE_OMX_TARGET_TEGRA
- GST_OMX_INIT_STRUCT (&bitrate_param);
- bitrate_param.nPortIndex = self->enc_out_port->index;
+ OMX_INDEXTYPE eIndex;
+ NVX_PARAM_TEMPFILEPATH enc_conf_loc;
+ gchar *location = g_strdup (ENCODER_CONF_LOCATION);
- err = gst_omx_component_get_parameter (self->enc,
- OMX_IndexParamVideoBitrate, &bitrate_param);
+ GST_DEBUG_OBJECT (self, "Setting encoder to use default configurations");
- if (err == OMX_ErrorNone) {
-#ifdef USE_OMX_TARGET_RPI
- /* FIXME: Workaround for RPi returning garbage for this parameter */
- if (bitrate_param.nVersion.nVersion == 0) {
- GST_OMX_INIT_STRUCT (&bitrate_param);
- bitrate_param.nPortIndex = self->enc_out_port->index;
- }
-#endif
- if (self->control_rate != 0xffffffff)
- bitrate_param.eControlRate = self->control_rate;
- if (self->target_bitrate != 0xffffffff)
- bitrate_param.nTargetBitrate = self->target_bitrate;
+ err = gst_omx_component_get_index (self->enc,
+ (char *) NVX_INDEX_PARAM_TEMPFILEPATH, &eIndex);
+ if (err == OMX_ErrorNone) {
+ if (location != NULL) {
+ GST_OMX_INIT_STRUCT (&enc_conf_loc);
+ enc_conf_loc.pTempPath = location;
err =
- gst_omx_component_set_parameter (self->enc,
- OMX_IndexParamVideoBitrate, &bitrate_param);
- if (err == OMX_ErrorUnsupportedIndex) {
- GST_WARNING_OBJECT (self,
- "Setting a bitrate not supported by the component");
- } else if (err == OMX_ErrorUnsupportedSetting) {
- GST_WARNING_OBJECT (self,
- "Setting bitrate settings %u %u not supported by the component",
- self->control_rate, self->target_bitrate);
- } else if (err != OMX_ErrorNone) {
- GST_ERROR_OBJECT (self,
- "Failed to set bitrate parameters: %s (0x%08x)",
- gst_omx_error_to_string (err), err);
- return FALSE;
- }
- } else {
- GST_ERROR_OBJECT (self, "Failed to get bitrate parameters: %s (0x%08x)",
- gst_omx_error_to_string (err), err);
+ gst_omx_component_set_parameter (self->enc, eIndex, &enc_conf_loc);
}
+ } else {
+ GST_WARNING_OBJECT (self, "Coudn't get extension index for %s",
+ (char *) NVX_INDEX_PARAM_TEMPFILEPATH);
}
+ if (err != OMX_ErrorNone)
+ GST_WARNING_OBJECT (self, "Couldn't set configurations");
+
+ g_free (location);
+
+#endif
+
if (self->quant_i_frames != 0xffffffff ||
self->quant_p_frames != 0xffffffff ||
self->quant_b_frames != 0xffffffff) {
@@ -422,18 +442,18 @@ gst_omx_video_enc_set_property (GObject * object, guint prop_id,
GstOMXVideoEnc *self = GST_OMX_VIDEO_ENC (object);
switch (prop_id) {
- case PROP_CONTROL_RATE:
- self->control_rate = g_value_get_enum (value);
+ case PROP_RC_MODE:
+ self->rc_mode = g_value_get_enum (value);
break;
- case PROP_TARGET_BITRATE:
- self->target_bitrate = g_value_get_uint (value);
+ case PROP_BITRATE:
+ self->bitrate = g_value_get_uint (value);
if (self->enc) {
OMX_VIDEO_CONFIG_BITRATETYPE config;
OMX_ERRORTYPE err;
GST_OMX_INIT_STRUCT (&config);
config.nPortIndex = self->enc_out_port->index;
- config.nEncodeBitrate = self->target_bitrate;
+ config.nEncodeBitrate = self->bitrate;
err =
gst_omx_component_set_config (self->enc,
OMX_IndexConfigVideoBitrate, &config);
@@ -452,6 +472,9 @@ gst_omx_video_enc_set_property (GObject * object, guint prop_id,
case PROP_QUANT_B_FRAMES:
self->quant_b_frames = g_value_get_uint (value);
break;
+ case PROP_INTRA_FRAME_INTERVAL:
+ self->iframeinterval = g_value_get_uint (value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -465,11 +488,11 @@ gst_omx_video_enc_get_property (GObject * object, guint prop_id, GValue * value,
GstOMXVideoEnc *self = GST_OMX_VIDEO_ENC (object);
switch (prop_id) {
- case PROP_CONTROL_RATE:
- g_value_set_enum (value, self->control_rate);
+ case PROP_RC_MODE:
+ g_value_set_enum (value, self->rc_mode);
break;
- case PROP_TARGET_BITRATE:
- g_value_set_uint (value, self->target_bitrate);
+ case PROP_BITRATE:
+ g_value_set_uint (value, self->bitrate);
break;
case PROP_QUANT_I_FRAMES:
g_value_set_uint (value, self->quant_i_frames);
@@ -480,6 +503,9 @@ gst_omx_video_enc_get_property (GObject * object, guint prop_id, GValue * value,
case PROP_QUANT_B_FRAMES:
g_value_set_uint (value, self->quant_b_frames);
break;
+ case PROP_INTRA_FRAME_INTERVAL:
+ g_value_set_uint (value, self->iframeinterval);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -662,13 +688,17 @@ gst_omx_video_enc_handle_output_frame (GstOMXVideoEnc * self, GstOMXPort * port,
GST_DEBUG_OBJECT (self, "Handling codec data");
caps = klass->get_caps (self, self->enc_out_port, self->input_state);
- codec_data = gst_buffer_new_and_alloc (buf->omx_buf->nFilledLen);
+ if (self->codec_data) {
+ codec_data = self->codec_data;
+ } else {
+ codec_data = gst_buffer_new_and_alloc (buf->omx_buf->nFilledLen);
- gst_buffer_map (codec_data, &map, GST_MAP_WRITE);
- memcpy (map.data,
- buf->omx_buf->pBuffer + buf->omx_buf->nOffset,
- buf->omx_buf->nFilledLen);
- gst_buffer_unmap (codec_data, &map);
+ gst_buffer_map (codec_data, &map, GST_MAP_WRITE);
+ memcpy (map.data,
+ buf->omx_buf->pBuffer + buf->omx_buf->nOffset,
+ buf->omx_buf->nFilledLen);
+ gst_buffer_unmap (codec_data, &map);
+ }
state =
gst_video_encoder_set_output_state (GST_VIDEO_ENCODER (self), caps,
self->input_state);
@@ -1099,12 +1129,149 @@ gst_omx_video_enc_get_supported_colorformats (GstOMXVideoEnc * self)
return negotiation_map;
}
+static OMX_ERRORTYPE
+gst_omx_video_enc_reconfigure_output_port (GstOMXVideoEnc * self)
+{
+
+ GstOMXPort *port;
+ OMX_ERRORTYPE err = OMX_ErrorNone;
+
+ port = self->enc_out_port;
+
+ if (!gst_omx_port_is_enabled (port)) {
+ err = gst_omx_port_set_enabled (port, TRUE);
+ if (err != OMX_ErrorNone) {
+ GST_INFO_OBJECT (self,
+ "Failed to enable port: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ goto done;
+ }
+ }
+
+ err = gst_omx_port_allocate_buffers (port);
+ if (err != OMX_ErrorNone)
+ goto done;
+
+ err = gst_omx_port_wait_enabled (port, 5 * GST_SECOND);
+ if (err != OMX_ErrorNone)
+ goto done;
+
+ err = gst_omx_port_populate (port);
+ if (err != OMX_ErrorNone)
+ goto done;
+
+ err = gst_omx_port_mark_reconfigured (port);
+ if (err != OMX_ErrorNone)
+ goto done;
+
+done:
+ return err;
+}
+
+static void
+gst_omx_video_enc_check_nvfeatures (GstOMXVideoEnc * self,
+ GstVideoCodecState * state)
+{
+ GstCapsFeatures *feature;
+
+ feature = gst_caps_get_features (state->caps, 0);
+ if (gst_caps_features_contains (feature, "memory:NVMM")) {
+ OMX_ERRORTYPE err = OMX_ErrorNone;
+ NVX_PARAM_USENVBUFFER param;
+ OMX_INDEXTYPE eIndex;
+
+ GST_DEBUG_OBJECT (self, "Setting encoder to use Nvmm buffer");
+
+ err = gst_omx_component_get_index (self->enc,
+ (char *) NVX_INDEX_CONFIG_USENVBUFFER, &eIndex);
+
+ if (err == OMX_ErrorNone) {
+ GST_OMX_INIT_STRUCT (&param);
+ param.nPortIndex = self->enc_in_port->index;
+ param.bUseNvBuffer = OMX_TRUE;
+ err = gst_omx_component_set_parameter (self->enc, eIndex, &param);
+ } else {
+ GST_WARNING_OBJECT (self, "Coudn't get extension index for %s",
+ (char *) NVX_INDEX_CONFIG_USENVBUFFER);
+ }
+
+ if (err != OMX_ErrorNone) {
+ GST_WARNING_OBJECT (self, "Couldn't use HW Accelerated path");
+ } else {
+ self->hw_path = TRUE;
+ }
+ }
+}
+
+static OMX_ERRORTYPE
+gstomx_set_rc_mode (GstOMXVideoEnc * self)
+{
+ OMX_INDEXTYPE eIndex;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ NVX_PARAM_RATECONTROLMODE oRCMode;
+
+ GST_OMX_INIT_STRUCT (&oRCMode);
+ oRCMode.nPortIndex = 0;
+ eError =
+ gst_omx_component_get_index (self->enc, (gpointer) NVX_INDEX_PARAM_RATECONTROLMODE,
+ &eIndex);
+ if (eError == OMX_ErrorNone) {
+ switch (self->rc_mode) {
+ case NVX_VIDEO_RateControlMode_CBR:
+ oRCMode.eRateCtrlMode = NVX_VIDEO_RateControlMode_CBR;
+ break;
+ case NVX_VIDEO_RateControlMode_VBR:
+ oRCMode.eRateCtrlMode = NVX_VIDEO_RateControlMode_VBR;
+ break;
+ case NVX_VIDEO_RateControlMode_VBR2:
+ oRCMode.eRateCtrlMode = NVX_VIDEO_RateControlMode_VBR2;
+ break;
+ default:
+ oRCMode.eRateCtrlMode = NVX_VIDEO_RateControlMode_VBR2;
+ break;
+ }
+
+ eError = gst_omx_component_set_parameter (self->enc, eIndex, &oRCMode);
+ if (eError != OMX_ErrorNone)
+ GST_ERROR_OBJECT (self,
+ "Failed to set rc_mode parameter: %s (0x%08x)",
+ gst_omx_error_to_string (eError), eError);
+ }
+ return eError;
+}
+
+static OMX_ERRORTYPE
+gstomx_set_bitrate (GstOMXVideoEnc * self)
+{
+ OMX_VIDEO_CONFIG_BITRATETYPE oBitrate;
+ OMX_ERRORTYPE err = OMX_ErrorNone;
+
+ GST_OMX_INIT_STRUCT (&oBitrate);
+
+ err =
+ gst_omx_component_get_config (self->enc,
+ OMX_IndexConfigVideoBitrate, &oBitrate);
+
+ oBitrate.nEncodeBitrate = self->bitrate;
+
+ err =
+ gst_omx_component_set_config (self->enc,
+ OMX_IndexConfigVideoBitrate, &oBitrate);
+ if (err != OMX_ErrorNone)
+ GST_ERROR_OBJECT (self,
+ "Failed to set bitrate parameter: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+
+ return err;
+}
+
static gboolean
gst_omx_video_enc_set_format (GstVideoEncoder * encoder,
GstVideoCodecState * state)
{
GstOMXVideoEnc *self;
GstOMXVideoEncClass *klass;
+ OMX_ERRORTYPE err;
gboolean needs_disable = FALSE;
OMX_PARAM_PORTDEFINITIONTYPE port_def;
GstVideoInfo *info = &state->info;
@@ -1117,6 +1284,7 @@ gst_omx_video_enc_set_format (GstVideoEncoder * encoder,
gst_video_format_to_string (info->finfo->format));
gst_omx_port_get_port_definition (self->enc_in_port, &port_def);
+ gst_omx_video_enc_check_nvfeatures (self, state);
needs_disable =
gst_omx_component_get_state (self->enc,
@@ -1242,6 +1410,22 @@ gst_omx_video_enc_set_format (GstVideoEncoder * encoder,
}
}
+ err = gstomx_set_rc_mode (self);
+ if (err != OMX_ErrorNone) {
+ GST_WARNING_OBJECT (self,
+ "Error setting rc_mode %u : %s (0x%08x)",
+ (guint) self->rc_mode, gst_omx_error_to_string (err), err);
+ return FALSE;
+ }
+
+ err = gstomx_set_bitrate (self);
+ if (err != OMX_ErrorNone) {
+ GST_WARNING_OBJECT (self,
+ "Error setting bitrate %u : %s (0x%08x)",
+ (guint) self->bitrate, gst_omx_error_to_string (err), err);
+ return FALSE;
+ }
+
GST_DEBUG_OBJECT (self, "Updating outport port definition");
if (gst_omx_port_update_port_definition (self->enc_out_port,
NULL) != OMX_ErrorNone)
@@ -1287,6 +1471,12 @@ gst_omx_video_enc_set_format (GstVideoEncoder * encoder,
return FALSE;
}
+#ifdef USE_OMX_TARGET_TEGRA
+ /* PortSetting change event comes only if output port has buffers allocated */
+ if (gst_omx_video_enc_reconfigure_output_port (self) != OMX_ErrorNone)
+ return FALSE;
+#endif
+
/* Unset flushing to allow ports to accept data again */
gst_omx_port_set_flushing (self->enc_in_port, 5 * GST_SECOND, FALSE);
gst_omx_port_set_flushing (self->enc_out_port, 5 * GST_SECOND, FALSE);
@@ -1362,7 +1552,12 @@ gst_omx_video_enc_fill_buffer (GstOMXVideoEnc * self, GstBuffer * inbuf,
}
/* Same strides and everything */
- if (gst_buffer_get_size (inbuf) ==
+ /*
+ * If component is using HW acceleration path, No need for this check.
+ * Because contents are not actual data but structures.
+ * We can copy content of buffer directly.
+ */
+ if (self->hw_path || gst_buffer_get_size (inbuf) ==
outbuf->omx_buf->nAllocLen - outbuf->omx_buf->nOffset) {
outbuf->omx_buf->nFilledLen = gst_buffer_get_size (inbuf);
@@ -1662,6 +1857,10 @@ gst_omx_video_enc_handle_frame (GstVideoEncoder * encoder,
gst_buffer_get_size (frame->input_buffer));
self->last_upstream_ts += duration;
}
+#ifdef USE_OMX_TARGET_TEGRA
+ if (self->hw_path)
+ buf->omx_buf->nFlags |= OMX_BUFFERFLAG_RETAIN_OMX_TS;
+#endif
id = g_slice_new0 (BufferIdentification);
id->timestamp = buf->omx_buf->nTimeStamp;
@@ -1829,35 +2028,122 @@ gst_omx_video_enc_propose_allocation (GstVideoEncoder * encoder,
(gst_omx_video_enc_parent_class)->propose_allocation (encoder, query);
}
+GstCaps *
+gst_omx_video_enc_negotiate_caps (GstVideoEncoder * encoder, GstCaps * caps,
+ GstCaps * filter)
+{
+ GstCaps *templ_caps;
+ GstCaps *allowed;
+ GstCaps *fcaps, *filter_caps;
+ GstCapsFeatures *feature;
+ gint i, j;
+
+ /* Allow downstream to specify width/height/framerate/PAR constraints
+ * and forward them upstream for video converters to handle
+ */
+ templ_caps =
+ caps ? gst_caps_ref (caps) :
+ gst_pad_get_pad_template_caps (encoder->sinkpad);
+ allowed = gst_pad_get_allowed_caps (encoder->srcpad);
+
+ if (!allowed || gst_caps_is_empty (allowed) || gst_caps_is_any (allowed)) {
+ fcaps = templ_caps;
+ goto done;
+ }
+
+ GST_LOG_OBJECT (encoder, "template caps %" GST_PTR_FORMAT, templ_caps);
+ GST_LOG_OBJECT (encoder, "allowed caps %" GST_PTR_FORMAT, allowed);
+
+ filter_caps = gst_caps_new_empty ();
+
+ for (i = 0; i < gst_caps_get_size (templ_caps); i++) {
+ GQuark q_name =
+ gst_structure_get_name_id (gst_caps_get_structure (templ_caps, i));
+ gchar *f_name =
+ gst_caps_features_to_string (gst_caps_get_features (templ_caps, i));
+
+ for (j = 0; j < gst_caps_get_size (allowed); j++) {
+ const GstStructure *allowed_s = gst_caps_get_structure (allowed, j);
+ const GValue *val;
+ GstStructure *s;
+
+ s = gst_structure_new_id_empty (q_name);
+ feature = gst_caps_features_new (f_name, NULL);
+ if ((val = gst_structure_get_value (allowed_s, "width")))
+ gst_structure_set_value (s, "width", val);
+ if ((val = gst_structure_get_value (allowed_s, "height")))
+ gst_structure_set_value (s, "height", val);
+ if ((val = gst_structure_get_value (allowed_s, "framerate")))
+ gst_structure_set_value (s, "framerate", val);
+ if ((val = gst_structure_get_value (allowed_s, "pixel-aspect-ratio")))
+ gst_structure_set_value (s, "pixel-aspect-ratio", val);
+
+ filter_caps = gst_caps_merge_structure_full (filter_caps, s, feature);
+ }
+ }
+
+ fcaps = gst_caps_intersect (filter_caps, templ_caps);
+ gst_caps_unref (filter_caps);
+ gst_caps_unref (templ_caps);
+
+ if (filter) {
+ GST_LOG_OBJECT (encoder, "intersecting with %" GST_PTR_FORMAT, filter);
+ filter_caps = gst_caps_intersect (fcaps, filter);
+ gst_caps_unref (fcaps);
+ fcaps = filter_caps;
+ }
+
+done:
+ gst_caps_replace (&allowed, NULL);
+
+ GST_LOG_OBJECT (encoder, "proxy caps %" GST_PTR_FORMAT, fcaps);
+
+ return fcaps;
+}
+
static GstCaps *
gst_omx_video_enc_getcaps (GstVideoEncoder * encoder, GstCaps * filter)
{
GstOMXVideoEnc *self = GST_OMX_VIDEO_ENC (encoder);
GList *negotiation_map = NULL, *l;
GstCaps *comp_supported_caps;
+ GstCaps *ret;
+ GstStructure *str;
+ gint n;
+ GValue list = G_VALUE_INIT;
+ GValue val = G_VALUE_INIT;
if (!self->enc)
- return gst_video_encoder_proxy_getcaps (encoder, NULL, filter);
+ return gst_omx_video_enc_negotiate_caps (encoder, NULL, filter);
negotiation_map = gst_omx_video_enc_get_supported_colorformats (self);
- comp_supported_caps = gst_caps_new_empty ();
+ comp_supported_caps = gst_pad_get_pad_template_caps (encoder->sinkpad);
+ comp_supported_caps = gst_caps_make_writable (comp_supported_caps);
+
+ g_value_init (&list, GST_TYPE_LIST);
+ g_value_init (&val, G_TYPE_STRING);
+
for (l = negotiation_map; l; l = l->next) {
VideoNegotiationMap *map = l->data;
- gst_caps_append_structure (comp_supported_caps,
- gst_structure_new ("video/x-raw",
- "format", G_TYPE_STRING,
- gst_video_format_to_string (map->format), NULL));
+ g_value_set_static_string (&val, gst_video_format_to_string (map->format));
+ gst_value_list_append_value (&list, &val);
}
if (!gst_caps_is_empty (comp_supported_caps)) {
- GstCaps *ret =
- gst_video_encoder_proxy_getcaps (encoder, comp_supported_caps, filter);
-
+ for (n = 0; n < gst_caps_get_size (comp_supported_caps); n++) {
+ str = gst_caps_get_structure (comp_supported_caps, n);
+ gst_structure_set_value (str, "format", &list);
+ }
+ ret =
+ gst_omx_video_enc_negotiate_caps (encoder, comp_supported_caps, filter);
gst_caps_unref (comp_supported_caps);
- return ret;
} else {
gst_caps_unref (comp_supported_caps);
- return gst_video_encoder_proxy_getcaps (encoder, NULL, filter);
+ ret = gst_omx_video_enc_negotiate_caps (encoder, NULL, filter);
}
+
+ g_value_unset (&val);
+ g_value_unset (&list);
+ return ret;
}