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