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