Closed TRYOKETHEPEN closed 2 months ago
问题: 使用mpp解码UVC摄像头的视频流(MJPEG,1280*720,30fps),获取第一帧后,阻塞在Decode()的do...while循环中。 on_uvc_frame_out()中可以正常保存本地.jpeg文件,查看该文件图像格式为YUV422。
查看之前的issue(https://github.com/rockchip-linux/mpp/issues/309 https://github.com/rockchip-linux/mpp/issues/82 https://github.com/rockchip-linux/mpp/issues/171 ),以及mpi_dec_test.c例程中有如下内容。是否当前MJPEG的解码还是只能使用advanced接口?
//省略 cmd->simple = (cmd->type != MPP_VIDEO_CodingMJPEG) ? (1) : (0); //省略 //进入dec_advanced()
开发板: RK3588,Debian11 mpp安装过程: install_log.txt mpp环境测试信息: test_log.txt
相关应用代码: main()->process_video_UVC()-->初始化解码器-->开始播放-->on_uvc_frame_out()->Decode()->mpp_decoder_frame_callback()
// UVC播放回调 void on_uvc_frame_out(uvc_frame_t *frame, void *ptr) { uvc_error_t ret; printf("callback! frame_format = %d, width = %d, height = %d, length = %lu, ptr = %p\n", frame->frame_format, frame->width, frame->height, frame->data_bytes, ptr); switch (frame->frame_format) { case UVC_FRAME_FORMAT_H264: break; case UVC_FRAME_FORMAT_MJPEG: static int jpeg_count = 0; char filename[16]; sprintf(filename, "%d.jpeg", jpeg_count++); FILE *fp; fp = fopen(filename, "w"); fwrite(frame->data, 1, frame->data_bytes, fp); fclose(fp); break; case UVC_FRAME_FORMAT_YUYV: break; default: break; } first_ctx.decoder->Decode((uint8_t *)frame->data, frame->data_bytes, 0); // 解码//*解码完成后触发回调mpp_decoder_frame_callback } // 处理UVC视频输入 static int process_video_UVC(const char *path) { uvc_context_t *ctx; uvc_device_t *dev; uvc_device_handle_t *devh; uvc_stream_ctrl_t ctrl; uvc_error_t res; res = uvc_init(&ctx, NULL); // 初始化UVC ctx if (res < 0) { uvc_perror(res, "uvc_init"); return res; } puts("UVC初始化成功"); res = uvc_find_device(ctx, &dev, 0x1e4e, 0x0109, NULL); // 寻找设备 筛选项: vendor_id, product_id, "serial_num",不筛选置为0,0,NULL if (res < 0) { uvc_perror(res, "uvc_find_device"); return res; } puts("找到UVC设备"); res = uvc_open(dev, &devh); // 打开设备,不能与其他进程同时占用 if (res < 0) { uvc_perror(res, "uvc_open"); return res; } puts("开启UVC设备"); printf("UVC设备信息:\n"); uvc_print_diag(devh, stderr); // 打印UVC设备信息 const uvc_format_desc_t *format_desc = uvc_get_format_descs(devh); // 格式描述体 enum uvc_frame_format frame_format; // 帧格式 int width, height, fps; switch (format_desc->bDescriptorSubtype) { case UVC_VS_FORMAT_MJPEG: frame_format = UVC_FRAME_FORMAT_MJPEG; break; case UVC_VS_FORMAT_FRAME_BASED: frame_format = UVC_FRAME_FORMAT_H264; break; default: frame_format = UVC_FRAME_FORMAT_YUYV; break; } if (format_desc->frame_descs) { width = format_desc->frame_descs->wWidth; height = format_desc->frame_descs->wHeight; fps = 10000000 / format_desc->frame_descs->dwDefaultFrameInterval; } printf("UVC格式=%4s %dx%d %dfps\n", format_desc->fourccFormat, width, height, fps); res = uvc_get_stream_ctrl_format_size(devh, &ctrl, frame_format, width, height, fps); // 协商第一个流文件 if (res < 0) { uvc_perror(res, "get_mode"); return res; } printf("\nUVC流控信息:\n"); uvc_print_stream_ctrl(&ctrl, stderr); // 打印流控信息 //省略 if (first_ctx.decoder == NULL) //! 首次进入才设置 { MppCodingType mpp_type; if (frame_format == UVC_FRAME_FORMAT_MJPEG) { mpp_type = MPP_VIDEO_CodingMJPEG; } else if (frame_format == UVC_FRAME_FORMAT_H264) { mpp_type = MPP_VIDEO_CodingAVC; } printf(">>>>>设置视频解码器\n"); MppDecoder *decoder = new MppDecoder(); // 记得delete decoder->Init(mpp_type, fps, NULL); // 初始化解码器 decoder->SetCallback(mpp_decoder_frame_callback); //* 注册解码回调函数 first_ctx.decoder = decoder; } res = uvc_start_streaming(devh, &ctrl, on_uvc_frame_out, (void *)12345, 0); //! 开启流 if (res < 0) { uvc_perror(res, "start_streaming"); return res; } puts(">>>>>开始播放"); printf(">>>>>按任意按键退出播放\n"); getchar(); //省略 return 0; } int main(int argc, char **argv) { //省略 printf(">>>>>处理输入视频\n"); if (strncmp(in_video_path.c_str(), "rtsp", 4) == 0) // 如果视频路径开头为rtsp { printf("输入为rtsp\n"); process_video_rtsp(in_video_path.c_str()); } else if (strncmp(in_video_path.c_str(), "USB", 3) == 0) // UVC摄像头 { printf("输入为UVC\n"); process_video_UVC(in_video_path.c_str()); } else { printf("输入视频不支持\n"); } //省略 return 0; }
解码实现: 参考https://github.com/rockchip-linux/rknn-toolkit2/blob/master/rknpu2/examples/rknn_yolov5_demo/utils/mpp_decoder.cpp ,只修改了Init传入MppCodingType 参数。
int MppDecoder::Init(MppCodingType video_type, int fps, void *userdata) { MPP_RET ret = MPP_OK; this->userdata = userdata; this->fps = fps; this->last_frame_time_ms = 0; mpp_type = video_type; LOGD("mpi_dec_test start \n"); //省略 }
运行日志:
>>>>>处理输入视频 输入为UVC UVC初始化成功 找到UVC设备 开启UVC设备 UVC设备信息: DEVICE CONFIGURATION (1e4e:0109/[none]) --- Status: idle VideoControl: bcdUVC: 0x0100 VideoStreaming(1): bEndpointAddress: 129 Formats: MJPEGFormat(1) bits per pixel: 0 GUID: 4d4a5047000000000000000000000000 (MJPG) default frame: 1 aspect ratio: 0x0 interlace flags: 00 copy protect: 00 FrameDescriptor(1) capabilities: 00 size: 1280x720 bit rate: 442368000-442368000 max frame size: 1843200 default interval: 1/30 interval[0]: 1/30 FrameDescriptor(2) capabilities: 00 size: 800x600 bit rate: 230400000-230400000 max frame size: 960000 default interval: 1/30 interval[0]: 1/30 FrameDescriptor(3) capabilities: 00 size: 640x480 bit rate: 147456000-147456000 max frame size: 614400 default interval: 1/30 interval[0]: 1/30 FrameDescriptor(4) capabilities: 00 size: 352x288 bit rate: 48660480-48660480 max frame size: 202752 default interval: 1/30 interval[0]: 1/30 FrameDescriptor(5) capabilities: 00 size: 320x240 bit rate: 36864000-36864000 max frame size: 153600 default interval: 1/30 interval[0]: 1/30 StillFrameDescriptor bEndPointAddress: 00 wWidth(1) = 1280 wHeight(1) = 720 wWidth(2) = 800 wHeight(2) = 600 wWidth(3) = 640 wHeight(3) = 480 wWidth(4) = 352 wHeight(4) = 288 wWidth(5) = 320 wHeight(5) = 240 UncompressedFormat(2) bits per pixel: 16 GUID: 5955593200001000800000aa00389b71 (YUY2) default frame: 1 aspect ratio: 0x0 interlace flags: 00 copy protect: 00 FrameDescriptor(1) capabilities: 00 size: 1280x720 bit rate: 132710400-132710400 max frame size: 1843200 default interval: 1/9 interval[0]: 1/9 FrameDescriptor(2) capabilities: 00 size: 640x480 bit rate: 147456000-147456000 max frame size: 614400 default interval: 1/30 interval[0]: 1/30 FrameDescriptor(3) capabilities: 00 size: 800x600 bit rate: 153600000-153600000 max frame size: 960000 default interval: 1/20 interval[0]: 1/20 FrameDescriptor(4) capabilities: 00 size: 352x288 bit rate: 48660480-48660480 max frame size: 202752 default interval: 1/30 interval[0]: 1/30 FrameDescriptor(5) capabilities: 00 size: 320x240 bit rate: 36864000-36864000 max frame size: 153600 default interval: 1/30 interval[0]: 1/30 StillFrameDescriptor bEndPointAddress: 00 wWidth(1) = 1280 wHeight(1) = 720 wWidth(2) = 640 wHeight(2) = 480 wWidth(3) = 800 wHeight(3) = 600 wWidth(4) = 352 wHeight(4) = 288 wWidth(5) = 320 wHeight(5) = 240 END DEVICE CONFIGURATION UVC格式=MJPG 1280x720 30fps UVC流控信息: bmHint: 0001 bFormatIndex: 1 bFrameIndex: 1 dwFrameInterval: 333333 wKeyFrameRate: 0 wPFrameRate: 0 wCompQuality: 0 wCompWindowSize: 0 wDelay: 0 dwMaxVideoFrameSize: 1843200 dwMaxPayloadTransferSize: 3060 bInterfaceNumber: 1 开启自动曝光 ... ... full AE not supported, trying aperture priority mode 开启自动曝光成功 >>>>>设置视频解码器 mpi_dec_test start mpi_dec_test decoder test start mpp_type 8 >>>>>开始播放 >>>>>按任意按键退出播放 callback! frame_format = 7, width = 1280, height = 720, length = 44602, ptr = 0x3039 //然后阻塞在这里
对应的mpp日志:
Apr 29 09:43:10 lubancat mpp[698243]: mpp_info: mpp version: e34f0dd1 author: Herman Chen 2023-07-17 [hal_vp8e]: Fix crash on unsupport input format //然后阻塞在这里
本地保存的.jpeg文件: 在on_uvc_frame_out()中生成的,0.jpeg.zip mpi_dec_test: 使用保存的.jpeg文件进行解码,结果OK
root@lubancat:/home/mpp/build/linux/aarch64/test# ./mpi_dec_test -i 0.jpeg -w 1280 -h 720 -t 8 Apr 29 09:59:42 lubancat mpp[706083]: mpi_dec_utils: input file 0.jpeg size 48365 Apr 29 09:59:42 lubancat mpp[706083]: mpi_dec_utils: cmd parse result: Apr 29 09:59:42 lubancat mpp[706083]: mpi_dec_utils: input file name: 0.jpeg Apr 29 09:59:42 lubancat mpp[706083]: mpi_dec_utils: output file name: Apr 29 09:59:42 lubancat mpp[706083]: mpi_dec_utils: width : 1280 Apr 29 09:59:42 lubancat mpp[706083]: mpi_dec_utils: height : 720 Apr 29 09:59:42 lubancat mpp[706083]: mpi_dec_utils: type : 8 Apr 29 09:59:42 lubancat mpp[706083]: mpi_dec_utils: max frames : 0 Apr 29 09:59:42 lubancat mpp[706083]: mpi_dec_test: mpi_dec_test start Apr 29 09:59:42 lubancat mpp[706083]: mpp_info: mpp version: 4cc3fb25 author: leo 2024-04-26 fix[allocato r]: fix on invalid DMA heap allocator Apr 29 09:59:42 lubancat mpp[706083]: mpi_dec_test: 0x55962c2680 mpi_dec_test decoder test start w 1280 h 720 type 8 Apr 29 09:59:42 lubancat mpp[706083]: mpi_dec_test: 0x55962c2680 decoded frame 0 Apr 29 09:59:42 lubancat mpp[706083]: mpi_dec_test: decode 1 frames time 1 ms delay 1 ms fps 562.75 Apr 29 09:59:42 lubancat mpp[706083]: mpi_dec_test: test success max memory 0.00 MB
@HermanChen 佬来看一下
是的,jpeg 解码走 advanced 接口。
可以参考 rkmedia 的做法
https://github.com/Caesar-github/rkmedia/blob/master/src/rkmpp/mpp_decoder.cc
问题: 使用mpp解码UVC摄像头的视频流(MJPEG,1280*720,30fps),获取第一帧后,阻塞在Decode()的do...while循环中。 on_uvc_frame_out()中可以正常保存本地.jpeg文件,查看该文件图像格式为YUV422。
查看之前的issue(https://github.com/rockchip-linux/mpp/issues/309 https://github.com/rockchip-linux/mpp/issues/82 https://github.com/rockchip-linux/mpp/issues/171 ),以及mpi_dec_test.c例程中有如下内容。是否当前MJPEG的解码还是只能使用advanced接口?
开发板: RK3588,Debian11 mpp安装过程: install_log.txt mpp环境测试信息: test_log.txt
相关应用代码: main()->process_video_UVC()-->初始化解码器-->开始播放-->on_uvc_frame_out()->Decode()->mpp_decoder_frame_callback()
解码实现: 参考https://github.com/rockchip-linux/rknn-toolkit2/blob/master/rknpu2/examples/rknn_yolov5_demo/utils/mpp_decoder.cpp ,只修改了Init传入MppCodingType 参数。
运行日志:
对应的mpp日志:
本地保存的.jpeg文件: 在on_uvc_frame_out()中生成的,0.jpeg.zip mpi_dec_test: 使用保存的.jpeg文件进行解码,结果OK