当前位置:首页>Linux>在Linux开发中,如何使用V4L2进行视频图像采集?

在Linux开发中,如何使用V4L2进行视频图像采集?

  • 2026-03-27 11:00:25
在Linux开发中,如何使用V4L2进行视频图像采集?

1. 项目目的

本项目是一个基于 Linux V4L2 框架的入门级视频采集示例,用来帮助初学者,在嵌入式 Linux 下,进行摄像头应用开发的核心流程。

通过这个 Demo,可以掌握以下内容:

  • 打开视频设备 /dev/video0
  • 查询摄像头驱动能力
  • 枚举摄像头支持的像素格式
  • 设置采集分辨率和像素格式
  • 申请并映射 mmap 缓冲区
  • 使用 QBUF / DQBUF 完成采集队列管理
  • 使用 STREAMON / STREAMOFF 启停视频流
  • 将采集到的原始视频帧保存为 .yuv 文件

这个 Demo 适合用于:

  • V4L2 入门学习
  • 嵌入式 Linux 应用开发面试准备
  • 摄像头采集流程调试
  • 后续扩展到图像显示、格式转换、编码和推流

2. 典型应用场景

V4L2 在嵌入式 Linux 中常见的使用场景包括:

2.1 USB 摄像头采集

使用 UVC 摄像头,通过 /dev/video0 获取图像,用于预览、拍照、识别等。

2.2 MIPI CSI 摄像头采集

板载 Sensor 经过 CSI/ISP 链路后,最终通过 V4L2 视频节点输出图像。

2.3 视频前端输入

采集到的 YUV 图像进一步送给编码器进行 H.264/H.265 压缩。

2.4 图像算法输入

将采集帧传给 OpenCV、目标检测、人脸识别、OCR 等算法模块。

2.5 本地显示预览

采集数据送给 DRM、SDL、Qt、OpenCV 等显示框架做实时预览。

2.6 音视频系统前端

视频走 V4L2,音频走 ALSA,再由 GStreamer 或 FFmpeg 做封装、推流和同步。


3. 本 Demo 的运行结果说明

本次运行环境中,程序已经成功跑通,日志如下特征说明系统工作正常:

3.1 成功识别摄像头

  • 驱动名:uvcvideo
  • 设备名:HD Camera: HD Camera
  • 总线:usb-sunxi-ehci-1.1

说明当前设备是一个 USB UVC 摄像头。

3.2 成功枚举格式

支持格式为:

  • MJPG:Motion-JPEG
  • YUYV:YUYV 4:2:2

本次选择的是 YUYV,更适合初学者学习原始图像采集流程。

3.3 成功设置图像格式

实际设置结果:

  • 分辨率:640 x 480
  • 像素格式:YUYV
  • bytesperline = 1280
  • sizeimage = 614400

计算关系如下:

  • YUYV 每像素占 2 字节
  • 每行大小:640 × 2 = 1280
  • 每帧大小:640 × 480 × 2 = 614400

这说明格式设置正确。

3.4 成功申请和映射缓冲区

程序申请了 4 个缓冲区,并用 mmap 映射到用户空间。

这说明以下步骤已经成功:

  • VIDIOC_REQBUFS
  • VIDIOC_QUERYBUF
  • mmap

3.5 成功开始采集并抓到帧

程序能够连续抓到 5 帧图像,并且打印了:

  • index
  • bytesused
  • sequence
  • timestamp

说明以下流程全部正常:

  • QBUF
  • STREAMON
  • DQBUF
  • 数据保存
  • 再次 QBUF
  • STREAMOFF

最终生成了:

  • frame_000.yuv
  • frame_001.yuv
  • frame_002.yuv
  • frame_003.yuv
  • frame_004.yuv

4. V4L2 采集主流程

本 Demo 的核心流程如下:

  1. open() 打开 /dev/video0

  2. VIDIOC_QUERYCAP 查询能力

  3. VIDIOC_ENUM_FMT 枚举支持格式

  4. VIDIOC_S_FMT 设置分辨率和像素格式

  5. VIDIOC_REQBUFS 申请缓冲区

  6. VIDIOC_QUERYBUF 查询每个缓冲区信息

  7. mmap() 映射缓冲区到用户空间

  8. VIDIOC_QBUF 将缓冲区入队

  9. VIDIOC_STREAMON 开启视频流

  10. 进入循环:

    • VIDIOC_DQBUF 取出一帧
    • 保存到 .yuv 文件
    • VIDIOC_QBUF 重新入队
  11. VIDIOC_STREAMOFF 停止视频流

  12. munmap() 释放映射

  13. close() 关闭设备

这是 V4L2 最经典、最重要的学习主线。


5. 关键接口说明

5.1 VIDIOC_QUERYCAP

查询设备能力,例如:

  • 是否支持视频采集
  • 是否支持流式 I/O
  • 驱动名、设备名、总线信息

5.2 VIDIOC_ENUM_FMT

枚举摄像头支持的像素格式,例如:

  • MJPG
  • YUYV
  • NV12

5.3 VIDIOC_S_FMT

设置采集格式,包括:

  • 宽度
  • 高度
  • 像素格式

5.4 VIDIOC_REQBUFS

向驱动申请一组缓冲区,用于流式采集。

5.5 VIDIOC_QUERYBUF

获取缓冲区长度、偏移地址等信息,为 mmap 做准备。

5.6 VIDIOC_QBUF

将空缓冲区交给驱动,表示该缓冲区可以用于接收下一帧图像。

5.7 VIDIOC_DQBUF

从驱动取回已经采满数据的缓冲区。

5.8 VIDIOC_STREAMON

开始视频流,驱动开始真正采集。

5.9 VIDIOC_STREAMOFF

停止视频流,结束采集。


6. 为什么使用 mmap 而不是 read

在 V4L2 中,常见 I/O 模式有:

  • read/write
  • mmap
  • userptr
  • dmabuf

本 Demo 选择 mmap,原因是:

  • 性能更高
  • 减少一次数据拷贝
  • 是最常见的 V4L2 入门模式
  • 易于理解缓冲区队列工作机制

对于高分辨率和高帧率采集,mmap 通常比 read() 更合适。


7. 日志字段理解

程序抓帧时会打印类似:

  • index
  • bytesused
  • sequence
  • timestamp

含义如下:

7.1 index

表示当前出队的是哪个缓冲区。

7.2 bytesused

表示当前这帧实际使用的字节数。

本例中通常为 614400,等于一帧完整 YUYV 图像大小。

7.3 sequence

表示帧序号。

如果序号偶尔跳变,通常说明:

  • 起流初期丢帧
  • 驱动内部丢弃某些帧
  • 应用没有赶上最初的某一帧

少量跳帧并不一定是错误。

7.4 timestamp

表示驱动给出的该帧时间戳,可用于:

  • 计算帧间隔
  • 判断实际帧率
  • 音视频同步

8. YUYV 原始数据说明

本 Demo 保存的是 .yuv 原始数据文件,而不是 .jpg 或 .bmp

这是因为 V4L2 当前输出格式是 YUYV,它属于原始像素数据,不能直接双击查看。

要查看它,必须告诉播放器:

  • 分辨率:640x480
  • 像素格式:yuyv422

例如在 Ubuntu 上用 ffplay

ffplay -f rawvideo -pixel_format yuyv422 -video_size 640x480 frame_000.yuv

注意:如果文件大小为 0 字节,播放器虽然能识别输入参数,但不会显示有效画面。


9. 本次调试过程中遇到的问题

9.1 宏名写错导致编译失败

出现过以下错误:

  • V4L2_BUF_TYPE_VIDIOC_CAPTURE
  • VIDEO_ENUM_FMT

这些都不是合法的 V4L2 宏。

正确写法是:

  • V4L2_BUF_TYPE_VIDEO_CAPTURE
  • VIDIOC_ENUM_FMT

这个问题说明 V4L2 中两类宏容易写混:

  • VIDIOC_*:ioctl 命令
  • V4L2_*:类型、属性、枚举值

9.2 使用 scp 拉取文件失败

Ubuntu 主机执行 scp 时,远端板子报:

ash: scp: not found

说明开发板系统中没有安装 scp 程序,因此不能用标准 scp 方式拉取文件。

9.3 使用 ssh "cat ..." > file 时中断

执行:

ssh root@板子IP "cat /root/frame_000.yuv" > frame_000.yuv

中途按下 Ctrl+C,导致本地得到的 frame_000.yuv 文件大小为 0。

后续调试确认开发板端原始文件是正常的,问题仅在文件传输链路,而不是 V4L2 采集逻辑。


10. 从这个 Demo 中学到的核心知识

通过本项目,应该重点理解以下内容:

10.1 V4L2 采集是一个队列模型

采集不是一次性读数据,而是:

  • 准备多个缓冲区
  • 先 QBUF
  • 再 STREAMON
  • 不断 DQBUF 取帧
  • 用完后再 QBUF 回去

10.2 为什么要多个缓冲区

如果只有一个缓冲区,驱动采集和应用处理无法并行,容易阻塞和掉帧。

10.3 mmap 是 V4L2 最常见的入门方式

理解了 mmap,就理解了应用层如何直接访问驱动分配的采集缓冲区。

10.4 bytesperline 和 sizeimage 很重要

不能只按理论值想当然处理图像,应优先参考驱动返回的真实参数。

10.5 原始图像不能直接双击查看

V4L2 采集到的是原始像素数据,需要配合分辨率和格式参数才能正确显示。


11. 面试表达参考

如果面试官问“你做过 V4L2 吗”,可以这样描述:

我做过一个基于 V4L2 的视频采集 Demo,能够打开 /dev/video0,查询设备能力,枚举摄像头支持的格式,并将摄像头设置为 640x480 YUYV。程序采用 mmap 方式申请和映射 4 个缓冲区,通过 QBUF / STREAMON / DQBUF / QBUF 完成采集循环,并把每一帧保存成 .yuv 原始图像文件。在调试过程中,我也处理过 V4L2 宏名写错导致的编译问题,以及开发板文件传输工具不完整带来的调试问题。

这段表述可以体现你:

  • 理解 V4L2 主流程
  • 具备基本调试能力
  • 不是只会背概念,而是做过实际运行

12. 后续扩展方向

在当前 Demo 基础上,可以继续做以下升级:

12.1 YUYV 转 RGB 并保存为 BMP

这样可以直接双击查看图像,更适合初学者。

12.2 支持 MJPEG 采集

摄像头支持 MJPG,可以直接保存压缩帧,减少文件体积。

12.3 实现实时预览

可结合:

  • SDL
  • OpenCV
  • Qt
  • DRM

12.4 多线程处理

实现采集线程、处理线程、保存线程分离,构建生产者消费者模型。

12.5 接入编码器

将采集帧送给硬件或软件编码器,生成 H.264/H.265 码流。

12.6 加入时间统计

统计:

  • 帧率
  • 丢帧情况
  • 帧间隔
  • 平均处理时延

13. 总结

这个 V4L2_DEMO 已经完成了一个标准的摄像头采集闭环:

  • 设备打开成功
  • 格式设置成功
  • 缓冲区申请成功
  • 视频流启动成功
  • 连续抓帧成功
  • 原始帧保存成功

从学习价值来看,这个 Demo 已经覆盖了嵌入式 Linux V4L2 应用开发最核心的主流程。

只要把这个 Demo 中的每一步都理解透,再继续往图像显示、格式转换、编码和推流方向扩展,就能够逐步建立完整的嵌入式 Linux 音视频开发能力。

代码框架

V4L2_Demo:  main.c  v4l2_capture.c  v4l2_capture.h  Makefile

源码

main.c#include "v4l2_capture.h"#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>static void usage(const char *prog){printf("Usage: %s [-d device] [-W width] [-H height] [-f pixfmt] [-n frame_count]\n", prog);printf("Example:\n");printf("  %s -d /dev/video0 -W 640 -H 480 -f YUYV -n 5\n", prog);}static uint32_t parse_pixfmt(const char *s){if (strcmp(s, "YUYV") == 0)return v4l2_fourcc('Y''U''Y''V');if (strcmp(s, "MJPG") == 0)return v4l2_fourcc('M''J''P''G');if (strcmp(s, "NV12") == 0)return v4l2_fourcc('N''V''1''2');    fprintf(stderr, "unsupported pixel format: %s\n", s);return 0;}int main(int argc, char *argv[]){    v4l2_ctx_t ctx;    uint32_t frame_count = 5;    const char *save_prefix = "frame";    int opt;    int ret = -1;    memset(&ctx, 0, sizeof(ctx));    ctx.fd = -1;    ctx.dev_name = "/dev/video0";    ctx.width = 640;    ctx.height = 480;    ctx.pixfmt = v4l2_fourcc('Y''U''Y''V');while ((opt = getopt(argc, argv, "d:W:H:f:n:h")) != -1)    {        switch (opt)        {case'd':            ctx.dev_name = optarg;break;case'W':            ctx.width = (uint32_t)atoi(optarg);break;case'H':            ctx.height = (uint32_t)atoi(optarg);break;case'f':            ctx.pixfmt = parse_pixfmt(optarg);if (ctx.pixfmt == 0)return -1;break;case'n':            frame_count = (uint32_t)atoi(optarg);break;case'h':        default:            usage(argv[0]);return 0;        }    }printf("========== V4L2 Demo Start ==========\n");printf("device      : %s\n", ctx.dev_name);printf("width       : %u\n", ctx.width);printf("height      : %u\n", ctx.height);printf("pixfmt      : %c%c%c%c\n",           ctx.pixfmt & 0xFF,           (ctx.pixfmt >> 8) & 0xFF,           (ctx.pixfmt >> 16) & 0xFF,           (ctx.pixfmt >> 24) & 0xFF);printf("frame_count : %u\n", frame_count);if (v4l2_open_device(&ctx) < 0)        goto out;if (v4l2_query_capability(&ctx) < 0)        goto out;    v4l2_enum_formats(&ctx);if (v4l2_set_format(&ctx) < 0)        goto out;if (v4l2_init_mmap(&ctx, 4) < 0)        goto out;if (v4l2_start_stream(&ctx) < 0)        goto out;if (v4l2_capture_frames(&ctx, frame_count, save_prefix) < 0)        goto stop;    ret = 0;stop:    v4l2_stop_stream(&ctx);out:    v4l2_uninit(&ctx);    v4l2_close_device(&ctx);if (ret == 0)printf("========== V4L2 Demo Success ==========\n");elseprintf("========== V4L2 Demo Failed ==========\n");return ret;}
v4l2_capture.h#ifndef V4L2_CAPTURE_H#define V4L2_CAPTURE_H#include <stdint.h>#include <linux/videodev2.h>/* *      表示一个mmap映射出来的缓冲区 *      start:用户空间可访问的起始地址 *      length:缓冲区长度 * */typedef struct{        void *start;        uint32_t length;}buffer_t;/* *      v4l2    设备上下文 * *      fd:打开的设备文件描述符 *      dev_name:设备节点名称,例如dev/video0 *      width/height:采集分辨率 *      pixfmt:像素格式,例如:V4L2_PIX_FMT_YUYV / V4L2_PIX_FMT_NV12 / V4L2_PIX_FMT_MJPEG *      buffers:  mmap  缓冲区数组 *      buffer_count:   缓冲区个数 * */typedef struct{        int fd;        const char *dev_name;        uint32_t width;        uint32_t height;        uint32_t pixfmt;        buffer_t *buffers;        uint32_t buffer_count;}v4l2_ctx_t;int v4l2_open_device(v4l2_ctx_t  *ctx);int v4l2_query_capability(v4l2_ctx_t *ctx);int v4l2_set_format(v4l2_ctx_t *ctx);int v4l2_enum_formats(v4l2_ctx_t *ctx);   //枚举格式功能函数int v4l2_init_mmap(v4l2_ctx_t *ctx, uint32_t req_count);int v4l2_start_stream(v4l2_ctx_t *ctx);int v4l2_capture_frames(v4l2_ctx_t *ctx,uint32_t frame_count,const char *save_prefix);int v4l2_stop_stream(v4l2_ctx_t *ctx);void v4l2_uninit(v4l2_ctx_t *ctx);void v4l2_close_device(v4l2_ctx_t *ctx);#endif
v4l2_capture.c#include "v4l2_capture.h"#include <stdio.h>#include <stdint.h>#include <stdlib.h>#include <string.h>#include <errno.h>#include <unistd.h>#include <fcntl.h>#include <sys/ioctl.h>#include <sys/mman.h>#include <sys/select.h>#include <sys/time.h>/* *      封装ioctl 避免信号中断时直接失败 *      linux下 ioctl 可能因为 eintr 被中断 *      因此这里做一个小封装,遇到eintr就重试 * */static int xioctl(int fd,int request,void *arg){        int ret;do{                ret = ioctl(fd,request,arg);        }while(ret == -1 && errno == EINTR);return ret;}/* *      打开v4l2设备节点 * */int v4l2_open_device(v4l2_ctx_t  *ctx){if(ctx == NULL || ctx -> dev_name == NULL)        {                fprintf(stderr,"invalid ctx or device name\n");return -1;        }        ctx->fd = open (ctx->dev_name,O_RDWR | O_NONBLOCK, 0);if(ctx->fd < 0)        {                perror("open video device failed");return -1;        }printf("open video successfully : %s\n",ctx->dev_name);return 0;}/* *      查询设备能力 * *      重点检查: *      1.是否是视频采集设备 *      2.是否支持streaming模式 * */int v4l2_query_capability(v4l2_ctx_t *ctx){        struct v4l2_capability cap;        memset(&cap,0,sizeof(cap));if(xioctl(ctx->fd,VIDIOC_QUERYCAP,&cap) < 0)        {                perror("VIDIOC_QUERYCAP failed");return -1;        }printf("Driver Name   : %s\n", cap.driver);printf("Card Name     : %s\n", cap.card);printf("Bus Info      : %s\n", cap.bus_info);printf("Version       : %u.%u.%u\n",                  (cap.version >> 16) & 0xFF,                 (cap.version >> 8) & 0xFF,                 cap.version & 0xFF);printf("Capabilities  : 0x%08x\n", cap.capabilities);if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE))        {                fprintf(stderr, "device does not support video capture\n");return -1;        }if (!(cap.capabilities & V4L2_CAP_STREAMING))        {                 fprintf(stderr, "device does not support streaming i/o\n");return -1;        }return 0;}/* *      设置采集格式 *      注意: *       1. 应用请求的 width/height/pixfmt 不一定被驱动完全接受 *       2. 驱动可能会返回调整后的参数 *       3. bytesperline 和 sizeimage 一定要打印出来 * * */int v4l2_set_format(v4l2_ctx_t *ctx){        struct v4l2_format fmt;        memset(&fmt,0,sizeof(fmt));        fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;        fmt.fmt.pix.width = ctx->width;        fmt.fmt.pix.height = ctx->height;        fmt.fmt.pix.pixelformat = ctx->pixfmt;        fmt.fmt.pix.field = V4L2_FIELD_ANY;if (xioctl(ctx->fd, VIDIOC_S_FMT, &fmt) < 0)        {                perror("VIDIOC_S_FMT failed");return -1;        }        /*        * 用驱动实际返回的值更新上下文        * 因为驱动可能修正了分辨率和格式        */        ctx->width = fmt.fmt.pix.width;        ctx->height = fmt.fmt.pix.height;        ctx->pixfmt = fmt.fmt.pix.pixelformat;printf("set format success\n");printf("Actual Width      : %u\n", fmt.fmt.pix.width);printf("Actual Height     : %u\n", fmt.fmt.pix.height);printf("Pixel Format      : %c%c%c%c\n",                fmt.fmt.pix.pixelformat & 0xFF,                (fmt.fmt.pix.pixelformat >> 8) & 0xFF,                (fmt.fmt.pix.pixelformat >> 16) & 0xFF,                (fmt.fmt.pix.pixelformat >> 24) & 0xFF);printf("Bytes Per Line    : %u\n", fmt.fmt.pix.bytesperline);printf("Size Image        : %u\n", fmt.fmt.pix.sizeimage);printf("Field             : %u\n", fmt.fmt.pix.field);return 0;}/* *      枚举格式功能函数 * *      作用: *      可以在设置格式之前,先打印摄像头可以支持哪些格式 * * */int v4l2_enum_formats(v4l2_ctx_t *ctx){        struct v4l2_fmtdesc fmtdesc;        memset(&fmtdesc,0,sizeof(fmtdesc));        fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;printf("Support formats\n");while(xioctl(ctx->fd,VIDIOC_ENUM_FMT,&fmtdesc) == 0)        {printf("  [%u] %c%c%c%c  %s\n",               fmtdesc.index,               fmtdesc.pixelformat & 0xFF,               (fmtdesc.pixelformat >> 8) & 0xFF,               (fmtdesc.pixelformat >> 16) & 0xFF,               (fmtdesc.pixelformat >> 24) & 0xFF,               fmtdesc.description);        fmtdesc.index++;        }return 0;}/* *      初始化 mmap  缓冲区 *      流程: *      1.向驱动申请若干buffer *      2.逐个查询buffer 的 offset 和 length *      3.用mmap把每个buffer映射到用户空间 * */int v4l2_init_mmap(v4l2_ctx_t *ctx,uint32_t req_count){        struct v4l2_requestbuffers req;        uint32_t i;        memset(&req,0,sizeof(req));        req.count = req_count;        req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;        req.memory = V4L2_MEMORY_MMAP;if(xioctl(ctx->fd,VIDIOC_REQBUFS,&req) < 0)        {                perror("VIDIOC_REQBUFS failed");return -1;        }if (req.count < 2)        {                fprintf(stderr, "insufficient buffer memory, got %u buffers\n", req.count);return -1;        }        ctx->buffers = (buffer_t *)calloc(req.count, sizeof(buffer_t));if (ctx->buffers == NULL)         {                fprintf(stderr, "calloc buffers failed\n");return -1;         }         ctx->buffer_count = req.count;for (i = 0; i < ctx->buffer_count; i++)         {                struct v4l2_buffer buf;                memset(&buf,0,sizeof(buf));                buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;                buf.memory = V4L2_MEMORY_MMAP;                buf.index = i;if(xioctl(ctx->fd,VIDIOC_QUERYBUF,&buf) < 0)                {                        perror("VIDIOC_QUERYBUF failed");return -1;                }                ctx->buffers[i].length = buf.length;                ctx->buffers[i].start = mmap(NULL,                                     buf.length,                                     PROT_READ | PROT_WRITE,                                     MAP_SHARED,                                     ctx->fd,                                     buf.m.offset);if(ctx->buffers[i].start  == MAP_FAILED )                {                        perror("mmap failed\n");return -1;                }printf("buffer[%u]: start=%p length=%u offset=%u\n",                        i,                        ctx->buffers[i].start,                        ctx->buffers[i].length,                        buf.m.offset);         }return 0;}/* *      启动视频流 * * 正确流程是: * 1. 先把全部 buffer QBUF 入队 * 2. 再调用 STREAMON * * 原因: * 硬件一旦开始采集,驱动必须立刻有空闲 buffer 可写入。 * * * */int v4l2_start_stream(v4l2_ctx_t *ctx){        uint32_t i;        enum v4l2_buf_type type;for (i = 0; i < ctx->buffer_count; i++)        {                struct v4l2_buffer buf;                memset(&buf, 0, sizeof(buf));                buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;                buf.memory = V4L2_MEMORY_MMAP;                buf.index = i;if (xioctl(ctx->fd, VIDIOC_QBUF, &buf) < 0)                {                        perror("VIDIOC_QBUF failed");return -1;                }        }type = V4L2_BUF_TYPE_VIDEO_CAPTURE;if (xioctl(ctx->fd, VIDIOC_STREAMON, &type) < 0)        {                perror("VIDIOC_STREAMON failed");return -1;        }printf("stream on success\n");return 0;}/* * 保存一帧原始数据到文件 * * 注意: * 保存的是原始像素数据,不是 jpg/png。 * 例如 YUYV/NV12 保存下来通常是 .yuv 文件。 * 可以用 ffplay 或者 ffmpeg 再验证。 */static int save_frame_to_file(const char *filename, const void *data, uint32_t size){    FILE *fp = fopen(filename, "wb");if (fp == NULL)    {        perror("fopen frame file failed");return -1;    }if (fwrite(data, 1, size, fp) != size)    {        perror("fwrite frame failed");        fclose(fp);return -1;    }    fclose(fp);return 0;}/* * 抓取若干帧 * * 使用 select 等待设备就绪,然后 DQBUF 取帧。 * * 为什么这里不用死循环疯狂 DQBUF? * 因为设备可能暂时没有帧准备好,select/poll 更合理。 */int v4l2_capture_frames(v4l2_ctx_t *ctx, uint32_t frame_count, const char *save_prefix){        uint32_t captured = 0;while (captured < frame_count)        {                fd_set fds;                struct timeval tv;                int ret;                FD_ZERO(&fds);                FD_SET(ctx->fd, &fds);                /*                * 设置等待超时,避免永久卡死                */                tv.tv_sec = 2;                tv.tv_usec = 0;        ret = select(ctx->fd + 1, &fds, NULL, NULL, &tv);if (ret < 0)        {if (errno == EINTR)continue;            perror("select failed");return -1;        }elseif (ret == 0)        {            fprintf(stderr, "select timeout\n");return -1;        }if (FD_ISSET(ctx->fd, &fds))        {            struct v4l2_buffer buf;            char filename[256];            memset(&buf, 0, sizeof(buf));            buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;            buf.memory = V4L2_MEMORY_MMAP;if (xioctl(ctx->fd, VIDIOC_DQBUF, &buf) < 0)            {                /*                 * 对非阻塞 fd 来说,如果当前没有可取的 buffer,                 * 可能返回 EAGAIN,这里直接继续即可。                 */if (errno == EAGAIN)continue;                perror("VIDIOC_DQBUF failed");return -1;            }printf("frame %u: index=%u bytesused=%u sequence=%u timestamp=%ld.%06ld\n",                   captured,                   buf.index,                   buf.bytesused,                   buf.sequence,                   buf.timestamp.tv_sec,                   buf.timestamp.tv_usec);            /*             * 为了演示,这里把每一帧都单独保存。             * 实际项目中通常不会每帧都落盘,因为会严重影响性能。             */            snprintf(filename, sizeof(filename), "%s_%03u.yuv", save_prefix, captured);if (save_frame_to_file(filename, ctx->buffers[buf.index].start, buf.bytesused) < 0)            {return -1;            }            /*             * 处理完这块 buffer 后,一定要重新 QBUF 入队。             * 否则驱动可用 buffer 会越来越少,最终采集停住。             */if (xioctl(ctx->fd, VIDIOC_QBUF, &buf) < 0)            {                perror("VIDIOC_QBUF requeue failed");return -1;            }            captured++;        }    }return 0;}/* * 停止视频流 */int v4l2_stop_stream(v4l2_ctx_t *ctx){    enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;if (xioctl(ctx->fd, VIDIOC_STREAMOFF, &type) < 0)    {        perror("VIDIOC_STREAMOFF failed");return -1;    }printf("stream off success\n");return 0;}/* * 释放 mmap 资源 */void v4l2_uninit(v4l2_ctx_t *ctx){    uint32_t i;if (ctx == NULL || ctx->buffers == NULL)return;for (i = 0; i < ctx->buffer_count; i++)    {if (ctx->buffers[i].start != NULL && ctx->buffers[i].start != MAP_FAILED)        {            munmap(ctx->buffers[i].start, ctx->buffers[i].length);        }    }    free(ctx->buffers);    ctx->buffers = NULL;    ctx->buffer_count = 0;}/* * 关闭设备节点 */void v4l2_close_device(v4l2_ctx_t *ctx){if (ctx && ctx->fd >= 0)    {        close(ctx->fd);        ctx->fd = -1;    }}
MakefileCC = arm-openwrt-linux-gccCFLAGS = -Wall -Wextra -O2TARGET = v4l2_demoSRCS = main.c v4l2_capture.cOBJS = $(SRCS:.c=.o)all: $(TARGET)$(TARGET): $(OBJS)        $(CC) $(CFLAGS) -o $@ $^%.o: %.c        $(CC) $(CFLAGS) -c $< -o $@clean:        rm -f $(TARGET) $(OBJS) frame_*.yuv1

交叉编译(在ubuntu上)

tammy@ubuntu:~/camera/v4l2_demo01$ makearm-openwrt-linux-gcc -Wall -Wextra -O2 -c main.c -o main.oarm-openwrt-linux-gcc -Wall -Wextra -O2 -c v4l2_capture.c -o v4l2_capture.oarm-openwrt-linux-gcc -Wall -Wextra -O2 -o v4l2_demo main.o v4l2_capture.otammy@ubuntu:~/camera/v4l2_demo01$ lsmain.c  main.o  Makefile  v4l2_capture.c  v4l2_capture.h  v4l2_capture.o  v4l2_demotammy@ubuntu:~/camera/v4l2_demo01$ adb push v4l2_demo /rootv4l2_demo: 1 file pushed. 1.1 MB/s (32124 bytes in 0.028s)

开发板运行:

root@Linux:~# ./v4l2_demo========== V4L2 Demo Start ==========device      : /dev/video0width       : 640height      : 480pixfmt      : YUYVframe_count : 5open video successfully : /dev/video0Driver Name   : uvcvideoCard Name     : HD Camera: HD CameraBus Info      : usb-sunxi-ehci-1.1Version       : 5.4.61Capabilities  : 0x84a00001Support formats  [0] MJPG  Motion-JPEG  [1] YUYV  YUYV 4:2:2set format successActual Width      : 640Actual Height     : 480Pixel Format      : YUYVBytes Per Line    : 1280Size Image        : 614400Field             : 1buffer[0]: start=0xb6e92000 length=614400 offset=0buffer[1]: start=0xb6dfc000 length=614400 offset=614400buffer[2]: start=0xb6d66000 length=614400 offset=1228800buffer[3]: start=0xb6cd0000 length=614400 offset=1843200stream on successframe 0: index=0 bytesused=614400 sequence=0 timestamp=48.244409frame 1: index=1 bytesused=614400 sequence=2 timestamp=48.328476frame 2: index=2 bytesused=614400 sequence=3 timestamp=48.364455frame 3: index=3 bytesused=614400 sequence=4 timestamp=48.396453frame 4: index=0 bytesused=614400 sequence=5 timestamp=48.428473stream off success========== V4L2 Demo Success ==========

采集到的图像文件:

root@Linux:~# lsframe_001.yuv   frame_003.yuv   frame_000.yuv   frame_002.yuv   frame_004.yuv   v4l2_demo

最新文章

随机文章

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-03-27 15:15:58 HTTP/2.0 GET : https://f.mffb.com.cn/a/483224.html
  2. 运行时间 : 0.087033s [ 吞吐率:11.49req/s ] 内存消耗:4,574.28kb 文件加载:140
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=273e6f100ecb794cafafc0064fa788a6
  1. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/public/index.php ( 0.79 KB )
  2. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/autoload.php ( 0.17 KB )
  3. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/platform_check.php ( 0.90 KB )
  5. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_static.php ( 4.90 KB )
  7. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  10. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  11. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  12. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  13. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  14. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  15. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  16. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  17. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  18. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  19. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  20. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  21. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  22. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/provider.php ( 0.19 KB )
  23. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  24. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  25. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  26. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/common.php ( 0.03 KB )
  27. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  28. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  29. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/app.php ( 0.95 KB )
  30. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cache.php ( 0.78 KB )
  31. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/console.php ( 0.23 KB )
  32. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cookie.php ( 0.56 KB )
  33. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/database.php ( 2.48 KB )
  34. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  35. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/filesystem.php ( 0.61 KB )
  36. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/lang.php ( 0.91 KB )
  37. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/log.php ( 1.35 KB )
  38. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/middleware.php ( 0.19 KB )
  39. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/route.php ( 1.89 KB )
  40. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/session.php ( 0.57 KB )
  41. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/trace.php ( 0.34 KB )
  42. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/view.php ( 0.82 KB )
  43. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/event.php ( 0.25 KB )
  44. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  45. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/service.php ( 0.13 KB )
  46. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/AppService.php ( 0.26 KB )
  47. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  48. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  49. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  50. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  51. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  52. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/services.php ( 0.14 KB )
  53. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  54. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  55. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  56. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  57. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  58. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  59. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  60. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  61. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  62. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  63. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  64. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  65. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  66. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  67. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  68. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  69. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  70. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  71. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  72. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  73. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  74. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  75. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  76. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  77. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  78. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  79. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  80. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  81. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  82. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  83. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/Request.php ( 0.09 KB )
  84. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  85. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/middleware.php ( 0.25 KB )
  86. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  87. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  88. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  89. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  90. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  91. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  92. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  93. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  94. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  95. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  96. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  97. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  98. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  99. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/route/app.php ( 1.72 KB )
  100. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  101. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  102. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  103. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/controller/Index.php ( 4.81 KB )
  104. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/BaseController.php ( 2.05 KB )
  105. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  106. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  107. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  108. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  109. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  110. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  111. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  112. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  113. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  114. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  115. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  116. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  117. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  118. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  119. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  120. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  121. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  122. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  123. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  124. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  125. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  126. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  127. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  128. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  129. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  130. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  131. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  132. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  133. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  134. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  135. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  136. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  137. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  138. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  139. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/runtime/temp/067d451b9a0c665040f3f1bdd3293d68.php ( 11.98 KB )
  140. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.000545s ] mysql:host=127.0.0.1;port=3306;dbname=f_mffb;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.000790s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.000338s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.000275s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.000531s ]
  6. SELECT * FROM `set` [ RunTime:0.000244s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.000558s ]
  8. SELECT * FROM `article` WHERE `id` = 483224 LIMIT 1 [ RunTime:0.000588s ]
  9. UPDATE `article` SET `lasttime` = 1774595758 WHERE `id` = 483224 [ RunTime:0.011925s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 67 LIMIT 1 [ RunTime:0.000320s ]
  11. SELECT * FROM `article` WHERE `id` < 483224 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.000518s ]
  12. SELECT * FROM `article` WHERE `id` > 483224 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.000738s ]
  13. SELECT * FROM `article` WHERE `id` < 483224 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.000776s ]
  14. SELECT * FROM `article` WHERE `id` < 483224 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.002425s ]
  15. SELECT * FROM `article` WHERE `id` < 483224 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.001246s ]
0.088504s