一、前语
本系列文章是对音视频技能入门常识的整理和复习,为进一步深化体系研究音视频技能巩固根底。文章列表:
- 01-音视频技能中心常识|了解音频技能【移动通讯技能的发展、声响的实质、深化了解音频】
- 02-音视频技能中心常识|树立开发环境【FFmpeg与Qt、Windows开发环境树立、Mac开发环境树立、Qt开发根底】
- 03-音视频技能中心常识|Qt开发根底【
.pro
文件的装备、Qt控件根底、信号与槽】 - 04-音视频技能中心常识|音频录制【命令行、C++编程】
- 05-音视频技能中心常识|音频播映【播映PCM、WAV、PCM转WAV、PCM转WAV、播映WAV】
- 06-音视频技能中心常识|音频重采样【音频重采样简介、用命令行进行重采样、经过编程重采样】
- 07-音视频技能中心常识|AAC编码【AAC编码器解码器、编译FFmpeg、AAC编码实战、AAC解码实战】
- 08-音视频技能中心常识|成像技能【重识图片、详解YUV、视频录制、显现BMP图片、显现YUV图片】
- 09-音视频技能中心常识|视频编码解码【了解H.264编码、H.264编码、H.264编码解码】
- 10-音视频技能中心常识|RTMP服务器树立【流媒体、服务器环境】
二、.pro
文件的装备
1. 跨渠道装备
之前咱们别离在Windows、Mac环境的Qt项目中集成了FFmpeg。
能够发现在 .pro 文件的装备中,FFmpeg库在Mac、Windows上的位置是有所差异的。这样就会导致 .pro 文件无法跨渠道运用。
# windows
INCLUDEPATH += F:/Dev/ffmpeg-4.3.2/include
# mac
INCLUDEPATH += /usr/local/Cellar/ffmpeg/4.3.2/include
为了完成跨渠道装备,能够在装备前面加上渠道标识的前缀,表示这个装备只会在对应的渠道生效。
# windows
win32:INCLUDEPATH += F:/Dev/ffmpeg-4.3.2/include
win32:LIBS += -LF:/Dev/ffmpeg-4.3.2/lib \
-lavcodec \
-lavdevice \
-lavfilter \
-lavformat \
-lavutil \
-lpostproc \
-lswscale \
-lswresample
# mac
macx:INCLUDEPATH += /usr/local/Cellar/ffmpeg/4.3.2/include
macx:LIBS += -L/usr/local/Cellar/ffmpeg/4.3.2/lib \
-lavcodec \
-lavdevice \
-lavfilter \
-lavformat \
-lavutil \
-lpostproc \
-lswscale \
-lswresample \
-lavresample
# linux
# linux:INCLUDEPATH += ...
# linux:LIBS += ...
以后针对每个渠道的装备可能会比较多,能够运用大括号来简化。
# windows
win32 {
INCLUDEPATH += F:/Dev/ffmpeg-4.3.2/include
LIBS += -LF:/Dev/ffmpeg-4.3.2/lib \
-lavcodec \
-lavdevice \
-lavfilter \
-lavformat \
-lavutil \
-lpostproc \
-lswscale \
-lswresample
}
# mac
macx {
INCLUDEPATH += /usr/local/Cellar/ffmpeg/4.3.2/include
LIBS += -L/usr/local/Cellar/ffmpeg/4.3.2/lib \
-lavcodec \
-lavdevice \
-lavfilter \
-lavformat \
-lavutil \
-lpostproc \
-lswscale \
-lswresample \
-lavresample
}
2. 自定义变量
能够将公共的信息抽取成变量,然后运用 $${} 去拜访。
# mac
macx {
FFMPEG_HOME = /usr/local/Cellar/ffmpeg/4.3.2
INCLUDEPATH += $${FFMPEG_HOME}/include
LIBS += -L$${FFMPEG_HOME}/lib \
-lavcodec \
-lavdevice \
-lavfilter \
-lavformat \
-lavutil \
-lpostproc \
-lswscale \
-lswresample \
-lavresample
}
3. 读取体系环境变量
也能够经过 $$()读取体系的环境变量。比方,我的Windows中有个叫做JAVA_HOME的环境变量。
# 运用message打印环境变量JAVA_HOME的值
message($$(JAVA_HOME))
终究能够在概要信息处看到JAVA_HOME的打印成果。
三、控件的根本运用
为了更好地学习Qt控件的运用,主张创立项目时先不要生成ui文件。
翻开mainwindow.cpp,在MainWindow的结构函数中编写界面的初始化代码。
1. 窗口设置
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent) {
// 设置窗口标题
setWindowTitle("主窗口");
// 设置窗口大小
// 窗口能够经过拖拽边际进行自在伸缩
// resize(400, 400);
// 设置窗口的固定大小
// 窗口不能经过拖拽边际进行自在伸缩
setFixedSize(400, 400);
// 设置窗口的位置
// 以父控件的左上角为坐标原点
// 没有父控件,就以屏幕的左上角作为坐标原点
move(100, 100);
}
Qt坐标系如下图所示。
2. 增加子控件
#include <QPushButton>
// 创立按钮
QPushButton *btn = new QPushButton;
// 设置按钮的文字
btn->setText("登录");
// 设置父控件为当时窗口
btn->setParent(this);
// 设置按钮的位置和大小
btn->move(50, 50);
btn->resize(100, 50);
// 创立第2个按钮
new QPushButton("注册", this);
new出来的Qt控件是不需求程序员手动delete的,Qt内部会主动管理内存:当父控件毁掉时,会顺带毁掉子控件。
四、信号与槽
1. 根本运用
- 信号(Signal):比方点击按钮就会宣布一个点击信号
- 槽(Slot):一般也叫槽函数,是用来处理信号的函数
- 官方文档参阅:Signals & Slots
上图中的效果是:
- 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);
2. 自定义信号与槽
信号的发送者和接收者都有必要承继自QObject,Qt中的控件终究都是承继自QObject,比方QMainWindow、QPushButton等。
3. 信号的发送者
- sender.h
- Q_OBJECT用以支持自定义信号和槽
- 自定义的信号需求写在 signals: 下面
- 自定义的信号只需求声明,不需求完成
#ifndef SENDER_H
#define SENDER_H
#include <QObject>
class Sender : public QObject {
Q_OBJECT
public:
explicit Sender(QObject *parent = nullptr);
// 自定义信号
signals:
void exit();
};
#endif // SENDER_H
- sender.cpp
#include "sender.h"
Sender::Sender(QObject *parent) : QObject(parent) {
}
4. 信号的接收者
- receiver.h
- 自定义的槽主张写在 public slots: 下面
#ifndef RECEIVER_H
#define RECEIVER_H
#include <QObject>
class Receiver : public QObject {
Q_OBJECT
public:
explicit Receiver(QObject *parent = nullptr);
// 自定义槽
public slots:
void handleExit();
};
#endif // RECEIVER_H
- receiver.cpp
#include "receiver.h"
#include <QDebug>
Receiver::Receiver(QObject *parent) : QObject(parent) {
}
// 完成槽函数,编写处理信号的代码
void Receiver::handleExit() {
qDebug() << "Receiver::handleExit()";
}
5. 衔接
- mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
class MainWindow : public QMainWindow {
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
};
#endif // MAINWINDOW_H
- mainwindow.cpp
#include "mainwindow.h"
#include "sender.h"
#include "receiver.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent) {
// 创立目标
Sender *sender = new Sender;
Receiver *receiver = new Receiver;
// 衔接
connect(sender,
&Sender::exit,
receiver,
&Receiver::handleExit);
// 宣布信号
// 终究会调用Receiver::handleExit函数
emit sender->exit();
// 毁掉目标
delete sender;
delete receiver;
}
MainWindow::~MainWindow() {
}
6. 参数和返回值
信号与槽都能够有参数和返回值:
- 发信号时的参数会传递给槽
- 槽的返回值会返回到发信号的位置
// 自定义信号
signals:
int exit(int a, int b);
// 自定义槽
public slots:
int handleExit(int a, int b);
int Receiver::handleExit(int a, int b) {
// Receiver::handleExit() 10 20
qDebug() << "Receiver::handleExit()" << a << b;
return a + b;
}
// 宣布信号
int a = emit sender->exit(10, 20);
// 30
qDebug() << a;
需求注意的是:信号的参数个数有必要大于等于槽的参数个数。比方下面的写法是过错的:
// 自定义信号
signals:
void exit(int a);
// 自定义槽
public slots:
void handleExit(int a, int b);
7. 衔接2个信号
比方下图,衔接了Object 1的Signal 1A和Object 2的Signal 2A
- 当Object 1宣布Signal 1A时,会触发Slot X、Slot Y
- 当Object 2宣布Signal 2A时,只会触发Slot Y,而不会触发Slot X
能够运用connect函数衔接2个信号
- 当sender宣布exit信号时,sender2会宣布exit2信号
- 当sender2宣布exit2信号时,sender并不会宣布exit信号
connect(sender,
&Sender::exit,
sender2,
&Sender2::exit2);
8. Lambda
也能够直接运用Lambda处理信号。
connect(sender, &Sender::exit, []() {
qDebug() << "lambda handle exit";
});
9. ui文件
如果你的控件是经过ui文件生成的,衔接槽函数的步骤会更加简略。
首先主张给按钮们起个有意义的变量名,比方别离叫做:loginButton、registerButton。
对着登录按钮右键,选择转为槽。
选择clicked信号,然后OK。
此刻,Qt Creator现已帮你主动生成了槽函数的声明和完成,当咱们点击登录按钮时,就会调用这个函数。
class MainWindow : public QMainWindow {
Q_OBJECT
private slots:
// 槽函数的声明
void on_loginButton_clicked();
};
// 槽函数的完成
void MainWindow::on_loginButton_clicked() {
qDebug() << "on_loginButton_clicked";
}
其实,仔细调查函数名能够发现一个规律,函数名的命名规矩是:on_控件的变量名_事件名。
所以,咱们能够测验编写以下代码。
class MainWindow : public QMainWindow {
Q_OBJECT
private slots:
// 槽函数的声明
void on_registerButton_clicked();
};
// 槽函数的完成
void MainWindow::on_registerButton_clicked() {
qDebug() << "on_registerButton_clicked";
}
然后,你点击一下注册按钮,会发现成功调用了MainWindow::on_registerButton_clicked函数。
所以得知:ui文件中的控件会主动跟符合命名规矩的槽函数树立衔接。
终究,再提示一个常识点:ui文件中的控件能够在代码中经过ui->变量名拜访。
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent), ui(new Ui::MainWindow) {
ui->setupUi(this);
// 经过ui->拜访ui文件中的2个按钮
ui->loginButton->setFixedSize(100, 30);
ui->registerButton->setFixedSize(100, 30);
}
专题系列文章
1. 前常识
- 01-探求iOS底层原理|总述
- 02-探求iOS底层原理|编译器LLVM项目【Clang、SwiftC、优化器、LLVM】
- 03-探求iOS底层原理|LLDB
- 04-探求iOS底层原理|ARM64汇编
2. 根据OC言语探求iOS底层原理
- 05-探求iOS底层原理|OC的实质
- 06-探求iOS底层原理|OC目标的实质
- 07-探求iOS底层原理|几种OC目标【实例目标、类目标、元类】、目标的isa指针、superclass、目标的办法调用、Class的底层实质
- 08-探求iOS底层原理|Category底层结构、App启动时Class与Category装载过程、load 和 initialize 履行、相关目标
- 09-探求iOS底层原理|KVO
- 10-探求iOS底层原理|KVC
- 11-探求iOS底层原理|探求Block的实质|【Block的数据类型(实质)与内存布局、变量捕获、Block的品种、内存管理、Block的修饰符、循环引证】
- 12-探求iOS底层原理|Runtime1【isa详解、class的结构、办法缓存cache_t】
- 13-探求iOS底层原理|Runtime2【音讯处理(发送、转发)&&动态办法解析、super的实质】
- 14-探求iOS底层原理|Runtime3【Runtime的相关运用】
- 15-探求iOS底层原理|RunLoop【两种RunloopMode、RunLoopMode中的Source0、Source1、Timer、Observer】
- 16-探求iOS底层原理|RunLoop的运用
- 17-探求iOS底层原理|多线程技能的底层原理【GCD源码剖析1:主行列、串行行列&&并行行列、大局并发行列】
- 18-探求iOS底层原理|多线程技能【GCD源码剖析1:dispatch_get_global_queue与dispatch_(a)sync、单例、线程死锁】
- 19-探求iOS底层原理|多线程技能【GCD源码剖析2:栅门函数dispatch_barrier_(a)sync、信号量dispatch_semaphore】
- 20-探求iOS底层原理|多线程技能【GCD源码剖析3:线程调度组dispatch_group、事件源dispatch Source】
- 21-探求iOS底层原理|多线程技能【线程锁:自旋锁、互斥锁、递归锁】
- 22-探求iOS底层原理|多线程技能【原子锁atomic、gcd Timer、NSTimer、CADisplayLink】
- 23-探求iOS底层原理|内存管理【Mach-O文件、Tagged Pointer、目标的内存管理、copy、引证计数、weak指针、autorelease
3. 根据Swift言语探求iOS底层原理
关于函数
、枚举
、可选项
、结构体
、类
、闭包
、特点
、办法
、swift多态原理
、String
、Array
、Dictionary
、引证计数
、MetaData
等Swift根本语法和相关的底层原理文章有如下几篇:
- 01-Swift5常用中心语法|了解Swift【Swift简介、Swift的版本、Swift编译原理】
- 02-Swift5常用中心语法|根底语法【Playground、常量与变量、常见数据类型、字面量、元组、流程操控、函数、枚举、可选项、guard语句、区间】
- 03-Swift5常用中心语法|面向目标【闭包、结构体、类、枚举】
- 04-Swift5常用中心语法|面向目标【特点、inout、类型特点、单例形式、办法、下标、承继、初始化】
- 05-Swift5常用中心语法|高档语法【可选链、协议、过错处理、泛型、String与Array、高档运算符、扩展、拜访操控、内存管理、字面量、形式匹配】
- 06-Swift5常用中心语法|编程范式与Swift源码【从OC到Swift、函数式编程、面向协议编程、响应式编程、Swift源码剖析】
4. C++中心语法
- 01-C++中心语法|C++概述【C++简介、C++来源、可移植性和规范、为什么C++会成功、从一个简略的程序开始知道C++】
- 02-C++中心语法|C++对C的扩展【::效果域运算符、姓名操控、struct类型加强、C/C++中的const、引证(reference)、函数】
- 03-C++中心语法|面向目标1【 C++编程规范、类和目标、面向目标程序设计事例、目标的结构和析构、C++面向目标模型初探】
- 04-C++中心语法|面向目标2【友元、内部类与局部类、强化训练(数组类封装)、运算符重载、仿函数、模板、类型转换、 C++规范、过错&&反常、智能指针】
- 05-C++中心语法|面向目标3【 承继和派生、多态、静态成员、const成员、引证类型成员、VS的内存窗口】
5. Vue全家桶
- 01-Vue全家桶中心常识|Vue根底【Vue概述、Vue根本运用、Vue模板语法、根底事例、Vue常用特性、归纳事例】
- 02-Vue全家桶中心常识|Vue常用特性【表单操作、自定义指令、核算特点、侦听器、过滤器、生命周期、归纳事例】
- 03-Vue全家桶中心常识|组件化开发【组件化开发思想、组件注册、Vue调试工具用法、组件间数据交互、组件插槽、根据组件的
- 04-Vue全家桶中心常识|多线程与网络【前后端交互形式、promise用法、fetch、axios、归纳事例】
- 05-Vue全家桶中心常识|Vue Router【根本运用、嵌套路由、动态路由匹配、命名路由、编程式导航、根据vue-router的事例】
- 06-Vue全家桶中心常识|前端工程化【模块化相关规范、webpack、Vue 单文件组件、Vue 脚手架、Element-UI 的根本运用】
- 07-Vue全家桶中心常识|Vuex【Vuex的根本运用、Vuex中的中心特性、vuex事例】
6. 音视频技能中心常识
- 01-音视频技能中心常识|了解音频技能【移动通讯技能的发展、声响的实质、深化了解音频】
- 02-音视频技能中心常识|树立开发环境【FFmpeg与Qt、Windows开发环境树立、Mac开发环境树立、Qt开发根底】
- 03-音视频技能中心常识|Qt开发根底【
.pro
文件的装备、Qt控件根底、信号与槽】 - 04-音视频技能中心常识|音频录制【命令行、C++编程】
- 05-音视频技能中心常识|音频播映【播映PCM、WAV、PCM转WAV、PCM转WAV、播映WAV】
- 06-音视频技能中心常识|音频重采样【音频重采样简介、用命令行进行重采样、经过编程重采样】
- 07-音视频技能中心常识|AAC编码【AAC编码器解码器、编译FFmpeg、AAC编码实战、AAC解码实战】
- 08-音视频技能中心常识|成像技能【重识图片、详解YUV、视频录制、显现BMP图片、显现YUV图片】
- 09-音视频技能中心常识|视频编码解码【了解H.264编码、H.264编码、H.264编码解码】
- 10-音视频技能中心常识|RTMP服务器树立【流媒体、服务器环境】
其它底层原理专题
1. 底层原理相关专题
- 01-核算机原理|核算机图形烘托原理这篇文章
- 02-核算机原理|移动终端屏幕成像与卡顿
2. iOS相关专题
- 01-iOS底层原理|iOS的各个烘托结构以及iOS图层烘托原理
- 02-iOS底层原理|iOS动画烘托原理
- 03-iOS底层原理|iOS OffScreen Rendering 离屏烘托原理
- 04-iOS底层原理|因CPU、GPU资源耗费导致卡顿的原因和解决计划
3. webApp相关专题
- 01-Web和类RN大前端的烘托原理
4. 跨渠道开发计划相关专题
- 01-Flutter页面烘托原理
5. 阶段性总结:Native、WebApp、跨渠道开发三种计划功能比较
- 01-Native、WebApp、跨渠道开发三种计划功能比较
6. Android、HarmonyOS页面烘托专题
- 01-Android页面烘托原理
- 02-HarmonyOS页面烘托原理 (
待输出
)
7. 小程序页面烘托专题
- 01-小程序结构烘托原理