音视频开发—V4L2介绍,FFmpeg 打开摄像头输出yuv文件

实验平台:Ubuntu20.04

摄像头:1080P 监控摄像头,采用V4L2驱动框架

文章目录

    • 1.V4L2相关介绍
      • 1.1. 基本概念
      • 1.2. 主要功能
      • 1.3. V4L2驱动框架
      • 1.4. 主要组件
      • 1.5. 使用V4L2的应用
      • 1.6. 常用V4L2工具
    • 2.ffmpeg命令实现打开摄像头输出yuv文件
    • 3.使用C语言编程实现
    • 4.注意事项
      • 4.1Packet 和 Frame 的区别
      • 4.2为什么读取摄像头时使用 packet而不是 frame?

1.V4L2相关介绍

Video4Linux2(V4L2)是Linux内核中用于视频设备的一个API,旨在提供对视频捕捉、输出和处理设备的支持。它是Video4Linux(V4L)的继任者,具有更强的功能和更好的设计。以下是V4L2的详细介绍:

1.1. 基本概念

  • API: V4L2提供了一个标准的应用程序编程接口(API),使开发者能够在用户空间与视频设备进行交互。
  • 设备文件: 在Linux系统中,视频设备通常表示为 /dev/video0/dev/video1 等设备文件。

1.2. 主要功能

  • 视频捕捉: 从摄像头或其他视频输入设备捕获视频帧。
  • 视频输出: 将视频数据输出到显示设备或其他输出目标。
  • 视频流: 支持视频流的处理和传输,包括实时视频流的捕获和播放。
  • 图像处理: 提供基本的图像处理功能,如缩放、色彩转换等。

1.3. V4L2驱动框架

  • 驱动层: V4L2驱动程序位于内核空间,负责与硬件进行交互,控制视频设备的操作。
  • 用户空间API: 提供给应用程序使用的系统调用接口,如 ioctl 系列函数,用于配置和控制视频设备。

1.4. 主要组件

  • 设备节点: 在 /dev 目录下创建的设备文件,用于用户空间程序访问视频设备。
  • 控制接口: 通过 ioctl 函数设置和获取设备参数,如分辨率、帧率、视频格式等。
  • 缓冲区管理: 支持多种缓冲区管理模式,包括内存映射(mmap)、用户指针(user pointer)和DMA缓冲区(DMABUF)。
  • 格式转换: 支持多种视频格式,如YUV、RGB、MJPEG、H.264等,并提供格式转换功能。

1.5. 使用V4L2的应用

  • 视频采集应用: 使用V4L2 API开发的视频捕捉应用程序,如网络摄像头软件、视频录制软件等。
  • 多媒体框架: GStreamer、FFmpeg等多媒体框架支持V4L2,可以使用这些框架方便地进行视频处理和传输。
  • 嵌入式系统: 在嵌入式Linux系统中,V4L2广泛用于摄像头、视频采集卡等设备的驱动开发。

1.6. 常用V4L2工具

  • v4l2-ctl: 一个命令行工具,用于控制和调试V4L2设备。可以查询设备信息、设置参数、捕获视频帧等。
    v4l2-ctl --list-formats-ext  # 列出设备支持的所有格式
    v4l2-ctl --set-fmt-video=width=1920,height=1080,pixelformat=H264  # 设置视频格式
    v4l2-ctl --stream-mmap --stream-count=100 --stream-to=output.raw  # 捕获视频流
    

比如可以查看本次实验的摄像头的相关参数

marxist@ubuntu:~/Desktop/audio_test/build$ v4l2-ctl --list-formats-ext
ioctl: VIDIOC_ENUM_FMTType: Video Capture[0]: 'MJPG' (Motion-JPEG, compressed)Size: Discrete 1920x1080Interval: Discrete 0.033s (30.000 fps)Size: Discrete 640x480Interval: Discrete 0.008s (120.101 fps)Interval: Discrete 0.011s (90.000 fps)Interval: Discrete 0.017s (60.500 fps)Interval: Discrete 0.033s (30.200 fps)Size: Discrete 1280x720Interval: Discrete 0.017s (60.000 fps)Interval: Discrete 0.033s (30.500 fps)Size: Discrete 1024x768Interval: Discrete 0.033s (30.000 fps)Size: Discrete 800x600Interval: Discrete 0.017s (60.000 fps)Size: Discrete 1280x1024Interval: Discrete 0.033s (30.000 fps)Size: Discrete 320x240Interval: Discrete 0.008s (120.101 fps)[1]: 'YUYV' (YUYV 4:2:2)Size: Discrete 1920x1080Interval: Discrete 0.167s (6.000 fps)Size: Discrete 640x480Interval: Discrete 0.033s (30.000 fps)Size: Discrete 1280x720Interval: Discrete 0.111s (9.000 fps)Size: Discrete 1024x768Interval: Discrete 0.167s (6.000 fps)Size: Discrete 800x600Interval: Discrete 0.050s (20.000 fps)Size: Discrete 1280x1024Interval: Discrete 0.167s (6.000 fps)Size: Discrete 320x240Interval: Discrete 0.033s (30.000 fps)

由上述可知,摄像头一共支持两种格式,一是MJPG格式,已经由硬件压缩好的一种格式,一种就是常见的YUV422格式,YUV同样支持多种分辨率格式。得知这些参数之后,方便编程实现录制输出工作。

2.ffmpeg命令实现打开摄像头输出yuv文件

命令示例:

ffmpeg -f v4l2 -framerate 9 -video_size 1280x720 -pixel_format yuyv422 -i /dev/video0 -c:v rawvideo -pix_fmt yuv420p output.yuv

参数解释:

-f v4l2: 指定输入格式为V4L2(Video4Linux2)。

-framerate 9: 设置帧率为9fps。

-video_size 1280x720: 设置视频分辨率为1280x720(720p)。

-pixel_format yuyv422: 指定像素格式为YUYV422。

-i /dev/video0: 指定输入设备为 /dev/video0

-c:v rawvideo: 指定视频编码器为原始视频(不压缩)。

output.yuv: 指定输出文件名为 output.yuv

播放示例:

注意:需要指定格式和分辨率,原始的数据文件并不包含这些信息,需要手动指定才能播放。

ffplay -pix_fmt yuyv422 -s 1280*720 output.yuv 

效果图:

在这里插入图片描述

此时正常解析出来yuv画面。

3.使用C语言编程实现

主要流程较为简单,如下所示:

在这里插入图片描述

完整代码实现:

extern "C"
{
#include <stdio.h>
#include <stdlib.h>
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libavdevice/avdevice.h>
#include <libswscale/swscale.h>
#include <libavutil/imgutils.h>
}
#include <iostream>
using namespace std;
#define OUTPUT_FILE "output.yuv"
#define CAMERA_DEVICE "/dev/video0"
AVFormatContext *format_ctx = NULL;
AVCodecContext *codec_ctx = NULL;
AVCodec *codec = NULL;
AVPacket packet ;
AVFrame *frame = NULL;
FILE *output_file = NULL;
AVInputFormat *input_format = NULL;
AVDictionary *options; //摄像头相关参数
int video_stream_index = -1;int open_v4l2_cam()
{input_format = av_find_input_format("v4l2");if (!input_format){fprintf(stderr, "Could not find input format 'v4l2'\n");return -1;}// 摄像头支持多种参数,因此使用option 指定参数 最大支持到9帧av_dict_set(&options, "video_size", "1280*720", 0);av_dict_set(&options, "framerate", "9", 0);av_dict_set(&options, "input_format", "yuyv422", 0);int ret = avformat_open_input(&format_ctx, CAMERA_DEVICE, input_format, &options);if (ret != 0){cerr << "open input device fail" << endl;return -1;}ret = avformat_find_stream_info(format_ctx, NULL);if (ret < 0){cerr << "findding stream info" << endl;return -1;}video_stream_index = -1;// 查找视频流for (size_t i = 0; i < format_ctx->nb_streams; i++){/* code */if (format_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO){video_stream_index = i;break;}}if (video_stream_index == -1){cerr << "no found video_steam" << endl;return -1;}return 0;
}
int init_codec_env()
{// 分配帧和数据包frame = av_frame_alloc();av_init_packet(&packet);// 准备写入文件output_file = fopen(OUTPUT_FILE, "wb");if (!output_file){fprintf(stderr, "Error opening output file\n");return -1;}
}void start_ouput_data()
{// 读取视频帧并保存为YUV 文件,cout << "start record" << endl;while (av_read_frame(format_ctx, &packet) >= 0){if (packet.stream_index == video_stream_index){fwrite(packet.data, 1, packet.size, output_file);}av_packet_unref(&packet);}
}
int main()
{avdevice_register_all(); // Ensure that device library is registeredint ret = open_v4l2_cam();if (ret < 0){cerr << "open cam fail !" << endl;return -1;}ret = init_codec_env();start_ouput_data();// 释放资源fclose(output_file);av_dict_free(&options);avformat_close_input(&format_ctx);return 0;
}

输出的yuv文件,为没有被编码的原始的数据,需要指定参数才能播放

效果如图:

在这里插入图片描述

4.注意事项

4.1Packet 和 Frame 的区别

  1. Packet(数据包):
    • 一般是指编码后的数据包(如H.264、H.265等编码格式的压缩数据)。
    • 包含元数据和编码数据。
    • 是数据流中的最小单位,可以包含一个完整帧或部分帧的数据。
  2. Frame(帧):
    • 是原始数据的表现形式,未经过编码压缩的原始视频或音频数据。
    • 在视频处理中,一个帧通常是一个完整的视频画面。
    • 在FFmpeg中,帧(AVFrame)是解码后的原始数据或编码前的原始数据。

4.2为什么读取摄像头时使用 packet而不是 frame?

当你通过FFmpeg读取视频数据时,即使没有显式地进行编码,FFmpeg也将视频数据封装在 AVPacket 中。原因如下:

  1. 数据流处理:
    • FFmpeg通过 av_read_frame 函数读取数据流,无论数据是否已经编码,读取到的数据都封装在 AVPacket 结构中。这是因为 AVPacket 是用于传输解码器或编码器之间的数据单位。
  2. 输入格式的处理:
    • 当使用 av_read_frame 从输入设备(如摄像头)读取数据时,FFmpeg将摄像头的原始数据作为 AVPacket 进行处理。这个 AVPacket 包含了从设备获取的原始数据块,即使这些数据是未压缩的。
  3. 统一接口:
    • av_read_frame 提供了一个统一的接口,用于处理各种输入数据流(文件、网络流、设备捕获)。这种设计简化了处理过程,不需要为不同的数据源提供不同的读取机制。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/21314.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ssm整合(spring+springmvc+mybatis)做一个小项目(SpringMVC学习笔记六)

一、mybatis层 1、搭建数据库&#xff1a; //创建数据库 CREATE DATABASE ssmbuild; //选择数据库 USE ssmbuild//检查如果数据库中有books这个表的话就给他删除 DROP TABLE IF EXISTS books//创建表books CREATE TABLE books( bookID INT(10) NOT NULL AUTO_INCREMENT COMME…

二叉树链式结构的实现

1.创建二叉树 (1)创建结构体 typedef int BTDataType;typedef struct BinaryTreeNode {BTDataType _data;struct BinaryTreeNode* _left;struct BinaryTreeNode* _right; }BTNode;(2)根据前序遍历构建树 //通过前序遍历的数组"123##45##6##"构建二叉树 BTNode* Bi…

docker以挂载目录启动容器报错问题的解决

拉取镜像&#xff1a; docker pull elasticsearch:7.4.2 docker pull kibana:7.4.2 创建实例&#xff1a; mkdir -p /mydata/elasticsearch/configmkdir -p /mydata/elasticsearch/dataecho "http.host: 0.0.0.0" >> /mydata/elasticsearch/config/elasti…

vs2019 c++20 规范 STL库中关于时间的模板 ratio<T,U> , duration<T,U> , time_point<T,U>等

(探讨一)在学习线程的时候&#xff0c;一些函数会让线程等待或睡眠一段时间。函数形参是时间单位&#xff0c;那么在 c 中是如何记录和表示时间的呢&#xff1f;以下给出模板简图&#xff1a; &#xff08;2 探讨二&#xff09;接着给出对模板类 duration_values 的成员函数的测…

【Leetcode 705 】设计哈希集合——数组嵌套链表(限制哈希Key)

题目 不使用任何内建的哈希表库设计一个哈希集合&#xff08;HashSet&#xff09;。 实现 MyHashSet 类&#xff1a; void add(key) 向哈希集合中插入值 key 。bool contains(key) 返回哈希集合中是否存在这个值 key 。void remove(key) 将给定值 key 从哈希集合中删除。如果…

免费企业域名备案手把手教程

走的阿里云的备案服务&#xff0c;全程免费 前提 主办者&#xff1a;你的企业主办者负责人&#xff1a;当前登录的阿里云账户的人&#xff0c;不是企业法人的话&#xff0c;得准备委托书&#xff0c;会有地方提供模板&#xff0c;打印一下&#xff0c;签字扫描上传就行域名的…

【强化学习】DPO(Direct Preference Optimization)算法学习笔记

【强化学习】DPO&#xff08;Direct Preference Optimization&#xff09;算法学习笔记 RLHF与DPO的关系KL散度Bradley-Terry模型DPO算法流程参考文献 RLHF与DPO的关系 DPO&#xff08;Direct Preference Optimization&#xff09;和RLHF&#xff08;Reinforcement Learning f…

Kaggle线上零售 CRM分析(RFM+BG-NBD+生存分析+PySpark)

数据集地址&#xff1a;数据集地址 我的NoteBook地址&#xff1a;NoteBook地址 这个此在线零售数据集包含2009年12月1日至2011年12月9日期间的在线零售的所有交易。该公司主要销售独特的各种场合礼品。这家公司的许多客户都是批发商。本文将通过pyspark对数据进行导入与预处理&…

思迈特受邀参加工信部等权威机构行业盛会,探讨AI领域前沿技术

近日&#xff0c;思迈特软件作为国产BI领域知名厂商&#xff0c;多次受邀出席行业盛会&#xff0c;与众多业内专家学者、行业精英及知名企业代表等汇聚一堂共襄盛会&#xff0c;探讨行业前沿热点研究及最新趋势&#xff0c;分享企业数字化建设创新成果与成功实践&#xff0c;共…

Spring高手之路19——Spring AOP注解指南

文章目录 1. 背景2. 基于AspectJ注解来实现AOP3. XML实现和注解实现AOP的代码对比4. AOP通知讲解5. AOP时序图 1. 背景 在现代软件开发中&#xff0c;面向切面编程&#xff08;AOP&#xff09;是一种强大的编程范式&#xff0c;允许开发者跨越应用程序的多个部分定义横切关注点…

深度解析:重庆耶非凡科技有限公司的人力rpo项目

在当今竞争激烈的商业环境中&#xff0c;人力资源项目的成功与否往往决定了一个企业的长远发展。重庆耶非凡科技有限公司作为行业内的佼佼者&#xff0c;其人力资源项目备受瞩目。本文将深入探讨该公司的人力资源项目&#xff0c;特别是其独特的选品师项目和人力RPO服务。 首先…

2024年06月在线IDE流行度最新排名

点击查看最新在线IDE流行度最新排名&#xff08;每月更新&#xff09; 2024年06月在线IDE流行度最新排名 TOP 在线IDE排名是通过分析在线ide名称在谷歌上被搜索的频率而创建的 在线IDE被搜索的次数越多&#xff0c;人们就会认为它越受欢迎。原始数据来自谷歌Trends 如果您相…

数字光强测量仪OPT3001

外观 参考价格 原理图 频谱 特性 说明 OPT3001 传感器用于测量可见光的密度。传感器的光 谱响应与人眼的视觉响应紧密匹配&#xff0c;其中具有很高的红 外线阻隔。 OPT3001 是一款可如人眼般测量光强的单芯片照度 计。OPT3001 器件兼具精密的频谱响应和较强的 IR 阻隔功能&a…

基于Weaviate构建多模态检索和多模态检索增强(RAG): Building Multimodal Search and RAG

Building Multimodal Search and RAG 本文是学习 https://www.deeplearning.ai/short-courses/building-multimodal-search-and-rag/ 这门课的学习笔记。 What you’ll learn in this course Learn how to build multimodal search and RAG systems. RAG systems enhance an …

在iPhone上恢复已删除的Safari历史记录的最佳方法

您是否正在寻找恢复 iPhone 上已删除的 Safari 历史记录的最佳方法&#xff1f;好吧&#xff0c;这篇文章提供了 4 种在有/无备份的情况下恢复 iPhone 上已删除的 Safari 历史记录的最佳方法。现在按照分步指南进行操作。 iPhone 上的 Safari 历史记录会被永久删除吗&#xff1…

kafka 发送文件二进制流及使用header发送附属信息

文章目录 背景案例发送方接收方 背景 需要使用kafka发送文件二进制以及附属信息 案例 发送方 import org.apache.kafka.clients.producer.KafkaProducer; import org.apache.kafka.clients.producer.ProducerRecord;import java.io.InputStream; import java.nio.charset.S…

Halo DB 魔法之 pg_pcpu_limit

↑ 关注「少安事务所」公众号&#xff0c;欢迎⭐收藏&#xff0c;不错过精彩内容~ 前情回顾 前面已经介绍了“光环”数据库的基本情况和安装办法&#xff0c;今天来介绍一个新话题。 哈喽&#xff0c;国产数据库&#xff01;Halo DB! 三步走&#xff0c;Halo DB 安装指引 ★ Ha…

Java Agent利器

一、JavaAgent技术 1.1 什么是JavaAgent JavaAgent是一种特殊的Java程序&#xff0c;是Instrumentation的客户端。它与普通Java程序通过main方法启动不同&#xff0c;JavaAgent并不是一个可以单独启动的程序&#xff0c;它必须依附在一个Java应用程序&#xff08;JVM&#xf…

java并发常见问题

1.死锁&#xff1a;当两个或多个线程无限期地等待对方释放锁时发生死锁。为了避免这种情况&#xff0c;你应该尽量减少锁定资源的时间&#xff0c;按顺序获取锁&#xff0c;并使用定时锁尝试。 2.竞态条件&#xff1a;当程序的行为依赖于线程的执行顺序或输入数据到达的顺序时…

Lagrange ZK Coprocessor:革新区块链领域的大数据应用

1. 引言 2024年5月11日&#xff0c;Lagrange Labs宣称获得由Founders Fund领投&#xff08;Archetype Ventures, 1kx, Maven11, Fenbushi Capital, Volt Capital, CMT Digital, Mantle Ecosystem Fund和其它天使投资人跟头&#xff09;的1320万美金种子轮融资&#xff0c;致力于…