1/*
2 * Copyright (c) 2021 Rockchip Electronics Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#define MODULE_TAG "mpi_enc_utils"
17
18#include <string.h>
19#include "securec.h"
20#include "mpp_mem.h"
21#include "mpp_log.h"
22#include "mpp_buffer.h"
23#include "rk_mpi.h"
24#include "mpp_common.h"
25#include "mpp_packet.h"
26#include "mpi_enc_utils.h"
27
28#include "mpp_env.h"
29
30static MPP_RET mpi_enc_gen_ref_cfg(MppEncRefCfg ref, signed int gop_mode)
31{
32    MppEncRefLtFrmCfg lt_ref[4];
33    MppEncRefStFrmCfg st_ref[16];
34    signed int lt_cnt = 0;
35    signed int st_cnt = 0;
36    MPP_RET ret = 0;
37
38    errno_t eok = memset_s(&lt_ref, sizeof(lt_ref), 0, sizeof(lt_ref));
39    if (eok != EOK) {
40        mpp_err("memset_s failed\n");
41        return MPP_NOK;
42    }
43    eok = memset_s(&st_ref, sizeof(st_ref), 0, sizeof(st_ref));
44    if (eok != EOK) {
45        mpp_err("memset_s failed\n");
46        return MPP_NOK;
47    }
48
49    switch (gop_mode) {
50        case 0x3: {
51            // tsvc4
52            //      /-> P1      /-> P3        /-> P5      /-> P7
53            //     /           /             /           /
54            //    //--------> P2            //--------> P6
55            //   //                        //
56            //  ///---------------------> P4
57            // ///
58            // P0 ------------------------------------------------> P8
59            lt_cnt = 1;
60
61            /* set 8 frame lt-ref gap */
62            lt_ref[0].lt_idx = 0;
63            lt_ref[0].temporal_id = 0;
64            lt_ref[0].ref_mode = REF_TO_PREV_LT_REF;
65            lt_ref[0].lt_gap = 8; // 8:set 8 frame
66            lt_ref[0].lt_delay = 0;
67
68            st_cnt = 0x9;
69            /* set tsvc4 st-ref struct */
70            /* st 0 layer 0 - ref */
71            st_ref[0].is_non_ref = 0;
72            st_ref[0].temporal_id = 0;
73            st_ref[0].ref_mode = REF_TO_TEMPORAL_LAYER;
74            st_ref[0].ref_arg = 0;
75            st_ref[0].repeat = 0;
76            /* st 1 layer 3 - non-ref */
77            st_ref[1].is_non_ref = 1;
78            st_ref[1].temporal_id = 0x3;
79            st_ref[1].ref_mode = REF_TO_PREV_REF_FRM;
80            st_ref[1].ref_arg = 0;
81            st_ref[1].repeat = 0;
82            /* st 2 layer 2 - ref */
83            st_ref[0x2].is_non_ref = 0;
84            st_ref[0x2].temporal_id = 0x2;
85            st_ref[0x2].ref_mode = REF_TO_PREV_REF_FRM;
86            st_ref[0x2].ref_arg = 0;
87            st_ref[0x2].repeat = 0;
88            /* st 3 layer 3 - non-ref */
89            st_ref[0x3].is_non_ref = 1;
90            st_ref[0x3].temporal_id = 0x3;
91            st_ref[0x3].ref_mode = REF_TO_PREV_REF_FRM;
92            st_ref[0x3].ref_arg = 0;
93            st_ref[0x3].repeat = 0;
94            /* st 4 layer 1 - ref */
95            st_ref[0x4].is_non_ref = 0;
96            st_ref[0x4].temporal_id = 1;
97            st_ref[0x4].ref_mode = REF_TO_PREV_LT_REF;
98            st_ref[0x4].ref_arg = 0;
99            st_ref[0x4].repeat = 0;
100            /* st 5 layer 3 - non-ref */
101            st_ref[0x5].is_non_ref = 1;
102            st_ref[0x5].temporal_id = 0x3;
103            st_ref[0x5].ref_mode = REF_TO_PREV_REF_FRM;
104            st_ref[0x5].ref_arg = 0;
105            st_ref[0x5].repeat = 0;
106            /* st 6 layer 2 - ref */
107            st_ref[0x6].is_non_ref = 0;
108            st_ref[0x6].temporal_id = 0x2;
109            st_ref[0x6].ref_mode = REF_TO_PREV_REF_FRM;
110            st_ref[0x6].ref_arg = 0;
111            st_ref[0x6].repeat = 0;
112            /* st 7 layer 3 - non-ref */
113            st_ref[0x7].is_non_ref = 1;
114            st_ref[0x7].temporal_id = 0x3;
115            st_ref[0x7].ref_mode = REF_TO_PREV_REF_FRM;
116            st_ref[0x7].ref_arg = 0;
117            st_ref[0x7].repeat = 0;
118            /* st 8 layer 0 - ref */
119            st_ref[0x8].is_non_ref = 0;
120            st_ref[0x8].temporal_id = 0;
121            st_ref[0x8].ref_mode = REF_TO_TEMPORAL_LAYER;
122            st_ref[0x8].ref_arg = 0;
123            st_ref[0x8].repeat = 0;
124            break;
125        }
126        case 0x2: {
127            // tsvc3
128            //     /-> P1      /-> P3
129            //    /           /
130            //   //--------> P2
131            //  //
132            // P0/---------------------> P4
133            lt_cnt = 0;
134
135            st_cnt = 0x5;
136            /* set tsvc4 st-ref struct */
137            /* st 0 layer 0 - ref */
138            st_ref[0].is_non_ref = 0;
139            st_ref[0].temporal_id = 0;
140            st_ref[0].ref_mode = REF_TO_TEMPORAL_LAYER;
141            st_ref[0].ref_arg = 0;
142            st_ref[0].repeat = 0;
143            /* st 1 layer 2 - non-ref */
144            st_ref[0x1].is_non_ref = 0x1;
145            st_ref[0x1].temporal_id = 0x2;
146            st_ref[0x1].ref_mode = REF_TO_PREV_REF_FRM;
147            st_ref[0x1].ref_arg = 0;
148            st_ref[0x1].repeat = 0;
149            /* st 2 layer 1 - ref */
150            st_ref[0x2].is_non_ref = 0;
151            st_ref[0x2].temporal_id = 0x1;
152            st_ref[0x2].ref_mode = REF_TO_PREV_REF_FRM;
153            st_ref[0x2].ref_arg = 0;
154            st_ref[0x2].repeat = 0;
155            /* st 3 layer 2 - non-ref */
156            st_ref[0x3].is_non_ref = 0x1;
157            st_ref[0x3].temporal_id = 0x2;
158            st_ref[0x3].ref_mode = REF_TO_PREV_REF_FRM;
159            st_ref[0x3].ref_arg = 0;
160            st_ref[0x3].repeat = 0;
161            /* st 4 layer 0 - ref */
162            st_ref[0x4].is_non_ref = 0;
163            st_ref[0x4].temporal_id = 0;
164            st_ref[0x4].ref_mode = REF_TO_TEMPORAL_LAYER;
165            st_ref[0x4].ref_arg = 0;
166            st_ref[0x4].repeat = 0;
167            break;
168        }
169        case 1: {
170            // tsvc2
171            //   /-> P1
172            //  /
173            // P0--------> P2
174            lt_cnt = 0;
175
176            st_cnt = 0x3;
177            /* set tsvc4 st-ref struct */
178            /* st 0 layer 0 - ref */
179            st_ref[0].is_non_ref = 0;
180            st_ref[0].temporal_id = 0;
181            st_ref[0].ref_mode = REF_TO_TEMPORAL_LAYER;
182            st_ref[0].ref_arg = 0;
183            st_ref[0].repeat = 0;
184            /* st 1 layer 2 - non-ref */
185            st_ref[1].is_non_ref = 1;
186            st_ref[1].temporal_id = 1;
187            st_ref[1].ref_mode = REF_TO_PREV_REF_FRM;
188            st_ref[1].ref_arg = 0;
189            st_ref[1].repeat = 0;
190            /* st 2 layer 1 - ref */
191            st_ref[0x2].is_non_ref = 0;
192            st_ref[0x2].temporal_id = 0;
193            st_ref[0x2].ref_mode = REF_TO_PREV_REF_FRM;
194            st_ref[0x2].ref_arg = 0;
195            st_ref[0x2].repeat = 0;
196            break;
197        }
198        default: {
199            mpp_err_f("unsupport gop mode %d\n", gop_mode);
200            break;
201        }
202    }
203
204    if (lt_cnt || st_cnt) {
205        ret = mpp_enc_ref_cfg_set_cfg_cnt(ref, lt_cnt, st_cnt);
206
207        if (lt_cnt) {
208            ret = mpp_enc_ref_cfg_add_lt_cfg(ref, lt_cnt, lt_ref);
209        }
210
211        if (st_cnt) {
212            ret = mpp_enc_ref_cfg_add_st_cfg(ref, st_cnt, st_ref);
213        }
214
215        /* check and get dpb size */
216        ret = mpp_enc_ref_cfg_check(ref);
217    }
218
219    return ret;
220}
221
222static MPP_RET mpi_enc_gen_smart_gop_ref_cfg(MppEncRefCfg ref, signed int gop_len, signed int vi_len)
223{
224    MppEncRefLtFrmCfg lt_ref[4];
225    MppEncRefStFrmCfg st_ref[16];
226    signed int lt_cnt = 1;
227    signed int st_cnt = 0x8;
228    signed int pos = 0;
229    MPP_RET ret = 0;
230
231    errno_t eok = memset_s(&lt_ref, sizeof(lt_ref), 0, sizeof(lt_ref));
232    if (eok != EOK) {
233        mpp_err("memset_s failed\n");
234        return MPP_NOK;
235    }
236    eok = memset_s(&st_ref, sizeof(st_ref), 0, sizeof(st_ref));
237    if (eok != EOK) {
238        mpp_err("memset_s failed\n");
239        return MPP_NOK;
240    }
241
242    ret = mpp_enc_ref_cfg_set_cfg_cnt(ref, lt_cnt, st_cnt);
243
244    /* set 8 frame lt-ref gap */
245    lt_ref[0].lt_idx = 0;
246    lt_ref[0].temporal_id = 0;
247    lt_ref[0].ref_mode = REF_TO_PREV_LT_REF;
248    lt_ref[0].lt_gap = gop_len;
249    lt_ref[0].lt_delay = 0;
250
251    mpp_enc_ref_cfg_add_lt_cfg(ref, 1, lt_ref);
252
253    /* st 0 layer 0 - ref */
254    st_ref[pos].is_non_ref = 0;
255    st_ref[pos].temporal_id = 0;
256    st_ref[pos].ref_mode = REF_TO_PREV_INTRA;
257    st_ref[pos].ref_arg = 0;
258    st_ref[pos].repeat = 0;
259    pos++;
260
261    /* st 1 layer 1 - non-ref */
262    if (vi_len > 1) {
263        st_ref[pos].is_non_ref = 0;
264        st_ref[pos].temporal_id = 1;
265        st_ref[pos].ref_mode = REF_TO_PREV_REF_FRM;
266        st_ref[pos].ref_arg = 0;
267        st_ref[pos].repeat = vi_len - 0x2;
268        pos++;
269    }
270
271    st_ref[pos].is_non_ref = 0;
272    st_ref[pos].temporal_id = 0;
273    st_ref[pos].ref_mode = REF_TO_PREV_INTRA;
274    st_ref[pos].ref_arg = 0;
275    st_ref[pos].repeat = 0;
276    pos++;
277
278    mpp_enc_ref_cfg_add_st_cfg(ref, pos, st_ref);
279
280    /* check and get dpb size */
281    ret = mpp_enc_ref_cfg_check(ref);
282
283    return ret;
284}
285
286/* ���˱������õ�һЩ����������ߣ�����ͼ���ʽ����������ʽ�ȣ�����������֪��ֱ����0
287 * test_mpp_enc_cfg_setup�������Զ�����Ĭ�ϵIJ�����bps�� gop�Ȳ���
288 */
289static MPP_RET test_ctx_init(MpiEncTestData **data, MpiEncTestArgs *cmd)
290{
291    MpiEncTestData *p = NULL;
292    MPP_RET ret = 0;
293
294    if (!data || !cmd) {
295        mpp_err_f("invalid input data %p cmd %p\n", data, cmd);
296        return MPP_ERR_NULL_PTR;
297    }
298
299    p = mpp_calloc(MpiEncTestData, 1);
300    if (!p) {
301        mpp_err_f("create MpiEncTestData failed\n");
302        ret = MPP_ERR_MALLOC;
303        *data = p;
304        return ret;
305    }
306
307    // get paramter from cmd
308    p->width = cmd->width;
309    p->height = cmd->height;
310    p->hor_stride = MPP_ALIGN(cmd->width, 0x10);  // 16:hor_stride
311    p->ver_stride = MPP_ALIGN(cmd->height, 0x10); // 16:ver_stride
312    p->fmt = cmd->format;
313    p->type = cmd->type;
314
315    // update resource parameter
316    switch (p->fmt & MPP_FRAME_FMT_MASK) {
317        case MPP_FMT_YUV420SP:
318        case MPP_FMT_YUV420P: {
319            p->frame_size = MPP_ALIGN(p->hor_stride, 0x40) * MPP_ALIGN(p->ver_stride, 0x40) * 0x3 / 0x2;
320            break;
321        }
322        case MPP_FMT_YUV422_YUYV:
323        case MPP_FMT_YUV422_YVYU:
324        case MPP_FMT_YUV422_UYVY:
325        case MPP_FMT_YUV422_VYUY:
326        case MPP_FMT_YUV422P:
327        case MPP_FMT_YUV422SP:
328        case MPP_FMT_RGB444:
329        case MPP_FMT_BGR444:
330        case MPP_FMT_RGB555:
331        case MPP_FMT_BGR555:
332        case MPP_FMT_RGB565:
333        case MPP_FMT_BGR565: {
334            p->frame_size = MPP_ALIGN(p->hor_stride, 0x40) * MPP_ALIGN(p->ver_stride, 0x40) * 0x2;
335            break;
336        }
337        default: {
338            p->frame_size = MPP_ALIGN(p->hor_stride, 0x40) * MPP_ALIGN(p->ver_stride, 0x40) * 0x4;
339            break;
340        }
341    }
342    *data = p;
343    return ret;
344}
345
346static MPP_RET test_ctx_deinit(MpiEncTestData **data)
347{
348    MpiEncTestData *p = NULL;
349
350    if (!data) {
351        mpp_err_f("invalid input data %p\n", data);
352        return MPP_ERR_NULL_PTR;
353    }
354    p = *data;
355    if (p) {
356        MPP_FREE(p);
357        *data = NULL;
358    }
359    return MPP_OK;
360}
361
362static MPP_RET test_mpp_enc_cfg_setup(MpiEncTestData *p)
363{
364    MPP_RET ret;
365    MppApi *mpi;
366    MppCtx ctx;
367    MppEncCfg cfg;
368
369    if (p == NULL) {
370        return MPP_ERR_NULL_PTR;
371    }
372
373    mpi = p->mpi;
374    ctx = p->ctx;
375    cfg = p->cfg;
376
377    /* setup default parameter */
378    if (p->fps_in_den == 0) {
379        p->fps_in_den = 1;
380    }
381    if (p->fps_in_num == 0) {
382        p->fps_in_num = 0x1e;
383    }
384    if (p->fps_out_den == 0) {
385        p->fps_out_den = 1;
386    }
387    if (p->fps_out_num == 0) {
388        p->fps_out_num = 0x1e;
389    }
390
391    /* ����Ĭ��bps */
392    if (!p->bps) {
393        p->bps = p->width * p->height / 0x8 * (p->fps_out_num / p->fps_out_den);
394    }
395
396    mpp_enc_cfg_set_s32(cfg, "prep:width", p->width);
397    mpp_enc_cfg_set_s32(cfg, "prep:height", p->height);
398    mpp_enc_cfg_set_s32(cfg, "prep:hor_stride", p->hor_stride);
399    mpp_enc_cfg_set_s32(cfg, "prep:ver_stride", p->ver_stride);
400    mpp_enc_cfg_set_s32(cfg, "prep:format", p->fmt);
401
402    mpp_enc_cfg_set_s32(cfg, "rc:mode", p->rc_mode);
403
404    /* fix input / output frame rate */
405    mpp_enc_cfg_set_s32(cfg, "rc:fps_in_flex", p->fps_in_flex);
406    mpp_enc_cfg_set_s32(cfg, "rc:fps_in_num", p->fps_in_num);
407    mpp_enc_cfg_set_s32(cfg, "rc:fps_in_denorm", p->fps_in_den);
408    mpp_enc_cfg_set_s32(cfg, "rc:fps_out_flex", p->fps_out_flex);
409    mpp_enc_cfg_set_s32(cfg, "rc:fps_out_num", p->fps_out_num);
410    mpp_enc_cfg_set_s32(cfg, "rc:fps_out_denorm", p->fps_out_den);
411    mpp_enc_cfg_set_s32(cfg, "rc:gop", p->gop_len ? p->gop_len : p->fps_out_num * 0x2);
412
413    /* drop frame or not when bitrate overflow */
414    mpp_enc_cfg_set_u32(cfg, "rc:drop_mode", MPP_ENC_RC_DROP_FRM_DISABLED);
415    mpp_enc_cfg_set_u32(cfg, "rc:drop_thd", 0x14); /* 20% of max bps */
416    mpp_enc_cfg_set_u32(cfg, "rc:drop_gap", 0x1);  /* Do not continuous drop frame */
417
418    /* setup bitrate for different rc_mode */
419    mpp_enc_cfg_set_s32(cfg, "rc:bps_target", p->bps);
420    switch (p->rc_mode) {
421        case MPP_ENC_RC_MODE_FIXQP: {
422            /* do not setup bitrate on FIXQP mode */
423            break;
424        }
425        case MPP_ENC_RC_MODE_CBR: {
426            /* CBR mode has narrow bound */
427            mpp_enc_cfg_set_s32(cfg, "rc:bps_max", p->bps_max ? p->bps_max : p->bps * 0x11 / 0x10);
428            mpp_enc_cfg_set_s32(cfg, "rc:bps_min", p->bps_min ? p->bps_min : p->bps * 0xf / 0x10);
429            break;
430        }
431        case MPP_ENC_RC_MODE_VBR:
432        case MPP_ENC_RC_MODE_AVBR: {
433            /* VBR mode has wide bound */
434            mpp_enc_cfg_set_s32(cfg, "rc:bps_max", p->bps_max ? p->bps_max : p->bps * 0x11 / 0x10);
435            mpp_enc_cfg_set_s32(cfg, "rc:bps_min", p->bps_min ? p->bps_min : p->bps * 1 / 0x10);
436            break;
437        }
438        default: {
439            /* default use CBR mode */
440            mpp_enc_cfg_set_s32(cfg, "rc:bps_max", p->bps_max ? p->bps_max : p->bps * 0x11 / 0x10);
441            mpp_enc_cfg_set_s32(cfg, "rc:bps_min", p->bps_min ? p->bps_min : p->bps * 0xf / 0x10);
442            break;
443        }
444    }
445
446    /* setup qp for different codec and rc_mode */
447    switch (p->type) {
448        case MPP_VIDEO_CodingAVC:
449        case MPP_VIDEO_CodingHEVC: {
450            switch (p->rc_mode) {
451                case MPP_ENC_RC_MODE_FIXQP: {
452                    mpp_enc_cfg_set_s32(cfg, "rc:qp_init", 0x14);  // 20:mpp cfg value
453                    mpp_enc_cfg_set_s32(cfg, "rc:qp_max", 0x14);   // 20:mpp cfg value
454                    mpp_enc_cfg_set_s32(cfg, "rc:qp_min", 0x14);   // 20:mpp cfg value
455                    mpp_enc_cfg_set_s32(cfg, "rc:qp_max_i", 0x14); // 20:mpp cfg value
456                    mpp_enc_cfg_set_s32(cfg, "rc:qp_min_i", 0x14); // 20:mpp cfg value
457                    mpp_enc_cfg_set_s32(cfg, "rc:qp_ip", 0x2);
458                    break;
459                }
460                case MPP_ENC_RC_MODE_CBR:
461                case MPP_ENC_RC_MODE_VBR:
462                case MPP_ENC_RC_MODE_AVBR: {
463                    mpp_enc_cfg_set_s32(cfg, "rc:qp_init", 0x1a);  // 26:mpp cfg value
464                    mpp_enc_cfg_set_s32(cfg, "rc:qp_max", 0x33);   // 51:mpp cfg value
465                    mpp_enc_cfg_set_s32(cfg, "rc:qp_min", 0xa);    // 10:mpp cfg value
466                    mpp_enc_cfg_set_s32(cfg, "rc:qp_max_i", 0x33); // 51:mpp cfg value
467                    mpp_enc_cfg_set_s32(cfg, "rc:qp_min_i", 0xa);  // 10:mpp cfg value
468                    mpp_enc_cfg_set_s32(cfg, "rc:qp_ip", 0x2);
469                    break;
470                }
471                default: {
472                    mpp_err_f("unsupport encoder rc mode %d\n", p->rc_mode);
473                    break;
474                }
475            }
476            break;
477        }
478        case MPP_VIDEO_CodingVP8: {
479            /* vp8 only setup base qp range */
480            mpp_enc_cfg_set_s32(cfg, "rc:qp_init", 0x28); // 40:mpp cfg value
481            mpp_enc_cfg_set_s32(cfg, "rc:qp_max", 0x7f);  // 127:mpp cfg value
482            mpp_enc_cfg_set_s32(cfg, "rc:qp_min", 0);
483            mpp_enc_cfg_set_s32(cfg, "rc:qp_max_i", 0x7f); // 127:mpp cfg value
484            mpp_enc_cfg_set_s32(cfg, "rc:qp_min_i", 0);
485            mpp_enc_cfg_set_s32(cfg, "rc:qp_ip", 0x6); // 6:mpp cfg value
486            break;
487        }
488        case MPP_VIDEO_CodingMJPEG: {
489            /* jpeg use special codec config to control qtable */
490            mpp_enc_cfg_set_s32(cfg, "jpeg:q_factor", 0x50); // 80:mpp cfg value
491            mpp_enc_cfg_set_s32(cfg, "jpeg:qf_max", 0x63);   // 99:mpp cfg value
492            mpp_enc_cfg_set_s32(cfg, "jpeg:qf_min", 1);
493            break;
494        }
495        default: {
496            break;
497        }
498    }
499
500    /* setup codec  */
501    mpp_enc_cfg_set_s32(cfg, "codec:type", p->type);
502    switch (p->type) {
503        case MPP_VIDEO_CodingAVC: {
504            /*
505             * H.264 profile_idc parameter
506             * 66  - Baseline profile
507             * 77  - Main profile
508             * 100 - High profile
509             */
510            mpp_enc_cfg_set_s32(cfg, "h264:profile", 0x64);
511            /*
512             * H.264 level_idc parameter
513             * 10 / 11 / 12 / 13    - qcif@15fps / cif@7.5fps / cif@15fps / cif@30fps
514             * 20 / 21 / 22         - cif@30fps / half-D1@@25fps / D1@12.5fps
515             * 30 / 31 / 32         - D1@25fps / 720p@30fps / 720p@60fps
516             * 40 / 41 / 42         - 1080p@30fps / 1080p@30fps / 1080p@60fps
517             * 50 / 51 / 52         - 4K@30fps
518             */
519            mpp_enc_cfg_set_s32(cfg, "h264:level", 0x28);
520            mpp_enc_cfg_set_s32(cfg, "h264:cabac_en", 0x1);
521            mpp_enc_cfg_set_s32(cfg, "h264:cabac_idc", 0x0);
522            mpp_enc_cfg_set_s32(cfg, "h264:trans8x8", 0x1);
523            break;
524        }
525        case MPP_VIDEO_CodingHEVC:
526        case MPP_VIDEO_CodingMJPEG:
527        case MPP_VIDEO_CodingVP8: {
528            break;
529        }
530        default: {
531            mpp_err_f("unsupport encoder coding type %d\n", p->type);
532            break;
533        }
534    }
535
536    p->split_mode = 0;
537    p->split_arg = 0;
538
539    mpp_env_get_u32("split_mode", &p->split_mode, MPP_ENC_SPLIT_NONE);
540    mpp_env_get_u32("split_arg", &p->split_arg, 0);
541
542    if (p->split_mode) {
543        mpp_log("%p split_mode %d split_arg %d\n", ctx, p->split_mode, p->split_arg);
544        mpp_enc_cfg_set_s32(cfg, "split:mode", p->split_mode);
545        mpp_enc_cfg_set_s32(cfg, "split:arg", p->split_arg);
546    }
547
548    ret = mpi->control(ctx, MPP_ENC_SET_CFG, cfg);
549    if (ret) {
550        mpp_err("mpi control enc set cfg failed ret %d\n", ret);
551        return ret;
552    }
553
554    /* optional */
555    p->sei_mode = MPP_ENC_SEI_MODE_ONE_FRAME;
556    ret = mpi->control(ctx, MPP_ENC_SET_SEI_CFG, &p->sei_mode);
557    if (ret) {
558        mpp_err("mpi control enc set sei cfg failed ret %d\n", ret);
559        return ret;
560    }
561
562    if (p->type == MPP_VIDEO_CodingAVC || p->type == MPP_VIDEO_CodingHEVC) {
563        p->header_mode = MPP_ENC_HEADER_MODE_EACH_IDR;
564        ret = mpi->control(ctx, MPP_ENC_SET_HEADER_MODE, &p->header_mode);
565        if (ret) {
566            mpp_err("mpi control enc set header mode failed ret %d\n", ret);
567            return ret;
568        }
569    }
570
571    unsigned int gop_mode = p->gop_mode;
572
573    mpp_env_get_u32("gop_mode", &gop_mode, gop_mode);
574    if (gop_mode) {
575        MppEncRefCfg ref;
576
577        mpp_enc_ref_cfg_init(&ref);
578
579        if (p->gop_mode < 0x4) {
580            mpi_enc_gen_ref_cfg(ref, gop_mode);
581        } else {
582            mpi_enc_gen_smart_gop_ref_cfg(ref, p->gop_len, p->vi_len);
583        }
584        ret = mpi->control(ctx, MPP_ENC_SET_REF_CFG, ref);
585        if (ret) {
586            mpp_err("mpi control enc set ref cfg failed ret %d\n", ret);
587            return ret;
588        }
589        mpp_enc_ref_cfg_deinit(&ref);
590    }
591    return ret;
592}
593
594static void test_mpp_frame_set_param(MppFrame frame, MpiEncTestData *p)
595{
596    mpp_frame_set_width(frame, p->width);
597    mpp_frame_set_height(frame, p->height);
598    mpp_frame_set_hor_stride(frame, p->hor_stride);
599    mpp_frame_set_ver_stride(frame, p->ver_stride);
600    mpp_frame_set_fmt(frame, p->fmt);
601    mpp_frame_set_eos(frame, p->frm_eos);
602}
603
604static void test_mpp_ctx_cleanup(MpiEncTestData *p)
605{
606    if (!p) {
607        mpp_err("test_mpp_ctx_cleanup p == NULL\n");
608        return;
609    }
610
611    if (p->mpi->reset) {
612        p->mpi->reset(p->ctx);
613    }
614
615    if (p->ctx) {
616        mpp_destroy(p->ctx);
617        p->ctx = NULL;
618    }
619
620    if (p->cfg) {
621        mpp_enc_cfg_deinit(p->cfg);
622        p->cfg = NULL;
623    }
624
625    if (p->pkt_buf) {
626        mpp_buffer_put(p->pkt_buf);
627        p->pkt_buf = NULL;
628    }
629
630    if (p->buf_grp) {
631        mpp_buffer_group_put(p->buf_grp);
632        p->buf_grp = NULL;
633    }
634
635    test_ctx_deinit(&p);
636}
637
638int hal_mpp_get_sps(void *ctx, unsigned char *buf, size_t *buf_size)
639{
640    int ret;
641    MppApi *mpi;
642    MppCtx mpp_ctx;
643    MppPacket packet = NULL;
644    MpiEncTestData *p = (MpiEncTestData *)ctx;
645    errno_t eok;
646
647    if (!p) {
648        mpp_err("mpi control enc get extra info failed\n");
649        return MPP_NOK;
650    }
651    mpi = p->mpi;
652    mpp_ctx = p->ctx;
653
654    /*
655     * Can use packet with normal malloc buffer as input not pkt_buf.
656     * Please refer to vpu_api_legacy.cpp for normal buffer case.
657     * Using pkt_buf buffer here is just for simplifing demo.
658     */
659
660    mpp_packet_init_with_buffer(&packet, p->pkt_buf);
661    /* NOTE: It is important to clear output packet length!! */
662    mpp_packet_set_length(packet, 0);
663
664    if (p->type == MPP_VIDEO_CodingAVC || p->type == MPP_VIDEO_CodingHEVC) {
665        ret = mpi->control(mpp_ctx, MPP_ENC_GET_HDR_SYNC, packet);
666        if (ret) {
667            mpp_err("mpi control enc get extra info failed\n");
668            ret = MPP_NOK;
669            mpp_packet_deinit(&packet);
670            return ret;
671        }
672    }
673
674    void *ptr = mpp_packet_get_pos(packet);
675    size_t len = mpp_packet_get_length(packet);
676    if (*buf_size < len) {
677        mpp_err("mpi buffer size too small\n");
678        ret = MPP_NOK;
679        mpp_packet_deinit(&packet);
680        return ret;
681    }
682
683    eok = memcpy_s(buf, len, ptr, len);
684    if (eok != EOK) {
685        mpp_err("memcpy_s failed\n");
686        return MPP_NOK;
687    }
688
689    *buf_size = len;
690
691    ret = MPP_OK;
692    mpp_packet_deinit(&packet);
693    return ret;
694}
695
696int hal_mpp_encode(void *ctx, int dma_fd, unsigned char *buf, size_t *buf_size)
697{
698    if (!ctx) {
699        mpp_err("memset_s failed\n");
700        return MPP_NOK;
701    }
702
703    MPP_RET ret = 0;
704    MppFrame frame = NULL;
705    MppMeta meta = NULL;
706    MppPacket packet = NULL;
707    MpiEncTestData *p = (MpiEncTestData *)ctx;
708    MppApi *mpi = p->mpi;
709    unsigned int eoi = 1;
710    unsigned int packet_num = 0;
711    MppBuffer cam_buf = NULL;
712    MppBufferInfo info;
713
714    errno_t eok = memset_s(&info, sizeof(MppBufferInfo), 0, sizeof(MppBufferInfo));
715    if (eok != EOK) {
716        mpp_err("memset_s failed\n");
717        return MPP_NOK;
718    }
719    info.type = MPP_BUFFER_TYPE_EXT_DMA;
720    info.fd = dma_fd;
721    info.size = p->frame_size & 0x07ffffff;
722    info.index = (p->frame_size & 0xf8000000) >> 0x1b;
723
724    ret = mpp_buffer_import(&cam_buf, &info);
725    if (ret != MPP_SUCCESS) {
726        mpp_err_f("mpp_buffer_import failed\n");
727        return MPP_NOK;
728    }
729
730    ret = mpp_frame_init(&frame);
731    if (ret) {
732        mpp_err_f("mpp_frame_init failed\n");
733        return MPP_NOK;
734    }
735
736    /* set frame size info */
737    test_mpp_frame_set_param(frame, p);
738
739    /* set frame data include fd */
740    mpp_frame_set_buffer(frame, cam_buf);
741
742    /* packet init */
743    mpp_packet_init_with_buffer(&packet, p->pkt_buf);
744    /* NOTE: It is important to clear output packet length!! */
745    mpp_packet_set_length(packet, 0);
746
747    meta = mpp_frame_get_meta(frame);
748    mpp_meta_set_packet(meta, KEY_OUTPUT_PACKET, packet);
749
750    /*
751     * NOTE: in non-block mode the frame can be resent.
752     * The default input timeout mode is block.
753     *
754     * User should release the input frame to meet the requirements of
755     * resource creator must be the resource destroyer.
756     */
757    ret = mpi->encode_put_frame(p->ctx, frame);
758    if (ret) {
759        mpp_err("mpp encode put frame failed\n");
760        mpp_frame_deinit(&frame);
761        if (cam_buf) {
762            mpp_buffer_put(cam_buf);
763        }
764        mpp_packet_deinit(&packet);
765        return ret;
766    }
767
768    mpp_frame_deinit(&frame);
769
770    packet_num = 0;
771
772    do {
773        ret = mpi->encode_get_packet(p->ctx, &packet);
774        if (ret) {
775            mpp_err("mpp encode get packet failed\n");
776            if (cam_buf) {
777                mpp_buffer_put(cam_buf);
778            }
779            mpp_packet_deinit(&packet);
780            return ret;
781        }
782
783        mpp_assert(packet);
784
785        if (packet) {
786            /* for low delay partition encoding */
787            if (mpp_packet_is_partition(packet)) {
788                eoi = mpp_packet_is_eoi(packet);
789            }
790
791            p->frame_count += eoi;
792            packet_num++;
793        }
794    } while (!eoi);
795
796    void *ptr = mpp_packet_get_pos(packet);
797    size_t len = mpp_packet_get_length(packet);
798
799    if (packet_num != 1) {
800        mpp_err("packet_num %u != 1\n");
801        ret = MPP_NOK;
802        if (cam_buf) {
803            mpp_buffer_put(cam_buf);
804        }
805        mpp_packet_deinit(&packet);
806        return ret;
807    }
808
809    if (*buf_size < len) {
810        mpp_err("mpi buffer size too small\n");
811        ret = MPP_NOK;
812        if (cam_buf) {
813            mpp_buffer_put(cam_buf);
814        }
815        mpp_packet_deinit(&packet);
816        return ret;
817    }
818
819    eok = memcpy_s(buf, len, ptr, len);
820    if (eok != EOK) {
821        mpp_err("memcpy_s failed\n");
822        return MPP_NOK;
823    }
824
825    *buf_size = len;
826
827    ret = MPP_OK;
828    if (cam_buf) {
829        mpp_buffer_put(cam_buf);
830    }
831
832    mpp_packet_deinit(&packet);
833    return ret;
834}
835
836void *hal_mpp_ctx_create(MpiEncTestArgs *args)
837{
838    MPP_RET ret = 0;
839    MpiEncTestData *p = NULL;
840    MppPollType timeout = MPP_POLL_BLOCK;
841
842    /* ��ʼ��һ�³��õIJ������ã�cmd�����ñȽ϶� */
843    ret = test_ctx_init(&p, args);
844    if (ret) {
845        mpp_err_f("test data init failed ret %d\n", ret);
846        mpp_err("%p mpi_enc_test failed ret %d\n", p->ctx, ret);
847        return NULL;
848    }
849
850    ret = mpp_buffer_group_get_internal(&p->buf_grp, MPP_BUFFER_TYPE_DRM);
851    if (ret) {
852        mpp_err_f("failed to get mpp buffer group ret %d\n", ret);
853        mpp_err("%p mpi_enc_test failed ret %d\n", p->ctx, ret);
854        return NULL;
855    }
856
857    /* pkt_buf�����Ա���?���Ǹ�packetʹ�õ�buffer */
858    ret = mpp_buffer_get(p->buf_grp, &p->pkt_buf, p->frame_size);
859    if (ret) {
860        mpp_err_f("failed to get buffer for output packet ret %d\n", ret);
861        mpp_err("%p mpi_enc_test failed ret %d\n", p->ctx, ret);
862        return NULL;
863    }
864
865    // encoder demo
866    ret = mpp_create(&p->ctx, &p->mpi);
867    if (ret) {
868        mpp_err("mpp_create failed ret %d\n", ret);
869        mpp_err("%p mpi_enc_test failed ret %d\n", p->ctx, ret);
870        return NULL;
871    }
872
873    mpp_log("%p mpi_enc_test encoder test start w %d h %d type %d\n", p->ctx, p->width, p->height, p->type);
874
875    ret = p->mpi->control(p->ctx, MPP_SET_OUTPUT_TIMEOUT, &timeout);
876    if (MPP_OK != ret) {
877        mpp_err("mpi control set output timeout %d ret %d\n", timeout, ret);
878        mpp_err("%p mpi_enc_test failed ret %d\n", p->ctx, ret);
879        return NULL;
880    }
881
882    ret = mpp_init(p->ctx, MPP_CTX_ENC, p->type);
883    if (ret) {
884        mpp_err("mpp_init failed ret %d\n", ret);
885        mpp_err("%p mpi_enc_test failed ret %d\n", p->ctx, ret);
886        return NULL;
887    }
888
889    ret = mpp_enc_cfg_init(&p->cfg);
890    if (ret) {
891        mpp_err_f("mpp_enc_cfg_init failed ret %d\n", ret);
892        mpp_err("%p mpi_enc_test failed ret %d\n", p->ctx, ret);
893        return NULL;
894    }
895
896    ret = test_mpp_enc_cfg_setup(p);
897    if (ret) {
898        mpp_err_f("test mpp setup failed ret %d\n", ret);
899        mpp_err("%p mpi_enc_test failed ret %d\n", p->ctx, ret);
900        return NULL;
901    }
902
903    return p;
904}
905
906void hal_mpp_ctx_delete(void *ctx)
907{
908    test_mpp_ctx_cleanup(ctx);
909}
910