Ubuntu下使用ffmpeg调用设备摄像头采集视频,保存yuv文件并播放

Ubuntu下使用ffmpeg调用设备摄像头采集视频,保存yuv文件并播放

打开视频设备

AVFormatContext* open_dev()
{
    // 获取采集格式
    AVInputFormat *inputFmt = av_find_input_format("video4linux2"); // 视频

    int ret = 0;
    AVFormatContext *fmt_ctx = NULL;
    char *deviceName = "/dev/video0"; // 视频设备
    AVDictionary *options = NULL;

    av_dict_set(&options, "video_size", "640x480", 0);  // 为打开视频设备设置参数
//    av_dict_set(&options, "pixel_format", "yuyv422",0);
    // 打开设备
    ret = avformat_open_input(&fmt_ctx, deviceName, inputFmt, &options);

    char errors[1024] = {0};
    if (ret < 0)
    {
        av_strerror(ret, errors, 1024);
        printf("Failed to open audio device, [%d]%s\n", ret, errors);
        return NULL;
    }
    return fmt_ctx;
}

录制视频并保存文件

void MainWindow::rec_video()
{
    AVFormatContext *fmt_ctx = NULL;
    AVPacket packet;
    av_init_packet(&packet);
    int ret = 0;
    // 设置日志级别
    av_log_set_level(AV_LOG_DEBUG);
    // 注册设备
    avdevice_register_all();

    // 创建文件
    char *outPath = "/opt/document/vedio.yuv";   // 保存视频文件
    FILE *outFile = fopen(outPath, "wb+");
    if (!outFile)
    {
        goto __ERROR;
    }

    // 打开设备
    fmt_ctx = open_dev();
    if (!fmt_ctx)
    {
        goto __ERROR;
    }

    while ((ret = av_read_frame(fmt_ctx, &packet) == 0) && m_status)
    {
        av_log(NULL, AV_LOG_INFO, "Packet size: %d(%p)\n",
               packet.size, packet.data);

        // 写入文件
        fwrite(packet.data, 1, packet.size, outFile);
        fflush(outFile);

        // 释放packet空间
        av_packet_unref(&packet);
    }

__ERROR:

    // 关闭文件
    if (outFile)
    {
        fclose(outFile);
    }

    // 关闭设备,释放上下文空间
    if (fmt_ctx)
    {
        avformat_close_input(&fmt_ctx);
    }

    av_log(NULL, AV_LOG_DEBUG, "Finish!\n");
}

下图为获取到的视频数据包大小:
在这里插入图片描述

av_read_frame阻塞问题:

采集视频时遇到了一个问题,就是程序执行到**while ((ret = av_read_frame(fmt_ctx, &packet) == 0) && m_status)**语句时会阻塞,程序一直卡在这个地方,没有返回,输出区没有packet大小,保存的文件大小为0字节。
因为我在虚拟机中连接了主机的摄像头,打开设备时摄像头也点亮了,所以我一直以为是代码有问题,尝试设置了回调、延时等等方法,都没有效果。最后我使用cheese调用摄像头,发现摄像头采集不到画面,我才发现是虚拟机设置的问题。
在这里插入图片描述
可以根据下拉列表具体内容选择,我这里改成了USB3.1。
然后再执行代码,很流畅的采集到了视频。
使用ffplay播放采集到的视频也正常。

ffplay -pix_fmt yuyv422 -s 640x480 vedio.yuv 

播放参数设置可以根据实际情况修改。
在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

VectorAL

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

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

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

打赏作者

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

抵扣说明:

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

余额充值