0x4C

  • 2024-07-01
  • 加入了学习《[高精度实验室] ADC系列 3&4 : 误差与噪声》,观看 5 动手实验 - ADC 噪声

  • 2024-03-28
  • 回复了主题帖: 【Luckfox幸狐 RV1106 Linux 开发板使用】 SC3336拍摄

    LOI-T_T-o 发表于 2024-3-27 17:44 你好,新手不太懂,求教一下。我SDK编译好了,按你的教程,偏绿的图片也拍出来了,那个simple_venc_jpeg文 ... 这个就是SDK下的例程代码,直接修改就行,然后编译SDK就好了,编译完成后在对应的输出路径下就有最后的程序了 在你设置好SDK的编译环境之后进入/luckfox-pico/media/samples路径下执行make 然后同级目录下的out/bin里就有对应的输出程序

  • 2024-02-25
  • 发表了主题帖: 【Luckfox幸狐 RV1106 Linux 开发板使用】USB外接 USB摄像头 EC20

    本帖最后由 0x4C 于 2024-2-25 18:57 编辑 本篇实现USB HOST 下使用USB摄像头和4G模块 1、配置USB摄像头     涉及修改的东西有点多,也记录一下SDK的编译流程,这里重新拉SDK编译,参考链接SDK 环境部署 | LUCKFOX WIKI git clone https://gitee.com/LuckfoxTECH/luckfox-pico.git             安装交叉编译工具链: cd {SDK_PATH}/tools/linux/toolchain/arm-rockchip830-linux-uclibcgnueabihf/ source env_install_toolchain.sh   选择编译目标平台: ./build.sh lunch     我是用的板载的flash       开始编译: ./build.sh     编译后打包固件: ./build.sh firmware     得到基础的SDK包     进入设备树文件路径,修改 <SDK目录>/sysdrv/source/kernel/arch/arm/boot/dts/rv1106g-luckfox-pico-pro-max.dts 将USB配置为USB HOST模式 &usbdrd_dwc3 { status = "okay"; dr_mode = "host"; };          接下来修改内核配置 cd ~/SDK目录/sysdrv/source/kernel cp ./arch/arm/configs/luckfox_rv1106_linux_defconfig .config make ARCH=arm menuconfig         按下 ‘/’进行搜索。       进入搜索栏,输入搜索内容回车       显示搜索相关内容,按数字1-N进行选择。       依次搜索并使能以下选项 SCSI SCSI_UFSHCD BLK_DEV_SD USB_STORAGE USB_MASS_STORAGE USB_EHCI_HCD     SCSI           SCSI_UFSHCD           BLK_DEV_SD       USB_STORAGE     USB_MASS_STORAGE           USB_EHCI_HCD     退出界面前先save一下     保存config,回到SDK目录下,并重新编译内核。 make ARCH=arm savedefconfig cp defconfig arch/arm/configs/luckfox_rv1106_linux_defconfig cd ~/SDK目录 ./build.sh kernel     打包固件 ./build.sh firmware     下载固件到板子上(先按住板子上的boot键再按住reset键)     这里要注意一点,电脑的USB供电功率一般比较低,我这里使用开关电源额外提供5v电源输入,特别是后面做EC20联网的时候供电不足会直接导致板子重启,卡了我很长的时间     USB使用一个USB扩展坞扩展            之前的固件烧录后插入USB扩展坞:            接下来继续修改内核配置来支持USB摄像头:     在内核中启用UVC驱动,可通过搜索关键字"Webcam"     在搜索结果中找到并勾选"USB Video Class (UVC)",最后保存并退出。           编译内核  打包固件 下载固件(尝试用串口下载了一下固件,最大波特率下载,奇慢无比,同时有概率写入失败:)) 插入USB摄像头:       可以看见已经生成了对应的设备节点:       写个程序用V4L2抓个图吧: #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdio.h> #include <sys/ioctl.h> #include <stdlib.h> #include <linux/types.h> #include <linux/videodev2.h> #include <malloc.h> #include <math.h> #include <string.h> #include <sys/mman.h> #include <errno.h> #include <assert.h> #include <linux/videodev2.h> int main(int argc, char** argv) { printf("********************************start***************************************\n"); int cameraFd;/* 定义一个设备描述符 */ cameraFd = open("/dev/video21", O_RDWR); if(cameraFd < 0){ perror("video设备打开失败\n"); return -1; } else{ printf("video设备打开成功\n"); } printf("********************************1***************************************\n"); struct v4l2_capability vcap; ioctl(cameraFd, VIDIOC_QUERYCAP, &vcap); if (!(V4L2_CAP_VIDEO_CAPTURE & vcap.capabilities)) { perror("Error: No capture video device!\n"); return -1; } printf("********************************2***************************************\n"); struct v4l2_fmtdesc fmtdesc; fmtdesc.index = 0; fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; printf("摄像头支持所有格式如下:\n"); while(ioctl(cameraFd,VIDIOC_ENUM_FMT,&fmtdesc) == 0){ printf("v4l2_format%d:%s\n",fmtdesc.index,fmtdesc.description); fmtdesc.index++; } printf("********************************3***************************************\n"); struct v4l2_frmsizeenum frmsize; frmsize.index = 0; frmsize.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; // printf("MJPEG格式支持所有分辨率如下:\n"); // frmsize.pixel_format = V4L2_PIX_FMT_MJPEG; // while(ioctl(cameraFd,VIDIOC_ENUM_FRAMESIZES,&frmsize) == 0){ // printf("frame_size<%d*%d>\n",frmsize.discrete.width,frmsize.discrete.height); // frmsize.index++; // } printf("YUYV422格式支持所有分辨率如下:\n"); frmsize.pixel_format = V4L2_PIX_FMT_MJPEG; while(ioctl(cameraFd,VIDIOC_ENUM_FRAMESIZES,&frmsize) == 0){ printf("frame_size<%d*%d>\n",frmsize.discrete.width,frmsize.discrete.height); frmsize.index++; } printf("********************************4***************************************\n"); // struct v4l2_frmivalenum frmival; // frmival.index = 0; // frmival.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; // frmival.pixel_format = V4L2_PIX_FMT_MJPEG; // frmival.width = 640; // frmival.height = 480; // while(ioctl(cameraFd,VIDIOC_ENUM_FRAMEINTERVALS,&frmival) == 0){ // printf("frame_interval under frame_size <%d*%d> support %dfps\n",frmival.width,frmival.height,frmival.discrete.denominator / frmival.discrete.numerator); // frmival.index++; // } struct v4l2_frmivalenum frmival; frmival.index = 0; frmival.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; frmival.pixel_format = V4L2_PIX_FMT_MJPEG; frmival.width = 2592; frmival.height = 1944; while(ioctl(cameraFd,VIDIOC_ENUM_FRAMEINTERVALS,&frmival) == 0){ printf("frame_interval under frame_size <%d*%d> support %dfps\n",frmival.width,frmival.height,frmival.discrete.denominator / frmival.discrete.numerator); frmival.index++; } printf("********************************5***************************************\n"); // struct v4l2_format vfmt; // vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; // vfmt.fmt.pix.width = 640; // vfmt.fmt.pix.height = 480; // vfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG; // if(ioctl(cameraFd,VIDIOC_S_FMT,&vfmt) < 0){ // perror("设置格式失败\n"); // return -1; // } // // 检查设置参数是否生效 // if(ioctl(cameraFd,VIDIOC_G_FMT,&vfmt) < 0){ // perror("获取设置格式失败\n"); // return -1; // } // else if(vfmt.fmt.pix.width == 640 && vfmt.fmt.pix.height == 480 && vfmt.fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG){ // printf("设置格式生效,实际分辨率大小<%d * %d>,图像格式:Motion-JPEG\n",vfmt.fmt.pix.width,vfmt.fmt.pix.height); // } // else{ // printf("设置格式未生效\n"); // } struct v4l2_format vfmt; vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; vfmt.fmt.pix.width = 2592; vfmt.fmt.pix.height = 1944; vfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG; if(ioctl(cameraFd,VIDIOC_S_FMT,&vfmt) < 0){ perror("设置格式失败\n"); return -1; } // 检查设置参数是否生效 if(ioctl(cameraFd,VIDIOC_G_FMT,&vfmt) < 0){ perror("获取设置格式失败\n"); return -1; } else if(vfmt.fmt.pix.width == 2592 && vfmt.fmt.pix.height == 1944 && vfmt.fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG){ printf("设置格式生效,实际分辨率大小<%d * %d>,图像格式:Motion-JPEG\n",vfmt.fmt.pix.width,vfmt.fmt.pix.height); } else{ printf("设置格式未生效\n"); } printf("********************************6***************************************\n"); struct v4l2_requestbuffers reqbuf; reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; reqbuf.count = 3; //3个帧缓冲 reqbuf.memory = V4L2_MEMORY_MMAP; if(ioctl(cameraFd,VIDIOC_REQBUFS,&reqbuf) < 0){ perror("申请缓冲区失败\n"); return -1; } printf("********************************7***************************************\n"); // 将帧缓冲映射到进程地址空间 void *frm_base[3]; //映射后的用户空间的首地址 unsigned int frm_size[3]; struct v4l2_buffer buf; buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; // 将每一帧对应的缓冲区的起始地址保存在frm_base数组中,读取采集数据时,只需直接读取映射区即可 for(buf.index=0;buf.index<3;buf.index++){ ioctl(cameraFd, VIDIOC_QUERYBUF, &buf); frm_base[buf.index] = mmap(NULL,buf.length,PROT_READ | PROT_WRITE,MAP_SHARED,cameraFd,buf.m.offset); frm_size[buf.index] = buf.length; if(frm_base[buf.index] == MAP_FAILED){ perror("mmap failed\n"); return -1; } // 入队操作 if(ioctl(cameraFd,VIDIOC_QBUF,&buf) < 0){ perror("入队失败\n"); return -1; } } printf("********************************8***************************************\n"); enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (ioctl(cameraFd, VIDIOC_STREAMON, &type) < 0){ perror("开始采集失败\n"); return -1; } printf("********************************9***************************************\n"); struct v4l2_buffer readbuffer; readbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; readbuffer.memory = V4L2_MEMORY_MMAP; if(ioctl(cameraFd, VIDIOC_DQBUF, &readbuffer) < 0){ perror("读取帧失败\n"); } // 保存这一帧,格式为jpg FILE *file = fopen("v4l2_cap.jpg","w+"); fwrite(frm_base[readbuffer.index],buf.length,1,file); fclose(file); printf("********************************10***************************************\n"); // 停止采集 if (ioctl(cameraFd, VIDIOC_STREAMOFF, &type) < 0){ perror("停止采集失败\n"); return -1; } // 释放映射 for(int i=0;i<3;i++){ munmap(frm_base[i],frm_size[i]); } close(cameraFd); return 0; }     编译方法:       vi ~/.bashrc export PATH=<SDK Directory>/tools/linux/toolchain/arm-rockchip830-linux-uclibcgnueabihf/bin:$PATH source ~/.bashrc arm-rockchip830-linux-uclibcgnueabihf-gcc gpio.c -o gpio     放到开发板,执行后可以看到效果:                 2、配置EC20         这里的配置仅仅提供一个参考,参考的博客:Quectel EC20在嵌入式平台的适配 - 大窟窿 - 博客园 (cnblogs.com)      进入文件夹下,路径:luckfox-pico/sysdrv/source/kernel/drivers/usb/serial            打开添加如下内容,保存  { USB_DEVICE(0x05C6, 0x9215) }, /* Quectel EC20 */       注释掉冲突的vid以及pid设备,路径:luckfox-pico/sysdrv/source/kernel/drivers/usb/serial                修改路径:luckfox-pico/sysdrv/source/kernel/drivers/net/usb 添加零包处理(这个和usb 协议中的批量传输有关)For Linux Kernel Version newer than 2.6.34: 路径:luckfox-pico/sysdrv/source/kernel/drivers/usb/serial .reset_resume = usb_wwan_resume,      修改内核配置:               编译内核  打包固件 下载固件  可以看见其设备节点ttyUSB0~3       下载ppp2.4.7源码 https://github.com/ppp-project/ppp.git git clone -b ppp-2.4.7 https://github.com/ppp-project/ppp.git     交叉编译 ./configure make CC=/home/czm/luckfox-pico/tools/linux/toolchain/arm-rockchip830-linux-uclibcgnueabihf/bin/arm-rockchip830-linux-uclibcgnueabihf-gcc     编译完成后会在当前目录下生成chat/chat、 pppd/pppd、 pppdump/pppdump 和pppstats/pppstats 这四个文件,把这四个文件拷贝到文件系统中的/usr/bin目录下     最后移植ppp拨号脚本(附件提供),放到/etc/目录下即可     使用 pppd -v :            移植完成后 使用 pppd call quectel-ppp & 拨号            使用iperf测速   

  • 2024-02-21
  • 回复了主题帖: 【Luckfox幸狐 RV1106 Linux 开发板使用】opencv-mobile 使用

    LitchiCheng 发表于 2024-2-21 09:16 这个opencv-mobile库精简到只能用rockchip isp的视频流,也就是只能插官方的摄像头 也可以这么玩,不去调他的读流接口就行,用原生的mpp接口读完视频流,转opencv 的mat型数据就好啦,这样编解码就都是自己能够控制的。也就是只用opencv的处理部分

  • 2024-02-20
  • 发表了主题帖: 【Luckfox幸狐 RV1106 Linux 开发板使用】opencv-mobile 使用

    本帖最后由 0x4C 于 2024-2-20 14:05 编辑     看官方教程提供了opencv-mobile的使用,简单易用,浅尝一下     官方教程: opencv-mobile | LUCKFOX WIKI 1、基本测试     创建一个文件夹 mkdir opencvMobile cd opencvMobile/    下载并解压包,放到创建的文件夹下面     在文件夹下创建新的文件 vi CMakeLists.txt 添加内容,将 <SDK Directory> 修改为自己的 SDK 路径,如 /home/luckfox/luckfox-pico/  project(opencv-mobile-test) cmake_minimum_required(VERSION 3.5) set(CMAKE_CXX_STANDARD 11) SET(CMAKE_C_COMPILER "<SDK Directory>/tools/linux/toolchain/arm-rockchip830-linux-uclibcgnueabihf/bin/arm-rockchip830-linux-uclibcgnueabihf-gcc") SET(CMAKE_CXX_COMPILER "<SDK Directory>/tools/linux/toolchain/arm-rockchip830-linux-uclibcgnueabihf/bin/arm-rockchip830-linux-uclibcgnueabihf-g++") set(OpenCV_DIR "${CMAKE_CURRENT_SOURCE_DIR}/opencv-mobile-4.8.1-luckfox-pico/lib/cmake/opencv4") find_package(OpenCV REQUIRED) include_directories(${OpenCV_INCLUDE_DIRS}) add_executable(opencv-mobile-test main.cpp) target_link_libraries(opencv-mobile-test ${OpenCV_LIBS})     创建main vi main.cpp #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <unistd.h> // sleep() int main() { cv::VideoCapture cap; cap.set(cv::CAP_PROP_FRAME_WIDTH, 320); cap.set(cv::CAP_PROP_FRAME_HEIGHT, 240); cap.open(0); const int w = cap.get(cv::CAP_PROP_FRAME_WIDTH); const int h = cap.get(cv::CAP_PROP_FRAME_HEIGHT); fprintf(stderr, "%d x %d\n", w, h); cv::Mat bgr[9]; for (int i = 0; i < 9; i++) { cap >> bgr[i]; sleep(1); } cap.release(); // combine into big image { cv::Mat out(h * 3, w * 3, CV_8UC3); bgr[0].copyTo(out(cv::Rect(0, 0, w, h))); bgr[1].copyTo(out(cv::Rect(w, 0, w, h))); bgr[2].copyTo(out(cv::Rect(w * 2, 0, w, h))); bgr[3].copyTo(out(cv::Rect(0, h, w, h))); bgr[4].copyTo(out(cv::Rect(w, h, w, h))); bgr[5].copyTo(out(cv::Rect(w * 2, h, w, h))); bgr[6].copyTo(out(cv::Rect(0, h * 2, w, h))); bgr[7].copyTo(out(cv::Rect(w, h * 2, w, h))); bgr[8].copyTo(out(cv::Rect(w * 2, h * 2, w, h))); cv::imwrite("out.jpg", out); } return 0; }     编译 mkdir build cd build cmake .. make     文件夹结构:       在build下就生成了可执行程序     将整个文件夹复制到开发板的root路径下       执行 ./opencv-mobile-test     得到图像   2、opencv4.9支持     github上已经更新到opencv4.9了,浅尝一下区别 nihui/opencv-mobile: The minimal opencv for Android, iOS, ARM Linux, Windows, Linux, MacOS, WebAssembly (github.com)     下载对应的包     解压后也放到刚才的文件夹下,删除build文件夹     修改camkelists.txt             其余步骤相同     使用的做设备 luckfox-pico max + sc3336     4.8.1下的输出 # ./opencv-mobile-test this device is not whitelisted for jpeg decoder cvi this device is not whitelisted for jpeg decoder cvi this device is not whitelisted for jpeg decoder cvi [ 430.140795] stream_cif_mipi_id0: s_power 1, entity use_count 1 devpath = /dev/video11 driver = rkisp_v7 card = rkisp_mainpath bus_info = platform:rkisp-vir0 version = 20000 capabilities = 84201000 device_caps = 4201000 fmt = UYVY 4:2:2 59565955 fmt = Y/CbCr 4:2:2 3631564e fmt = Y/CrCb 4:2:2 3136564e fmt = Y/CrCb 4:2:0 3132564e size = 32 x 16 ~ 2304 x 1296 (+8 +8) fmt = Y/CbCr 4:2:0 3231564e fmt = Y/CrCb 4:2:0 (N-C) 31324d4e fmt = Y/CbCr 4:2:0 (N-C) 32314d4e rkaiq log level ff0 [ 430.324185] stream_cif_mipi_id0: open video, entity use_countt 2 [ 430.324391] stream_cif_mipi_id1: open video, entity use_countt 1 /dev/video11 does not support changing fps rga_api version 1.9.1_[0] [ 430.338940] rkisp rkisp-vir0: first params buf queue [ 430.341360] rkisp_hw ffa00000.rkisp: set isp clk = 198000000Hz [ 430.341486] rkcif-mipi-lvds: sditf_reinit_mode, mode->rdbk_mode 0, mode->name rkisp-vir0, link_mode 1 [ 430.343320] rkcif-mipi-lvds: stream320 x 240 [0] start streaming [ 430.343452] rockchip-mipi-csi2 ffa20000.mipi-csi2: stream on, src_sd: baffe55e, sd_name:rockchip-csi2-dphy0 [ 430.343466] rockchip-mipi-csi2 ffa20000.mipi-csi2: stream ON [ 430.343542] rockchip-csi2-dphy0: dphy0, data_rate_mbps 506 [ 430.343574] rockchip-csi2-dphy csi2-dphy0: csi2_dphy_s_stream stream on:1, dphy0 [ 430.343587] rockchip-csi2-dphy csi2-dphy0: csi2_dphy_s_stream stream on:1, dphy0 [ 439.456220] rkcif-mipi-lvds: stream[0] start stopping, total mode 0x2, cur 0x2 [ 439.478307] rockchip-mipi-csi2 ffa20000.mipi-csi2: stream off, src_sd: baffe55e, sd_name:rockchip-csi2-dphy0 [ 439.478359] rockchip-mipi-csi2 ffa20000.mMessageParser process loop exit! ipi-csi2: stream OFF [ 439.480935] rockchip-csi2-dphy csi2-dphy0: csi2_dphy_s_stream_stop stream stop, dphy0 [ 439.480973] rockchip-csi2-dphy csi2-dphy0: csi2_dphy_s_stream stream on:0, dpmpp[645]: mpp_buffer: mpi_buf_id = 136, dma_buf_fd = 5 mpp[645]: mpp: mClinetFd 7 open ok attr.chan_id 0 [ 439.481019] rockchip-csi2-dphy csi2-dphy0: csi2_dphy_s_stream stream on:0, dphy0 [ 439.481238] rkcif-mipi-lvds: stream[0] stopping finished, dma_en 0x0 [ 439.496563] stream_cif_mipi_id1: close video, entity use_count# # 0 [ 439.496651] stream_cif_mipi_id0: close video, entity use_count 1 [ 439.497314] stream_cif_mipi_id0: s_power 0, entity use_count 0 [ 439.516121] mpp_vcodec: 44: num_chan = 0 [ 439.516219] mpp_vcodec: 103: chan_entry->handle 65722eb9, enc 65722eb9 [ 439.516826] 755: MPP_ENC_SET_CFG in [ 439.516855] 524: MPP_ENC_SET_RC_CFG bps 0 [0 : 0] fps [1:1] gop 1     4.9.0的输出 # ./opencv-mobile-test this device is not whitelisted for jpeg decoder cvi this device is not whitelisted for jpeg decoder cvi this device is not whitelisted for jpeg decoder cvi this device is not whitelisted for capture cvi this device is not whitelisted for capture cvi this device is not whitelisted for capture cvi this device is not whitelisted for capture cvi this device is not whitelisted for capture cvi this device is not whitelisted for capture cvi this device is not whitelisted for capture cvi this device is not whitelisted for capture v4l2 awispapi [ 1681.086395] stream_cif_mipi_id0: s_power 1, entity use_count 1 devpath = /dev/video11 driver = rkisp_v7 card = rkisp_mainpath bus_info = platform:rkisp-vir0 version = 20000 capabilities = 84201000 device_caps = 4201000 fmt = UYVY 4:2:2 59565955 fmt = Y/CbCr 4:2:2 3631564e fmt = Y/CrCb 4:2:2 3136564e fmt = Y/CrCb 4:2:0 3132564e size = 32 x 16 ~ 2304 x 1296 (+8 +8) fmt = Y/CbCr 4:2:0 3231564e fmt = Y/CrCb 4:2:0 (N-C) 31324d4e fmt = Y/CbCr 4:2:0 (N-C) 32314d4e rkaiq log level ff0 [ 1681.269800] stream_cif_mipi_id0: open video, entity use_countt 2 [ 1681.270001] stream_cif_mipi_id1: open video, entity use_countt 1 /dev/video11 does not support changing fps rga_api version 1.9.1_[0] [ 1681.284710] rkisp rkisp-vir0: first params buf queue [ 1681.287253] rkisp_hw ffa00000.rkisp: set isp clk = 198000000Hz [ 1681.287302] rkcif-mipi-lvds: sditf_reinit_mode, mode->rdbk_mode 0, mode->name rkisp-vir0, link_mode 1 [ 1681.289425] rkcif-mipi-lvds: stream[0] start st320 x 240 reaming [ 1681.289596] rockchip-mipi-csi2 ffa20000.mipi-csi2: stream on, src_sd: baffe55e, sd_name:rockchip-csi2-dphy0 [ 1681.289611] rockchip-mipi-csi2 ffa20000.mipi-csi2: stream ON [ 1681.289661] rockchip-csi2-dphy0: dphy0, data_rate_mbps 506 [ 1681.289691] rockchip-csi2-dphy csi2-dphy0: csi2_dphy_s_stream stream on:1, dphy0 [ 1681.289703] rockchip-csi2-dphy csi2-dphy0: csi2_dphy_s_stream stream on:1, dphy0 [ 1690.398035] rkcif-mipi-lvds: stream[0] start stopping, total mode 0x2, cur 0x2 [ 1690.424739] rockchip-mipi-csi2 ffa20000.mipi-csi2: stream off, src_sd: baffe55e, sd_name:rockchip-csi2-dphy0 [ 1690.424791] rockchip-mipi-MessageParser process loop exit! csi2 ffa20000.mipi-csi2: stream OFF [ 1690.427185] rockchip-csi2-dphy csi2-dphy0: csi2_dphy_s_stream_stop stream stop, dphy0 [ 1690.427235] rockchip-csi2-dphy csi2-dphmpp[740]: mpp_buffer: mpi_buf_id = 136, dma_buf_fd = 5 ympp[740]: mpp: mClinetFd 7 open ok attr.chan_id 0 0: csi2_dphy_s_stream stream on:0, dphy0 [ 1690.427297] rockchip-csi2-dphy csi2-dphy0: csi2_dphy_s_stream stream on:0ioctl IOCTL_FREE_IOMMU_ADDR failed 9 Bad file descriptor ioctl ION_IOC_FREE failed 9 Bad file descriptor , dphy0 [ 1690.427546] rkcif# -mipi-lvds: stream[0] stopping finished, dma_en 0x0 [ 1690.439913] stream_cif_mipi_id1: close video, entity use_count 0 [ 1690.440016] stream_cif_mipi_id0: close video, entity use_count 1 [ 1690.440679] stream_cif_mipi_id0: s_power 0, entity use_count 0 [ 1690.459025] mpp_vcodec: 44: num_chan = 0 [ 1690.459126] mpp_vcodec: 103: chan_entry->handle 68c79227, enc 68c79227 [ 1690.459735] 755: MPP_ENC_SET_CFG in [ 1690.459764] 524: MPP_ENC_SET_RC_CFG bps 0 [0 : 0] fps [1:1] gop 1 3、寻找最大色块 #include <iostream> #include <vector> // 添加 vector 头文件 #include <opencv2/opencv.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> using namespace cv; int main() { Mat image = imread("test.jpg"); // 替换为您的图像路径 Mat hsvImage; cvtColor(image, hsvImage, COLOR_BGR2HSV); // 定义红色范围 Scalar lowerRed = Scalar(0, 100, 100); Scalar upperRed = Scalar(10, 255, 255); // 提取红色物体 Mat redMask; inRange(hsvImage, lowerRed, upperRed, redMask); // 查找红色物体的轮廓 std::vector<std::vector<Point>> contours; findContours(redMask, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE); // 绘制红色物体的轮廓并计算中心坐标 for (const auto& contour : contours) { drawContours(image, std::vector<std::vector<Point>>{contour}, -1, Scalar(0, 0, 255), 2); // 计算轮廓的中心坐标 Moments mu = moments(contour, false); Point2f center = Point2f(mu.m10 / mu.m00, mu.m01 / mu.m00); // 在图像上绘制中心坐标 circle(image, center, 5, Scalar(255, 255, 255), -1); // 输出中心坐标 std::cout << "Red object center coordinates: (" << center.x << ", " << center.y << ")" << std::endl; } // 显示结果 imshow("Red Objects", image); waitKey(0); return 0; }     将测试图片放到和程序同一路径下,执行 ./opencv-mobile-test      输出结果: # ./opencv-mobile-test this device is not whitelisted for jpeg decoder cvi this device is not whitelisted for jpeg decoder cvi this device is not whitelisted for jpeg decoder cvi Red object center coordinates: (nan, nan) Red object center coordinates: (nan, nan) Red object center coordinates: (245.15, 156.34) imshow save image to Red Objects.pngwaitKey stub#      

  • 回复了主题帖: 【Luckfox幸狐 RV1106 Linux 开发板使用】 SC3336拍摄

    wangerxian 发表于 2024-2-20 17:39 专用的摄像头要插在板子的哪? CSI Camera | LUCKFOX WIKI

  • 回复了主题帖: 【Luckfox幸狐 RV1106 Linux 开发板使用】 SC3336拍摄

    LitchiCheng 发表于 2024-2-20 09:37 看来都买了那个专用的摄像头,我还是白嫖用USB摄像头 主要是测试跑压缩这块要方便一点

  • 回复了主题帖: 【Luckfox幸狐 RV1106 Linux 开发板使用】 SC3336拍摄

    nmg 发表于 2024-2-20 09:09 实际的效果那里没有,是不是视频上传忘记点击名称,插入啦? 第一次用,不太懂 哈哈哈 重新添加了

  • 发表了主题帖: 【Luckfox幸狐 RV1106 Linux 开发板使用】 SC3336拍摄

    本帖最后由 0x4C 于 2024-2-20 11:39 编辑 Luckfox的这块RV1106开发板是对SC3336进行了支持的,同时RV1106有着强大硬编码能力 本篇主要是实现使用SC3336来拍图,同时将图像进行JPEG硬编码然后通过网络发送出去   1、基本JPEG压缩测试     源码路径:/luckfox-pico/media/samples/simple_venc_jpeg.c     测试时用串口调试,连接网线到路由器来传输文件     串口连接:            插上网线,ifconfig看下设备的IP地址       键盘WIN+E,输入设备的IP地址:192.168.110.90     用户名为 root,密码为 luckfox       连接后就可以看见板子的文件了       默认的SDK编译完成后,在/oem/usr/bin下已经有测试的例程程序了            运行前先关闭开机自启的IPC程序 killall rkipc     输入  ./simple_venc_jpeg -w 1920 -h 1080 运行程序     在命令行每回车一次就会拍一张图片,对应的图片会保存在 /tmp/*.jpeg 下            最后输入 quit 程序结束运行,然后将图片拷贝到电脑上查看     打开拍摄的图片我们会发现图片的颜色可能会偏色,显示不正常,我们需要修改程序如下(代码段的main(){}部分): int main(int argc, char *argv[]) { RK_S32 s32Ret = RK_FAILURE; RK_U32 u32Width = 1920; RK_U32 u32Height = 1080; RK_CODEC_ID_E enCodecType = RK_VIDEO_ID_JPEG; RK_CHAR *pCodecName = "JPEG"; RK_S32 s32chnlId = 0; int c; while ((c = getopt(argc, argv, optstr)) != -1) { switch (c) { case 'w': u32Width = atoi(optarg); break; case 'h': u32Height = atoi(optarg); break; case 'I': s32chnlId = atoi(optarg); break; case '?': default: print_usage(argv[0]); return 0; } } printf("#CodecName:%s\n", pCodecName); printf("#Resolution: %dx%d\n", u32Width, u32Height); printf("#CameraIdx: %d\n\n", s32chnlId); printf("#Frame Count to save: %d\n", g_s32FrameCnt); char *iq_dir = "/etc/iqfiles"; if (iq_dir) { #ifdef RKAIQ printf("ISP IQ file path: %s\n\n", iq_dir); SAMPLE_COMM_ISP_Init(0, RK_AIQ_WORKING_MODE_NORMAL, 0, iq_dir); SAMPLE_COMM_ISP_Run(0); printf("ISP RUN!\n"); #endif } signal(SIGINT, sigterm_handler); if (RK_MPI_SYS_Init() != RK_SUCCESS) { RK_LOGE("rk mpi sys init fail!"); goto __FAILED; } vi_dev_init(); vi_chn_init(s32chnlId, u32Width, u32Height); // venc init test_venc_init(0, u32Width, u32Height, enCodecType); MPP_CHN_S stSrcChn, stDestChn; // bind vi to venc stSrcChn.enModId = RK_ID_VI; stSrcChn.s32DevId = 0; stSrcChn.s32ChnId = s32chnlId; stDestChn.enModId = RK_ID_VENC; stDestChn.s32DevId = 0; stDestChn.s32ChnId = 0; printf("====RK_MPI_SYS_Bind vi0 to venc0====\n"); s32Ret = RK_MPI_SYS_Bind(&stSrcChn, &stDestChn); if (s32Ret != RK_SUCCESS) { RK_LOGE("bind 0 ch venc failed"); goto __FAILED; } VENC_RECV_PIC_PARAM_S stRecvParam; pthread_t main_thread; pthread_create(&main_thread, NULL, GetMediaBuffer0, NULL); char cmd[64]; VENC_JPEG_PARAM_S stJpegParam; stJpegParam.u32Qfactor = 77; RK_MPI_VENC_SetJpegParam(0, &stJpegParam); while (!quit) { fgets(cmd, sizeof(cmd), stdin); printf("#Input cmd:%s\n", cmd); if (strstr(cmd, "quit")) { printf("#Get 'quit' cmd!\n"); quit = true; break; } memset(&stRecvParam, 0, sizeof(VENC_RECV_PIC_PARAM_S)); stRecvParam.s32RecvPicNum = 1; s32Ret = RK_MPI_VENC_StartRecvFrame(0, &stRecvParam); if (s32Ret) { printf("RK_MPI_VENC_StartRecvFrame failed!\n"); break; } usleep(30000); // sleep 30 ms. } sleep(1); pthread_join(&main_thread, NULL); s32Ret = RK_MPI_SYS_UnBind(&stSrcChn, &stDestChn); if (s32Ret != RK_SUCCESS) { RK_LOGE("RK_MPI_SYS_UnBind fail %x", s32Ret); } s32Ret = RK_MPI_VI_DisableChn(0, s32chnlId); RK_LOGE("RK_MPI_VI_DisableChn %x", s32Ret); s32Ret = RK_MPI_VENC_StopRecvFrame(0); if (s32Ret != RK_SUCCESS) { return s32Ret; } s32Ret = RK_MPI_VENC_DestroyChn(0); if (s32Ret != RK_SUCCESS) { RK_LOGE("RK_MPI_VDEC_DestroyChn fail %x", s32Ret); } s32Ret = RK_MPI_VI_DisableDev(0); RK_LOGE("RK_MPI_VI_DisableDev %x", s32Ret); __FAILED: RK_LOGE("test running exit:%d", s32Ret); RK_MPI_SYS_Exit(); #ifdef RKAIQ SAMPLE_COMM_ISP_Stop(0); #endif return 0; }     重新编译后下载到板子上,重新测试就可以看到正常的图片了           左修改前,右修改后  可以看见拍摄的差异还是很明显的 2、图像VI和JPEG压缩非绑定     例程中图像输入后就直接送入JPEG压缩了,但是我们不总是希望这样。我们希望还可以对输入的图像(例如这里输入的YUV图像)进行自己的处理,处理之后再进行压缩,这里提供一种我测试的方法。     新建一个文件用来测试代码 vi_jpeg.c     修改media下的Makefile文件,添加 vi_jpeg: vi_jpeg.c @$(SAMPLE_CC) $^ -o $@ $(SAMPLE_CFLAGS) $(LD_FLAGS)            代码参考/luckfox-pico/media/samples/test/sample_camera_stresstest.c       /* * Copyright 2021 Rockchip Electronics Co. LTD * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifdef __cplusplus #if __cplusplus extern "C" { #endif #endif /* End of #ifdef __cplusplus */ #include <assert.h> #include <errno.h> #include <fcntl.h> #include <getopt.h> #include <pthread.h> #include <semaphore.h> #include <signal.h> #include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/prctl.h> #include <time.h> #include <unistd.h> #include "sample_comm.h" #define FILE_TEST typedef struct _rkMpiCtx { SAMPLE_VI_CTX_S vi; SAMPLE_VPSS_CTX_S vpss; SAMPLE_VENC_CTX_S venc; } SAMPLE_MPI_CTX_S; static int g_loopcount = 1; static int g_framcount = 200; static COMPRESS_MODE_E g_compressMode = COMPRESS_AFBC_16x16; static SAMPLE_MPI_CTX_S *g_ctx; static bool quit = false; static void sigterm_handler(int sig) { fprintf(stderr, "signal %d\n", sig); g_loopcount = 0; quit = true; } static RK_CHAR optstr[] = "?::n:l:c:f:e:"; static const struct option long_options[] = { {"index", required_argument, NULL, 'n'}, {"loop_count", required_argument, NULL, 'l'}, {"frame_count", required_argument, NULL, 'c'}, {"pixel_format", optional_argument, NULL, 'f'}, {NULL, 0, NULL, 0}, }; uint8_t encodingType = 0; /* 选择编码类型 */ /****************************************************************************** * function : show usage ******************************************************************************/ static void print_usage(const RK_CHAR *name) { printf("Usage : %s -n <index> -l <loop count> -c <frame count> -f <pixel format>\n", name); printf("index:\n"); printf("\t 0)isp stresstest(IqFileDir: /etc/iqfiles ~ /usr/share/iqfiles)\n"); printf("\t 1)venc stresstest(H264 ~ H265)\n"); printf("\t 2)venc stresstest(1x ~ 0.5x resolution)\n"); printf("\t 3)vi->vps->venc stresstest\n"); printf("pixel format:\n"); printf("\t nv12) no compress\n"); printf("\t afbc) compress\n"); } /****************************************************************************** * function : vi thread ******************************************************************************/ static void *vi_get_stream(void *pArgs) { SAMPLE_VI_CTX_S *ctx = (SAMPLE_VI_CTX_S *)(pArgs); RK_S32 s32Ret = RK_FAILURE; char name[256] = {0}; FILE *fp = RK_NULL; void *pData = RK_NULL; RK_S32 loopCount = 0; if (ctx->dstFilePath) { snprintf(name, sizeof(name), "/%s/vi_%d.bin", ctx->dstFilePath, ctx->s32DevId); fp = fopen(name, "wb"); if (fp == RK_NULL) { printf("chn %d can't open %s file !\n", ctx->s32DevId, ctx->dstFilePath); quit = true; return RK_NULL; } } while (!quit) { s32Ret = SAMPLE_COMM_VI_GetChnFrame(ctx, &pData); if (s32Ret == RK_SUCCESS) { if (ctx->stViFrame.stVFrame.u64PrivateData <= 0) { // SAMPLE_COMM_VI_ReleaseChnFrame(ctx); // continue; } // exit when complete if (ctx->s32loopCount > 0) { if (loopCount >= ctx->s32loopCount) { SAMPLE_COMM_VI_ReleaseChnFrame(ctx); quit = true; break; } } if (fp) { fwrite(pData, 1, ctx->stViFrame.stVFrame.u64PrivateData, fp); fflush(fp); } RK_LOGE( "SAMPLE_COMM_VI_GetChnFrame DevId %d ok:data %p size:%llu loop:%d seq:%d " "pts:%lld ms\n", ctx->s32DevId, pData, ctx->stViFrame.stVFrame.u64PrivateData, loopCount, ctx->stViFrame.stVFrame.u32TimeRef, ctx->stViFrame.stVFrame.u64PTS / 1000); SAMPLE_COMM_VI_ReleaseChnFrame(ctx); loopCount++; } usleep(1000); } if (fp) fclose(fp); return RK_NULL; } /****************************************************************************** * function : vpss thread ******************************************************************************/ static RK_U8 data[2560 * 1520 * 2]; static RK_U8 data0[2560 * 1520 * 2]; static RK_U8 data1[2560 * 1520 * 2]; static void *vpss_get_stream(void *pArgs) { SAMPLE_VPSS_CTX_S *ctx = (SAMPLE_VPSS_CTX_S *)(pArgs); RK_S32 s32Ret = RK_FAILURE; char name[256] = {0}; FILE *fp = RK_NULL; FILE *fbc0 = RK_NULL; FILE *fbc1 = RK_NULL; void *pData = RK_NULL; RK_S32 loopCount = 0; VIDEO_FRAME_INFO_S stChnFrameInfos; if (ctx->dstFilePath) { snprintf(name, sizeof(name), "/%s/vpss_%d.yuv", ctx->dstFilePath, ctx->s32ChnId); fp = fopen(name, "wb"); if (fp == RK_NULL) { printf("chn %d can't open %s file !\n", ctx->s32ChnId, ctx->dstFilePath); quit = true; return RK_NULL; } } #if 0 fbc0 = fopen("/data/vpss_1280_760_fbc.bin", "r"); if (fbc0 == RK_NULL) { printf("can't open /data/vpss_1280_760_fbc.bin file !\n"); quit = true; return RK_NULL; } fbc1 = fopen("/data/vpss_2560_1520_fbc.bin", "r"); if (fbc1 == RK_NULL) { printf("can't open /data/vpss_2560_1520_fbc.bin file !\n"); quit = true; return RK_NULL; } fread(data0, 1, 1552384, fbc0); fread(data1, 1, 6164480, fbc1); #endif while (!quit) { s32Ret = SAMPLE_COMM_VPSS_GetChnFrame(ctx, &pData); if (s32Ret == RK_SUCCESS) { if (ctx->stChnFrameInfos.stVFrame.u64PrivateData <= 0) { continue; } #if 0 // exit when complete if (ctx->s32loopCount > 0) { if (loopCount >= ctx->s32loopCount) { SAMPLE_COMM_VPSS_ReleaseChnFrame(ctx); quit = true; break; } } #endif // if (fp) { // fwrite(pData, 1, ctx->stChnFrameInfos.stVFrame.u64PrivateData, fp); // fflush(fp); // } #if 1 // SAMPLE_COMM_VENC_SendStream( // &g_ctx->venc, pData, ctx->stChnFrameInfos.stVFrame.u32Width, // ctx->stChnFrameInfos.stVFrame.u32Height, // ctx->stChnFrameInfos.stVFrame.u64PrivateData, g_compressMode); s32Ret = RK_MPI_VENC_SendFrame(g_ctx->venc.s32ChnId, &ctx->stChnFrameInfos.stVFrame, -1); if (s32Ret != RK_SUCCESS) { RK_LOGE("RK_MPI_VENC_SendFrame fail %x", s32Ret); } #else if (ctx->stChnFrameInfos.stVFrame.u32Width == 1280) { SAMPLE_COMM_VENC_SendStream( &g_ctx->venc, data0, ctx->stChnFrameInfos.stVFrame.u32Width, ctx->stChnFrameInfos.stVFrame.u32Height, 1552384, g_compressMode); } else if (ctx->stChnFrameInfos.stVFrame.u32Width == 2560) { SAMPLE_COMM_VENC_SendStream( &g_ctx->venc, data1, ctx->stChnFrameInfos.stVFrame.u32Width, ctx->stChnFrameInfos.stVFrame.u32Height, 6164480, g_compressMode); } #endif printf("SAMPLE_COMM_VPSS_GetChnFrame DevId %d ok:data %p size:%llu loop:%d " "seq:%d " "pts:%lld ms\n", ctx->s32GrpId, pData, ctx->stChnFrameInfos.stVFrame.u64PrivateData, loopCount, ctx->stChnFrameInfos.stVFrame.u32TimeRef, ctx->stChnFrameInfos.stVFrame.u64PTS / 1000); SAMPLE_COMM_VPSS_ReleaseChnFrame(ctx); loopCount++; } usleep(1000); } if (fp) fclose(fp); return RK_NULL; } static void *vpss_send_stream(void *pArgs) { SAMPLE_VPSS_CTX_S *ctx = (SAMPLE_VPSS_CTX_S *)(pArgs); RK_S32 s32Ret = RK_FAILURE; FILE *fbc = RK_NULL; void *pData = RK_NULL; RK_S32 loopCount = 0; fbc = fopen("/data/vpss_2560_1520_fbc.bin", "r"); if (fbc == RK_NULL) { printf("can't open /data/vpss_2560_1520_fbc.bin file !\n"); quit = true; return RK_NULL; } fread(data, 1, 6164480, fbc); while (!quit) { // exit when complete if (ctx->s32loopCount > 0) { if (loopCount >= ctx->s32loopCount) { quit = true; break; } } SAMPLE_COMM_VPSS_SendStream(&g_ctx->vpss, data, 2560, 1520, 6164480, g_compressMode); loopCount++; usleep(20000); } if (fbc) fclose(fbc); return RK_NULL; } /****************************************************************************** * function : venc thread ******************************************************************************/ static void *venc_get_stream(void *pArgs) { SAMPLE_VENC_CTX_S *ctx = (SAMPLE_VENC_CTX_S *)(pArgs); RK_S32 s32Ret = RK_FAILURE; char name[256] = {0}; FILE *fp = RK_NULL; void *pData = RK_NULL; RK_S32 loopCount = 0; if (ctx->dstFilePath) { if(3 != encodingType) { snprintf(name, sizeof(name), "/%s/venc_%d.bin", ctx->dstFilePath, ctx->s32ChnId); fp = fopen(name, "wb"); if (fp == RK_NULL) { printf("chn %d can't open %s file !\n", ctx->s32ChnId, ctx->dstFilePath); quit = true; return RK_NULL; } } } while (!quit) { s32Ret = SAMPLE_COMM_VENC_GetStream(ctx, &pData); if (s32Ret == RK_SUCCESS) { // exit when complete if (ctx->s32loopCount > 0) { if (loopCount >= ctx->s32loopCount) { SAMPLE_COMM_VENC_ReleaseStream(ctx); quit = true; break; } // if (fp) // { // fwrite(pData, 1, ctx->stFrame.pstPack->u32Len, fp); // fflush(fp); // } if(3 != encodingType) { fwrite(pData, 1, ctx->stFrame.pstPack->u32Len, fp); fflush(fp); } else { static uint16_t pictureIndex = 0; snprintf(name, sizeof(name), "/%s/venc_%d.jpeg", ctx->dstFilePath, pictureIndex); fp = fopen(name, "wb"); if (fp == RK_NULL) { printf("chn %d can't open %s file !\n", ctx->s32ChnId, ctx->dstFilePath); quit = true; return RK_NULL; } fwrite(pData, 1, ctx->stFrame.pstPack->u32Len, fp); fflush(fp); pictureIndex++; printf("pictureIndex = %d",pictureIndex); } } PrintStreamDetails(ctx->s32ChnId, ctx->stFrame.pstPack->u32Len); RK_LOGD("chn:%d, loopCount:%d wd:%d\n", ctx->s32ChnId, loopCount, ctx->stFrame.pstPack->u32Len); SAMPLE_COMM_VENC_ReleaseStream(ctx); loopCount++; } usleep(1000); } if (fp) fclose(fp); return RK_NULL; } int SAMPLE_CAMERA_VENC_Stresstest(SAMPLE_MPI_CTX_S *ctx, RK_S32 mode) { RK_S32 s32Ret = RK_FAILURE; int video_width = 2560; int video_height = 1520; int venc_width = 2560; int venc_height = 1520; RK_CHAR *pOutPathVenc = NULL; RK_CHAR *iq_file_dir = "/etc/iqfiles"; RK_CHAR *pCodecName = "H264"; CODEC_TYPE_E enCodecType = RK_CODEC_TYPE_H264; VENC_RC_MODE_E enRcMode = VENC_RC_MODE_H264CBR; RK_S32 s32BitRate = 10 * 1024; RK_S32 s32CamId = 0; MPP_CHN_S stSrcChn, stDestChn; RK_S32 s32loopCnt = g_framcount; RK_S32 i; RK_BOOL bMultictx = RK_FALSE; quit = false; pthread_t vpss_thread_id[2]; if (mode == 1) { s32loopCnt = -1; } pOutPathVenc ="tmp"; printf("#CameraIdx: %d\n", s32CamId); printf("#CodecName:%s\n", pCodecName); printf("#Output Path: %s\n", pOutPathVenc); if (iq_file_dir) { #ifdef RKAIQ printf("#Rkaiq XML DirPath: %s\n", iq_file_dir); printf("#bMultictx: %d\n\n", bMultictx); rk_aiq_working_mode_t hdr_mode = RK_AIQ_WORKING_MODE_NORMAL; SAMPLE_COMM_ISP_Init(s32CamId, hdr_mode, bMultictx, iq_file_dir); SAMPLE_COMM_ISP_Run(s32CamId); #endif } if (RK_MPI_SYS_Init() != RK_SUCCESS) { goto __FAILED; } MB_POOL pool = MB_INVALID_POOLID; MB_POOL_CONFIG_S stMbPoolCfg; memset(&stMbPoolCfg, 0, sizeof(MB_POOL_CONFIG_S)); stMbPoolCfg.u64MBSize = video_width * video_height * 2; stMbPoolCfg.u32MBCnt = 10; stMbPoolCfg.enAllocType = MB_ALLOC_TYPE_DMA; pool = RK_MPI_MB_CreatePool(&stMbPoolCfg); ctx->vpss.pool = ctx->venc.pool = pool; // Init VI[0] ctx->vi.u32Width = video_width; ctx->vi.u32Height = video_height; ctx->vi.s32DevId = s32CamId; ctx->vi.u32PipeId = ctx->vi.s32DevId; ctx->vi.s32ChnId = 2; // rk3588 mainpath:0 selfpath:1 fbcpath:2 ctx->vi.stChnAttr.stIspOpt.u32BufCount = 4; ctx->vi.stChnAttr.stIspOpt.enMemoryType = VI_V4L2_MEMORY_TYPE_DMABUF; ctx->vi.stChnAttr.u32Depth = 1; ctx->vi.stChnAttr.enPixelFormat = RK_FMT_YUV420SP; ctx->vi.stChnAttr.enCompressMode = g_compressMode; ctx->vi.stChnAttr.stFrameRate.s32SrcFrameRate = -1; ctx->vi.stChnAttr.stFrameRate.s32DstFrameRate = -1; if (g_compressMode == COMPRESS_MODE_NONE) { ctx->vi.s32ChnId = 0; } SAMPLE_COMM_VI_CreateChn(&ctx->vi); // Init VPSS[0] ctx->vpss.s32GrpId = 0; ctx->vpss.s32ChnId = 0; // RGA_device: VIDEO_PROC_DEV_RGA GPU_device: VIDEO_PROC_DEV_GPU ctx->vpss.enVProcDevType = VIDEO_PROC_DEV_RGA; // ctx->vpss.enVProcDevType = VIDEO_PROC_DEV_GPU; ctx->vpss.s32loopCount = s32loopCnt; ctx->vpss.stGrpVpssAttr.enPixelFormat = RK_FMT_YUV420SP; ctx->vpss.stGrpVpssAttr.enCompressMode = g_compressMode; ctx->vpss.stCropInfo.bEnable = RK_FALSE; ctx->vpss.stCropInfo.enCropCoordinate = VPSS_CROP_RATIO_COOR; ctx->vpss.stCropInfo.stCropRect.s32X = 0; ctx->vpss.stCropInfo.stCropRect.s32Y = 0; ctx->vpss.stCropInfo.stCropRect.u32Width = video_width; ctx->vpss.stCropInfo.stCropRect.u32Height = video_height; ctx->vpss.stChnCropInfo[0].bEnable = RK_TRUE; ctx->vpss.stChnCropInfo[0].enCropCoordinate = VPSS_CROP_RATIO_COOR; ctx->vpss.stChnCropInfo[0].stCropRect.s32X = 0; ctx->vpss.stChnCropInfo[0].stCropRect.s32Y = 0; ctx->vpss.stChnCropInfo[0].stCropRect.u32Width = venc_width * 1000 / video_width; ctx->vpss.stChnCropInfo[0].stCropRect.u32Height = venc_height * 1000 / video_height; ctx->vpss.s32ChnRotation[0] = ROTATION_0; ctx->vpss.stRotationEx[0].bEnable = RK_FALSE; ctx->vpss.stRotationEx[0].stRotationEx.u32Angle = 60; ctx->vpss.stVpssChnAttr[0].enChnMode = VPSS_CHN_MODE_USER; ctx->vpss.stVpssChnAttr[0].enDynamicRange = DYNAMIC_RANGE_SDR8; ctx->vpss.stVpssChnAttr[0].enPixelFormat = RK_FMT_YUV420SP; ctx->vpss.stVpssChnAttr[0].enCompressMode = g_compressMode; ctx->vpss.stVpssChnAttr[0].stFrameRate.s32SrcFrameRate = -1; ctx->vpss.stVpssChnAttr[0].stFrameRate.s32DstFrameRate = -1; ctx->vpss.stVpssChnAttr[0].u32Width = venc_width; ctx->vpss.stVpssChnAttr[0].u32Height = venc_height; ctx->vpss.stVpssChnAttr[0].u32Depth = 2; ctx->vpss.dstFilePath = pOutPathVenc; SAMPLE_COMM_VPSS_CreateChn(&ctx->vpss); #if defined(FILE_TEST) pthread_create(&vpss_thread_id[0], 0, vpss_get_stream, (void *)(&ctx->vpss)); // pthread_create(&vpss_thread_id[1], 0, vpss_send_stream, (void *)(&ctx->vpss)); #endif // Init VENC[0] ctx->venc.s32ChnId = 0; ctx->venc.u32Width = venc_width; ctx->venc.u32Height = venc_height; ctx->venc.u32Fps = 30; ctx->venc.u32Gop = 50; ctx->venc.u32BitRate = s32BitRate; switch (encodingType) { case 1: ctx->venc.enCodecType = RK_CODEC_TYPE_H265; ctx->venc.enRcMode = VENC_RC_MODE_H265CBR; // H264 66:Baseline 77:Main Profile 100:High Profile // H265 0:Main Profile 1:Main 10 Profile // MJPEG 0:Baseline ctx->venc.stChnAttr.stVencAttr.u32Profile = 100; break; case 2: ctx->venc.enCodecType = RK_CODEC_TYPE_H264; ctx->venc.enRcMode = VENC_RC_MODE_H264CBR; ctx->venc.stChnAttr.stVencAttr.u32Profile = 100; break; case 3: ctx->venc.enCodecType = RK_CODEC_TYPE_JPEG; break; default: break; } ctx->venc.getStreamCbFunc = venc_get_stream; ctx->venc.s32loopCount = s32loopCnt; ctx->venc.dstFilePath = pOutPathVenc; ctx->venc.stChnAttr.stGopAttr.enGopMode = VENC_GOPMODE_NORMALP; // VENC_GOPMODE_SMARTP SAMPLE_COMM_VENC_CreateChn(&ctx->venc); // Bind VI[0] and VPSS[0] stSrcChn.enModId = RK_ID_VI; stSrcChn.s32DevId = ctx->vi.s32DevId; stSrcChn.s32ChnId = ctx->vi.s32ChnId; stDestChn.enModId = RK_ID_VPSS; stDestChn.s32DevId = ctx->vpss.s32GrpId; stDestChn.s32ChnId = ctx->vpss.s32ChnId; SAMPLE_COMM_Bind(&stSrcChn, &stDestChn); #if !defined(FILE_TEST) // Bind VPSS[0] and VENC[0] stSrcChn.enModId = RK_ID_VPSS; stSrcChn.s32DevId = ctx->vpss.s32GrpId; stSrcChn.s32ChnId = ctx->vpss.s32ChnId; stDestChn.enModId = RK_ID_VENC; stDestChn.s32DevId = 0; stDestChn.s32ChnId = ctx->venc.s32ChnId; SAMPLE_COMM_Bind(&stSrcChn, &stDestChn); #endif printf("%s initial finish\n", __func__); if (mode == 0) { while (!quit) { sleep(1); } if (ctx->venc.getStreamCbFunc) { pthread_join(ctx->venc.getStreamThread, NULL); } if (g_loopcount > 0) { g_loopcount--; printf("sample_camera_stresstest: g_loopcount(%d)\n", g_loopcount); } } printf("%s exit!\n", __func__); if (mode == 1) { quit = true; if (ctx->venc.getStreamCbFunc) { pthread_join(ctx->venc.getStreamThread, NULL); } pthread_join(vpss_thread_id[0], NULL); pthread_join(vpss_thread_id[1], NULL); } RK_MPI_MB_DestroyPool(pool); #if !defined(FILE_TEST) // UnBind VPSS[0] and VENC[0] stSrcChn.enModId = RK_ID_VPSS; stSrcChn.s32DevId = ctx->vpss.s32GrpId; stSrcChn.s32ChnId = ctx->vpss.s32ChnId; stDestChn.enModId = RK_ID_VENC; stDestChn.s32DevId = 0; stDestChn.s32ChnId = ctx->venc.s32ChnId; SAMPLE_COMM_UnBind(&stSrcChn, &stDestChn); printf("%s Unbind VPSS[0] - VENC[0]!\n", __func__); // Bind VI[0] and VPSS[0] stSrcChn.enModId = RK_ID_VI; stSrcChn.s32DevId = ctx->vi.s32DevId; stSrcChn.s32ChnId = ctx->vi.s32ChnId; stDestChn.enModId = RK_ID_VPSS; stDestChn.s32DevId = ctx->vpss.s32GrpId; stDestChn.s32ChnId = ctx->vpss.s32ChnId; SAMPLE_COMM_UnBind(&stSrcChn, &stDestChn); printf("%s Unbind VI[0] - VPSS[0]!\n", __func__); #endif // Destroy VENC[0] SAMPLE_COMM_VENC_DestroyChn(&ctx->venc); // Destroy VPSS[0] SAMPLE_COMM_VPSS_DestroyChn(&ctx->vpss); // Destroy VI[0] SAMPLE_COMM_VI_DestroyChn(&ctx->vi); __FAILED: RK_MPI_SYS_Exit(); if (iq_file_dir) { #ifdef RKAIQ SAMPLE_COMM_ISP_Stop(s32CamId); #endif } return 0; } /****************************************************************************** * function : main() * Description : main ******************************************************************************/ int main(int argc, char *argv[]) { RK_S32 s32Ret = RK_FAILURE; RK_S32 s32Index; struct sigaction sa; RK_CHAR *iq_file_dir = "/etc/iqfiles"; RK_BOOL bMultictx = RK_FALSE; RK_S32 s32CamId = 0; SAMPLE_MPI_CTX_S ctx; if (argc < 2) { print_usage(argv[0]); return 0; } signal(SIGINT, sigterm_handler); int c; while ((c = getopt_long(argc, argv, optstr, long_options, NULL)) != -1) { const char *tmp_optarg = optarg; switch (c) { case 'n': s32Index = atoi(optarg); break; case 'l': g_loopcount = atoi(optarg); break; case 'c': g_framcount = atoi(optarg); break; case 'f': if (!strcmp(optarg, "nv12")) { g_compressMode = COMPRESS_MODE_NONE; } else if (!strcmp(optarg, "afbc")) { g_compressMode = COMPRESS_AFBC_16x16; } break; case 'e': if (!strcmp(optarg, "h265")) { encodingType = 1; } else if (!strcmp(optarg, "h264")) { encodingType = 2; } else if (!strcmp(optarg, "jpeg")) { encodingType = 3; } break; case '?': default: print_usage(argv[0]); return 0; } } memset(&ctx, 0, sizeof(SAMPLE_MPI_CTX_S)); g_ctx = &ctx; s32Ret = SAMPLE_CAMERA_VENC_Stresstest(&ctx, 0); printf("%s finish!\n", __func__); return 0; } #ifdef __cplusplus #if __cplusplus } #endif #endif /* End of #ifdef __cplusplus */     编译下载到板子后执行 ./vi_jpeg -n 1 -l 1 -c 10 -f nv12 -e jpeg,-c 表示测试的图片数量 -e 表示编码类型 (h264,h265,jpeg)     程序结束后在/tmp/路径下生成相应的文件,测试jpeg编码生成.jpeg文件,264/265 生成.bin文件            .bin的文件可以使用YUV VIEVER 查看 3、UDP发送JPEG图片     编译下载到板子后执行 ./vi_jpeg -n 1 -l 1 -c 1000 -f nv12 -e jpeg -i 192.168.110.36 -p 8000,代表拍图1000张 jpeg编码 udp服务器地址为192.168.110.36 端口为 8000 /* * Copyright 2021 Rockchip Electronics Co. LTD * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifdef __cplusplus #if __cplusplus extern "C" { #endif #endif /* End of #ifdef __cplusplus */ #include <assert.h> #include <errno.h> #include <fcntl.h> #include <getopt.h> #include <pthread.h> #include <semaphore.h> #include <signal.h> #include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/prctl.h> #include <time.h> #include <unistd.h> #include <sys/socket.h> #include <sys/types.h> #include <arpa/inet.h> #include "sample_comm.h" #define FILE_TEST typedef struct _rkMpiCtx { SAMPLE_VI_CTX_S vi; SAMPLE_VPSS_CTX_S vpss; SAMPLE_VENC_CTX_S venc; } SAMPLE_MPI_CTX_S; static int g_loopcount = 1; static int g_framcount = 200; static COMPRESS_MODE_E g_compressMode = COMPRESS_AFBC_16x16; static SAMPLE_MPI_CTX_S *g_ctx; static bool quit = false; static void sigterm_handler(int sig) { fprintf(stderr, "signal %d\n", sig); g_loopcount = 0; quit = true; pthread_cancel(pthread_self()); } static RK_CHAR optstr[] = "?::n:l:c:f:e:i:p:"; static const struct option long_options[] = { {"index", required_argument, NULL, 'n'}, {"loop_count", required_argument, NULL, 'l'}, {"frame_count", required_argument, NULL, 'c'}, {"pixel_format", optional_argument, NULL, 'f'}, {NULL, 0, NULL, 0}, }; uint8_t encodingType = 0; /* 选择编码类型 */ int sockfd; char *udpServerIp = NULL; int udpServerPort = 0; #define UDP_SEND_MAX_LEN ( 60 * 1024 ) /* 设置UDP一包发送的最大数量 */ /****************************************************************************** * function : show usage ******************************************************************************/ static void print_usage(const RK_CHAR *name) { printf("Usage : %s -n <index> -l <loop count> -c <frame count> -f <pixel format>\n", name); printf("index:\n"); printf("\t 0)isp stresstest(IqFileDir: /etc/iqfiles ~ /usr/share/iqfiles)\n"); printf("\t 1)venc stresstest(H264 ~ H265)\n"); printf("\t 2)venc stresstest(1x ~ 0.5x resolution)\n"); printf("\t 3)vi->vps->venc stresstest\n"); printf("pixel format:\n"); printf("\t nv12) no compress\n"); printf("\t afbc) compress\n"); } void *recv_thread(void *arg) { int socket_fd = *(int *)arg; struct sockaddr_in recv_addr; socklen_t addrlen = sizeof(recv_addr); char recvbuf[1024] = {0}; while(1) { if(recvfrom(socket_fd, recvbuf, 1024, 0,(struct sockaddr*)&recv_addr,&addrlen) < 0) //1024表示本次接收的最大字节数 printf("rec error!\n"); printf("[recv from %s:%d]%s \n",inet_ntoa(*(struct in_addr*)&recv_addr.sin_addr.s_addr),ntohs(recv_addr.sin_port),recvbuf); } printf("%s------------------------------------------------------------------------------------------------exit\n", __func__); pthread_exit(NULL); } /****************************************************************************** * function : vi thread ******************************************************************************/ static void *vi_get_stream(void *pArgs) { SAMPLE_VI_CTX_S *ctx = (SAMPLE_VI_CTX_S *)(pArgs); RK_S32 s32Ret = RK_FAILURE; char name[256] = {0}; FILE *fp = RK_NULL; void *pData = RK_NULL; RK_S32 loopCount = 0; if (ctx->dstFilePath) { snprintf(name, sizeof(name), "/%s/vi_%d.bin", ctx->dstFilePath, ctx->s32DevId); fp = fopen(name, "wb"); if (fp == RK_NULL) { printf("chn %d can't open %s file !\n", ctx->s32DevId, ctx->dstFilePath); quit = true; return RK_NULL; } } while (!quit) { s32Ret = SAMPLE_COMM_VI_GetChnFrame(ctx, &pData); if (s32Ret == RK_SUCCESS) { if (ctx->stViFrame.stVFrame.u64PrivateData <= 0) { // SAMPLE_COMM_VI_ReleaseChnFrame(ctx); // continue; } // exit when complete if (ctx->s32loopCount > 0) { if (loopCount >= ctx->s32loopCount) { SAMPLE_COMM_VI_ReleaseChnFrame(ctx); quit = true; break; } } if (fp) { fwrite(pData, 1, ctx->stViFrame.stVFrame.u64PrivateData, fp); fflush(fp); } RK_LOGE( "SAMPLE_COMM_VI_GetChnFrame DevId %d ok:data %p size:%llu loop:%d seq:%d " "pts:%lld ms\n", ctx->s32DevId, pData, ctx->stViFrame.stVFrame.u64PrivateData, loopCount, ctx->stViFrame.stVFrame.u32TimeRef, ctx->stViFrame.stVFrame.u64PTS / 1000); SAMPLE_COMM_VI_ReleaseChnFrame(ctx); loopCount++; } usleep(1000); } if (fp) fclose(fp); return RK_NULL; } /****************************************************************************** * function : vpss thread ******************************************************************************/ static RK_U8 data[2560 * 1520 * 2]; static RK_U8 data0[2560 * 1520 * 2]; static RK_U8 data1[2560 * 1520 * 2]; static void *vpss_get_stream(void *pArgs) { SAMPLE_VPSS_CTX_S *ctx = (SAMPLE_VPSS_CTX_S *)(pArgs); RK_S32 s32Ret = RK_FAILURE; char name[256] = {0}; FILE *fp = RK_NULL; FILE *fbc0 = RK_NULL; FILE *fbc1 = RK_NULL; void *pData = RK_NULL; RK_S32 loopCount = 0; VIDEO_FRAME_INFO_S stChnFrameInfos; if (ctx->dstFilePath) { snprintf(name, sizeof(name), "/%s/vpss_%d.yuv", ctx->dstFilePath, ctx->s32ChnId); fp = fopen(name, "wb"); if (fp == RK_NULL) { printf("chn %d can't open %s file !\n", ctx->s32ChnId, ctx->dstFilePath); quit = true; return RK_NULL; } } #if 0 fbc0 = fopen("/data/vpss_1280_760_fbc.bin", "r"); if (fbc0 == RK_NULL) { printf("can't open /data/vpss_1280_760_fbc.bin file !\n"); quit = true; return RK_NULL; } fbc1 = fopen("/data/vpss_2560_1520_fbc.bin", "r"); if (fbc1 == RK_NULL) { printf("can't open /data/vpss_2560_1520_fbc.bin file !\n"); quit = true; return RK_NULL; } fread(data0, 1, 1552384, fbc0); fread(data1, 1, 6164480, fbc1); #endif while (!quit) { s32Ret = SAMPLE_COMM_VPSS_GetChnFrame(ctx, &pData); if (s32Ret == RK_SUCCESS) { if (ctx->stChnFrameInfos.stVFrame.u64PrivateData <= 0) { continue; } #if 0 // exit when complete if (ctx->s32loopCount > 0) { if (loopCount >= ctx->s32loopCount) { SAMPLE_COMM_VPSS_ReleaseChnFrame(ctx); quit = true; break; } } #endif // if (fp) { // fwrite(pData, 1, ctx->stChnFrameInfos.stVFrame.u64PrivateData, fp); // fflush(fp); // } #if 1 // SAMPLE_COMM_VENC_SendStream( // &g_ctx->venc, pData, ctx->stChnFrameInfos.stVFrame.u32Width, // ctx->stChnFrameInfos.stVFrame.u32Height, // ctx->stChnFrameInfos.stVFrame.u64PrivateData, g_compressMode); s32Ret = RK_MPI_VENC_SendFrame(g_ctx->venc.s32ChnId, &ctx->stChnFrameInfos.stVFrame, -1); if (s32Ret != RK_SUCCESS) { RK_LOGE("RK_MPI_VENC_SendFrame fail %x", s32Ret); } #else if (ctx->stChnFrameInfos.stVFrame.u32Width == 1280) { SAMPLE_COMM_VENC_SendStream( &g_ctx->venc, data0, ctx->stChnFrameInfos.stVFrame.u32Width, ctx->stChnFrameInfos.stVFrame.u32Height, 1552384, g_compressMode); } else if (ctx->stChnFrameInfos.stVFrame.u32Width == 2560) { SAMPLE_COMM_VENC_SendStream( &g_ctx->venc, data1, ctx->stChnFrameInfos.stVFrame.u32Width, ctx->stChnFrameInfos.stVFrame.u32Height, 6164480, g_compressMode); } #endif printf("SAMPLE_COMM_VPSS_GetChnFrame DevId %d ok:data %p size:%llu loop:%d " "seq:%d " "pts:%lld ms\n", ctx->s32GrpId, pData, ctx->stChnFrameInfos.stVFrame.u64PrivateData, loopCount, ctx->stChnFrameInfos.stVFrame.u32TimeRef, ctx->stChnFrameInfos.stVFrame.u64PTS / 1000); SAMPLE_COMM_VPSS_ReleaseChnFrame(ctx); loopCount++; } usleep(1000); } if (fp) fclose(fp); return RK_NULL; } static void *vpss_send_stream(void *pArgs) { SAMPLE_VPSS_CTX_S *ctx = (SAMPLE_VPSS_CTX_S *)(pArgs); RK_S32 s32Ret = RK_FAILURE; FILE *fbc = RK_NULL; void *pData = RK_NULL; RK_S32 loopCount = 0; fbc = fopen("/data/vpss_2560_1520_fbc.bin", "r"); if (fbc == RK_NULL) { printf("can't open /data/vpss_2560_1520_fbc.bin file !\n"); quit = true; return RK_NULL; } fread(data, 1, 6164480, fbc); while (!quit) { // exit when complete if (ctx->s32loopCount > 0) { if (loopCount >= ctx->s32loopCount) { quit = true; break; } } SAMPLE_COMM_VPSS_SendStream(&g_ctx->vpss, data, 2560, 1520, 6164480, g_compressMode); loopCount++; usleep(20000); } if (fbc) fclose(fbc); return RK_NULL; } /****************************************************************************** * function : venc thread ******************************************************************************/ static void *venc_get_stream(void *pArgs) { SAMPLE_VENC_CTX_S *ctx = (SAMPLE_VENC_CTX_S *)(pArgs); RK_S32 s32Ret = RK_FAILURE; char name[256] = {0}; FILE *fp = RK_NULL; void *pData = RK_NULL; RK_S32 loopCount = 0; if (ctx->dstFilePath) { if(3 != encodingType) { snprintf(name, sizeof(name), "/%s/venc_%d.bin", ctx->dstFilePath, ctx->s32ChnId); fp = fopen(name, "wb"); if (fp == RK_NULL) { printf("chn %d can't open %s file !\n", ctx->s32ChnId, ctx->dstFilePath); quit = true; return RK_NULL; } } } while (!quit) { s32Ret = SAMPLE_COMM_VENC_GetStream(ctx, &pData); if (s32Ret == RK_SUCCESS) { // exit when complete if (ctx->s32loopCount > 0) { if (loopCount >= ctx->s32loopCount) { SAMPLE_COMM_VENC_ReleaseStream(ctx); quit = true; break; } // if (fp) // { // fwrite(pData, 1, ctx->stFrame.pstPack->u32Len, fp); // fflush(fp); // } if(3 != encodingType) { fwrite(pData, 1, ctx->stFrame.pstPack->u32Len, fp); fflush(fp); } else { static uint16_t pictureIndex = 0; snprintf(name, sizeof(name), "/%s/venc_%d.jpeg", ctx->dstFilePath, pictureIndex); fp = fopen(name, "wb"); if (fp == RK_NULL) { printf("chn %d can't open %s file !\n", ctx->s32ChnId, ctx->dstFilePath); quit = true; return RK_NULL; } // fwrite(pData, 1, ctx->stFrame.pstPack->u32Len, fp); // fflush(fp); pictureIndex++; printf("pictureIndex = %d",pictureIndex); } char picInfo[100]; unsigned int preSendPicLen = ctx->stFrame.pstPack->u32Len; int sendCnt = 0; unsigned char * startPalce = pData; struct sockaddr_in sock_addr = {0}; sock_addr.sin_family = AF_INET; // 设置地址族为IPv4 sock_addr.sin_port = htons(udpServerPort); // 设置地址的端口号信息 sock_addr.sin_addr.s_addr = inet_addr(udpServerIp); // 设置IP地址 sprintf(picInfo,"%s,%d,%ld,%s","frameData",ctx->stFrame.pstPack->u32Len,0,"123"); sendto(sockfd,picInfo,strlen(picInfo), 0, (struct sockaddr *)&sock_addr, sizeof(sock_addr));/* 发送图片大小数据包 */ /* 发送图片数据包 */ if(preSendPicLen > UDP_SEND_MAX_LEN) /* 如果图片的大小大于设定的最大值,分包发送 */ { // ESP_LOGI(camera,"preSendPicLen = %d \r\n",preSendPicLen); while(UDP_SEND_MAX_LEN * (sendCnt + 1) < preSendPicLen) { sendto(sockfd,startPalce + (UDP_SEND_MAX_LEN * sendCnt),UDP_SEND_MAX_LEN, 0, (struct sockaddr *)&sock_addr, sizeof(sock_addr)); sendCnt++; } sendto(sockfd,startPalce + (UDP_SEND_MAX_LEN * sendCnt),preSendPicLen % UDP_SEND_MAX_LEN, 0, (struct sockaddr *)&sock_addr, sizeof(sock_addr)); sendCnt = 0; } else /* 如果图片的大小没有大于设定的最大值,直接发送 */ { sendto(sockfd,startPalce,preSendPicLen, 0, (struct sockaddr *)&sock_addr, sizeof(sock_addr)); } } PrintStreamDetails(ctx->s32ChnId, ctx->stFrame.pstPack->u32Len); RK_LOGD("chn:%d, loopCount:%d wd:%d\n", ctx->s32ChnId, loopCount, ctx->stFrame.pstPack->u32Len); SAMPLE_COMM_VENC_ReleaseStream(ctx); loopCount++; } usleep(1000); } if (fp) fclose(fp); return RK_NULL; } int SAMPLE_CAMERA_VENC_Stresstest(SAMPLE_MPI_CTX_S *ctx, RK_S32 mode) { RK_S32 s32Ret = RK_FAILURE; int video_width = 2560; int video_height = 1520; int venc_width = 2560; int venc_height = 1520; RK_CHAR *pOutPathVenc = NULL; RK_CHAR *iq_file_dir = "/etc/iqfiles"; RK_CHAR *pCodecName = "H264"; CODEC_TYPE_E enCodecType = RK_CODEC_TYPE_H264; VENC_RC_MODE_E enRcMode = VENC_RC_MODE_H264CBR; RK_S32 s32BitRate = 10 * 1024; RK_S32 s32CamId = 0; MPP_CHN_S stSrcChn, stDestChn; RK_S32 s32loopCnt = g_framcount; RK_S32 i; RK_BOOL bMultictx = RK_FALSE; quit = false; pthread_t vpss_thread_id[2]; if (mode == 1) { s32loopCnt = -1; } pOutPathVenc ="tmp"; printf("#CameraIdx: %d\n", s32CamId); printf("#CodecName:%s\n", pCodecName); printf("#Output Path: %s\n", pOutPathVenc); if (iq_file_dir) { #ifdef RKAIQ printf("#Rkaiq XML DirPath: %s\n", iq_file_dir); printf("#bMultictx: %d\n\n", bMultictx); rk_aiq_working_mode_t hdr_mode = RK_AIQ_WORKING_MODE_NORMAL; SAMPLE_COMM_ISP_Init(s32CamId, hdr_mode, bMultictx, iq_file_dir); SAMPLE_COMM_ISP_Run(s32CamId); #endif } if (RK_MPI_SYS_Init() != RK_SUCCESS) { goto __FAILED; } MB_POOL pool = MB_INVALID_POOLID; MB_POOL_CONFIG_S stMbPoolCfg; memset(&stMbPoolCfg, 0, sizeof(MB_POOL_CONFIG_S)); stMbPoolCfg.u64MBSize = video_width * video_height * 2; stMbPoolCfg.u32MBCnt = 10; stMbPoolCfg.enAllocType = MB_ALLOC_TYPE_DMA; pool = RK_MPI_MB_CreatePool(&stMbPoolCfg); ctx->vpss.pool = ctx->venc.pool = pool; // Init VI[0] ctx->vi.u32Width = video_width; ctx->vi.u32Height = video_height; ctx->vi.s32DevId = s32CamId; ctx->vi.u32PipeId = ctx->vi.s32DevId; ctx->vi.s32ChnId = 2; // rk3588 mainpath:0 selfpath:1 fbcpath:2 ctx->vi.stChnAttr.stIspOpt.u32BufCount = 4; ctx->vi.stChnAttr.stIspOpt.enMemoryType = VI_V4L2_MEMORY_TYPE_DMABUF; ctx->vi.stChnAttr.u32Depth = 1; ctx->vi.stChnAttr.enPixelFormat = RK_FMT_YUV420SP; ctx->vi.stChnAttr.enCompressMode = g_compressMode; ctx->vi.stChnAttr.stFrameRate.s32SrcFrameRate = -1; ctx->vi.stChnAttr.stFrameRate.s32DstFrameRate = -1; if (g_compressMode == COMPRESS_MODE_NONE) { ctx->vi.s32ChnId = 0; } SAMPLE_COMM_VI_CreateChn(&ctx->vi); // Init VPSS[0] ctx->vpss.s32GrpId = 0; ctx->vpss.s32ChnId = 0; // RGA_device: VIDEO_PROC_DEV_RGA GPU_device: VIDEO_PROC_DEV_GPU ctx->vpss.enVProcDevType = VIDEO_PROC_DEV_RGA; // ctx->vpss.enVProcDevType = VIDEO_PROC_DEV_GPU; ctx->vpss.s32loopCount = s32loopCnt; ctx->vpss.stGrpVpssAttr.enPixelFormat = RK_FMT_YUV420SP; ctx->vpss.stGrpVpssAttr.enCompressMode = g_compressMode; ctx->vpss.stCropInfo.bEnable = RK_FALSE; ctx->vpss.stCropInfo.enCropCoordinate = VPSS_CROP_RATIO_COOR; ctx->vpss.stCropInfo.stCropRect.s32X = 0; ctx->vpss.stCropInfo.stCropRect.s32Y = 0; ctx->vpss.stCropInfo.stCropRect.u32Width = video_width; ctx->vpss.stCropInfo.stCropRect.u32Height = video_height; ctx->vpss.stChnCropInfo[0].bEnable = RK_TRUE; ctx->vpss.stChnCropInfo[0].enCropCoordinate = VPSS_CROP_RATIO_COOR; ctx->vpss.stChnCropInfo[0].stCropRect.s32X = 0; ctx->vpss.stChnCropInfo[0].stCropRect.s32Y = 0; ctx->vpss.stChnCropInfo[0].stCropRect.u32Width = venc_width * 1000 / video_width; ctx->vpss.stChnCropInfo[0].stCropRect.u32Height = venc_height * 1000 / video_height; ctx->vpss.s32ChnRotation[0] = ROTATION_0; ctx->vpss.stRotationEx[0].bEnable = RK_FALSE; ctx->vpss.stRotationEx[0].stRotationEx.u32Angle = 60; ctx->vpss.stVpssChnAttr[0].enChnMode = VPSS_CHN_MODE_USER; ctx->vpss.stVpssChnAttr[0].enDynamicRange = DYNAMIC_RANGE_SDR8; ctx->vpss.stVpssChnAttr[0].enPixelFormat = RK_FMT_YUV420SP; ctx->vpss.stVpssChnAttr[0].enCompressMode = g_compressMode; ctx->vpss.stVpssChnAttr[0].stFrameRate.s32SrcFrameRate = -1; ctx->vpss.stVpssChnAttr[0].stFrameRate.s32DstFrameRate = -1; ctx->vpss.stVpssChnAttr[0].u32Width = venc_width; ctx->vpss.stVpssChnAttr[0].u32Height = venc_height; ctx->vpss.stVpssChnAttr[0].u32Depth = 2; ctx->vpss.dstFilePath = pOutPathVenc; SAMPLE_COMM_VPSS_CreateChn(&ctx->vpss); #if defined(FILE_TEST) pthread_create(&vpss_thread_id[0], 0, vpss_get_stream, (void *)(&ctx->vpss)); // pthread_create(&vpss_thread_id[1], 0, vpss_send_stream, (void *)(&ctx->vpss)); #endif // Init VENC[0] ctx->venc.s32ChnId = 0; ctx->venc.u32Width = venc_width; ctx->venc.u32Height = venc_height; ctx->venc.u32Fps = 30; ctx->venc.u32Gop = 50; ctx->venc.u32BitRate = s32BitRate; switch (encodingType) { case 1: ctx->venc.enCodecType = RK_CODEC_TYPE_H265; ctx->venc.enRcMode = VENC_RC_MODE_H265CBR; // H264 66:Baseline 77:Main Profile 100:High Profile // H265 0:Main Profile 1:Main 10 Profile // MJPEG 0:Baseline ctx->venc.stChnAttr.stVencAttr.u32Profile = 100; break; case 2: ctx->venc.enCodecType = RK_CODEC_TYPE_H264; ctx->venc.enRcMode = VENC_RC_MODE_H264CBR; ctx->venc.stChnAttr.stVencAttr.u32Profile = 100; break; case 3: ctx->venc.enCodecType = RK_CODEC_TYPE_JPEG; break; default: break; } ctx->venc.getStreamCbFunc = venc_get_stream; ctx->venc.s32loopCount = s32loopCnt; ctx->venc.dstFilePath = pOutPathVenc; ctx->venc.stChnAttr.stGopAttr.enGopMode = VENC_GOPMODE_NORMALP; // VENC_GOPMODE_SMARTP SAMPLE_COMM_VENC_CreateChn(&ctx->venc); // Bind VI[0] and VPSS[0] stSrcChn.enModId = RK_ID_VI; stSrcChn.s32DevId = ctx->vi.s32DevId; stSrcChn.s32ChnId = ctx->vi.s32ChnId; stDestChn.enModId = RK_ID_VPSS; stDestChn.s32DevId = ctx->vpss.s32GrpId; stDestChn.s32ChnId = ctx->vpss.s32ChnId; SAMPLE_COMM_Bind(&stSrcChn, &stDestChn); #if !defined(FILE_TEST) // Bind VPSS[0] and VENC[0] stSrcChn.enModId = RK_ID_VPSS; stSrcChn.s32DevId = ctx->vpss.s32GrpId; stSrcChn.s32ChnId = ctx->vpss.s32ChnId; stDestChn.enModId = RK_ID_VENC; stDestChn.s32DevId = 0; stDestChn.s32ChnId = ctx->venc.s32ChnId; SAMPLE_COMM_Bind(&stSrcChn, &stDestChn); #endif printf("%s initial finish\n", __func__); if (mode == 0) { while (!quit) { sleep(1); } if (ctx->venc.getStreamCbFunc) { pthread_join(ctx->venc.getStreamThread, NULL); } if (g_loopcount > 0) { g_loopcount--; printf("sample_camera_stresstest: g_loopcount(%d)\n", g_loopcount); } } printf("%s exit!\n", __func__); if (mode == 1) { quit = true; if (ctx->venc.getStreamCbFunc) { pthread_join(ctx->venc.getStreamThread, NULL); } pthread_join(vpss_thread_id[0], NULL); pthread_join(vpss_thread_id[1], NULL); } RK_MPI_MB_DestroyPool(pool); #if !defined(FILE_TEST) // UnBind VPSS[0] and VENC[0] stSrcChn.enModId = RK_ID_VPSS; stSrcChn.s32DevId = ctx->vpss.s32GrpId; stSrcChn.s32ChnId = ctx->vpss.s32ChnId; stDestChn.enModId = RK_ID_VENC; stDestChn.s32DevId = 0; stDestChn.s32ChnId = ctx->venc.s32ChnId; SAMPLE_COMM_UnBind(&stSrcChn, &stDestChn); printf("%s Unbind VPSS[0] - VENC[0]!\n", __func__); // Bind VI[0] and VPSS[0] stSrcChn.enModId = RK_ID_VI; stSrcChn.s32DevId = ctx->vi.s32DevId; stSrcChn.s32ChnId = ctx->vi.s32ChnId; stDestChn.enModId = RK_ID_VPSS; stDestChn.s32DevId = ctx->vpss.s32GrpId; stDestChn.s32ChnId = ctx->vpss.s32ChnId; SAMPLE_COMM_UnBind(&stSrcChn, &stDestChn); printf("%s Unbind VI[0] - VPSS[0]!\n", __func__); #endif // Destroy VENC[0] SAMPLE_COMM_VENC_DestroyChn(&ctx->venc); // Destroy VPSS[0] SAMPLE_COMM_VPSS_DestroyChn(&ctx->vpss); // Destroy VI[0] SAMPLE_COMM_VI_DestroyChn(&ctx->vi); __FAILED: RK_MPI_SYS_Exit(); if (iq_file_dir) { #ifdef RKAIQ SAMPLE_COMM_ISP_Stop(s32CamId); #endif } return 0; } /****************************************************************************** * function : main() * Description : main ******************************************************************************/ int main(int argc, char *argv[]) { RK_S32 s32Ret = RK_FAILURE; RK_S32 s32Index; struct sigaction sa; RK_CHAR *iq_file_dir = "/etc/iqfiles"; RK_BOOL bMultictx = RK_FALSE; RK_S32 s32CamId = 0; SAMPLE_MPI_CTX_S ctx; if (argc < 2) { print_usage(argv[0]); return 0; } signal(SIGINT, sigterm_handler); int c; while ((c = getopt_long(argc, argv, optstr, long_options, NULL)) != -1) { const char *tmp_optarg = optarg; switch (c) { case 'n': s32Index = atoi(optarg); break; case 'l': g_loopcount = atoi(optarg); break; case 'c': g_framcount = atoi(optarg); break; case 'f': if (!strcmp(optarg, "nv12")) { g_compressMode = COMPRESS_MODE_NONE; } else if (!strcmp(optarg, "afbc")) { g_compressMode = COMPRESS_AFBC_16x16; } break; case 'e': if (!strcmp(optarg, "h265")) { encodingType = 1; } else if (!strcmp(optarg, "h264")) { encodingType = 2; } else if (!strcmp(optarg, "jpeg")) { encodingType = 3; } break; case 'i': udpServerIp = optarg; break; case 'p': udpServerPort = atoi(optarg); break; case '?': default: print_usage(argv[0]); return 0; } } sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (-1 == sockfd) { printf("socket open err."); return -1; } // 2、绑定本地的相关信息,如果不绑定,则系统会随机分配一个端口号 struct sockaddr_in local_addr = {0}; local_addr.sin_family = AF_INET; //使用IPv4地址 local_addr.sin_addr.s_addr = inet_addr(udpServerIp); //本机IP地址 local_addr.sin_port = htons(udpServerPort); //端口 // local_addr.sin_addr.s_addr = htonl(INADDR_ANY); //将套接字和IP、端口绑定 if (bind(sockfd, (struct sockaddr*)&local_addr, sizeof(local_addr)) < 0) printf("bind error"); // 3、打印本机ip地址和端口号 printf("IP地址: %s\n", udpServerIp); printf("端口号: %d\n", udpServerPort); pthread_t udpRecThread = -1; // 4、创建一个线程,用来接收数据 pthread_create(&udpRecThread, NULL, recv_thread, &sockfd); // // 5、等待输入数据,然后发送出去,直到输入的数据为'quit','192.168.0.107'表示目的ip地址,8266表示目的端口号 // struct sockaddr_in sock_addr = {0}; // sock_addr.sin_family = AF_INET; // 设置地址族为IPv4 // sock_addr.sin_port = htons(8266); // 设置地址的端口号信息 // sock_addr.sin_addr.s_addr = inet_addr(udpServerIp); // 设置IP地址 // char sendbuf[1024]={"hello world, I am a UDP socket."}; // int cnt = 10; // while(cnt--) // { // printf("please input a string.input 'quit' to quit.\n"); // scanf("%s",sendbuf); // if(strcmp(sendbuf,"quit") == 0) // break; // sendto(sockfd, sendbuf, strlen(sendbuf), 0, (struct sockaddr*)&sock_addr, sizeof(sock_addr)); // } memset(&ctx, 0, sizeof(SAMPLE_MPI_CTX_S)); g_ctx = &ctx; s32Ret = SAMPLE_CAMERA_VENC_Stresstest(&ctx, 0); printf("%s finish!\n", __func__); // 等待线程退出 pthread_join(recv_thread, NULL); close(sockfd); return 0; } #ifdef __cplusplus #if __cplusplus } #endif #endif /* End of #ifdef __cplusplus */     这里拿了之前自己做的UDP收图的程序     实际的效果: [localvideo]ca1746bb589066034be771abefc2b30b[/localvideo]  

学过的课程

最近访客

< 1/4 >

统计信息

已有45人来访过

  • 芯积分:69
  • 好友:--
  • 主题:3
  • 回复:6

留言

你需要登录后才可以留言 登录 | 注册


现在还没有留言