ffmpeg 采集视频数据 后播放

虚拟机环境采坑记录:

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

我调试的环境是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
        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

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/LinuxArmbiggod/article/details/121503308