2024-12-02 2025-02-21 音视频 头文件部分 内容比较少,我就全部放这了, 自己看吧~ 1234567891011121314151617181920212223242526272829303132333435#include "AudioRecorder.h"#include "videoRecorder.h"#include <QMainWindow>QT_BEGIN_NAMESPACEnamespace Ui {class MainWindow;}QT_END_NAMESPACEclass MainWindow : public QMainWindow{ Q_OBJECTpublic: MainWindow(QWidget *parent = nullptr); ~MainWindow(); int open_device(AVFormatContext **fmt_ctx); int Main_av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt); int Main_avformat_write_header(AVFormatContext *s, AVDictionary **options);private slots: void on_pushButton_clicked();private: Ui::MainWindow *ui; AudioRecorder *aread; VideoRecorder *vread; // create file 设置文件操作对象用于存储消息 const char* outFilename = "output.mp4"; AVFormatContext *ofmt_ctx = nullptr; // 输出上下文 QReadWriteLock lock; // 线程安全,读锁 不允许在读取时进行修改; 写锁 不允许在写的时候进行读写 注意读写锁不能包含在同一个作用域里}; 源文件部分 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475#include "./ui_mainwindow.h"#include "mainwindow.h"MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow){ ui->setupUi(this); aread = new AudioRecorder(this, &ofmt_ctx); vread = new VideoRecorder(this, &ofmt_ctx);}MainWindow::~MainWindow(){ delete ui;}int MainWindow::Main_av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt){ QWriteLocker locker(&lock); // 写锁 return av_interleaved_write_frame(s, pkt);}int stream_nb = 0;int MainWindow::Main_avformat_write_header(AVFormatContext *s, AVDictionary **options){ // 写头文件 stream_nb += 1; if (stream_nb == 1) { qDebug() << "等待下一个流"; while (1) { if (stream_nb == 2) return 1; } }; return avformat_write_header(ofmt_ctx, NULL);};void MainWindow::on_pushButton_clicked(){ if (!vread->flage) { // 配置输出上下文 avformat_alloc_output_context2(&ofmt_ctx, NULL, NULL, outFilename); if (!ofmt_ctx) { qDebug() << "创建输出上下文失败!"; return; } // 打开输出 if (!(ofmt_ctx->oformat->flags & AVFMT_NOFILE)) { // 2.3 创建并初始化一个AVIOContext, 用以访问URL(outFilename)指定的资源 if (avio_open(&ofmt_ctx->pb, outFilename, AVIO_FLAG_WRITE) < 0) { qDebug() << "can't open output URL: %s\n" << outFilename; return; } } stream_nb = 0; aread->flage = true; vread->flage = true; aread->start(); vread->start(); ui->pushButton->setText("停止"); } else { aread->flage = false; vread->flage = false; aread->wait(); vread->wait(); av_write_trailer(ofmt_ctx); /* close output */ if (ofmt_ctx && !(ofmt_ctx->oformat->flags & AVFMT_NOFILE)) { avio_closep(&ofmt_ctx->pb); } avformat_free_context(ofmt_ctx); ui->pushButton->setText("开始"); }} 总结 通过多线程, 调用FFmpeg的API,音频采集部分利用FIFO缓冲区存储音频数据,视频采集部分直接存放于pFrameYUV,音频经过解码、编码成AAC后进行写入,视频经过解码、编码成H264后进行写入 第一次写,感觉写的很乱,有很多不足的地方。 有不好的地方可以帮忙指出来 让我偷偷懒吧~~~ 前一篇 利用rtmp对本地flv文件进行推流 后一篇 ②实现电脑音频和视频的录制并封装成mp4
说些什么吧!