├── CMakeLists.txt ├── README.md └── src ├── cam_mpp_opencv.cpp ├── cam_mpp_rga.cpp ├── cam_opencv.cpp ├── cam_v4l2_opencv.cpp ├── cam_v4l2_rga.cpp ├── file_mpp_rga.cpp ├── file_opencv.cpp └── resize_demo.cpp /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0.0) 2 | project(rga_demo) 3 | 4 | find_package(OpenCV 4 REQUIRED) 5 | include_directories(${OpenCV_INCLUDE_DIRS}) 6 | 7 | set( 8 | include_libs 9 | /home/linaro/librga/build/build_linux/install/include/ 10 | /home/linaro/mpp/osal/inc/ 11 | /home/linaro/mpp/utils/ 12 | /home/linaro/mpp/inc/ 13 | /home/linaro/mpp/mpp/base/inc/ 14 | /usr/include/rga/ 15 | # /usr/include/linux/ 16 | ) 17 | 18 | include_directories(${include_libs}) 19 | 20 | add_library(mpp_utils STATIC 21 | /home/linaro/mpp/utils/mpp_enc_roi_utils.c 22 | /home/linaro/mpp/utils/mpi_enc_utils.c 23 | /home/linaro/mpp/utils/mpi_dec_utils.c 24 | /home/linaro/mpp/utils/mpp_opt.c 25 | /home/linaro/mpp/utils/utils.c 26 | /home/linaro/mpp/utils/iniparser.c 27 | /home/linaro/mpp/utils/dictionary.c 28 | /home/linaro/mpp/utils/camera_source.c 29 | ) 30 | 31 | 32 | # 添加动态链接库 33 | set( 34 | dynamic_libs pthread 35 | /home/linaro/librga/build/build_linux/librga.so 36 | /home/linaro/mpp/build/linux/aarch64/mpp/librockchip_mpp.so 37 | /home/linaro/mpp/build/linux/aarch64/mpp/legacy/librockchip_vpu.so 38 | ) 39 | 40 | 41 | 42 | 43 | 44 | # cam_v4l2_opencv v4l2直接读摄像头,将读出的数据直接丢入opencv 45 | add_executable(cam_v4l2_opencv 46 | src/cam_v4l2_opencv.cpp 47 | ) 48 | target_link_libraries(cam_v4l2_opencv 49 | ${include_libs} 50 | ${dynamic_libs} 51 | ${OpenCV_LIBS} 52 | mpp_utils 53 | ) 54 | 55 | 56 | # cam_v4l2_rga v4l2直接读摄像头,将读出的数据直接丢入rga 57 | add_executable(cam_v4l2_rga 58 | src/cam_v4l2_rga.cpp 59 | ) 60 | target_link_libraries(cam_v4l2_rga 61 | ${include_libs} 62 | ${dynamic_libs} 63 | ${OpenCV_LIBS} 64 | mpp_utils 65 | ) 66 | 67 | 68 | # cam_opencv opencv直接读摄像头 69 | add_executable(cam_opencv 70 | src/cam_opencv.cpp 71 | ) 72 | target_link_libraries(cam_opencv 73 | ${include_libs} 74 | ${dynamic_libs} 75 | ${OpenCV_LIBS} 76 | mpp_utils 77 | ) 78 | 79 | 80 | # cam_mpp_opencv mpp读摄像头,将读出来的数据直接丢入opencv 81 | add_executable(cam_mpp_opencv 82 | src/cam_mpp_opencv.cpp 83 | ) 84 | target_link_libraries(cam_mpp_opencv 85 | ${include_libs} 86 | ${dynamic_libs} 87 | ${OpenCV_LIBS} 88 | mpp_utils 89 | ) 90 | 91 | 92 | # cam_mpp_rga mpp读摄像头,将读出来的数据直接丢入rga 93 | add_executable(cam_mpp_rga 94 | src/cam_mpp_rga.cpp 95 | ) 96 | target_link_libraries(cam_mpp_rga 97 | ${include_libs} 98 | ${dynamic_libs} 99 | ${OpenCV_LIBS} 100 | mpp_utils 101 | ) 102 | 103 | 104 | # file_opencv opencv直接读视频文件 105 | add_executable(file_opencv 106 | src/file_opencv.cpp 107 | ) 108 | target_link_libraries(file_opencv 109 | ${include_libs} 110 | ${dynamic_libs} 111 | ${OpenCV_LIBS} 112 | mpp_utils 113 | ) 114 | 115 | 116 | # file_mpp_rga mpp读视频文件,将读出来的数据直接丢入rga 117 | add_executable(file_mpp_rga 118 | src/file_mpp_rga.cpp 119 | ) 120 | target_link_libraries(file_mpp_rga 121 | ${include_libs} 122 | ${dynamic_libs} 123 | ${OpenCV_LIBS} 124 | mpp_utils 125 | ) 126 | 127 | 128 | # resize_demo 对比opencv与rga进行resize比较 129 | add_executable(resize_demo 130 | src/resize_demo.cpp 131 | ) 132 | target_link_libraries(resize_demo 133 | ${include_libs} 134 | ${dynamic_libs} 135 | ${OpenCV_LIBS} 136 | mpp_utils 137 | ) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### cam_v4l2_opencv: 2 | v4l2直接读摄像头,将读出的数据直接丢入opencv 3 | 4 | ### cam_v4l2_rga: 5 | v4l2直接读摄像头,将读出的数据直接丢入rga 6 | 7 | ### cam_opencv: 8 | opencv直接读摄像头 9 | 10 | ### cam_mpp_opencv: 11 | mpp读yuv文件,将读出来的数据直接丢入opencv 12 | 13 | ### cam_mpp_rga: 14 | mpp读摄像头,将读出来的数据直接丢入rga 15 | 16 | ### file_opencv: 17 | opencv直接读视频文件 18 | 19 | ### file_mpp_rga: 20 | mpp读视频文件,将读出来的数据直接丢入rga 21 | 22 | ### resize_demo: 23 | 对比opencv与rga进行resize比较 24 | -------------------------------------------------------------------------------- /src/cam_mpp_opencv.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Rockchip Electronics Co. LTD 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 18 | /* 19 | 输入是yuv时,要注意选择合适的运行命令,-t 7 -f 0 20 | 输入是摄像头时,没找到合适的转opencv的方式 21 | */ 22 | 23 | #include 24 | #include "rk_mpi.h" 25 | 26 | #include "mpp_env.h" 27 | #include "mpp_mem.h" 28 | #include "mpp_time.h" 29 | #include "mpp_debug.h" 30 | #include "mpp_common.h" 31 | 32 | #include "utils.h" 33 | #include "mpi_enc_utils.h" 34 | #include "camera_source.h" 35 | #include "mpp_enc_roi_utils.h" 36 | 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | 43 | 44 | typedef struct { 45 | // base flow context 46 | MppCtx ctx; 47 | MppApi *mpi; 48 | RK_S32 chn; 49 | 50 | // global flow control flag 51 | RK_U32 frm_eos; 52 | RK_U32 pkt_eos; 53 | RK_U32 frm_pkt_cnt; 54 | RK_S32 frame_num; 55 | RK_S32 frame_count; 56 | RK_U64 stream_size; 57 | /* end of encoding flag when set quit the loop */ 58 | volatile RK_U32 loop_end; 59 | 60 | // src and dst 61 | FILE *fp_input; 62 | FILE *fp_output; 63 | FILE *fp_verify; 64 | 65 | /* encoder config set */ 66 | MppEncCfg cfg; 67 | MppEncPrepCfg prep_cfg; 68 | MppEncRcCfg rc_cfg; 69 | MppEncCodecCfg codec_cfg; 70 | MppEncSliceSplit split_cfg; 71 | MppEncOSDPltCfg osd_plt_cfg; 72 | MppEncOSDPlt osd_plt; 73 | MppEncOSDData osd_data; 74 | RoiRegionCfg roi_region; 75 | MppEncROICfg roi_cfg; 76 | 77 | // input / output 78 | MppBufferGroup buf_grp; 79 | MppBuffer frm_buf; 80 | MppBuffer pkt_buf; 81 | MppBuffer md_info; 82 | MppEncSeiMode sei_mode; 83 | MppEncHeaderMode header_mode; 84 | 85 | // paramter for resource malloc 86 | RK_U32 width; 87 | RK_U32 height; 88 | RK_U32 hor_stride; 89 | RK_U32 ver_stride; 90 | MppFrameFormat fmt; 91 | MppCodingType type; 92 | RK_S32 loop_times; 93 | CamSource *cam_ctx; 94 | MppEncRoiCtx roi_ctx; 95 | 96 | // resources 97 | size_t header_size; 98 | size_t frame_size; 99 | size_t mdinfo_size; 100 | /* NOTE: packet buffer may overflow */ 101 | size_t packet_size; 102 | 103 | RK_U32 osd_enable; 104 | RK_U32 osd_mode; 105 | RK_U32 split_mode; 106 | RK_U32 split_arg; 107 | RK_U32 split_out; 108 | 109 | RK_U32 user_data_enable; 110 | RK_U32 roi_enable; 111 | 112 | // rate control runtime parameter 113 | RK_S32 fps_in_flex; 114 | RK_S32 fps_in_den; 115 | RK_S32 fps_in_num; 116 | RK_S32 fps_out_flex; 117 | RK_S32 fps_out_den; 118 | RK_S32 fps_out_num; 119 | RK_S32 bps; 120 | RK_S32 bps_max; 121 | RK_S32 bps_min; 122 | RK_S32 rc_mode; 123 | RK_S32 gop_mode; 124 | RK_S32 gop_len; 125 | RK_S32 vi_len; 126 | 127 | RK_S64 first_frm; 128 | RK_S64 first_pkt; 129 | } MpiEncTestData; 130 | 131 | /* For each instance thread return value */ 132 | typedef struct { 133 | float frame_rate; 134 | RK_U64 bit_rate; 135 | RK_S64 elapsed_time; 136 | RK_S32 frame_count; 137 | RK_S64 stream_size; 138 | RK_S64 delay; 139 | } MpiEncMultiCtxRet; 140 | 141 | typedef struct { 142 | MpiEncTestArgs *cmd; // pointer to global command line info 143 | const char *name; 144 | RK_S32 chn; 145 | 146 | pthread_t thd; // thread for for each instance 147 | MpiEncTestData ctx; // context of encoder 148 | MpiEncMultiCtxRet ret; // return of encoder 149 | } MpiEncMultiCtxInfo; 150 | 151 | 152 | MPP_RET test_ctx_init(MpiEncMultiCtxInfo *info) 153 | { 154 | MpiEncTestArgs *cmd = info->cmd; 155 | MpiEncTestData *p = &info->ctx; 156 | MPP_RET ret = MPP_OK; 157 | 158 | // get paramter from cmd 159 | p->width = cmd->width; 160 | p->height = cmd->height; 161 | p->hor_stride = (cmd->hor_stride) ? (cmd->hor_stride) : 162 | (MPP_ALIGN(cmd->width, 16)); 163 | p->ver_stride = (cmd->ver_stride) ? (cmd->ver_stride) : 164 | (MPP_ALIGN(cmd->height, 16)); 165 | p->fmt = cmd->format; 166 | p->type = cmd->type; 167 | p->bps = cmd->bps_target; 168 | p->bps_min = cmd->bps_min; 169 | p->bps_max = cmd->bps_max; 170 | p->rc_mode = cmd->rc_mode; 171 | p->frame_num = cmd->frame_num; 172 | if (cmd->type == MPP_VIDEO_CodingMJPEG && p->frame_num == 0) { 173 | mpp_log("jpege default encode only one frame. Use -n [num] for rc case\n"); 174 | p->frame_num = 1; 175 | } 176 | p->gop_mode = cmd->gop_mode; 177 | p->gop_len = cmd->gop_len; 178 | p->vi_len = cmd->vi_len; 179 | 180 | p->fps_in_flex = cmd->fps_in_flex; 181 | p->fps_in_den = cmd->fps_in_den; 182 | p->fps_in_num = cmd->fps_in_num; 183 | p->fps_out_flex = cmd->fps_out_flex; 184 | p->fps_out_den = cmd->fps_out_den; 185 | p->fps_out_num = cmd->fps_out_num; 186 | p->mdinfo_size = (MPP_VIDEO_CodingHEVC == cmd->type) ? 187 | (MPP_ALIGN(p->hor_stride, 32) >> 5) * 188 | (MPP_ALIGN(p->ver_stride, 32) >> 5) * 16 : 189 | (MPP_ALIGN(p->hor_stride, 64) >> 6) * 190 | (MPP_ALIGN(p->ver_stride, 16) >> 4) * 16; 191 | 192 | if (cmd->file_input) { 193 | if (!strncmp(cmd->file_input, "/dev/video", 10)) { 194 | mpp_log("open camera device"); 195 | p->cam_ctx = camera_source_init(cmd->file_input, 4, p->width, p->height, p->fmt); 196 | mpp_log("new framecap ok"); 197 | if (p->cam_ctx == NULL) 198 | mpp_err("open %s fail", cmd->file_input); 199 | } else { 200 | p->fp_input = fopen(cmd->file_input, "rb"); 201 | if (NULL == p->fp_input) { 202 | mpp_err("failed to open input file %s\n", cmd->file_input); 203 | mpp_err("create default yuv image for test\n"); 204 | } 205 | } 206 | } 207 | 208 | if (cmd->file_output) { 209 | p->fp_output = fopen(cmd->file_output, "w+b"); 210 | if (NULL == p->fp_output) { 211 | mpp_err("failed to open output file %s\n", cmd->file_output); 212 | ret = MPP_ERR_OPEN_FILE; 213 | } 214 | } 215 | 216 | if (cmd->file_slt) { 217 | p->fp_verify = fopen(cmd->file_slt, "wt"); 218 | if (!p->fp_verify) 219 | mpp_err("failed to open verify file %s\n", cmd->file_slt); 220 | } 221 | 222 | // update resource parameter 223 | switch (p->fmt & MPP_FRAME_FMT_MASK) { 224 | case MPP_FMT_YUV420SP: 225 | case MPP_FMT_YUV420P: { 226 | p->frame_size = MPP_ALIGN(p->hor_stride, 64) * MPP_ALIGN(p->ver_stride, 64) * 3 / 2; 227 | } break; 228 | 229 | case MPP_FMT_YUV422_YUYV : 230 | case MPP_FMT_YUV422_YVYU : 231 | case MPP_FMT_YUV422_UYVY : 232 | case MPP_FMT_YUV422_VYUY : 233 | case MPP_FMT_YUV422P : 234 | case MPP_FMT_YUV422SP : { 235 | p->frame_size = MPP_ALIGN(p->hor_stride, 64) * MPP_ALIGN(p->ver_stride, 64) * 2; 236 | } break; 237 | case MPP_FMT_RGB444 : 238 | case MPP_FMT_BGR444 : 239 | case MPP_FMT_RGB555 : 240 | case MPP_FMT_BGR555 : 241 | case MPP_FMT_RGB565 : 242 | case MPP_FMT_BGR565 : 243 | case MPP_FMT_RGB888 : 244 | case MPP_FMT_BGR888 : 245 | case MPP_FMT_RGB101010 : 246 | case MPP_FMT_BGR101010 : 247 | case MPP_FMT_ARGB8888 : 248 | case MPP_FMT_ABGR8888 : 249 | case MPP_FMT_BGRA8888 : 250 | case MPP_FMT_RGBA8888 : { 251 | p->frame_size = MPP_ALIGN(p->hor_stride, 64) * MPP_ALIGN(p->ver_stride, 64); 252 | } break; 253 | 254 | default: { 255 | p->frame_size = MPP_ALIGN(p->hor_stride, 64) * MPP_ALIGN(p->ver_stride, 64) * 4; 256 | } break; 257 | } 258 | 259 | if (MPP_FRAME_FMT_IS_FBC(p->fmt)) { 260 | if ((p->fmt & MPP_FRAME_FBC_MASK) == MPP_FRAME_FBC_AFBC_V1) 261 | p->header_size = MPP_ALIGN(MPP_ALIGN(p->width, 16) * MPP_ALIGN(p->height, 16) / 16, SZ_4K); 262 | else 263 | p->header_size = MPP_ALIGN(p->width, 16) * MPP_ALIGN(p->height, 16) / 16; 264 | } else { 265 | p->header_size = 0; 266 | } 267 | 268 | return ret; 269 | } 270 | 271 | MPP_RET test_ctx_deinit(MpiEncTestData *p) 272 | { 273 | if (p) { 274 | if (p->cam_ctx) { 275 | camera_source_deinit(p->cam_ctx); 276 | p->cam_ctx = NULL; 277 | } 278 | if (p->fp_input) { 279 | fclose(p->fp_input); 280 | p->fp_input = NULL; 281 | } 282 | if (p->fp_output) { 283 | fclose(p->fp_output); 284 | p->fp_output = NULL; 285 | } 286 | if (p->fp_verify) { 287 | fclose(p->fp_verify); 288 | p->fp_verify = NULL; 289 | } 290 | } 291 | return MPP_OK; 292 | } 293 | 294 | MPP_RET test_mpp_enc_cfg_setup(MpiEncMultiCtxInfo *info) 295 | { 296 | MpiEncTestArgs *cmd = info->cmd; 297 | MpiEncTestData *p = &info->ctx; 298 | MppApi *mpi = p->mpi; 299 | MppCtx ctx = p->ctx; 300 | MppEncCfg cfg = p->cfg; 301 | RK_U32 quiet = cmd->quiet; 302 | MPP_RET ret; 303 | RK_U32 rotation; 304 | RK_U32 mirroring; 305 | RK_U32 flip; 306 | 307 | /* setup default parameter */ 308 | if (p->fps_in_den == 0) 309 | p->fps_in_den = 1; 310 | if (p->fps_in_num == 0) 311 | p->fps_in_num = 30; 312 | if (p->fps_out_den == 0) 313 | p->fps_out_den = 1; 314 | if (p->fps_out_num == 0) 315 | p->fps_out_num = 30; 316 | 317 | if (!p->bps) 318 | p->bps = p->width * p->height / 8 * (p->fps_out_num / p->fps_out_den); 319 | 320 | mpp_enc_cfg_set_s32(cfg, "prep:width", p->width); 321 | mpp_enc_cfg_set_s32(cfg, "prep:height", p->height); 322 | mpp_enc_cfg_set_s32(cfg, "prep:hor_stride", p->hor_stride); 323 | mpp_enc_cfg_set_s32(cfg, "prep:ver_stride", p->ver_stride); 324 | mpp_enc_cfg_set_s32(cfg, "prep:format", p->fmt); 325 | 326 | mpp_enc_cfg_set_s32(cfg, "rc:mode", p->rc_mode); 327 | 328 | /* fix input / output frame rate */ 329 | mpp_enc_cfg_set_s32(cfg, "rc:fps_in_flex", p->fps_in_flex); 330 | mpp_enc_cfg_set_s32(cfg, "rc:fps_in_num", p->fps_in_num); 331 | mpp_enc_cfg_set_s32(cfg, "rc:fps_in_denorm", p->fps_in_den); 332 | mpp_enc_cfg_set_s32(cfg, "rc:fps_out_flex", p->fps_out_flex); 333 | mpp_enc_cfg_set_s32(cfg, "rc:fps_out_num", p->fps_out_num); 334 | mpp_enc_cfg_set_s32(cfg, "rc:fps_out_denorm", p->fps_out_den); 335 | mpp_enc_cfg_set_s32(cfg, "rc:gop", p->gop_len ? p->gop_len : p->fps_out_num * 2); 336 | 337 | /* drop frame or not when bitrate overflow */ 338 | mpp_enc_cfg_set_u32(cfg, "rc:drop_mode", MPP_ENC_RC_DROP_FRM_DISABLED); 339 | mpp_enc_cfg_set_u32(cfg, "rc:drop_thd", 20); /* 20% of max bps */ 340 | mpp_enc_cfg_set_u32(cfg, "rc:drop_gap", 1); /* Do not continuous drop frame */ 341 | 342 | /* setup bitrate for different rc_mode */ 343 | mpp_enc_cfg_set_s32(cfg, "rc:bps_target", p->bps); 344 | switch (p->rc_mode) { 345 | case MPP_ENC_RC_MODE_FIXQP : { 346 | /* do not setup bitrate on FIXQP mode */ 347 | } break; 348 | case MPP_ENC_RC_MODE_CBR : { 349 | /* CBR mode has narrow bound */ 350 | mpp_enc_cfg_set_s32(cfg, "rc:bps_max", p->bps_max ? p->bps_max : p->bps * 17 / 16); 351 | mpp_enc_cfg_set_s32(cfg, "rc:bps_min", p->bps_min ? p->bps_min : p->bps * 15 / 16); 352 | } break; 353 | case MPP_ENC_RC_MODE_VBR : 354 | case MPP_ENC_RC_MODE_AVBR : { 355 | /* VBR mode has wide bound */ 356 | mpp_enc_cfg_set_s32(cfg, "rc:bps_max", p->bps_max ? p->bps_max : p->bps * 17 / 16); 357 | mpp_enc_cfg_set_s32(cfg, "rc:bps_min", p->bps_min ? p->bps_min : p->bps * 1 / 16); 358 | } break; 359 | default : { 360 | /* default use CBR mode */ 361 | mpp_enc_cfg_set_s32(cfg, "rc:bps_max", p->bps_max ? p->bps_max : p->bps * 17 / 16); 362 | mpp_enc_cfg_set_s32(cfg, "rc:bps_min", p->bps_min ? p->bps_min : p->bps * 15 / 16); 363 | } break; 364 | } 365 | 366 | /* setup qp for different codec and rc_mode */ 367 | switch (p->type) { 368 | case MPP_VIDEO_CodingAVC : 369 | case MPP_VIDEO_CodingHEVC : { 370 | switch (p->rc_mode) { 371 | case MPP_ENC_RC_MODE_FIXQP : { 372 | RK_S32 fix_qp = cmd->qp_init; 373 | 374 | mpp_enc_cfg_set_s32(cfg, "rc:qp_init", fix_qp); 375 | mpp_enc_cfg_set_s32(cfg, "rc:qp_max", fix_qp); 376 | mpp_enc_cfg_set_s32(cfg, "rc:qp_min", fix_qp); 377 | mpp_enc_cfg_set_s32(cfg, "rc:qp_max_i", fix_qp); 378 | mpp_enc_cfg_set_s32(cfg, "rc:qp_min_i", fix_qp); 379 | mpp_enc_cfg_set_s32(cfg, "rc:qp_ip", 0); 380 | } break; 381 | case MPP_ENC_RC_MODE_CBR : 382 | case MPP_ENC_RC_MODE_VBR : 383 | case MPP_ENC_RC_MODE_AVBR : { 384 | mpp_enc_cfg_set_s32(cfg, "rc:qp_init", -1); 385 | mpp_enc_cfg_set_s32(cfg, "rc:qp_max", 51); 386 | mpp_enc_cfg_set_s32(cfg, "rc:qp_min", 10); 387 | mpp_enc_cfg_set_s32(cfg, "rc:qp_max_i", 51); 388 | mpp_enc_cfg_set_s32(cfg, "rc:qp_min_i", 10); 389 | mpp_enc_cfg_set_s32(cfg, "rc:qp_ip", 2); 390 | } break; 391 | default : { 392 | mpp_err_f("unsupport encoder rc mode %d\n", p->rc_mode); 393 | } break; 394 | } 395 | } break; 396 | case MPP_VIDEO_CodingVP8 : { 397 | /* vp8 only setup base qp range */ 398 | mpp_enc_cfg_set_s32(cfg, "rc:qp_init", 40); 399 | mpp_enc_cfg_set_s32(cfg, "rc:qp_max", 127); 400 | mpp_enc_cfg_set_s32(cfg, "rc:qp_min", 0); 401 | mpp_enc_cfg_set_s32(cfg, "rc:qp_max_i", 127); 402 | mpp_enc_cfg_set_s32(cfg, "rc:qp_min_i", 0); 403 | mpp_enc_cfg_set_s32(cfg, "rc:qp_ip", 6); 404 | } break; 405 | case MPP_VIDEO_CodingMJPEG : { 406 | /* jpeg use special codec config to control qtable */ 407 | mpp_enc_cfg_set_s32(cfg, "jpeg:q_factor", 80); 408 | mpp_enc_cfg_set_s32(cfg, "jpeg:qf_max", 99); 409 | mpp_enc_cfg_set_s32(cfg, "jpeg:qf_min", 1); 410 | } break; 411 | default : { 412 | } break; 413 | } 414 | 415 | /* setup codec */ 416 | mpp_enc_cfg_set_s32(cfg, "codec:type", p->type); 417 | switch (p->type) { 418 | case MPP_VIDEO_CodingAVC : { 419 | RK_U32 constraint_set; 420 | 421 | /* 422 | * H.264 profile_idc parameter 423 | * 66 - Baseline profile 424 | * 77 - Main profile 425 | * 100 - High profile 426 | */ 427 | mpp_enc_cfg_set_s32(cfg, "h264:profile", 100); 428 | /* 429 | * H.264 level_idc parameter 430 | * 10 / 11 / 12 / 13 - qcif@15fps / cif@7.5fps / cif@15fps / cif@30fps 431 | * 20 / 21 / 22 - cif@30fps / half-D1@@25fps / D1@12.5fps 432 | * 30 / 31 / 32 - D1@25fps / 720p@30fps / 720p@60fps 433 | * 40 / 41 / 42 - 1080p@30fps / 1080p@30fps / 1080p@60fps 434 | * 50 / 51 / 52 - 4K@30fps 435 | */ 436 | mpp_enc_cfg_set_s32(cfg, "h264:level", 40); 437 | mpp_enc_cfg_set_s32(cfg, "h264:cabac_en", 1); 438 | mpp_enc_cfg_set_s32(cfg, "h264:cabac_idc", 0); 439 | mpp_enc_cfg_set_s32(cfg, "h264:trans8x8", 1); 440 | 441 | mpp_env_get_u32("constraint_set", &constraint_set, 0); 442 | if (constraint_set & 0x3f0000) 443 | mpp_enc_cfg_set_s32(cfg, "h264:constraint_set", constraint_set); 444 | } break; 445 | case MPP_VIDEO_CodingHEVC : 446 | case MPP_VIDEO_CodingMJPEG : 447 | case MPP_VIDEO_CodingVP8 : { 448 | } break; 449 | default : { 450 | mpp_err_f("unsupport encoder coding type %d\n", p->type); 451 | } break; 452 | } 453 | 454 | p->split_mode = 0; 455 | p->split_arg = 0; 456 | p->split_out = 0; 457 | 458 | mpp_env_get_u32("split_mode", &p->split_mode, MPP_ENC_SPLIT_NONE); 459 | mpp_env_get_u32("split_arg", &p->split_arg, 0); 460 | mpp_env_get_u32("split_out", &p->split_out, 0); 461 | 462 | if (p->split_mode) { 463 | mpp_log_q(quiet, "%p split mode %d arg %d out %d\n", ctx, 464 | p->split_mode, p->split_arg, p->split_out); 465 | mpp_enc_cfg_set_s32(cfg, "split:mode", p->split_mode); 466 | mpp_enc_cfg_set_s32(cfg, "split:arg", p->split_arg); 467 | mpp_enc_cfg_set_s32(cfg, "split:out", p->split_out); 468 | } 469 | 470 | mpp_env_get_u32("mirroring", &mirroring, 0); 471 | mpp_env_get_u32("rotation", &rotation, 0); 472 | mpp_env_get_u32("flip", &flip, 0); 473 | 474 | mpp_enc_cfg_set_s32(cfg, "prep:mirroring", mirroring); 475 | mpp_enc_cfg_set_s32(cfg, "prep:rotation", rotation); 476 | mpp_enc_cfg_set_s32(cfg, "prep:flip", flip); 477 | 478 | ret = mpi->control(ctx, MPP_ENC_SET_CFG, cfg); 479 | if (ret) { 480 | mpp_err("mpi control enc set cfg failed ret %d\n", ret); 481 | // goto RET; 482 | } 483 | 484 | /* optional */ 485 | p->sei_mode = MPP_ENC_SEI_MODE_ONE_FRAME; 486 | ret = mpi->control(ctx, MPP_ENC_SET_SEI_CFG, &p->sei_mode); 487 | if (ret) { 488 | mpp_err("mpi control enc set sei cfg failed ret %d\n", ret); 489 | // goto RET; 490 | } 491 | // { 492 | // RK_U32 sei_mode; 493 | 494 | // mpp_env_get_u32("sei_mode", &sei_mode, MPP_ENC_SEI_MODE_ONE_FRAME); 495 | // p->sei_mode = sei_mode; 496 | // ret = mpi->control(ctx, MPP_ENC_SET_SEI_CFG, &p->sei_mode); 497 | // if (ret) { 498 | // mpp_err("mpi control enc set sei cfg failed ret %d\n", ret); 499 | // goto RET; 500 | // } 501 | // } 502 | 503 | if (p->type == MPP_VIDEO_CodingAVC || p->type == MPP_VIDEO_CodingHEVC) { 504 | p->header_mode = MPP_ENC_HEADER_MODE_EACH_IDR; 505 | ret = mpi->control(ctx, MPP_ENC_SET_HEADER_MODE, &p->header_mode); 506 | if (ret) { 507 | mpp_err("mpi control enc set header mode failed ret %d\n", ret); 508 | // goto RET; 509 | } 510 | } 511 | 512 | RK_U32 gop_mode = p->gop_mode; 513 | 514 | mpp_env_get_u32("gop_mode", &gop_mode, gop_mode); 515 | if (gop_mode) { 516 | MppEncRefCfg ref; 517 | 518 | mpp_enc_ref_cfg_init(&ref); 519 | 520 | if (p->gop_mode < 4) 521 | mpi_enc_gen_ref_cfg(ref, gop_mode); 522 | else 523 | mpi_enc_gen_smart_gop_ref_cfg(ref, p->gop_len, p->vi_len); 524 | 525 | ret = mpi->control(ctx, MPP_ENC_SET_REF_CFG, ref); 526 | if (ret) { 527 | mpp_err("mpi control enc set ref cfg failed ret %d\n", ret); 528 | // goto RET; 529 | } 530 | mpp_enc_ref_cfg_deinit(&ref); 531 | } 532 | 533 | /* setup test mode by env */ 534 | mpp_env_get_u32("osd_enable", &p->osd_enable, 0); 535 | mpp_env_get_u32("osd_mode", &p->osd_mode, MPP_ENC_OSD_PLT_TYPE_DEFAULT); 536 | mpp_env_get_u32("roi_enable", &p->roi_enable, 0); 537 | mpp_env_get_u32("user_data_enable", &p->user_data_enable, 0); 538 | 539 | if (p->roi_enable) { 540 | mpp_enc_roi_init(&p->roi_ctx, p->width, p->height, p->type, 4); 541 | mpp_assert(p->roi_ctx); 542 | } 543 | 544 | // RET: 545 | return ret; 546 | } 547 | 548 | void YUV420SP2Mat(MppFrame frame, cv::Mat &rgbImg ) { 549 | RK_U32 width = 0; 550 | RK_U32 height = 0; 551 | RK_U32 h_stride = 0; 552 | RK_U32 v_stride = 0; 553 | 554 | MppBuffer buffer = NULL; 555 | RK_U8 *base = NULL; 556 | 557 | width = mpp_frame_get_width(frame); 558 | height = mpp_frame_get_height(frame); 559 | h_stride = mpp_frame_get_hor_stride(frame); 560 | v_stride = mpp_frame_get_ver_stride(frame); 561 | buffer = mpp_frame_get_buffer(frame); 562 | 563 | base = (RK_U8 *)mpp_buffer_get_ptr(buffer); 564 | RK_U32 buf_size = mpp_frame_get_buf_size(frame); 565 | size_t base_length = mpp_buffer_get_size(buffer); 566 | if (base == NULL) { 567 | std::cout << "base = null" << std::endl; 568 | } 569 | RK_U32 i; 570 | RK_U8 *base_y = base; 571 | RK_U8 *base_c = base + h_stride * v_stride; 572 | 573 | cv::Mat yuvImg; 574 | yuvImg.create(480 * 3 / 2, 640, CV_8UC1); 575 | //转为YUV420p格式 576 | int idx = 0; 577 | for (i = 0; i < height; i++, base_y += h_stride) { 578 | memcpy(yuvImg.data + idx, base_y, width); 579 | idx += width; 580 | } 581 | for (i = 0; i < height / 2; i++, base_c += h_stride) { 582 | memcpy(yuvImg.data + idx, base_c, width); 583 | idx += width; 584 | } 585 | //这里的转码需要转为RGB 3通道, RGBA四通道则不能检测成功 586 | cv::cvtColor(yuvImg, rgbImg, cv::COLOR_YUV420sp2RGB); 587 | 588 | 589 | } 590 | 591 | MPP_RET test_mpp_run(MpiEncMultiCtxInfo *info) 592 | { 593 | int count = 0; 594 | MpiEncTestArgs *cmd = info->cmd; 595 | MpiEncTestData *p = &info->ctx; 596 | MppApi *mpi = p->mpi; 597 | MppCtx ctx = p->ctx; 598 | RK_U32 quiet = cmd->quiet; 599 | RK_S32 chn = info->chn; 600 | RK_U32 cap_num = 0; 601 | DataCrc checkcrc; 602 | MPP_RET ret = MPP_OK; 603 | 604 | memset(&checkcrc, 0, sizeof(checkcrc)); 605 | checkcrc.sum = mpp_malloc(RK_ULONG, 512); 606 | 607 | if (p->type == MPP_VIDEO_CodingAVC || p->type == MPP_VIDEO_CodingHEVC) { 608 | MppPacket packet = NULL; 609 | 610 | /* 611 | * Can use packet with normal malloc buffer as input not pkt_buf. 612 | * Please refer to vpu_api_legacy.cpp for normal buffer case. 613 | * Using pkt_buf buffer here is just for simplifing demo. 614 | */ 615 | mpp_packet_init_with_buffer(&packet, p->pkt_buf); 616 | /* NOTE: It is important to clear output packet length!! */ 617 | mpp_packet_set_length(packet, 0); 618 | 619 | ret = mpi->control(ctx, MPP_ENC_GET_HDR_SYNC, packet); 620 | if (ret) { 621 | mpp_err("mpi control enc get extra info failed\n"); 622 | // goto RET; 623 | } else { 624 | /* get and write sps/pps for H.264 */ 625 | 626 | void *ptr = mpp_packet_get_pos(packet); 627 | size_t len = mpp_packet_get_length(packet); 628 | 629 | if (p->fp_output) 630 | fwrite(ptr, 1, len, p->fp_output); 631 | } 632 | 633 | mpp_packet_deinit(&packet); 634 | } 635 | while (!p->pkt_eos) { 636 | MppMeta meta = NULL; 637 | MppFrame frame = NULL; 638 | MppPacket packet = NULL; 639 | //获得开辟的内存的首地址 640 | void *buf = mpp_buffer_get_ptr(p->frm_buf); 641 | 642 | RK_S32 cam_frm_idx = -1; 643 | MppBuffer cam_buf = NULL; 644 | RK_U32 eoi = 1; 645 | 646 | if (p->fp_input) { 647 | ret = read_image((RK_U8 *)buf, p->fp_input, p->width, p->height, 648 | p->hor_stride, p->ver_stride, p->fmt); 649 | if (ret == MPP_NOK || feof(p->fp_input)) { 650 | p->frm_eos = 1; 651 | 652 | if (p->frame_num < 0 || p->frame_count < p->frame_num) { 653 | clearerr(p->fp_input); 654 | rewind(p->fp_input); 655 | p->frm_eos = 0; 656 | mpp_log_q(quiet, "chn %d loop times %d\n", chn, ++p->loop_times); 657 | continue; 658 | } 659 | mpp_log_q(quiet, "chn %d found last frame. feof %d\n", chn, feof(p->fp_input)); 660 | } 661 | // } else if (ret == MPP_ERR_VALUE) 662 | // goto RET; 663 | } else { 664 | if (p->cam_ctx == NULL) { 665 | ret = fill_image((RK_U8 *)buf, p->width, p->height, p->hor_stride, 666 | p->ver_stride, p->fmt, p->frame_count); 667 | // if (ret) 668 | // goto RET; 669 | } else { 670 | cam_frm_idx = camera_source_get_frame(p->cam_ctx); 671 | mpp_assert(cam_frm_idx >= 0); 672 | 673 | /* skip unstable frames */ 674 | if (cap_num++ < 50) { 675 | camera_source_put_frame(p->cam_ctx, cam_frm_idx); 676 | continue; 677 | } 678 | 679 | cam_buf = camera_frame_to_buf(p->cam_ctx, cam_frm_idx); 680 | mpp_assert(cam_buf); 681 | } 682 | } 683 | 684 | ret = mpp_frame_init(&frame); //为什么初始化成功?? frame一直是null,在初始化的时候为空会报错?有关于null与空指针含义。 685 | if (ret) { 686 | mpp_err_f("mpp_frame_init failed\n"); 687 | // goto RET; 688 | } 689 | //设置编码图像的格式 690 | mpp_frame_set_width(frame, p->width); 691 | mpp_frame_set_height(frame, p->height); 692 | mpp_frame_set_hor_stride(frame, p->hor_stride); 693 | mpp_frame_set_ver_stride(frame, p->ver_stride); 694 | mpp_frame_set_fmt(frame, p->fmt); 695 | std::cout << "p->width : " << p->width << std::endl; 696 | std::cout << "p->height : " << p->height << std::endl; 697 | std::cout << "----mpp_frame_set_fmt---- : " << p->fmt << std::endl; 698 | mpp_frame_set_eos(frame, p->frm_eos); 699 | 700 | if (p->fp_input && feof(p->fp_input)){ 701 | std::cout << "-------------------" << std::endl; 702 | mpp_frame_set_buffer(frame, NULL); 703 | } else if (cam_buf){ 704 | mpp_frame_set_buffer(frame, cam_buf); 705 | } else{ 706 | mpp_frame_set_buffer(frame, p->frm_buf); 707 | 708 | std::cout << "---****正确*****------" << std::endl; 709 | cv::Mat rgbImg; 710 | YUV420SP2Mat(frame, rgbImg); 711 | cv::imwrite("./file.jpg", rgbImg); 712 | } 713 | meta = mpp_frame_get_meta(frame); 714 | mpp_packet_init_with_buffer(&packet, p->pkt_buf); 715 | /* NOTE: It is important to clear output packet length!! */ 716 | mpp_packet_set_length(packet, 0); 717 | mpp_meta_set_packet(meta, KEY_OUTPUT_PACKET, packet); 718 | mpp_meta_set_buffer(meta, KEY_MOTION_INFO, p->md_info); 719 | 720 | if (p->osd_enable || p->user_data_enable || p->roi_enable) { 721 | if (p->user_data_enable) { 722 | MppEncUserData user_data; 723 | const char *str = "this is user data\n"; 724 | 725 | if ((p->frame_count & 10) == 0) { 726 | user_data.pdata = (void *)str; 727 | user_data.len = strlen(str) + 1; 728 | mpp_meta_set_ptr(meta, KEY_USER_DATA, &user_data); 729 | } 730 | static RK_U8 uuid_debug_info[16] = { 731 | 0x57, 0x68, 0x97, 0x80, 0xe7, 0x0c, 0x4b, 0x65, 732 | 0xa9, 0x06, 0xae, 0x29, 0x94, 0x11, 0xcd, 0x9a 733 | }; 734 | 735 | MppEncUserDataSet data_group; 736 | MppEncUserDataFull datas[2]; 737 | const char *str1 = "this is user data 1\n"; 738 | const char *str2 = "this is user data 2\n"; 739 | data_group.count = 2; 740 | datas[0].len = strlen(str1) + 1; 741 | datas[0].pdata = (void *)str1; 742 | datas[0].uuid = uuid_debug_info; 743 | 744 | datas[1].len = strlen(str2) + 1; 745 | datas[1].pdata = (void *)str2; 746 | datas[1].uuid = uuid_debug_info; 747 | 748 | data_group.datas = datas; 749 | 750 | mpp_meta_set_ptr(meta, KEY_USER_DATAS, &data_group); 751 | } 752 | 753 | if (p->osd_enable) { 754 | /* gen and cfg osd plt */ 755 | mpi_enc_gen_osd_plt(&p->osd_plt, p->frame_count); 756 | 757 | p->osd_plt_cfg.change = MPP_ENC_OSD_PLT_CFG_CHANGE_ALL; 758 | p->osd_plt_cfg.type = MPP_ENC_OSD_PLT_TYPE_USERDEF; 759 | p->osd_plt_cfg.plt = &p->osd_plt; 760 | 761 | ret = mpi->control(ctx, MPP_ENC_SET_OSD_PLT_CFG, &p->osd_plt_cfg); 762 | if (ret) { 763 | mpp_err("mpi control enc set osd plt failed ret %d\n", ret); 764 | // goto RET; 765 | } 766 | 767 | /* gen and cfg osd plt */ 768 | mpi_enc_gen_osd_data(&p->osd_data, p->buf_grp, p->width, 769 | p->height, p->frame_count); 770 | mpp_meta_set_ptr(meta, KEY_OSD_DATA, (void*)&p->osd_data); 771 | } 772 | 773 | if (p->roi_enable) { 774 | RoiRegionCfg *region = &p->roi_region; 775 | 776 | /* calculated in pixels */ 777 | region->x = MPP_ALIGN(p->width / 8, 16); 778 | region->y = MPP_ALIGN(p->height / 8, 16); 779 | region->w = 128; 780 | region->h = 256; 781 | region->force_intra = 0; 782 | region->qp_mode = 1; 783 | region->qp_val = 24; 784 | 785 | mpp_enc_roi_add_region(p->roi_ctx, region); 786 | 787 | region->x = MPP_ALIGN(p->width / 2, 16); 788 | region->y = MPP_ALIGN(p->height / 4, 16); 789 | region->w = 256; 790 | region->h = 128; 791 | region->force_intra = 1; 792 | region->qp_mode = 1; 793 | region->qp_val = 10; 794 | 795 | mpp_enc_roi_add_region(p->roi_ctx, region); 796 | 797 | /* send roi info by metadata */ 798 | mpp_enc_roi_setup_meta(p->roi_ctx, meta); 799 | } 800 | } 801 | 802 | if (!p->first_frm) 803 | p->first_frm = mpp_time(); 804 | /* 805 | * NOTE: in non-block mode the frame can be resent. 806 | * The default input timeout mode is block. 807 | * 808 | * User should release the input frame to meet the requirements of 809 | * resource creator must be the resource destroyer. 810 | */ 811 | 812 | ret = mpi->encode_put_frame(ctx, frame); //输入图像进行编码 813 | 814 | mpp_frame_deinit(&frame); 815 | do { 816 | ret = mpi->encode_get_packet(ctx, &packet); //获得编码后的packet 817 | if (ret) { 818 | mpp_err("chn %d encode get packet failed\n", chn); 819 | // goto RET; 820 | } 821 | 822 | mpp_assert(packet); 823 | 824 | //获得编码后的数据长度和首地址,将其写入文件 825 | if (packet) { 826 | // write packet to file here 827 | void *ptr = mpp_packet_get_pos(packet); 828 | size_t len = mpp_packet_get_length(packet); 829 | char log_buf[256]; 830 | RK_S32 log_size = sizeof(log_buf) - 1; 831 | RK_S32 log_len = 0; 832 | 833 | if (!p->first_pkt) 834 | p->first_pkt = mpp_time(); 835 | 836 | p->pkt_eos = mpp_packet_get_eos(packet); 837 | 838 | if (p->fp_output){ 839 | fwrite(ptr, 1, len, p->fp_output); 840 | } 841 | if (p->fp_verify && !p->pkt_eos) { 842 | calc_data_crc((RK_U8 *)ptr, (RK_U32)len, &checkcrc); 843 | mpp_log("p->frame_count=%d, len=%d\n", p->frame_count, len); 844 | write_data_crc(p->fp_verify, &checkcrc); 845 | } 846 | 847 | log_len += snprintf(log_buf + log_len, log_size - log_len, 848 | "encoded frame %-4d", p->frame_count); 849 | 850 | /* for low delay partition encoding */ 851 | if (mpp_packet_is_partition(packet)) { 852 | eoi = mpp_packet_is_eoi(packet); 853 | 854 | log_len += snprintf(log_buf + log_len, log_size - log_len, 855 | " pkt %d", p->frm_pkt_cnt); 856 | p->frm_pkt_cnt = (eoi) ? (0) : (p->frm_pkt_cnt + 1); 857 | } 858 | 859 | log_len += snprintf(log_buf + log_len, log_size - log_len, 860 | " size %-7zu", len); 861 | 862 | if (mpp_packet_has_meta(packet)) { 863 | meta = mpp_packet_get_meta(packet); 864 | RK_S32 temporal_id = 0; 865 | RK_S32 lt_idx = -1; 866 | RK_S32 avg_qp = -1; 867 | 868 | if (MPP_OK == mpp_meta_get_s32(meta, KEY_TEMPORAL_ID, &temporal_id)) 869 | log_len += snprintf(log_buf + log_len, log_size - log_len, 870 | " tid %d", temporal_id); 871 | 872 | if (MPP_OK == mpp_meta_get_s32(meta, KEY_LONG_REF_IDX, <_idx)) 873 | log_len += snprintf(log_buf + log_len, log_size - log_len, 874 | " lt %d", lt_idx); 875 | 876 | if (MPP_OK == mpp_meta_get_s32(meta, KEY_ENC_AVERAGE_QP, &avg_qp)) 877 | log_len += snprintf(log_buf + log_len, log_size - log_len, 878 | " qp %d", avg_qp); 879 | } 880 | 881 | mpp_log_q(quiet, "chn %d %s\n", chn, log_buf); 882 | 883 | mpp_packet_deinit(&packet); 884 | fps_calc_inc(cmd->fps); 885 | 886 | p->stream_size += len; 887 | p->frame_count += eoi; 888 | 889 | if (p->pkt_eos) { 890 | mpp_log_q(quiet, "chn %d found last packet\n", chn); 891 | mpp_assert(p->frm_eos); 892 | } 893 | } 894 | } while (!eoi); 895 | 896 | if (cam_frm_idx >= 0) 897 | camera_source_put_frame(p->cam_ctx, cam_frm_idx); 898 | 899 | if (p->frame_num > 0 && p->frame_count >= p->frame_num) 900 | break; 901 | 902 | if (p->loop_end) 903 | break; 904 | 905 | if (p->frm_eos && p->pkt_eos) 906 | break; 907 | } 908 | // RET: 909 | // MPP_FREE(checkcrc.sum); 910 | 911 | return ret; 912 | } 913 | 914 | void *enc_test(void *arg) 915 | { 916 | MpiEncMultiCtxInfo *info = (MpiEncMultiCtxInfo *)arg; 917 | MpiEncTestArgs *cmd = info->cmd; 918 | MpiEncTestData *p = &info->ctx; 919 | MpiEncMultiCtxRet *enc_ret = &info->ret; 920 | MppPollType timeout = MPP_POLL_BLOCK; 921 | RK_U32 quiet = cmd->quiet; 922 | MPP_RET ret = MPP_OK; 923 | RK_S64 t_s = 0; 924 | RK_S64 t_e = 0; 925 | 926 | mpp_log_q(quiet, "%s start\n", info->name); 927 | 928 | ret = test_ctx_init(info); 929 | if (ret) { 930 | mpp_err_f("test data init failed ret %d\n", ret); 931 | goto MPP_TEST_OUT; 932 | } 933 | 934 | ret = mpp_buffer_group_get_internal(&p->buf_grp, MPP_BUFFER_TYPE_DRM); 935 | if (ret) { 936 | mpp_err_f("failed to get mpp buffer group ret %d\n", ret); 937 | goto MPP_TEST_OUT; 938 | } 939 | 940 | ret = mpp_buffer_get(p->buf_grp, &p->frm_buf, p->frame_size + p->header_size); 941 | if (ret) { 942 | mpp_err_f("failed to get buffer for input frame ret %d\n", ret); 943 | goto MPP_TEST_OUT; 944 | } 945 | 946 | ret = mpp_buffer_get(p->buf_grp, &p->pkt_buf, p->frame_size); 947 | if (ret) { 948 | mpp_err_f("failed to get buffer for output packet ret %d\n", ret); 949 | goto MPP_TEST_OUT; 950 | } 951 | 952 | ret = mpp_buffer_get(p->buf_grp, &p->md_info, p->mdinfo_size); 953 | if (ret) { 954 | mpp_err_f("failed to get buffer for motion info output packet ret %d\n", ret); 955 | goto MPP_TEST_OUT; 956 | } 957 | 958 | // encoder demo 959 | ret = mpp_create(&p->ctx, &p->mpi); 960 | if (ret) { 961 | mpp_err("mpp_create failed ret %d\n", ret); 962 | goto MPP_TEST_OUT; 963 | } 964 | 965 | mpp_log_q(quiet, "%p encoder test start w %d h %d type %d\n", 966 | p->ctx, p->width, p->height, p->type); 967 | 968 | ret = p->mpi->control(p->ctx, MPP_SET_OUTPUT_TIMEOUT, &timeout); 969 | if (MPP_OK != ret) { 970 | mpp_err("mpi control set output timeout %d ret %d\n", timeout, ret); 971 | goto MPP_TEST_OUT; 972 | } 973 | 974 | ret = mpp_init(p->ctx, MPP_CTX_ENC, p->type); 975 | if (ret) { 976 | mpp_err("mpp_init failed ret %d\n", ret); 977 | goto MPP_TEST_OUT; 978 | } 979 | 980 | ret = mpp_enc_cfg_init(&p->cfg); 981 | if (ret) { 982 | mpp_err_f("mpp_enc_cfg_init failed ret %d\n", ret); 983 | goto MPP_TEST_OUT; 984 | } 985 | 986 | ret = p->mpi->control(p->ctx, MPP_ENC_GET_CFG, p->cfg); 987 | if (ret) { 988 | mpp_err_f("get enc cfg failed ret %d\n", ret); 989 | goto MPP_TEST_OUT; 990 | } 991 | 992 | ret = test_mpp_enc_cfg_setup(info); 993 | if (ret) { 994 | mpp_err_f("test mpp setup failed ret %d\n", ret); 995 | goto MPP_TEST_OUT; 996 | } 997 | 998 | t_s = mpp_time(); 999 | ret = test_mpp_run(info); 1000 | t_e = mpp_time(); 1001 | if (ret) { 1002 | mpp_err_f("test mpp run failed ret %d\n", ret); 1003 | goto MPP_TEST_OUT; 1004 | } 1005 | 1006 | ret = p->mpi->reset(p->ctx); 1007 | if (ret) { 1008 | mpp_err("mpi->reset failed\n"); 1009 | goto MPP_TEST_OUT; 1010 | } 1011 | 1012 | enc_ret->elapsed_time = t_e - t_s; 1013 | enc_ret->frame_count = p->frame_count; 1014 | enc_ret->stream_size = p->stream_size; 1015 | enc_ret->frame_rate = (float)p->frame_count * 1000000 / enc_ret->elapsed_time; 1016 | enc_ret->bit_rate = (p->stream_size * 8 * (p->fps_out_num / p->fps_out_den)) / p->frame_count; 1017 | enc_ret->delay = p->first_pkt - p->first_frm; 1018 | 1019 | MPP_TEST_OUT: 1020 | if (p->ctx) { 1021 | mpp_destroy(p->ctx); 1022 | p->ctx = NULL; 1023 | } 1024 | 1025 | if (p->cfg) { 1026 | mpp_enc_cfg_deinit(p->cfg); 1027 | p->cfg = NULL; 1028 | } 1029 | 1030 | if (p->frm_buf) { 1031 | mpp_buffer_put(p->frm_buf); 1032 | p->frm_buf = NULL; 1033 | } 1034 | 1035 | if (p->pkt_buf) { 1036 | mpp_buffer_put(p->pkt_buf); 1037 | p->pkt_buf = NULL; 1038 | } 1039 | 1040 | if (p->md_info) { 1041 | mpp_buffer_put(p->md_info); 1042 | p->md_info = NULL; 1043 | } 1044 | 1045 | if (p->osd_data.buf) { 1046 | mpp_buffer_put(p->osd_data.buf); 1047 | p->osd_data.buf = NULL; 1048 | } 1049 | 1050 | if (p->buf_grp) { 1051 | mpp_buffer_group_put(p->buf_grp); 1052 | p->buf_grp = NULL; 1053 | } 1054 | 1055 | if (p->roi_ctx) { 1056 | mpp_enc_roi_deinit(p->roi_ctx); 1057 | p->roi_ctx = NULL; 1058 | } 1059 | 1060 | test_ctx_deinit(p); 1061 | 1062 | return NULL; 1063 | } 1064 | 1065 | int enc_test_multi(MpiEncTestArgs* cmd, const char *name) 1066 | { 1067 | MpiEncMultiCtxInfo *ctxs = NULL; 1068 | float total_rate = 0.0; 1069 | RK_S32 ret = MPP_NOK; 1070 | RK_S32 i = 0; 1071 | 1072 | ctxs = mpp_calloc(MpiEncMultiCtxInfo, cmd->nthreads); 1073 | if (NULL == ctxs) { 1074 | mpp_err("failed to alloc context for instances\n"); 1075 | return -1; 1076 | } 1077 | 1078 | for (i = 0; i < cmd->nthreads; i++) { 1079 | ctxs[i].cmd = cmd; 1080 | ctxs[i].name = name; 1081 | ctxs[i].chn = i; 1082 | 1083 | ret = pthread_create(&ctxs[i].thd, NULL, enc_test, &ctxs[i]); 1084 | if (ret) { 1085 | mpp_err("failed to create thread %d\n", i); 1086 | return ret; 1087 | } 1088 | } 1089 | 1090 | if (cmd->frame_num < 0) { 1091 | // wait for input then quit encoding 1092 | mpp_log("*******************************************\n"); 1093 | mpp_log("**** Press Enter to stop loop encoding ****\n"); 1094 | mpp_log("*******************************************\n"); 1095 | 1096 | getc(stdin); 1097 | for (i = 0; i < cmd->nthreads; i++) 1098 | ctxs[i].ctx.loop_end = 1; 1099 | } 1100 | 1101 | for (i = 0; i < cmd->nthreads; i++) 1102 | pthread_join(ctxs[i].thd, NULL); 1103 | 1104 | for (i = 0; i < cmd->nthreads; i++) { 1105 | MpiEncMultiCtxRet *enc_ret = &ctxs[i].ret; 1106 | 1107 | mpp_log("chn %d encode %d frames time %lld ms delay %3d ms fps %3.2f bps %lld\n", 1108 | i, enc_ret->frame_count, (RK_S64)(enc_ret->elapsed_time / 1000), 1109 | (RK_S32)(enc_ret->delay / 1000), enc_ret->frame_rate, enc_ret->bit_rate); 1110 | 1111 | total_rate += enc_ret->frame_rate; 1112 | } 1113 | 1114 | MPP_FREE(ctxs); 1115 | 1116 | total_rate /= cmd->nthreads; 1117 | mpp_log("%s average frame rate %.2f\n", name, total_rate); 1118 | 1119 | return ret; 1120 | } 1121 | 1122 | 1123 | 1124 | int main(int argc, char **argv) 1125 | { 1126 | RK_S32 ret = MPP_NOK; 1127 | MpiEncTestArgs* cmd = mpi_enc_test_cmd_get(); 1128 | 1129 | // parse the cmd option 1130 | ret = mpi_enc_test_cmd_update_by_args(cmd, argc, argv); 1131 | if (ret) 1132 | goto DONE; 1133 | 1134 | mpi_enc_test_cmd_show_opt(cmd); 1135 | 1136 | ret = enc_test_multi(cmd, argv[0]); 1137 | 1138 | DONE: 1139 | mpi_enc_test_cmd_put(cmd); 1140 | 1141 | return ret; 1142 | } 1143 | 1144 | -------------------------------------------------------------------------------- /src/cam_mpp_rga.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Rockchip Electronics Co. LTD 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include 18 | #include "rk_mpi.h" 19 | 20 | #include "mpp_env.h" 21 | #include "mpp_mem.h" 22 | #include "mpp_time.h" 23 | #include "mpp_debug.h" 24 | #include "mpp_common.h" 25 | 26 | #include "utils.h" 27 | #include "mpi_enc_utils.h" 28 | #include "camera_source.h" 29 | #include "mpp_enc_roi_utils.h" 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | #include "rga.h" 38 | #include "RgaUtils.h" 39 | #include "im2d.h" 40 | 41 | typedef struct { 42 | // base flow context 43 | MppCtx ctx; 44 | MppApi *mpi; 45 | RK_S32 chn; 46 | 47 | // global flow control flag 48 | RK_U32 frm_eos; 49 | RK_U32 pkt_eos; 50 | RK_U32 frm_pkt_cnt; 51 | RK_S32 frame_num; 52 | RK_S32 frame_count; 53 | RK_U64 stream_size; 54 | /* end of encoding flag when set quit the loop */ 55 | volatile RK_U32 loop_end; 56 | 57 | // src and dst 58 | FILE *fp_input; 59 | FILE *fp_output; 60 | FILE *fp_verify; 61 | 62 | /* encoder config set */ 63 | MppEncCfg cfg; 64 | MppEncPrepCfg prep_cfg; 65 | MppEncRcCfg rc_cfg; 66 | MppEncCodecCfg codec_cfg; 67 | MppEncSliceSplit split_cfg; 68 | MppEncOSDPltCfg osd_plt_cfg; 69 | MppEncOSDPlt osd_plt; 70 | MppEncOSDData osd_data; 71 | RoiRegionCfg roi_region; 72 | MppEncROICfg roi_cfg; 73 | 74 | // input / output 75 | MppBufferGroup buf_grp; 76 | MppBuffer frm_buf; 77 | MppBuffer pkt_buf; 78 | MppBuffer md_info; 79 | MppEncSeiMode sei_mode; 80 | MppEncHeaderMode header_mode; 81 | 82 | // paramter for resource malloc 83 | RK_U32 width; 84 | RK_U32 height; 85 | RK_U32 hor_stride; 86 | RK_U32 ver_stride; 87 | MppFrameFormat fmt; 88 | MppCodingType type; 89 | RK_S32 loop_times; 90 | CamSource *cam_ctx; 91 | MppEncRoiCtx roi_ctx; 92 | 93 | // resources 94 | size_t header_size; 95 | size_t frame_size; 96 | size_t mdinfo_size; 97 | /* NOTE: packet buffer may overflow */ 98 | size_t packet_size; 99 | 100 | RK_U32 osd_enable; 101 | RK_U32 osd_mode; 102 | RK_U32 split_mode; 103 | RK_U32 split_arg; 104 | RK_U32 split_out; 105 | 106 | RK_U32 user_data_enable; 107 | RK_U32 roi_enable; 108 | 109 | // rate control runtime parameter 110 | RK_S32 fps_in_flex; 111 | RK_S32 fps_in_den; 112 | RK_S32 fps_in_num; 113 | RK_S32 fps_out_flex; 114 | RK_S32 fps_out_den; 115 | RK_S32 fps_out_num; 116 | RK_S32 bps; 117 | RK_S32 bps_max; 118 | RK_S32 bps_min; 119 | RK_S32 rc_mode; 120 | RK_S32 gop_mode; 121 | RK_S32 gop_len; 122 | RK_S32 vi_len; 123 | 124 | RK_S64 first_frm; 125 | RK_S64 first_pkt; 126 | } MpiEncTestData; 127 | 128 | /* For each instance thread return value */ 129 | typedef struct { 130 | float frame_rate; 131 | RK_U64 bit_rate; 132 | RK_S64 elapsed_time; 133 | RK_S32 frame_count; 134 | RK_S64 stream_size; 135 | RK_S64 delay; 136 | } MpiEncMultiCtxRet; 137 | 138 | typedef struct { 139 | MpiEncTestArgs *cmd; // pointer to global command line info 140 | const char *name; 141 | RK_S32 chn; 142 | 143 | pthread_t thd; // thread for for each instance 144 | MpiEncTestData ctx; // context of encoder 145 | MpiEncMultiCtxRet ret; // return of encoder 146 | } MpiEncMultiCtxInfo; 147 | 148 | 149 | MPP_RET test_ctx_init(MpiEncMultiCtxInfo *info) 150 | { 151 | MpiEncTestArgs *cmd = info->cmd; 152 | MpiEncTestData *p = &info->ctx; 153 | MPP_RET ret = MPP_OK; 154 | 155 | // get paramter from cmd 156 | p->width = cmd->width; 157 | p->height = cmd->height; 158 | p->hor_stride = (cmd->hor_stride) ? (cmd->hor_stride) : 159 | (MPP_ALIGN(cmd->width, 16)); 160 | p->ver_stride = (cmd->ver_stride) ? (cmd->ver_stride) : 161 | (MPP_ALIGN(cmd->height, 16)); 162 | p->fmt = cmd->format; 163 | p->type = cmd->type; 164 | p->bps = cmd->bps_target; 165 | p->bps_min = cmd->bps_min; 166 | p->bps_max = cmd->bps_max; 167 | p->rc_mode = cmd->rc_mode; 168 | p->frame_num = cmd->frame_num; 169 | if (cmd->type == MPP_VIDEO_CodingMJPEG && p->frame_num == 0) { 170 | mpp_log("jpege default encode only one frame. Use -n [num] for rc case\n"); 171 | p->frame_num = 1; 172 | } 173 | p->gop_mode = cmd->gop_mode; 174 | p->gop_len = cmd->gop_len; 175 | p->vi_len = cmd->vi_len; 176 | 177 | p->fps_in_flex = cmd->fps_in_flex; 178 | p->fps_in_den = cmd->fps_in_den; 179 | p->fps_in_num = cmd->fps_in_num; 180 | p->fps_out_flex = cmd->fps_out_flex; 181 | p->fps_out_den = cmd->fps_out_den; 182 | p->fps_out_num = cmd->fps_out_num; 183 | p->mdinfo_size = (MPP_VIDEO_CodingHEVC == cmd->type) ? 184 | (MPP_ALIGN(p->hor_stride, 32) >> 5) * 185 | (MPP_ALIGN(p->ver_stride, 32) >> 5) * 16 : 186 | (MPP_ALIGN(p->hor_stride, 64) >> 6) * 187 | (MPP_ALIGN(p->ver_stride, 16) >> 4) * 16; 188 | 189 | if (cmd->file_input) { 190 | if (!strncmp(cmd->file_input, "/dev/video", 10)) { 191 | mpp_log("open camera device"); 192 | p->cam_ctx = camera_source_init(cmd->file_input, 4, p->width, p->height, p->fmt); 193 | mpp_log("new framecap ok"); 194 | if (p->cam_ctx == NULL) 195 | mpp_err("open %s fail", cmd->file_input); 196 | } else { 197 | p->fp_input = fopen(cmd->file_input, "rb"); 198 | if (NULL == p->fp_input) { 199 | mpp_err("failed to open input file %s\n", cmd->file_input); 200 | mpp_err("create default yuv image for test\n"); 201 | } 202 | } 203 | } 204 | 205 | if (cmd->file_output) { 206 | p->fp_output = fopen(cmd->file_output, "w+b"); 207 | if (NULL == p->fp_output) { 208 | mpp_err("failed to open output file %s\n", cmd->file_output); 209 | ret = MPP_ERR_OPEN_FILE; 210 | } 211 | } 212 | 213 | if (cmd->file_slt) { 214 | p->fp_verify = fopen(cmd->file_slt, "wt"); 215 | if (!p->fp_verify) 216 | mpp_err("failed to open verify file %s\n", cmd->file_slt); 217 | } 218 | 219 | // update resource parameter 220 | switch (p->fmt & MPP_FRAME_FMT_MASK) { 221 | case MPP_FMT_YUV420SP: 222 | case MPP_FMT_YUV420P: { 223 | p->frame_size = MPP_ALIGN(p->hor_stride, 64) * MPP_ALIGN(p->ver_stride, 64) * 3 / 2; 224 | } break; 225 | 226 | case MPP_FMT_YUV422_YUYV : 227 | case MPP_FMT_YUV422_YVYU : 228 | case MPP_FMT_YUV422_UYVY : 229 | case MPP_FMT_YUV422_VYUY : 230 | case MPP_FMT_YUV422P : 231 | case MPP_FMT_YUV422SP : { 232 | p->frame_size = MPP_ALIGN(p->hor_stride, 64) * MPP_ALIGN(p->ver_stride, 64) * 2; 233 | } break; 234 | case MPP_FMT_RGB444 : 235 | case MPP_FMT_BGR444 : 236 | case MPP_FMT_RGB555 : 237 | case MPP_FMT_BGR555 : 238 | case MPP_FMT_RGB565 : 239 | case MPP_FMT_BGR565 : 240 | case MPP_FMT_RGB888 : 241 | case MPP_FMT_BGR888 : 242 | case MPP_FMT_RGB101010 : 243 | case MPP_FMT_BGR101010 : 244 | case MPP_FMT_ARGB8888 : 245 | case MPP_FMT_ABGR8888 : 246 | case MPP_FMT_BGRA8888 : 247 | case MPP_FMT_RGBA8888 : { 248 | p->frame_size = MPP_ALIGN(p->hor_stride, 64) * MPP_ALIGN(p->ver_stride, 64); 249 | } break; 250 | 251 | default: { 252 | p->frame_size = MPP_ALIGN(p->hor_stride, 64) * MPP_ALIGN(p->ver_stride, 64) * 4; 253 | } break; 254 | } 255 | 256 | if (MPP_FRAME_FMT_IS_FBC(p->fmt)) { 257 | if ((p->fmt & MPP_FRAME_FBC_MASK) == MPP_FRAME_FBC_AFBC_V1) 258 | p->header_size = MPP_ALIGN(MPP_ALIGN(p->width, 16) * MPP_ALIGN(p->height, 16) / 16, SZ_4K); 259 | else 260 | p->header_size = MPP_ALIGN(p->width, 16) * MPP_ALIGN(p->height, 16) / 16; 261 | } else { 262 | p->header_size = 0; 263 | } 264 | 265 | return ret; 266 | } 267 | 268 | MPP_RET test_ctx_deinit(MpiEncTestData *p) 269 | { 270 | if (p) { 271 | if (p->cam_ctx) { 272 | camera_source_deinit(p->cam_ctx); 273 | p->cam_ctx = NULL; 274 | } 275 | if (p->fp_input) { 276 | fclose(p->fp_input); 277 | p->fp_input = NULL; 278 | } 279 | if (p->fp_output) { 280 | fclose(p->fp_output); 281 | p->fp_output = NULL; 282 | } 283 | if (p->fp_verify) { 284 | fclose(p->fp_verify); 285 | p->fp_verify = NULL; 286 | } 287 | } 288 | return MPP_OK; 289 | } 290 | 291 | MPP_RET test_mpp_enc_cfg_setup(MpiEncMultiCtxInfo *info) 292 | { 293 | MpiEncTestArgs *cmd = info->cmd; 294 | MpiEncTestData *p = &info->ctx; 295 | MppApi *mpi = p->mpi; 296 | MppCtx ctx = p->ctx; 297 | MppEncCfg cfg = p->cfg; 298 | RK_U32 quiet = cmd->quiet; 299 | MPP_RET ret; 300 | RK_U32 rotation; 301 | RK_U32 mirroring; 302 | RK_U32 flip; 303 | 304 | /* setup default parameter */ 305 | if (p->fps_in_den == 0) 306 | p->fps_in_den = 1; 307 | if (p->fps_in_num == 0) 308 | p->fps_in_num = 30; 309 | if (p->fps_out_den == 0) 310 | p->fps_out_den = 1; 311 | if (p->fps_out_num == 0) 312 | p->fps_out_num = 30; 313 | 314 | if (!p->bps) 315 | p->bps = p->width * p->height / 8 * (p->fps_out_num / p->fps_out_den); 316 | 317 | mpp_enc_cfg_set_s32(cfg, "prep:width", p->width); 318 | mpp_enc_cfg_set_s32(cfg, "prep:height", p->height); 319 | mpp_enc_cfg_set_s32(cfg, "prep:hor_stride", p->hor_stride); 320 | mpp_enc_cfg_set_s32(cfg, "prep:ver_stride", p->ver_stride); 321 | mpp_enc_cfg_set_s32(cfg, "prep:format", p->fmt); 322 | 323 | mpp_enc_cfg_set_s32(cfg, "rc:mode", p->rc_mode); 324 | 325 | /* fix input / output frame rate */ 326 | mpp_enc_cfg_set_s32(cfg, "rc:fps_in_flex", p->fps_in_flex); 327 | mpp_enc_cfg_set_s32(cfg, "rc:fps_in_num", p->fps_in_num); 328 | mpp_enc_cfg_set_s32(cfg, "rc:fps_in_denorm", p->fps_in_den); 329 | mpp_enc_cfg_set_s32(cfg, "rc:fps_out_flex", p->fps_out_flex); 330 | mpp_enc_cfg_set_s32(cfg, "rc:fps_out_num", p->fps_out_num); 331 | mpp_enc_cfg_set_s32(cfg, "rc:fps_out_denorm", p->fps_out_den); 332 | mpp_enc_cfg_set_s32(cfg, "rc:gop", p->gop_len ? p->gop_len : p->fps_out_num * 2); 333 | 334 | /* drop frame or not when bitrate overflow */ 335 | mpp_enc_cfg_set_u32(cfg, "rc:drop_mode", MPP_ENC_RC_DROP_FRM_DISABLED); 336 | mpp_enc_cfg_set_u32(cfg, "rc:drop_thd", 20); /* 20% of max bps */ 337 | mpp_enc_cfg_set_u32(cfg, "rc:drop_gap", 1); /* Do not continuous drop frame */ 338 | 339 | /* setup bitrate for different rc_mode */ 340 | mpp_enc_cfg_set_s32(cfg, "rc:bps_target", p->bps); 341 | switch (p->rc_mode) { 342 | case MPP_ENC_RC_MODE_FIXQP : { 343 | /* do not setup bitrate on FIXQP mode */ 344 | } break; 345 | case MPP_ENC_RC_MODE_CBR : { 346 | /* CBR mode has narrow bound */ 347 | mpp_enc_cfg_set_s32(cfg, "rc:bps_max", p->bps_max ? p->bps_max : p->bps * 17 / 16); 348 | mpp_enc_cfg_set_s32(cfg, "rc:bps_min", p->bps_min ? p->bps_min : p->bps * 15 / 16); 349 | } break; 350 | case MPP_ENC_RC_MODE_VBR : 351 | case MPP_ENC_RC_MODE_AVBR : { 352 | /* VBR mode has wide bound */ 353 | mpp_enc_cfg_set_s32(cfg, "rc:bps_max", p->bps_max ? p->bps_max : p->bps * 17 / 16); 354 | mpp_enc_cfg_set_s32(cfg, "rc:bps_min", p->bps_min ? p->bps_min : p->bps * 1 / 16); 355 | } break; 356 | default : { 357 | /* default use CBR mode */ 358 | mpp_enc_cfg_set_s32(cfg, "rc:bps_max", p->bps_max ? p->bps_max : p->bps * 17 / 16); 359 | mpp_enc_cfg_set_s32(cfg, "rc:bps_min", p->bps_min ? p->bps_min : p->bps * 15 / 16); 360 | } break; 361 | } 362 | 363 | /* setup qp for different codec and rc_mode */ 364 | switch (p->type) { 365 | case MPP_VIDEO_CodingAVC : 366 | case MPP_VIDEO_CodingHEVC : { 367 | switch (p->rc_mode) { 368 | case MPP_ENC_RC_MODE_FIXQP : { 369 | RK_S32 fix_qp = cmd->qp_init; 370 | 371 | mpp_enc_cfg_set_s32(cfg, "rc:qp_init", fix_qp); 372 | mpp_enc_cfg_set_s32(cfg, "rc:qp_max", fix_qp); 373 | mpp_enc_cfg_set_s32(cfg, "rc:qp_min", fix_qp); 374 | mpp_enc_cfg_set_s32(cfg, "rc:qp_max_i", fix_qp); 375 | mpp_enc_cfg_set_s32(cfg, "rc:qp_min_i", fix_qp); 376 | mpp_enc_cfg_set_s32(cfg, "rc:qp_ip", 0); 377 | } break; 378 | case MPP_ENC_RC_MODE_CBR : 379 | case MPP_ENC_RC_MODE_VBR : 380 | case MPP_ENC_RC_MODE_AVBR : { 381 | mpp_enc_cfg_set_s32(cfg, "rc:qp_init", -1); 382 | mpp_enc_cfg_set_s32(cfg, "rc:qp_max", 51); 383 | mpp_enc_cfg_set_s32(cfg, "rc:qp_min", 10); 384 | mpp_enc_cfg_set_s32(cfg, "rc:qp_max_i", 51); 385 | mpp_enc_cfg_set_s32(cfg, "rc:qp_min_i", 10); 386 | mpp_enc_cfg_set_s32(cfg, "rc:qp_ip", 2); 387 | } break; 388 | default : { 389 | mpp_err_f("unsupport encoder rc mode %d\n", p->rc_mode); 390 | } break; 391 | } 392 | } break; 393 | case MPP_VIDEO_CodingVP8 : { 394 | /* vp8 only setup base qp range */ 395 | mpp_enc_cfg_set_s32(cfg, "rc:qp_init", 40); 396 | mpp_enc_cfg_set_s32(cfg, "rc:qp_max", 127); 397 | mpp_enc_cfg_set_s32(cfg, "rc:qp_min", 0); 398 | mpp_enc_cfg_set_s32(cfg, "rc:qp_max_i", 127); 399 | mpp_enc_cfg_set_s32(cfg, "rc:qp_min_i", 0); 400 | mpp_enc_cfg_set_s32(cfg, "rc:qp_ip", 6); 401 | } break; 402 | case MPP_VIDEO_CodingMJPEG : { 403 | /* jpeg use special codec config to control qtable */ 404 | mpp_enc_cfg_set_s32(cfg, "jpeg:q_factor", 80); 405 | mpp_enc_cfg_set_s32(cfg, "jpeg:qf_max", 99); 406 | mpp_enc_cfg_set_s32(cfg, "jpeg:qf_min", 1); 407 | } break; 408 | default : { 409 | } break; 410 | } 411 | 412 | /* setup codec */ 413 | mpp_enc_cfg_set_s32(cfg, "codec:type", p->type); 414 | switch (p->type) { 415 | case MPP_VIDEO_CodingAVC : { 416 | RK_U32 constraint_set; 417 | 418 | /* 419 | * H.264 profile_idc parameter 420 | * 66 - Baseline profile 421 | * 77 - Main profile 422 | * 100 - High profile 423 | */ 424 | mpp_enc_cfg_set_s32(cfg, "h264:profile", 100); 425 | /* 426 | * H.264 level_idc parameter 427 | * 10 / 11 / 12 / 13 - qcif@15fps / cif@7.5fps / cif@15fps / cif@30fps 428 | * 20 / 21 / 22 - cif@30fps / half-D1@@25fps / D1@12.5fps 429 | * 30 / 31 / 32 - D1@25fps / 720p@30fps / 720p@60fps 430 | * 40 / 41 / 42 - 1080p@30fps / 1080p@30fps / 1080p@60fps 431 | * 50 / 51 / 52 - 4K@30fps 432 | */ 433 | mpp_enc_cfg_set_s32(cfg, "h264:level", 40); 434 | mpp_enc_cfg_set_s32(cfg, "h264:cabac_en", 1); 435 | mpp_enc_cfg_set_s32(cfg, "h264:cabac_idc", 0); 436 | mpp_enc_cfg_set_s32(cfg, "h264:trans8x8", 1); 437 | 438 | mpp_env_get_u32("constraint_set", &constraint_set, 0); 439 | if (constraint_set & 0x3f0000) 440 | mpp_enc_cfg_set_s32(cfg, "h264:constraint_set", constraint_set); 441 | } break; 442 | case MPP_VIDEO_CodingHEVC : 443 | case MPP_VIDEO_CodingMJPEG : 444 | case MPP_VIDEO_CodingVP8 : { 445 | } break; 446 | default : { 447 | mpp_err_f("unsupport encoder coding type %d\n", p->type); 448 | } break; 449 | } 450 | 451 | p->split_mode = 0; 452 | p->split_arg = 0; 453 | p->split_out = 0; 454 | 455 | mpp_env_get_u32("split_mode", &p->split_mode, MPP_ENC_SPLIT_NONE); 456 | mpp_env_get_u32("split_arg", &p->split_arg, 0); 457 | mpp_env_get_u32("split_out", &p->split_out, 0); 458 | 459 | if (p->split_mode) { 460 | mpp_log_q(quiet, "%p split mode %d arg %d out %d\n", ctx, 461 | p->split_mode, p->split_arg, p->split_out); 462 | mpp_enc_cfg_set_s32(cfg, "split:mode", p->split_mode); 463 | mpp_enc_cfg_set_s32(cfg, "split:arg", p->split_arg); 464 | mpp_enc_cfg_set_s32(cfg, "split:out", p->split_out); 465 | } 466 | 467 | mpp_env_get_u32("mirroring", &mirroring, 0); 468 | mpp_env_get_u32("rotation", &rotation, 0); 469 | mpp_env_get_u32("flip", &flip, 0); 470 | 471 | mpp_enc_cfg_set_s32(cfg, "prep:mirroring", mirroring); 472 | mpp_enc_cfg_set_s32(cfg, "prep:rotation", rotation); 473 | mpp_enc_cfg_set_s32(cfg, "prep:flip", flip); 474 | 475 | ret = mpi->control(ctx, MPP_ENC_SET_CFG, cfg); 476 | if (ret) { 477 | mpp_err("mpi control enc set cfg failed ret %d\n", ret); 478 | // goto RET; 479 | } 480 | 481 | /* optional */ 482 | p->sei_mode = MPP_ENC_SEI_MODE_ONE_FRAME; 483 | ret = mpi->control(ctx, MPP_ENC_SET_SEI_CFG, &p->sei_mode); 484 | if (ret) { 485 | mpp_err("mpi control enc set sei cfg failed ret %d\n", ret); 486 | // goto RET; 487 | } 488 | // { 489 | // RK_U32 sei_mode; 490 | 491 | // mpp_env_get_u32("sei_mode", &sei_mode, MPP_ENC_SEI_MODE_ONE_FRAME); 492 | // p->sei_mode = sei_mode; 493 | // ret = mpi->control(ctx, MPP_ENC_SET_SEI_CFG, &p->sei_mode); 494 | // if (ret) { 495 | // mpp_err("mpi control enc set sei cfg failed ret %d\n", ret); 496 | // goto RET; 497 | // } 498 | // } 499 | 500 | if (p->type == MPP_VIDEO_CodingAVC || p->type == MPP_VIDEO_CodingHEVC) { 501 | p->header_mode = MPP_ENC_HEADER_MODE_EACH_IDR; 502 | ret = mpi->control(ctx, MPP_ENC_SET_HEADER_MODE, &p->header_mode); 503 | if (ret) { 504 | mpp_err("mpi control enc set header mode failed ret %d\n", ret); 505 | // goto RET; 506 | } 507 | } 508 | 509 | RK_U32 gop_mode = p->gop_mode; 510 | 511 | mpp_env_get_u32("gop_mode", &gop_mode, gop_mode); 512 | if (gop_mode) { 513 | MppEncRefCfg ref; 514 | 515 | mpp_enc_ref_cfg_init(&ref); 516 | 517 | if (p->gop_mode < 4) 518 | mpi_enc_gen_ref_cfg(ref, gop_mode); 519 | else 520 | mpi_enc_gen_smart_gop_ref_cfg(ref, p->gop_len, p->vi_len); 521 | 522 | ret = mpi->control(ctx, MPP_ENC_SET_REF_CFG, ref); 523 | if (ret) { 524 | mpp_err("mpi control enc set ref cfg failed ret %d\n", ret); 525 | // goto RET; 526 | } 527 | mpp_enc_ref_cfg_deinit(&ref); 528 | } 529 | 530 | /* setup test mode by env */ 531 | mpp_env_get_u32("osd_enable", &p->osd_enable, 0); 532 | mpp_env_get_u32("osd_mode", &p->osd_mode, MPP_ENC_OSD_PLT_TYPE_DEFAULT); 533 | mpp_env_get_u32("roi_enable", &p->roi_enable, 0); 534 | mpp_env_get_u32("user_data_enable", &p->user_data_enable, 0); 535 | 536 | if (p->roi_enable) { 537 | mpp_enc_roi_init(&p->roi_ctx, p->width, p->height, p->type, 4); 538 | mpp_assert(p->roi_ctx); 539 | } 540 | 541 | // RET: 542 | return ret; 543 | } 544 | 545 | 546 | double what_time_is_it_now() 547 | { 548 | // 单位: ms 549 | struct timeval time; 550 | if (gettimeofday(&time,NULL)){ 551 | return 0; 552 | } 553 | return (double)time.tv_sec * 1000 + (double)time.tv_usec * .001; 554 | } 555 | 556 | MPP_RET test_mpp_run(MpiEncMultiCtxInfo *info) 557 | { 558 | MpiEncTestArgs *cmd = info->cmd; 559 | MpiEncTestData *p = &info->ctx; 560 | MppApi *mpi = p->mpi; 561 | MppCtx ctx = p->ctx; 562 | RK_U32 quiet = cmd->quiet; 563 | RK_S32 chn = info->chn; 564 | RK_U32 cap_num = 0; 565 | DataCrc checkcrc; 566 | MPP_RET ret = MPP_OK; 567 | 568 | memset(&checkcrc, 0, sizeof(checkcrc)); 569 | checkcrc.sum = mpp_malloc(RK_ULONG, 512); 570 | 571 | if (p->type == MPP_VIDEO_CodingAVC || p->type == MPP_VIDEO_CodingHEVC) { 572 | MppPacket packet = NULL; 573 | 574 | /* 575 | * Can use packet with normal malloc buffer as input not pkt_buf. 576 | * Please refer to vpu_api_legacy.cpp for normal buffer case. 577 | * Using pkt_buf buffer here is just for simplifing demo. 578 | */ 579 | mpp_packet_init_with_buffer(&packet, p->pkt_buf); 580 | /* NOTE: It is important to clear output packet length!! */ 581 | mpp_packet_set_length(packet, 0); 582 | 583 | ret = mpi->control(ctx, MPP_ENC_GET_HDR_SYNC, packet); 584 | if (ret) { 585 | mpp_err("mpi control enc get extra info failed\n"); 586 | // goto RET; 587 | } else { 588 | /* get and write sps/pps for H.264 */ 589 | 590 | void *ptr = mpp_packet_get_pos(packet); 591 | size_t len = mpp_packet_get_length(packet); 592 | 593 | if (p->fp_output) 594 | fwrite(ptr, 1, len, p->fp_output); 595 | } 596 | 597 | mpp_packet_deinit(&packet); 598 | } 599 | 600 | // 创建OpenCV窗口 601 | // cv::namedWindow("camera", cv::WINDOW_AUTOSIZE); 602 | // 初始化性能计算相关 603 | double end; 604 | double start; 605 | double fps; 606 | int count = 0; 607 | double sum = 0; 608 | 609 | // init rga context 610 | rga_buffer_t src_img; 611 | rga_buffer_t dst_img; 612 | rga_buffer_handle_t src_handle, dst_handle; 613 | // std::cout << "mpp_frame_set_eos : " << p->height << std::endl; 614 | 615 | memset(&src_img, 0, sizeof(src_img)); 616 | memset(&dst_img, 0, sizeof(dst_img)); 617 | // std::cout << "mpp_frame_set_eos : " << p->height << std::endl; 618 | 619 | int width = cmd->width; 620 | int height = cmd->height; 621 | void* resize_buf = nullptr; 622 | resize_buf = malloc(height * width * 3); 623 | // std::cout << "mpp_frame_set_eos : " << p->height << std::endl; 624 | 625 | char *src_buf, *dst_buf; 626 | int src_buf_size, dst_buf_size; 627 | int src_format = RK_FORMAT_YUYV_422; 628 | int dst_format = RK_FORMAT_BGR_888; 629 | RK_U8 *base = NULL; 630 | dst_buf = (char *)malloc(dst_buf_size); 631 | // std::cout << "mpp_frame_set_eos : " << p->height << std::endl; 632 | 633 | memset(dst_buf, 0x80, dst_buf_size); 634 | std::cout << "mpp_frame_set_eos : " << p->height << std::endl; 635 | 636 | src_buf_size = width * height * get_bpp_from_format(src_format); 637 | dst_buf_size = width * height * get_bpp_from_format(dst_format); 638 | 639 | 640 | while (!p->pkt_eos) { 641 | double ttt = what_time_is_it_now(); 642 | MppMeta meta = NULL; 643 | MppFrame frame = NULL; 644 | MppPacket packet = NULL; 645 | //获得开辟的内存的首地址 646 | void *buf = mpp_buffer_get_ptr(p->frm_buf); 647 | 648 | RK_S32 cam_frm_idx = -1; 649 | MppBuffer cam_buf = NULL; 650 | RK_U32 eoi = 1; 651 | 652 | if (p->fp_input) { 653 | ret = read_image((RK_U8 *)buf, p->fp_input, p->width, p->height, 654 | p->hor_stride, p->ver_stride, p->fmt); 655 | if (ret == MPP_NOK || feof(p->fp_input)) { 656 | p->frm_eos = 1; 657 | 658 | if (p->frame_num < 0 || p->frame_count < p->frame_num) { 659 | clearerr(p->fp_input); 660 | rewind(p->fp_input); 661 | p->frm_eos = 0; 662 | mpp_log_q(quiet, "chn %d loop times %d\n", chn, ++p->loop_times); 663 | continue; 664 | } 665 | mpp_log_q(quiet, "chn %d found last frame. feof %d\n", chn, feof(p->fp_input)); 666 | } 667 | // } else if (ret == MPP_ERR_VALUE) 668 | // goto RET; 669 | } else { 670 | if (p->cam_ctx == NULL) { 671 | ret = fill_image((RK_U8 *)buf, p->width, p->height, p->hor_stride, 672 | p->ver_stride, p->fmt, p->frame_count); 673 | // if (ret) 674 | // goto RET; 675 | } else { 676 | cam_frm_idx = camera_source_get_frame(p->cam_ctx); 677 | mpp_assert(cam_frm_idx >= 0); 678 | 679 | /* skip unstable frames */ 680 | if (cap_num++ < 50) { 681 | camera_source_put_frame(p->cam_ctx, cam_frm_idx); 682 | continue; 683 | } 684 | 685 | cam_buf = camera_frame_to_buf(p->cam_ctx, cam_frm_idx); 686 | mpp_assert(cam_buf); 687 | } 688 | } 689 | 690 | ret = mpp_frame_init(&frame); //为什么初始化成功?? frame一直是null,在初始化的时候为空会报错?有关于null与空指针含义。 691 | if (ret) { 692 | mpp_err_f("mpp_frame_init failed\n"); 693 | // goto RET; 694 | } 695 | //设置编码图像的格式 696 | mpp_frame_set_width(frame, p->width); 697 | mpp_frame_set_height(frame, p->height); 698 | mpp_frame_set_hor_stride(frame, p->hor_stride); 699 | mpp_frame_set_ver_stride(frame, p->ver_stride); 700 | mpp_frame_set_fmt(frame, p->fmt); 701 | std::cout << "p->width : " << p->width << std::endl; 702 | std::cout << "p->height : " << p->height << std::endl; 703 | std::cout << "----mpp_frame_set_fmt---- : " << p->fmt << std::endl; 704 | mpp_frame_set_eos(frame, p->frm_eos); 705 | 706 | 707 | if (p->fp_input && feof(p->fp_input)){ 708 | std::cout << "-------------------" << std::endl; 709 | mpp_frame_set_buffer(frame, NULL); 710 | } else if (cam_buf){ 711 | mpp_frame_set_buffer(frame, cam_buf); 712 | std::cout << "*******************" << std::endl; 713 | base = (RK_U8 *)mpp_buffer_get_ptr(cam_buf); 714 | size_t base_length = mpp_buffer_get_size(cam_buf); 715 | int fd = mpp_buffer_get_fd(cam_buf); 716 | src_handle = importbuffer_fd(fd, src_buf_size); 717 | dst_handle = importbuffer_virtualaddr(dst_buf, dst_buf_size); 718 | src_img = wrapbuffer_handle(src_handle, width, height, src_format); 719 | dst_img = wrapbuffer_handle(dst_handle, width, height, dst_format); 720 | double tt = what_time_is_it_now(); 721 | std::cout << "cost time ------ " << tt - ttt << std::endl; 722 | int rets; 723 | rets = imcheck(src_img, dst_img, {}, {}); 724 | rets = imcvtcolor(src_img, dst_img, src_format, dst_format); 725 | // cv::Mat col_img(cv::Size(width, height), CV_8UC3, dst_buf); 726 | // if (cv::waitKey(30) == 27) { 727 | // break; 728 | // } 729 | // cv::imshow("camera", col_img); 730 | } else{ 731 | mpp_frame_set_buffer(frame, p->frm_buf); 732 | std::cout << "---****正确*****------" << std::endl; 733 | // 可以换成上面的方式 一般来说 physical address > fd > virtual address 734 | RK_U8 *base = NULL; 735 | base = (RK_U8 *)mpp_buffer_get_ptr(p->frm_buf); 736 | src_img = wrapbuffer_virtualaddr((void*)base, width, height, RK_FORMAT_YCbCr_420_SP); 737 | dst_img = wrapbuffer_virtualaddr((void*)resize_buf, width, height, RK_FORMAT_BGR_888); 738 | int ret = imcheck(src_img, dst_img, {}, {}); 739 | ret = imcvtcolor(src_img, dst_img, RK_FORMAT_YCbCr_420_SP, RK_FORMAT_BGR_888); 740 | end = what_time_is_it_now(); 741 | double t_diff = end - start; 742 | sum += t_diff; 743 | fps = 1000.0 / t_diff; 744 | count++; 745 | std::cout << "Frame " << count << ", time: " << t_diff << " s, FPS: " << fps << std::endl; 746 | cv::Mat col_img(cv::Size(width, height), CV_8UC3, resize_buf); 747 | // if (cv::waitKey(30) == 27) { 748 | // break; 749 | // } 750 | // cv::imshow("camera", col_img); 751 | } 752 | 753 | meta = mpp_frame_get_meta(frame); 754 | mpp_packet_init_with_buffer(&packet, p->pkt_buf); 755 | /* NOTE: It is important to clear output packet length!! */ 756 | mpp_packet_set_length(packet, 0); 757 | mpp_meta_set_packet(meta, KEY_OUTPUT_PACKET, packet); 758 | mpp_meta_set_buffer(meta, KEY_MOTION_INFO, p->md_info); 759 | 760 | if (p->osd_enable || p->user_data_enable || p->roi_enable) { 761 | if (p->user_data_enable) { 762 | MppEncUserData user_data; 763 | const char *str = "this is user data\n"; 764 | 765 | if ((p->frame_count & 10) == 0) { 766 | user_data.pdata = (void *)str; 767 | user_data.len = strlen(str) + 1; 768 | mpp_meta_set_ptr(meta, KEY_USER_DATA, &user_data); 769 | } 770 | static RK_U8 uuid_debug_info[16] = { 771 | 0x57, 0x68, 0x97, 0x80, 0xe7, 0x0c, 0x4b, 0x65, 772 | 0xa9, 0x06, 0xae, 0x29, 0x94, 0x11, 0xcd, 0x9a 773 | }; 774 | 775 | MppEncUserDataSet data_group; 776 | MppEncUserDataFull datas[2]; 777 | const char *str1 = "this is user data 1\n"; 778 | const char *str2 = "this is user data 2\n"; 779 | data_group.count = 2; 780 | datas[0].len = strlen(str1) + 1; 781 | datas[0].pdata = (void *)str1; 782 | datas[0].uuid = uuid_debug_info; 783 | 784 | datas[1].len = strlen(str2) + 1; 785 | datas[1].pdata = (void *)str2; 786 | datas[1].uuid = uuid_debug_info; 787 | 788 | data_group.datas = datas; 789 | 790 | mpp_meta_set_ptr(meta, KEY_USER_DATAS, &data_group); 791 | } 792 | 793 | if (p->osd_enable) { 794 | /* gen and cfg osd plt */ 795 | mpi_enc_gen_osd_plt(&p->osd_plt, p->frame_count); 796 | 797 | p->osd_plt_cfg.change = MPP_ENC_OSD_PLT_CFG_CHANGE_ALL; 798 | p->osd_plt_cfg.type = MPP_ENC_OSD_PLT_TYPE_USERDEF; 799 | p->osd_plt_cfg.plt = &p->osd_plt; 800 | 801 | ret = mpi->control(ctx, MPP_ENC_SET_OSD_PLT_CFG, &p->osd_plt_cfg); 802 | if (ret) { 803 | mpp_err("mpi control enc set osd plt failed ret %d\n", ret); 804 | // goto RET; 805 | } 806 | 807 | /* gen and cfg osd plt */ 808 | mpi_enc_gen_osd_data(&p->osd_data, p->buf_grp, p->width, 809 | p->height, p->frame_count); 810 | mpp_meta_set_ptr(meta, KEY_OSD_DATA, (void*)&p->osd_data); 811 | } 812 | 813 | if (p->roi_enable) { 814 | RoiRegionCfg *region = &p->roi_region; 815 | 816 | /* calculated in pixels */ 817 | region->x = MPP_ALIGN(p->width / 8, 16); 818 | region->y = MPP_ALIGN(p->height / 8, 16); 819 | region->w = 128; 820 | region->h = 256; 821 | region->force_intra = 0; 822 | region->qp_mode = 1; 823 | region->qp_val = 24; 824 | 825 | mpp_enc_roi_add_region(p->roi_ctx, region); 826 | 827 | region->x = MPP_ALIGN(p->width / 2, 16); 828 | region->y = MPP_ALIGN(p->height / 4, 16); 829 | region->w = 256; 830 | region->h = 128; 831 | region->force_intra = 1; 832 | region->qp_mode = 1; 833 | region->qp_val = 10; 834 | 835 | mpp_enc_roi_add_region(p->roi_ctx, region); 836 | 837 | /* send roi info by metadata */ 838 | mpp_enc_roi_setup_meta(p->roi_ctx, meta); 839 | } 840 | } 841 | 842 | if (!p->first_frm) 843 | p->first_frm = mpp_time(); 844 | /* 845 | * NOTE: in non-block mode the frame can be resent. 846 | * The default input timeout mode is block. 847 | * 848 | * User should release the input frame to meet the requirements of 849 | * resource creator must be the resource destroyer. 850 | */ 851 | 852 | ret = mpi->encode_put_frame(ctx, frame); //输入图像进行编码 853 | 854 | 855 | // std::cout << "*******************" << std::endl; 856 | // MppBuffer buffer = mpp_frame_get_buffer(frame); 857 | // void *base = mpp_buffer_get_ptr(buffer); 858 | // src = wrapbuffer_virtualaddr(base, width, height, RK_FORMAT_YUYV_422); 859 | // dst = wrapbuffer_virtualaddr((void*)resize_buf, width, height, RK_FORMAT_BGR_888); 860 | // int ret = imcheck(src, dst, {}, {}); 861 | // ret = imcvtcolor(src, dst, RK_FORMAT_YUYV_422, RK_FORMAT_BGR_888); 862 | // end = what_time_is_it_now(); 863 | // double t_diff = end - start; 864 | // sum += t_diff; 865 | // fps = 1000.0 / t_diff; 866 | // count++; 867 | // std::cout << "Frame " << count << ", time: " << t_diff << " s, FPS: " << fps << std::endl; 868 | // cv::Mat col_img(cv::Size(width, height), CV_8UC3, resize_buf); 869 | // if (cv::waitKey(30) == 27) { 870 | // break; 871 | // } 872 | // cv::imshow("camera", col_img); 873 | 874 | 875 | 876 | mpp_frame_deinit(&frame); 877 | do { 878 | ret = mpi->encode_get_packet(ctx, &packet); //获得编码后的packet 879 | if (ret) { 880 | mpp_err("chn %d encode get packet failed\n", chn); 881 | // goto RET; 882 | } 883 | 884 | mpp_assert(packet); 885 | 886 | //获得编码后的数据长度和首地址,将其写入文件 887 | if (packet) { 888 | // write packet to file here 889 | void *ptr = mpp_packet_get_pos(packet); 890 | size_t len = mpp_packet_get_length(packet); 891 | char log_buf[256]; 892 | RK_S32 log_size = sizeof(log_buf) - 1; 893 | RK_S32 log_len = 0; 894 | 895 | if (!p->first_pkt) 896 | p->first_pkt = mpp_time(); 897 | 898 | p->pkt_eos = mpp_packet_get_eos(packet); 899 | 900 | if (p->fp_output){ 901 | fwrite(ptr, 1, len, p->fp_output); 902 | } 903 | if (p->fp_verify && !p->pkt_eos) { 904 | calc_data_crc((RK_U8 *)ptr, (RK_U32)len, &checkcrc); 905 | mpp_log("p->frame_count=%d, len=%d\n", p->frame_count, len); 906 | write_data_crc(p->fp_verify, &checkcrc); 907 | } 908 | 909 | log_len += snprintf(log_buf + log_len, log_size - log_len, 910 | "encoded frame %-4d", p->frame_count); 911 | 912 | /* for low delay partition encoding */ 913 | if (mpp_packet_is_partition(packet)) { 914 | eoi = mpp_packet_is_eoi(packet); 915 | 916 | log_len += snprintf(log_buf + log_len, log_size - log_len, 917 | " pkt %d", p->frm_pkt_cnt); 918 | p->frm_pkt_cnt = (eoi) ? (0) : (p->frm_pkt_cnt + 1); 919 | } 920 | 921 | log_len += snprintf(log_buf + log_len, log_size - log_len, 922 | " size %-7zu", len); 923 | 924 | if (mpp_packet_has_meta(packet)) { 925 | meta = mpp_packet_get_meta(packet); 926 | RK_S32 temporal_id = 0; 927 | RK_S32 lt_idx = -1; 928 | RK_S32 avg_qp = -1; 929 | 930 | if (MPP_OK == mpp_meta_get_s32(meta, KEY_TEMPORAL_ID, &temporal_id)) 931 | log_len += snprintf(log_buf + log_len, log_size - log_len, 932 | " tid %d", temporal_id); 933 | 934 | if (MPP_OK == mpp_meta_get_s32(meta, KEY_LONG_REF_IDX, <_idx)) 935 | log_len += snprintf(log_buf + log_len, log_size - log_len, 936 | " lt %d", lt_idx); 937 | 938 | if (MPP_OK == mpp_meta_get_s32(meta, KEY_ENC_AVERAGE_QP, &avg_qp)) 939 | log_len += snprintf(log_buf + log_len, log_size - log_len, 940 | " qp %d", avg_qp); 941 | } 942 | 943 | mpp_log_q(quiet, "chn %d %s\n", chn, log_buf); 944 | 945 | mpp_packet_deinit(&packet); 946 | fps_calc_inc(cmd->fps); 947 | 948 | p->stream_size += len; 949 | p->frame_count += eoi; 950 | 951 | if (p->pkt_eos) { 952 | mpp_log_q(quiet, "chn %d found last packet\n", chn); 953 | mpp_assert(p->frm_eos); 954 | } 955 | } 956 | } while (!eoi); 957 | 958 | if (cam_frm_idx >= 0) 959 | camera_source_put_frame(p->cam_ctx, cam_frm_idx); 960 | 961 | if (p->frame_num > 0 && p->frame_count >= p->frame_num) 962 | break; 963 | 964 | if (p->loop_end) 965 | break; 966 | 967 | if (p->frm_eos && p->pkt_eos) 968 | break; 969 | } 970 | if (src_handle) 971 | releasebuffer_handle(src_handle); 972 | if (dst_handle) 973 | releasebuffer_handle(dst_handle); 974 | if (src_buf) 975 | free(src_buf); 976 | if (dst_buf) 977 | free(dst_buf); 978 | if (resize_buf) 979 | free(resize_buf); 980 | // RET: 981 | // MPP_FREE(checkcrc.sum); 982 | 983 | return ret; 984 | } 985 | 986 | void *enc_test(void *arg) 987 | { 988 | MpiEncMultiCtxInfo *info = (MpiEncMultiCtxInfo *)arg; 989 | MpiEncTestArgs *cmd = info->cmd; 990 | MpiEncTestData *p = &info->ctx; 991 | MpiEncMultiCtxRet *enc_ret = &info->ret; 992 | MppPollType timeout = MPP_POLL_BLOCK; 993 | RK_U32 quiet = cmd->quiet; 994 | MPP_RET ret = MPP_OK; 995 | RK_S64 t_s = 0; 996 | RK_S64 t_e = 0; 997 | 998 | mpp_log_q(quiet, "%s start\n", info->name); 999 | 1000 | ret = test_ctx_init(info); 1001 | if (ret) { 1002 | mpp_err_f("test data init failed ret %d\n", ret); 1003 | goto MPP_TEST_OUT; 1004 | } 1005 | 1006 | ret = mpp_buffer_group_get_internal(&p->buf_grp, MPP_BUFFER_TYPE_DRM); 1007 | if (ret) { 1008 | mpp_err_f("failed to get mpp buffer group ret %d\n", ret); 1009 | goto MPP_TEST_OUT; 1010 | } 1011 | 1012 | ret = mpp_buffer_get(p->buf_grp, &p->frm_buf, p->frame_size + p->header_size); 1013 | if (ret) { 1014 | mpp_err_f("failed to get buffer for input frame ret %d\n", ret); 1015 | goto MPP_TEST_OUT; 1016 | } 1017 | 1018 | ret = mpp_buffer_get(p->buf_grp, &p->pkt_buf, p->frame_size); 1019 | if (ret) { 1020 | mpp_err_f("failed to get buffer for output packet ret %d\n", ret); 1021 | goto MPP_TEST_OUT; 1022 | } 1023 | 1024 | ret = mpp_buffer_get(p->buf_grp, &p->md_info, p->mdinfo_size); 1025 | if (ret) { 1026 | mpp_err_f("failed to get buffer for motion info output packet ret %d\n", ret); 1027 | goto MPP_TEST_OUT; 1028 | } 1029 | 1030 | // encoder demo 1031 | ret = mpp_create(&p->ctx, &p->mpi); 1032 | if (ret) { 1033 | mpp_err("mpp_create failed ret %d\n", ret); 1034 | goto MPP_TEST_OUT; 1035 | } 1036 | 1037 | mpp_log_q(quiet, "%p encoder test start w %d h %d type %d\n", 1038 | p->ctx, p->width, p->height, p->type); 1039 | 1040 | ret = p->mpi->control(p->ctx, MPP_SET_OUTPUT_TIMEOUT, &timeout); 1041 | if (MPP_OK != ret) { 1042 | mpp_err("mpi control set output timeout %d ret %d\n", timeout, ret); 1043 | goto MPP_TEST_OUT; 1044 | } 1045 | 1046 | ret = mpp_init(p->ctx, MPP_CTX_ENC, p->type); 1047 | if (ret) { 1048 | mpp_err("mpp_init failed ret %d\n", ret); 1049 | goto MPP_TEST_OUT; 1050 | } 1051 | 1052 | ret = mpp_enc_cfg_init(&p->cfg); 1053 | if (ret) { 1054 | mpp_err_f("mpp_enc_cfg_init failed ret %d\n", ret); 1055 | goto MPP_TEST_OUT; 1056 | } 1057 | 1058 | ret = p->mpi->control(p->ctx, MPP_ENC_GET_CFG, p->cfg); 1059 | if (ret) { 1060 | mpp_err_f("get enc cfg failed ret %d\n", ret); 1061 | goto MPP_TEST_OUT; 1062 | } 1063 | 1064 | ret = test_mpp_enc_cfg_setup(info); 1065 | if (ret) { 1066 | mpp_err_f("test mpp setup failed ret %d\n", ret); 1067 | goto MPP_TEST_OUT; 1068 | } 1069 | 1070 | t_s = mpp_time(); 1071 | ret = test_mpp_run(info); 1072 | t_e = mpp_time(); 1073 | if (ret) { 1074 | mpp_err_f("test mpp run failed ret %d\n", ret); 1075 | goto MPP_TEST_OUT; 1076 | } 1077 | 1078 | ret = p->mpi->reset(p->ctx); 1079 | if (ret) { 1080 | mpp_err("mpi->reset failed\n"); 1081 | goto MPP_TEST_OUT; 1082 | } 1083 | 1084 | enc_ret->elapsed_time = t_e - t_s; 1085 | enc_ret->frame_count = p->frame_count; 1086 | enc_ret->stream_size = p->stream_size; 1087 | enc_ret->frame_rate = (float)p->frame_count * 1000000 / enc_ret->elapsed_time; 1088 | enc_ret->bit_rate = (p->stream_size * 8 * (p->fps_out_num / p->fps_out_den)) / p->frame_count; 1089 | enc_ret->delay = p->first_pkt - p->first_frm; 1090 | 1091 | MPP_TEST_OUT: 1092 | if (p->ctx) { 1093 | mpp_destroy(p->ctx); 1094 | p->ctx = NULL; 1095 | } 1096 | 1097 | if (p->cfg) { 1098 | mpp_enc_cfg_deinit(p->cfg); 1099 | p->cfg = NULL; 1100 | } 1101 | 1102 | if (p->frm_buf) { 1103 | mpp_buffer_put(p->frm_buf); 1104 | p->frm_buf = NULL; 1105 | } 1106 | 1107 | if (p->pkt_buf) { 1108 | mpp_buffer_put(p->pkt_buf); 1109 | p->pkt_buf = NULL; 1110 | } 1111 | 1112 | if (p->md_info) { 1113 | mpp_buffer_put(p->md_info); 1114 | p->md_info = NULL; 1115 | } 1116 | 1117 | if (p->osd_data.buf) { 1118 | mpp_buffer_put(p->osd_data.buf); 1119 | p->osd_data.buf = NULL; 1120 | } 1121 | 1122 | if (p->buf_grp) { 1123 | mpp_buffer_group_put(p->buf_grp); 1124 | p->buf_grp = NULL; 1125 | } 1126 | 1127 | if (p->roi_ctx) { 1128 | mpp_enc_roi_deinit(p->roi_ctx); 1129 | p->roi_ctx = NULL; 1130 | } 1131 | 1132 | test_ctx_deinit(p); 1133 | 1134 | return NULL; 1135 | } 1136 | 1137 | int enc_test_multi(MpiEncTestArgs* cmd, const char *name) 1138 | { 1139 | MpiEncMultiCtxInfo *ctxs = NULL; 1140 | float total_rate = 0.0; 1141 | RK_S32 ret = MPP_NOK; 1142 | RK_S32 i = 0; 1143 | 1144 | ctxs = mpp_calloc(MpiEncMultiCtxInfo, cmd->nthreads); 1145 | if (NULL == ctxs) { 1146 | mpp_err("failed to alloc context for instances\n"); 1147 | return -1; 1148 | } 1149 | 1150 | for (i = 0; i < cmd->nthreads; i++) { 1151 | ctxs[i].cmd = cmd; 1152 | ctxs[i].name = name; 1153 | ctxs[i].chn = i; 1154 | 1155 | ret = pthread_create(&ctxs[i].thd, NULL, enc_test, &ctxs[i]); 1156 | if (ret) { 1157 | mpp_err("failed to create thread %d\n", i); 1158 | return ret; 1159 | } 1160 | } 1161 | 1162 | if (cmd->frame_num < 0) { 1163 | // wait for input then quit encoding 1164 | mpp_log("*******************************************\n"); 1165 | mpp_log("**** Press Enter to stop loop encoding ****\n"); 1166 | mpp_log("*******************************************\n"); 1167 | 1168 | getc(stdin); 1169 | for (i = 0; i < cmd->nthreads; i++) 1170 | ctxs[i].ctx.loop_end = 1; 1171 | } 1172 | 1173 | for (i = 0; i < cmd->nthreads; i++) 1174 | pthread_join(ctxs[i].thd, NULL); 1175 | 1176 | for (i = 0; i < cmd->nthreads; i++) { 1177 | MpiEncMultiCtxRet *enc_ret = &ctxs[i].ret; 1178 | 1179 | mpp_log("chn %d encode %d frames time %lld ms delay %3d ms fps %3.2f bps %lld\n", 1180 | i, enc_ret->frame_count, (RK_S64)(enc_ret->elapsed_time / 1000), 1181 | (RK_S32)(enc_ret->delay / 1000), enc_ret->frame_rate, enc_ret->bit_rate); 1182 | 1183 | total_rate += enc_ret->frame_rate; 1184 | } 1185 | 1186 | MPP_FREE(ctxs); 1187 | 1188 | total_rate /= cmd->nthreads; 1189 | mpp_log("%s average frame rate %.2f\n", name, total_rate); 1190 | 1191 | return ret; 1192 | } 1193 | 1194 | 1195 | 1196 | int main(int argc, char **argv) 1197 | { 1198 | RK_S32 ret = MPP_NOK; 1199 | MpiEncTestArgs* cmd = mpi_enc_test_cmd_get(); 1200 | 1201 | // parse the cmd option 1202 | ret = mpi_enc_test_cmd_update_by_args(cmd, argc, argv); 1203 | if (ret) 1204 | goto DONE; 1205 | 1206 | mpi_enc_test_cmd_show_opt(cmd); 1207 | 1208 | ret = enc_test_multi(cmd, argv[0]); 1209 | 1210 | DONE: 1211 | mpi_enc_test_cmd_put(cmd); 1212 | 1213 | return ret; 1214 | } 1215 | 1216 | -------------------------------------------------------------------------------- /src/cam_opencv.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace cv; 4 | int main() 5 | { 6 | cv::VideoCapture cap; 7 | 8 | // 读摄像头的mjpeg数据 9 | // cap.set(cv::CAP_PROP_FOURCC, cv::VideoWriter::fourcc('M', 'J', 'P', 'G')); 10 | // cap.set(cv::CAP_PROP_CONVERT_RGB, false); 11 | 12 | // 读摄像头的yuv数据 13 | cap.set(cv::CAP_PROP_FORMAT, CV_8UC1); 14 | cap.set(cv::CAP_PROP_CONVERT_RGB, false); 15 | if (!cap.open(0)) { 16 | std::cerr << "Failed to open camera." << std::endl; 17 | return -1; 18 | } 19 | 20 | cv::Mat frame; 21 | double fps; 22 | double t = 0; 23 | double t_start = cv::getTickCount(); // 获取起始时间戳 24 | int count = 0; 25 | 26 | while (true) { 27 | cap >> frame; // 读取一帧图像 28 | if (frame.empty()) { 29 | break; 30 | } 31 | 32 | double t_end = cv::getTickCount(); // 获取结束时间戳 33 | double t_diff = (t_end - t_start) / cv::getTickFrequency(); // 计算时间差 34 | fps = 1.0 / t_diff; // 计算帧率 35 | 36 | t += t_diff; 37 | count++; 38 | 39 | std::cout << "Frame " << count << ", time: " << t_diff << " s, FPS: " << fps << std::endl; 40 | 41 | t_start = t_end; 42 | } 43 | 44 | double average_time = t / count; 45 | std::cout << "Average time per frame: " << average_time << " s" << std::endl; 46 | 47 | cap.release(); 48 | cv::destroyAllWindows(); 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /src/cam_v4l2_opencv.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | 14 | #define CAM_DEVICE "/dev/video0" // 摄像头设备文件路径 15 | #define IMG_WIDTH 640 // 图像宽度 16 | #define IMG_HEIGHT 480 // 图像高度 17 | 18 | double what_time_is_it_now() 19 | { 20 | // 单位: ms 21 | struct timeval time; 22 | if (gettimeofday(&time,NULL)){ 23 | return 0; 24 | } 25 | return (double)time.tv_sec * 1000 + (double)time.tv_usec * .001; 26 | } 27 | 28 | 29 | int main() { 30 | // 打开摄像头设备 31 | int fd = open(CAM_DEVICE, O_RDWR); 32 | if (fd == -1) { 33 | perror("Error: failed to open camera."); 34 | return -1; 35 | } 36 | 37 | // 设置视频格式 38 | struct v4l2_format fmt; 39 | memset(&fmt, 0, sizeof(fmt)); 40 | fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 41 | fmt.fmt.pix.width = IMG_WIDTH; 42 | fmt.fmt.pix.height = IMG_HEIGHT; 43 | fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; 44 | if (ioctl(fd, VIDIOC_S_FMT, &fmt) == -1) { 45 | perror("Error: failed to set video format."); 46 | return -1; 47 | } 48 | 49 | // 申请缓冲区 50 | struct v4l2_requestbuffers req; 51 | memset(&req, 0, sizeof(req)); 52 | req.count = 1; 53 | req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 54 | req.memory = V4L2_MEMORY_MMAP; 55 | if (ioctl(fd, VIDIOC_REQBUFS, &req) == -1) { 56 | perror("Error: failed to request buffer."); 57 | return -1; 58 | } 59 | 60 | // 映射缓冲区 61 | struct v4l2_buffer buf; 62 | memset(&buf, 0, sizeof(buf)); 63 | buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 64 | buf.memory = V4L2_MEMORY_MMAP; 65 | buf.index = 0; 66 | if (ioctl(fd, VIDIOC_QUERYBUF, &buf) == -1) { 67 | perror("Error: failed to query buffer."); 68 | return -1; 69 | } 70 | void *buf_start = mmap(NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.offset); 71 | if (buf_start == MAP_FAILED) { 72 | perror("Error: failed to mmap buffer."); 73 | return -1; 74 | } 75 | 76 | // 开始捕获图像 77 | if (ioctl(fd, VIDIOC_STREAMON, &buf.type) == -1) { 78 | perror("Error: failed to start stream."); 79 | return -1; 80 | } 81 | 82 | // // 创建OpenCV窗口 83 | // cv::namedWindow("camera", cv::WINDOW_AUTOSIZE); 84 | 85 | double end; 86 | double start; 87 | double fps; 88 | int count = 0; 89 | double sum = 0; 90 | // 读取摄像头数据并处理 91 | while (true) { 92 | printf("---------------------------\n"); 93 | start = what_time_is_it_now(); 94 | // 读取图像数据 95 | if (ioctl(fd, VIDIOC_QBUF, &buf) == -1) { 96 | perror("Error: failed to queue buffer."); 97 | return -1; 98 | } 99 | if (ioctl(fd, VIDIOC_DQBUF, &buf) == -1) { 100 | perror("Error: failed to dequeue buffer."); 101 | return -1; 102 | } 103 | 104 | // 将YUYV格式转换为BGR格式 105 | cv::Mat img(IMG_HEIGHT, IMG_WIDTH, CV_8UC2, buf_start); 106 | cv::cvtColor(img, img, cv::COLOR_YUV2BGR_YUYV); 107 | // cv::imwrite("test.jpg", img); 108 | 109 | end = what_time_is_it_now(); 110 | double t_diff = end - start; 111 | sum += t_diff; 112 | fps = 1000.0 / t_diff; 113 | count++; 114 | std::cout << "Frame " << count << ", time: " << t_diff << " s, FPS: " << fps << std::endl; 115 | 116 | // if (cv::waitKey(30) == 27) { 117 | // break; 118 | // } 119 | // cv::imshow("camera", img); 120 | } 121 | double average_time = sum / count; 122 | std::cout << "Average time per frame: " << average_time << " s" << std::endl; 123 | 124 | // 释放缓冲区 125 | if (ioctl(fd, VIDIOC_QBUF, &buf) == -1) { 126 | perror("Error: failed to queue buffer."); 127 | return -1; 128 | } 129 | 130 | // 停止捕获图像并释放资源 131 | if (ioctl(fd, VIDIOC_STREAMOFF, &buf.type) == -1) { 132 | perror("Error: failed to stop stream."); 133 | return -1; 134 | } 135 | munmap(buf_start, buf.length); 136 | close(fd); 137 | 138 | return 0; 139 | } 140 | -------------------------------------------------------------------------------- /src/cam_v4l2_rga.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include "rga.h" 13 | #include "RgaUtils.h" 14 | #include "im2d.h" 15 | 16 | 17 | #define CAM_DEVICE "/dev/video0" // 摄像头设备文件路径 18 | #define IMG_WIDTH 640 // 图像宽度 19 | #define IMG_HEIGHT 480 // 图像高度 20 | 21 | double what_time_is_it_now() 22 | { 23 | // 单位: ms 24 | struct timeval time; 25 | if (gettimeofday(&time,NULL)){ 26 | return 0; 27 | } 28 | return (double)time.tv_sec * 1000 + (double)time.tv_usec * .001; 29 | } 30 | 31 | 32 | int main() { 33 | // 打开摄像头设备 34 | int fd = open(CAM_DEVICE, O_RDWR); 35 | if (fd == -1) { 36 | perror("Error: failed to open camera."); 37 | return -1; 38 | } 39 | 40 | // 设置视频格式 41 | struct v4l2_format fmt; 42 | memset(&fmt, 0, sizeof(fmt)); 43 | fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 44 | fmt.fmt.pix.width = IMG_WIDTH; 45 | fmt.fmt.pix.height = IMG_HEIGHT; 46 | fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; 47 | if (ioctl(fd, VIDIOC_S_FMT, &fmt) == -1) { 48 | perror("Error: failed to set video format."); 49 | return -1; 50 | } 51 | 52 | // 申请缓冲区 53 | struct v4l2_requestbuffers req; 54 | memset(&req, 0, sizeof(req)); 55 | req.count = 1; 56 | req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 57 | req.memory = V4L2_MEMORY_MMAP; 58 | if (ioctl(fd, VIDIOC_REQBUFS, &req) == -1) { 59 | perror("Error: failed to request buffer."); 60 | return -1; 61 | } 62 | 63 | // 映射缓冲区 64 | struct v4l2_buffer buf; 65 | memset(&buf, 0, sizeof(buf)); 66 | buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 67 | buf.memory = V4L2_MEMORY_MMAP; 68 | buf.index = 0; 69 | if (ioctl(fd, VIDIOC_QUERYBUF, &buf) == -1) { 70 | perror("Error: failed to query buffer."); 71 | return -1; 72 | } 73 | void *buf_start = mmap(NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.offset); 74 | if (buf_start == MAP_FAILED) { 75 | perror("Error: failed to mmap buffer."); 76 | return -1; 77 | } 78 | 79 | // 开始捕获图像 80 | if (ioctl(fd, VIDIOC_STREAMON, &buf.type) == -1) { 81 | perror("Error: failed to start stream."); 82 | return -1; 83 | } 84 | 85 | // // 创建OpenCV窗口 86 | // cv::namedWindow("camera", cv::WINDOW_AUTOSIZE); 87 | 88 | double end; 89 | double start; 90 | double fps; 91 | int count = 0; 92 | double sum = 0; 93 | 94 | // init rga context 95 | rga_buffer_t src; 96 | rga_buffer_t dst; 97 | memset(&src, 0, sizeof(src)); 98 | memset(&dst, 0, sizeof(dst)); 99 | int width = 640; 100 | int height = 480; 101 | void* resize_buf = nullptr; 102 | resize_buf = malloc(height * width * 3); 103 | 104 | // 读取摄像头数据并处理 105 | while (true) { 106 | printf("---------------------------\n"); 107 | start = what_time_is_it_now(); 108 | // 读取图像数据 109 | if (ioctl(fd, VIDIOC_QBUF, &buf) == -1) { 110 | perror("Error: failed to queue buffer."); 111 | return -1; 112 | } 113 | if (ioctl(fd, VIDIOC_DQBUF, &buf) == -1) { 114 | perror("Error: failed to dequeue buffer."); 115 | return -1; 116 | } 117 | 118 | src = wrapbuffer_virtualaddr((void*)buf_start, width, height, RK_FORMAT_YUYV_422); 119 | dst = wrapbuffer_virtualaddr((void*)resize_buf, width, height, RK_FORMAT_BGR_888); 120 | int ret = imcheck(src, dst, {}, {}); 121 | ret = imcvtcolor(src, dst, RK_FORMAT_YUYV_422, RK_FORMAT_BGR_888); 122 | end = what_time_is_it_now(); 123 | double t_diff = end - start; 124 | sum += t_diff; 125 | fps = 1000.0 / t_diff; 126 | count++; 127 | std::cout << "Frame " << count << ", time: " << t_diff << " s, FPS: " << fps << std::endl; 128 | 129 | cv::Mat col_img(cv::Size(width, height), CV_8UC3, resize_buf); 130 | if (cv::waitKey(30) == 27) { 131 | break; 132 | } 133 | // cv::imshow("camera", col_img); 134 | } 135 | double average_time = sum / count; 136 | std::cout << "Average time per frame: " << average_time << " s" << std::endl; 137 | 138 | 139 | // // 释放缓冲区 140 | // if (ioctl(fd, VIDIOC_QBUF, &buf) == -1) { 141 | // perror("Error: failed to queue buffer."); 142 | // return -1; 143 | // } 144 | 145 | // 停止捕获图像并释放资源 146 | if (ioctl(fd, VIDIOC_STREAMOFF, &buf.type) == -1) { 147 | perror("Error: failed to stop stream."); 148 | return -1; 149 | } 150 | munmap(buf_start, buf.length); 151 | close(fd); 152 | 153 | return 0; 154 | } 155 | -------------------------------------------------------------------------------- /src/file_mpp_rga.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Rockchip Electronics Co. LTD 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 18 | #include 19 | #include "rk_mpi.h" 20 | 21 | #include "mpp_mem.h" 22 | #include "mpp_env.h" 23 | #include "mpp_time.h" 24 | #include "mpp_list.h" 25 | #include "mpp_lock.h" 26 | #include "mpp_debug.h" 27 | #include "mpp_common.h" 28 | 29 | #include "utils.h" 30 | #include "mpi_dec_utils.h" 31 | #include "camera_source.h" 32 | 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | 40 | #include "rga.h" 41 | #include "RgaUtils.h" 42 | #include "im2d.h" 43 | 44 | using namespace std; 45 | 46 | typedef struct { 47 | MpiDecTestCmd *cmd; 48 | MppCtx ctx; 49 | MppApi *mpi; 50 | RK_U32 quiet; 51 | 52 | /* end of stream flag when set quit the loop */ 53 | RK_U32 loop_end; 54 | 55 | /* input and output */ 56 | MppBufferGroup frm_grp; 57 | MppPacket packet; 58 | MppFrame frame; 59 | 60 | FILE *fp_output; 61 | RK_S32 frame_count; 62 | RK_S32 frame_num; 63 | 64 | RK_S64 first_pkt; 65 | RK_S64 first_frm; 66 | 67 | size_t max_usage; 68 | float frame_rate; 69 | RK_S64 elapsed_time; 70 | RK_S64 delay; 71 | FILE *fp_verify; 72 | FrmCrc checkcrc; 73 | } MpiDecLoopData; 74 | 75 | static int dec_simple(MpiDecLoopData *data) 76 | { 77 | RK_U32 pkt_done = 0; 78 | RK_U32 pkt_eos = 0; 79 | MPP_RET ret = MPP_OK; 80 | MpiDecTestCmd *cmd = data->cmd; 81 | MppCtx ctx = data->ctx; 82 | MppApi *mpi = data->mpi; 83 | MppPacket packet = data->packet; 84 | FileBufSlot *slot = NULL; 85 | RK_U32 quiet = data->quiet; 86 | FrmCrc *checkcrc = &data->checkcrc; 87 | 88 | // when packet size is valid read the input binary file 89 | ret = reader_read(cmd->reader, &slot); 90 | 91 | mpp_assert(ret == MPP_OK); 92 | mpp_assert(slot); 93 | 94 | pkt_eos = slot->eos; 95 | 96 | if (pkt_eos) { 97 | if (data->frame_num < 0 || data->frame_num > data->frame_count) { 98 | mpp_log_q(quiet, "%p loop again\n", ctx); 99 | reader_rewind(cmd->reader); 100 | pkt_eos = 0; 101 | } else { 102 | mpp_log_q(quiet, "%p found last packet\n", ctx); 103 | data->loop_end = 1; 104 | } 105 | } 106 | 107 | mpp_packet_set_data(packet, slot->data); 108 | mpp_packet_set_size(packet, slot->size); 109 | mpp_packet_set_pos(packet, slot->data); 110 | mpp_packet_set_length(packet, slot->size); 111 | // setup eos flag 112 | if (pkt_eos) 113 | mpp_packet_set_eos(packet); 114 | 115 | 116 | int width = cmd->width; 117 | int height = cmd->height; 118 | 119 | // 创建OpenCV窗口 120 | // cv::namedWindow("camera", cv::WINDOW_AUTOSIZE); 121 | do { 122 | RK_U32 frm_eos = 0; 123 | RK_S32 times = 30; 124 | 125 | // send the packet first if packet is not done 126 | if (!pkt_done) { 127 | ret = mpi->decode_put_packet(ctx, packet); 128 | if (MPP_OK == ret) { 129 | pkt_done = 1; 130 | if (!data->first_pkt) 131 | data->first_pkt = mpp_time(); 132 | } 133 | } 134 | 135 | // then get all available frame and release 136 | do { 137 | RK_S32 get_frm = 0; 138 | MppFrame frame = NULL; 139 | 140 | try_again: 141 | ret = mpi->decode_get_frame(ctx, &frame); 142 | if (MPP_ERR_TIMEOUT == ret) { 143 | if (times > 0) { 144 | times--; 145 | msleep(1); 146 | goto try_again; 147 | } 148 | mpp_err("%p decode_get_frame failed too much time\n", ctx); 149 | } 150 | if (ret) { 151 | mpp_err("%p decode_get_frame failed ret %d\n", ret, ctx); 152 | break; 153 | } 154 | 155 | if (frame) { 156 | // 直接塞入rga 157 | std::cout << "*******************" << std::endl; 158 | 159 | // 方法1 160 | rga_buffer_t src_img; 161 | rga_buffer_t dst_img; 162 | rga_buffer_handle_t src_handle, dst_handle; 163 | memset(&src_img, 0, sizeof(src_img)); 164 | memset(&dst_img, 0, sizeof(dst_img)); 165 | char *src_buf, *dst_buf; 166 | int src_buf_size, dst_buf_size; 167 | int src_format = RK_FORMAT_YCrCb_420_SP; 168 | int dst_format = RK_FORMAT_RGB_888; 169 | RK_U8 *base = NULL; 170 | MppBuffer tmp_buf = NULL; 171 | src_buf_size = width * height * get_bpp_from_format(src_format); 172 | dst_buf_size = width * height * get_bpp_from_format(dst_format); 173 | dst_buf = (char *)malloc(dst_buf_size); // 没有释放 174 | memset(dst_buf, 0x80, dst_buf_size); 175 | tmp_buf = mpp_frame_get_buffer(frame); 176 | base = (RK_U8 *)mpp_buffer_get_ptr(tmp_buf); 177 | size_t base_length = mpp_buffer_get_size(tmp_buf); 178 | int fd = mpp_buffer_get_fd(tmp_buf); 179 | src_handle = importbuffer_fd(fd, src_buf_size); 180 | dst_handle = importbuffer_virtualaddr(dst_buf, dst_buf_size); 181 | src_img = wrapbuffer_handle(src_handle, width, height, src_format); 182 | dst_img = wrapbuffer_handle(dst_handle, width, height, dst_format); 183 | int rets; 184 | rets = imcheck(src_img, dst_img, {}, {}); 185 | rets = imcvtcolor(src_img, dst_img, src_format, dst_format); 186 | cv::Mat col_img(cv::Size(width, height), CV_8UC3, dst_buf); 187 | if (cv::waitKey(30) == 27) { 188 | break; 189 | } 190 | // cv::imshow("camera", col_img); 191 | cv::imwrite("/mnt/udisk/librga_demo/data/" + std::to_string(data->frame_count) + ".jpg", col_img); 192 | std::cout << "/mnt/udisk/librga_demo/data/" + std::to_string(data->frame_count) + ".jpg" << std::endl; 193 | if (src_handle) 194 | releasebuffer_handle(src_handle); 195 | if (dst_handle) 196 | releasebuffer_handle(dst_handle); 197 | if (src_buf) 198 | free(src_buf); 199 | if (dst_buf) 200 | free(dst_buf); 201 | 202 | 203 | 204 | 205 | // // 方法2 206 | // rga_buffer_t src_img; 207 | // rga_buffer_t dst_img; 208 | // memset(&src_img, 0, sizeof(src_img)); 209 | // memset(&dst_img, 0, sizeof(dst_img)); 210 | // void* resize_buf = nullptr; 211 | // resize_buf = malloc(height * width * 3); 212 | // RK_U8 *base = NULL; 213 | // MppBuffer tmp_buf = NULL; 214 | // tmp_buf = mpp_frame_get_buffer(frame); 215 | // base = (RK_U8 *)mpp_buffer_get_ptr(tmp_buf); 216 | // src_img = wrapbuffer_virtualaddr((void*)base, width, height, RK_FORMAT_YCbCr_420_SP); 217 | // dst_img = wrapbuffer_virtualaddr((void*)resize_buf, width, height, RK_FORMAT_BGR_888); 218 | // int ret = imcheck(src_img, dst_img, {}, {}); 219 | // ret = imcvtcolor(src_img, dst_img, RK_FORMAT_YCbCr_420_SP, RK_FORMAT_BGR_888); 220 | // cv::Mat col_img(cv::Size(width, height), CV_8UC3, resize_buf); 221 | // cv::imwrite("file_mpp_rga.jpg", col_img); 222 | // if (resize_buf) 223 | // free(resize_buf); 224 | 225 | 226 | 227 | 228 | 229 | if (mpp_frame_get_info_change(frame)) { 230 | RK_U32 width = mpp_frame_get_width(frame); 231 | RK_U32 height = mpp_frame_get_height(frame); 232 | RK_U32 hor_stride = mpp_frame_get_hor_stride(frame); 233 | RK_U32 ver_stride = mpp_frame_get_ver_stride(frame); 234 | RK_U32 buf_size = mpp_frame_get_buf_size(frame); 235 | 236 | mpp_log_q(quiet, "%p decode_get_frame get info changed found\n", ctx); 237 | mpp_log_q(quiet, "%p decoder require buffer w:h [%d:%d] stride [%d:%d] buf_size %d", 238 | ctx, width, height, hor_stride, ver_stride, buf_size); 239 | 240 | /* 241 | * NOTE: We can choose decoder's buffer mode here. 242 | * There are three mode that decoder can support: 243 | * 244 | * Mode 1: Pure internal mode 245 | * In the mode user will NOT call MPP_DEC_SET_EXT_BUF_GROUP 246 | * control to decoder. Only call MPP_DEC_SET_INFO_CHANGE_READY 247 | * to let decoder go on. Then decoder will use create buffer 248 | * internally and user need to release each frame they get. 249 | * 250 | * Advantage: 251 | * Easy to use and get a demo quickly 252 | * Disadvantage: 253 | * 1. The buffer from decoder may not be return before 254 | * decoder is close. So memroy leak or crash may happen. 255 | * 2. The decoder memory usage can not be control. Decoder 256 | * is on a free-to-run status and consume all memory it can 257 | * get. 258 | * 3. Difficult to implement zero-copy display path. 259 | * 260 | * Mode 2: Half internal mode 261 | * This is the mode current test code using. User need to 262 | * create MppBufferGroup according to the returned info 263 | * change MppFrame. User can use mpp_buffer_group_limit_config 264 | * function to limit decoder memory usage. 265 | * 266 | * Advantage: 267 | * 1. Easy to use 268 | * 2. User can release MppBufferGroup after decoder is closed. 269 | * So memory can stay longer safely. 270 | * 3. Can limit the memory usage by mpp_buffer_group_limit_config 271 | * Disadvantage: 272 | * 1. The buffer limitation is still not accurate. Memory usage 273 | * is 100% fixed. 274 | * 2. Also difficult to implement zero-copy display path. 275 | * 276 | * Mode 3: Pure external mode 277 | * In this mode use need to create empty MppBufferGroup and 278 | * import memory from external allocator by file handle. 279 | * On Android surfaceflinger will create buffer. Then 280 | * mediaserver get the file handle from surfaceflinger and 281 | * commit to decoder's MppBufferGroup. 282 | * 283 | * Advantage: 284 | * 1. Most efficient way for zero-copy display 285 | * Disadvantage: 286 | * 1. Difficult to learn and use. 287 | * 2. Player work flow may limit this usage. 288 | * 3. May need a external parser to get the correct buffer 289 | * size for the external allocator. 290 | * 291 | * The required buffer size caculation: 292 | * hor_stride * ver_stride * 3 / 2 for pixel data 293 | * hor_stride * ver_stride / 2 for extra info 294 | * Total hor_stride * ver_stride * 2 will be enough. 295 | * 296 | * For H.264/H.265 20+ buffers will be enough. 297 | * For other codec 10 buffers will be enough. 298 | */ 299 | 300 | if (NULL == data->frm_grp) { 301 | /* If buffer group is not set create one and limit it */ 302 | ret = mpp_buffer_group_get_internal(&data->frm_grp, MPP_BUFFER_TYPE_ION); 303 | if (ret) { 304 | mpp_err("%p get mpp buffer group failed ret %d\n", ctx, ret); 305 | break; 306 | } 307 | 308 | /* Set buffer to mpp decoder */ 309 | ret = mpi->control(ctx, MPP_DEC_SET_EXT_BUF_GROUP, data->frm_grp); 310 | if (ret) { 311 | mpp_err("%p set buffer group failed ret %d\n", ctx, ret); 312 | break; 313 | } 314 | } else { 315 | /* If old buffer group exist clear it */ 316 | ret = mpp_buffer_group_clear(data->frm_grp); 317 | if (ret) { 318 | mpp_err("%p clear buffer group failed ret %d\n", ctx, ret); 319 | break; 320 | } 321 | } 322 | 323 | /* Use limit config to limit buffer count to 24 with buf_size */ 324 | ret = mpp_buffer_group_limit_config(data->frm_grp, buf_size, 24); 325 | if (ret) { 326 | mpp_err("%p limit buffer group failed ret %d\n", ctx, ret); 327 | break; 328 | } 329 | 330 | /* 331 | * All buffer group config done. Set info change ready to let 332 | * decoder continue decoding 333 | */ 334 | ret = mpi->control(ctx, MPP_DEC_SET_INFO_CHANGE_READY, NULL); 335 | if (ret) { 336 | mpp_err("%p info change ready failed ret %d\n", ctx, ret); 337 | break; 338 | } 339 | } else { 340 | char log_buf[256]; 341 | RK_S32 log_size = sizeof(log_buf) - 1; 342 | RK_S32 log_len = 0; 343 | RK_U32 err_info = mpp_frame_get_errinfo(frame); 344 | RK_U32 discard = mpp_frame_get_discard(frame); 345 | 346 | if (!data->first_frm) 347 | data->first_frm = mpp_time(); 348 | 349 | log_len += snprintf(log_buf + log_len, log_size - log_len, 350 | "decode get frame %d", data->frame_count); 351 | 352 | if (mpp_frame_has_meta(frame)) { 353 | MppMeta meta = mpp_frame_get_meta(frame); 354 | RK_S32 temporal_id = 0; 355 | 356 | mpp_meta_get_s32(meta, KEY_TEMPORAL_ID, &temporal_id); 357 | 358 | log_len += snprintf(log_buf + log_len, log_size - log_len, 359 | " tid %d", temporal_id); 360 | } 361 | 362 | if (err_info || discard) { 363 | log_len += snprintf(log_buf + log_len, log_size - log_len, 364 | " err %x discard %x", err_info, discard); 365 | } 366 | mpp_log_q(quiet, "%p %s\n", ctx, log_buf); 367 | 368 | data->frame_count++; 369 | if (data->fp_output && !err_info) 370 | dump_mpp_frame_to_file(frame, data->fp_output); 371 | 372 | if (data->fp_verify) { 373 | calc_frm_crc(frame, checkcrc); 374 | write_frm_crc(data->fp_verify, checkcrc); 375 | } 376 | 377 | fps_calc_inc(cmd->fps); 378 | } 379 | frm_eos = mpp_frame_get_eos(frame); 380 | mpp_frame_deinit(&frame); 381 | get_frm = 1; 382 | } 383 | 384 | // try get runtime frame memory usage 385 | if (data->frm_grp) { 386 | size_t usage = mpp_buffer_group_usage(data->frm_grp); 387 | if (usage > data->max_usage) 388 | data->max_usage = usage; 389 | } 390 | 391 | // if last packet is send but last frame is not found continue 392 | if (pkt_eos && pkt_done && !frm_eos) { 393 | msleep(1); 394 | continue; 395 | } 396 | 397 | if (frm_eos) { 398 | mpp_log_q(quiet, "%p found last packet\n", ctx); 399 | break; 400 | } 401 | 402 | if ((data->frame_num > 0 && (data->frame_count >= data->frame_num)) || 403 | ((data->frame_num == 0) && frm_eos)) 404 | break; 405 | 406 | if (get_frm) 407 | continue; 408 | break; 409 | } while (1); 410 | 411 | if ((data->frame_num > 0 && (data->frame_count >= data->frame_num)) || 412 | ((data->frame_num == 0) && frm_eos)) { 413 | data->loop_end = 1; 414 | break; 415 | } 416 | 417 | if (pkt_done) 418 | break; 419 | 420 | /* 421 | * why sleep here: 422 | * mpi->decode_put_packet will failed when packet in internal queue is 423 | * full,waiting the package is consumed .Usually hardware decode one 424 | * frame which resolution is 1080p needs 2 ms,so here we sleep 1ms 425 | * * is enough. 426 | */ 427 | msleep(1); 428 | } while (1); 429 | 430 | return ret; 431 | } 432 | 433 | static int dec_advanced(MpiDecLoopData *data) 434 | { 435 | MPP_RET ret = MPP_OK; 436 | MpiDecTestCmd *cmd = data->cmd; 437 | MppCtx ctx = data->ctx; 438 | MppApi *mpi = data->mpi; 439 | MppPacket packet = NULL; 440 | MppFrame frame = data->frame; 441 | MppTask task = NULL; 442 | RK_U32 quiet = data->quiet; 443 | FileBufSlot *slot = NULL; 444 | FrmCrc *checkcrc = &data->checkcrc; 445 | 446 | ret = reader_index_read(cmd->reader, 0, &slot); 447 | mpp_assert(ret == MPP_OK); 448 | mpp_assert(slot); 449 | 450 | mpp_packet_init_with_buffer(&packet, slot->buf); 451 | 452 | // setup eos flag 453 | if (slot->eos) 454 | mpp_packet_set_eos(packet); 455 | 456 | ret = mpi->poll(ctx, MPP_PORT_INPUT, MPP_POLL_BLOCK); 457 | if (ret) { 458 | mpp_err("%p mpp input poll failed\n", ctx); 459 | return ret; 460 | } 461 | 462 | ret = mpi->dequeue(ctx, MPP_PORT_INPUT, &task); /* input queue */ 463 | if (ret) { 464 | mpp_err("%p mpp task input dequeue failed\n", ctx); 465 | return ret; 466 | } 467 | 468 | mpp_assert(task); 469 | 470 | mpp_task_meta_set_packet(task, KEY_INPUT_PACKET, packet); 471 | mpp_task_meta_set_frame (task, KEY_OUTPUT_FRAME, frame); 472 | 473 | ret = mpi->enqueue(ctx, MPP_PORT_INPUT, task); /* input queue */ 474 | if (ret) { 475 | mpp_err("%p mpp task input enqueue failed\n", ctx); 476 | return ret; 477 | } 478 | 479 | if (!data->first_pkt) 480 | data->first_pkt = mpp_time(); 481 | 482 | /* poll and wait here */ 483 | ret = mpi->poll(ctx, MPP_PORT_OUTPUT, MPP_POLL_BLOCK); 484 | if (ret) { 485 | mpp_err("%p mpp output poll failed\n", ctx); 486 | return ret; 487 | } 488 | 489 | ret = mpi->dequeue(ctx, MPP_PORT_OUTPUT, &task); /* output queue */ 490 | if (ret) { 491 | mpp_err("%p mpp task output dequeue failed\n", ctx); 492 | return ret; 493 | } 494 | 495 | mpp_assert(task); 496 | 497 | if (task) { 498 | MppFrame frame_out = NULL; 499 | 500 | mpp_task_meta_get_frame(task, KEY_OUTPUT_FRAME, &frame_out); 501 | 502 | if (frame) { 503 | if (!data->first_frm) 504 | data->first_frm = mpp_time(); 505 | 506 | /* write frame to file here */ 507 | if (data->fp_output) 508 | dump_mpp_frame_to_file(frame, data->fp_output); 509 | 510 | if (data->fp_verify) { 511 | calc_frm_crc(frame, checkcrc); 512 | write_frm_crc(data->fp_verify, checkcrc); 513 | } 514 | 515 | mpp_log_q(quiet, "%p decoded frame %d\n", ctx, data->frame_count); 516 | data->frame_count++; 517 | 518 | if (mpp_frame_get_eos(frame_out)) { 519 | mpp_log_q(quiet, "%p found eos frame\n", ctx); 520 | } 521 | fps_calc_inc(cmd->fps); 522 | } 523 | 524 | if (data->frame_num > 0) { 525 | if (data->frame_count >= data->frame_num) 526 | data->loop_end = 1; 527 | } else if (data->frame_num == 0) { 528 | if (slot->eos) 529 | data->loop_end = 1; 530 | } 531 | 532 | /* output queue */ 533 | ret = mpi->enqueue(ctx, MPP_PORT_OUTPUT, task); 534 | if (ret) 535 | mpp_err("%p mpp task output enqueue failed\n", ctx); 536 | } 537 | 538 | /* 539 | * The following input port task dequeue and enqueue is to make sure that 540 | * the input packet can be released. We can directly deinit the input packet 541 | * after frame output in most cases. 542 | */ 543 | if (0) { 544 | mpp_packet_deinit(&packet); 545 | } else { 546 | ret = mpi->dequeue(ctx, MPP_PORT_INPUT, &task); /* input queue */ 547 | if (ret) { 548 | mpp_err("%p mpp task input dequeue failed\n", ctx); 549 | return ret; 550 | } 551 | 552 | mpp_assert(task); 553 | if (task) { 554 | MppPacket packet_out = NULL; 555 | 556 | mpp_task_meta_get_packet(task, KEY_INPUT_PACKET, &packet_out); 557 | 558 | if (!packet_out || packet_out != packet) 559 | mpp_err_f("mismatch packet %p -> %p\n", packet, packet_out); 560 | 561 | mpp_packet_deinit(&packet_out); 562 | 563 | /* input empty task back to mpp to maintain task status */ 564 | ret = mpi->enqueue(ctx, MPP_PORT_INPUT, task); 565 | if (ret) 566 | mpp_err("%p mpp task input enqueue failed\n", ctx); 567 | } 568 | } 569 | 570 | return ret; 571 | } 572 | 573 | void *thread_decode(void *arg) 574 | { 575 | MpiDecLoopData *data = (MpiDecLoopData *)arg; 576 | MpiDecTestCmd *cmd = data->cmd; 577 | MppCtx ctx = data->ctx; 578 | MppApi *mpi = data->mpi; 579 | RK_S64 t_s, t_e; 580 | 581 | memset(&data->checkcrc, 0, sizeof(data->checkcrc)); 582 | data->checkcrc.luma.sum = mpp_malloc(RK_ULONG, 512); 583 | data->checkcrc.chroma.sum = mpp_malloc(RK_ULONG, 512); 584 | 585 | t_s = mpp_time(); 586 | 587 | if (cmd->simple) { 588 | while (!data->loop_end) 589 | dec_simple(data); 590 | } else { 591 | /* NOTE: change output format before jpeg decoding */ 592 | if (MPP_FRAME_FMT_IS_YUV(cmd->format) || MPP_FRAME_FMT_IS_RGB(cmd->format)) { 593 | MPP_RET ret = mpi->control(ctx, MPP_DEC_SET_OUTPUT_FORMAT, &cmd->format); 594 | if (ret) { 595 | mpp_err("Failed to set output format %d\n", cmd->format); 596 | return NULL; 597 | } 598 | } 599 | 600 | while (!data->loop_end) 601 | dec_advanced(data); 602 | } 603 | 604 | t_e = mpp_time(); 605 | data->elapsed_time = t_e - t_s; 606 | data->frame_count = data->frame_count; 607 | data->frame_rate = (float)data->frame_count * 1000000 / data->elapsed_time; 608 | data->delay = data->first_frm - data->first_pkt; 609 | 610 | mpp_log("decode %d frames time %lld ms delay %3d ms fps %3.2f\n", 611 | data->frame_count, (RK_S64)(data->elapsed_time / 1000), 612 | (RK_S32)(data->delay / 1000), data->frame_rate); 613 | 614 | MPP_FREE(data->checkcrc.luma.sum); 615 | MPP_FREE(data->checkcrc.chroma.sum); 616 | 617 | return NULL; 618 | } 619 | 620 | int dec_decode(MpiDecTestCmd *cmd) 621 | { 622 | // base flow context 623 | MppCtx ctx = NULL; 624 | MppApi *mpi = NULL; 625 | 626 | // input / output 627 | MppPacket packet = NULL; 628 | MppFrame frame = NULL; 629 | 630 | // paramter for resource malloc 631 | RK_U32 width = cmd->width; 632 | RK_U32 height = cmd->height; 633 | MppCodingType type = cmd->type; 634 | 635 | // config for runtime mode 636 | MppDecCfg cfg = NULL; 637 | RK_U32 need_split = 1; 638 | 639 | // resources 640 | MppBuffer frm_buf = NULL; 641 | pthread_t thd; 642 | pthread_attr_t attr; 643 | MpiDecLoopData data; 644 | // MPP_RET ret = MPP_OK; 645 | RK_S32 ret = MPP_OK; 646 | 647 | mpp_log("mpi_dec_test start\n"); 648 | memset(&data, 0, sizeof(data)); 649 | pthread_attr_init(&attr); 650 | 651 | cmd->simple = (cmd->type != MPP_VIDEO_CodingMJPEG) ? (1) : (0); 652 | 653 | if (cmd->have_output) { 654 | data.fp_output = fopen(cmd->file_output, "w+b"); 655 | if (NULL == data.fp_output) { 656 | mpp_err("failed to open output file %s\n", cmd->file_output); 657 | goto MPP_TEST_OUT; 658 | } 659 | } 660 | 661 | if (cmd->file_slt) { 662 | data.fp_verify = fopen(cmd->file_slt, "wt"); 663 | if (!data.fp_verify) 664 | mpp_err("failed to open verify file %s\n", cmd->file_slt); 665 | } 666 | 667 | if (cmd->simple) { 668 | ret = mpp_packet_init(&packet, NULL, 0); 669 | if (ret) { 670 | mpp_err("mpp_packet_init failed\n"); 671 | goto MPP_TEST_OUT; 672 | } 673 | } else { 674 | RK_U32 hor_stride = MPP_ALIGN(width, 16); 675 | RK_U32 ver_stride = MPP_ALIGN(height, 16); 676 | 677 | ret = mpp_buffer_group_get_internal(&data.frm_grp, MPP_BUFFER_TYPE_ION); 678 | if (ret) { 679 | mpp_err("failed to get buffer group for input frame ret %d\n", ret); 680 | goto MPP_TEST_OUT; 681 | } 682 | 683 | ret = mpp_frame_init(&frame); /* output frame */ 684 | if (ret) { 685 | mpp_err("mpp_frame_init failed\n"); 686 | goto MPP_TEST_OUT; 687 | } 688 | 689 | /* 690 | * NOTE: For jpeg could have YUV420 and YUV422 the buffer should be 691 | * larger for output. And the buffer dimension should align to 16. 692 | * YUV420 buffer is 3/2 times of w*h. 693 | * YUV422 buffer is 2 times of w*h. 694 | * So create larger buffer with 2 times w*h. 695 | */ 696 | ret = mpp_buffer_get(data.frm_grp, &frm_buf, hor_stride * ver_stride * 4); 697 | if (ret) { 698 | mpp_err("failed to get buffer for input frame ret %d\n", ret); 699 | goto MPP_TEST_OUT; 700 | } 701 | 702 | mpp_frame_set_buffer(frame, frm_buf); 703 | } 704 | 705 | // decoder demo 706 | ret = mpp_create(&ctx, &mpi); 707 | if (ret) { 708 | mpp_err("mpp_create failed\n"); 709 | goto MPP_TEST_OUT; 710 | } 711 | 712 | mpp_log("%p mpi_dec_test decoder test start w %d h %d type %d\n", 713 | ctx, width, height, type); 714 | 715 | ret = mpp_init(ctx, MPP_CTX_DEC, type); 716 | if (ret) { 717 | mpp_err("%p mpp_init failed\n", ctx); 718 | goto MPP_TEST_OUT; 719 | } 720 | 721 | mpp_dec_cfg_init(&cfg); 722 | 723 | /* get default config from decoder context */ 724 | ret = mpi->control(ctx, MPP_DEC_GET_CFG, cfg); 725 | if (ret) { 726 | mpp_err("%p failed to get decoder cfg ret %d\n", ctx, ret); 727 | goto MPP_TEST_OUT; 728 | } 729 | 730 | /* 731 | * split_parse is to enable mpp internal frame spliter when the input 732 | * packet is not aplited into frames. 733 | */ 734 | ret = mpp_dec_cfg_set_u32(cfg, "base:split_parse", need_split); 735 | if (ret) { 736 | mpp_err("%p failed to set split_parse ret %d\n", ctx, ret); 737 | goto MPP_TEST_OUT; 738 | } 739 | 740 | ret = mpi->control(ctx, MPP_DEC_SET_CFG, cfg); 741 | if (ret) { 742 | mpp_err("%p failed to set cfg %p ret %d\n", ctx, cfg, ret); 743 | goto MPP_TEST_OUT; 744 | } 745 | 746 | data.cmd = cmd; 747 | data.ctx = ctx; 748 | data.mpi = mpi; 749 | data.loop_end = 0; 750 | data.packet = packet; 751 | data.frame = frame; 752 | data.frame_count = 0; 753 | data.frame_num = cmd->frame_num; 754 | data.quiet = cmd->quiet; 755 | 756 | pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 757 | 758 | ret = pthread_create(&thd, &attr, thread_decode, &data); 759 | if (ret) { 760 | mpp_err("failed to create thread for input ret %d\n", ret); 761 | goto MPP_TEST_OUT; 762 | } 763 | 764 | if (cmd->frame_num < 0) { 765 | // wait for input then quit decoding 766 | mpp_log("*******************************************\n"); 767 | mpp_log("**** Press Enter to stop loop decoding ****\n"); 768 | mpp_log("*******************************************\n"); 769 | 770 | getc(stdin); 771 | data.loop_end = 1; 772 | } 773 | 774 | pthread_join(thd, NULL); 775 | 776 | cmd->max_usage = data.max_usage; 777 | 778 | ret = mpi->reset(ctx); 779 | if (ret) { 780 | mpp_err("%p mpi->reset failed\n", ctx); 781 | goto MPP_TEST_OUT; 782 | } 783 | 784 | MPP_TEST_OUT: 785 | if (data.packet) { 786 | mpp_packet_deinit(&data.packet); 787 | data.packet = NULL; 788 | } 789 | 790 | if (frame) { 791 | mpp_frame_deinit(&frame); 792 | frame = NULL; 793 | } 794 | 795 | if (ctx) { 796 | mpp_destroy(ctx); 797 | ctx = NULL; 798 | } 799 | 800 | if (!cmd->simple) { 801 | if (frm_buf) { 802 | mpp_buffer_put(frm_buf); 803 | frm_buf = NULL; 804 | } 805 | } 806 | 807 | if (data.frm_grp) { 808 | mpp_buffer_group_put(data.frm_grp); 809 | data.frm_grp = NULL; 810 | } 811 | 812 | if (data.fp_output) { 813 | fclose(data.fp_output); 814 | data.fp_output = NULL; 815 | } 816 | 817 | if (data.fp_verify) { 818 | fclose(data.fp_verify); 819 | data.fp_verify = NULL; 820 | } 821 | 822 | if (cfg) { 823 | mpp_dec_cfg_deinit(cfg); 824 | cfg = NULL; 825 | } 826 | 827 | pthread_attr_destroy(&attr); 828 | 829 | return ret; 830 | } 831 | 832 | int main(int argc, char **argv) 833 | { 834 | RK_S32 ret = 0; 835 | MpiDecTestCmd cmd_ctx; 836 | MpiDecTestCmd* cmd = &cmd_ctx; 837 | 838 | memset((void*)cmd, 0, sizeof(*cmd)); 839 | cmd->format = MPP_FMT_BUTT; 840 | cmd->pkt_size = MPI_DEC_STREAM_SIZE; 841 | 842 | // parse the cmd option 843 | ret = mpi_dec_test_cmd_init(cmd, argc, argv); 844 | if (ret) 845 | goto RET; 846 | 847 | mpi_dec_test_cmd_options(cmd); 848 | 849 | ret = dec_decode(cmd); 850 | if (MPP_OK == ret) 851 | mpp_log("test success max memory %.2f MB\n", cmd->max_usage / (float)(1 << 20)); 852 | else 853 | mpp_err("test failed ret %d\n", ret); 854 | 855 | RET: 856 | mpi_dec_test_cmd_deinit(cmd); 857 | 858 | return ret; 859 | } 860 | 861 | -------------------------------------------------------------------------------- /src/file_opencv.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace cv; 4 | int main() 5 | { 6 | cv::VideoCapture cap; 7 | 8 | // 读摄像头的mjpeg数据 9 | // cap.set(cv::CAP_PROP_FOURCC, cv::VideoWriter::fourcc('M', 'J', 'P', 'G')); 10 | // cap.set(cv::CAP_PROP_CONVERT_RGB, false); 11 | 12 | // 读摄像头的yuv数据 13 | // cap.set(cv::CAP_PROP_FORMAT, CV_8UC1); 14 | // cap.set(cv::CAP_PROP_CONVERT_RGB, false); 15 | if (!cap.open("/udisk/librga_demo/xingren_demo.mp4")) { 16 | std::cerr << "Failed to open camera." << std::endl; 17 | return -1; 18 | } 19 | 20 | cv::Mat frame; 21 | double fps; 22 | double t = 0; 23 | double t_start = cv::getTickCount(); // 获取起始时间戳 24 | int count = 0; 25 | 26 | while (true) { 27 | cap >> frame; // 读取一帧图像 28 | if (frame.empty()) { 29 | break; 30 | } 31 | 32 | double t_end = cv::getTickCount(); // 获取结束时间戳 33 | double t_diff = (t_end - t_start) / cv::getTickFrequency(); // 计算时间差 34 | fps = 1.0 / t_diff; // 计算帧率 35 | 36 | t += t_diff; 37 | count++; 38 | 39 | std::cout << "Frame " << count << ", time: " << t_diff << " s, FPS: " << fps << std::endl; 40 | 41 | t_start = t_end; 42 | } 43 | 44 | double average_time = t / count; 45 | std::cout << "Average time per frame: " << average_time << " s" << std::endl; 46 | 47 | cap.release(); 48 | cv::destroyAllWindows(); 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /src/resize_demo.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #define _BASETSD_H 10 | 11 | #include "RgaUtils.h" 12 | #include "im2d.h" 13 | #include "opencv2/core/core.hpp" 14 | #include "opencv2/imgcodecs.hpp" 15 | #include "opencv2/imgproc.hpp" 16 | #include "rga.h" 17 | 18 | using namespace std; 19 | using namespace cv; 20 | 21 | /* 22 | * 测试librga与opencv的resize性能 23 | */ 24 | 25 | 26 | double what_time_is_it_now() 27 | { 28 | // 单位: ms 29 | struct timeval time; 30 | if (gettimeofday(&time,NULL)){ 31 | return 0; 32 | } 33 | return (double)time.tv_sec * 1000 + (double)time.tv_usec * .001; 34 | } 35 | 36 | int main() 37 | { 38 | // init rga context 39 | rga_buffer_t src; 40 | rga_buffer_t dst; 41 | memset(&src, 0, sizeof(src)); 42 | memset(&dst, 0, sizeof(dst)); 43 | 44 | // opencv read img 45 | string img_path = "/udisk/workspaces/rknpu2/examples/rknn_yolov5_demo/model/bus.jpg"; 46 | cv::Mat orig_img = cv::imread(img_path); 47 | int img_width = orig_img.cols; 48 | int img_height = orig_img.rows; 49 | printf("img width = %d, img height = %d\n", img_width, img_height); 50 | 51 | // rga resize img 52 | int dst_width = 1920; 53 | int dst_height = 1080; 54 | void* resize_buf = nullptr; 55 | resize_buf = malloc(dst_height * dst_width * 3); 56 | memset(resize_buf, 0x00, dst_height * dst_width * 3); 57 | double rga_sum = 0; 58 | double rga_end; 59 | double rga_start; 60 | for (int i = 0; i < 30; i++) { 61 | 62 | src = wrapbuffer_virtualaddr((void*)orig_img.data, img_width, img_height, RK_FORMAT_RGB_888); 63 | dst = wrapbuffer_virtualaddr((void*)resize_buf, dst_width, dst_height, RK_FORMAT_RGB_888); 64 | // int ret = imcheck(src, dst, src_rect, dst_rect); 65 | int ret = imcheck(src, dst, {}, {}); 66 | rga_start = what_time_is_it_now(); 67 | IM_STATUS STATUS = imresize(src, dst); 68 | rga_end = what_time_is_it_now(); 69 | rga_sum += rga_end - rga_start; 70 | } 71 | double rga_one = rga_sum / 30; 72 | 73 | // val result img 74 | cv::Mat resize_img(cv::Size(dst_width, dst_height), CV_8UC3, resize_buf); 75 | cv::imwrite("rga_resize_val.jpg", resize_img); 76 | 77 | 78 | 79 | Mat resized_image; 80 | double opencv_sum = 0; 81 | double opencv_start; 82 | double opencv_end; 83 | for (int i = 0; i < 30; i++) { 84 | opencv_start = what_time_is_it_now(); 85 | cv::resize(orig_img, resized_image, cv::Size(dst_width, dst_height)); 86 | opencv_end = what_time_is_it_now(); 87 | opencv_sum += opencv_end - opencv_start; 88 | } 89 | double opencv_one = opencv_sum / 30; 90 | cv::imwrite("opencv_resize_val.jpg", resized_image); 91 | 92 | std::cout << "rga cost time : " << rga_one << std::endl; 93 | std::cout << "opencv cost time : " << opencv_one << std::endl; 94 | std::cout << "rga ave cost time : " << rga_end - rga_start << std::endl; 95 | std::cout << "opencv ave cost time : " << opencv_end - opencv_start << std::endl; 96 | 97 | orig_img.release(); 98 | resized_image.release(); 99 | release_buffer: 100 | free(resize_buf); 101 | 102 | return 0; 103 | } 104 | --------------------------------------------------------------------------------