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