xref: /rockchip-linux_mpp/mpp/mpi.c (revision 437bfbeb9567cca9cd9080e3f6954aa9d6a94f18)
1 /* SPDX-License-Identifier: Apache-2.0 OR MIT */
2 /*
3  * Copyright (c) 2015 Rockchip Electronics Co., Ltd.
4  */
5 
6 #define MODULE_TAG "mpi"
7 
8 #include <string.h>
9 
10 #include "rk_mpi.h"
11 
12 #include "mpp_env.h"
13 #include "mpp_mem.h"
14 #include "mpp_debug.h"
15 #include "mpp_common.h"
16 
17 #include "mpi_impl.h"
18 #include "mpp_info.h"
19 
20 RK_U32 mpi_debug = 0;
21 
22 typedef struct {
23     MppCtxType      type;
24     MppCodingType   coding;
25     const char      *type_name;
26     const char      *coding_name;
27 } MppCodingTypeInfo;
28 
29 static MppCodingTypeInfo support_list[] = {
30 #if HAVE_MPEG2D
31     {   MPP_CTX_DEC,    MPP_VIDEO_CodingMPEG2,      "dec",  "mpeg2",        },
32 #endif
33 #if HAVE_MPEG4D
34     {   MPP_CTX_DEC,    MPP_VIDEO_CodingMPEG4,      "dec",  "mpeg4",        },
35 #endif
36 #if HAVE_H263D
37     {   MPP_CTX_DEC,    MPP_VIDEO_CodingH263,       "dec",  "h.263",        },
38 #endif
39 #if HAVE_H264D
40     {   MPP_CTX_DEC,    MPP_VIDEO_CodingAVC,        "dec",  "h.264/AVC",    },
41 #endif
42 #if HAVE_H265D
43     {   MPP_CTX_DEC,    MPP_VIDEO_CodingHEVC,       "dec",  "h.265/HEVC",   },
44 #endif
45 #if HAVE_VP8D
46     {   MPP_CTX_DEC,    MPP_VIDEO_CodingVP8,        "dec",  "vp8",          },
47 #endif
48 #if HAVE_VP9D
49     {   MPP_CTX_DEC,    MPP_VIDEO_CodingVP9,        "dec",  "VP9",          },
50 #endif
51 #if HAVE_AVSD
52     {   MPP_CTX_DEC,    MPP_VIDEO_CodingAVS,        "dec",  "avs",          },
53     {   MPP_CTX_DEC,    MPP_VIDEO_CodingAVSPLUS,    "dec",  "avs+",         },
54 #endif
55 #if HAVE_AVS2D
56     {   MPP_CTX_DEC,    MPP_VIDEO_CodingAVS2,       "dec",  "avs2",         },
57 #endif
58 #if HAVE_JPEGD
59     {   MPP_CTX_DEC,    MPP_VIDEO_CodingMJPEG,      "dec",  "jpeg",         },
60 #endif
61 #if HAVE_AV1D
62     {   MPP_CTX_DEC,    MPP_VIDEO_CodingAV1,        "dec",  "av1",          },
63 #endif
64 #if HAVE_H264E
65     {   MPP_CTX_ENC,    MPP_VIDEO_CodingAVC,        "enc",  "h.264/AVC",    },
66 #endif
67 #if HAVE_JPEGE
68     {   MPP_CTX_ENC,    MPP_VIDEO_CodingMJPEG,      "enc",  "jpeg",         },
69 #endif
70 #if HAVE_H265E
71     {   MPP_CTX_ENC,    MPP_VIDEO_CodingHEVC,       "enc",  "h265",         },
72 #endif
73 #if HAVE_VP8E
74     {   MPP_CTX_ENC,    MPP_VIDEO_CodingVP8,        "enc",  "vp8",          }
75 #endif
76 };
77 
78 #define check_mpp_ctx(ctx)  _check_mpp_ctx(ctx, __FUNCTION__)
79 
_check_mpp_ctx(MpiImpl * p,const char * caller)80 static MPP_RET _check_mpp_ctx(MpiImpl *p, const char *caller)
81 {
82     if (NULL == p || p->check != p || NULL == p->ctx) {
83         _mpp_err(MODULE_TAG, "found invalid context %p\n", caller, p);
84         return MPP_ERR_UNKNOW;
85     }
86     return MPP_OK;
87 }
88 
mpi_decode(MppCtx ctx,MppPacket packet,MppFrame * frame)89 static MPP_RET mpi_decode(MppCtx ctx, MppPacket packet, MppFrame *frame)
90 {
91     MPP_RET ret = MPP_NOK;
92     MpiImpl *p = (MpiImpl *)ctx;
93 
94     mpi_dbg_func("enter ctx %p packet %p frame %p\n", ctx, packet, frame);
95 
96     do {
97         ret = check_mpp_ctx(p);
98         if (ret)
99             break;
100 
101         /*
102          * NOTE: packet and frame could be NULL
103          * If packet is NULL then it is equal to get_frame
104          * If frame is NULL then it is equal to put_packet
105          */
106         if (frame)
107             *frame = NULL;
108 
109         ret = mpp_decode(p->ctx, packet, frame);
110     } while (0);
111 
112     mpi_dbg_func("leave ctx %p ret %d\n", ctx, ret);
113     return ret;
114 }
115 
mpi_decode_put_packet(MppCtx ctx,MppPacket packet)116 static MPP_RET mpi_decode_put_packet(MppCtx ctx, MppPacket packet)
117 {
118     MPP_RET ret = MPP_NOK;
119     MpiImpl *p = (MpiImpl *)ctx;
120 
121     mpi_dbg_func("enter ctx %p packet %p\n", ctx, packet);
122     do {
123         ret = check_mpp_ctx(p);
124         if (ret)
125             break;
126 
127         if (NULL == packet) {
128             mpp_err_f("found NULL input packet\n");
129             ret = MPP_ERR_NULL_PTR;
130             break;
131         }
132 
133         ret = mpp_put_packet(p->ctx, packet);
134     } while (0);
135 
136     mpi_dbg_func("leave ctx %p ret %d\n", ctx, ret);
137     return ret;
138 }
139 
mpi_decode_get_frame(MppCtx ctx,MppFrame * frame)140 static MPP_RET mpi_decode_get_frame(MppCtx ctx, MppFrame *frame)
141 {
142     MPP_RET ret = MPP_NOK;
143     MpiImpl *p = (MpiImpl *)ctx;
144 
145     mpi_dbg_func("enter ctx %p frame %p\n", ctx, frame);
146     do {
147         ret = check_mpp_ctx(p);
148         if (ret)
149             break;
150 
151         if (NULL == frame) {
152             mpp_err_f("found NULL input frame\n");
153             ret = MPP_ERR_NULL_PTR;
154             break;
155         }
156 
157         ret = mpp_get_frame(p->ctx, frame);
158     } while (0);
159 
160     mpi_dbg_func("leave ctx %p ret %d\n", ctx, ret);
161     return ret;
162 }
163 
mpi_encode(MppCtx ctx,MppFrame frame,MppPacket * packet)164 static MPP_RET mpi_encode(MppCtx ctx, MppFrame frame, MppPacket *packet)
165 {
166     MPP_RET ret = MPP_NOK;
167     MpiImpl *p = (MpiImpl *)ctx;
168 
169     mpi_dbg_func("enter ctx %p frame %p packet %p\n", ctx, frame, packet);
170     do {
171         ret = check_mpp_ctx(p);
172         if (ret)
173             break;
174 
175         if (NULL == frame || NULL == packet) {
176             mpp_err_f("found NULL input frame %p packet %p\n", frame, packet);
177             ret = MPP_ERR_NULL_PTR;
178             break;
179         }
180 
181         // TODO: do encode here
182     } while (0);
183 
184     mpi_dbg_func("leave ctx %p ret %d\n", ctx, ret);
185     return ret;
186 }
187 
mpi_encode_put_frame(MppCtx ctx,MppFrame frame)188 static MPP_RET mpi_encode_put_frame(MppCtx ctx, MppFrame frame)
189 {
190     MPP_RET ret = MPP_NOK;
191     MpiImpl *p = (MpiImpl *)ctx;
192 
193     mpi_dbg_func("enter ctx %p frame %p\n", ctx, frame);
194     do {
195         ret = check_mpp_ctx(p);
196         if (ret)
197             break;
198 
199         if (NULL == frame) {
200             mpp_err_f("found NULL input frame\n");
201             ret = MPP_ERR_NULL_PTR;
202             break;
203         }
204 
205         ret = mpp_put_frame(p->ctx, frame);
206     } while (0);
207 
208     mpi_dbg_func("leave ctx %p ret %d\n", ctx, ret);
209     return ret;
210 }
211 
mpi_encode_get_packet(MppCtx ctx,MppPacket * packet)212 static MPP_RET mpi_encode_get_packet(MppCtx ctx, MppPacket *packet)
213 {
214     MPP_RET ret = MPP_NOK;
215     MpiImpl *p = (MpiImpl *)ctx;
216 
217     mpi_dbg_func("enter ctx %p packet %p\n", ctx, packet);
218     do {
219         ret = check_mpp_ctx(p);
220         if (ret)
221             break;
222 
223         if (NULL == packet) {
224             mpp_err_f("found NULL input packet\n");
225             ret = MPP_ERR_NULL_PTR;
226             break;
227         }
228 
229         ret = mpp_get_packet(p->ctx, packet);
230     } while (0);
231 
232     mpi_dbg_func("leave ctx %p ret %d\n", ctx, ret);
233     return ret;
234 }
235 
mpi_isp(MppCtx ctx,MppFrame dst,MppFrame src)236 static MPP_RET mpi_isp(MppCtx ctx, MppFrame dst, MppFrame src)
237 {
238     MPP_RET ret = MPP_OK;
239     mpi_dbg_func("enter ctx %p dst %p src %p\n", ctx, dst, src);
240 
241     // TODO: do isp process here
242 
243     mpi_dbg_func("leave ctx %p ret %d\n", ctx, ret);
244     return MPP_OK;
245 }
246 
mpi_isp_put_frame(MppCtx ctx,MppFrame frame)247 static MPP_RET mpi_isp_put_frame(MppCtx ctx, MppFrame frame)
248 {
249     MPP_RET ret = MPP_OK;
250     mpi_dbg_func("enter ctx %p frame %p\n", ctx, frame);
251 
252     // TODO: do isp put frame process here
253 
254     mpi_dbg_func("leave ctx %p ret %d\n", ctx, ret);
255     return ret;
256 }
257 
mpi_isp_get_frame(MppCtx ctx,MppFrame * frame)258 static MPP_RET mpi_isp_get_frame(MppCtx ctx, MppFrame *frame)
259 {
260     MPP_RET ret = MPP_OK;
261     mpi_dbg_func("enter ctx %p frame %p\n", ctx, frame);
262 
263     // TODO: do isp get frame process here
264 
265     mpi_dbg_func("leave ret %d\n", ret);
266     return ret;
267 }
268 
mpi_poll(MppCtx ctx,MppPortType type,MppPollType timeout)269 static MPP_RET mpi_poll(MppCtx ctx, MppPortType type, MppPollType timeout)
270 {
271     MPP_RET ret = MPP_NOK;
272     MpiImpl *p = (MpiImpl *)ctx;
273 
274     mpi_dbg_func("enter ctx %p type %d timeout %d\n", ctx, type, timeout);
275     do {
276         ret = check_mpp_ctx(p);
277         if (ret)
278             break;;
279 
280         if (type >= MPP_PORT_BUTT ||
281             timeout < MPP_POLL_BUTT ||
282             timeout > MPP_POLL_MAX) {
283             mpp_err_f("invalid input type %d timeout %d\n", type, timeout);
284             ret = MPP_ERR_UNKNOW;
285             break;
286         }
287 
288         ret = mpp_poll(p->ctx, type, timeout);
289         if (ret > 0)
290             ret = MPP_OK;
291     } while (0);
292 
293     mpi_dbg_func("leave ctx %p ret %d\n", ctx, ret);
294     return ret;
295 }
296 
mpi_dequeue(MppCtx ctx,MppPortType type,MppTask * task)297 static MPP_RET mpi_dequeue(MppCtx ctx, MppPortType type, MppTask *task)
298 {
299     MPP_RET ret = MPP_NOK;
300     MpiImpl *p = (MpiImpl *)ctx;
301 
302     mpi_dbg_func("enter ctx %p type %d task %p\n", ctx, type, task);
303     do {
304         ret = check_mpp_ctx(p);
305         if (ret)
306             break;;
307 
308         if (type >= MPP_PORT_BUTT || NULL == task) {
309             mpp_err_f("invalid input type %d task %p\n", type, task);
310             ret = MPP_ERR_UNKNOW;
311             break;
312         }
313 
314         ret = mpp_dequeue(p->ctx, type, task);
315     } while (0);
316 
317     mpi_dbg_func("leave ctx %p ret %d\n", ctx, ret);
318     return ret;
319 }
320 
mpi_enqueue(MppCtx ctx,MppPortType type,MppTask task)321 static MPP_RET mpi_enqueue(MppCtx ctx, MppPortType type, MppTask task)
322 {
323     MPP_RET ret = MPP_NOK;
324     MpiImpl *p = (MpiImpl *)ctx;
325 
326     mpi_dbg_func("enter ctx %p type %d task %p\n", ctx, type, task);
327     do {
328         ret = check_mpp_ctx(p);
329         if (ret)
330             break;;
331 
332         if (type >= MPP_PORT_BUTT || NULL == task) {
333             mpp_err_f("invalid input type %d task %p\n", type, task);
334             ret = MPP_ERR_UNKNOW;
335             break;
336         }
337 
338         ret = mpp_enqueue(p->ctx, type, task);
339     } while (0);
340 
341     mpi_dbg_func("leave ctx %p ret %d\n", ctx, ret);
342     return ret;
343 }
344 
mpi_reset(MppCtx ctx)345 static MPP_RET mpi_reset(MppCtx ctx)
346 {
347     MPP_RET ret = MPP_NOK;
348     MpiImpl *p = (MpiImpl *)ctx;
349 
350     mpi_dbg_func("enter ctx %p\n", ctx);
351     do {
352         ret = check_mpp_ctx(p);
353         if (ret)
354             break;;
355 
356         ret = mpp_reset(p->ctx);
357     } while (0);
358 
359     mpi_dbg_func("leave ctx %p ret %d\n", ctx, ret);
360     return ret;
361 }
362 
mpi_control(MppCtx ctx,MpiCmd cmd,MppParam param)363 static MPP_RET mpi_control(MppCtx ctx, MpiCmd cmd, MppParam param)
364 {
365     MPP_RET ret = MPP_NOK;
366     MpiImpl *p = (MpiImpl *)ctx;
367 
368     mpi_dbg_func("enter ctx %p cmd %x parm %p\n", ctx, cmd, param);
369     do {
370         ret = check_mpp_ctx(p);
371         if (ret)
372             break;;
373 
374         ret = mpp_control(p->ctx, cmd, param);
375     } while (0);
376 
377     mpi_dbg_func("leave ctx %p ret %d\n", ctx, ret);
378     return ret;
379 }
380 
381 static MppApi mpp_api = {
382     .size              = sizeof(mpp_api),
383     .version           = 0,
384     .decode            = mpi_decode,
385     .decode_put_packet = mpi_decode_put_packet,
386     .decode_get_frame  = mpi_decode_get_frame,
387     .encode            = mpi_encode,
388     .encode_put_frame  = mpi_encode_put_frame,
389     .encode_get_packet = mpi_encode_get_packet,
390     .isp               = mpi_isp,
391     .isp_put_frame     = mpi_isp_put_frame,
392     .isp_get_frame     = mpi_isp_get_frame,
393     .poll              = mpi_poll,
394     .dequeue           = mpi_dequeue,
395     .enqueue           = mpi_enqueue,
396     .reset             = mpi_reset,
397     .control           = mpi_control,
398     .reserv            = {0},
399 };
400 
mpp_create(MppCtx * ctx,MppApi ** mpi)401 MPP_RET mpp_create(MppCtx *ctx, MppApi **mpi)
402 {
403     mpp_env_get_u32("mpi_debug", &mpi_debug, 0);
404     mpp_get_log_level();
405 
406     if (NULL == ctx || NULL == mpi) {
407         mpp_err_f("invalid input ctx %p mpi %p\n", ctx, mpi);
408         return MPP_ERR_NULL_PTR;
409     }
410 
411     *ctx = NULL;
412     *mpi = NULL;
413 
414     MPP_RET ret = MPP_OK;
415     mpi_dbg_func("enter ctx %p mpi %p\n", ctx, mpi);
416     do {
417         MpiImpl *p = mpp_malloc(MpiImpl, 1);
418         if (NULL == p) {
419             mpp_err_f("failed to allocate context\n");
420             ret = MPP_ERR_MALLOC;
421             break;
422         }
423 
424         memset(p, 0, sizeof(*p));
425         ret = mpp_ctx_create(&p->ctx, p);
426         if (ret || NULL == p->ctx) {
427             mpp_free(p);
428             mpp_err_f("failed to create Mpp context ret %d\n", ret);
429             ret = MPP_ERR_MALLOC;
430             break;
431         }
432 
433         mpp_api.version = 0;
434         p->api      = &mpp_api;
435         p->check    = p;
436         *ctx = p;
437         *mpi = p->api;
438     } while (0);
439 
440     show_mpp_version();
441 
442     mpi_dbg_func("leave ret %d ctx %p mpi %p\n", ret, *ctx, *mpi);
443     return ret;
444 }
445 
mpp_init(MppCtx ctx,MppCtxType type,MppCodingType coding)446 MPP_RET mpp_init(MppCtx ctx, MppCtxType type, MppCodingType coding)
447 {
448     MPP_RET ret = MPP_OK;
449     MpiImpl *p = (MpiImpl*)ctx;
450 
451     mpi_dbg_func("enter ctx %p type %d coding %d\n", ctx, type, coding);
452     do {
453         ret = check_mpp_ctx(p);
454         if (ret)
455             break;
456 
457         if (type >= MPP_CTX_BUTT ||
458             coding >= MPP_VIDEO_CodingMax) {
459             mpp_err_f("invalid input type %d coding %d\n", type, coding);
460             ret = MPP_ERR_UNKNOW;
461             break;
462         }
463 
464         ret = mpp_ctx_init(p->ctx, type, coding);
465         p->type     = type;
466         p->coding   = coding;
467     } while (0);
468 
469     mpi_dbg_func("leave ctx %p ret %d\n", ctx, ret);
470     return ret;
471 }
472 
mpp_destroy(MppCtx ctx)473 MPP_RET mpp_destroy(MppCtx ctx)
474 {
475     mpi_dbg_func("enter ctx %p\n", ctx);
476 
477     MPP_RET ret = MPP_OK;
478     MpiImpl *p = (MpiImpl*)ctx;
479 
480     do {
481         ret = check_mpp_ctx(p);
482         if (ret)
483             return ret;
484 
485         if (p->ctx)
486             mpp_ctx_destroy(p->ctx);
487 
488         mpp_free(p);
489     } while (0);
490 
491     mpi_dbg_func("leave ctx %p ret %d\n", ctx, ret);
492     return ret;
493 }
494 
mpp_check_support_format(MppCtxType type,MppCodingType coding)495 MPP_RET mpp_check_support_format(MppCtxType type, MppCodingType coding)
496 {
497     MPP_RET ret = MPP_NOK;
498     RK_U32 i = 0;
499 
500     for (i = 0; i < MPP_ARRAY_ELEMS(support_list); i++) {
501         MppCodingTypeInfo *info = &support_list[i];
502         if (type    == info->type &&
503             coding  == info->coding) {
504             ret = MPP_OK;
505             break;
506         }
507     }
508     return ret;
509 }
510 
mpp_show_support_format(void)511 void mpp_show_support_format(void)
512 {
513     RK_U32 i = 0;
514 
515     mpp_log("mpp coding type support list:");
516 
517     for (i = 0; i < MPP_ARRAY_ELEMS(support_list); i++) {
518         MppCodingTypeInfo *info = &support_list[i];
519         mpp_log("type: %s id %d coding: %-16s id %d\n",
520                 info->type_name, info->type,
521                 info->coding_name, info->coding);
522     }
523 }
524 
525 typedef struct {
526     MppFrameFormat  format;
527     const char      *name;
528 } MppFrameFormatInfo;
529 
530 static MppFrameFormatInfo color_list[] = {
531     { MPP_FMT_YUV420SP,         "YUV420SP,      NV12"   },
532     { MPP_FMT_YUV420SP_10BIT,   "YUV420SP-10bit"        },
533     { MPP_FMT_YUV422SP,         "YUV422SP,      NV24"   },
534     { MPP_FMT_YUV422SP_10BIT,   "YUV422SP-10bit"        },
535     { MPP_FMT_YUV420P,          "YUV420P,       I420"   },
536     { MPP_FMT_YUV420SP_VU,      "YUV420SP,      NV21"   },
537     { MPP_FMT_YUV422P,          "YUV422P,       422P"   },
538     { MPP_FMT_YUV422SP_VU,      "YUV422SP,      NV42"   },
539     { MPP_FMT_YUV422_YUYV,      "YUV422-YUYV,   YUY2"   },
540     { MPP_FMT_YUV422_UYVY,      "YUV422-UYVY,   UYVY"   },
541     { MPP_FMT_YUV400,           "YUV400-Y8,     Y800"   },
542     { MPP_FMT_YUV444SP,         "YUV444SP"              },
543     { MPP_FMT_YUV444P,          "YUV444P"               },
544 
545     { MPP_FMT_RGB565,           "RGB565"                },
546     { MPP_FMT_BGR565,           "BGR565"                },
547     { MPP_FMT_RGB555,           "RGB555"                },
548     { MPP_FMT_BGR555,           "BGR555"                },
549     { MPP_FMT_RGB888,           "RGB888"                },
550     { MPP_FMT_BGR888,           "BGR888"                },
551 
552     { MPP_FMT_ARGB8888,         "ARGB8888"              },
553     { MPP_FMT_ABGR8888,         "ABGR8888"              },
554     { MPP_FMT_BGRA8888,         "BGRA8888"              },
555     { MPP_FMT_RGBA8888,         "RGBA8888"              },
556 };
557 
mpp_show_color_format(void)558 void mpp_show_color_format(void)
559 {
560     RK_U32 i = 0;
561 
562     mpp_log("mpp color support list:");
563 
564     for (i = 0; i < MPP_ARRAY_ELEMS(color_list); i++) {
565         MppFrameFormatInfo *info = &color_list[i];
566         mpp_log("color: id %-5d 0x%05x %s\n",
567                 info->format, info->format, info->name);
568     }
569 }
570