summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuillaume Desmottes <guillaume.desmottes@collabora.com>2020-02-06 10:11:13 +0530
committerGuillaume Desmottes <guillaume.desmottes@collabora.com>2020-02-27 04:05:48 +0000
commit1c3f39c4d784465c3da79d58e57091b96c6e4ddf (patch)
tree7985798188cbb989f0565cc278ea010883e48e2f
parent3c45c8ecbebfa284ef6706c28acbceef24b564d0 (diff)
downloadgst-omx-1c3f39c4d784465c3da79d58e57091b96c6e4ddf.tar.gz
omxvideoenc: add support of alternate interlace mode on zynq
It's only supported by the Zynq HEVC encoder for now.
-rw-r--r--omx/gstomxh265enc.c9
-rw-r--r--omx/gstomxvideoenc.c127
2 files changed, 136 insertions, 0 deletions
diff --git a/omx/gstomxh265enc.c b/omx/gstomxh265enc.c
index e05105f..aaddd5f 100644
--- a/omx/gstomxh265enc.c
+++ b/omx/gstomxh265enc.c
@@ -27,6 +27,7 @@
#include "gstomxh265enc.h"
#include "gstomxh265utils.h"
+#include "gstomxvideo.h"
GST_DEBUG_CATEGORY_STATIC (gst_omx_h265_enc_debug_category);
#define GST_CAT_DEFAULT gst_omx_h265_enc_debug_category
@@ -194,6 +195,14 @@ gst_omx_h265_enc_class_init (GstOMXH265EncClass * klass)
GST_PARAM_MUTABLE_READY));
#endif
+ videoenc_class->cdata.default_sink_template_caps =
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ GST_VIDEO_CAPS_MAKE_WITH_FEATURES (GST_CAPS_FEATURE_FORMAT_INTERLACED,
+ GST_OMX_VIDEO_SUPPORTED_FORMATS)
+ ", interlace-mode = (string) alternate ; "
+#endif
+ GST_VIDEO_CAPS_MAKE (GST_OMX_VIDEO_SUPPORTED_FORMATS);
+
videoenc_class->cdata.default_src_template_caps = "video/x-h265, "
"width=(int) [ 1, MAX ], " "height=(int) [ 1, MAX ], "
"framerate = (fraction) [0, MAX], stream-format=(string) byte-stream, "
diff --git a/omx/gstomxvideoenc.c b/omx/gstomxvideoenc.c
index 03a006e..b050db1 100644
--- a/omx/gstomxvideoenc.c
+++ b/omx/gstomxvideoenc.c
@@ -2374,6 +2374,75 @@ gst_omx_video_enc_framerate_changed (GstOMXVideoEnc * self,
return FALSE;
}
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+static gboolean
+gst_omx_video_enc_set_interlacing_parameters (GstOMXVideoEnc * self,
+ GstVideoInfo * info)
+{
+ OMX_ERRORTYPE err;
+ OMX_INTERLACEFORMATTYPE interlace_format_param;
+
+ GST_OMX_INIT_STRUCT (&interlace_format_param);
+ interlace_format_param.nPortIndex = self->enc_in_port->index;
+
+ err = gst_omx_component_get_parameter (self->enc,
+ (OMX_INDEXTYPE) OMX_ALG_IndexParamVideoInterlaceFormatCurrent,
+ &interlace_format_param);
+
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self,
+ "Failed to get interlace format: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ return FALSE;
+ }
+
+ if (info->interlace_mode == GST_VIDEO_INTERLACE_MODE_PROGRESSIVE)
+ interlace_format_param.nFormat = OMX_InterlaceFrameProgressive;
+ else if (info->interlace_mode == GST_VIDEO_INTERLACE_MODE_ALTERNATE) {
+ if (GST_VIDEO_INFO_FIELD_ORDER (info) ==
+ GST_VIDEO_FIELD_ORDER_BOTTOM_FIELD_FIRST)
+ interlace_format_param.nFormat =
+ OMX_ALG_InterlaceAlternateBottomFieldFirst;
+ else if (GST_VIDEO_INFO_FIELD_ORDER (info) ==
+ GST_VIDEO_FIELD_ORDER_BOTTOM_FIELD_FIRST)
+ interlace_format_param.nFormat = OMX_ALG_InterlaceAlternateTopFieldFirst;
+ else {
+ GST_INFO_OBJECT (self,
+ "input field-order unspecified, assume top-field-first");
+ interlace_format_param.nFormat = OMX_ALG_InterlaceAlternateTopFieldFirst;
+ }
+ } else {
+ /* Caps templates should ensure this doesn't happen but just to be safe.. */
+ GST_ERROR_OBJECT (self, "Video interlacing mode %s not supported",
+ gst_video_interlace_mode_to_string (info->interlace_mode));
+ return FALSE;
+ }
+
+ err = gst_omx_component_set_parameter (self->enc,
+ (OMX_INDEXTYPE) OMX_ALG_IndexParamVideoInterlaceFormatCurrent,
+ &interlace_format_param);
+
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self,
+ "Failed to set interlacing mode %s (%s) format: %s (0x%08x)",
+ gst_video_interlace_mode_to_string (info->interlace_mode),
+ interlace_format_param.nFormat ==
+ OMX_ALG_InterlaceAlternateTopFieldFirst ? "top-field-first" :
+ "bottom-field-first", gst_omx_error_to_string (err), err);
+ return FALSE;
+ } else {
+ GST_DEBUG_OBJECT (self,
+ "Video interlacing mode %s (%s) set on component",
+ gst_video_interlace_mode_to_string (info->interlace_mode),
+ interlace_format_param.nFormat ==
+ OMX_ALG_InterlaceAlternateTopFieldFirst ? "top-field-first" :
+ "bottom-field-first");
+ }
+
+ return TRUE;
+}
+#endif // USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+
static gboolean
gst_omx_video_enc_set_format (GstVideoEncoder * encoder,
GstVideoCodecState * state)
@@ -2458,6 +2527,11 @@ gst_omx_video_enc_set_format (GstVideoEncoder * encoder,
port_def.format.video.nFrameWidth = info->width;
port_def.format.video.nFrameHeight = GST_VIDEO_INFO_FIELD_HEIGHT (info);
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ if (!gst_omx_video_enc_set_interlacing_parameters (self, info))
+ return FALSE;
+#endif
+
if (G_UNLIKELY (klass->cdata.hacks & GST_OMX_HACK_VIDEO_FRAMERATE_INTEGER)) {
port_def.format.video.xFramerate =
info->fps_d ? GST_VIDEO_INFO_FIELD_RATE_N (info) / (info->fps_d) : 0;
@@ -3101,6 +3175,13 @@ gst_omx_video_enc_handle_frame (GstVideoEncoder * encoder,
buf->omx_buf->nTickCount = 0;
}
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ if (GST_VIDEO_BUFFER_IS_TOP_FIELD (frame->input_buffer))
+ buf->omx_buf->nFlags |= OMX_ALG_BUFFERFLAG_TOP_FIELD;
+ else if (GST_VIDEO_BUFFER_IS_BOTTOM_FIELD (frame->input_buffer))
+ buf->omx_buf->nFlags |= OMX_ALG_BUFFERFLAG_BOT_FIELD;
+#endif
+
self->started = TRUE;
err = gst_omx_port_release_buffer (port, buf);
if (err != OMX_ErrorNone)
@@ -3428,6 +3509,50 @@ filter_supported_formats (GList * negotiation_map)
}
static GstCaps *
+add_interlace_to_caps (GstOMXVideoEnc * self, GstCaps * caps)
+{
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ OMX_ERRORTYPE err;
+ OMX_INTERLACEFORMATTYPE interlace_format_param;
+ GstCaps *caps_alternate;
+
+ if (gst_caps_is_empty (caps))
+ /* No caps to add to */
+ return caps;
+
+ GST_OMX_INIT_STRUCT (&interlace_format_param);
+ interlace_format_param.nPortIndex = self->enc_in_port->index;
+
+ err = gst_omx_component_get_parameter (self->enc,
+ OMX_ALG_IndexParamVideoInterlaceFormatSupported, &interlace_format_param);
+
+ if (err != OMX_ErrorNone) {
+ GST_WARNING_OBJECT (self,
+ "Failed to get OMX_ALG_IndexParamVideoInterlaceFormatSupported %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ return caps;
+ }
+
+ if (!(interlace_format_param.nFormat &
+ OMX_ALG_InterlaceAlternateTopFieldFirst)
+ && !(interlace_format_param.nFormat &
+ OMX_ALG_InterlaceAlternateBottomFieldFirst))
+ return caps;
+
+ /* Alternate mode is supported, create an 'alternate' variant of the caps
+ * with the caps feature. */
+ caps_alternate = gst_caps_copy (caps);
+
+ gst_caps_set_features_simple (caps_alternate,
+ gst_caps_features_new (GST_CAPS_FEATURE_FORMAT_INTERLACED, NULL));
+
+ caps = gst_caps_merge (caps, caps_alternate);
+#endif // USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+
+ return caps;
+}
+
+static GstCaps *
gst_omx_video_enc_getcaps (GstVideoEncoder * encoder, GstCaps * filter)
{
GstOMXVideoEnc *self = GST_OMX_VIDEO_ENC (encoder);
@@ -3447,6 +3572,8 @@ gst_omx_video_enc_getcaps (GstVideoEncoder * encoder, GstCaps * filter)
g_list_free_full (negotiation_map,
(GDestroyNotify) gst_omx_video_negotiation_map_free);
+ comp_supported_caps = add_interlace_to_caps (self, comp_supported_caps);
+
if (!gst_caps_is_empty (comp_supported_caps)) {
ret =
gst_video_encoder_proxy_getcaps (encoder, comp_supported_caps, filter);