音视频合集
1.Qt入门基础
2.音频基础
3.Mac环境安装FFmpeg和Qt
4.命令行操控音频
5.代码操控音频
6.播放PCM文件
7.PCM转WAV
8.WAV播放
9.音频重采样
10.AAC编码
11.手动编译ffmpeg
12.AAC编码实战
13.AAC 解码实战
14.YUV
15.录音视频
16.H264编码实战
17.H264解码
18.视频解码成yuv和pcm
1.Qt入门基础
1.1 控件的基本使用
从上一个文章Mac环境搭建的时候,可以看到创建工程的时候,是帮我们创立了了一个form 的文件,这个文件里面包含了一个可视化的ui,我们可以直接在里面拖拽控件,类似于iOS的故事板,为了更好的了解qt的控件,这里我们创建的时候,不勾选Generate form这一个选项,然后再.cpp文件中,代码创建控件
1.2 窗口设置
代码
//设置窗口标题
setWindowTitle("主窗口");
//设置窗口大小,可以自由拖动
resize(600,600);
//设置窗口的固定大小,窗口不能通过拖拽边缘进行自由伸缩
// setFixedSize(600,600);
//设置窗口的位置,以父控件的左上角为坐标原点,没有父控件的情况,就以屏幕的左上角作为坐标原点
move(200,200);
效果图
1.3 添加子控件
代码
// 创建按钮
QPushButton *btn = new QPushButton;
// 设置按钮的文字
btn->setText("登录");
// 设置父控件为当前窗口
btn->setParent(this);
// 设置按钮的位置和大小
btn->move(50, 50);
btn->resize(100, 50);
// 创建第2个按钮
new QPushButton("注册", this);
效果图
2. 信号与槽
2.1 基本概念
- 信号:泛指某一行为,例如说点击按钮时候会发出一个信号
- 槽(Slot): 也叫槽函数,用来处理信号的函数
官方文档
上面的大概意思是:
Object1发出信号signal1,交给Object2的槽slot1、slot2去处理
- 这个时候Object1是信号的发送者,Object2是信号的接收者
Object1发出信号signal2,交给Object4的槽slot1去处理
- Object1是信号的发送者,Object4是信号的接收者
Object3发出信号signal1,交给Object4的槽slot3去处理
- Object3是信号的发送者,Object4是信号的接收者
总结:1个信号可以由多个槽进行处理,1个槽可以处理多个信号
- 信号的发送者、信号、信号的接收者、槽 之间的通信方式是通过connect函数
connect(信号的发送者, 信号, 信号的接收者, 槽);
// 比如点击按钮,关闭当前窗口
// btn发出clicked信号,就会调用this的close函数
connect(btn, &QPushButton::clicked, this, &MainWindow::close);
// 可以通过disconnect断开连接
disconnect(btn, &QPushButton::clicked, this, &MainWindow::close);
一个简单的案例
btn->setText("关闭");
btn->setFixedSize(100, 30);
btn->setParent(this);
// 连接信号与槽
// 点击按钮,关闭MainWindow窗口
// btn发出信号
// MainWindow接收信号,调用槽函数:close
connect(btn, &QPushButton::clicked,
this, &MainWindow::close);
这个时候点击关闭,可以看到窗口就关闭了,这个就是信号与槽的概念了
2.2 自定义信号与槽
同一对象
- Counter.h
#ifndef COUNTER_H
#define COUNTER_H
#include
class Counter : public QObject
{
Q_OBJECT
public:
explicit Counter(QObject *parent = nullptr);
// Counter() { m_value = 0; }
int value() const { return m_value; }
public slots:
void setValue(int value);
signals:
void valueChanged(int newValue);
private:
int m_value;
};
#endif // COUNTER_H
- COunter.cpp
#include "counter.h"
#include
Counter::Counter(QObject *parent) : QObject(parent)
{
}
void Counter::setValue(int value)
{
if (value != m_value) {
m_value = value;
qDebug() << "Counter::setValue" << m_value;
emit valueChanged(value);
}
}
不同对象
- 发送者
- senderobj.h
#ifndef SENDEROBJ_H
#define SENDEROBJ_H
#include
class SenderObj : public QObject
{
Q_OBJECT
public:
explicit SenderObj(QObject *parent = nullptr);
signals:
//自定义信号
void exit();
};
#endif // SENDEROBJ_H
- senderobj.cpp
#include "senderobj.h"
SenderObj::SenderObj(QObject *parent) : QObject(parent)
{
}
- 接受者
- receiverobj.h
#ifndef RECEIVEROBJ_H
#define RECEIVEROBJ_H
#include
class receiverObj : public QObject
{
Q_OBJECT
public:
explicit receiverObj(QObject *parent = nullptr);
//自定义槽
public slots:
void handleExit();
};
#endif // RECEIVEROBJ_H
- receiverobj.cpp
#include "receiverobj.h"
#include
receiverObj::receiverObj(QObject *parent) : QObject(parent)
{
}
//实现槽函数,编写处理信号的代码
void receiverObj::handleExit(){
qDebug() << "receiverobj::handleExit()";
}
- 链接signal 和 slots
- mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
};
#endif // MAINWINDOW_H
- mainwidow.cpp
#include "mainwindow.h"
#include "counter.h"
#include "senderobj.h"
#include "receiverobj.h"
//https://doc.qt.io/qt-5/signalsandslots.html
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
//创建对象
SenderObj *sender = new SenderObj;
receiverObj *receiver = new receiverObj;
//连接
connect(sender,&SenderObj::exit,receiver,&receiverObj::handleExit);
//发出信号,最终会调用receiverobj::handleExit 函数
emit sender->exit();
//销毁对象
delete sender;
delete receiver;
}
MainWindow::~MainWindow()
{
}
终端结果输出:
21:36:27: Starting /Users/songlin/audio/build-custom_signal_and_slot-Desktop_x86_darwin_generic_mach_o_64bit-Debug/custom_signal_and_slot.app/Contents/MacOS/custom_signal_and_slot ...
receiverobj::handleExit()
注意:参数解释
- Q_OBJECT用以支持自定义信号和槽
- 自定义的信号需要写在signals:下面
- 自定义的信号只需要声明,不需要实现
- 自定义的槽需要卸载slot:下面
刚刚上面示范了不同对象的自定义信号与槽,但是方法都是无参数,无返回值的,接下来我们可以看看有参数和有返回值的例子
- sender.h
#ifndef SENDER_H
#define SENDER_H
#include
class Sender : public QObject {
Q_OBJECT
public:
explicit Sender(QObject *parent = nullptr);
signals:
int exit(int n1, int n2);
void exit2(int n1, int n2);
};
#endif // SENDER_H
- sender.cpp
#include "sender.h"
Sender::Sender(QObject *parent) : QObject(parent) {
}
- receiver.h
#ifndef RECEIVER_H
#define RECEIVER_H
#include
class Receiver : public QObject {
Q_OBJECT
public:
explicit Receiver(QObject *parent = nullptr);
public slots:
int handleExit(int n1, int n2);
void handleExit2(int n1, int n2);
};
#endif // RECEIVER_H
- recever.cpp
#include "receiver.h"
#include
Receiver::Receiver(QObject *parent) : QObject(parent) {
}
int Receiver::handleExit(int n1, int n2) {
qDebug() << "Receiver::handleExit" << n1;
return n1 + 20;
}
void Receiver::handleExit2(int n1, int n2) {
qDebug() << "Receiver::handleExit2";
}
- mainwindow.cpp
Sender *sender = new Sender;
Receiver *receiver = new Receiver;
connect(sender, &Sender::exit,
receiver, &Receiver::handleExit);
connect(sender, &Sender::exit2,
receiver, &Receiver::handleExit2);
emit sender->exit(10, 20);
除开这种方式,还可以使用lambda的展示形式
- mainwindow.cpp 之lambda连接
Sender *sender = new Sender;
Receiver *receiver = new Receiver;
//Lambda
connect(sender, &Sender::exit, [](int n1, int n2) {
qDebug() << "Lambda" << n1 << n2;
});
emit sender->exit(10, 20);
代码控件连接
QPushButton *btn = new QPushButton;
btn->setText("按钮");
btn->setFixedSize(100, 40);
btn->setParent(this);
connect(btn, &QPushButton::clicked,
this, &MainWindow::handleClick);
void MainWindow::handleClick() {
qDebug() << "点击了按钮 - handleClick";
}
通过ui 文件建立signal 和 slot
新建一个工程叫做signal_slot_ui
进入到ui文件
此时,Qt Creator已经帮你自动生成了槽函数的声明和实现,当我们点击登录按钮时,就会调用这个函数
- mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_loginBtn_clicked();
void on_registerBtn_clicked();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
- maindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_loginBtn_clicked()
{
}
void MainWindow::on_registerBtn_clicked()
{
}
为了方便看到测试结果,我们可以再实现方法那里写上打印信息
void MainWindow::on_loginBtn_clicked()
{
qDebug() << "on_loginButton_clicked";
}
void MainWindow::on_registerBtn_clicked()
{
qDebug() << "on_registerBtn_clicked";
}
最终可以看到我们点击按钮的时候,终端有了相应的输出
22:10:43: Starting /Users/songlin/audio/build-signal_sinal_ui-Desktop_x86_darwin_generic_mach_o_64bit-Debug/signal_sinal_ui.app/Contents/MacOS/signal_sinal_ui ...
on_loginButton_clicked
on_registerBtn_clicked