mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-20 00:31:13 +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 "gstomxh265enc.h"
|
||||||
#include "gstomxh265utils.h"
|
#include "gstomxh265utils.h"
|
||||||
|
#include "gstomxvideo.h"
|
||||||
|
|
||||||
GST_DEBUG_CATEGORY_STATIC (gst_omx_h265_enc_debug_category);
|
GST_DEBUG_CATEGORY_STATIC (gst_omx_h265_enc_debug_category);
|
||||||
#define GST_CAT_DEFAULT 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));
|
GST_PARAM_MUTABLE_READY));
|
||||||
#endif
|
#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, "
|
videoenc_class->cdata.default_src_template_caps = "video/x-h265, "
|
||||||
"width=(int) [ 1, MAX ], " "height=(int) [ 1, MAX ], "
|
"width=(int) [ 1, MAX ], " "height=(int) [ 1, MAX ], "
|
||||||
"framerate = (fraction) [0, MAX], stream-format=(string) byte-stream, "
|
"framerate = (fraction) [0, MAX], stream-format=(string) byte-stream, "
|
||||||
|
|
|
@ -2374,6 +2374,75 @@ gst_omx_video_enc_framerate_changed (GstOMXVideoEnc * self,
|
||||||
return FALSE;
|
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
|
static gboolean
|
||||||
gst_omx_video_enc_set_format (GstVideoEncoder * encoder,
|
gst_omx_video_enc_set_format (GstVideoEncoder * encoder,
|
||||||
GstVideoCodecState * state)
|
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.nFrameWidth = info->width;
|
||||||
port_def.format.video.nFrameHeight = GST_VIDEO_INFO_FIELD_HEIGHT (info);
|
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)) {
|
if (G_UNLIKELY (klass->cdata.hacks & GST_OMX_HACK_VIDEO_FRAMERATE_INTEGER)) {
|
||||||
port_def.format.video.xFramerate =
|
port_def.format.video.xFramerate =
|
||||||
info->fps_d ? GST_VIDEO_INFO_FIELD_RATE_N (info) / (info->fps_d) : 0;
|
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;
|
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;
|
self->started = TRUE;
|
||||||
err = gst_omx_port_release_buffer (port, buf);
|
err = gst_omx_port_release_buffer (port, buf);
|
||||||
if (err != OMX_ErrorNone)
|
if (err != OMX_ErrorNone)
|
||||||
|
@ -3427,6 +3508,50 @@ filter_supported_formats (GList * negotiation_map)
|
||||||
return 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 *
|
static GstCaps *
|
||||||
gst_omx_video_enc_getcaps (GstVideoEncoder * encoder, GstCaps * filter)
|
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,
|
g_list_free_full (negotiation_map,
|
||||||
(GDestroyNotify) gst_omx_video_negotiation_map_free);
|
(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)) {
|
if (!gst_caps_is_empty (comp_supported_caps)) {
|
||||||
ret =
|
ret =
|
||||||
gst_video_encoder_proxy_getcaps (encoder, comp_supported_caps, filter);
|
gst_video_encoder_proxy_getcaps (encoder, comp_supported_caps, filter);
|
||||||
|
|
Loading…
Reference in a new issue