307 lines
9.1 KiB
Diff
307 lines
9.1 KiB
Diff
From 02517deddcd968b332eb6d996d00609b4784a980 Mon Sep 17 00:00:00 2001
|
|
From: Jeffy Chen <jeffy.chen@rock-chips.com>
|
|
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 <jeffy.chen@rock-chips.com>
|
|
---
|
|
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 <gst/gst.h>
|
|
#include <gst/video/video.h>
|
|
|
|
+#ifdef HAVE_RGA
|
|
+#include <rga/rga.h>
|
|
+#include <rga/RgaApi.h>
|
|
+#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
|
|
|