UP-MOBNET-Ⅱ型实验箱摄像机视频采集实验

文章目录

  • 实验箱型号
  • 实验内容和材料准备
  • 实验环境准备
    • 试验箱烧写linux系统
    • redHat配置交叉编译环境
  • V4l2视频采集原理
  • 编写摄像机驱动程序和测试程序
    • camer.h
    • camer.c
    • main.c
    • Makefile
  • 特别强调
  • 交叉编译驱动程序
  • 移植和演示程序

实验箱型号


名称 移动互联网教学科研平台Ⅱ型
型号 UP-MOBNET-Ⅱ
编号 03019024
批号 32017040520

实验内容和材料准备



实验内容:
      实验了解v4l2视频采集过程和原理、熟悉试验箱开发环境和烧写流程、交叉编译原理和程序移植。
硬件:
      UP-MobNet-II 型平台、12V 电源线、串口线、USB 数据线
软件:
      Xshell、fastboot.exe、fastboot.bat、WinImage.exe

实验环境准备



整体流程:

#mermaid-svg-oGmR2hhwXmh0iAVM .label{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);fill:#333;color:#333}#mermaid-svg-oGmR2hhwXmh0iAVM .label text{fill:#333}#mermaid-svg-oGmR2hhwXmh0iAVM .node rect,#mermaid-svg-oGmR2hhwXmh0iAVM .node circle,#mermaid-svg-oGmR2hhwXmh0iAVM .node ellipse,#mermaid-svg-oGmR2hhwXmh0iAVM .node polygon,#mermaid-svg-oGmR2hhwXmh0iAVM .node path{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-oGmR2hhwXmh0iAVM .node .label{text-align:center;fill:#333}#mermaid-svg-oGmR2hhwXmh0iAVM .node.clickable{cursor:pointer}#mermaid-svg-oGmR2hhwXmh0iAVM .arrowheadPath{fill:#333}#mermaid-svg-oGmR2hhwXmh0iAVM .edgePath .path{stroke:#333;stroke-width:1.5px}#mermaid-svg-oGmR2hhwXmh0iAVM .flowchart-link{stroke:#333;fill:none}#mermaid-svg-oGmR2hhwXmh0iAVM .edgeLabel{background-color:#e8e8e8;text-align:center}#mermaid-svg-oGmR2hhwXmh0iAVM .edgeLabel rect{opacity:0.9}#mermaid-svg-oGmR2hhwXmh0iAVM .edgeLabel span{color:#333}#mermaid-svg-oGmR2hhwXmh0iAVM .cluster rect{fill:#ffffde;stroke:#aa3;stroke-width:1px}#mermaid-svg-oGmR2hhwXmh0iAVM .cluster text{fill:#333}#mermaid-svg-oGmR2hhwXmh0iAVM div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:12px;background:#ffffde;border:1px solid #aa3;border-radius:2px;pointer-events:none;z-index:100}#mermaid-svg-oGmR2hhwXmh0iAVM .actor{stroke:#ccf;fill:#ECECFF}#mermaid-svg-oGmR2hhwXmh0iAVM text.actor>tspan{fill:#000;stroke:none}#mermaid-svg-oGmR2hhwXmh0iAVM .actor-line{stroke:grey}#mermaid-svg-oGmR2hhwXmh0iAVM .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333}#mermaid-svg-oGmR2hhwXmh0iAVM .messageLine1{stroke-width:1.5;stroke-dasharray:2, 2;stroke:#333}#mermaid-svg-oGmR2hhwXmh0iAVM #arrowhead path{fill:#333;stroke:#333}#mermaid-svg-oGmR2hhwXmh0iAVM .sequenceNumber{fill:#fff}#mermaid-svg-oGmR2hhwXmh0iAVM #sequencenumber{fill:#333}#mermaid-svg-oGmR2hhwXmh0iAVM #crosshead path{fill:#333;stroke:#333}#mermaid-svg-oGmR2hhwXmh0iAVM .messageText{fill:#333;stroke:#333}#mermaid-svg-oGmR2hhwXmh0iAVM .labelBox{stroke:#ccf;fill:#ECECFF}#mermaid-svg-oGmR2hhwXmh0iAVM .labelText,#mermaid-svg-oGmR2hhwXmh0iAVM .labelText>tspan{fill:#000;stroke:none}#mermaid-svg-oGmR2hhwXmh0iAVM .loopText,#mermaid-svg-oGmR2hhwXmh0iAVM .loopText>tspan{fill:#000;stroke:none}#mermaid-svg-oGmR2hhwXmh0iAVM .loopLine{stroke-width:2px;stroke-dasharray:2, 2;stroke:#ccf;fill:#ccf}#mermaid-svg-oGmR2hhwXmh0iAVM .note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-oGmR2hhwXmh0iAVM .noteText,#mermaid-svg-oGmR2hhwXmh0iAVM .noteText>tspan{fill:#000;stroke:none}#mermaid-svg-oGmR2hhwXmh0iAVM .activation0{fill:#f4f4f4;stroke:#666}#mermaid-svg-oGmR2hhwXmh0iAVM .activation1{fill:#f4f4f4;stroke:#666}#mermaid-svg-oGmR2hhwXmh0iAVM .activation2{fill:#f4f4f4;stroke:#666}#mermaid-svg-oGmR2hhwXmh0iAVM .mermaid-main-font{font-family:"trebuchet ms", verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-oGmR2hhwXmh0iAVM .section{stroke:none;opacity:0.2}#mermaid-svg-oGmR2hhwXmh0iAVM .section0{fill:rgba(102,102,255,0.49)}#mermaid-svg-oGmR2hhwXmh0iAVM .section2{fill:#fff400}#mermaid-svg-oGmR2hhwXmh0iAVM .section1,#mermaid-svg-oGmR2hhwXmh0iAVM .section3{fill:#fff;opacity:0.2}#mermaid-svg-oGmR2hhwXmh0iAVM .sectionTitle0{fill:#333}#mermaid-svg-oGmR2hhwXmh0iAVM .sectionTitle1{fill:#333}#mermaid-svg-oGmR2hhwXmh0iAVM .sectionTitle2{fill:#333}#mermaid-svg-oGmR2hhwXmh0iAVM .sectionTitle3{fill:#333}#mermaid-svg-oGmR2hhwXmh0iAVM .sectionTitle{text-anchor:start;font-size:11px;text-height:14px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-oGmR2hhwXmh0iAVM .grid .tick{stroke:#d3d3d3;opacity:0.8;shape-rendering:crispEdges}#mermaid-svg-oGmR2hhwXmh0iAVM .grid .tick text{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-oGmR2hhwXmh0iAVM .grid path{stroke-width:0}#mermaid-svg-oGmR2hhwXmh0iAVM .today{fill:none;stroke:red;stroke-width:2px}#mermaid-svg-oGmR2hhwXmh0iAVM .task{stroke-width:2}#mermaid-svg-oGmR2hhwXmh0iAVM .taskText{text-anchor:middle;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-oGmR2hhwXmh0iAVM .taskText:not([font-size]){font-size:11px}#mermaid-svg-oGmR2hhwXmh0iAVM .taskTextOutsideRight{fill:#000;text-anchor:start;font-size:11px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-oGmR2hhwXmh0iAVM .taskTextOutsideLeft{fill:#000;text-anchor:end;font-size:11px}#mermaid-svg-oGmR2hhwXmh0iAVM .task.clickable{cursor:pointer}#mermaid-svg-oGmR2hhwXmh0iAVM .taskText.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-oGmR2hhwXmh0iAVM .taskTextOutsideLeft.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-oGmR2hhwXmh0iAVM .taskTextOutsideRight.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-oGmR2hhwXmh0iAVM .taskText0,#mermaid-svg-oGmR2hhwXmh0iAVM .taskText1,#mermaid-svg-oGmR2hhwXmh0iAVM .taskText2,#mermaid-svg-oGmR2hhwXmh0iAVM .taskText3{fill:#fff}#mermaid-svg-oGmR2hhwXmh0iAVM .task0,#mermaid-svg-oGmR2hhwXmh0iAVM .task1,#mermaid-svg-oGmR2hhwXmh0iAVM .task2,#mermaid-svg-oGmR2hhwXmh0iAVM .task3{fill:#8a90dd;stroke:#534fbc}#mermaid-svg-oGmR2hhwXmh0iAVM .taskTextOutside0,#mermaid-svg-oGmR2hhwXmh0iAVM .taskTextOutside2{fill:#000}#mermaid-svg-oGmR2hhwXmh0iAVM .taskTextOutside1,#mermaid-svg-oGmR2hhwXmh0iAVM .taskTextOutside3{fill:#000}#mermaid-svg-oGmR2hhwXmh0iAVM .active0,#mermaid-svg-oGmR2hhwXmh0iAVM .active1,#mermaid-svg-oGmR2hhwXmh0iAVM .active2,#mermaid-svg-oGmR2hhwXmh0iAVM .active3{fill:#bfc7ff;stroke:#534fbc}#mermaid-svg-oGmR2hhwXmh0iAVM .activeText0,#mermaid-svg-oGmR2hhwXmh0iAVM .activeText1,#mermaid-svg-oGmR2hhwXmh0iAVM .activeText2,#mermaid-svg-oGmR2hhwXmh0iAVM .activeText3{fill:#000 !important}#mermaid-svg-oGmR2hhwXmh0iAVM .done0,#mermaid-svg-oGmR2hhwXmh0iAVM .done1,#mermaid-svg-oGmR2hhwXmh0iAVM .done2,#mermaid-svg-oGmR2hhwXmh0iAVM .done3{stroke:grey;fill:#d3d3d3;stroke-width:2}#mermaid-svg-oGmR2hhwXmh0iAVM .doneText0,#mermaid-svg-oGmR2hhwXmh0iAVM .doneText1,#mermaid-svg-oGmR2hhwXmh0iAVM .doneText2,#mermaid-svg-oGmR2hhwXmh0iAVM .doneText3{fill:#000 !important}#mermaid-svg-oGmR2hhwXmh0iAVM .crit0,#mermaid-svg-oGmR2hhwXmh0iAVM .crit1,#mermaid-svg-oGmR2hhwXmh0iAVM .crit2,#mermaid-svg-oGmR2hhwXmh0iAVM .crit3{stroke:#f88;fill:red;stroke-width:2}#mermaid-svg-oGmR2hhwXmh0iAVM .activeCrit0,#mermaid-svg-oGmR2hhwXmh0iAVM .activeCrit1,#mermaid-svg-oGmR2hhwXmh0iAVM .activeCrit2,#mermaid-svg-oGmR2hhwXmh0iAVM .activeCrit3{stroke:#f88;fill:#bfc7ff;stroke-width:2}#mermaid-svg-oGmR2hhwXmh0iAVM .doneCrit0,#mermaid-svg-oGmR2hhwXmh0iAVM .doneCrit1,#mermaid-svg-oGmR2hhwXmh0iAVM .doneCrit2,#mermaid-svg-oGmR2hhwXmh0iAVM .doneCrit3{stroke:#f88;fill:#d3d3d3;stroke-width:2;cursor:pointer;shape-rendering:crispEdges}#mermaid-svg-oGmR2hhwXmh0iAVM .milestone{transform:rotate(45deg) scale(0.8, 0.8)}#mermaid-svg-oGmR2hhwXmh0iAVM .milestoneText{font-style:italic}#mermaid-svg-oGmR2hhwXmh0iAVM .doneCritText0,#mermaid-svg-oGmR2hhwXmh0iAVM .doneCritText1,#mermaid-svg-oGmR2hhwXmh0iAVM .doneCritText2,#mermaid-svg-oGmR2hhwXmh0iAVM .doneCritText3{fill:#000 !important}#mermaid-svg-oGmR2hhwXmh0iAVM .activeCritText0,#mermaid-svg-oGmR2hhwXmh0iAVM .activeCritText1,#mermaid-svg-oGmR2hhwXmh0iAVM .activeCritText2,#mermaid-svg-oGmR2hhwXmh0iAVM .activeCritText3{fill:#000 !important}#mermaid-svg-oGmR2hhwXmh0iAVM .titleText{text-anchor:middle;font-size:18px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-oGmR2hhwXmh0iAVM g.classGroup text{fill:#9370db;stroke:none;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:10px}#mermaid-svg-oGmR2hhwXmh0iAVM g.classGroup text .title{font-weight:bolder}#mermaid-svg-oGmR2hhwXmh0iAVM g.clickable{cursor:pointer}#mermaid-svg-oGmR2hhwXmh0iAVM g.classGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-oGmR2hhwXmh0iAVM g.classGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-oGmR2hhwXmh0iAVM .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5}#mermaid-svg-oGmR2hhwXmh0iAVM .classLabel .label{fill:#9370db;font-size:10px}#mermaid-svg-oGmR2hhwXmh0iAVM .relation{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-oGmR2hhwXmh0iAVM .dashed-line{stroke-dasharray:3}#mermaid-svg-oGmR2hhwXmh0iAVM #compositionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-oGmR2hhwXmh0iAVM #compositionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-oGmR2hhwXmh0iAVM #aggregationStart{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-oGmR2hhwXmh0iAVM #aggregationEnd{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-oGmR2hhwXmh0iAVM #dependencyStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-oGmR2hhwXmh0iAVM #dependencyEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-oGmR2hhwXmh0iAVM #extensionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-oGmR2hhwXmh0iAVM #extensionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-oGmR2hhwXmh0iAVM .commit-id,#mermaid-svg-oGmR2hhwXmh0iAVM .commit-msg,#mermaid-svg-oGmR2hhwXmh0iAVM .branch-label{fill:lightgrey;color:lightgrey;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-oGmR2hhwXmh0iAVM .pieTitleText{text-anchor:middle;font-size:25px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-oGmR2hhwXmh0iAVM .slice{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-oGmR2hhwXmh0iAVM g.stateGroup text{fill:#9370db;stroke:none;font-size:10px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-oGmR2hhwXmh0iAVM g.stateGroup text{fill:#9370db;fill:#333;stroke:none;font-size:10px}#mermaid-svg-oGmR2hhwXmh0iAVM g.statediagram-cluster .cluster-label text{fill:#333}#mermaid-svg-oGmR2hhwXmh0iAVM g.stateGroup .state-title{font-weight:bolder;fill:#000}#mermaid-svg-oGmR2hhwXmh0iAVM g.stateGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-oGmR2hhwXmh0iAVM g.stateGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-oGmR2hhwXmh0iAVM .transition{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-oGmR2hhwXmh0iAVM .stateGroup .composit{fill:white;border-bottom:1px}#mermaid-svg-oGmR2hhwXmh0iAVM .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px}#mermaid-svg-oGmR2hhwXmh0iAVM .state-note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-oGmR2hhwXmh0iAVM .state-note text{fill:black;stroke:none;font-size:10px}#mermaid-svg-oGmR2hhwXmh0iAVM .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.7}#mermaid-svg-oGmR2hhwXmh0iAVM .edgeLabel text{fill:#333}#mermaid-svg-oGmR2hhwXmh0iAVM .stateLabel text{fill:#000;font-size:10px;font-weight:bold;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-oGmR2hhwXmh0iAVM .node circle.state-start{fill:black;stroke:black}#mermaid-svg-oGmR2hhwXmh0iAVM .node circle.state-end{fill:black;stroke:white;stroke-width:1.5}#mermaid-svg-oGmR2hhwXmh0iAVM #statediagram-barbEnd{fill:#9370db}#mermaid-svg-oGmR2hhwXmh0iAVM .statediagram-cluster rect{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-oGmR2hhwXmh0iAVM .statediagram-cluster rect.outer{rx:5px;ry:5px}#mermaid-svg-oGmR2hhwXmh0iAVM .statediagram-state .divider{stroke:#9370db}#mermaid-svg-oGmR2hhwXmh0iAVM .statediagram-state .title-state{rx:5px;ry:5px}#mermaid-svg-oGmR2hhwXmh0iAVM .statediagram-cluster.statediagram-cluster .inner{fill:white}#mermaid-svg-oGmR2hhwXmh0iAVM .statediagram-cluster.statediagram-cluster-alt .inner{fill:#e0e0e0}#mermaid-svg-oGmR2hhwXmh0iAVM .statediagram-cluster .inner{rx:0;ry:0}#mermaid-svg-oGmR2hhwXmh0iAVM .statediagram-state rect.basic{rx:5px;ry:5px}#mermaid-svg-oGmR2hhwXmh0iAVM .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#efefef}#mermaid-svg-oGmR2hhwXmh0iAVM .note-edge{stroke-dasharray:5}#mermaid-svg-oGmR2hhwXmh0iAVM .statediagram-note rect{fill:#fff5ad;stroke:#aa3;stroke-width:1px;rx:0;ry:0}:root{--mermaid-font-family: '"trebuchet ms", verdana, arial';--mermaid-font-family: "Comic Sans MS", "Comic Sans", cursive}#mermaid-svg-oGmR2hhwXmh0iAVM .error-icon{fill:#522}#mermaid-svg-oGmR2hhwXmh0iAVM .error-text{fill:#522;stroke:#522}#mermaid-svg-oGmR2hhwXmh0iAVM .edge-thickness-normal{stroke-width:2px}#mermaid-svg-oGmR2hhwXmh0iAVM .edge-thickness-thick{stroke-width:3.5px}#mermaid-svg-oGmR2hhwXmh0iAVM .edge-pattern-solid{stroke-dasharray:0}#mermaid-svg-oGmR2hhwXmh0iAVM .edge-pattern-dashed{stroke-dasharray:3}#mermaid-svg-oGmR2hhwXmh0iAVM .edge-pattern-dotted{stroke-dasharray:2}#mermaid-svg-oGmR2hhwXmh0iAVM .marker{fill:#333}#mermaid-svg-oGmR2hhwXmh0iAVM .marker.cross{stroke:#333}:root { --mermaid-font-family: "trebuchet ms", verdana, arial;} #mermaid-svg-oGmR2hhwXmh0iAVM {color: rgba(0, 0, 0, 0.75);font: ;}

实验环境准备
实验箱Linux环境
交叉编译环境
交叉编译程序
程序移植
测试程序

试验箱烧写linux系统



UP-MobNet-II 型出厂程序烧写
注:出厂烧写文件镜像及工具存放在光盘的 IMG 文件夹下!且 u-boot 一般用户无需更改,该烧写步骤可以略过。
该试验箱u-boot不需要改动;出厂时BootLoader已经写好


1. 连线:
将产品附带串口线一端连接到 PC 机端串口,另一端连接到 UP-MobNet-II 型平台串口 0(RS232-0 即开发板左侧起靠近网口的串口)上。
将产品附带 USB 数据线连接 PC 机 USB 口与 UP-MobNet-II 型平台 OTG 接口。
其中串口大概是4、电源开关是1、网线口是2、usb数据线口(OTG接口)是3


2. 跳线: 备注:核心板内侧为 1,外侧为 0,跳线模式出厂已经默认跳到 iNAND 模式,根据需要更改。
这里试验箱跳线一般已经调好,不需要改动


3. 使用Xshell登录UP-MobNet-II 型系统串口终端

(如果这时间有需要安装驱动,在Win10中可以下载驱动精灵,其可以帮助管理所需要的驱动)

首先查看电脑的端口号:
电脑->管理->设备管理器(Win10需要在查看中打开显示隐藏设备)->端口(COM)


Xshell连接UP-MobNet-II :
Xshell->文件->新建->连接->协议serial->串口->选择自己的COM->波特率115200->连接


确定连接后,连接电源。按下 UP-MobNet-II 型平台左上角 POWER 电源键,系统上电。Xshell 进入开发板的 U-BOOT 功能界面(3秒等待),(3秒内)按下回车,进入 U-BOOT 界面


在 u-boot 界面下,输入 fastboot 命令.


因为该板子BootLoader出厂写好了不需要烧写 u-boot.bin
直接烧写系统镜像 zImage、rootfs_up4412.cramfs:

双击光盘/IMG/fastboot.bat 文件->选择'2'kernel 烧写 zImage(完成后)->选择‘3’system 烧写 rootfs_up4412.cramfs


完成烧写,重启实验平台,加载启动信息

如下图所示:

查看端口号:

Xshell连接实验箱:

进入Uboot模式

使用fastboot工具

烧写完成,加载启动信息




redHat配置交叉编译环境

将光盘中交叉编译工具的源码 arm-2009q3.tar.bz2 拷贝到/usr/local/arm(没有该目录就新建一个)目录下,并解压:


#tar jxvf arm-2009q3.tar.bz2
2. 修改环境变量:
#vim ~/.bashrc
在文件末添加
export PATH=/usr/local/arm/arm-2009q3/bin:$PATH
编译器安装成功。
#source ~/.bashrc
测试
arm-none-linux-gnueabi-gcc -v
注意,如果是64位Linux系统(ubuntu20),需要再安装额外的一些软件。如下操作。
 .安装32位库(64位系统需要)
  因为ia32-libs数据库的问题需安装32位库
  依次执行下列命令即可
1. sudo dpkg --add-architecture i386
2. sudo apt-get update
3. sudo apt-get dist-upgrade
ubuntu 20安装以上库之后,还是提示找不到arm-none-linux-gnueabi-gcc错误。之后安装libc6-i386库,解决问题。
apt-get install libc6-i386
测试
arm-none-linux-gnueabi-gcc -v


arm-none-linux-gnueabi-gcc -v


V4l2视频采集原理

#mermaid-svg-4vo7RPli9axzDKTk .label{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);fill:#333;color:#333}#mermaid-svg-4vo7RPli9axzDKTk .label text{fill:#333}#mermaid-svg-4vo7RPli9axzDKTk .node rect,#mermaid-svg-4vo7RPli9axzDKTk .node circle,#mermaid-svg-4vo7RPli9axzDKTk .node ellipse,#mermaid-svg-4vo7RPli9axzDKTk .node polygon,#mermaid-svg-4vo7RPli9axzDKTk .node path{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-4vo7RPli9axzDKTk .node .label{text-align:center;fill:#333}#mermaid-svg-4vo7RPli9axzDKTk .node.clickable{cursor:pointer}#mermaid-svg-4vo7RPli9axzDKTk .arrowheadPath{fill:#333}#mermaid-svg-4vo7RPli9axzDKTk .edgePath .path{stroke:#333;stroke-width:1.5px}#mermaid-svg-4vo7RPli9axzDKTk .flowchart-link{stroke:#333;fill:none}#mermaid-svg-4vo7RPli9axzDKTk .edgeLabel{background-color:#e8e8e8;text-align:center}#mermaid-svg-4vo7RPli9axzDKTk .edgeLabel rect{opacity:0.9}#mermaid-svg-4vo7RPli9axzDKTk .edgeLabel span{color:#333}#mermaid-svg-4vo7RPli9axzDKTk .cluster rect{fill:#ffffde;stroke:#aa3;stroke-width:1px}#mermaid-svg-4vo7RPli9axzDKTk .cluster text{fill:#333}#mermaid-svg-4vo7RPli9axzDKTk div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:12px;background:#ffffde;border:1px solid #aa3;border-radius:2px;pointer-events:none;z-index:100}#mermaid-svg-4vo7RPli9axzDKTk .actor{stroke:#ccf;fill:#ECECFF}#mermaid-svg-4vo7RPli9axzDKTk text.actor>tspan{fill:#000;stroke:none}#mermaid-svg-4vo7RPli9axzDKTk .actor-line{stroke:grey}#mermaid-svg-4vo7RPli9axzDKTk .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333}#mermaid-svg-4vo7RPli9axzDKTk .messageLine1{stroke-width:1.5;stroke-dasharray:2, 2;stroke:#333}#mermaid-svg-4vo7RPli9axzDKTk #arrowhead path{fill:#333;stroke:#333}#mermaid-svg-4vo7RPli9axzDKTk .sequenceNumber{fill:#fff}#mermaid-svg-4vo7RPli9axzDKTk #sequencenumber{fill:#333}#mermaid-svg-4vo7RPli9axzDKTk #crosshead path{fill:#333;stroke:#333}#mermaid-svg-4vo7RPli9axzDKTk .messageText{fill:#333;stroke:#333}#mermaid-svg-4vo7RPli9axzDKTk .labelBox{stroke:#ccf;fill:#ECECFF}#mermaid-svg-4vo7RPli9axzDKTk .labelText,#mermaid-svg-4vo7RPli9axzDKTk .labelText>tspan{fill:#000;stroke:none}#mermaid-svg-4vo7RPli9axzDKTk .loopText,#mermaid-svg-4vo7RPli9axzDKTk .loopText>tspan{fill:#000;stroke:none}#mermaid-svg-4vo7RPli9axzDKTk .loopLine{stroke-width:2px;stroke-dasharray:2, 2;stroke:#ccf;fill:#ccf}#mermaid-svg-4vo7RPli9axzDKTk .note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-4vo7RPli9axzDKTk .noteText,#mermaid-svg-4vo7RPli9axzDKTk .noteText>tspan{fill:#000;stroke:none}#mermaid-svg-4vo7RPli9axzDKTk .activation0{fill:#f4f4f4;stroke:#666}#mermaid-svg-4vo7RPli9axzDKTk .activation1{fill:#f4f4f4;stroke:#666}#mermaid-svg-4vo7RPli9axzDKTk .activation2{fill:#f4f4f4;stroke:#666}#mermaid-svg-4vo7RPli9axzDKTk .mermaid-main-font{font-family:"trebuchet ms", verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-4vo7RPli9axzDKTk .section{stroke:none;opacity:0.2}#mermaid-svg-4vo7RPli9axzDKTk .section0{fill:rgba(102,102,255,0.49)}#mermaid-svg-4vo7RPli9axzDKTk .section2{fill:#fff400}#mermaid-svg-4vo7RPli9axzDKTk .section1,#mermaid-svg-4vo7RPli9axzDKTk .section3{fill:#fff;opacity:0.2}#mermaid-svg-4vo7RPli9axzDKTk .sectionTitle0{fill:#333}#mermaid-svg-4vo7RPli9axzDKTk .sectionTitle1{fill:#333}#mermaid-svg-4vo7RPli9axzDKTk .sectionTitle2{fill:#333}#mermaid-svg-4vo7RPli9axzDKTk .sectionTitle3{fill:#333}#mermaid-svg-4vo7RPli9axzDKTk .sectionTitle{text-anchor:start;font-size:11px;text-height:14px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-4vo7RPli9axzDKTk .grid .tick{stroke:#d3d3d3;opacity:0.8;shape-rendering:crispEdges}#mermaid-svg-4vo7RPli9axzDKTk .grid .tick text{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-4vo7RPli9axzDKTk .grid path{stroke-width:0}#mermaid-svg-4vo7RPli9axzDKTk .today{fill:none;stroke:red;stroke-width:2px}#mermaid-svg-4vo7RPli9axzDKTk .task{stroke-width:2}#mermaid-svg-4vo7RPli9axzDKTk .taskText{text-anchor:middle;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-4vo7RPli9axzDKTk .taskText:not([font-size]){font-size:11px}#mermaid-svg-4vo7RPli9axzDKTk .taskTextOutsideRight{fill:#000;text-anchor:start;font-size:11px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-4vo7RPli9axzDKTk .taskTextOutsideLeft{fill:#000;text-anchor:end;font-size:11px}#mermaid-svg-4vo7RPli9axzDKTk .task.clickable{cursor:pointer}#mermaid-svg-4vo7RPli9axzDKTk .taskText.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-4vo7RPli9axzDKTk .taskTextOutsideLeft.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-4vo7RPli9axzDKTk .taskTextOutsideRight.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-4vo7RPli9axzDKTk .taskText0,#mermaid-svg-4vo7RPli9axzDKTk .taskText1,#mermaid-svg-4vo7RPli9axzDKTk .taskText2,#mermaid-svg-4vo7RPli9axzDKTk .taskText3{fill:#fff}#mermaid-svg-4vo7RPli9axzDKTk .task0,#mermaid-svg-4vo7RPli9axzDKTk .task1,#mermaid-svg-4vo7RPli9axzDKTk .task2,#mermaid-svg-4vo7RPli9axzDKTk .task3{fill:#8a90dd;stroke:#534fbc}#mermaid-svg-4vo7RPli9axzDKTk .taskTextOutside0,#mermaid-svg-4vo7RPli9axzDKTk .taskTextOutside2{fill:#000}#mermaid-svg-4vo7RPli9axzDKTk .taskTextOutside1,#mermaid-svg-4vo7RPli9axzDKTk .taskTextOutside3{fill:#000}#mermaid-svg-4vo7RPli9axzDKTk .active0,#mermaid-svg-4vo7RPli9axzDKTk .active1,#mermaid-svg-4vo7RPli9axzDKTk .active2,#mermaid-svg-4vo7RPli9axzDKTk .active3{fill:#bfc7ff;stroke:#534fbc}#mermaid-svg-4vo7RPli9axzDKTk .activeText0,#mermaid-svg-4vo7RPli9axzDKTk .activeText1,#mermaid-svg-4vo7RPli9axzDKTk .activeText2,#mermaid-svg-4vo7RPli9axzDKTk .activeText3{fill:#000 !important}#mermaid-svg-4vo7RPli9axzDKTk .done0,#mermaid-svg-4vo7RPli9axzDKTk .done1,#mermaid-svg-4vo7RPli9axzDKTk .done2,#mermaid-svg-4vo7RPli9axzDKTk .done3{stroke:grey;fill:#d3d3d3;stroke-width:2}#mermaid-svg-4vo7RPli9axzDKTk .doneText0,#mermaid-svg-4vo7RPli9axzDKTk .doneText1,#mermaid-svg-4vo7RPli9axzDKTk .doneText2,#mermaid-svg-4vo7RPli9axzDKTk .doneText3{fill:#000 !important}#mermaid-svg-4vo7RPli9axzDKTk .crit0,#mermaid-svg-4vo7RPli9axzDKTk .crit1,#mermaid-svg-4vo7RPli9axzDKTk .crit2,#mermaid-svg-4vo7RPli9axzDKTk .crit3{stroke:#f88;fill:red;stroke-width:2}#mermaid-svg-4vo7RPli9axzDKTk .activeCrit0,#mermaid-svg-4vo7RPli9axzDKTk .activeCrit1,#mermaid-svg-4vo7RPli9axzDKTk .activeCrit2,#mermaid-svg-4vo7RPli9axzDKTk .activeCrit3{stroke:#f88;fill:#bfc7ff;stroke-width:2}#mermaid-svg-4vo7RPli9axzDKTk .doneCrit0,#mermaid-svg-4vo7RPli9axzDKTk .doneCrit1,#mermaid-svg-4vo7RPli9axzDKTk .doneCrit2,#mermaid-svg-4vo7RPli9axzDKTk .doneCrit3{stroke:#f88;fill:#d3d3d3;stroke-width:2;cursor:pointer;shape-rendering:crispEdges}#mermaid-svg-4vo7RPli9axzDKTk .milestone{transform:rotate(45deg) scale(0.8, 0.8)}#mermaid-svg-4vo7RPli9axzDKTk .milestoneText{font-style:italic}#mermaid-svg-4vo7RPli9axzDKTk .doneCritText0,#mermaid-svg-4vo7RPli9axzDKTk .doneCritText1,#mermaid-svg-4vo7RPli9axzDKTk .doneCritText2,#mermaid-svg-4vo7RPli9axzDKTk .doneCritText3{fill:#000 !important}#mermaid-svg-4vo7RPli9axzDKTk .activeCritText0,#mermaid-svg-4vo7RPli9axzDKTk .activeCritText1,#mermaid-svg-4vo7RPli9axzDKTk .activeCritText2,#mermaid-svg-4vo7RPli9axzDKTk .activeCritText3{fill:#000 !important}#mermaid-svg-4vo7RPli9axzDKTk .titleText{text-anchor:middle;font-size:18px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-4vo7RPli9axzDKTk g.classGroup text{fill:#9370db;stroke:none;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:10px}#mermaid-svg-4vo7RPli9axzDKTk g.classGroup text .title{font-weight:bolder}#mermaid-svg-4vo7RPli9axzDKTk g.clickable{cursor:pointer}#mermaid-svg-4vo7RPli9axzDKTk g.classGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-4vo7RPli9axzDKTk g.classGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-4vo7RPli9axzDKTk .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5}#mermaid-svg-4vo7RPli9axzDKTk .classLabel .label{fill:#9370db;font-size:10px}#mermaid-svg-4vo7RPli9axzDKTk .relation{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-4vo7RPli9axzDKTk .dashed-line{stroke-dasharray:3}#mermaid-svg-4vo7RPli9axzDKTk #compositionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-4vo7RPli9axzDKTk #compositionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-4vo7RPli9axzDKTk #aggregationStart{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-4vo7RPli9axzDKTk #aggregationEnd{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-4vo7RPli9axzDKTk #dependencyStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-4vo7RPli9axzDKTk #dependencyEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-4vo7RPli9axzDKTk #extensionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-4vo7RPli9axzDKTk #extensionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-4vo7RPli9axzDKTk .commit-id,#mermaid-svg-4vo7RPli9axzDKTk .commit-msg,#mermaid-svg-4vo7RPli9axzDKTk .branch-label{fill:lightgrey;color:lightgrey;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-4vo7RPli9axzDKTk .pieTitleText{text-anchor:middle;font-size:25px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-4vo7RPli9axzDKTk .slice{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-4vo7RPli9axzDKTk g.stateGroup text{fill:#9370db;stroke:none;font-size:10px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-4vo7RPli9axzDKTk g.stateGroup text{fill:#9370db;fill:#333;stroke:none;font-size:10px}#mermaid-svg-4vo7RPli9axzDKTk g.statediagram-cluster .cluster-label text{fill:#333}#mermaid-svg-4vo7RPli9axzDKTk g.stateGroup .state-title{font-weight:bolder;fill:#000}#mermaid-svg-4vo7RPli9axzDKTk g.stateGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-4vo7RPli9axzDKTk g.stateGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-4vo7RPli9axzDKTk .transition{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-4vo7RPli9axzDKTk .stateGroup .composit{fill:white;border-bottom:1px}#mermaid-svg-4vo7RPli9axzDKTk .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px}#mermaid-svg-4vo7RPli9axzDKTk .state-note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-4vo7RPli9axzDKTk .state-note text{fill:black;stroke:none;font-size:10px}#mermaid-svg-4vo7RPli9axzDKTk .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.7}#mermaid-svg-4vo7RPli9axzDKTk .edgeLabel text{fill:#333}#mermaid-svg-4vo7RPli9axzDKTk .stateLabel text{fill:#000;font-size:10px;font-weight:bold;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-4vo7RPli9axzDKTk .node circle.state-start{fill:black;stroke:black}#mermaid-svg-4vo7RPli9axzDKTk .node circle.state-end{fill:black;stroke:white;stroke-width:1.5}#mermaid-svg-4vo7RPli9axzDKTk #statediagram-barbEnd{fill:#9370db}#mermaid-svg-4vo7RPli9axzDKTk .statediagram-cluster rect{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-4vo7RPli9axzDKTk .statediagram-cluster rect.outer{rx:5px;ry:5px}#mermaid-svg-4vo7RPli9axzDKTk .statediagram-state .divider{stroke:#9370db}#mermaid-svg-4vo7RPli9axzDKTk .statediagram-state .title-state{rx:5px;ry:5px}#mermaid-svg-4vo7RPli9axzDKTk .statediagram-cluster.statediagram-cluster .inner{fill:white}#mermaid-svg-4vo7RPli9axzDKTk .statediagram-cluster.statediagram-cluster-alt .inner{fill:#e0e0e0}#mermaid-svg-4vo7RPli9axzDKTk .statediagram-cluster .inner{rx:0;ry:0}#mermaid-svg-4vo7RPli9axzDKTk .statediagram-state rect.basic{rx:5px;ry:5px}#mermaid-svg-4vo7RPli9axzDKTk .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#efefef}#mermaid-svg-4vo7RPli9axzDKTk .note-edge{stroke-dasharray:5}#mermaid-svg-4vo7RPli9axzDKTk .statediagram-note rect{fill:#fff5ad;stroke:#aa3;stroke-width:1px;rx:0;ry:0}:root{--mermaid-font-family: '"trebuchet ms", verdana, arial';--mermaid-font-family: "Comic Sans MS", "Comic Sans", cursive}#mermaid-svg-4vo7RPli9axzDKTk .error-icon{fill:#522}#mermaid-svg-4vo7RPli9axzDKTk .error-text{fill:#522;stroke:#522}#mermaid-svg-4vo7RPli9axzDKTk .edge-thickness-normal{stroke-width:2px}#mermaid-svg-4vo7RPli9axzDKTk .edge-thickness-thick{stroke-width:3.5px}#mermaid-svg-4vo7RPli9axzDKTk .edge-pattern-solid{stroke-dasharray:0}#mermaid-svg-4vo7RPli9axzDKTk .edge-pattern-dashed{stroke-dasharray:3}#mermaid-svg-4vo7RPli9axzDKTk .edge-pattern-dotted{stroke-dasharray:2}#mermaid-svg-4vo7RPli9axzDKTk .marker{fill:#333}#mermaid-svg-4vo7RPli9axzDKTk .marker.cross{stroke:#333}:root { --mermaid-font-family: "trebuchet ms", verdana, arial;} #mermaid-svg-4vo7RPli9axzDKTk {color: rgba(0, 0, 0, 0.75);font: ;}

打开视频设备
设定属性
设定采集方式
处理数据
关闭视频设备

采集方式
打开视频设备后,可以设置该视频设备的属性,例如裁剪、缩放等。这一步是可选的。在Linux编程中,一般使用ioctl函数来对设备的I/O通道进行管理:
extern int ioctl (int __fd, unsigned long int __request, …) __THROW;
__fd:设备的ID,例如刚才用open函数打开视频通道后返回的cameraFd;
__request:具体的命令标志符。
在进行V4L2开发中,一般会用到以下的命令标志符:

VIDIOC_REQBUFS:分配内存
VIDIOC_QUERYBUF:把VIDIOC_REQBUFS中分配的数据缓存转换成物理地址
VIDIOC_QUERYCAP:查询驱动功能
VIDIOC_ENUM_FMT:获取当前驱动支持的视频格式
VIDIOC_S_FMT:设置当前驱动的频捕获格式
VIDIOC_G_FMT:读取当前驱动的频捕获格式
VIDIOC_TRY_FMT:验证当前驱动的显示格式
VIDIOC_CROPCAP:查询驱动的修剪能力
VIDIOC_S_CROP:设置视频信号的边框
VIDIOC_G_CROP:读取视频信号的边框
VIDIOC_QBUF:把数据放回缓存队列
VIDIOC_DQBUF:把数据从缓存中读取出来
VIDIOC_STREAMON:开始视频显示函数
VIDIOC_STREAMOFF:结束视频显示函数
VIDIOC_QUERYSTD:检查当前视频设备支持的标准,例如PAL或NTSC。
这些IO调用,有些是必须的,有些是可选择的。
操作流程
1. 打开设备文件。
int fd=open(”/dev/video0″,O_RDWR);
2. 取得设备的capability,看看设备具有什么功能,比如是否具有视频输入,或者音频输入输出等。VIDIOC_QUERYCAP,struct v4l2_capability
v4l2_std_id std;
do {ret= ioctl(fd, VIDIOC_QUERYSTD, &std);
} while (ret == -1 && errno == EAGAIN);
switch (std) {case V4L2_STD_NTSC:
//……
case V4L2_STD_PAL:
//……}

操作流程

  1. 打开设备文件。
int fd=open(”/dev/video0″,O_RDWR);
  1. 取得设备的capability,看看设备具有什么功能,比如是否具有视频输入,或者音频输入输出等。VIDIOC_QUERYCAP,struct v4l2_capability
v4l2_std_id std;
do {ret= ioctl(fd, VIDIOC_QUERYSTD, &std);
} while (ret == -1 && errno == EAGAIN);
switch (std) {case V4L2_STD_NTSC:
//……
case V4L2_STD_PAL:
//……
}
  1. 选择视频输入,一个视频设备可以有多个视频输入。

VIDIOC_S_INPUT,struct v4l2_input(可不要)

  1. 设置视频的制式和帧格式,制式包括PAL,NTSC,帧的格式个包括宽度和高度等。
VIDIOC_S_STD,VIDIOC_S_FMT,struct v4l2_std_id,struct v4l2_format
struct v4l2_format fmt;v4l2_format 结构如下:
struct v4l2_format
{enum v4l2_buf_type type; // 数据流类型,必须永远是V4L2_BUF_TYPE_VIDEO_CAPTURE
union
{struct v4l2_pix_format pix;
struct v4l2_window win;
struct v4l2_vbi_format vbi;
__u8 raw_data[200];
} fmt;
};
struct v4l2_pix_format
{__u32 width; // 宽,必须是16 的倍数
__u32 height; // 高,必须是16 的倍数
__u32 pixelformat; // 视频数据存储类型,例如是YUV 4 :2 :2 还是RGB
enum v4l2_field field;
__u32 bytesperline;
__u32 sizeimage;
enum v4l2_colorspace colorspace;
__u32 priv;
};

样例:

memset ( &fmt, 0, sizeof(fmt) );
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.width = 320;
fmt.fmt.pix.height = 240;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_JPEG;
if (ioctl(fd, VIDIOC_S_FMT, &fmt) < 0)
{printf("set format failed\n");
//return 0;
}
  1. 向驱动申请帧缓冲,一般不超过5个。struct v4l2_requestbuffers
struct v4l2_requestbuffers
{__u32 count; // 缓存数量,也就是说在缓存队列里保持多少张照片
enum v4l2_buf_type type; // 数据流类型,必须永远是V4L2_BUF_TYPE_VIDEO_CAPTURE
enum v4l2_memory memory; // V4L2_MEMORY_MMAP 或 V4L2_MEMORY_USERPTR
__u32 reserved[2];
};

样例:

struct v4l2_requestbuffers req;
memset(&req, 0, sizeof (req));
req.count = 4;
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_MMAP;
if (ioctl(fd,VIDIOC_REQBUFS,&req) == -1)
{perror("VIDIOC_REQBUFS error \n");
//return -1;
}

6.申请物理内存

将申请到的帧缓冲映射到用户空间,这样就可以直接操作采集到的帧了,而不必去复制。将申请到的帧缓冲全部入队列,以便存放采集到的数据.VIDIOC_QBUF,struct v4l2_buffer

VideoBuffer* buffers = calloc( req.count, sizeof(VideoBuffer) );
printf("sizeof(VideoBuffer) is %d\n",sizeof(VideoBuffer));
struct v4l2_buffer buf;
for (numBufs = 0; numBufs < req.count; numBufs++)
{memset( &buf, 0, sizeof(buf) );
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = numBufs;
if (ioctl(fd, VIDIOC_QUERYBUF, &buf) < 0)
{printf("VIDIOC_QUERYBUF error\n");
//return -1;
}
printf("buf len is %d\n",sizeof(buf));
//内存映射
buffers[numBufs].length = buf.length;
buffers[numBufs].offset = (size_t) buf.m.offset;
buffers[numBufs].start = mmap (NULL, buf.length,PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.offset);
printf("buffers.length = %d,buffers.offset = %d ,buffers.start[0] = %d\n",buffers[numBufs].length,buffers[numBufs].offset,buffers[numBufs].start[0]);
printf("buf2 len is %d\n",sizeof(buffers[numBufs].start));
if (buffers[numBufs].start == MAP_FAILED)
{perror("buffers error\n");
//return -1;
}
if (ioctl (fd, VIDIOC_QBUF, &buf) < 0)
{printf("VIDIOC_QBUF error\n");
//return -1;
}
}
  1. 开始视频的采集。
enum v4l2_buf_type type;
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (ioctl (fd, VIDIOC_STREAMON, &type) < 0)
{printf("VIDIOC_STREAMON error\n");
// return -1;
}
7. 出队列以取得已采集数据的帧缓冲,取得原始采集数据。VIDIOC_DQBUF, 将缓冲重新入队列尾,这样可以循环采集。VIDIOC_QBUF
if (ioctl(fd, VIDIOC_DQBUF, &buf) < 0)
{perror("VIDIOC_DQBUF failed.\n");
//return -1;
}
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
unsigned char *ptcur = buffers[numBufs].start;
DEBUG("buf.bytesused = %d \n",buf.bytesused);
int i1;
for(i1=0; i1<buf.bytesused; i1++)
{if((buffers[numBufs].start[i1] == 0x000000FF) && (buffers[numBufs].start[i1+1] == 0x000000C4))
{DEBUG("huffman table finded! \nbuf.bytesused = %d\nFFC4 = %d \n",buf.bytesused,i1);
break;
}
}
if(i1 == buf.bytesused)printf("huffman table don't exist! \n");
int i;
for(i=0; i<buf.bytesused; i++)
{if((buffers[numBufs].start[i] == 0x000000FF) && (buffers[numBufs].start[i+1] == 0x000000D8)) break;
ptcur++;
}
DEBUG("i=%d,FF=%02x,D8=%02x\n",i,buffers[numBufs].start[i],buffers[numBufs].start[i+1]);
int imagesize =buf.bytesused - i;
DEBUG("buf.bytesused = %d \n",buf.bytesused);
DEBUG ("imagesize = %d \n",imagesize);
  1. 停止视频的采集。VIDIOC_STREAMOFF
  2. 关闭视频设备。close(fd);

编写摄像机驱动程序和测试程序

v4l2视频流采集:

camer.h
/*************************************************************************> File Name: camer.h> 作者:YJK > Mail: 745506980@qq.com > Created Time: 2020年11月18日 星期三 14时17分55秒************************************************************************/#ifndef   __CAMER_H
#define __CAMER_H
#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>
#include<stdlib.h>
#include<linux/videodev2.h>
#include<sys/ioctl.h>
#include<errno.h>
#include<string.h>
#include<assert.h>
#include<getopt.h>
#include<sys/stat.h>
#include<sys/mman.h>
#include<asm/types.h>
#include<linux/fb.h>#define CLEAN(x) (memset(&(x), 0, sizeof(x)))#define WIDTH 640#define HEIGHT 480typedef struct Video_Buffer{void * start;unsigned int length;
}Video_Buffer;int ioctl_(int fd, int request, void *arg);void sys_exit(const char *s);int open_device(const char * device_name);int open_file(const char * file_name);void start_stream(void);void end_stream(void);int init_device(void);int init_mmap(void);static int read_frame(void);int process_frame(void);void close_mmap(void);void close_device(void);#endif
camer.c
/*
*    Copyright (C) 2020   JunKe Yuan<745506980@qq.com>
*
*    This  is free software; you can redistribute it and/or
*    modify it under the terms of the GNU Lesser General Public
*    License as published by the Free Software Foundation; either
*    version 2.1 of the License, or (at your option) any later version.
*
*    This  is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
*    Lesser General Public License for more details.
*
*    You should have received a copy of the GNU Lesser General Public
*    License along with this library; if not, write to the Free Software
*    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
*    USA
*
*/ #include "camer.h"
#include <linux/i2c.h>
#include <linux/videodev2.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/select.h>
#include <time.h>int fd;
int file_fd;
int frame_size;
static Video_Buffer * buffer = NULL;
int ioctl_(int fd, int request, void *arg)
{int ret = 0;do{ret = ioctl(fd, request, arg);}while(ret == -1 && ret == EINTR);return ret;
}int open_device(const char * device_name)
{struct stat st;if( -1 == stat( device_name, &st ) ){printf( "Cannot identify '%s'\n" , device_name );return -1;}if ( !S_ISCHR( st.st_mode ) ){printf( "%s is no device\n" , device_name );return -1;}fd = open(device_name, O_RDWR | O_NONBLOCK , 0);if ( -1 == fd ){printf( "Cannot open '%s'\n" , device_name );return -1;}return 0;
}int init_device()
{//查询设备信息struct v4l2_capability cap;if (ioctl_(fd, VIDIOC_QUERYCAP, &cap) == -1){perror("VIDIOC_QUERYCAP");return -1;}printf("---------------------LINE:%d\n", __LINE__);printf("DriverName:%s\nCard Name:%s\nBus info:%s\nDriverVersion:%u.%u.%u\n",cap.driver,cap.card,cap.bus_info,(cap.version>>16)&0xFF,(cap.version>>8)&0xFF,(cap.version)&0xFF); //选择视频输入struct v4l2_input input;CLEAN(input);input.index = 0;if ( ioctl_(fd, VIDIOC_S_INPUT,&input) == -1){printf("VIDIOC_S_INPUT IS ERROR! LINE:%d\n",__LINE__);return -1;}/*查看摄像头支持的视频格式*/struct v4l2_fmtdesc fmtdesc;
//  struct v4l2_frmsizeenum frmsize;fmtdesc.index = 0;fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;printf("fm:\n");while(ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc) != -1){  //列举出所有支持的格式printf("%d.%s   %c%c%c%c\n", fmtdesc.index + 1, fmtdesc.description, fmtdesc.pixelformat &  0xFF,(fmtdesc.pixelformat >> 8) & 0xFF,(fmtdesc.pixelformat >> 16) & 0xFF,(fmtdesc.pixelformat >> 24) & 0xFF);
#if 0frmsize.pixel_format = fmtdesc.pixelformat;frmsize.index = 0;while(ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &frmsize) != -1){          printf("%dx%d\n",frmsize.discrete.width, frmsize.discrete.height);frmsize.index++;}
#endif      fmtdesc.index++;}   /*查看摄像头支持的分辨率*///设置帧格式struct v4l2_format fmt;CLEAN(fmt);fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;fmt.fmt.pix.width = WIDTH;fmt.fmt.pix.height = HEIGHT;//视频格式//  fmt.fmt.pix.pixelformat = pixformat;fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YVU420;
//  fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;if (ioctl_(fd, VIDIOC_S_FMT, &fmt) == -1){printf("VIDIOC_S_FMT IS ERROR! LINE:%d\n",__LINE__);return -1;}fmt.type = V4L2_BUF_TYPE_PRIVATE;if (ioctl_(fd, VIDIOC_S_FMT, &fmt) == -1){printf("VIDIOC_S_FMT IS ERROR! LINE:%d\n", __LINE__);return -1;}//查看帧格式fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;if ( ioctl_(fd, VIDIOC_G_FMT, &fmt) == -1){printf("VIDIOC_G_FMT IS ERROR! LINE:%d\n", __LINE__);return -1;}printf("width:%d\nheight:%d\npixelformat:%c%c%c%c field:%d\n",fmt.fmt.pix.width, fmt.fmt.pix.height,fmt.fmt.pix.pixelformat &  0xFF,(fmt.fmt.pix.pixelformat >> 8) & 0xFF,(fmt.fmt.pix.pixelformat >> 16) & 0xFF,(fmt.fmt.pix.pixelformat >> 24) & 0xFF,fmt.fmt.pix.field);
#if 0   /*设置流相关  帧率*/struct v4l2_streamparm parm;CLEAN(parm);parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;parm.parm.capture.capability = V4L2_CAP_TIMEPERFRAME; //是否可以被timeperframe参数控制帧率parm.parm.capture.timeperframe.denominator = 30; //时间间隔分母parm.parm.capture.timeperframe.numerator = 1; //分子 if (ioctl_(fd, VIDIOC_S_PARM, &parm) == -1){//    printf("VIDIOC_S_PARM IS ERROR! \n");perror("VIDIOC_S_PARM");return -1;}if (ioctl_(fd, VIDIOC_G_PARM, (struct v4l2_streamparm*)&parm) == -1){     printf("VIDIOC_G_PARM IS ERROR! \n");return -1;}
#endif#if 1
/*YUYV*/__u32 min = fmt.fmt.pix.width * 2;if ( fmt.fmt.pix.bytesperline < min )fmt.fmt.pix.bytesperline = min;
/*YUV420*/min = ( unsigned int )WIDTH * HEIGHT * 3 / 2;if ( fmt.fmt.pix.sizeimage < min )fmt.fmt.pix.sizeimage = min;frame_size = fmt.fmt.pix.sizeimage;printf("After Buggy driver paranoia\n");printf("    >>fmt.fmt.pix.sizeimage = %d\n", fmt.fmt.pix.sizeimage);printf("    >>fmt.fmt.pix.bytesperline = %d\n", fmt.fmt.pix.bytesperline);printf("-#-#-#-#-#-#-#-#-#-#-#-#-#-\n");printf("\n");
#endifreturn 0;}int init_mmap()
{//申请帧缓冲区struct v4l2_requestbuffers req;CLEAN(req);req.count = 4;req.memory = V4L2_MEMORY_MMAP;  //使用内存映射缓冲区req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;//申请4个帧缓冲区,在内核空间中if ( ioctl_(fd, VIDIOC_REQBUFS, &req) == -1 ) {printf("VIDIOC_REQBUFS IS ERROR! LINE:%d\n",__LINE__);return -1;}//获取每个帧信息,并映射到用户空间buffer = (Video_Buffer *)calloc(req.count, sizeof(Video_Buffer));if (buffer == NULL){printf("calloc is error! LINE:%d\n",__LINE__);return -1;}struct v4l2_buffer buf;int buf_index = 0;for (buf_index = 0; buf_index < req.count; buf_index ++){CLEAN(buf);buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;buf.index = buf_index;buf.memory = V4L2_MEMORY_MMAP;if (ioctl_(fd, VIDIOC_QUERYBUF, &buf) == -1) //获取每个帧缓冲区的信息 如length和offset{printf("VIDIOC_QUERYBUF IS ERROR! LINE:%d\n",__LINE__);return -1;}//将内核空间中的帧缓冲区映射到用户空间buffer[buf_index].length = buf.length;buffer[buf_index].start = mmap(NULL, //由内核分配映射的起始地址buf.length,//长度PROT_READ | PROT_WRITE, //可读写MAP_SHARED,//可共享fd,buf.m.offset);if (buffer[buf_index].start == MAP_FAILED){printf("MAP_FAILED LINE:%d\n",__LINE__);return -1;}//将帧缓冲区放入视频输入队列if (ioctl_(fd, VIDIOC_QBUF, &buf) == -1){printf("VIDIOC_QBUF IS ERROR! LINE:%d\n", __LINE__);return -1;}       printf("Frame buffer :%d   address :0x%x    length:%d\n",buf_index, (__u32)buffer[buf_index].start, buffer[buf_index].length);}   return 0;
}void start_stream()
{enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;if (ioctl_(fd, VIDIOC_STREAMON, &type) == -1){fprintf(stderr, "VIDIOC_STREAMON IS ERROR! LINE:%d\n", __LINE__);exit(EXIT_FAILURE);}
}
void end_stream()
{enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;if (ioctl_(fd, VIDIOC_STREAMOFF, &type) == -1){fprintf(stderr, "VIDIOC_STREAMOFF IS ERROR! LINE:%d\n", __LINE__);exit(EXIT_FAILURE);}
}int read_frame()
{struct v4l2_buffer buf;int ret = 0;CLEAN(buf);buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;buf.memory = V4L2_MEMORY_MMAP;if (ioctl_(fd, VIDIOC_DQBUF, &buf) == -1){printf("VIDIOC_DQBUF! LINEL:%d\n", __LINE__);return -1;}
//  time_t start,end;
//  start = time(NULL);
#if 1   ret = write(file_fd, buffer[0].start ,frame_size);
//  printf("write:%d\n",frame_size);#endif
#if 0ret = Encode_frame(en, pixformat, file_fd, buf_sp, buffer[0].start, WIDTH, HEIGHT, timer);    if (ret == -1){fprintf(stderr,"Encode_frame\n");return -1;}
#endif
//  end = time(NULL);
//  printf("time:%0.f\n",difftime(end, start));if (ioctl_(fd, VIDIOC_QBUF, &buf) == -1){printf("VIDIOC_QBUF! LINE:%d\n", __LINE__);return -1;}return 0;
}int open_file(const char * file_name)
{file_fd = open(file_name, O_RDWR | O_CREAT, 0777);if (file_fd == -1){printf("open file is error! LINE:%d\n", __LINE__);return -1;}return 0;
//  file = fopen(file_name, "wr+");
}void close_mmap()
{int i = 0;for (i = 0; i < 4 ; i++){munmap(buffer[i].start, buffer[i].length);}free(buffer);
}
void close_device()
{close(fd);close(file_fd);
}
int process_frame()
{struct timeval tvptr;int ret;tvptr.tv_usec = 0;  //等待50 ustvptr.tv_sec = 2;fd_set fdread;FD_ZERO(&fdread);FD_SET(fd, &fdread);ret = select(fd + 1, &fdread, NULL, NULL, &tvptr);if (ret == -1){perror("EXIT_FAILURE");exit(EXIT_FAILURE);}if (ret == 0){printf("timeout! \n");}
//  struct timeval start,end;
//  gettimeofday(&start, NULL);if(read_frame() == -1){fprintf(stderr, "readframe is error\n");return -1;}       //  gettimeofday(&end, NULL);
//  printf("time:%ldms\n",(end.tv_sec - start.tv_sec)*1000 + (end.tv_usec - start.tv_usec)/1000);return 0;
}
main.c
/*************************************************************************> File Name: main.c> 作者:YJK > Mail: 745506980@qq.com > Created Time: 2020年11月21日 星期六 18时46分19秒************************************************************************/#include<stdio.h>
#include"camer.h"#define DEVICE_NAME "/dev/video0"#define FILE_NAME "./out.yuv"
int main(int argc,char *argv[])
{int ret = 0;int i;ret = open_device(DEVICE_NAME);if (ret == -1) exit(EXIT_FAILURE);open_file(FILE_NAME);init_device();init_mmap();start_stream();for (i = 0 ; i < 600; i++){process_frame(); printf("frame:%d\n",i);}end_stream();close_mmap();close_device();return 0;
}
Makefile
#########################################################################
# File Name: Makefile
# 作者:YJK
# mail: 745506980@qq.comc
# Created Time: 2021年04月29日 星期四 20时47分10秒
#########################################################################
#    $^ 当前规则中的所有依赖
#    $< 当前规则中的第一个依赖
#    $@ 当前规则中触发命令生成的目标
#    @ 不把执行的信息打印到显示屏上CC = arm-linux-gcc
TARGET = mainOBJS += main.o
OBJS += camer.o$(TARGET) : $(OBJS)$(CC) -o $@ $^%.o : %.c$(CC) -c $< -o $@clean:rm $(TARGET) $(OBJS)

特别强调

Makefile文件中CC指定的是交叉编译的编译工具,我的是arm-linux-gcc,
其他的交叉编译,比如之前的交叉编译环境是arm-none-linux-gnueabi-gcc
就把CC改为CC = arm-none-linux-gnueabi-gcc

CC = arm-linux-gcc


交叉编译驱动程序

在安装Gcc的redHat上新建一个目录:main.c、camer.h、camer.c、Makefile在同一目录下

make编译,编译后如下:

生成main,接下来把main移植到试验箱


移植和演示程序

移植程序的方法有很多:
1. 拷贝到U盘中,再把U盘挂载到实验箱
2. 在PC端使用tftpd32软件,网络通信将程序发送到实验箱
3. 配置samba服务使得PC端、ubuntu和实验箱共享一个网络映射文件


这里只移植一个main所以,用U盘挂载的方法;
1、把main拷贝到U盘
2、把U盘插入实验箱对应的插口
插入以后实验箱打印如下信息:

3、查看U盘信息
命令: fdisk -l

4、挂载U盘
命令:mount -t vfat /dev/sda4 /mnt

5、运行程序

命令: ./main


结束:

6、导出out.you

7、卸载U盘
U盘大的可能时间长一点十多秒

8、在Win10播放
使用的播放器是YUVPlayer.exe
因为视频格式是yuv格式
参数设置

UP-MOBNET-Ⅱ型实验箱摄像机视频采集实验相关推荐

  1. UP-MOBNET-Ⅱ型实验箱LED驱动控制实验

    UP-MOBNET-Ⅱ型实验箱LED驱动控制实验 文章目录 实验箱 实验内容 实验环境 实验原理 硬件接口原理 驱动层程序分析 应用层程序分析: Makefile: 实验步骤 实验目录: 在内核中添加 ...

  2. 计算机组成原理实验箱D7,计算机组成原理实验(实验箱).doc

    计算机组成原理实验(实验箱).doc PAGE PAGE 10 1. A,W寄存器实验实验要求:利用CPTH 实验仪上的K16..K23 开关做为DBUS 的数据,其它开关做为控制信号,将数据写入寄存 ...

  3. 计算机组成原理实验箱D7,计算机组成原理实验.ppt

    文档介绍: TDN-CM实验仪简介TDN-CM实验仪是一个计算机的模型机,采用单元电路结构,实验既可按各单元模块做,也可以将各模块连接成整机运行.实验仪主要分为:运算器模块(ALUUNIT)主存储器模 ...

  4. 高校智能教学时代--- CY-TIY物联网实验箱

    高校智能教学时代--- CY-TIY物联网实验箱 CY-TIY物联网教学实验系统是专为高等院校.职高的物联网专业和计算机.通讯.电子等专业的学生学习.应用物联网技术而开发的完整的实验教学系统,结合现在 ...

  5. 计算机组成原理实验箱连接显示输出,计算机组成原理实验箱介绍.ppt

    计算机组成原理实验箱介绍,,实验系统由实验箱.PC机.软件三大部分组成.本课程围绕实验箱组织教学,通过在实验箱上的一系列实验来学习计算机的基本工作原理.实验箱包含七个部分:,实验箱简介(1),1.数据 ...

  6. 嵌入式LINUX环境下视频采集知识

    Video for Linux two(Video4Linux2)简称V4L2,是V4L的改进版.V4L2是linux操作系统下用于采集图片.视频和音频数据的API接口,配合适当的视频采集设备和相应的 ...

  7. 2021年茶艺师(中级)考试及茶艺师(中级)实操考试视频

    题库来源:安全生产模拟考试一点通公众号小程序 茶艺师(中级)考试根据新茶艺师(中级)考试大纲要求,安全生产模拟考试一点通将茶艺师(中级)模拟考试试题进行汇编,组成一套茶艺师(中级)全真模拟考试试题,学 ...

  8. 2021年美容师(初级)考试内容及美容师(初级)实操考试视频

    题库来源:安全生产模拟考试一点通公众号小程序 美容师(初级)考试内容考前必练!安全生产模拟考试一点通每个月更新美容师(初级)实操考试视频题目及答案!多做几遍,其实通过美容师(初级)操作证考试很简单. ...

  9. 2020中式烹调师(初级)证考试及中式烹调师(初级)实操考试视频

    题库来源:安全生产模拟考试一点通公众号小程序 2020中式烹调师(初级)证考试及中式烹调师(初级)实操考试视频,包含中式烹调师(初级)证考试答案解析及中式烹调师(初级)实操考试视频练习.由安全生产模拟 ...

最新文章

  1. (转帖)数据库时代的终结
  2. ASP.NET使用AJAX应注意IIS有没有.ashx扩展
  3. oracle跨库插入数据,Oracle跨数据库查询并插入实现原理及代码
  4. pdf转word python_Python实现PDF转Word
  5. 【HANA系列】SAP HANA SQL获取当前日期最后一天
  6. Java多线程、主线程等待所有子线程执行完毕、共享资源
  7. PAT 乙级1019 数字黑洞
  8. Ubuntu14.04下安装Samba
  9. 测试文档模板_基于模型的测试(贰)
  10. 滚动长截图,截取第三方应用,如微博、知乎、头条长图文...
  11. 《凤凰项目》--读书笔记
  12. android AndroidManifest.xml 属性详细解析
  13. 亚马逊为证券市场树立标杆 拆股已不再受追捧
  14. 2019-01-01T00:00:00.000Z 这种时间日期类型格式是属于:格林尼治时间
  15. 计算机综合症怎么治,哪些运动可以用来治疗“电脑综合症”
  16. 全景Engine智能管理软件7.0-PLG模式全新上线
  17. Leetcode——226. 翻转二叉树
  18. 【笨木头Unity】入门之旅007:Demo之四处找死(二)_主角移动和旋转
  19. ROS机器人程序设计(原书第2版)补充资料 (零) 源代码、资料和印刷错误修订等 2017年02月22日更新
  20. 网络之TCP与UDP

热门文章

  1. lubuntu(18.04) 安装中文输入法,安装 googlepinyin
  2. 恢复分区导致C盘无法扩展
  3. 人工智能基础之人工智能研究进展及领域
  4. XXL-Job学习笔记
  5. 驾考科目1 非口诀 记忆知识点
  6. 211126-Matlab读取mhd文件并转为dcm
  7. 微信小程序之 判断CheckBox选中状态
  8. v-echarts的介绍及使用
  9. python 计算曲线面积_利用Python中的numpy包实现PR曲线和ROC曲线的计算!
  10. vue 刷新当前页面的方式