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