mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-19 16:21:17 +00:00
omxvideoenc: add support of alternate interlace mode on zynq
It's only supported by the Zynq HEVC encoder for now.
This commit is contained in:
parent
3c45c8ecbe
commit
1c3f39c4d7
2 changed files with 136 additions and 0 deletions
|
@ -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, "
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue