用mmap+poll方式实现视频流从驱动层采集到应用层渲染的全过程

33 阅读2分钟

模拟实现相机驱动,采用mmap+poll方式实现了视频流从驱动层采集到应用层渲染的全过程。先看实验结果:

out.gif

开发环境:gcc版本7.5.0,内核5.4.0,系统Ubuntu18.04.6

**@**:~$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/local/libexec/gcc/x86_64-pc-linux-gnu/7.5.0/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: ../configure -enable-checking=release -enable-languages=c,c++ -disable-multilib
Thread model: posix
gcc version 7.5.0 (GCC) 
**@**:~$ uname -a
Linux ** 5.4.0-150-generic #167~18.04.1-Ubuntu SMP Wed May 24 00:51:42 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux

一、模拟相机驱动层工作

  1. 在驱动中开辟内存,用于存储yuv视频帧
  2. 实现mmap函数,将设备中的物理内存地址映射到应用进程中
  3. 在下半部构造yuv视频帧
  4. 将视频帧拷贝共享内存中。
  5. 唤醒被read方法阻塞的应用进程,通过copy_to_user将视频帧已经准备完成的消息返回给应用层。

二、应用层读操作

  1. 以非阻塞方式打开设备文件
  2. 调用mmap触发驱动中的mmap函数,将驱动内存地址映射到应用进程中。
  3. 不断轮询poll方法,检测是否有有可读的视频帧。
  4. 无帧时,read方法阻塞(驱动控制)应用进程。有帧时,进程被驱动唤醒,copy_to_user拷贝至用户的数据将被应用从buffer中读取(非视频帧)。
  5. 从共享内存中直接读取驱动写入的yuv视频帧
  6. 使用QT框架将yuv视频帧转换成RGB,完成渲染。顺便实现动态环形采样。

三、实验结果

图片上半部为qt渲染效果及动态框选示意,下半部为驱动程序模拟生成YUV视频帧并通知QT应用读取共享内存中的YUV帧。 image.png

桌面录屏

ffmpeg -f x11grab -s 750x750 -i :0.0+10,50 output_file.mp4

ffmpeg -i output_file.mp4 -ss 00:00:29.500 -t 3 out.gif

ffmpeg -f x11grab -s 650x600 -i :0.0+10,50 -pix_fmt yuv420p output_file.mp4

ffmpeg -i output_file.mp4 -vf "[in]drawtext=text='Rendering yuv frames via QT,':fontsize=24:fontcolor=white:x=100:y=100,drawtext=text='and Box selection dynamically.':fontsize=24:fontcolor=white:x=100:y=150,drawtext=text='Generate YUV frames in Driver.':fontsize=28:fontcolor=red:x=100:y=400[out]" -codec:a copy a_d_w.mp4