ffmpeg 采集视频数据 后播放

本文记录了在Ubuntu虚拟机中解决摄像头无法打开的问题,包括检查设备、更新VMware版本等步骤。此外,还介绍了使用ffmpeg进行音频采集,并通过示例代码展示了如何读取/dev/video0设备的视频数据,强调了正确设置视频格式的重要性。在播放采集的视频数据时,应注意与采集格式匹配。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

虚拟机环境采坑记录:

大坑:关于虚拟机打不开摄像头

我调试的环境是Ubuntu 虚拟机, 首先确认 摄像头 是否可以正常打开,直接用茄子试试: cheese。
如果打不开 首先确认 虚拟机是否有摄像头设备 /dev/video0, 如果没有的话需要添加设备,添加前确认 Windows主机可以打开相机,在设备管理器看一下有没有相机之类的设备,不行的话先卸载驱动 再重新加载驱动。虚拟机有摄像头设备后正常是这样的:
摄像头已连接状态
在这里插入图片描述
在这里插入图片描述

如果打开后界面是黑的,可以尝试 更换USB兼容性
在这里插入图片描述

巨坑:
1 Windows 主机在使能 相机功能时,虚拟机开机直接进入grub界面,或者死机。
2 在虚拟机中打开摄像头,尝试直接 cheese, 虚拟机直接死机

这两个现象折腾了我大半天,最后升级 VMware版本,我把版本从 12.04 升级到 15.5,这个问题解决了!!!

最后虚拟机摄像头完美打开


本实验环境是 Linux系统,内容是 使用 ffmpeg 采集射频数据并播放

#include <stdio.h>
#include <string.h>
#include "libavutil/avutil.h"
#include "libavdevice/avdevice.h"
#include "libavformat/avformat.h"
#include "libavcodec/avcodec.h"
#include "libswresample/swresample.h"


void rec_audio() {

    int ret = 0;
    char errors[1024] = {0, };

    //视频数据上下文
    AVFormatContext *fmt_ctx = NULL;
    AVDictionary *options = NULL;

    //pakcet 存储获取的视频数据
    AVPacket pkt;

	//视频设备节点
    char *devicename = "/dev/video0";

    //set log level
    av_log_set_level(AV_LOG_DEBUG);

    //register audio device  向ffmpeg注册设备
    avdevice_register_all();

    //设置采集方式,对于不同的平台,采集数据的方式不同  linux系统是 
    /*
    返回值:输入格式
    */
	AVInputFormat *iformat = av_find_input_format("v4l2");

	/* 设置视频其他参数
	参数1:视频参数 options
	参数2:指定    -video_size 分辨率参数 640x480 
				  -framerate 帧率 30
	参数3:分辨率
	参数4:暂时不关心
	*/
	av_dict_set(&options,"video_size","640x480",0);
	av_dict_set(&options,"framerate","30",0);
	av_dict_set(&options, "pixel_format", "yuyv422", 0);

    //打开视频设备
    /*
	参数1 获得 视频数据上下文 AVFormatContext
	参数2 网络地址/本地文件(设备名)
	参数3 输入格式
	参数4 其他参数 这里为NULL
    */
    if((ret = avformat_open_input(&fmt_ctx, devicename, iformat, &options)) < 0 ){
        av_strerror(ret, errors, 1024);
        fprintf(stderr, "Failed to open video device, [%d]%s\n", ret, errors);
        return;

    }

    //创建输出的视频文件  将视频数据写到该文件
    char *out = "/home/mhr/Desktop/video/video_test/video.yuv";
    FILE *outfile = fopen(out, "wb+");

 
	/* read data from device  获取视频数据 到pkt
	参数1: 视频数据上下文
	参数2: 视频数据存放的目标地址
	返回值:return 0 is OK
	*/
    while((ret = av_read_frame(fmt_ctx, &pkt)) == 0) {

        av_log(NULL, AV_LOG_INFO,"packet size is %d(%p)\n", pkt.size, pkt.data);

        //write file
		//pkt.size:(宽 X 高) X (yuv420=1.5/yuv422=2/yuv444=3)
        fwrite(pkt.data, 1, pkt.size, outfile);
        fflush(outfile);
        av_packet_unref(&pkt); //release pkt
    }


    //close file
    fclose(outfile);
	
    //关闭设备 并 释放视频数据上下文
    avformat_close_input(&fmt_ctx);
    av_log(NULL, AV_LOG_DEBUG, "finish!\n");

    return;
}

int main(int argc, char *argv[])
{
    rec_audio();
    return 0;
}

注意:播放的时候要注意自己的实验唤醒下 摄像头采集数据的格式,本人的摄像头采集格式是 yuyv422,所以播放的时候也要指明播放格式 !

如果采集视频指定的格式不对,ffmpeg会尝试做纠正:

在这里插入图片描述
如果采用正确的格式 就没有调整格式的过程了:
在这里插入图片描述
可以注意一下 采集的每一帧图像的大小是 614400,正好是符合分辨率为640x480的 yuv422格式的图像大小的。
Y分量:640x480 = 307200
UV分量总和 == Y分量
所以一帧图像大小就是 307200 * 2 = 614400

播放:
ffplay -pix_fmt yuyv422 -s 640x480 video.yuv

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Linux老A

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值