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
mpi_enc_gen_ref_cfg(MppEncRefCfg ref,signed int gop_mode)30 static 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(<_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
mpi_enc_gen_smart_gop_ref_cfg(MppEncRefCfg ref,signed int gop_len,signed int vi_len)222 static 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(<_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 */
test_ctx_init(MpiEncTestData ** data,MpiEncTestArgs * cmd)289 static 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
test_ctx_deinit(MpiEncTestData ** data)346 static 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
test_mpp_enc_cfg_setup(MpiEncTestData * p)362 static 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
test_mpp_frame_set_param(MppFrame frame,MpiEncTestData * p)594 static 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
test_mpp_ctx_cleanup(MpiEncTestData * p)604 static 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
hal_mpp_get_sps(void * ctx,unsigned char * buf,size_t * buf_size)638 int 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
hal_mpp_encode(void * ctx,int dma_fd,unsigned char * buf,size_t * buf_size)696 int 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
hal_mpp_ctx_create(MpiEncTestArgs * args)836 void *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
hal_mpp_ctx_delete(void * ctx)906 void hal_mpp_ctx_delete(void *ctx)
907 {
908 test_mpp_ctx_cleanup(ctx);
909 }
910