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