音视频-视频录制编程

2021-07-14  本文已影响0人  li_礼光
Mac下ffmpeg视频录制
ffmpeg -f avfoundation -framerate 30 -i 0 out.yuv
Mac下ffmpeg音频录制
ffmpeg -f avfoundation -i :0 out.wav

对比命令行的录制音频和视频. 其实可以猜得到, 视频录制编程 跟音视频-ffmpeg录制PCM是一样的思路的.

主要步骤

注册设备 avdevice_register_all();
获取输入格式对象 av_find_input_format
打开设备 avformat_open_input
采集数据 av_read_frame
释放资源 avformat_close_input

Mac平台添加info

<key>NSCameraUsageDescription</key>
<string>申请使用摄像头进行录制</string>

如果添加了还报错, 删除之前编译好的工程.

可能会遇到的格式支持方案的报错

[avfoundation @ 0x10c0c5600] Selected framerate (29.970030) is not supported by the device.
[avfoundation @ 0x10c0c5600] Supported modes:
[avfoundation @ 0x10c0c5600]   1280x720@[1.000000 30.000000]fps
[avfoundation @ 0x10c0c5600]   1280x720@[1.000000 30.000000]fps
[avfoundation @ 0x10c0c5600]   1280x720@[1.000000 30.000000]fps

设置符合规则的像素格式和视频大小, 如何设置

通过API的注释中搜索, 可以搜索关键字"pixel_format" 或者是"pixel", 像素格式可以发现

 * @code
 * AVDictionary *options = NULL;
 * av_dict_set(&options, "video_size", "640x480", 0);
 * av_dict_set(&options, "pixel_format", "rgb24", 0);
 *
 * if (avformat_open_input(&s, url, NULL, &options) < 0)
 *     abort();
 * av_dict_free(&options);

就知道了怎么设置视频参数格式


代码实现

// 格式名称,设备名称
#ifdef Q_OS_WIN
    // todo win下的配置根据电脑来, 因为win没有摄像头, 用Mac的来实现先
#else
    #define FMT_NAME "avfoundation"
    #define DEVICE_NAME "0"
    #define FILEPATH "/Users/liliguang/Desktop/"
    #define FILENAME "record_to_yuv.yuv"
    #define VEDIO_SIZE "1280x720"
    #define FRAMERATE "30"
    #define PIXEL_FORMAT "uyvy422"
#endif
void VedioThread::run() {
    qDebug() << this << "开始执行----------";
    // 获取输入格式对象
    AVInputFormat *fmt = av_find_input_format(FMT_NAME);
    if (!fmt) {
        qDebug() << "获取输入格式对象失败" << FMT_NAME;
        return;
    }
    qDebug() << "fmt : " << fmt;
    // 格式上下文(将来可以利用上下文操作设备)


    AVFormatContext *ctx = nullptr;


    AVDictionary *options = NULL;
    av_dict_set(&options, "video_size", VEDIO_SIZE, 0);
    av_dict_set(&options, "framerate", FRAMERATE, 0);
    av_dict_set(&options, "pixel_format", PIXEL_FORMAT , 0);

    // 打开设备
    int ret = avformat_open_input(&ctx, DEVICE_NAME, fmt, &options);
    if (ret < 0) {
        char errbuf[1024];
        av_strerror(ret, errbuf, sizeof (errbuf));
        qDebug() << "打开设备失败" << errbuf;
        return;
    }
    qDebug() << "ret : " << ret;

    // 文件名
    QString filename = FILEPATH;
    filename += FILENAME;
    QFile file(filename);
    if (!file.open(QFile::WriteOnly)) {
        qDebug() << "文件打开失败" << filename;
        // 关闭设备
        avformat_close_input(&ctx);
        return;
    }
    // 数据包
    AVPacket pkt;
    while (!isInterruptionRequested()) {
        // 不断采集数据
        ret = av_read_frame(ctx, &pkt);
        if (ret == 0) { // 读取成功
            // 将数据写入文件
            file.write((const char *) pkt.data, pkt.size);
        } else if (ret == AVERROR(EAGAIN)) { // 资源临时不可用
            continue;
        } else { // 其他错误
            char errbuf[1024];
            av_strerror(ret, errbuf, sizeof (errbuf));
            qDebug() << "av_read_frame error" << errbuf << ret;
            break;
        }
    }
    // 释放资源
    // 关闭文件
    file.close();
    // 关闭设备
    avformat_close_input(&ctx);
    qDebug() << this << "正常结束----------";
}

正常输出:
2021-07-14 23:30:40.838608+0800 9_record_to_yuv[10634:364232] VedioThread(0x12583ba30) 开始执行----------
2021-07-14 23:30:40.838828+0800 9_record_to_yuv[10634:364232] fmt :  0x10166fac0
2021-07-14 23:30:40.841558+0800 9_record_to_yuv[10634:364232] [plugin] AddInstanceForFactory: No factory registered for id <CFUUID 0x1097673c0> F8BB1C28-BAE8-11D6-9C31-00039315CD46
2021-07-14 23:30:40.865234+0800 9_record_to_yuv[10634:364232]  HALC_ShellDriverPlugIn::Open: Can't get a pointer to the Open routine
2021-07-14 23:30:40.865519+0800 9_record_to_yuv[10634:364232]  HALC_ShellDriverPlugIn::Open: Can't get a pointer to the Open routine
2021-07-14 23:30:40.886784+0800 9_record_to_yuv[10634:364232] [plugin] AddInstanceForFactory: No factory registered for id <CFUUID 0x12583f000> 30010C1C-93BF-11D8-8B5B-000A95AF9C6A
2021-07-14 23:30:43.274195+0800 9_record_to_yuv[10634:364232] ret :  0
2021-07-14 23:30:56.460552+0800 9_record_to_yuv[10634:364232] [] CMIO_DAL_PlugIn.cpp:269:StreamCopyBufferQueue Error: 1852797029, got an error from the plug-in routine
2021-07-14 23:30:56.464971+0800 9_record_to_yuv[10634:364232] VedioThread(0x12583ba30) 正常结束----------
2021-07-14 23:30:56.465248+0800 9_record_to_yuv[10634:364047] VedioThread(0x12583ba30) 析构(内存被回收)

使用FFmpeg命令行播放

ffplay -video_size 1280x720 -pixel_format uyvy422 -framerate 30 record_to_yuv.yuv 

自测播放正常

上一篇下一篇

猜你喜欢

热点阅读