当前位置: 首页 > news >正文

树莓派学习专题<14>:树莓派4B:从V4L2驱动直接获取h264码流

树莓派学习专题<14>:树莓派学习专题<14>:树莓派4B:从V4L2驱动直接获取h264码流

  • 0. 项目代码
  • 1. 背景
  • 2. 代码

0. 项目代码

可以从下面获取到项目中的代码。
https://github.com/cdsmakc/h264_codec_base_rpi4b_rpi5_rv1106_visual_studio.git

1. 背景

之前的文章,记录了在树莓派4上,使用V4L2驱动获取YUV图像,然后通过x264编码。由于sensor本身并不能输出264码流,驱动本身也不负责编码,因此我一直以为从V4L2获取264码流是不可能的。但是在使用V4L2驱动罗列摄像头支持的数据格式时,却可以看到驱动能够输出264码流:

--Format descriptor --------------------------------------
-- 01. Planar YUV 4:2:0         (YU12)
-- 02. YUYV 4:2:2               (YUYV)
-- 03. 24-bit RGB 8-8-8         (RGB3)
-- 04. JFIF JPEG                (JPEG)
-- 05. H.264                    (H264)   --->此处
-- 06. Motion-JPEG              (MJPG)
-- 07. YVYU 4:2:2               (YVYU)
-- 08. VYUY 4:2:2               (VYUY)
-- 09. UYVY 4:2:2               (UYVY)
-- 10. Y/UV 4:2:0               (NV12)
-- 11. 24-bit BGR 8-8-8         (BGR3)
-- 12. Planar YVU 4:2:0         (YV12)
-- 13. Y/VU 4:2:0               (NV21)
-- 14. 32-bit XBGR 8-8-8-8      (RX24)
----------------------------------------------------------

也可以用V4L2-CTL工具查看输出支持的格式(注意:需要修改config.txt文件,参看之前的文章):

njl@raspberrypi:~ $ v4l2-ctl -d /dev/video0 --list-formats-ext
ioctl: VIDIOC_ENUM_FMTType: Video Capture[0]: 'YU12' (Planar YUV 4:2:0)Size: Stepwise 32x32 - 3280x2464 with step 2/2[1]: 'YUYV' (YUYV 4:2:2)Size: Stepwise 32x32 - 3280x2464 with step 2/2[2]: 'RGB3' (24-bit RGB 8-8-8)Size: Stepwise 32x32 - 3280x2464 with step 2/2[3]: 'JPEG' (JFIF JPEG, compressed)Size: Stepwise 32x32 - 3280x2464 with step 2/2[4]: 'H264' (H.264, compressed)Size: Stepwise 32x32 - 3280x2464 with step 2/2[5]: 'MJPG' (Motion-JPEG, compressed)Size: Stepwise 32x32 - 3280x2464 with step 2/2[6]: 'YVYU' (YVYU 4:2:2)Size: Stepwise 32x32 - 3280x2464 with step 2/2[7]: 'VYUY' (VYUY 4:2:2)Size: Stepwise 32x32 - 3280x2464 with step 2/2[8]: 'UYVY' (UYVY 4:2:2)Size: Stepwise 32x32 - 3280x2464 with step 2/2[9]: 'NV12' (Y/UV 4:2:0)Size: Stepwise 32x32 - 3280x2464 with step 2/2[10]: 'BGR3' (24-bit BGR 8-8-8)Size: Stepwise 32x32 - 3280x2464 with step 2/2[11]: 'YV12' (Planar YVU 4:2:0)Size: Stepwise 32x32 - 3280x2464 with step 2/2[12]: 'NV21' (Y/VU 4:2:0)Size: Stepwise 32x32 - 3280x2464 with step 2/2[13]: 'RX24' (32-bit XBGR 8-8-8-8)Size: Stepwise 32x32 - 3280x2464 with step 2/2

可以看到,摄像头即可以输出264码流也可以输出MJPEG码流。一上来没有注意到这点,后来看到树莓派论坛上的帖子才知道,树莓派官方已经将摄像头硬件设备、ISP和硬件编码器等做了封装,从而使得可以使用V4L2驱动从 /dev/video0 设备直接获取图像264码流。

2. 代码

使用V4L2获取摄像头的代码和之前的代码相同,只是输出格式需要改一下:

/* 设置输出格式 */
stFormat.type                = V4L2_BUF_TYPE_VIDEO_CAPTURE ;
stFormat.fmt.pix.width       = g_stRCEConfig.usWidth ;
stFormat.fmt.pix.height      = g_stRCEConfig.usHeight ;
stFormat.fmt.pix.pixelformat = (0 == g_stRCEConfig.uiHWEncoder) ? V4L2_PIX_FMT_YUV420 : V4L2_PIX_FMT_H264 ;iRetVal = ioctl(g_stCAMWorkarea.iCameraFile, VIDIOC_S_FMT, &stFormat) ;

如果需要获取264码流,使用VIDIOC_S_FMT命令设置输出格式时,指定V4L2_PIX_FMT_H264即可。

此外,使用硬件编码时,树莓派4B可以输出到60fps;如果获取YUV420的图像,大约只能到47fps(只是获取图像,不考虑软编码的情况下)。另外,在默认情况下,硬件编码的264码流还是很大的,有时候接近10Mbps。这个也可以修改。这需要额外的命令来实现。

INT __RCE_CAM_SetRCParams(VOID)
{struct v4l2_ext_controls stExtCtrls ;struct v4l2_ext_control  stExtCtrl ;INT                      iRetVal ;memset(&stExtCtrls, 0, sizeof(stExtCtrls)) ;memset(&stExtCtrl, 0, sizeof(stExtCtrl)) ;stExtCtrl.id          = V4L2_CID_MPEG_VIDEO_BITRATE ;stExtCtrl.value       = g_stRCEConfig.uiHWBitrate ;stExtCtrl.size        = 0 ;stExtCtrls.controls   = &stExtCtrl ;stExtCtrls.count      = 1 ;stExtCtrls.ctrl_class = V4L2_CTRL_CLASS_MPEG ;iRetVal = ioctl(g_stCAMWorkarea.iCameraFile, VIDIOC_S_EXT_CTRLS, &stExtCtrls) ;if(-1 == iRetVal){printf("File %s, func %s, line %d : ioctl VIDIOC_S_EXT_CTRLS error. ioctl : %s.\n", __FILE__, __func__, __LINE__, strerror(errno)) ;return -1 ;}return 0 ;
}

其中,g_stRCEConfig.uiHWBitrate即是码流目标值,以bps为单位。例如希望码流是3Mbps左右,则设置3000000。这个码流设置下去,也只是告知编码器按此目标工作,不代表输出就是这个码流。实际上,输出码流是变化的,只是均值尽量接近这个值而已。


相关文章:

  • Flutter基础(Isolate)
  • 构建 AI 系统的 4 大 Agentic AI 设计模式
  • ClickHouse基础知识
  • 嵌入式网络通信与物联网协议全解析:Wi-Fi、BLE、LoRa、ZigBee 实战指南
  • golang pprof性能调试工具
  • 内网对抗之信息收集篇
  • Note2.3 机器学习:Adaptive Learning Rate
  • Java 大视界 -- Java 大数据机器学习模型在金融市场高频交易策略优化与风险控制中的应用(327)
  • springboot+Vue逍遥大药房管理系统
  • SmartETL中数据库操作与流程解耦的设计与应用
  • Stewart并联结构两自由度正逆解计算和工作空间仿真
  • 使用asyncio构建高性能网络爬虫
  • for each循环语句
  • FPGA芯片的配置方法
  • [Java 基础]HashMap
  • Element Plus el-button实例类型详解
  • 什么是数字签名(ECDSA)?
  • 非阻塞 IO
  • Java面试题030:一文深入了解MySQL(2)
  • 将文档转为数据集