xref: /OK3568_Linux_fs/external/gstreamer-rockchip/gst/rockchipmpp/gstmpp.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  * Copyright 2017 Rockchip Electronics Co., Ltd
3  *     Author: Randy Li <randy.li@rock-chips.com>
4  *
5  * Copyright 2021 Rockchip Electronics Co., Ltd
6  *     Author: Jeffy Chen <jeffy.chen@rock-chips.com>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
21  * Boston, MA 02110-1301, USA.
22  *
23  */
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27 
28 #include <string.h>
29 
30 #include <gst/allocators/gstdmabuf.h>
31 
32 #include "gstmpp.h"
33 #include "gstmpph264enc.h"
34 #include "gstmpph265enc.h"
35 #include "gstmppvp8enc.h"
36 #include "gstmppjpegenc.h"
37 #include "gstmppjpegdec.h"
38 #include "gstmppvideodec.h"
39 #include "gstmppvpxalphadecodebin.h"
40 
41 GST_DEBUG_CATEGORY_STATIC (mpp_debug);
42 #define GST_CAT_DEFAULT mpp_debug
43 
44 struct gst_mpp_format
45 {
46   GstVideoFormat gst_format;
47   MppFrameFormat mpp_format;
48 #ifdef HAVE_RGA
49   RgaSURF_FORMAT rga_format;
50 #endif
51   gint pixel_stride0;
52   gboolean is_yuv;
53 };
54 
55 #ifdef HAVE_RGA
56 #define GST_MPP_FORMAT(gst, mpp, rga, pixel_stride0, yuv) \
57   { GST_VIDEO_FORMAT_ ## gst, MPP_FMT_ ## mpp, RK_FORMAT_ ## rga, \
58     pixel_stride0, yuv }
59 #else
60 #define GST_MPP_FORMAT(gst, mpp, rga, pixel_stride0, yuv) \
61   { GST_VIDEO_FORMAT_ ## gst, MPP_FMT_ ## mpp, pixel_stride0, yuv}
62 #endif
63 
64 struct gst_mpp_format gst_mpp_formats[] = {
65   GST_MPP_FORMAT (I420, YUV420P, YCbCr_420_P, 1, 1),
66   GST_MPP_FORMAT (YV12, BUTT, YCrCb_420_P, 1, 1),
67   GST_MPP_FORMAT (NV12, YUV420SP, YCbCr_420_SP, 1, 1),
68   GST_MPP_FORMAT (NV21, YUV420SP_VU, YCrCb_420_SP, 1, 1),
69 #ifdef HAVE_NV12_10LE40
70   GST_MPP_FORMAT (NV12_10LE40, YUV420SP_10BIT, YCbCr_420_SP_10B, 1, 1),
71 #else
72   GST_MPP_FORMAT (UNKNOWN, YUV420SP_10BIT, YCbCr_420_SP_10B, 1, 1),
73 #endif
74 #ifdef HAVE_NV16_10LE40
75   GST_MPP_FORMAT (NV16_10LE40, YUV422SP_10BIT, YCbCr_422_SP_10B, 1, 1),
76 #else
77   GST_MPP_FORMAT (UNKNOWN, YUV422SP_10BIT, YCbCr_422_SP_10B, 1, 1),
78 #endif
79   GST_MPP_FORMAT (Y42B, YUV422P, YCbCr_422_P, 1, 1),
80   GST_MPP_FORMAT (NV16, YUV422SP, YCbCr_422_SP, 1, 1),
81   GST_MPP_FORMAT (NV61, YUV422SP_VU, YCrCb_422_SP, 1, 1),
82   GST_MPP_FORMAT (NV24, YUV444SP, UNKNOWN, 1, 1),
83   GST_MPP_FORMAT (Y444, YUV444P, UNKNOWN, 1, 1),
84   GST_MPP_FORMAT (YUY2, YUV422_YUYV, UNKNOWN, 2, 1),
85   GST_MPP_FORMAT (YVYU, YUV422_YVYU, UNKNOWN, 2, 1),
86   GST_MPP_FORMAT (UYVY, YUV422_UYVY, UNKNOWN, 2, 1),
87   GST_MPP_FORMAT (VYUY, YUV422_VYUY, UNKNOWN, 2, 1),
88   GST_MPP_FORMAT (RGB16, RGB565LE, UNKNOWN, 2, 0),
89   GST_MPP_FORMAT (BGR16, BGR565LE, RGB_565, 2, 0),
90   GST_MPP_FORMAT (RGB, RGB888, RGB_888, 3, 0),
91   GST_MPP_FORMAT (BGR, BGR888, BGR_888, 3, 0),
92   GST_MPP_FORMAT (ARGB, ARGB8888, UNKNOWN, 4, 0),
93   GST_MPP_FORMAT (ABGR, ABGR8888, UNKNOWN, 4, 0),
94   GST_MPP_FORMAT (RGBA, RGBA8888, RGBA_8888, 4, 0),
95   GST_MPP_FORMAT (BGRA, BGRA8888, BGRA_8888, 4, 0),
96   GST_MPP_FORMAT (xRGB, ARGB8888, UNKNOWN, 4, 0),
97   GST_MPP_FORMAT (xBGR, ABGR8888, UNKNOWN, 4, 0),
98   GST_MPP_FORMAT (RGBx, RGBA8888, RGBX_8888, 4, 0),
99   GST_MPP_FORMAT (BGRx, BGRA8888, BGRX_8888, 4, 0),
100 };
101 
102 #define GST_MPP_GET_FORMAT(type, format) ({ \
103   struct gst_mpp_format *_tmp; \
104   for (guint i = 0; i < ARRAY_SIZE (gst_mpp_formats) || (_tmp = NULL); i++) { \
105     _tmp = &gst_mpp_formats[i]; \
106     if (_tmp->type ## _format == (format)) break;\
107   }; _tmp; \
108 })
109 
110 gboolean
gst_mpp_use_rga()111 gst_mpp_use_rga ()
112 {
113   static int mpp_use_rga = -1;
114 
115 #ifdef HAVE_RGA
116   if (mpp_use_rga < 0) {
117     const gchar *buf = g_getenv ("GST_MPP_NO_RGA");
118     if (!buf || buf[0] == '0')
119       mpp_use_rga = 1;
120     else
121       mpp_use_rga = 0;
122   }
123 #endif
124 
125   return mpp_use_rga > 0;
126 }
127 
128 const gchar *
gst_mpp_video_format_to_string(GstVideoFormat format)129 gst_mpp_video_format_to_string (GstVideoFormat format)
130 {
131   if (format == GST_VIDEO_FORMAT_UNKNOWN)
132     return "UNKNOWN";
133 
134   return gst_video_format_to_string (format);
135 }
136 
137 GstVideoFormat
gst_mpp_mpp_format_to_gst_format(MppFrameFormat mpp_format)138 gst_mpp_mpp_format_to_gst_format (MppFrameFormat mpp_format)
139 {
140   struct gst_mpp_format *format = GST_MPP_GET_FORMAT (mpp,
141       mpp_format & MPP_FRAME_FMT_MASK);
142   return format ? format->gst_format : GST_VIDEO_FORMAT_UNKNOWN;
143 }
144 
145 MppFrameFormat
gst_mpp_gst_format_to_mpp_format(GstVideoFormat gst_format)146 gst_mpp_gst_format_to_mpp_format (GstVideoFormat gst_format)
147 {
148   struct gst_mpp_format *format = GST_MPP_GET_FORMAT (gst, gst_format);
149   return format ? format->mpp_format : MPP_FMT_BUTT;
150 }
151 
152 #ifdef HAVE_RGA
153 static RgaSURF_FORMAT
gst_mpp_mpp_format_to_rga_format(MppFrameFormat mpp_format)154 gst_mpp_mpp_format_to_rga_format (MppFrameFormat mpp_format)
155 {
156   struct gst_mpp_format *format = GST_MPP_GET_FORMAT (mpp,
157       mpp_format & MPP_FRAME_FMT_MASK);
158   return format ? format->rga_format : RK_FORMAT_UNKNOWN;
159 }
160 
161 static RgaSURF_FORMAT
gst_mpp_gst_format_to_rga_format(GstVideoFormat gst_format)162 gst_mpp_gst_format_to_rga_format (GstVideoFormat gst_format)
163 {
164   struct gst_mpp_format *format = GST_MPP_GET_FORMAT (gst, gst_format);
165   return format ? format->rga_format : RK_FORMAT_UNKNOWN;
166 }
167 
168 static gboolean
gst_mpp_set_rga_info(rga_info_t * info,RgaSURF_FORMAT rga_format,guint width,guint height,guint hstride,guint vstride)169 gst_mpp_set_rga_info (rga_info_t * info, RgaSURF_FORMAT rga_format,
170     guint width, guint height, guint hstride, guint vstride)
171 {
172   struct gst_mpp_format *format = GST_MPP_GET_FORMAT (rga, rga_format);
173 
174   g_assert (format);
175   if (format->is_yuv) {
176     /* RGA requires yuv image rect align to 2 */
177     width &= ~1;
178     height &= ~1;
179 
180     if (vstride % 2)
181       return FALSE;
182   }
183 
184   if (info->fd < 0 && !info->virAddr)
185     return FALSE;
186 
187   info->mmuFlag = 1;
188   rga_set_rect (&info->rect, 0, 0, width, height, hstride, vstride, rga_format);
189   return TRUE;
190 }
191 
192 static gboolean
gst_mpp_rga_info_from_mpp_frame(rga_info_t * info,MppFrame mframe)193 gst_mpp_rga_info_from_mpp_frame (rga_info_t * info, MppFrame mframe)
194 {
195   MppFrameFormat mpp_format = mpp_frame_get_fmt (mframe);
196   MppBuffer mbuf = mpp_frame_get_buffer (mframe);
197   guint width = mpp_frame_get_width (mframe);
198   guint height = mpp_frame_get_height (mframe);
199   guint hstride = mpp_frame_get_hor_stride (mframe);
200   guint vstride = mpp_frame_get_ver_stride (mframe);
201   RgaSURF_FORMAT rga_format = gst_mpp_mpp_format_to_rga_format (mpp_format);
202 
203   g_return_val_if_fail (mbuf, FALSE);
204 
205   info->fd = mpp_buffer_get_fd (mbuf);
206 
207   return gst_mpp_set_rga_info (info, rga_format, width, height,
208       hstride, vstride);
209 }
210 
211 static gboolean
gst_mpp_rga_info_from_video_info(rga_info_t * info,GstVideoInfo * vinfo)212 gst_mpp_rga_info_from_video_info (rga_info_t * info, GstVideoInfo * vinfo)
213 {
214   GstVideoFormat format = GST_VIDEO_INFO_FORMAT (vinfo);
215   guint width = GST_VIDEO_INFO_WIDTH (vinfo);
216   guint height = GST_VIDEO_INFO_HEIGHT (vinfo);
217   guint hstride = GST_MPP_VIDEO_INFO_HSTRIDE (vinfo);
218   guint vstride = GST_MPP_VIDEO_INFO_VSTRIDE (vinfo);
219   RgaSURF_FORMAT rga_format = gst_mpp_gst_format_to_rga_format (format);
220 
221   return gst_mpp_set_rga_info (info, rga_format, width, height,
222       hstride, vstride);
223 }
224 
225 static gboolean
gst_mpp_rga_do_convert(rga_info_t * src_info,rga_info_t * dst_info)226 gst_mpp_rga_do_convert (rga_info_t * src_info, rga_info_t * dst_info)
227 {
228   static gint rga_supported = 1;
229   static gint rga_inited = 0;
230 
231   if (!rga_supported || !gst_mpp_use_rga ())
232     return FALSE;
233 
234   if (!rga_inited) {
235     if (c_RkRgaInit () < 0) {
236       rga_supported = 0;
237       GST_WARNING ("failed to init RGA");
238       return FALSE;
239     }
240     rga_inited = 1;
241   }
242 
243   if (c_RkRgaBlit (src_info, dst_info, NULL) < 0) {
244     GST_WARNING ("failed to blit");
245     return FALSE;
246   }
247 
248   GST_DEBUG ("converted with RGA");
249   return TRUE;
250 }
251 
252 static gint
gst_mpp_rga_get_rotation(gint rotation)253 gst_mpp_rga_get_rotation (gint rotation)
254 {
255   switch (rotation) {
256     case 0:
257       return 0;
258     case 90:
259       return HAL_TRANSFORM_ROT_90;
260     case 180:
261       return HAL_TRANSFORM_ROT_180;
262     case 270:
263       return HAL_TRANSFORM_ROT_270;
264     default:
265       return -1;
266   }
267 }
268 
269 gboolean
gst_mpp_rga_convert(GstBuffer * inbuf,GstVideoInfo * src_vinfo,GstMemory * out_mem,GstVideoInfo * dst_vinfo,gint rotation)270 gst_mpp_rga_convert (GstBuffer * inbuf, GstVideoInfo * src_vinfo,
271     GstMemory * out_mem, GstVideoInfo * dst_vinfo, gint rotation)
272 {
273   GstMapInfo mapinfo = { 0, };
274   gboolean ret;
275 
276   rga_info_t src_info = { 0, };
277   rga_info_t dst_info = { 0, };
278 
279   if (!gst_mpp_rga_info_from_video_info (&src_info, src_vinfo))
280     return FALSE;
281 
282   if (!gst_mpp_rga_info_from_video_info (&dst_info, dst_vinfo))
283     return FALSE;
284 
285   /* Prefer using dma fd */
286   if (gst_buffer_n_memory (inbuf) == 1) {
287     GstMemory *mem = gst_buffer_peek_memory (inbuf, 0);
288     gsize offset;
289 
290     if (gst_is_dmabuf_memory (mem)) {
291       gst_memory_get_sizes (mem, &offset, NULL);
292       if (!offset)
293         src_info.fd = gst_dmabuf_memory_get_fd (mem);
294     }
295   }
296 
297   if (src_info.fd <= 0) {
298     gst_buffer_map (inbuf, &mapinfo, GST_MAP_READ);
299     src_info.virAddr = mapinfo.data;
300   }
301 
302   dst_info.fd = gst_dmabuf_memory_get_fd (out_mem);
303 
304   src_info.rotation = gst_mpp_rga_get_rotation (rotation);
305   if (src_info.rotation < 0)
306     return FALSE;
307 
308   ret = gst_mpp_rga_do_convert (&src_info, &dst_info);
309 
310   gst_buffer_unmap (inbuf, &mapinfo);
311   return ret;
312 }
313 
314 gboolean
gst_mpp_rga_convert_from_mpp_frame(MppFrame * mframe,GstMemory * out_mem,GstVideoInfo * dst_vinfo,gint rotation)315 gst_mpp_rga_convert_from_mpp_frame (MppFrame * mframe,
316     GstMemory * out_mem, GstVideoInfo * dst_vinfo, gint rotation)
317 {
318   rga_info_t src_info = { 0, };
319   rga_info_t dst_info = { 0, };
320 
321   if (!gst_mpp_rga_info_from_mpp_frame (&src_info, mframe))
322     return FALSE;
323 
324   if (!gst_mpp_rga_info_from_video_info (&dst_info, dst_vinfo))
325     return FALSE;
326 
327   dst_info.fd = gst_dmabuf_memory_get_fd (out_mem);
328 
329   src_info.rotation = gst_mpp_rga_get_rotation (rotation);
330   if (src_info.rotation < 0)
331     return FALSE;
332 
333   return gst_mpp_rga_do_convert (&src_info, &dst_info);
334 }
335 #endif
336 
337 void
gst_mpp_video_info_update_format(GstVideoInfo * info,GstVideoFormat format,guint width,guint height)338 gst_mpp_video_info_update_format (GstVideoInfo * info, GstVideoFormat format,
339     guint width, guint height)
340 {
341   GstCaps *caps;
342   const gchar *fmt = gst_mpp_video_format_to_string (format);
343 
344   GST_DEBUG ("update format to %s (%dx%d)", fmt, width, height);
345 
346   if (GST_VIDEO_INFO_FORMAT (info) == GST_VIDEO_FORMAT_UNKNOWN) {
347     gst_video_info_set_format (info, format, width, height);
348     return;
349   }
350 
351   caps = gst_video_info_to_caps (info);
352   gst_caps_set_simple (caps, "format", G_TYPE_STRING, fmt,
353       "width", G_TYPE_INT, width, "height", G_TYPE_INT, height, NULL);
354   gst_video_info_from_caps (info, caps);
355   gst_caps_unref (caps);
356 }
357 
358 gboolean
gst_mpp_video_info_align(GstVideoInfo * info,gint hstride,gint vstride)359 gst_mpp_video_info_align (GstVideoInfo * info, gint hstride, gint vstride)
360 {
361   GstVideoAlignment align;
362   guint stride;
363   guint i;
364 
365   if (!hstride)
366     hstride = GST_MPP_ALIGN (GST_MPP_VIDEO_INFO_HSTRIDE (info));
367 
368   if (!vstride)
369     vstride = GST_MPP_ALIGN (GST_MPP_VIDEO_INFO_VSTRIDE (info));
370 
371   GST_DEBUG ("aligning %dx%d to %dx%d", GST_VIDEO_INFO_WIDTH (info),
372       GST_VIDEO_INFO_HEIGHT (info), hstride, vstride);
373 
374   gst_video_alignment_reset (&align);
375 
376   /* Apply vstride */
377   align.padding_bottom = vstride - GST_VIDEO_INFO_HEIGHT (info);
378   if (!gst_video_info_align (info, &align))
379     return FALSE;
380 
381   /* Apply vstride for single-plane */
382   if (GST_VIDEO_INFO_N_PLANES (info) == 1)
383     GST_VIDEO_INFO_SIZE (info) =
384         GST_VIDEO_INFO_PLANE_STRIDE (info, 0) * vstride;
385 
386   if (GST_VIDEO_INFO_PLANE_STRIDE (info, 0) == hstride)
387     return TRUE;
388 
389   /* Apply hstride */
390   stride = GST_VIDEO_INFO_PLANE_STRIDE (info, 0);
391   for (i = 0; i < GST_VIDEO_INFO_N_PLANES (info); i++) {
392     GST_VIDEO_INFO_PLANE_STRIDE (info, i) =
393         GST_VIDEO_INFO_PLANE_STRIDE (info, i) * hstride / stride;
394     GST_VIDEO_INFO_PLANE_OFFSET (info, i) =
395         GST_VIDEO_INFO_PLANE_OFFSET (info, i) / stride * hstride;
396 
397     GST_DEBUG ("plane %d, stride %d, offset %" G_GSIZE_FORMAT, i,
398         GST_VIDEO_INFO_PLANE_STRIDE (info, i),
399         GST_VIDEO_INFO_PLANE_OFFSET (info, i));
400   }
401   GST_VIDEO_INFO_SIZE (info) = GST_VIDEO_INFO_SIZE (info) / stride * hstride;
402 
403   GST_DEBUG ("aligned size %" G_GSIZE_FORMAT, GST_VIDEO_INFO_SIZE (info));
404 
405   return TRUE;
406 }
407 
408 guint
gst_mpp_get_pixel_stride(GstVideoInfo * info)409 gst_mpp_get_pixel_stride (GstVideoInfo * info)
410 {
411   GstVideoFormat gst_format = GST_VIDEO_INFO_FORMAT (info);
412   struct gst_mpp_format *format = GST_MPP_GET_FORMAT (gst, gst_format);
413   guint hstride = GST_MPP_VIDEO_INFO_HSTRIDE (info);
414 
415   if (!format)
416     return hstride;
417 
418   return hstride / format->pixel_stride0;
419 }
420 
421 static gboolean
plugin_init(GstPlugin * plugin)422 plugin_init (GstPlugin * plugin)
423 {
424   GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "mpp", 0, "MPP");
425 
426   gst_mpp_h264_enc_register (plugin, GST_RANK_PRIMARY + 1);
427   gst_mpp_h265_enc_register (plugin, GST_RANK_PRIMARY + 1);
428   gst_mpp_vp8_enc_register (plugin, GST_RANK_PRIMARY + 1);
429   gst_mpp_jpeg_enc_register (plugin, GST_RANK_PRIMARY + 1);
430 
431   gst_mpp_video_dec_register (plugin, GST_RANK_PRIMARY + 1);
432   gst_mpp_jpeg_dec_register (plugin, GST_RANK_PRIMARY + 1);
433 
434 #ifdef USE_VPXALPHADEC
435   gst_mpp_vpx_alpha_decode_bin_register (plugin,
436       GST_RANK_PRIMARY + GST_MPP_ALPHA_DECODE_BIN_RANK_OFFSET);
437 #endif
438 
439   return TRUE;
440 }
441 
442 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
443     GST_VERSION_MINOR,
444     rockchipmpp,
445     "Rockchip Mpp Video Plugin",
446     plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN);
447