From 02517deddcd968b332eb6d996d00609b4784a980 Mon Sep 17 00:00:00 2001 From: Jeffy Chen Date: Fri, 8 Nov 2019 17:36:20 +0800 Subject: [PATCH 05/12] video-flip: Support rockchip RGA 2D accel Disabled by default, set env GST_VIDEO_FLIP_USE_RGA=1 to enable. Signed-off-by: Jeffy Chen --- gst/videofilter/gstvideoflip.c | 216 ++++++++++++++++++++++++++++++++- gst/videofilter/meson.build | 2 +- meson.build | 3 + 3 files changed, 218 insertions(+), 3 deletions(-) diff --git a/gst/videofilter/gstvideoflip.c b/gst/videofilter/gstvideoflip.c index 07db899..9ea405b 100644 --- a/gst/videofilter/gstvideoflip.c +++ b/gst/videofilter/gstvideoflip.c @@ -48,6 +48,11 @@ #include #include +#ifdef HAVE_RGA +#include +#include +#endif + /* GstVideoFlip properties */ enum { @@ -68,7 +73,7 @@ GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_ALWAYS, GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ AYUV, " "ARGB, BGRA, ABGR, RGBA, Y444, xRGB, RGBx, xBGR, BGRx, " - "RGB, BGR, I420, YV12, IYUV, YUY2, UYVY, YVYU, NV12, NV21," + "RGB, BGR, I420, YV12, IYUV, YUY2, UYVY, YVYU, NV12, NV21, NV12_10LE40, " "GRAY8, GRAY16_BE, GRAY16_LE, I420_10LE, I420_10BE, I420_12LE, I420_12BE, " "I422_10LE, I422_10BE, I422_12LE, I422_12BE, Y444_10LE, Y444_10BE, Y444_12LE, Y444_12BE }")) ); @@ -79,7 +84,7 @@ GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_ALWAYS, GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ AYUV, " "ARGB, BGRA, ABGR, RGBA, Y444, xRGB, RGBx, xBGR, BGRx, " - "RGB, BGR, I420, YV12, IYUV, YUY2, UYVY, YVYU, NV12, NV21," + "RGB, BGR, I420, YV12, IYUV, YUY2, UYVY, YVYU, NV12, NV21, NV12_10LE40, " "GRAY8, GRAY16_BE, GRAY16_LE, I420_10LE, I420_10BE, I420_12LE, I420_12BE, " "I422_10LE, I422_10BE, I422_12LE, I422_12BE, Y444_10LE, Y444_10BE, Y444_12LE, Y444_12BE }")) ); @@ -1454,6 +1459,193 @@ gst_video_flip_y422 (GstVideoFlip * videoflip, GstVideoFrame * dest, } } +#ifdef HAVE_RGA +static RgaSURF_FORMAT +get_rga_format (GstVideoFormat format) +{ + switch (format) { + case GST_VIDEO_FORMAT_BGRA: + case GST_VIDEO_FORMAT_BGRx: + return RK_FORMAT_BGRA_8888; + case GST_VIDEO_FORMAT_RGBA: + return RK_FORMAT_RGBA_8888; + case GST_VIDEO_FORMAT_RGBx: + return RK_FORMAT_RGBX_8888; + case GST_VIDEO_FORMAT_BGR: + return RK_FORMAT_BGR_888; + case GST_VIDEO_FORMAT_RGB: + return RK_FORMAT_RGB_888; + case GST_VIDEO_FORMAT_RGB16: + return RK_FORMAT_RGB_565; + case GST_VIDEO_FORMAT_NV12: + return RK_FORMAT_YCbCr_420_SP; + case GST_VIDEO_FORMAT_NV21: + return RK_FORMAT_YCrCb_420_SP; + case GST_VIDEO_FORMAT_I420: + return RK_FORMAT_YCbCr_420_P; + case GST_VIDEO_FORMAT_YV12: + return RK_FORMAT_YCrCb_420_P; + case GST_VIDEO_FORMAT_NV16: + return RK_FORMAT_YCbCr_422_SP; + case GST_VIDEO_FORMAT_NV61: + return RK_FORMAT_YCrCb_422_SP; + case GST_VIDEO_FORMAT_Y42B: + return RK_FORMAT_YCbCr_422_P; + case GST_VIDEO_FORMAT_NV12_10LE40: + return RK_FORMAT_YCbCr_420_SP_10B; + default: + return RK_FORMAT_UNKNOWN; + } +} + +static gboolean +get_rga_info (const GstVideoFrame * frame, rga_info_t * info, + int x, int y, int w, int h) +{ + GstVideoMeta *meta = gst_buffer_get_video_meta (frame->buffer); + const GstVideoInfo *vinfo = &frame->info; + RgaSURF_FORMAT format; + gint hstride, vstride0, i; + guint8 *ptr; + + memset (info, 0, sizeof (rga_info_t)); + + if (!meta) + return FALSE; + + hstride = meta->stride[0]; + vstride0 = meta->n_planes == 1 ? meta->height : meta->offset[1] / hstride; + + /* RGA requires contig buffer */ + ptr = GST_VIDEO_FRAME_PLANE_DATA (frame, 0); + for (i = 1; i < GST_VIDEO_FRAME_N_PLANES (frame); i++) { + gint size = GST_VIDEO_FRAME_PLANE_OFFSET (frame, i) - + GST_VIDEO_FRAME_PLANE_OFFSET (frame, i - 1); + gint vstride = size / meta->stride[i - 1]; + + ptr += size; + if (ptr != GST_VIDEO_FRAME_PLANE_DATA (frame, i)) + return FALSE; + + if ((meta->stride[i] != hstride && meta->stride[i] != hstride / 2) || + (vstride != vstride0 && vstride != vstride0 / 2)) + return FALSE; + } + + format = get_rga_format (GST_VIDEO_INFO_FORMAT (vinfo)); + switch (format) { + case RK_FORMAT_RGBX_8888: + case RK_FORMAT_RGBA_8888: + case RK_FORMAT_BGRA_8888: + hstride /= 4; + break; + case RK_FORMAT_RGB_888: + case RK_FORMAT_BGR_888: + hstride /= 3; + break; + case RK_FORMAT_RGB_565: + hstride /= 2; + break; + case RK_FORMAT_YCbCr_420_SP_10B: + case RK_FORMAT_YCbCr_422_SP: + case RK_FORMAT_YCrCb_422_SP: + case RK_FORMAT_YCbCr_422_P: + case RK_FORMAT_YCrCb_422_P: + case RK_FORMAT_YCbCr_420_SP: + case RK_FORMAT_YCrCb_420_SP: + case RK_FORMAT_YCbCr_420_P: + case RK_FORMAT_YCrCb_420_P: + /* RGA requires yuv image rect align to 2 */ + x = (x + 1) & ~1; + y = (y + 1) & ~1; + w &= ~1; + h &= ~1; + + if (vstride0 % 2) + return FALSE; + break; + default: + return FALSE; + } + + info->virAddr = GST_VIDEO_FRAME_PLANE_DATA (frame, 0); + info->mmuFlag = 1; + + rga_set_rect (&info->rect, x, y, w, h, hstride, vstride0, format); + return TRUE; +} + +static gboolean +video_flip_try_rga (GstVideoFlip * videoflip, + GstVideoFrame * out_frame, GstVideoFrame * in_frame) +{ + gint sw = GST_VIDEO_FRAME_WIDTH (in_frame); + gint sh = GST_VIDEO_FRAME_HEIGHT (in_frame); + gint dw = GST_VIDEO_FRAME_WIDTH (out_frame); + gint dh = GST_VIDEO_FRAME_HEIGHT (out_frame); + + rga_info_t src_info = { 0 }; + rga_info_t dst_info = { 0 }; + static int rga_supported = 1; + static int rga_inited = 0; + const char *buf; + + buf = g_getenv ("GST_VIDEO_FLIP_USE_RGA"); + if (!buf || strcmp (buf, "1")) + return FALSE; + + if (!rga_supported) + return FALSE; + + if (!rga_inited) { + if (c_RkRgaInit () < 0) { + rga_supported = 0; + return FALSE; + } + rga_inited = 1; + } + + if (!get_rga_info (in_frame, &src_info, 0, 0, sw, sh)) { + GST_DEBUG ("unsupported src info for RGA"); + return FALSE; + } + + if (!get_rga_info (out_frame, &dst_info, 0, 0, dw, dh)) { + GST_DEBUG ("unsupported dst info for RGA"); + return FALSE; + } + + switch (videoflip->active_method) { + case GST_VIDEO_ORIENTATION_90R: + src_info.rotation = HAL_TRANSFORM_ROT_90; + break; + case GST_VIDEO_ORIENTATION_180: + src_info.rotation = HAL_TRANSFORM_ROT_180; + break; + case GST_VIDEO_ORIENTATION_90L: + src_info.rotation = HAL_TRANSFORM_ROT_270; + break; + case GST_VIDEO_ORIENTATION_HORIZ: + src_info.rotation = HAL_TRANSFORM_FLIP_H; + break; + case GST_VIDEO_ORIENTATION_VERT: + src_info.rotation = HAL_TRANSFORM_FLIP_V; + break; + default: + GST_DEBUG ("unsupported rotation for RGA"); + return FALSE; + } + + if (c_RkRgaBlit (&src_info, &dst_info, NULL) < 0) { + GST_DEBUG ("failed to blit with RGA"); + return FALSE; + } + + GST_DEBUG ("flipped with RGA"); + return TRUE; +} +#endif + static void gst_video_flip_configure_process (GstVideoFlip * vf) { @@ -1504,6 +1696,12 @@ gst_video_flip_configure_process (GstVideoFlip * vf) case GST_VIDEO_FORMAT_NV21: vf->process = gst_video_flip_semi_planar_yuv; break; +#ifdef HAVE_RGA + case GST_VIDEO_FORMAT_NV12_10LE40: + /* Not supported by the official videoflip */ + vf->process = video_flip_try_rga; + break; +#endif default: break; } @@ -1684,6 +1882,20 @@ gst_video_flip_transform_frame (GstVideoFilter * vfilter, GST_VIDEO_FRAME_WIDTH (out_frame), GST_VIDEO_FRAME_HEIGHT (out_frame)); g_type_class_unref (enum_class); +#ifdef HAVE_RGA + /* Accel flip with rockchip RGA */ + if (video_flip_try_rga (videoflip, out_frame, in_frame)) { + GST_OBJECT_UNLOCK (videoflip); + return GST_FLOW_OK; + } + + /* Not supported by the official videoflip */ + if (G_UNLIKELY (videoflip->process == video_flip_try_rga)) { + GST_OBJECT_UNLOCK (videoflip); + goto not_negotiated; + } +#endif + videoflip->process (videoflip, out_frame, in_frame); proposed = videoflip->proposed_method; diff --git a/gst/videofilter/meson.build b/gst/videofilter/meson.build index d7b6788..1a594c6 100644 --- a/gst/videofilter/meson.build +++ b/gst/videofilter/meson.build @@ -10,7 +10,7 @@ gstvideofilter = library('gstvideofilter', vfilter_sources, c_args : gst_plugins_good_args, include_directories : [configinc], - dependencies : [gstbase_dep, gstvideo_dep, libm], + dependencies : [gstbase_dep, gstvideo_dep, libm, rga_dep], install : true, install_dir : plugins_install_dir, ) diff --git a/meson.build b/meson.build index c21a5ad..0f3f2f2 100644 --- a/meson.build +++ b/meson.build @@ -382,6 +382,9 @@ gst_plugins_good_args = ['-DHAVE_CONFIG_H'] configinc = include_directories('.') libsinc = include_directories('gst-libs') +rga_dep = dependency('librga', required: false) +cdata.set('HAVE_RGA', rga_dep.found()) + have_orcc = false orcc_args = [] orc_targets = [] -- 2.20.1