1From f397165ca764cb6023e6efa88afb0df643789ea6 Mon Sep 17 00:00:00 2001
2From: Jeffy Chen <jeffy.chen@rock-chips.com>
3Date: Thu, 31 Oct 2019 18:45:19 +0800
4Subject: [PATCH 08/14] video-converter: Support rockchip RGA 2D accel
5
6Disabled by default, set env GST_VIDEO_CONVERT_USE_RGA=1 to enable.
7
8Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
9---
10 gst-libs/gst/video/meson.build       |   2 +-
11 gst-libs/gst/video/video-converter.c | 180 +++++++++++++++++++++++++++
12 meson.build                          |   3 +
13 3 files changed, 184 insertions(+), 1 deletion(-)
14
15diff --git a/gst-libs/gst/video/meson.build b/gst-libs/gst/video/meson.build
16index cc5b241..615444d 100644
17--- a/gst-libs/gst/video/meson.build
18+++ b/gst-libs/gst/video/meson.build
19@@ -113,7 +113,7 @@ gstvideo_h = video_enums[1]
20 video_gen_sources = [gstvideo_h]
21
22 orcsrc = 'video-orc'
23-gstvideo_deps = [gst_base_dep, libm]
24+gstvideo_deps = [gst_base_dep, libm, rga_dep]
25 if have_orcc
26   gstvideo_deps += [orc_dep]
27   orc_h = custom_target(orcsrc + '.h',
28diff --git a/gst-libs/gst/video/video-converter.c b/gst-libs/gst/video/video-converter.c
29index 9b77eab..c49d9a0 100644
30--- a/gst-libs/gst/video/video-converter.c
31+++ b/gst-libs/gst/video/video-converter.c
32@@ -38,6 +38,11 @@
33
34 #include "video-orc.h"
35
36+#ifdef HAVE_RGA
37+#include <rga/rga.h>
38+#include <rga/RgaApi.h>
39+#endif
40+
41 /**
42  * SECTION:videoconverter
43  * @title: GstVideoConverter
44@@ -2742,6 +2747,169 @@ gst_video_converter_get_config (GstVideoConverter * convert)
45   return convert->config;
46 }
47
48+#ifdef HAVE_RGA
49+static RgaSURF_FORMAT
50+get_rga_format (GstVideoFormat format)
51+{
52+  switch (format) {
53+    case GST_VIDEO_FORMAT_BGRA:
54+    case GST_VIDEO_FORMAT_BGRx:
55+      return RK_FORMAT_BGRA_8888;
56+    case GST_VIDEO_FORMAT_RGBA:
57+      return RK_FORMAT_RGBA_8888;
58+    case GST_VIDEO_FORMAT_RGBx:
59+      return RK_FORMAT_RGBX_8888;
60+    case GST_VIDEO_FORMAT_BGR:
61+      return RK_FORMAT_BGR_888;
62+    case GST_VIDEO_FORMAT_RGB:
63+      return RK_FORMAT_RGB_888;
64+    case GST_VIDEO_FORMAT_BGR16:
65+      return RK_FORMAT_RGB_565;
66+    case GST_VIDEO_FORMAT_NV12:
67+      return RK_FORMAT_YCbCr_420_SP;
68+    case GST_VIDEO_FORMAT_NV21:
69+      return RK_FORMAT_YCrCb_420_SP;
70+    case GST_VIDEO_FORMAT_I420:
71+      return RK_FORMAT_YCbCr_420_P;
72+    case GST_VIDEO_FORMAT_YV12:
73+      return RK_FORMAT_YCrCb_420_P;
74+    case GST_VIDEO_FORMAT_NV16:
75+      return RK_FORMAT_YCbCr_422_SP;
76+    case GST_VIDEO_FORMAT_NV61:
77+      return RK_FORMAT_YCrCb_422_SP;
78+    case GST_VIDEO_FORMAT_Y42B:
79+      return RK_FORMAT_YCbCr_422_P;
80+    case GST_VIDEO_FORMAT_NV12_10LE40:
81+      return RK_FORMAT_YCbCr_420_SP_10B;
82+    default:
83+      return RK_FORMAT_UNKNOWN;
84+  }
85+}
86+
87+static gboolean
88+get_rga_info (const GstVideoFrame * frame, rga_info_t * info,
89+    int x, int y, int w, int h)
90+{
91+  GstVideoMeta *meta = gst_buffer_get_video_meta (frame->buffer);
92+  const GstVideoInfo *vinfo = &frame->info;
93+  RgaSURF_FORMAT format;
94+  gint hstride, vstride0, i;
95+  guint8 *ptr;
96+
97+  memset (info, 0, sizeof (rga_info_t));
98+
99+  if (!meta)
100+    return FALSE;
101+
102+  hstride = meta->stride[0];
103+  vstride0 = meta->n_planes == 1 ? meta->height : meta->offset[1] / hstride;
104+
105+  /* RGA requires contig buffer */
106+  ptr = GST_VIDEO_FRAME_PLANE_DATA (frame, 0);
107+  for (i = 1; i < GST_VIDEO_FRAME_N_PLANES (frame); i++) {
108+    gint size = GST_VIDEO_FRAME_PLANE_OFFSET (frame, i) -
109+        GST_VIDEO_FRAME_PLANE_OFFSET (frame, i - 1);
110+    gint vstride = size / meta->stride[i - 1];
111+
112+    ptr += size;
113+    if (ptr != GST_VIDEO_FRAME_PLANE_DATA (frame, i))
114+      return FALSE;
115+
116+    if ((meta->stride[i] != hstride && meta->stride[i] != hstride / 2) ||
117+        (vstride != vstride0 && vstride != vstride0 / 2))
118+      return FALSE;
119+  }
120+
121+  format = get_rga_format (GST_VIDEO_INFO_FORMAT (vinfo));
122+  switch (format) {
123+    case RK_FORMAT_RGBX_8888:
124+    case RK_FORMAT_RGBA_8888:
125+    case RK_FORMAT_BGRA_8888:
126+      hstride /= 4;
127+      break;
128+    case RK_FORMAT_RGB_888:
129+    case RK_FORMAT_BGR_888:
130+      hstride /= 3;
131+      break;
132+    case RK_FORMAT_RGB_565:
133+      hstride /= 2;
134+      break;
135+    case RK_FORMAT_YCbCr_420_SP_10B:
136+    case RK_FORMAT_YCbCr_422_SP:
137+    case RK_FORMAT_YCrCb_422_SP:
138+    case RK_FORMAT_YCbCr_422_P:
139+    case RK_FORMAT_YCrCb_422_P:
140+    case RK_FORMAT_YCbCr_420_SP:
141+    case RK_FORMAT_YCrCb_420_SP:
142+    case RK_FORMAT_YCbCr_420_P:
143+    case RK_FORMAT_YCrCb_420_P:
144+      /* RGA requires yuv image rect align to 2 */
145+      x = (x + 1) & ~1;
146+      y = (y + 1) & ~1;
147+      w &= ~1;
148+      h &= ~1;
149+
150+      if (vstride0 % 2)
151+        return FALSE;
152+      break;
153+    default:
154+      return FALSE;
155+  }
156+
157+  info->virAddr = GST_VIDEO_FRAME_PLANE_DATA (frame, 0);
158+  info->mmuFlag = 1;
159+
160+  rga_set_rect (&info->rect, x, y, w, h, hstride, vstride0, format);
161+  return TRUE;
162+}
163+
164+static gboolean
165+video_converter_try_rga (GstVideoConverter * convert,
166+    const GstVideoFrame * src, GstVideoFrame * dest)
167+{
168+  rga_info_t src_info = { 0 };
169+  rga_info_t dst_info = { 0 };
170+  static int rga_supported = 1;
171+  static int rga_inited = 0;
172+  const char *buf;
173+
174+  buf = g_getenv ("GST_VIDEO_CONVERT_USE_RGA");
175+  if (!buf || strcmp (buf, "1"))
176+    return FALSE;
177+
178+  if (!rga_supported)
179+    return FALSE;
180+
181+  if (!rga_inited) {
182+    if (c_RkRgaInit () < 0) {
183+      rga_supported = 0;
184+      return FALSE;
185+    }
186+    rga_inited = 1;
187+  }
188+
189+  if (!get_rga_info (src, &src_info, convert->in_x, convert->in_y,
190+          convert->in_width, convert->in_height)) {
191+    GST_DEBUG ("unsupported src info for RGA");
192+    return FALSE;
193+  }
194+
195+  if (!get_rga_info (dest, &dst_info, convert->out_x, convert->out_y,
196+          convert->out_width, convert->out_height)) {
197+    GST_DEBUG ("unsupported dst info for RGA");
198+    return FALSE;
199+  }
200+
201+  if (c_RkRgaBlit (&src_info, &dst_info, NULL) < 0) {
202+    GST_DEBUG ("failed to blit with RGA");
203+    return FALSE;
204+  }
205+
206+  GST_DEBUG ("converted with RGA");
207+  return TRUE;
208+}
209+#endif
210+
211 /**
212  * gst_video_converter_frame:
213  * @convert: a #GstVideoConverter
214@@ -2789,6 +2957,12 @@ gst_video_converter_frame (GstVideoConverter * convert,
215           convert->out_width == 0 || convert->out_height == 0))
216     return;
217
218+#ifdef HAVE_RGA
219+  /* Accel convert with rockchip RGA */
220+  if (video_converter_try_rga (convert, src, dest))
221+    return;
222+#endif
223+
224   convert->convert (convert, src, dest);
225 }
226
227@@ -7218,6 +7392,12 @@ convert_scale_planes (GstVideoConverter * convert,
228 {
229   int i, n_planes;
230
231+#ifdef HAVE_RGA
232+  /* Accel convert with rockchip RGA */
233+  if (video_converter_try_rga (convert, src, dest))
234+    return;
235+#endif
236+
237   n_planes = GST_VIDEO_FRAME_N_PLANES (dest);
238   for (i = 0; i < n_planes; i++) {
239     if (convert->fconvert[i])
240diff --git a/meson.build b/meson.build
241index 19a8347..4341e8e 100644
242--- a/meson.build
243+++ b/meson.build
244@@ -305,6 +305,9 @@ if get_option('default_library') == 'static'
245   gst_plugins_base_args += ['-DGST_STATIC_COMPILATION']
246 endif
247
248+rga_dep = dependency('librga', required: false)
249+core_conf.set('HAVE_RGA', rga_dep.found())
250+
251 # X11 checks are for sys/ and tests/
252 x11_dep = dependency('x11', required : get_option('x11'))
253 # GIO is used by the GIO plugin, and by the TCP, SDP, and RTSP plugins
254--
2552.20.1
256
257