<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title>V4L2 - Tag - 枕石的个人博客</title><link>https://blog.zsmgc.love/tags/v4l2/</link><description>V4L2 - Tag - 枕石的个人博客</description><generator>Hugo -- gohugo.io</generator><language>zh-CN</language><managingEditor>3499129952@qq.com (枕石)</managingEditor><webMaster>3499129952@qq.com (枕石)</webMaster><lastBuildDate>Fri, 30 Jan 2026 00:14:45 +0800</lastBuildDate><atom:link href="https://blog.zsmgc.love/tags/v4l2/" rel="self" type="application/rss+xml"/><item><title>V4l2loopback实现笔记（五）:VB2 缓冲区管理</title><link>https://blog.zsmgc.love/posts/v4l2loopback%E5%AE%9E%E7%8E%B0%E7%AC%94%E8%AE%B0vb2%E7%BC%93%E5%86%B2%E5%8C%BA%E7%AE%A1%E7%90%86/</link><pubDate>Fri, 30 Jan 2026 00:14:45 +0800</pubDate><author>枕石</author><guid>https://blog.zsmgc.love/posts/v4l2loopback%E5%AE%9E%E7%8E%B0%E7%AC%94%E8%AE%B0vb2%E7%BC%93%E5%86%B2%E5%8C%BA%E7%AE%A1%E7%90%86/</guid><description><![CDATA[<p>本模块演示 videobuf2 (VB2) 框架的使用，这是 Linux 内核中处理视频流的标准方法。</p>
<h3 id="实现的功能">实现的功能</h3>
<ul>
<li>VB2 队列初始化 (<code>vb2_queue_init</code>)</li>
<li>缓冲区操作回调 (<code>vb2_ops</code>)</li>
<li>缓冲区请求和查询 (<code>REQBUFS</code>, <code>QUERYBUF</code>)</li>
<li>缓冲区入队和出队 (<code>QBUF</code>, <code>DQBUF</code>)</li>
<li>流控制 (<code>STREAMON</code>, <code>STREAMOFF</code>)</li>
<li>多种 I/O 模式支持 (<code>MMAP</code>, <code>USERPTR</code>, <code>READ/WRITE</code>)</li>
</ul>
<h2 id="学习要点">学习要点</h2>
<ol>
<li>理解 VB2 框架的设计目标和优势</li>
<li>理解 <code>vb2_ops</code> 各回调的调用时机</li>
<li>理解缓冲区状态机</li>
<li>理解为什么 <code>stop_streaming</code> 必须返回所有缓冲区</li>
<li>理解 VB2 与自定义缓冲区管理的权衡</li>
</ol>
<h2 id="代码解析">代码解析</h2>
<h3 id="结构体定义">结构体定义</h3>
<h4 id="1-struct-vb2fw_format">1. struct vb2fw_format</h4>
<div class="code-block code-line-numbers" style="counter-reset: code-block 0">
    <div class="code-header language-c">
        <span class="code-title"><i class="arrow fas fa-angle-right fa-fw" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h fa-fw" aria-hidden="true"></i></span>
        <span class="copy" title="Copy to clipboard"><i class="far fa-copy fa-fw" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">vb2fw_format</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">u32</span> <span class="n">fourcc</span><span class="p">;</span>           <span class="cm">/* V4L2 FourCC 代码 */</span>
</span></span><span class="line"><span class="cl">    <span class="n">u32</span> <span class="n">depth</span><span class="p">;</span>            <span class="cm">/* 每像素位数 */</span>
</span></span><span class="line"><span class="cl">    <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">name</span><span class="p">;</span>     <span class="cm">/* 格式名称 */</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">vb2fw_format</span> <span class="n">vb2fw_formats</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="p">.</span><span class="n">fourcc</span> <span class="o">=</span> <span class="n">V4L2_PIX_FMT_YUYV</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="p">.</span><span class="n">depth</span>  <span class="o">=</span> <span class="mi">16</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="p">.</span><span class="n">name</span>   <span class="o">=</span> <span class="s">&#34;YUYV 4:2:2&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="p">.</span><span class="n">fourcc</span> <span class="o">=</span> <span class="n">V4L2_PIX_FMT_UYVY</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="p">.</span><span class="n">depth</span>  <span class="o">=</span> <span class="mi">16</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="p">.</span><span class="n">name</span>   <span class="o">=</span> <span class="s">&#34;UYVY 4:2:2&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="p">.</span><span class="n">fourcc</span> <span class="o">=</span> <span class="n">V4L2_PIX_FMT_RGB24</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="p">.</span><span class="n">depth</span>  <span class="o">=</span> <span class="mi">24</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="p">.</span><span class="n">name</span>   <span class="o">=</span> <span class="s">&#34;RGB24&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="p">.</span><span class="n">fourcc</span> <span class="o">=</span> <span class="n">V4L2_PIX_FMT_BGR24</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="p">.</span><span class="n">depth</span>  <span class="o">=</span> <span class="mi">24</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="p">.</span><span class="n">name</span>   <span class="o">=</span> <span class="s">&#34;BGR24&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="p">.</span><span class="n">fourcc</span> <span class="o">=</span> <span class="n">V4L2_PIX_FMT_YUV420</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="p">.</span><span class="n">depth</span>  <span class="o">=</span> <span class="mi">12</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="p">.</span><span class="n">name</span>   <span class="o">=</span> <span class="s">&#34;YUV 4:2:0&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="p">.</span><span class="n">fourcc</span> <span class="o">=</span> <span class="n">V4L2_PIX_FMT_NV12</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="p">.</span><span class="n">depth</span>  <span class="o">=</span> <span class="mi">12</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="p">.</span><span class="n">name</span>   <span class="o">=</span> <span class="s">&#34;NV12&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span></span></span></code></pre></div></div>
<p>将 V4L2 标准的 fourcc 码（如 V4L2_PIX_FMT_YUYV）与驱动计算所需的参数（如 depth 像素深度）关联起来。当用户调用 S_FMT 设置分辨率时，你需要计算 sizeimage = width * height * (depth / 8)。这个结构体让你能通过简单的循环找到当前格式对应的计算权重。</p>]]></description></item><item><title>V4l2loopback实现笔记（四）:V4L2(Video for Linux 2) 框架入门</title><link>https://blog.zsmgc.love/posts/v4l2loopback%E5%AE%9E%E7%8E%B0%E7%AC%94%E8%AE%B0v4l2%E6%A1%86%E6%9E%B6%E5%85%A5%E9%97%A8/</link><pubDate>Wed, 28 Jan 2026 13:15:33 +0800</pubDate><author>枕石</author><guid>https://blog.zsmgc.love/posts/v4l2loopback%E5%AE%9E%E7%8E%B0%E7%AC%94%E8%AE%B0v4l2%E6%A1%86%E6%9E%B6%E5%85%A5%E9%97%A8/</guid><description><![CDATA[<p>本模块演示 V4L2 (Video for Linux 2) 子系统的基础用法，创建一个可被 v4l2 工具识别的视频设备，支持基本的格式查询和设置操作。</p>
<h3 id="实现的功能">实现的功能</h3>
<ul>
<li>V4L2 设备注册 (<code>v4l2_device_register</code>, <code>video_register_device</code>)</li>
<li>设备能力查询 (<code>VIDIOC_QUERYCAP</code>)</li>
<li>格式枚举和协商 (<code>VIDIOC_ENUM_FMT</code>, <code>VIDIOC_G_FMT</code>, <code>VIDIOC_S_FMT</code>, <code>VIDIOC_TRY_FMT</code>)</li>
<li>多种像素格式支持</li>
<li>设备能力标志设置</li>
</ul>
<h3 id="学习要点">学习要点</h3>
<ol>
<li>理解 <code>v4l2_device</code> 和 <code>video_device</code> 的关系</li>
<li>理解 <code>v4l2_ioctl_ops</code> 的结构和用途</li>
<li>理解格式协商的 try/set 模式</li>
<li>理解设备能力标志的含义</li>
<li>理解 V4L2 文件操作与标准文件操作的区别</li>
</ol>
<h2 id="v4l2-核心概念">V4L2 核心概念</h2>
<h3 id="ioctl-操作分类">ioctl 操作分类</h3>
<table>
  <thead>
      <tr>
          <th>类别</th>
          <th>操作</th>
          <th>用途</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>查询</td>
          <td>QUERYCAP</td>
          <td>设备能力</td>
      </tr>
      <tr>
          <td>格式</td>
          <td>ENUM_FMT, G/S/TRY_FMT</td>
          <td>格式协商</td>
      </tr>
      <tr>
          <td>缓冲区</td>
          <td>REQBUFS, QUERYBUF, QBUF, DQBUF</td>
          <td>缓冲区管理</td>
      </tr>
      <tr>
          <td>流控制</td>
          <td>STREAMON, STREAMOFF</td>
          <td>流控制</td>
      </tr>
      <tr>
          <td>控制</td>
          <td>QUERYCTRL, G/S_CTRL</td>
          <td>设备参数</td>
      </tr>
  </tbody>
</table>
<h3 id="格式协商流程">格式协商流程</h3>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-">
        <span class="code-title"><i class="arrow fas fa-angle-right fa-fw" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h fa-fw" aria-hidden="true"></i></span>
        <span class="copy" title="Copy to clipboard"><i class="far fa-copy fa-fw" aria-hidden="true"></i></span>
    </div><pre tabindex="0"><code>应用程序                          驱动程序
    │                                │
    ├── ENUM_FMT ─────────────────►  │  枚举支持的格式
    │                                │
    ├── TRY_FMT  ─────────────────►  │  尝试格式(驱动调整)
    │  ◄───────────────────────────  │  返回调整后的格式
    │                                │
    ├── S_FMT    ─────────────────►  │  设置格式
    │                                │
    └── G_FMT    ─────────────────►  │  确认当前格式</code></pre></div>
<h2 id="问题与思考">问题与思考</h2>
<ol>
<li>kzalloc是什么？和kmalloc有什么区别？什么时候用哪个？
kzalloc = kmalloc + memset(&hellip;, 0, &hellip;), 用于分配并初始化为0的内存块。kmalloc分配的内存未初始化，可能包含垃圾值。通常在需要清零内存时使用kzalloc，否则使用kmalloc以节省初始化开销。</li>
<li>v4l2_device和video_device的区别和联系是什么？</li>
<li>v4l2_ioctl_ops结构体的作用是什么？如何实现自定义的ioctl操作？</li>
</ol>
<h2 id="v4l2-device-structure">V4L2 device structure</h2>
<div class="code-block code-line-numbers" style="counter-reset: code-block 0">
    <div class="code-header language-c">
        <span class="code-title"><i class="arrow fas fa-angle-right fa-fw" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h fa-fw" aria-hidden="true"></i></span>
        <span class="copy" title="Copy to clipboard"><i class="far fa-copy fa-fw" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">v4l2_framework_device</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">struct</span> <span class="n">v4l2_device</span> <span class="n">v4l2_dev</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">struct</span> <span class="n">video_device</span> <span class="n">vdev</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">struct</span> <span class="n">v4l2_fh</span> <span class="n">vfh</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="cm">/* Format settings */</span>
</span></span><span class="line"><span class="cl">    <span class="k">struct</span> <span class="n">v4l2_format</span> <span class="n">current_format</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">struct</span> <span class="n">mutex</span> <span class="n">lock</span><span class="p">;</span>  <span class="c1">// Protection for format changes
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="cl">    <span class="cm">/* Frame dimensions */</span>
</span></span><span class="line"><span class="cl">    <span class="kt">int</span> <span class="n">width</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="kt">int</span> <span class="n">height</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">u32</span> <span class="n">format</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span></span></span></code></pre></div></div>
<p>V4L2 框架的核心对象：</p>]]></description></item></channel></rss>