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