美文网首页
19_视频录制02_编程

19_视频录制02_编程

作者: 咸鱼Jay | 来源:发表于2022-11-08 17:07 被阅读0次

本文的主要内容:演示如何通过编程采集摄像头的视频数据。
整体的流程跟《08_音频录制02_编程》类似。

依赖库

需要依赖4个库。

extern "C" {
#include <libavdevice/avdevice.h>
#include <libavformat/avformat.h>
#include <libavutil/avutil.h>
#include <libavutil/imgutils.h>
#include <libavcodec/avcodec.h>
}

宏定义

#ifdef Q_OS_WIN
    // 格式名称
    #define FMT_NAME "dshow"
    // 设备名称
    #define DEVICE_NAME "video=Integrated Camera"
    // YUV文件名
    #define FILENAME "F:/out.yuv"
#else
    #define FMT_NAME "avfoundation"
    #define DEVICE_NAME "0"
    #define FILENAME "/Users/mj/Desktop/out.yuv"
#endif

#define ERROR_BUF(ret) \
    char errbuf[1024]; \
    av_strerror(ret, errbuf, sizeof (errbuf));

权限申请

在Mac平台,有2个注意点:

  • 需要在Info.plist中添加摄像头的使用说明,申请摄像头的使用权限
  • 使用Debug模式运行程序
  • 不然会出现闪退的情况
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
        <key>NSCameraUsageDescription</key>
        <string>使用摄像头采集您的靓照</string>
</dict>
</plist>

注册设备

在整个程序的运行过程中,只需要执行1次注册设备的代码。

// 初始化libavdevice并注册所有输入和输出设备
avdevice_register_all();

获取输入格式对象

// 获取输入格式对象
AVInputFormat *fmt = av_find_input_format(FMT_NAME);
if (!fmt) {
    qDebug() << "av_find_input_format error" << FMT_NAME;
    return;
}

打开输入设备

// 格式上下文
AVFormatContext *ctx = nullptr;

// 传递给输入设备的参数
AVDictionary *options = nullptr;
av_dict_set(&options, "video_size", "640x480", 0);
av_dict_set(&options, "pixel_format", "yuyv422", 0);
av_dict_set(&options, "framerate", "30", 0);

// 打开输入设备
int ret = avformat_open_input(&ctx, DEVICE_NAME, fmt, &options);
if (ret < 0) {
    ERROR_BUF(ret);
    qDebug() << "avformat_open_input error" << errbuf;
    return;
}

打开输出文件

// 打开文件
QFile file(FILENAME);
if (!file.open(QFile::WriteOnly)) {
    qDebug() << "file open error" << FILENAME;

    // 关闭输入设备
    avformat_close_input(&ctx);
    return;
}

采集视频数据

// 计算每一帧的大小
AVCodecParameters *params = ctx->streams[0]->codecpar;
int imageSize = av_image_get_buffer_size(
                    (AVPixelFormat) params->format,
                    params->width, params->height,
                    1);

// 数据包
AVPacket *pkt = av_packet_alloc();
while (!isInterruptionRequested()) {
    // 不断采集数据
    ret = av_read_frame(ctx, pkt);

    if (ret == 0) { // 读取成功
        // 将数据写入文件
        file.write((const char *) pkt->data, imageSize);
        /*
         这里要使用imageSize,而不是pkt->size。
         pkt->size有可能比imageSize大(比如在Mac平台),
         使用pkt->size会导致写入一些多余数据到YUV文件中,
         进而导致YUV内容无法正常播放
        */

        // 释放资源
        av_packet_unref(pkt);
    } else if (ret == AVERROR(EAGAIN)) { // 资源临时不可用
        continue;
    } else { // 其他错误
        ERROR_BUF(ret);
        qDebug() << "av_read_frame error" << errbuf;
        break;
    }
}

释放资源

// 释放资源
av_packet_free(&pkt);

// 关闭文件
file.close();

// 关闭设备
avformat_close_input(&ctx);

代码链接

相关文章

  • 19_视频录制02_编程

    本文的主要内容:演示如何通过编程采集摄像头的视频数据。整体的流程跟《08_音频录制02_编程[https://ww...

  • 09_使用SDL播放PCM

    通过命令ffpay播放PCM 可以使用ffplay播放《08_音频录制02_编程[https://www.jian...

  • 08_音频录制02_编程

    通过编程录音 开发录音功能的主要步骤是: 注册设备 获取输入格式对象 打开设备 采集数据 释放资源 需要用到的FF...

  • 音视频-视频录制编程

    Mac下ffmpeg视频录制 Mac下ffmpeg音频录制 对比命令行的录制音频和视频. 其实可以猜得到, 视频...

  • 函数式编程和链式编程

    链式编程的代表:masonry框架。函数式编程的代表:ReactiveCocoa框架。 本人录制技术视频地址:ht...

  • 关于学习方法

    我最近在一个培训机构学习编程语言python,课程是在线学习提前录制好的视频,然后老师直播串讲。录制的视频每节只有...

  • 专业正版一键解锁,不要太爽,低调使用...

    录制视频是一个很常见的需求,比如给别人录制操作步骤,做B站等视频平台需要录制视频,录制网课等教学课程,录制游戏视频...

  • 《录制视频》

    讲师四期翟冲【原创】分享第604天2018.08.29今天我们几个伙伴一块录制视频,完成幸福家第三阶的作业。因为昨...

  • 视频录制

    https://www.jianshu.com/p/fe00883ad3d2https://www.jianshu...

  • 视频录制

    视频录制需要导入AVFoundation框架,视频录制的基本步骤: <1>创建视频、音频设备<2>指定视频、音频设...

网友评论

      本文标题:19_视频录制02_编程

      本文链接:https://www.haomeiwen.com/subject/wvpitdtx.html