From 413f05269c8d28375f4c3b9e0adf14a274e161a6 Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Tue, 14 Mar 2017 03:00:49 +1100 Subject: omxvideoenc: Add GST_OMX_HACK_HEIGHT_MULTIPLE_16 for Rpi The Raspberry Pi encoder produces corrupt output unless the input height is a multiple of 16. Add a hack that adds zero padding when needed. --- omx/gstomx.c | 4 +++- omx/gstomx.h | 5 ++++ omx/gstomxvideoenc.c | 67 ++++++++++++++++++++++++++++++---------------------- 3 files changed, 47 insertions(+), 29 deletions(-) diff --git a/omx/gstomx.c b/omx/gstomx.c index f9b41eb..214f618 100644 --- a/omx/gstomx.c +++ b/omx/gstomx.c @@ -2454,7 +2454,7 @@ gst_omx_command_to_string (OMX_COMMANDTYPE cmd) } #if defined(USE_OMX_TARGET_RPI) -#define DEFAULT_HACKS (GST_OMX_HACK_NO_COMPONENT_ROLE) +#define DEFAULT_HACKS (GST_OMX_HACK_NO_COMPONENT_ROLE | GST_OMX_HACK_HEIGHT_MULTIPLE_16) #else #define DEFAULT_HACKS (0) #endif @@ -2490,6 +2490,8 @@ gst_omx_parse_hacks (gchar ** hacks) hacks_flags |= GST_OMX_HACK_NO_DISABLE_OUTPORT; else if (g_str_equal (*hacks, "signals-premature-eos")) hacks_flags |= GST_OMX_HACK_SIGNALS_PREMATURE_EOS; + else if (g_str_equal (*hacks, "height-multiple-16")) + hacks_flags |= GST_OMX_HACK_HEIGHT_MULTIPLE_16; else GST_WARNING ("Unknown hack: %s", *hacks); hacks++; diff --git a/omx/gstomx.h b/omx/gstomx.h index 60a315b..cafed89 100644 --- a/omx/gstomx.h +++ b/omx/gstomx.h @@ -134,6 +134,11 @@ G_BEGIN_DECLS */ #define GST_OMX_HACK_NO_DISABLE_OUTPORT G_GUINT64_CONSTANT (0x0000000000000100) +/* If the encoder requires input buffers that have a height + * which is a multiple of 16 pixels + */ +#define GST_OMX_HACK_HEIGHT_MULTIPLE_16 G_GUINT64_CONSTANT (0x0000000000000200) + typedef struct _GstOMXCore GstOMXCore; typedef struct _GstOMXPort GstOMXPort; typedef enum _GstOMXPortDirection GstOMXPortDirection; diff --git a/omx/gstomxvideoenc.c b/omx/gstomxvideoenc.c index 6a027b8..111b213 100644 --- a/omx/gstomxvideoenc.c +++ b/omx/gstomxvideoenc.c @@ -1053,7 +1053,11 @@ gst_omx_video_enc_set_format (GstVideoEncoder * encoder, port_def.format.video.nStride = GST_ROUND_UP_4 (info->width); /* safe (?) default */ port_def.format.video.nFrameHeight = info->height; - port_def.format.video.nSliceHeight = info->height; + + if (klass->cdata.hacks & GST_OMX_HACK_HEIGHT_MULTIPLE_16) + port_def.format.video.nSliceHeight = GST_ROUND_UP_16 (info->height); + else + port_def.format.video.nSliceHeight = info->height; switch (port_def.format.video.eColorFormat) { case OMX_COLOR_FormatYUV420Planar: @@ -1303,6 +1307,9 @@ gst_omx_video_enc_fill_buffer (GstOMXVideoEnc * self, GstBuffer * inbuf, outbuf->omx_buf->nAllocLen - outbuf->omx_buf->nOffset) { outbuf->omx_buf->nFilledLen = gst_buffer_get_size (inbuf); + GST_LOG_OBJECT (self, "Matched strides - direct copy %u bytes", + outbuf->omx_buf->nFilledLen); + gst_buffer_extract (inbuf, 0, outbuf->omx_buf->pBuffer + outbuf->omx_buf->nOffset, outbuf->omx_buf->nFilledLen); @@ -1311,10 +1318,11 @@ gst_omx_video_enc_fill_buffer (GstOMXVideoEnc * self, GstBuffer * inbuf, } /* Different strides */ + GST_LOG_OBJECT (self, "Mismatched strides - copying line-by-line"); switch (info->finfo->format) { case GST_VIDEO_FORMAT_I420:{ - gint i, j, height, width; + gint i, j, height, width, dest_height; guint8 *src, *dest; gint src_stride, dest_stride; @@ -1329,20 +1337,17 @@ gst_omx_video_enc_fill_buffer (GstOMXVideoEnc * self, GstBuffer * inbuf, for (i = 0; i < 3; i++) { if (i == 0) { dest_stride = port_def->format.video.nStride; - src_stride = GST_VIDEO_FRAME_COMP_STRIDE (&frame, 0); - - /* XXX: Try this if no stride was set */ - if (dest_stride == 0) - dest_stride = src_stride; + dest_height = port_def->format.video.nSliceHeight; } else { dest_stride = port_def->format.video.nStride / 2; - src_stride = GST_VIDEO_FRAME_COMP_STRIDE (&frame, 1); - - /* XXX: Try this if no stride was set */ - if (dest_stride == 0) - dest_stride = src_stride; + dest_height = port_def->format.video.nSliceHeight / 2; } + src_stride = GST_VIDEO_FRAME_COMP_STRIDE (&frame, i); + /* XXX: Try this if no stride was set */ + if (dest_stride == 0) + dest_stride = src_stride; + dest = outbuf->omx_buf->pBuffer + outbuf->omx_buf->nOffset; if (i > 0) dest += @@ -1371,13 +1376,19 @@ gst_omx_video_enc_fill_buffer (GstOMXVideoEnc * self, GstBuffer * inbuf, src += src_stride; dest += dest_stride; } + for (; j < dest_height; j++) { + memset (dest, 0, dest_stride); + outbuf->omx_buf->nFilledLen += dest_stride; + src += src_stride; + dest += dest_stride; + } } gst_video_frame_unmap (&frame); ret = TRUE; break; } case GST_VIDEO_FORMAT_NV12:{ - gint i, j, height, width; + gint i, j, height, width, dest_height; guint8 *src, *dest; gint src_stride, dest_stride; @@ -1388,22 +1399,13 @@ gst_omx_video_enc_fill_buffer (GstOMXVideoEnc * self, GstBuffer * inbuf, ret = FALSE; break; } + dest_stride = port_def->format.video.nStride; for (i = 0; i < 2; i++) { - if (i == 0) { - dest_stride = port_def->format.video.nStride; - src_stride = GST_VIDEO_FRAME_COMP_STRIDE (&frame, 0); - /* XXX: Try this if no stride was set */ - if (dest_stride == 0) - dest_stride = src_stride; - } else { - dest_stride = port_def->format.video.nStride; - src_stride = GST_VIDEO_FRAME_COMP_STRIDE (&frame, 1); - - /* XXX: Try this if no stride was set */ - if (dest_stride == 0) - dest_stride = src_stride; - } + src_stride = GST_VIDEO_FRAME_COMP_STRIDE (&frame, i); + /* XXX: Try this if no stride was set */ + if (dest_stride == 0) + dest_stride = src_stride; dest = outbuf->omx_buf->pBuffer + outbuf->omx_buf->nOffset; if (i == 1) @@ -1411,6 +1413,10 @@ gst_omx_video_enc_fill_buffer (GstOMXVideoEnc * self, GstBuffer * inbuf, port_def->format.video.nSliceHeight * port_def->format.video.nStride; + if (i == 0) + dest_height = port_def->format.video.nSliceHeight; + else + dest_height = port_def->format.video.nSliceHeight / 2; src = GST_VIDEO_FRAME_COMP_DATA (&frame, i); height = GST_VIDEO_FRAME_COMP_HEIGHT (&frame, i); width = GST_VIDEO_FRAME_COMP_WIDTH (&frame, i) * (i == 0 ? 1 : 2); @@ -1429,7 +1435,12 @@ gst_omx_video_enc_fill_buffer (GstOMXVideoEnc * self, GstBuffer * inbuf, src += src_stride; dest += dest_stride; } - + for (; j < dest_height; j++) { + memset (dest, 0, dest_stride); + outbuf->omx_buf->nFilledLen += dest_stride; + src += src_stride; + dest += dest_stride; + } } gst_video_frame_unmap (&frame); ret = TRUE; -- cgit v1.2.1