From 1c3f39c4d784465c3da79d58e57091b96c6e4ddf Mon Sep 17 00:00:00 2001 From: Guillaume Desmottes Date: Thu, 6 Feb 2020 10:11:13 +0530 Subject: omxvideoenc: add support of alternate interlace mode on zynq It's only supported by the Zynq HEVC encoder for now. --- omx/gstomxh265enc.c | 9 ++++ omx/gstomxvideoenc.c | 127 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 136 insertions(+) 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) @@ -3427,6 +3508,50 @@ filter_supported_formats (GList * negotiation_map) return 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) { @@ -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); -- cgit v1.2.1