一、前言
顺应时代的技术发展潮流,逐步学习并掌握音视频技术核心知识,让技术落地,让知识赋能生活,让科技造福千万灯火。
二、FFmpeg与Qt
1. 为什么选择FFmpeg?
每个主流平台基本都有自己的音视频开发库(API),用以处理音视频数据,比如:
- iOS:AVFoundation、AudioUnit等
- Android:MediaPlayer、MediaCodec等
- Windows:DirectShow等
- …
为了让所有平台的开发者都能够学习到音视频开发的通用技术,本教程主要讲解跨平台的音视频开发库FFmpeg。其实只要你掌握了FFmpeg,也可以很快上手其他音视频开发库,因为底层原理都是一样的,你最终操作的都是一样的数据,比如MP3、MP4文件。
2. FFmpeg简介
FFmpeg的名字由FF和mpeg组成。
- FF是Fast Forward(译为:快进、快速前进)的简称
- mpeg来源于Moving Picture Experts Group(简称:MPEG,译为:动态影像专家小组)
- MPEG是源自ISO与IEC等国际组织的工作小组
- MPEG的其中一项工作是:制定音视频相关的标准(比如压缩标准)
有很多知名项目都采用了FFmpeg,比如:
- Google Chrome:浏览器
- Firefox:浏览器
- VLC:跨平台播放器
- MPlayer
- ijkplayer:bilibili团队开发的Android/iOS播放器框架
- Perian:Apple公司的QuickTime组件
3. Qt
如果要想开发一个播放器,肯定得编写界面,同样为了保证跨平台开发,这里采用的GUI库是Qt,官方的开发工具QtCreator是跨平台的(支持Windows、Mac、Linux)。Qt开发采用的编程语言是C++。
如若你尚未掌握C++语言,或者已经对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的内存窗口】
三、Windows开发环境搭建
1. FFMpeg下载
网上已经有编译好的FFmpeg,目前最新的Release版本是4.3.2,可以直接下载到项目中进行开发使用。
- Windows版本下载:ffmpeg-4.3.2-2021-02-27-full_build-shared.7z
- 源码下载:ffmpeg-4.3.2.tar.xz
- 网上编译好的FFmpeg一般是完整版,体积比较大
- 日后我们可以根据实际需要,对FFmpeg的源码进行裁剪后再进行重新编译
解压ffmpeg-4.3.2-2021-02-27-full_build-shared.7z文件后,目录结构如下所示:
- bin
- 有编译好的可执行程序:ffmpeg.exe、ffplay.exe、ffprobe.exe,可以直接在命令行上使用,比如
- ffplay xx.mp4:可以直接播放某个视频
- ffmpeg -version:可以查看FFmpeg的版本号
- 有运行时需要用到的动态库文件(*.dll)
- 有编译好的可执行程序:ffmpeg.exe、ffplay.exe、ffprobe.exe,可以直接在命令行上使用,比如
- doc:FFmpeg的使用文档
- include:开发时需要包含的头文件
- lib:链接时需要用到的库文件
2. Qt下载
本教程中选择5.14.2版本(从5.15版本开始是收费版本)。
- 下载地址:download.qt.io/archive/qt/…
- Windows系统选择下载:qt-opensource-windows-x86-5.14.2.exe
3. Qt开发
3.1 第一个Qt项目
打开QtCreator,文件 -> 新建文件或项目。
Application -> Qt Widgets Application。
设置项目名称和项目的存放路径。
QtCreator默认会创建一个MainWindow类(主窗口)。
勾选MinGW编译器。
双击打开mainwindow.ui文件,可以往右边的主窗口中添加一些界面元素(比如按钮)。
点击左下角的运行按钮(绿色三角形),即可看到一个窗口界面,这个就是QtCreator默认创建的主窗口(MainWindow对象)。
3.2 消除警告
每次运行Qt程序,你的控制台可能都会出现以下警告信息:QT_DEVICE_PIXEL_RATIO已经过期。
Warning: QT_DEVICE_PIXEL_RATIO is deprecated. Instead use:
QT_AUTO_SCREEN_SCALE_FACTOR to enable platform plugin controlled per-screen factors.
QT_SCREEN_SCALE_FACTORS to set per-screen DPI.
QT_SCALE_FACTOR to set the application global scale factor.
解决方案:设置环境变量QT_SCALE_FACTOR为1即可。
#include "mainwindow.h"
#include <QApplication>
// 导入头文件【也可以不导入,因为<QApplication>中已经包含了<QByteArray>】
// #include <QByteArray>
int main(int argc, char *argv[]) {
// 通过qputenv函数设置QT_SCALE_FACTOR为1
qputenv("QT_SCALE_FACTOR", QByteArray("1"));
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
3.3 集成FFmpeg到Qt项目中
在Windows中,我们最终是通过调用FFmpeg动态库(dll)中的函数来操作音视频数据,使用dll的其中一种方式是需要用到3种文件:
- .h:头文件(Header File)
- 包含了函数的声明
- 通过*#include*去导入相应的头文件
- .dll:动态链接库(Dynamic Link Library)
- 包含了函数的具体实现代码
- Windows程序会在运行过程中,动态调用dll中的函数
- .lib或**.dll.a**:(动态链接库的)导入库(Import Library)
- .lib:用于MSVC编译器中
- .dll.a:用于MinGW编译器中
- 包含了dll中函数的入口,用于辅助找到并调用dll中的函数
- 最终需要链接到Windows程序中(比如合并到exe文件中)
值得一提的是,在Windows中,静态链接库(Static Link Library)的扩展名也是**.lib**、.dll.a。静态链接库和导入库的区别是:
- 静态链接库:包含了函数的具体实现代码
- 导入库:不包含函数的具体实现代码(函数的具体实现代码存储在dll中)
3.2.1 修改**.pro**文件
# 设置头文件的目录,以便编译器能够找到头文件
INCLUDEPATH += %FFMPEG_HOME%/include
# 设置导入库的目录和需要链接的导入库
LIBS += -L%FFMPEG_HOME%/lib \
-lavcodec \
-lavdevice \
-lavfilter \
-lavformat \
-lavutil \
-lpostproc \
-lswscale \
-lswresample
- #号后面的内容是注释
- %FFMPEG_HOME%表示ffmpeg-4.3.2-2021-02-27-full_build-shared.7z解压后的目录
- 需要根据你的实际情况修改为真实的路径
- -L:设置导入库的目录,以便编译器能够找到导入库
- -l:设置需要链接的导入库名称
- 导入库名称需要去掉文件名前面的lib,比如libavcodec.dll.a就写成avcodec
3.2.2 调用函数
在main.cpp中调用av_version_info函数,获取FFmpeg的版本信息。
#include "mainwindow.h"
#include <QApplication>
// 为了使用qDebug函数
#include <QDebug>
// FFmpeg是C语言库
// 有了extern "C",才能在C++中导入C语言函数
extern "C" {
#include <libavcodec/avcodec.h>
}
int main(int argc, char *argv[]) {
// 打印版本信息
qDebug() << av_version_info();
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
3.2.3 拷贝dll文件
Qt程序编译成功后,会生成一个exe文件
- exe是Windows中的一种可执行文件
- 我们编写的程序代码最终都存在了exe文件中
为了保证exe在运行时能成功调用FFmpeg的函数,那么就得让exe能够找到FFmpeg的dll文件(动态库文件)。可以将**%FFMPEG_HOME%/bin**目录中的所有dll文件拷贝到exe文件所在的目录中,exe在运行的时候,能自动找到跟它同一目录下的dll文件。
可以通过查看构建目录得知exe文件所在的目录。
运行程序后,如果能在控制台看到4.3.2字样的输出信息,说明FFmpeg已经集成成功。
3.2.4 dll的搜索顺序
exe在寻找dll文件时,大概按照以下优先级顺序去查找(这里只列出了大概的搜索路径,并没有写全):
-
exe所在的目录
-
Windows的System目录
- C:/Windows/System
- C:/Windows/System32
-
Windows目录
- C:/Windows
-
环境变量Path中的路径
- 所以可以考虑将**%FFMPEG_HOME%/bin**目录配置到Path变量中
- 置于如何配置Windows的环境变量Path,这是基本开发常识了,就不再讲解了
第1种方式需要在每一个Qt程序中都拷贝一份FFmpeg的dll文件,第2~4种方式可以让多个Qt程序共用同一份FFmpeg的dll文件。
3.3 .pro文件
.pro文件是Qt项目的主配置文件。
# 包含了core、gui两个模块
QT += core gui
# 高于4版本,就包含widgets模块
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
# 源代码
SOURCES += \
main.cpp \
mainwindow.cpp
# 头文件
HEADERS += \
mainwindow.h
# ui文件
FORMS += \
mainwindow.ui
3.4 常用快捷键
- 字体缩放:Ctrl + 鼠标滚轮
- 帮助文档:F1
- 注释:Ctrl + /
- 同名的.h、.cpp文件之间切换:F4
四、Mac开发环境搭建
在不同的Mac环境下,实践出来的效果可能跟本教程会有所差异。我的Mac环境是:Intel CPU、macOS Big Sur(11.2.2)。
1. FFMpeg安装
在Mac环境中,直接使用Homebrew安装FFmpeg即可。还没有安装Homebrew,或者嫌Homebrew下载速度慢的童鞋,可以参考这篇文章:《Mac安装Homebrew》。
brew install ffmpeg
安装完毕后,如果能成功在命令行查看FFmpeg的版本号,那说明已经安装成功。
ffmpeg -version
1.1 目录结构
通过brew install安装的软件会存放到 /usr/local/Cellar 目录中,通过以下命令可以打开FFmpeg的安装目录。
cd /usr/local/Cellar/ffmpeg
open .
- bin:有编译好的可执行程序:ffmpeg、ffplay等,可以直接在命令行上使用,比如
- ffplay xx.mp4:可以直接播放某个视频
- ffmpeg -version:可以查看FFmpeg的版本号
- include:开发时需要包含的头文件
- lib:链接时需要用到的库文件
2. Qt安装
通过brew install安装Qt,最终被安装在 /usr/local/Cellar/qt 目录。
brew install qt
通过brew install –cask安装Qt Creator,最终被安装在 /usr/local/Caskroom/qt-creator 目录。
brew install --cask qt-creator
2.1 配置
通过brew安装的Qt和Qt Creator是分开的,需要在Qt Creator中设置一下Qt的路径。
Qt的路径是在 /usr/local 中,默认是隐藏的。
- 可以使用快捷键 Command + Shift + . 显示隐藏文件和文件夹
- 可以使用快捷键 Command + Shift + G 手动输入Qt的文件夹:/usr/local/Cellar/qt
选择bin目录下的qmake。
设置64bit那一项为默认开发环境。
滚动到底下,选择刚才设置的Qt版本。
3. Qt开发
3.1 新建项目
新建项目的操作和Windows版本差不多。
运行后的效果如下图所示。
3.2 设置头文件路径
INCLUDEPATH += /usr/local/Cellar/ffmpeg/版本号/include
3.3 设置库文件路径
**注意:结合ffmpeg的lib目录下的库列表,获取自己当前项目需要的库即可 **
LIBS += -L /usr/local/Cellar/ffmpeg/版本号/lib\
-
-
-lavcodec \
-
-
-
-lavdevice \
-
-
-
-lavfilter \
-
-
-
-lavformat \
-
-
-
-lavutil \
-
-
-
-lpostproc \
-
-
-
-lswscale \
-
-
-
....
-
# 设置头文件路径
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
打印FFmpeg版本号。
#include "mainwindow.h"
#include <QApplication>
#include <QDebug>
extern "C" {
#include <libavcodec/avcodec.h>
}
int main(int argc, char *argv[]) {
// 打印版本号
qDebug() << av_version_info();
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}