xref: /OK3568_Linux_fs/external/mpp/mpp/mpi.cpp (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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