【秒懂音视频开发】20_视频录制02_编程

原文地址: 【秒懂音视频开发】20_视频录制02_编程 - M了个J - 博客园

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

1 依赖库

需要依赖4个库。

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

2 宏定义

#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));

3 权限申请

在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>

4 注册设备

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

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

5 获取输入格式对象

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

6 打开输入设备

// 格式上下文
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;
}

7 打开输出文件

// 打开文件
QFile file(FILENAME);
if (!file.open(QFile::WriteOnly)) {
qDebug() << "file open error" << FILENAME;
// 关闭输入设备
avformat_close_input(&ctx);
return;
}

8 采集视频数据

// 计算每一帧的大小
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;
}
}

9 释放资源

// 释放资源
av_packet_free(&pkt);
// 关闭文件
file.close();
// 关闭设备
avformat_close_input(&ctx);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值