xref: /rockchip-linux_mpp/mpp/legacy/vpu_api_legacy.cpp (revision 437bfbeb9567cca9cd9080e3f6954aa9d6a94f18)
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 "vpu_api_legacy"
18 
19 #include "string.h"
20 
21 #include "mpp_mem.h"
22 #include "mpp_env.h"
23 #include "mpp_time.h"
24 #include "mpp_debug.h"
25 #include "mpp_common.h"
26 
27 #include "vpu_api_legacy.h"
28 #include "mpp_packet_impl.h"
29 #include "mpp_buffer_impl.h"
30 #include "mpp_frame.h"
31 #include "mpp_compat.h"
32 
33 #define VPU_API_ENC_INPUT_TIMEOUT 100
34 
35 RK_U32 vpu_api_debug = 0;
36 
vpu_pic_type_remap_to_mpp(EncInputPictureType type)37 static MppFrameFormat vpu_pic_type_remap_to_mpp(EncInputPictureType type)
38 {
39     MppFrameFormat ret = MPP_FMT_BUTT;
40     switch (type) {
41     case ENC_INPUT_YUV420_PLANAR : {
42         ret = MPP_FMT_YUV420P;
43     } break;
44     case ENC_INPUT_YUV420_SEMIPLANAR : {
45         ret = MPP_FMT_YUV420SP;
46     } break;
47     case ENC_INPUT_YUV420_SEMIPLANAR_VU : {
48         ret = MPP_FMT_YUV420SP_VU;
49     } break;
50     case ENC_INPUT_YUV422_INTERLEAVED_YUYV : {
51         ret = MPP_FMT_YUV422_YUYV;
52     } break;
53     case ENC_INPUT_YUV422_INTERLEAVED_UYVY : {
54         ret = MPP_FMT_YUV422_UYVY;
55     } break;
56     case ENC_INPUT_RGB565 : {
57         ret = MPP_FMT_RGB565;
58     } break;
59     case ENC_INPUT_BGR565 : {
60         ret = MPP_FMT_BGR565;
61     } break;
62     case ENC_INPUT_RGB555 : {
63         ret = MPP_FMT_RGB555;
64     } break;
65     case ENC_INPUT_BGR555 : {
66         ret = MPP_FMT_BGR555;
67     } break;
68     case ENC_INPUT_RGB444 : {
69         ret = MPP_FMT_RGB444;
70     } break;
71     case ENC_INPUT_BGR444 : {
72         ret = MPP_FMT_BGR444;
73     } break;
74     case ENC_INPUT_RGB888 : {
75         ret = MPP_FMT_RGB888;
76     } break;
77     case ENC_INPUT_BGR888 : {
78         ret = MPP_FMT_BGR888;
79     } break;
80     case ENC_INPUT_RGB101010 : {
81         ret = MPP_FMT_RGB101010;
82     } break;
83     case ENC_INPUT_BGR101010 : {
84         ret = MPP_FMT_BGR101010;
85     } break;
86     default : {
87         mpp_err("There is no match format, err!!!!!!");
88     } break;
89     }
90     return ret;
91 }
92 
vpu_api_set_enc_cfg(MppCtx mpp_ctx,MppApi * mpi,MppEncCfg enc_cfg,MppCodingType coding,MppFrameFormat fmt,EncParameter_t * cfg)93 static MPP_RET vpu_api_set_enc_cfg(MppCtx mpp_ctx, MppApi *mpi, MppEncCfg enc_cfg,
94                                    MppCodingType coding, MppFrameFormat fmt,
95                                    EncParameter_t *cfg)
96 {
97     MPP_RET ret = MPP_OK;
98     RK_S32 width    = cfg->width;
99     RK_S32 height   = cfg->height;
100     RK_S32 bps      = cfg->bitRate;
101     RK_S32 fps_in   = cfg->framerate;
102     RK_S32 fps_out  = (cfg->framerateout) ? (cfg->framerateout) : (fps_in);
103     RK_S32 gop      = (cfg->intraPicRate) ? (cfg->intraPicRate) : (fps_out);
104     RK_S32 qp_init  = (coding == MPP_VIDEO_CodingAVC) ? (26) :
105                       (coding == MPP_VIDEO_CodingMJPEG) ? (10) :
106                       (coding == MPP_VIDEO_CodingVP8) ? (56) :
107                       (coding == MPP_VIDEO_CodingHEVC) ? (26) : (0);
108     RK_S32 qp       = (cfg->qp) ? (cfg->qp) : (qp_init);
109     RK_S32 profile  = cfg->profileIdc;
110     RK_S32 level    = cfg->levelIdc;
111     RK_S32 cabac_en = cfg->enableCabac;
112     RK_S32 rc_mode  = cfg->rc_mode;
113     RK_U32 is_fix_qp = (rc_mode == MPP_ENC_RC_MODE_FIXQP) ? 1 : 0;
114 
115     RK_S32 qp_max   = (cfg->reserved[0] & 0xFF00) >> 8;
116     RK_S32 qp_min   = cfg->reserved[0] & 0x00FF;
117 
118     if (qp_max == 0 || qp_max < qp) {
119         qp_max = 51;
120     }
121     if (qp_min == 0 || qp_min > qp) {
122         qp_min = 10;
123     }
124 
125     mpp_log("setup encoder rate control config:\n");
126     mpp_log("width %4d height %4d format %d:%x\n", width, height, cfg->format, fmt);
127     mpp_log("rc_mode %s qp %d bps %d\n", (rc_mode) ? ("CBR") : ("CQP"), qp, bps);
128     mpp_log("fps in %d fps out %d gop %d\n", fps_in, fps_out, gop);
129     mpp_log("setup encoder stream feature config:\n");
130     mpp_log("profile %d level %d cabac %d\n", profile, level, cabac_en);
131     mpp_log("setup encoder qp_init %d qp_min %d qp_max %d\n", qp, qp_min, qp_max);
132 
133     mpp_assert(width);
134     mpp_assert(height);
135     mpp_assert(qp);
136 
137     mpp_enc_cfg_set_s32(enc_cfg, "prep:width", width);
138     mpp_enc_cfg_set_s32(enc_cfg, "prep:height", height);
139     switch (fmt & MPP_FRAME_FMT_MASK) {
140     case MPP_FMT_YUV420P:
141     case MPP_FMT_YUV420SP :
142     case MPP_FMT_YUV420SP_VU : {
143         mpp_enc_cfg_set_s32(enc_cfg, "prep:hor_stride", MPP_ALIGN(width, 16));
144     } break;
145     case MPP_FMT_RGB565:
146     case MPP_FMT_BGR565:
147     case MPP_FMT_RGB555:
148     case MPP_FMT_BGR555: {
149         mpp_enc_cfg_set_s32(enc_cfg, "prep:hor_stride", 2 * MPP_ALIGN(width, 16));
150     } break;
151     case MPP_FMT_RGB888 :
152     case MPP_FMT_BGR888 : {
153         mpp_enc_cfg_set_s32(enc_cfg, "prep:hor_stride", 3 * MPP_ALIGN(width, 16));
154     } break;
155     case MPP_FMT_ARGB8888 :
156     case MPP_FMT_ABGR8888 :
157     case MPP_FMT_BGRA8888 :
158     case MPP_FMT_RGBA8888 : {
159         mpp_enc_cfg_set_s32(enc_cfg, "prep:hor_stride", 4 * MPP_ALIGN(width, 16));
160     } break;
161     default: {
162         mpp_err("unsupport format 0x%x\n", fmt & MPP_FRAME_FMT_MASK);
163     } break;
164     }
165     mpp_enc_cfg_set_s32(enc_cfg, "prep:ver_stride", MPP_ALIGN(height, 8));
166     mpp_enc_cfg_set_s32(enc_cfg, "prep:format", fmt);
167 
168     mpp_enc_cfg_set_s32(enc_cfg, "rc:mode", is_fix_qp ? MPP_ENC_RC_MODE_FIXQP :
169                         (rc_mode ? MPP_ENC_RC_MODE_CBR : MPP_ENC_RC_MODE_VBR));
170     mpp_enc_cfg_set_s32(enc_cfg, "rc:bps_target", bps);
171     mpp_enc_cfg_set_s32(enc_cfg, "rc:bps_max", bps * 17 / 16);
172     mpp_enc_cfg_set_s32(enc_cfg, "rc:bps_min", rc_mode ? bps * 15 / 16 : bps * 1 / 16);
173     mpp_enc_cfg_set_s32(enc_cfg, "rc:fps_in_flex", 0);
174     mpp_enc_cfg_set_s32(enc_cfg, "rc:fps_in_num", fps_in);
175     mpp_enc_cfg_set_s32(enc_cfg, "rc:fps_in_denom", 1);
176     mpp_enc_cfg_set_s32(enc_cfg, "rc:fps_out_flex", 0);
177     mpp_enc_cfg_set_s32(enc_cfg, "rc:fps_out_num", fps_out);
178     mpp_enc_cfg_set_s32(enc_cfg, "rc:fps_out_denom", 1);
179     mpp_enc_cfg_set_s32(enc_cfg, "rc:gop", gop);
180 
181     mpp_enc_cfg_set_s32(enc_cfg, "codec:type", coding);
182     switch (coding) {
183     case MPP_VIDEO_CodingAVC : {
184         mpp_enc_cfg_set_s32(enc_cfg, "h264:profile", profile);
185         mpp_enc_cfg_set_s32(enc_cfg, "h264:level", level);
186         mpp_enc_cfg_set_s32(enc_cfg, "h264:cabac_en", cabac_en);
187         mpp_enc_cfg_set_s32(enc_cfg, "h264:cabac_idc", 0);
188         mpp_enc_cfg_set_s32(enc_cfg, "h264:qp_init", is_fix_qp ? qp : -1);
189         mpp_enc_cfg_set_s32(enc_cfg, "h264:qp_min", is_fix_qp ? qp : qp_min);
190         mpp_enc_cfg_set_s32(enc_cfg, "h264:qp_max", is_fix_qp ? qp : qp_max);
191         mpp_enc_cfg_set_s32(enc_cfg, "h264:qp_min_i", is_fix_qp ? 10 : qp_min);
192         mpp_enc_cfg_set_s32(enc_cfg, "h264:qp_max_i", is_fix_qp ? 51 : qp_max);
193         mpp_enc_cfg_set_s32(enc_cfg, "h264:qp_step", 4);
194         mpp_enc_cfg_set_s32(enc_cfg, "h264:qp_delta_ip", 3);
195     } break;
196     case MPP_VIDEO_CodingVP8 : {
197         mpp_enc_cfg_set_s32(enc_cfg, "vp8:qp_init", -1);
198         mpp_enc_cfg_set_s32(enc_cfg, "vp8:qp_min", 0);
199         mpp_enc_cfg_set_s32(enc_cfg, "vp8:qp_max", 127);
200         mpp_enc_cfg_set_s32(enc_cfg, "vp8:qp_min_i", 0);
201         mpp_enc_cfg_set_s32(enc_cfg, "vp8:qp_max_i", 127);
202     } break;
203     case MPP_VIDEO_CodingMJPEG : {
204         mpp_enc_cfg_set_s32(enc_cfg, "jpeg:quant", qp);
205     } break;
206     default : {
207         mpp_err_f("support encoder coding type %d\n", coding);
208     } break;
209     }
210 
211     ret = mpi->control(mpp_ctx, MPP_ENC_SET_CFG, enc_cfg);
212     if (ret) {
213         mpp_err("setup enc config failed ret %d\n", ret);
214         goto RET;
215     }
216 RET:
217     return ret;
218 }
219 
is_valid_dma_fd(int fd)220 static int is_valid_dma_fd(int fd)
221 {
222     int ret = 1;
223     /* detect input file handle */
224     int fs_flag = fcntl(fd, F_GETFL, NULL);
225     int fd_flag = fcntl(fd, F_GETFD, NULL);
226 
227     if (fs_flag == -1 || fd_flag == -1) {
228         ret = 0;
229     }
230 
231     return ret;
232 }
233 
copy_align_raw_buffer_to_dest(RK_U8 * dst,RK_U8 * src,RK_U32 width,RK_U32 height,MppFrameFormat fmt)234 static int copy_align_raw_buffer_to_dest(RK_U8 *dst, RK_U8 *src, RK_U32 width,
235                                          RK_U32 height, MppFrameFormat fmt)
236 {
237     int ret = 1;
238     RK_U32 index = 0;
239     RK_U8 *dst_buf = dst;
240     RK_U8 *src_buf = src;
241     RK_U32 row = 0;
242     RK_U32 hor_stride = MPP_ALIGN(width, 16);
243     RK_U32 ver_stride = MPP_ALIGN(height, 8);
244     RK_U8 *dst_u = dst_buf + hor_stride * ver_stride;
245     RK_U8 *dst_v = dst_u + hor_stride * ver_stride / 4;
246 
247     switch (fmt) {
248     case MPP_FMT_YUV420SP :
249     case MPP_FMT_YUV420SP_VU : {
250         for (row = 0; row < height; row++) {
251             memcpy(dst_buf + row * hor_stride, src_buf + index, width);
252             index += width;
253         }
254         for (row = 0; row < height / 2; row++) {
255             memcpy(dst_u + row * hor_stride, src_buf + index, width);
256             index += width;
257         }
258     } break;
259     case MPP_FMT_YUV420P : {
260         for (row = 0; row < height; row++) {
261             memcpy(dst_buf + row * hor_stride, src_buf + index, width);
262             index += width;
263         }
264         for (row = 0; row < height / 2; row++) {
265             memcpy(dst_u + row * hor_stride / 2, src_buf + index, width / 2);
266             index += width / 2;
267         }
268         for (row = 0; row < height / 2; row++) {
269             memcpy(dst_v + row * hor_stride / 2, src_buf + index, width / 2);
270             index += width / 2;
271         }
272     } break;
273     case MPP_FMT_RGB888 :
274     case MPP_FMT_BGR888 : {
275         for (row = 0; row < height; row++) {
276             memcpy(dst_buf + row * hor_stride * 3, src_buf + row * width * 3, width * 3);
277         }
278     } break;
279     case MPP_FMT_ABGR8888 :
280     case MPP_FMT_ARGB8888 :
281     case MPP_FMT_BGRA8888 :
282     case MPP_FMT_RGBA8888 : {
283         for (row = 0; row < height; row++) {
284             memcpy(dst_buf + row * hor_stride * 4, src_buf + row * width * 4, width * 4);
285         }
286     } break;
287     default : {
288         mpp_err("unsupport align fmt:%d now\n", fmt);
289     } break;
290     }
291 
292     return ret;
293 }
294 
VpuApiLegacy()295 VpuApiLegacy::VpuApiLegacy() :
296     mpp_ctx(NULL),
297     mpi(NULL),
298     init_ok(0),
299     frame_count(0),
300     set_eos(0),
301     frm_info(NULL),
302     memGroup(NULL),
303     format(MPP_FMT_YUV420P),
304     mInputTimeOutMs(0),
305     fd_input(-1),
306     fd_output(-1),
307     mEosSet(0),
308     enc_cfg(NULL),
309     enc_hdr_pkt(NULL),
310     enc_hdr_buf(NULL),
311     enc_hdr_buf_size(0),
312     dec_out_frm_struct_type(0)
313 {
314     vpu_api_dbg_func("enter\n");
315 
316     mpp_create(&mpp_ctx, &mpi);
317     mpp_frame_init(&frm_info);
318 
319     memset(&frm_rdy_cb, 0, sizeof(FrameRdyCB));
320     memset(&enc_param, 0, sizeof(enc_param));
321 
322     mlvec = NULL;
323     memset(&mlvec_dy_cfg, 0, sizeof(mlvec_dy_cfg));
324 
325     vpu_api_dbg_func("leave\n");
326 }
327 
~VpuApiLegacy()328 VpuApiLegacy::~VpuApiLegacy()
329 {
330     vpu_api_dbg_func("enter\n");
331 
332     mpp_frame_deinit(&frm_info);
333     mpp_destroy(mpp_ctx);
334 
335     if (memGroup) {
336         mpp_buffer_group_put(memGroup);
337         memGroup = NULL;
338     }
339 
340     if (enc_cfg) {
341         mpp_enc_cfg_deinit(enc_cfg);
342         enc_cfg = NULL;
343     }
344 
345     if (mlvec) {
346         vpu_api_mlvec_deinit(mlvec);
347         mlvec = NULL;
348     }
349 
350     if (enc_hdr_pkt) {
351         mpp_packet_deinit(&enc_hdr_pkt);
352         enc_hdr_pkt = NULL;
353     }
354     MPP_FREE(enc_hdr_buf);
355     enc_hdr_buf_size = 0;
356 
357     vpu_api_dbg_func("leave\n");
358 }
359 
init_frame_info(VpuCodecContext * ctx,MppCtx mpp_ctx,MppApi * mpi,MppFrame frame_info,VPU_GENERIC * p)360 static RK_S32 init_frame_info(VpuCodecContext *ctx, MppCtx mpp_ctx, MppApi *mpi,
361                               MppFrame frame_info, VPU_GENERIC *p)
362 {
363     RK_S32 ret = -1;
364     RK_U32 fbcOutFmt = 0;
365 
366     if (ctx->private_data)
367         fbcOutFmt = *(RK_U32 *)ctx->private_data;
368 
369     if (ctx->extra_cfg.bit_depth
370         || ctx->extra_cfg.yuv_format) {
371         if (ctx->extra_cfg.bit_depth == 10)
372             p->CodecType = (ctx->extra_cfg.yuv_format == 1)
373                            ? MPP_FMT_YUV422SP_10BIT : MPP_FMT_YUV420SP_10BIT;
374         else
375             p->CodecType = (ctx->extra_cfg.yuv_format == 1)
376                            ? MPP_FMT_YUV422SP : MPP_FMT_YUV420SP;
377     } else {
378         /**hightest of p->ImgWidth bit show current dec bitdepth
379           * 0 - 8bit
380           * 1 - 10bit
381           **/
382         if (p->ImgWidth & 0x80000000)
383             p->CodecType = (p->ImgWidth & 0x40000000)
384                            ? MPP_FMT_YUV422SP_10BIT : MPP_FMT_YUV420SP_10BIT;
385         else
386             p->CodecType = (p->ImgWidth & 0x40000000)
387                            ? MPP_FMT_YUV422SP : MPP_FMT_YUV420SP;
388     }
389     p->ImgWidth = (p->ImgWidth & 0xFFFF);
390 
391     mpp_frame_set_width(frame_info, p->ImgWidth);
392     mpp_frame_set_height(frame_info, p->ImgHeight);
393     mpp_frame_set_fmt(frame_info, (MppFrameFormat)(p->CodecType | fbcOutFmt));
394 
395     ret = mpi->control(mpp_ctx, MPP_DEC_SET_FRAME_INFO, (MppParam)frame_info);
396     /* output the parameters used */
397     p->ImgHorStride = mpp_frame_get_hor_stride(frame_info);
398     p->ImgVerStride = mpp_frame_get_ver_stride(frame_info);
399     p->BufSize = mpp_frame_get_buf_size(frame_info);
400 
401     return ret;
402 }
403 
404 
init(VpuCodecContext * ctx,RK_U8 * extraData,RK_U32 extra_size)405 RK_S32 VpuApiLegacy::init(VpuCodecContext *ctx, RK_U8 *extraData, RK_U32 extra_size)
406 {
407     vpu_api_dbg_func("enter\n");
408 
409     MPP_RET ret = MPP_OK;
410     MppCtxType type;
411 
412     if (mpp_ctx == NULL || mpi == NULL) {
413         mpp_err("found invalid context input");
414         return MPP_ERR_NULL_PTR;
415     }
416 
417     if (CODEC_DECODER == ctx->codecType) {
418         type = MPP_CTX_DEC;
419     } else if (CODEC_ENCODER == ctx->codecType) {
420         type = MPP_CTX_ENC;
421     } else {
422         mpp_err("found invalid codec type %d\n", ctx->codecType);
423         return MPP_ERR_VPU_CODEC_INIT;
424     }
425 
426     ret = mpp_init(mpp_ctx, type, (MppCodingType)ctx->videoCoding);
427     if (ret) {
428         mpp_err_f(" init error. \n");
429         return ret;
430     }
431 
432     if (MPP_CTX_ENC == type) {
433         EncParameter_t *param = (EncParameter_t*)ctx->private_data;
434         MppCodingType coding = (MppCodingType)ctx->videoCoding;
435         MppPollType block = (MppPollType)VPU_API_ENC_INPUT_TIMEOUT;
436         MppEncSeiMode sei_mode = MPP_ENC_SEI_MODE_DISABLE;
437 
438         /* setup input / output block mode */
439         ret = mpi->control(mpp_ctx, MPP_SET_INPUT_TIMEOUT, (MppParam)&block);
440         if (MPP_OK != ret)
441             mpp_err("mpi control MPP_SET_INPUT_TIMEOUT failed\n");
442 
443         /* disable sei by default */
444         ret = mpi->control(mpp_ctx, MPP_ENC_SET_SEI_CFG, &sei_mode);
445         if (ret)
446             mpp_err("mpi control MPP_ENC_SET_SEI_CFG failed ret %d\n", ret);
447 
448         if (memGroup == NULL) {
449             ret = mpp_buffer_group_get_internal(&memGroup, MPP_BUFFER_TYPE_ION);
450             if (ret) {
451                 mpp_err("memGroup mpp_buffer_group_get failed %d\n", ret);
452                 return ret;
453             }
454         }
455 
456         ret = mpp_enc_cfg_init(&enc_cfg);
457         if (ret) {
458             mpp_err("mpp_enc_cfg_init failed %d\n", ret);
459             mpp_buffer_group_put(memGroup);
460             memGroup = NULL;
461             return ret;
462         }
463 
464         format = vpu_pic_type_remap_to_mpp((EncInputPictureType)param->format);
465 
466         memcpy(&enc_param, param, sizeof(enc_param));
467 
468         if (MPP_OK == vpu_api_mlvec_check_cfg(param)) {
469             if (NULL == mlvec) {
470                 vpu_api_mlvec_init(&mlvec);
471                 vpu_api_mlvec_setup(mlvec, mpp_ctx, mpi, enc_cfg);
472             }
473         }
474 
475         if (mlvec)
476             vpu_api_mlvec_set_st_cfg(mlvec, (VpuApiMlvecStaticCfg *)param);
477 
478         vpu_api_set_enc_cfg(mpp_ctx, mpi, enc_cfg, coding, format, param);
479 
480         if (!mlvec) {
481             if (NULL == enc_hdr_pkt) {
482                 if (NULL == enc_hdr_buf) {
483                     enc_hdr_buf_size = SZ_1K;
484                     enc_hdr_buf = mpp_calloc_size(RK_U8, enc_hdr_buf_size);
485                 }
486 
487                 if (enc_hdr_buf)
488                     mpp_packet_init(&enc_hdr_pkt, enc_hdr_buf, enc_hdr_buf_size);
489             }
490 
491             mpp_assert(enc_hdr_pkt);
492             if (enc_hdr_pkt) {
493                 ret = mpi->control(mpp_ctx, MPP_ENC_GET_HDR_SYNC, enc_hdr_pkt);
494                 ctx->extradata_size = mpp_packet_get_length(enc_hdr_pkt);
495                 ctx->extradata      = mpp_packet_get_data(enc_hdr_pkt);
496             }
497         }
498     } else { /* MPP_CTX_DEC */
499         vpug.CodecType  = ctx->codecType;
500         vpug.ImgWidth   = ctx->width;
501         vpug.ImgHeight  = ctx->height;
502 
503         init_frame_info(ctx, mpp_ctx, mpi, frm_info, &vpug);
504 
505         if (extraData != NULL) {
506             MppPacket pkt = NULL;
507 
508             mpp_packet_init(&pkt, extraData, extra_size);
509             mpp_packet_set_extra_data(pkt);
510             mpi->decode_put_packet(mpp_ctx, pkt);
511             mpp_packet_deinit(&pkt);
512         }
513 
514         RK_U32 flag = 0;
515         ret = mpi->control(mpp_ctx, MPP_DEC_SET_ENABLE_DEINTERLACE, &flag);
516         if (ret)
517             mpp_err_f("disable mpp deinterlace failed ret %d\n", ret);
518     }
519 
520     init_ok = 1;
521 
522     vpu_api_dbg_func("leave\n");
523     return ret;
524 }
525 
flush(VpuCodecContext * ctx)526 RK_S32 VpuApiLegacy::flush(VpuCodecContext *ctx)
527 {
528     (void)ctx;
529     vpu_api_dbg_func("enter\n");
530     if (mpi && mpi->reset && init_ok) {
531         mpi->reset(mpp_ctx);
532         set_eos = 0;
533         mEosSet = 0;
534     }
535     vpu_api_dbg_func("leave\n");
536     return 0;
537 }
538 
setup_VPU_FRAME_from_mpp_frame(VpuCodecContext * ctx,VPU_FRAME * vframe,MppFrame mframe)539 static void setup_VPU_FRAME_from_mpp_frame(VpuCodecContext *ctx, VPU_FRAME *vframe, MppFrame mframe)
540 {
541     MppBuffer buf = mpp_frame_get_buffer(mframe);
542     RK_U64 pts  = mpp_frame_get_pts(mframe);
543     RK_U32 mode = mpp_frame_get_mode(mframe);
544 
545     MppFrameColorRange colorRan = mpp_frame_get_color_range(mframe);
546     MppFrameColorTransferCharacteristic colorTrc = mpp_frame_get_color_trc(mframe);
547     MppFrameColorPrimaries colorPri = mpp_frame_get_color_primaries(mframe);
548     MppFrameColorSpace colorSpa = mpp_frame_get_colorspace(mframe);
549 
550     if (buf)
551         mpp_buffer_inc_ref(buf);
552 
553     vframe->CodingType = ctx->videoCoding;
554     vframe->DisplayWidth = mpp_frame_get_width(mframe);
555     vframe->DisplayHeight = mpp_frame_get_height(mframe);
556     vframe->FrameWidth = mpp_frame_get_hor_stride(mframe);
557     vframe->FrameHeight = mpp_frame_get_ver_stride(mframe);
558 
559     vframe->ColorRange = (colorRan == MPP_FRAME_RANGE_JPEG);
560     vframe->ColorPrimaries = colorPri;
561     vframe->ColorTransfer = colorTrc;
562     vframe->ColorCoeffs = colorSpa;
563 
564     if (mode == MPP_FRAME_FLAG_FRAME)
565         vframe->FrameType = 0;
566     else {
567         RK_U32 field_order = mode & MPP_FRAME_FLAG_FIELD_ORDER_MASK;
568         if (field_order == MPP_FRAME_FLAG_TOP_FIRST)
569             vframe->FrameType = 1;
570         else if (field_order == MPP_FRAME_FLAG_BOT_FIRST)
571             vframe->FrameType = 2;
572         else if (field_order == MPP_FRAME_FLAG_DEINTERLACED)
573             vframe->FrameType = 4;
574     }
575     vframe->ErrorInfo = mpp_frame_get_errinfo(mframe) | mpp_frame_get_discard(mframe);
576     vframe->ShowTime.TimeHigh = (RK_U32)(pts >> 32);
577     vframe->ShowTime.TimeLow = (RK_U32)pts;
578     switch (mpp_frame_get_fmt(mframe) & MPP_FRAME_FMT_MASK) {
579     case MPP_FMT_YUV420SP: {
580         vframe->ColorType = VPU_OUTPUT_FORMAT_YUV420_SEMIPLANAR;
581         vframe->OutputWidth = 0x20;
582     } break;
583     case MPP_FMT_YUV420SP_10BIT: {
584         vframe->ColorType = VPU_OUTPUT_FORMAT_YUV420_SEMIPLANAR;
585         vframe->ColorType |= VPU_OUTPUT_FORMAT_BIT_10;
586         vframe->OutputWidth = 0x22;
587     } break;
588     case MPP_FMT_YUV422SP: {
589         vframe->ColorType = VPU_OUTPUT_FORMAT_YUV422;
590         vframe->OutputWidth = 0x10;
591     } break;
592     case MPP_FMT_YUV422SP_10BIT: {
593         vframe->ColorType = VPU_OUTPUT_FORMAT_YUV422;
594         vframe->ColorType |= VPU_OUTPUT_FORMAT_BIT_10;
595         vframe->OutputWidth = 0x23;
596     } break;
597     case MPP_FMT_YUV444SP: {
598         vframe->ColorType = VPU_OUTPUT_FORMAT_YUV444;
599         vframe->OutputWidth = 0x11;
600     } break;
601     default: {
602     } break;
603     }
604 
605     switch (mpp_frame_get_fmt(mframe) & MPP_FRAME_FBC_MASK) {
606     case MPP_FRAME_FBC_AFBC_V1: {
607         vframe->ColorType |= VPU_OUTPUT_FORMAT_FBC_AFBC_V1;
608     } break;
609     case MPP_FRAME_FBC_AFBC_V2: {
610         vframe->ColorType |= VPU_OUTPUT_FORMAT_FBC_AFBC_V2;
611     } break;
612     default: {
613     } break;
614     }
615 
616     switch (colorTrc) {
617     case MPP_FRAME_TRC_SMPTEST2084: {
618         vframe->ColorType |= VPU_OUTPUT_FORMAT_DYNCRANGE_HDR10; //HDR10
619     } break;
620     case MPP_FRAME_TRC_ARIB_STD_B67: {
621         vframe->ColorType |= VPU_OUTPUT_FORMAT_DYNCRANGE_HDR_HLG; //HDR_HLG
622     } break;
623     default: {
624     } break;
625     }
626 
627     if (buf) {
628         MppBufferImpl *p = (MppBufferImpl*)buf;
629         void *ptr = (p->mode == MPP_BUFFER_INTERNAL) ?
630                     mpp_buffer_get_ptr(buf) : NULL;
631         RK_S32 fd = mpp_buffer_get_fd(buf);
632 
633         vframe->FrameBusAddr[0] = fd;
634         vframe->FrameBusAddr[1] = fd;
635         vframe->vpumem.vir_addr = (RK_U32*)ptr;
636         vframe->vpumem.phy_addr = fd;
637 
638         vframe->vpumem.size = vframe->FrameWidth * vframe->FrameHeight * 3 / 2;
639         vframe->vpumem.offset = (RK_U32*)buf;
640     }
641 }
642 
setup_video_frame_meta(VideoFrame_t * videoFrame,MppFrame mframe)643 static void setup_video_frame_meta(VideoFrame_t *videoFrame, MppFrame mframe)
644 {
645     if (mpp_frame_get_thumbnail_en(mframe) == MPP_FRAME_THUMBNAIL_MIXED) {
646         MppMeta meta = NULL;
647         RK_S32 yOffset = 0;
648         RK_S32 uvOffset = 0;
649 
650         meta = mpp_frame_get_meta(mframe);
651         mpp_meta_get_s32(meta, KEY_DEC_TBN_Y_OFFSET, &yOffset);
652         mpp_meta_get_s32(meta, KEY_DEC_TBN_UV_OFFSET, &uvOffset);
653         if (yOffset && uvOffset) {
654             videoFrame->thumbInfo.enable = 1;
655             videoFrame->thumbInfo.yOffset = yOffset;
656             videoFrame->thumbInfo.uvOffset = uvOffset;
657         } else {
658             videoFrame->thumbInfo.enable = 0;
659         }
660     }
661 
662     if (MPP_FRAME_FMT_IS_HDR(mpp_frame_get_fmt(mframe))) {
663         MppMeta meta = NULL;
664         RK_S32 offset = 0;
665         RK_S32 size = 0;
666 
667         meta = mpp_frame_get_meta(mframe);
668         mpp_meta_get_s32(meta, KEY_HDR_META_OFFSET, &offset);
669         mpp_meta_get_s32(meta, KEY_HDR_META_SIZE, &size);
670         videoFrame->hdrInfo.isHdr = 1;
671         videoFrame->hdrInfo.offset = offset;
672         videoFrame->hdrInfo.size = size;
673     }
674 
675     videoFrame->viewId = mpp_frame_get_viewid(mframe);
676 }
677 
decode(VpuCodecContext * ctx,VideoPacket_t * pkt,DecoderOut_t * aDecOut)678 RK_S32 VpuApiLegacy::decode(VpuCodecContext *ctx, VideoPacket_t *pkt, DecoderOut_t *aDecOut)
679 {
680     MPP_RET ret = MPP_OK;
681     MppFrame mframe = NULL;
682     MppPacket packet = NULL;
683 
684     vpu_api_dbg_func("enter\n");
685 
686     if (ctx->videoCoding == OMX_RK_VIDEO_CodingMJPEG) {
687         MppTask task = NULL;
688 
689         if (!init_ok) {
690             mpp_err("init failed!\n");
691             return VPU_API_ERR_VPU_CODEC_INIT;
692         }
693 
694         /* check input param */
695         if (!pkt || !aDecOut) {
696             mpp_err("invalid input %p and output %p\n", pkt, aDecOut);
697             return VPU_API_ERR_UNKNOW;
698         }
699 
700         if (pkt->size <= 0) {
701             mpp_err("invalid input size %d\n", pkt->size);
702             return VPU_API_ERR_UNKNOW;
703         }
704 
705         /* try import input buffer and output buffer */
706         RK_S32 fd           = -1;
707         RK_U32 width        = ctx->width;
708         RK_U32 height       = ctx->height;
709         RK_U32 hor_stride   = MPP_ALIGN(width,  16);
710         RK_U32 ver_stride   = MPP_ALIGN(height, 16);
711         MppBuffer   str_buf = NULL; /* input */
712         MppBuffer   pic_buf = NULL; /* output */
713 
714         ret = mpp_frame_init(&mframe);
715         if (MPP_OK != ret) {
716             mpp_err_f("mpp_frame_init failed\n");
717             goto DECODE_OUT;
718         }
719 
720         fd = (RK_S32)(pkt->pts & 0xffffffff);
721         if (fd_input < 0) {
722             fd_input = is_valid_dma_fd(fd);
723         }
724 
725         if (fd_input) {
726             MppBufferInfo   inputCommit;
727 
728             memset(&inputCommit, 0, sizeof(inputCommit));
729             inputCommit.type = MPP_BUFFER_TYPE_ION;
730             inputCommit.size = pkt->size;
731             inputCommit.fd = fd;
732 
733             ret = mpp_buffer_import(&str_buf, &inputCommit);
734             if (ret) {
735                 mpp_err_f("import input picture buffer failed\n");
736                 goto DECODE_OUT;
737             }
738         } else {
739             if (NULL == pkt->data) {
740                 ret = MPP_ERR_NULL_PTR;
741                 goto DECODE_OUT;
742             }
743 
744             ret = mpp_buffer_get(memGroup, &str_buf, pkt->size);
745             if (ret) {
746                 mpp_err_f("allocate input picture buffer failed\n");
747                 goto DECODE_OUT;
748             }
749             memcpy((RK_U8*) mpp_buffer_get_ptr(str_buf), pkt->data, pkt->size);
750         }
751 
752         fd = (RK_S32)(aDecOut->timeUs & 0xffffffff);
753         if (fd_output < 0) {
754             fd_output = is_valid_dma_fd(fd);
755         }
756 
757         if (fd_output) {
758             MppBufferInfo outputCommit;
759 
760             memset(&outputCommit, 0, sizeof(outputCommit));
761             /* in order to avoid interface change use space in output to transmit information */
762             outputCommit.type = MPP_BUFFER_TYPE_ION;
763             outputCommit.fd = fd;
764             outputCommit.size = width * height * 3 / 2;
765             outputCommit.ptr = (void*)aDecOut->data;
766 
767             ret = mpp_buffer_import(&pic_buf, &outputCommit);
768             if (ret) {
769                 mpp_err_f("import output stream buffer failed\n");
770                 goto DECODE_OUT;
771             }
772         } else {
773             ret = mpp_buffer_get(memGroup, &pic_buf, hor_stride * ver_stride * 3 / 2);
774             if (ret) {
775                 mpp_err_f("allocate output stream buffer failed\n");
776                 goto DECODE_OUT;
777             }
778         }
779 
780         mpp_packet_init_with_buffer(&packet, str_buf); /* input */
781         mpp_frame_set_buffer(mframe, pic_buf); /* output */
782 
783         vpu_api_dbg_func("mpp import input fd %d output fd %d",
784                          mpp_buffer_get_fd(str_buf), mpp_buffer_get_fd(pic_buf));
785 
786         ret = mpi->poll(mpp_ctx, MPP_PORT_INPUT, MPP_POLL_BLOCK);
787         if (ret) {
788             mpp_err("mpp input poll failed\n");
789             goto DECODE_OUT;
790         }
791 
792         ret = mpi->dequeue(mpp_ctx, MPP_PORT_INPUT, &task);
793         if (ret) {
794             mpp_err("mpp task input dequeue failed\n");
795             goto DECODE_OUT;
796         }
797 
798         mpp_task_meta_set_packet(task, KEY_INPUT_PACKET, packet);
799         mpp_task_meta_set_frame (task, KEY_OUTPUT_FRAME, mframe);
800 
801         ret = mpi->enqueue(mpp_ctx, MPP_PORT_INPUT, task);
802         if (ret) {
803             mpp_err("mpp task input enqueue failed\n");
804             goto DECODE_OUT;
805         }
806 
807         pkt->size = 0;
808         task = NULL;
809 
810         ret = mpi->poll(mpp_ctx, MPP_PORT_INPUT, MPP_POLL_BLOCK);
811         if (ret) {
812             mpp_err("mpp output poll failed\n");
813             goto DECODE_OUT;
814         }
815 
816         ret = mpi->dequeue(mpp_ctx, MPP_PORT_OUTPUT, &task);
817         if (ret) {
818             mpp_err("ret %d mpp task output dequeue failed\n", ret);
819             goto DECODE_OUT;
820         }
821 
822         if (task) {
823             MppFrame frame_out = NULL;
824 
825             mpp_task_meta_get_frame(task, KEY_OUTPUT_FRAME, &frame_out);
826             mpp_assert(frame_out == mframe);
827             vpu_api_dbg_func("decoded frame %d\n", frame_count);
828             frame_count++;
829 
830             ret = mpi->enqueue(mpp_ctx, MPP_PORT_OUTPUT, task);
831             if (ret) {
832                 mpp_err("mpp task output enqueue failed\n");
833                 goto DECODE_OUT;
834             }
835             task = NULL;
836         }
837 
838         // copy decoded frame into output buffer, and set outpub frame size
839         if (mframe != NULL) {
840             MppBuffer buf_out = mpp_frame_get_buffer(mframe);
841             size_t len  = mpp_buffer_get_size(buf_out);
842             aDecOut->size = len;
843 
844             if (fd_output) {
845                 mpp_log_f("fd for output is invalid!\n");
846                 // TODO: check frame format and allocate correct buffer
847                 aDecOut->data = mpp_malloc(RK_U8, width * height * 3 / 2);
848                 memcpy(aDecOut->data, (RK_U8*) mpp_buffer_get_ptr(pic_buf), aDecOut->size);
849             }
850 
851             vpu_api_dbg_func("get frame %p size %d\n", mframe, len);
852 
853             mpp_frame_deinit(&mframe);
854         } else {
855             mpp_log("outputPacket is NULL!");
856         }
857 
858     DECODE_OUT:
859         if (str_buf) {
860             mpp_buffer_put(str_buf);
861             str_buf = NULL;
862         }
863 
864         if (pic_buf) {
865             mpp_buffer_put(pic_buf);
866             pic_buf = NULL;
867         }
868     } else {
869         mpp_packet_init(&packet, pkt->data, pkt->size);
870         mpp_packet_set_pts(packet, pkt->pts);
871         if (pkt->nFlags & OMX_BUFFERFLAG_EOS) {
872             mpp_packet_set_eos(packet);
873         }
874 
875         vpu_api_dbg_input("input size %-6d flag %x pts %lld\n",
876                           pkt->size, pkt->nFlags, pkt->pts);
877 
878         ret = mpi->decode(mpp_ctx, packet, &mframe);
879         if (MPP_OK == ret) {
880             pkt->size = 0;
881         }
882         if (ret || NULL == mframe) {
883             aDecOut->size = 0;
884         } else {
885             VPU_FRAME *vframe = NULL;
886             MppBuffer buf = mpp_frame_get_buffer(mframe);
887 
888             if (dec_out_frm_struct_type) {
889                 VideoFrame_t *videoFrame = (VideoFrame_t *)aDecOut->data;
890                 vframe = &videoFrame->vpuFrame;
891                 memset(videoFrame, 0, sizeof(VideoFrame_t));
892                 aDecOut->size = sizeof(VideoFrame_t);
893                 setup_video_frame_meta(videoFrame, mframe);
894             } else {
895                 vframe = (VPU_FRAME *)aDecOut->data;
896                 memset(vframe, 0, sizeof(VPU_FRAME));
897                 aDecOut->size = sizeof(VPU_FRAME);
898             }
899 
900             setup_VPU_FRAME_from_mpp_frame(ctx, vframe, mframe);
901 
902             aDecOut->timeUs = mpp_frame_get_pts(mframe);
903             frame_count++;
904 
905             if (mpp_frame_get_eos(mframe)) {
906                 set_eos = 1;
907                 if (buf == NULL) {
908                     aDecOut->size = 0;
909                 }
910             }
911             if (vpu_api_debug & VPU_API_DBG_OUTPUT) {
912                 mpp_log("get one frame pts %lld, fd 0x%x, poc %d, errinfo %x, discard %d, eos %d, verr %d",
913                         aDecOut->timeUs,
914                         ((buf) ? (mpp_buffer_get_fd(buf)) : (-1)),
915                         mpp_frame_get_poc(mframe),
916                         mpp_frame_get_errinfo(mframe),
917                         mpp_frame_get_discard(mframe),
918                         mpp_frame_get_eos(mframe), vframe->ErrorInfo);
919             }
920 
921             /*
922              * IMPORTANT: mframe is malloced from mpi->decode_get_frame
923              * So we need to deinit mframe here. But the buffer in the frame should not be free with mframe.
924              * Because buffer need to be set to vframe->vpumem.offset and send to display.
925              * The we have to clear the buffer pointer in mframe then release mframe.
926              */
927             mpp_frame_deinit(&mframe);
928         }
929     }
930 
931     if (packet)
932         mpp_packet_deinit(&packet);
933 
934     if (mframe)
935         mpp_frame_deinit(&mframe);
936 
937     vpu_api_dbg_func("leave ret %d\n", ret);
938     return ret;
939 }
940 
decode_sendstream(VideoPacket_t * pkt)941 RK_S32 VpuApiLegacy::decode_sendstream(VideoPacket_t *pkt)
942 {
943     vpu_api_dbg_func("enter\n");
944 
945     RK_S32 ret = MPP_OK;
946     MppPacket mpkt = NULL;
947 
948     if (!init_ok) {
949         return VPU_API_ERR_VPU_CODEC_INIT;
950     }
951 
952     mpp_packet_init(&mpkt, pkt->data, pkt->size);
953     mpp_packet_set_pts(mpkt, pkt->pts);
954     if (pkt->nFlags & OMX_BUFFERFLAG_EOS) {
955         mpp_packet_set_eos(mpkt);
956     }
957 
958     vpu_api_dbg_input("input size %-6d flag %x pts %lld\n",
959                       pkt->size, pkt->nFlags, pkt->pts);
960 
961     ret = mpi->decode_put_packet(mpp_ctx, mpkt);
962     if (ret == MPP_OK) {
963         pkt->size = 0;
964     } else if (mInputTimeOutMs == 0) {
965         /* reduce cpu overhead here */
966         msleep(1);
967     }
968 
969     mpp_packet_deinit(&mpkt);
970 
971     vpu_api_dbg_func("leave ret %d\n", ret);
972     /* NOTE: always return success for old player compatibility */
973     return MPP_OK;
974 }
975 
decode_getoutframe(VpuCodecContext * ctx,DecoderOut_t * aDecOut)976 RK_S32 VpuApiLegacy::decode_getoutframe(VpuCodecContext *ctx, DecoderOut_t *aDecOut)
977 {
978     RK_S32 ret = 0;
979     VPU_FRAME *vframe = NULL;
980     MppFrame  mframe = NULL;
981 
982     vpu_api_dbg_func("enter\n");
983 
984     if (!init_ok) {
985         return VPU_API_ERR_VPU_CODEC_INIT;
986     }
987 
988     if (NULL == mpi) {
989         aDecOut->size = 0;
990         return 0;
991     }
992 
993     if (set_eos) {
994         aDecOut->size = 0;
995         mEosSet = 1;
996         return VPU_API_EOS_STREAM_REACHED;
997     }
998 
999     ret = mpi->decode_get_frame(mpp_ctx, &mframe);
1000     if (ret || NULL == mframe) {
1001         aDecOut->size = 0;
1002     } else {
1003         MppBuffer buf = mpp_frame_get_buffer(mframe);
1004 
1005         if (dec_out_frm_struct_type) {
1006             VideoFrame_t *videoFrame = (VideoFrame_t *)aDecOut->data;
1007             vframe = &videoFrame->vpuFrame;
1008             memset(videoFrame, 0, sizeof(VideoFrame_t));
1009             aDecOut->size = sizeof(VideoFrame_t);
1010             setup_video_frame_meta(videoFrame, mframe);
1011         } else {
1012             vframe = (VPU_FRAME *)aDecOut->data;
1013             memset(vframe, 0, sizeof(VPU_FRAME));
1014             aDecOut->size = sizeof(VPU_FRAME);
1015         }
1016 
1017         setup_VPU_FRAME_from_mpp_frame(ctx, vframe, mframe);
1018 
1019         aDecOut->timeUs = mpp_frame_get_pts(mframe);
1020         frame_count++;
1021 
1022         if (mpp_frame_get_eos(mframe) && !mpp_frame_get_info_change(mframe)) {
1023             set_eos = 1;
1024             if (buf == NULL) {
1025                 aDecOut->size = 0;
1026                 mEosSet = 1;
1027                 ret = VPU_API_EOS_STREAM_REACHED;
1028             } else {
1029                 aDecOut->nFlags |= VPU_API_EOS_STREAM_REACHED;
1030             }
1031         }
1032         if (vpu_api_debug & VPU_API_DBG_OUTPUT) {
1033             mpp_log("get one frame pts %lld, fd 0x%x, poc %d, errinfo %x, discard %d, eos %d, verr %d",
1034                     aDecOut->timeUs,
1035                     ((buf) ? (mpp_buffer_get_fd(buf)) : (-1)),
1036                     mpp_frame_get_poc(mframe),
1037                     mpp_frame_get_errinfo(mframe),
1038                     mpp_frame_get_discard(mframe),
1039                     mpp_frame_get_eos(mframe), vframe->ErrorInfo);
1040         }
1041 
1042         /*
1043          * IMPORTANT: mframe is malloced from mpi->decode_get_frame
1044          * So we need to deinit mframe here. But the buffer in the frame should not be free with mframe.
1045          * Because buffer need to be set to vframe->vpumem.offset and send to display.
1046          * The we have to clear the buffer pointer in mframe then release mframe.
1047          */
1048         mpp_frame_deinit(&mframe);
1049     }
1050 
1051     vpu_api_dbg_func("leave ret %d\n", ret);
1052 
1053     return ret;
1054 }
1055 
encode(VpuCodecContext * ctx,EncInputStream_t * aEncInStrm,EncoderOut_t * aEncOut)1056 RK_S32 VpuApiLegacy::encode(VpuCodecContext *ctx, EncInputStream_t *aEncInStrm, EncoderOut_t *aEncOut)
1057 {
1058     MPP_RET ret = MPP_OK;
1059     MppTask task = NULL;
1060     vpu_api_dbg_func("enter\n");
1061 
1062     if (!init_ok)
1063         return VPU_API_ERR_VPU_CODEC_INIT;
1064 
1065     /* check input param */
1066     if (!aEncInStrm || !aEncOut) {
1067         mpp_err("invalid input %p and output %p\n", aEncInStrm, aEncOut);
1068         return VPU_API_ERR_UNKNOW;
1069     }
1070 
1071     if (NULL == aEncInStrm->buf || 0 == aEncInStrm->size) {
1072         mpp_err("invalid input buffer %p size %d\n", aEncInStrm->buf, aEncInStrm->size);
1073         return VPU_API_ERR_UNKNOW;
1074     }
1075 
1076     /* try import input buffer and output buffer */
1077     RK_S32 fd           = -1;
1078     RK_U32 width        = ctx->width;
1079     RK_U32 height       = ctx->height;
1080     RK_U32 hor_stride   = MPP_ALIGN(width,  16);
1081     RK_U32 ver_stride   = MPP_ALIGN(height, 16);
1082     MppFrame    frame   = NULL;
1083     MppPacket   packet  = NULL;
1084     MppBuffer   pic_buf = NULL;
1085     MppBuffer   str_buf = NULL;
1086 
1087     ret = mpp_frame_init(&frame);
1088     if (MPP_OK != ret) {
1089         mpp_err_f("mpp_frame_init failed\n");
1090         goto ENCODE_OUT;
1091     }
1092 
1093     mpp_frame_set_width(frame, width);
1094     mpp_frame_set_height(frame, height);
1095     mpp_frame_set_ver_stride(frame, ver_stride);
1096     switch (format & MPP_FRAME_FMT_MASK) {
1097     case MPP_FMT_YUV420P :
1098     case MPP_FMT_YUV420SP :
1099     case MPP_FMT_YUV420SP_VU : {
1100         mpp_frame_set_hor_stride(frame, hor_stride);
1101     } break;
1102     case MPP_FMT_RGB565:
1103     case MPP_FMT_BGR565:
1104     case MPP_FMT_RGB555:
1105     case MPP_FMT_BGR555: {
1106         mpp_frame_set_hor_stride(frame, hor_stride * 2);
1107     } break;
1108     case MPP_FMT_RGB888 :
1109     case MPP_FMT_BGR888 : {
1110         mpp_frame_set_hor_stride(frame, hor_stride * 3);
1111     } break;
1112     case MPP_FMT_ARGB8888 :
1113     case MPP_FMT_ABGR8888 :
1114     case MPP_FMT_BGRA8888 :
1115     case MPP_FMT_RGBA8888 : {
1116         mpp_frame_set_hor_stride(frame, hor_stride * 4);
1117     } break;
1118     default: {
1119         mpp_err("unsupport format 0x%x\n", format & MPP_FRAME_FMT_MASK);
1120     } break;
1121     }
1122     mpp_frame_set_fmt(frame, (MppFrameFormat)(format & MPP_FRAME_FMT_MASK));
1123     if (aEncInStrm->nFlags) {
1124         mpp_log_f("found eos\n");
1125         mpp_frame_set_eos(frame, 1);
1126     }
1127 
1128     fd = aEncInStrm->bufPhyAddr;
1129     if (fd_input < 0) {
1130         fd_input = is_valid_dma_fd(fd);
1131     }
1132     if (fd_input) {
1133         MppBufferInfo   inputCommit;
1134 
1135         memset(&inputCommit, 0, sizeof(inputCommit));
1136         inputCommit.type = MPP_BUFFER_TYPE_ION;
1137         inputCommit.size = aEncInStrm->size;
1138         inputCommit.fd = fd;
1139 
1140         ret = mpp_buffer_import(&pic_buf, &inputCommit);
1141         if (ret) {
1142             mpp_err_f("import input picture buffer failed\n");
1143             goto ENCODE_OUT;
1144         }
1145     } else {
1146         if (NULL == aEncInStrm->buf) {
1147             ret = MPP_ERR_NULL_PTR;
1148             goto ENCODE_OUT;
1149         }
1150 
1151         ret = mpp_buffer_get(memGroup, &pic_buf, aEncInStrm->size);
1152         if (ret) {
1153             mpp_err_f("allocate input picture buffer failed\n");
1154             goto ENCODE_OUT;
1155         }
1156         memcpy((RK_U8*) mpp_buffer_get_ptr(pic_buf), aEncInStrm->buf, aEncInStrm->size);
1157     }
1158 
1159     fd = (RK_S32)(aEncOut->timeUs & 0xffffffff);
1160 
1161     if (fd_output < 0) {
1162         fd_output = is_valid_dma_fd(fd);
1163     }
1164     if (fd_output) {
1165         RK_S32 *tmp = (RK_S32*)(&aEncOut->timeUs);
1166         MppBufferInfo outputCommit;
1167 
1168         memset(&outputCommit, 0, sizeof(outputCommit));
1169         /* in order to avoid interface change use space in output to transmit information */
1170         outputCommit.type = MPP_BUFFER_TYPE_ION;
1171         outputCommit.fd = fd;
1172         outputCommit.size = tmp[1];
1173         outputCommit.ptr = (void*)aEncOut->data;
1174 
1175         ret = mpp_buffer_import(&str_buf, &outputCommit);
1176         if (ret) {
1177             mpp_err_f("import output stream buffer failed\n");
1178             goto ENCODE_OUT;
1179         }
1180     } else {
1181         ret = mpp_buffer_get(memGroup, &str_buf, hor_stride * ver_stride);
1182         if (ret) {
1183             mpp_err_f("allocate output stream buffer failed\n");
1184             goto ENCODE_OUT;
1185         }
1186     }
1187 
1188     mpp_frame_set_buffer(frame, pic_buf);
1189     mpp_packet_init_with_buffer(&packet, str_buf);
1190     mpp_packet_set_length(packet, 0);
1191 
1192     vpu_api_dbg_func("mpp import input fd %d output fd %d",
1193                      mpp_buffer_get_fd(pic_buf), mpp_buffer_get_fd(str_buf));
1194 
1195     ret = mpi->poll(mpp_ctx, MPP_PORT_INPUT, MPP_POLL_BLOCK);
1196     if (ret) {
1197         mpp_err("mpp input poll failed\n");
1198         goto ENCODE_OUT;
1199     }
1200 
1201     ret = mpi->dequeue(mpp_ctx, MPP_PORT_INPUT, &task);
1202     if (ret) {
1203         mpp_err("mpp task input dequeue failed\n");
1204         goto ENCODE_OUT;
1205     }
1206     if (task == NULL) {
1207         mpp_err("mpi dequeue from MPP_PORT_INPUT fail, task equal with NULL!");
1208         goto ENCODE_OUT;
1209     }
1210 
1211     mpp_task_meta_set_frame (task, KEY_INPUT_FRAME,  frame);
1212     mpp_task_meta_set_packet(task, KEY_OUTPUT_PACKET, packet);
1213 
1214     ret = mpi->enqueue(mpp_ctx, MPP_PORT_INPUT, task);
1215     if (ret) {
1216         mpp_err("mpp task input enqueue failed\n");
1217         goto ENCODE_OUT;
1218     }
1219     task = NULL;
1220 
1221     ret = mpi->poll(mpp_ctx, MPP_PORT_OUTPUT, MPP_POLL_BLOCK);
1222     if (ret) {
1223         mpp_err("mpp output poll failed\n");
1224         goto ENCODE_OUT;
1225     }
1226 
1227     ret = mpi->dequeue(mpp_ctx, MPP_PORT_OUTPUT, &task);
1228     if (ret) {
1229         mpp_err("ret %d mpp task output dequeue failed\n", ret);
1230         goto ENCODE_OUT;
1231     }
1232 
1233     mpp_assert(task);
1234 
1235     if (task) {
1236         MppFrame frame_out = NULL;
1237         MppFrame packet_out = NULL;
1238 
1239         mpp_task_meta_get_packet(task, KEY_OUTPUT_PACKET, &packet_out);
1240 
1241         mpp_assert(packet_out == packet);
1242         vpu_api_dbg_func("encoded frame %d\n", frame_count);
1243         frame_count++;
1244 
1245         ret = mpi->enqueue(mpp_ctx, MPP_PORT_OUTPUT, task);
1246         if (ret) {
1247             mpp_err("mpp task output enqueue failed\n");
1248             goto ENCODE_OUT;
1249         }
1250         task = NULL;
1251 
1252         ret = mpi->poll(mpp_ctx, MPP_PORT_INPUT, MPP_POLL_BLOCK);
1253         if (ret) {
1254             mpp_err("mpp input poll failed\n");
1255             goto ENCODE_OUT;
1256         }
1257 
1258         // dequeue task from MPP_PORT_INPUT
1259         ret = mpi->dequeue(mpp_ctx, MPP_PORT_INPUT, &task);
1260         if (ret) {
1261             mpp_log_f("failed to dequeue from input port ret %d\n", ret);
1262             goto ENCODE_OUT;
1263         }
1264         mpp_assert(task);
1265         ret = mpp_task_meta_get_frame(task, KEY_INPUT_FRAME, &frame_out);
1266         mpp_assert(frame_out  == frame);
1267         ret = mpi->enqueue(mpp_ctx, MPP_PORT_INPUT, task);
1268         if (ret) {
1269             mpp_err("mpp task output enqueue failed\n");
1270             goto ENCODE_OUT;
1271         }
1272         task = NULL;
1273     }
1274 
1275     // copy encoded stream into output buffer, and set output stream size
1276     if (packet) {
1277         RK_U32 eos = mpp_packet_get_eos(packet);
1278         RK_S64 pts = mpp_packet_get_pts(packet);
1279         size_t length = mpp_packet_get_length(packet);
1280         MppMeta meta = mpp_packet_get_meta(packet);
1281         RK_S32 is_intra = 0;
1282 
1283         if (!fd_output) {
1284             RK_U8 *src = (RK_U8 *)mpp_packet_get_data(packet);
1285             size_t buffer = MPP_ALIGN(length, SZ_4K);
1286 
1287             aEncOut->data = mpp_malloc(RK_U8, buffer);
1288 
1289             if (ctx->videoCoding == OMX_RK_VIDEO_CodingAVC) {
1290                 // remove first 00 00 00 01
1291                 length -= 4;
1292                 memcpy(aEncOut->data, src + 4, length);
1293             } else {
1294                 memcpy(aEncOut->data, src, length);
1295             }
1296         }
1297 
1298         mpp_meta_get_s32(meta, KEY_OUTPUT_INTRA, &is_intra);
1299 
1300         aEncOut->size = (RK_S32)length;
1301         aEncOut->timeUs = pts;
1302         aEncOut->keyFrame = is_intra;
1303 
1304         vpu_api_dbg_output("get packet %p size %d pts %lld keyframe %d eos %d\n",
1305                            packet, length, pts, aEncOut->keyFrame, eos);
1306 
1307         mpp_packet_deinit(&packet);
1308     } else {
1309         mpp_log("outputPacket is NULL!");
1310     }
1311 
1312 ENCODE_OUT:
1313     if (pic_buf) {
1314         mpp_buffer_put(pic_buf);
1315         pic_buf = NULL;
1316     }
1317 
1318     if (str_buf) {
1319         mpp_buffer_put(str_buf);
1320         str_buf = NULL;
1321     }
1322 
1323     if (frame)
1324         mpp_frame_deinit(&frame);
1325 
1326     if (packet)
1327         mpp_packet_deinit(&packet);
1328 
1329     vpu_api_dbg_func("leave ret %d\n", ret);
1330 
1331     return ret;
1332 }
1333 
encoder_sendframe(VpuCodecContext * ctx,EncInputStream_t * aEncInStrm)1334 RK_S32 VpuApiLegacy::encoder_sendframe(VpuCodecContext *ctx, EncInputStream_t *aEncInStrm)
1335 {
1336     RK_S32 ret = 0;
1337     vpu_api_dbg_func("enter\n");
1338 
1339     RK_U32 width        = ctx->width;
1340     RK_U32 height       = ctx->height;
1341     RK_U32 hor_stride   = MPP_ALIGN(width,  16);
1342     RK_U32 ver_stride   = MPP_ALIGN(height, 8);
1343     RK_S64 pts          = aEncInStrm->timeUs;
1344     RK_S32 fd           = aEncInStrm->bufPhyAddr;
1345     RK_U32 size         = aEncInStrm->size;
1346 
1347     /* try import input buffer and output buffer */
1348     MppFrame frame = NULL;
1349 
1350     ret = mpp_frame_init(&frame);
1351     if (MPP_OK != ret) {
1352         mpp_err_f("mpp_frame_init failed\n");
1353         goto FUNC_RET;
1354     }
1355 
1356     mpp_frame_set_width(frame, width);
1357     mpp_frame_set_height(frame, height);
1358     mpp_frame_set_ver_stride(frame, ver_stride);
1359     mpp_frame_set_pts(frame, pts);
1360     switch (format & MPP_FRAME_FMT_MASK) {
1361     case MPP_FMT_YUV420P :
1362     case MPP_FMT_YUV420SP :
1363     case MPP_FMT_YUV420SP_VU : {
1364         mpp_frame_set_hor_stride(frame, hor_stride);
1365     } break;
1366     case MPP_FMT_RGB565:
1367     case MPP_FMT_BGR565:
1368     case MPP_FMT_RGB555:
1369     case MPP_FMT_BGR555: {
1370         mpp_frame_set_hor_stride(frame, hor_stride * 2);
1371     } break;
1372     case MPP_FMT_RGB888 :
1373     case MPP_FMT_BGR888 : {
1374         mpp_frame_set_hor_stride(frame, hor_stride * 3);
1375     } break;
1376     case MPP_FMT_ARGB8888 :
1377     case MPP_FMT_ABGR8888 :
1378     case MPP_FMT_BGRA8888 :
1379     case MPP_FMT_RGBA8888 : {
1380         mpp_frame_set_hor_stride(frame, hor_stride * 4);
1381     } break;
1382     default: {
1383         mpp_err("unsupport format 0x%x\n", format & MPP_FRAME_FMT_MASK);
1384     } break;
1385     }
1386     mpp_frame_set_fmt(frame, (MppFrameFormat)(format & MPP_FRAME_FMT_MASK));
1387     if (aEncInStrm->nFlags) {
1388         mpp_log_f("found eos true\n");
1389         mpp_frame_set_eos(frame, 1);
1390     }
1391 
1392     if (size <= 0) {
1393         mpp_frame_set_buffer(frame, NULL);
1394         if (!aEncInStrm->nFlags)
1395             mpp_err_f("found empty frame without eos flag set!\n");
1396         goto PUT_FRAME;
1397     }
1398 
1399     if (fd_input < 0) {
1400         fd_input = is_valid_dma_fd(fd);
1401     }
1402     if (fd_input) {
1403         MppBufferInfo   inputCommit;
1404 
1405         memset(&inputCommit, 0, sizeof(inputCommit));
1406         inputCommit.type = MPP_BUFFER_TYPE_ION;
1407         inputCommit.size = size;
1408         inputCommit.fd = fd;
1409         if (size > 0) {
1410             MppBuffer buffer = NULL;
1411             ret = mpp_buffer_import(&buffer, &inputCommit);
1412             if (ret) {
1413                 mpp_err_f("import input picture buffer failed\n");
1414                 goto FUNC_RET;
1415             }
1416             mpp_frame_set_buffer(frame, buffer);
1417             mpp_buffer_put(buffer);
1418             buffer = NULL;
1419         }
1420     } else {
1421         RK_U32 align_size   = 0;
1422 
1423         if (NULL == aEncInStrm->buf) {
1424             ret = MPP_ERR_NULL_PTR;
1425             goto FUNC_RET;
1426         }
1427         if (format >= MPP_FMT_YUV420SP && format < MPP_FMT_YUV_BUTT) {
1428             align_size = hor_stride * MPP_ALIGN(ver_stride, 16) * 3 / 2;
1429         } else  if (format >= MPP_FMT_YUV420SP_VU && format < MPP_FMT_YUV_BUTT) {
1430             align_size = hor_stride * MPP_ALIGN(ver_stride, 16) * 3 / 2;
1431         } else if (format >= MPP_FMT_RGB565 && format < MPP_FMT_BGR888) {
1432             align_size = hor_stride * MPP_ALIGN(ver_stride, 16) * 3;
1433         } else if (format >= MPP_FMT_RGB101010 && format < MPP_FMT_RGB_BUTT) {
1434             align_size = hor_stride * MPP_ALIGN(ver_stride, 16) * 4;
1435         } else {
1436             mpp_err_f("unsupport input format:%d\n", format);
1437             ret = MPP_NOK;
1438             goto FUNC_RET;
1439         }
1440         if (align_size > 0) {
1441             MppBuffer buffer = NULL;
1442             ret = mpp_buffer_get(memGroup, &buffer, align_size);
1443             if (ret) {
1444                 mpp_err_f("allocate input picture buffer failed\n");
1445                 goto FUNC_RET;
1446             }
1447             copy_align_raw_buffer_to_dest((RK_U8 *)mpp_buffer_get_ptr(buffer),
1448                                           aEncInStrm->buf, width, height, format);
1449             mpp_frame_set_buffer(frame, buffer);
1450             mpp_buffer_put(buffer);
1451             buffer = NULL;
1452         }
1453     }
1454 
1455 PUT_FRAME:
1456 
1457     vpu_api_dbg_input("w %d h %d input fd %d size %d pts %lld, flag %d \n",
1458                       width, height, fd, size, aEncInStrm->timeUs, aEncInStrm->nFlags);
1459     if (mlvec) {
1460         MppMeta meta = mpp_frame_get_meta(frame);
1461 
1462         vpu_api_mlvec_set_dy_cfg(mlvec, &mlvec_dy_cfg, meta);
1463     }
1464 
1465     ret = mpi->encode_put_frame(mpp_ctx, frame);
1466     if (ret)
1467         mpp_err_f("encode_put_frame ret %d\n", ret);
1468     else
1469         aEncInStrm->size = 0;
1470 
1471 FUNC_RET:
1472     if (frame)
1473         mpp_frame_deinit(&frame);
1474 
1475     vpu_api_dbg_func("leave ret %d\n", ret);
1476     return ret;
1477 }
1478 
encoder_getstream(VpuCodecContext * ctx,EncoderOut_t * aEncOut)1479 RK_S32 VpuApiLegacy::encoder_getstream(VpuCodecContext *ctx, EncoderOut_t *aEncOut)
1480 {
1481     RK_S32 ret = 0;
1482     MppPacket packet = NULL;
1483     vpu_api_dbg_func("enter\n");
1484 
1485     ret = mpi->encode_get_packet(mpp_ctx, &packet);
1486     if (ret) {
1487         mpp_err_f("encode_get_packet failed ret %d\n", ret);
1488         goto FUNC_RET;
1489     }
1490     if (packet) {
1491         RK_U8 *src = (RK_U8 *)mpp_packet_get_data(packet);
1492         RK_U32 eos = mpp_packet_get_eos(packet);
1493         RK_S64 pts = mpp_packet_get_pts(packet);
1494         size_t length = mpp_packet_get_length(packet);
1495         MppMeta meta = mpp_packet_get_meta(packet);
1496         RK_S32 is_intra = 0;
1497 
1498         RK_U32 offset = 0;
1499         if (ctx->videoCoding == OMX_RK_VIDEO_CodingAVC) {
1500             offset = 4;
1501             length = (length > offset) ? (length - offset) : 0;
1502         }
1503         aEncOut->data = NULL;
1504         if (length > 0) {
1505             aEncOut->data = mpp_calloc(RK_U8, MPP_ALIGN(length + 16, SZ_4K));
1506             if (aEncOut->data)
1507                 memcpy(aEncOut->data, src + offset, length);
1508         }
1509 
1510         mpp_meta_get_s32(meta, KEY_OUTPUT_INTRA, &is_intra);
1511 
1512         aEncOut->size = (RK_S32)length;
1513         aEncOut->timeUs = pts;
1514         aEncOut->keyFrame = is_intra;
1515 
1516         vpu_api_dbg_output("get packet %p size %d pts %lld keyframe %d eos %d\n",
1517                            packet, length, pts, aEncOut->keyFrame, eos);
1518 
1519         mEosSet = eos;
1520         mpp_packet_deinit(&packet);
1521     } else {
1522         aEncOut->size = 0;
1523         vpu_api_dbg_output("get NULL packet, eos %d\n", mEosSet);
1524         if (mEosSet)
1525             ret = -1;
1526     }
1527 
1528 FUNC_RET:
1529     vpu_api_dbg_func("leave ret %d\n", ret);
1530     return ret;
1531 }
1532 
perform(PerformCmd cmd,RK_S32 * data)1533 RK_S32 VpuApiLegacy::perform(PerformCmd cmd, RK_S32 *data)
1534 {
1535     vpu_api_dbg_func("enter\n");
1536     switch (cmd) {
1537     case INPUT_FORMAT_MAP : {
1538         EncInputPictureType vpu_frame_fmt = *(EncInputPictureType *)data;
1539         MppFrameFormat mpp_frame_fmt = vpu_pic_type_remap_to_mpp(vpu_frame_fmt);
1540         *(MppFrameFormat *)data = mpp_frame_fmt;
1541     } break;
1542     default:
1543         mpp_err("cmd can not match with any option!");
1544         break;
1545     }
1546     vpu_api_dbg_func("leave\n");
1547     return 0;
1548 }
1549 
frameReadyCallback(void * ctx,void * mppCtx,RK_S32 cmd,void * mppFrame)1550 static RK_S32 frameReadyCallback(void *ctx, void *mppCtx, RK_S32 cmd, void *mppFrame)
1551 {
1552     (void)mppCtx;
1553     (void)cmd;
1554     (void)mppFrame;
1555     VpuApiLegacy *vpuApi = (VpuApiLegacy *)ctx;
1556     RK_S32 ret = 0;
1557 
1558     vpu_api_dbg_func("enter\n");
1559 
1560     if (!vpuApi) {
1561         return ret;
1562     }
1563 
1564     if (vpuApi->frm_rdy_cb.cb) {
1565         ret = vpuApi->frm_rdy_cb.cb(vpuApi->frm_rdy_cb.cbCtx);
1566     }
1567 
1568     vpu_api_dbg_func("leave ret %d\n", ret);
1569 
1570     return ret;
1571 }
1572 
control(VpuCodecContext * ctx,VPU_API_CMD cmd,void * param)1573 RK_S32 VpuApiLegacy::control(VpuCodecContext *ctx, VPU_API_CMD cmd, void *param)
1574 {
1575     vpu_api_dbg_func("enter cmd 0x%x param %p\n", cmd, param);
1576 
1577     if (mpi == NULL && !init_ok) {
1578         return 0;
1579     }
1580 
1581     MpiCmd mpicmd = MPI_CMD_BUTT;
1582     switch (cmd) {
1583     case VPU_API_ENABLE_DEINTERLACE : {
1584         mpicmd = MPP_DEC_SET_ENABLE_DEINTERLACE;
1585     } break;
1586     case VPU_API_ENC_SETCFG : {
1587         MppCodingType coding = (MppCodingType)ctx->videoCoding;
1588 
1589         memcpy(&enc_param, param, sizeof(enc_param));
1590         return vpu_api_set_enc_cfg(mpp_ctx, mpi, enc_cfg, coding, format, &enc_param);
1591     } break;
1592     case VPU_API_ENC_GETCFG : {
1593         memcpy(param, &enc_param, sizeof(enc_param));
1594         return mpi->control(mpp_ctx, MPP_ENC_GET_CFG, enc_cfg);;
1595     } break;
1596     case VPU_API_ENC_SETFORMAT : {
1597         EncInputPictureType type = *((EncInputPictureType *)param);
1598         MppCodingType coding = (MppCodingType)ctx->videoCoding;
1599         MppFrameFormat old_fmt = format;
1600 
1601         format = vpu_pic_type_remap_to_mpp(type);
1602         if (old_fmt != format)
1603             return vpu_api_set_enc_cfg(mpp_ctx, mpi, enc_cfg, coding, format, &enc_param);
1604         else
1605             return 0;
1606     } break;
1607     case VPU_API_ENC_SETIDRFRAME : {
1608         mpicmd = MPP_ENC_SET_IDR_FRAME;
1609     } break;
1610     case VPU_API_SET_VPUMEM_CONTEXT: {
1611         mpicmd = MPP_DEC_SET_EXT_BUF_GROUP;
1612     } break;
1613     case VPU_API_USE_PRESENT_TIME_ORDER: {
1614         mpicmd = MPP_DEC_SET_PRESENT_TIME_ORDER;
1615     } break;
1616     case VPU_API_SET_INFO_CHANGE: {
1617         mpicmd = MPP_DEC_SET_INFO_CHANGE_READY;
1618     } break;
1619     case VPU_API_USE_FAST_MODE: {
1620         mpicmd = MPP_DEC_SET_PARSER_FAST_MODE;
1621     } break;
1622     case VPU_API_DEC_GET_STREAM_COUNT: {
1623         mpicmd = MPP_DEC_GET_STREAM_COUNT;
1624     } break;
1625     case VPU_API_GET_VPUMEM_USED_COUNT: {
1626         mpicmd = MPP_DEC_GET_VPUMEM_USED_COUNT;
1627     } break;
1628     case VPU_API_SET_OUTPUT_BLOCK: {
1629         mpicmd = MPP_SET_OUTPUT_TIMEOUT;
1630         if (param) {
1631             RK_S32 timeout = *((RK_S32*)param);
1632 
1633             if (timeout) {
1634                 if (timeout < 0)
1635                     mpp_log("set output mode to block\n");
1636                 else
1637                     mpp_log("set output timeout %d ms\n", timeout);
1638             } else {
1639                 mpp_log("set output mode to non-block\n");
1640             }
1641         }
1642     } break;
1643     case VPU_API_SET_INPUT_BLOCK: {
1644         mpicmd = MPP_SET_INPUT_TIMEOUT;
1645         if (param) {
1646             RK_S32 timeout = *((RK_S32*)param);
1647             mInputTimeOutMs = timeout;
1648 
1649             if (timeout) {
1650                 if (timeout < 0)
1651                     mpp_log("set input mode to block\n");
1652                 else
1653                     mpp_log("set input timeout %d ms\n", timeout);
1654             } else {
1655                 mpp_log("set input mode to non-block\n");
1656             }
1657         }
1658     } break;
1659     case VPU_API_GET_EOS_STATUS: {
1660         *((RK_S32 *)param) = mEosSet;
1661         mpicmd = MPI_CMD_BUTT;
1662     } break;
1663     case VPU_API_SET_FRAME_INFO: {
1664         mpicmd = MPI_CMD_BUTT;
1665         mpi->control(mpp_ctx, MPP_DEC_SET_FRAME_INFO, (MppParam)frm_info);
1666     } break;
1667     case VPU_API_GET_FRAME_INFO: {
1668         *((VPU_GENERIC *)param) = vpug;
1669         mpicmd = MPI_CMD_BUTT;
1670     } break;
1671     case VPU_API_SET_OUTPUT_MODE: {
1672         mpicmd = MPP_DEC_SET_OUTPUT_FORMAT;
1673         mpp_frame_set_fmt(frm_info, (param) ? (*((MppFrameFormat *)param)) :
1674                           (MPP_FMT_YUV420SP));
1675     } break;
1676     case VPU_API_DEC_EN_FBC_HDR_256_ODD : {
1677         MppCompat *compatItem = NULL;
1678         compatItem = mpp_compat_query_by_id(MPP_COMPAT_DEC_FBC_HDR_256_ODD);
1679         if (compatItem) {
1680             mpp_compat_update(compatItem, 1);
1681         }
1682     } break;
1683     case VPU_API_DEC_OUT_FRM_STRUCT_TYPE: {
1684         dec_out_frm_struct_type = *((RK_S32 *)param);
1685         return 0;
1686     } break;
1687     case VPU_API_DEC_EN_THUMBNAIL: {
1688         RK_S32 ret = 0;
1689         MppDecCfg cfg;
1690         RK_U32 val = *((RK_U32 *)param);
1691         ret = mpp_dec_cfg_init(&cfg);
1692         if (ret) {
1693             return ret;
1694         }
1695         ret = mpi->control(mpp_ctx, MPP_DEC_GET_CFG, cfg);
1696         mpp_dec_cfg_set_u32(cfg, "base:enable_thumbnail", val);
1697         ret = mpi->control(mpp_ctx, MPP_DEC_SET_CFG, cfg);
1698         mpp_dec_cfg_deinit(cfg);
1699         return ret;
1700     } break;
1701     case VPU_API_DEC_EN_HDR_META: {
1702         RK_S32 ret = 0;
1703         MppDecCfg cfg;
1704         RK_U32 val = *((RK_U32 *)param);
1705         ret = mpp_dec_cfg_init(&cfg);
1706         if (ret) {
1707             return ret;
1708         }
1709         ret = mpi->control(mpp_ctx, MPP_DEC_GET_CFG, cfg);
1710         mpp_dec_cfg_set_u32(cfg, "base:enable_hdr_meta", val);
1711         ret = mpi->control(mpp_ctx, MPP_DEC_SET_CFG, cfg);
1712         mpp_dec_cfg_deinit(cfg);
1713         return ret;
1714     } break;
1715     case VPU_API_SET_FRM_RDY_CB: {
1716         RK_S32 ret = 0;
1717         MppDecCfg cfg;
1718         FrameRdyCB *cb = (FrameRdyCB *)param;
1719 
1720         ret = mpp_dec_cfg_init(&cfg);
1721         if (ret) {
1722             return ret;
1723         }
1724 
1725         frm_rdy_cb.cb = cb->cb;
1726         frm_rdy_cb.cbCtx = cb->cbCtx;
1727         mpp_dec_cfg_set_ptr(cfg, "cb:frm_rdy_cb",
1728                             frm_rdy_cb.cb ? (void *)frm_rdy_cb.cb : (void *)frameReadyCallback);
1729         mpp_dec_cfg_set_ptr(cfg, "cb:frm_rdy_ctx", frm_rdy_cb.cbCtx);
1730         ret = mpi->control(mpp_ctx, MPP_DEC_SET_CFG, cfg);
1731         mpp_dec_cfg_deinit(cfg);
1732         return ret;
1733     } break;
1734     case VPU_API_SET_DISABLE_ERROR: {
1735         mpicmd = MPP_DEC_SET_DISABLE_ERROR;
1736     } break;
1737     case VPU_API_SET_DIS_ERR_CLR_MARK: {
1738         mpicmd = MPP_DEC_SET_DIS_ERR_CLR_MARK;
1739     } break;
1740     case VPU_API_SET_IMMEDIATE_OUT: {
1741         mpicmd = MPP_DEC_SET_IMMEDIATE_OUT;
1742     } break;
1743     case VPU_API_ENC_SET_VEPU22_CFG: {
1744         mpicmd = MPP_ENC_SET_CODEC_CFG;
1745     } break;
1746     case VPU_API_ENC_GET_VEPU22_CFG: {
1747         mpicmd = MPP_ENC_GET_CODEC_CFG;
1748     } break;
1749     case VPU_API_ENC_SET_VEPU22_CTU_QP: {
1750         mpicmd = MPP_ENC_SET_CTU_QP;
1751     } break;
1752     case VPU_API_ENC_SET_VEPU22_ROI: {
1753         mpicmd = MPP_ENC_SET_ROI_CFG;
1754     } break;
1755     case VPU_API_ENC_MPP_SETCFG: {
1756         mpicmd = MPP_ENC_SET_CFG;
1757     } break;
1758     case VPU_API_ENC_MPP_GETCFG: {
1759         *((MppEncCfg *)param) = enc_cfg;
1760         return 0;
1761     } break;
1762     case VPU_API_ENC_SET_MAX_TID: {
1763         RK_S32 max_tid = *(RK_S32 *)param;
1764 
1765         vpu_api_dbg_ctrl("VPU_API_ENC_SET_MAX_TID %d\n", max_tid);
1766         mlvec_dy_cfg.max_tid = max_tid;
1767         mlvec_dy_cfg.updated |= VPU_API_ENC_MAX_TID_UPDATED;
1768 
1769         if (mlvec)
1770             vpu_api_mlvec_set_dy_max_tid(mlvec, max_tid);
1771 
1772         return 0;
1773     } break;
1774     case VPU_API_ENC_SET_MARK_LTR: {
1775         RK_S32 mark_ltr = *(RK_S32 *)param;
1776 
1777         vpu_api_dbg_ctrl("VPU_API_ENC_SET_MARK_LTR %d\n", mark_ltr);
1778 
1779         mlvec_dy_cfg.mark_ltr = mark_ltr;
1780         if (mark_ltr >= 0)
1781             mlvec_dy_cfg.updated |= VPU_API_ENC_MARK_LTR_UPDATED;
1782 
1783         return 0;
1784     } break;
1785     case VPU_API_ENC_SET_USE_LTR: {
1786         RK_S32 use_ltr = *(RK_S32 *)param;
1787 
1788         vpu_api_dbg_ctrl("VPU_API_ENC_SET_USE_LTR %d\n", use_ltr);
1789 
1790         mlvec_dy_cfg.use_ltr = use_ltr;
1791         mlvec_dy_cfg.updated |= VPU_API_ENC_USE_LTR_UPDATED;
1792 
1793         return 0;
1794     } break;
1795     case VPU_API_ENC_SET_FRAME_QP: {
1796         RK_S32 frame_qp = *(RK_S32 *)param;
1797 
1798         vpu_api_dbg_ctrl("VPU_API_ENC_SET_FRAME_QP %d\n", frame_qp);
1799 
1800         mlvec_dy_cfg.frame_qp = frame_qp;
1801         mlvec_dy_cfg.updated |= VPU_API_ENC_FRAME_QP_UPDATED;
1802 
1803         return 0;
1804     } break;
1805     case VPU_API_ENC_SET_BASE_LAYER_PID: {
1806         RK_S32 base_layer_pid = *(RK_S32 *)param;
1807 
1808         vpu_api_dbg_ctrl("VPU_API_ENC_SET_BASE_LAYER_PID %d\n", base_layer_pid);
1809 
1810         mlvec_dy_cfg.base_layer_pid = base_layer_pid;
1811         mlvec_dy_cfg.updated |= VPU_API_ENC_BASE_PID_UPDATED;
1812 
1813         return 0;
1814     } break;
1815     case VPU_API_GET_EXTRA_INFO: {
1816         EncoderOut_t *out = (EncoderOut_t *)param;
1817 
1818         vpu_api_dbg_ctrl("VPU_API_GET_EXTRA_INFO\n");
1819 
1820         if (NULL == enc_hdr_pkt) {
1821             if (NULL == enc_hdr_buf) {
1822                 enc_hdr_buf_size = SZ_1K;
1823                 enc_hdr_buf = mpp_calloc_size(RK_U8, enc_hdr_buf_size);
1824             }
1825 
1826             if (enc_hdr_buf)
1827                 mpp_packet_init(&enc_hdr_pkt, enc_hdr_buf, enc_hdr_buf_size);
1828         }
1829 
1830         mpp_assert(enc_hdr_pkt);
1831         if (enc_hdr_pkt) {
1832             mpi->control(mpp_ctx, MPP_ENC_GET_HDR_SYNC, enc_hdr_pkt);
1833 
1834             RK_S32 length = mpp_packet_get_length(enc_hdr_pkt);
1835             void *src = mpp_packet_get_data(enc_hdr_pkt);
1836 
1837             memcpy(out->data, src, length);
1838             out->size = length;
1839         }
1840         return 0;
1841     } break;
1842     case VPU_API_SET_PARSER_SPLIT_MODE: {
1843         mpicmd = MPP_DEC_SET_PARSER_SPLIT_MODE;
1844     } break;
1845     case VPU_API_DEC_EN_MVC: {
1846         mpicmd = MPP_DEC_SET_ENABLE_MVC;
1847     } break;
1848     default: {
1849     } break;
1850     }
1851 
1852     RK_S32 ret = -1;
1853     if (mpicmd < MPI_CMD_BUTT)
1854         ret = mpi->control(mpp_ctx, mpicmd, (MppParam)param);
1855 
1856     vpu_api_dbg_func("leave\n");
1857     return ret;
1858 }
1859 
1860