1From 02517deddcd968b332eb6d996d00609b4784a980 Mon Sep 17 00:00:00 2001
2From: Jeffy Chen <jeffy.chen@rock-chips.com>
3Date: Fri, 8 Nov 2019 17:36:20 +0800
4Subject: [PATCH 05/12] video-flip: Support rockchip RGA 2D accel
5
6Disabled by default, set env GST_VIDEO_FLIP_USE_RGA=1 to enable.
7
8Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
9---
10 gst/videofilter/gstvideoflip.c | 216 ++++++++++++++++++++++++++++++++-
11 gst/videofilter/meson.build    |   2 +-
12 meson.build                    |   3 +
13 3 files changed, 218 insertions(+), 3 deletions(-)
14
15diff --git a/gst/videofilter/gstvideoflip.c b/gst/videofilter/gstvideoflip.c
16index 07db899..9ea405b 100644
17--- a/gst/videofilter/gstvideoflip.c
18+++ b/gst/videofilter/gstvideoflip.c
19@@ -48,6 +48,11 @@
20 #include <gst/gst.h>
21 #include <gst/video/video.h>
22
23+#ifdef HAVE_RGA
24+#include <rga/rga.h>
25+#include <rga/RgaApi.h>
26+#endif
27+
28 /* GstVideoFlip properties */
29 enum
30 {
31@@ -68,7 +73,7 @@ GST_STATIC_PAD_TEMPLATE ("src",
32     GST_PAD_ALWAYS,
33     GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ AYUV, "
34             "ARGB, BGRA, ABGR, RGBA, Y444, xRGB, RGBx, xBGR, BGRx, "
35-            "RGB, BGR, I420, YV12, IYUV, YUY2, UYVY, YVYU, NV12, NV21,"
36+            "RGB, BGR, I420, YV12, IYUV, YUY2, UYVY, YVYU, NV12, NV21, NV12_10LE40, "
37             "GRAY8, GRAY16_BE, GRAY16_LE, I420_10LE, I420_10BE, I420_12LE, I420_12BE, "
38             "I422_10LE, I422_10BE, I422_12LE, I422_12BE, Y444_10LE, Y444_10BE, Y444_12LE, Y444_12BE }"))
39     );
40@@ -79,7 +84,7 @@ GST_STATIC_PAD_TEMPLATE ("sink",
41     GST_PAD_ALWAYS,
42     GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ AYUV, "
43             "ARGB, BGRA, ABGR, RGBA, Y444, xRGB, RGBx, xBGR, BGRx, "
44-            "RGB, BGR, I420, YV12, IYUV, YUY2, UYVY, YVYU, NV12, NV21,"
45+            "RGB, BGR, I420, YV12, IYUV, YUY2, UYVY, YVYU, NV12, NV21, NV12_10LE40, "
46             "GRAY8, GRAY16_BE, GRAY16_LE, I420_10LE, I420_10BE, I420_12LE, I420_12BE, "
47             "I422_10LE, I422_10BE, I422_12LE, I422_12BE, Y444_10LE, Y444_10BE, Y444_12LE, Y444_12BE }"))
48     );
49@@ -1454,6 +1459,193 @@ gst_video_flip_y422 (GstVideoFlip * videoflip, GstVideoFrame * dest,
50   }
51 }
52
53+#ifdef HAVE_RGA
54+static RgaSURF_FORMAT
55+get_rga_format (GstVideoFormat format)
56+{
57+  switch (format) {
58+    case GST_VIDEO_FORMAT_BGRA:
59+    case GST_VIDEO_FORMAT_BGRx:
60+      return RK_FORMAT_BGRA_8888;
61+    case GST_VIDEO_FORMAT_RGBA:
62+      return RK_FORMAT_RGBA_8888;
63+    case GST_VIDEO_FORMAT_RGBx:
64+      return RK_FORMAT_RGBX_8888;
65+    case GST_VIDEO_FORMAT_BGR:
66+      return RK_FORMAT_BGR_888;
67+    case GST_VIDEO_FORMAT_RGB:
68+      return RK_FORMAT_RGB_888;
69+    case GST_VIDEO_FORMAT_RGB16:
70+      return RK_FORMAT_RGB_565;
71+    case GST_VIDEO_FORMAT_NV12:
72+      return RK_FORMAT_YCbCr_420_SP;
73+    case GST_VIDEO_FORMAT_NV21:
74+      return RK_FORMAT_YCrCb_420_SP;
75+    case GST_VIDEO_FORMAT_I420:
76+      return RK_FORMAT_YCbCr_420_P;
77+    case GST_VIDEO_FORMAT_YV12:
78+      return RK_FORMAT_YCrCb_420_P;
79+    case GST_VIDEO_FORMAT_NV16:
80+      return RK_FORMAT_YCbCr_422_SP;
81+    case GST_VIDEO_FORMAT_NV61:
82+      return RK_FORMAT_YCrCb_422_SP;
83+    case GST_VIDEO_FORMAT_Y42B:
84+      return RK_FORMAT_YCbCr_422_P;
85+    case GST_VIDEO_FORMAT_NV12_10LE40:
86+      return RK_FORMAT_YCbCr_420_SP_10B;
87+    default:
88+      return RK_FORMAT_UNKNOWN;
89+  }
90+}
91+
92+static gboolean
93+get_rga_info (const GstVideoFrame * frame, rga_info_t * info,
94+    int x, int y, int w, int h)
95+{
96+  GstVideoMeta *meta = gst_buffer_get_video_meta (frame->buffer);
97+  const GstVideoInfo *vinfo = &frame->info;
98+  RgaSURF_FORMAT format;
99+  gint hstride, vstride0, i;
100+  guint8 *ptr;
101+
102+  memset (info, 0, sizeof (rga_info_t));
103+
104+  if (!meta)
105+    return FALSE;
106+
107+  hstride = meta->stride[0];
108+  vstride0 = meta->n_planes == 1 ? meta->height : meta->offset[1] / hstride;
109+
110+  /* RGA requires contig buffer */
111+  ptr = GST_VIDEO_FRAME_PLANE_DATA (frame, 0);
112+  for (i = 1; i < GST_VIDEO_FRAME_N_PLANES (frame); i++) {
113+    gint size = GST_VIDEO_FRAME_PLANE_OFFSET (frame, i) -
114+        GST_VIDEO_FRAME_PLANE_OFFSET (frame, i - 1);
115+    gint vstride = size / meta->stride[i - 1];
116+
117+    ptr += size;
118+    if (ptr != GST_VIDEO_FRAME_PLANE_DATA (frame, i))
119+      return FALSE;
120+
121+    if ((meta->stride[i] != hstride && meta->stride[i] != hstride / 2) ||
122+        (vstride != vstride0 && vstride != vstride0 / 2))
123+      return FALSE;
124+  }
125+
126+  format = get_rga_format (GST_VIDEO_INFO_FORMAT (vinfo));
127+  switch (format) {
128+    case RK_FORMAT_RGBX_8888:
129+    case RK_FORMAT_RGBA_8888:
130+    case RK_FORMAT_BGRA_8888:
131+      hstride /= 4;
132+      break;
133+    case RK_FORMAT_RGB_888:
134+    case RK_FORMAT_BGR_888:
135+      hstride /= 3;
136+      break;
137+    case RK_FORMAT_RGB_565:
138+      hstride /= 2;
139+      break;
140+    case RK_FORMAT_YCbCr_420_SP_10B:
141+    case RK_FORMAT_YCbCr_422_SP:
142+    case RK_FORMAT_YCrCb_422_SP:
143+    case RK_FORMAT_YCbCr_422_P:
144+    case RK_FORMAT_YCrCb_422_P:
145+    case RK_FORMAT_YCbCr_420_SP:
146+    case RK_FORMAT_YCrCb_420_SP:
147+    case RK_FORMAT_YCbCr_420_P:
148+    case RK_FORMAT_YCrCb_420_P:
149+      /* RGA requires yuv image rect align to 2 */
150+      x = (x + 1) & ~1;
151+      y = (y + 1) & ~1;
152+      w &= ~1;
153+      h &= ~1;
154+
155+      if (vstride0 % 2)
156+        return FALSE;
157+      break;
158+    default:
159+      return FALSE;
160+  }
161+
162+  info->virAddr = GST_VIDEO_FRAME_PLANE_DATA (frame, 0);
163+  info->mmuFlag = 1;
164+
165+  rga_set_rect (&info->rect, x, y, w, h, hstride, vstride0, format);
166+  return TRUE;
167+}
168+
169+static gboolean
170+video_flip_try_rga (GstVideoFlip * videoflip,
171+    GstVideoFrame * out_frame, GstVideoFrame * in_frame)
172+{
173+  gint sw = GST_VIDEO_FRAME_WIDTH (in_frame);
174+  gint sh = GST_VIDEO_FRAME_HEIGHT (in_frame);
175+  gint dw = GST_VIDEO_FRAME_WIDTH (out_frame);
176+  gint dh = GST_VIDEO_FRAME_HEIGHT (out_frame);
177+
178+  rga_info_t src_info = { 0 };
179+  rga_info_t dst_info = { 0 };
180+  static int rga_supported = 1;
181+  static int rga_inited = 0;
182+  const char *buf;
183+
184+  buf = g_getenv ("GST_VIDEO_FLIP_USE_RGA");
185+  if (!buf || strcmp (buf, "1"))
186+    return FALSE;
187+
188+  if (!rga_supported)
189+    return FALSE;
190+
191+  if (!rga_inited) {
192+    if (c_RkRgaInit () < 0) {
193+      rga_supported = 0;
194+      return FALSE;
195+    }
196+    rga_inited = 1;
197+  }
198+
199+  if (!get_rga_info (in_frame, &src_info, 0, 0, sw, sh)) {
200+    GST_DEBUG ("unsupported src info for RGA");
201+    return FALSE;
202+  }
203+
204+  if (!get_rga_info (out_frame, &dst_info, 0, 0, dw, dh)) {
205+    GST_DEBUG ("unsupported dst info for RGA");
206+    return FALSE;
207+  }
208+
209+  switch (videoflip->active_method) {
210+    case GST_VIDEO_ORIENTATION_90R:
211+      src_info.rotation = HAL_TRANSFORM_ROT_90;
212+      break;
213+    case GST_VIDEO_ORIENTATION_180:
214+      src_info.rotation = HAL_TRANSFORM_ROT_180;
215+      break;
216+    case GST_VIDEO_ORIENTATION_90L:
217+      src_info.rotation = HAL_TRANSFORM_ROT_270;
218+      break;
219+    case GST_VIDEO_ORIENTATION_HORIZ:
220+      src_info.rotation = HAL_TRANSFORM_FLIP_H;
221+      break;
222+    case GST_VIDEO_ORIENTATION_VERT:
223+      src_info.rotation = HAL_TRANSFORM_FLIP_V;
224+      break;
225+    default:
226+      GST_DEBUG ("unsupported rotation for RGA");
227+      return FALSE;
228+  }
229+
230+  if (c_RkRgaBlit (&src_info, &dst_info, NULL) < 0) {
231+    GST_DEBUG ("failed to blit with RGA");
232+    return FALSE;
233+  }
234+
235+  GST_DEBUG ("flipped with RGA");
236+  return TRUE;
237+}
238+#endif
239+
240 static void
241 gst_video_flip_configure_process (GstVideoFlip * vf)
242 {
243@@ -1504,6 +1696,12 @@ gst_video_flip_configure_process (GstVideoFlip * vf)
244     case GST_VIDEO_FORMAT_NV21:
245       vf->process = gst_video_flip_semi_planar_yuv;
246       break;
247+#ifdef HAVE_RGA
248+    case GST_VIDEO_FORMAT_NV12_10LE40:
249+      /* Not supported by the official videoflip */
250+      vf->process = video_flip_try_rga;
251+      break;
252+#endif
253     default:
254       break;
255   }
256@@ -1684,6 +1882,20 @@ gst_video_flip_transform_frame (GstVideoFilter * vfilter,
257       GST_VIDEO_FRAME_WIDTH (out_frame), GST_VIDEO_FRAME_HEIGHT (out_frame));
258   g_type_class_unref (enum_class);
259
260+#ifdef HAVE_RGA
261+  /* Accel flip with rockchip RGA */
262+  if (video_flip_try_rga (videoflip, out_frame, in_frame)) {
263+    GST_OBJECT_UNLOCK (videoflip);
264+    return GST_FLOW_OK;
265+  }
266+
267+  /* Not supported by the official videoflip */
268+  if (G_UNLIKELY (videoflip->process == video_flip_try_rga)) {
269+    GST_OBJECT_UNLOCK (videoflip);
270+    goto not_negotiated;
271+  }
272+#endif
273+
274   videoflip->process (videoflip, out_frame, in_frame);
275
276   proposed = videoflip->proposed_method;
277diff --git a/gst/videofilter/meson.build b/gst/videofilter/meson.build
278index d7b6788..1a594c6 100644
279--- a/gst/videofilter/meson.build
280+++ b/gst/videofilter/meson.build
281@@ -10,7 +10,7 @@ gstvideofilter = library('gstvideofilter',
282   vfilter_sources,
283   c_args : gst_plugins_good_args,
284   include_directories : [configinc],
285-  dependencies : [gstbase_dep, gstvideo_dep, libm],
286+  dependencies : [gstbase_dep, gstvideo_dep, libm, rga_dep],
287   install : true,
288   install_dir : plugins_install_dir,
289 )
290diff --git a/meson.build b/meson.build
291index c21a5ad..0f3f2f2 100644
292--- a/meson.build
293+++ b/meson.build
294@@ -382,6 +382,9 @@ gst_plugins_good_args = ['-DHAVE_CONFIG_H']
295 configinc = include_directories('.')
296 libsinc = include_directories('gst-libs')
297
298+rga_dep = dependency('librga', required: false)
299+cdata.set('HAVE_RGA', rga_dep.found())
300+
301 have_orcc = false
302 orcc_args = []
303 orc_targets = []
304--
3052.20.1
306
307