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