前幾天項(xiàng)目需要壓縮視頻,Github
上找了許多庫扇苞,要么就是太大欺殿,要么就是質(zhì)量不高寄纵,其實(shí)我只需要壓縮視頻,最好的方案還是定制編譯一個(gè) FFmpeg
給 Android
用脖苏。
本項(xiàng)目使用
FFmpeg
和libx264
(一個(gè)第三方的視頻編碼器) 來編譯出可以在Android
上使用的動(dòng)態(tài)庫
一程拭、下載源碼
創(chuàng)建一個(gè)叫 FFmpegAndroid
的目錄,下載 libx264
的源碼和ffmpeg
的源碼棍潘,然后在 FFmpegAndroid
文件夾下建立一個(gè) bulid
文件夾恃鞋,用于存放編譯腳本和輸出
--- FFmpegAndroid
|-- ffmpeg
|-- x264
|-- build
二、編譯 FFmpeg
編譯 x264 編碼器
先在 build
文件夾下建立 setting.sh
, 用于申明一些公用的環(huán)境變量亦歉,比如 $NDK
恤浪、$CPU
...
setting.sh
# ndk 環(huán)境
NDK=$HOME/Library/Android/sdk/ndk-bundle
SYSROOT=$NDK/platforms/android-14/arch-arm/
TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64
# cpu 架構(gòu)平臺(tái),若要編譯 x86 則指定 x86
CPU=armv7-a
然后建立 libx264
的編譯腳本 build_x264.sh
肴楷,libx264
是一個(gè)開源的H.264編碼器水由,據(jù)說是最好的視頻有損編碼器。ffmpeg
默認(rèn)不自帶赛蔫,但是支持 x264
作為第三方編碼器編譯砂客。
build_x264.sh
./config 內(nèi)的# 注釋必須在運(yùn)行的時(shí)候去掉
#!/bin/bash
# 引入需要的環(huán)境變量
. setting.sh
# 輸出下看看對(duì)不對(duì),可以去掉濒募,這里調(diào)試用
echo "use toolchain: $TOOLCHAIN"
echo "use system root: $SYSROOT"
# 輸出文件的前綴鞭盟,也就是指定最后靜態(tài)庫輸出到那里
PREFIX=$(pwd)/lib/x264/$CPU
# 優(yōu)化參數(shù)
OPTIMIZE_CFLAGS="-mfloat-abi=softfp -mfpu=vfp -marm -march=$CPU "
ADDI_CFLAGS=""
ADDI_LDFLAGS=""
# 因?yàn)楫?dāng)前目錄在 build 目錄,需要切換到 x264 去執(zhí)行 config
cd ../x264
function build_x264
{
./configure \
--prefix=$PREFIX \
# 不編譯動(dòng)態(tài)庫
--disable-shared \
--disable-asm \
# 編譯靜態(tài)庫
--enable-static \
--enable-pic \
--enable-strip \
--host=arm-linux-androideabi \
--cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
--sysroot=$SYSROOT \
--extra-cflags="-Os -fpic $ADDI_CFLAGS $OPTIMIZE_CFLAGS" \
--extra-ldflags="$ADDI_LDFLAGS" \
$ADDITIONAL_CONFIGURE_FLAG
make clean
make -j4
make install
}
# 執(zhí)行編譯指令
build_x264
寫完之后就可以編譯 x264
庫了瑰剃,編譯之前還有一點(diǎn)要注意的是齿诉,默認(rèn)編譯出來的文件后綴并不是 *.so
,這 Android
是識(shí)別不了的晌姚,需要對(duì) x264
源碼里面的 config
做如下修改:
將
echo "SOSUFFIX=so" >> config.mak
echo "SONAME=libx264.so.$API" >> config.mak
echo "SOFLAGS=-shared -Wl,-soname,\$(SONAME) $SOFLAGS" >> config.mak
修改成
echo "SOSUFFIX=so" >> config.mak
echo "SONAME=libx264-$API.so" >> config.mak
echo "SOFLAGS=-shared -Wl,-soname,\$(SONAME) $SOFLAGS" >> config.mak
別忘了給
build_x264.sh
和setting.sh
賦予可執(zhí)行權(quán)限 (chmod +x build_x264.sh setting.sh
)
修改完后就可以執(zhí)行腳本命令了
./build_x264.sh
等待一段時(shí)間后粤剧,build
文件夾目錄下應(yīng)該有個(gè) lib
目錄(build 腳本里面 prefix 指定的目錄),里面存放了 x264
的靜態(tài)庫
這里為什么編譯成靜態(tài)庫而不是動(dòng)態(tài)庫呢挥唠?靜態(tài)庫可以把內(nèi)容編譯到待會(huì)兒要編譯
ffmpeg
的so庫里去抵恋,不需要單獨(dú)加載libx264.so
了,如果你硬要編譯成動(dòng)態(tài)庫也可以宝磨,加載ffmpeg.so
的時(shí)候加載libx264.so
就可以
至此弧关,x264
編碼器編譯完畢
編譯 FFmpeg
同樣在 build
文件夾下建立編譯腳本 build_ffmpeg.sh
,編譯 ffmpeg
比編譯 x264
略微麻煩點(diǎn)唤锉,首先肯定不能全功能編譯世囊,那還不如直接去網(wǎng)上找一個(gè)編譯好的,要自己定制哪些組件需要窿祥,哪些組件不需要
FFmpeg它主要含有以下幾個(gè)核心庫:
- libavcodec-提供了更加全面的編解碼實(shí)現(xiàn)的合集
- libavformat-提供了更加全面的音視頻容器格式的封裝和解析以及所支持的協(xié)議
- libavutil-提供了一些公共函數(shù)
- libavfilter-提供音視頻的過濾器株憾,如視頻加水印、音頻變聲等
- libavdevice-提供支持眾多設(shè)備數(shù)據(jù)的輸入與輸出,如讀取攝像頭數(shù)據(jù)嗤瞎、屏幕錄制
- libswresample,libavresample-提供音頻的重采樣工具
- libswscale-提供對(duì)視頻圖像進(jìn)行色彩轉(zhuǎn)換墙歪、縮放以及像素格式轉(zhuǎn)換,如圖像的YUV轉(zhuǎn)換
- libpostproc-多媒體后處理器
如果不修改什么配置贝奇,直接編譯的話虹菲,我發(fā)現(xiàn) libavcodec.so
有 7.8MB,我可以在這方面下手掉瞳,指定 decoder
和 encoder
届惋,因?yàn)槲倚枰氖且曨l壓縮,所以編碼器(encoder
)我就只需要 x264
(視頻編碼) 和 aac
(音頻編碼)菠赚,至于解碼器,挑幾個(gè)常用的就可以了
查看編碼器和解碼器種類郑藏,可以通過 ./config --list-decoders 或 ./config --list-encoers 命令實(shí)現(xiàn)(ffmpeg目錄下)
./config 內(nèi)的# 注釋必須在運(yùn)行的時(shí)候去掉
#!/bin/bash
# 導(dǎo)入環(huán)境變量
. setting.sh
# 輸出衡查,調(diào)試用
echo "use toolchain: $TOOLCHAIN"
echo "use system root: $SYSROOT"
# x264庫所在的位置,ffmpeg 需要鏈接 x264
LIB_DIR=$(pwd)/lib;
# ffmpeg編譯輸出前綴
PREFIX=$LIB_DIR/ffmpeg/$CPU
# x264的頭文件地址
INC="$LIB_DIR/x264/$CPU/include"
# x264的靜態(tài)庫地址
LIB="$LIB_DIR/x264/$CPU/lib"
# 輸出調(diào)試
echo "include dir: $INC"
echo "lib dir: $LIB"
# 編譯優(yōu)化參數(shù)
FF_EXTRA_CFLAGS="-march=$CPU -mfpu=vfpv3-d16 -mfloat-abi=softfp -mthumb"
# 編譯優(yōu)化參數(shù)必盖,-I$INC 指定 x264 頭文件路徑
FF_CFLAGS="-O3 -Wall -pipe \
-ffast-math \
-fstrict-aliasing -Werror=strict-aliasing \
-Wno-psabi -Wa,--noexecstack \
-DANDROID \
-I$INC"
cd ../ffmpeg
function build_arm
{
./configure \
# 這里需要啟動(dòng)生成動(dòng)態(tài)庫
--enable-shared \
# 靜態(tài)庫就不生成了
--disable-static \
--disable-ffmpeg \
--disable-ffplay \
--disable-ffprobe \
--disable-ffserver \
--disable-symver \
# 禁用全部的編碼
--disable-encoders \
# 啟用 x264 這個(gè)庫
--enable-libx264 \
# 啟用 x264 編碼
--enable-encoder=libx264 \
# 啟用 aac 音頻編碼
--enable-encoder=aac \
# 啟用幾個(gè)圖片編碼拌牲,由于生成視頻預(yù)覽
--enable-encoder=mjpeg \
--enable-encoder=png \
# 禁用全部的解碼器
--disable-decoders \
# 啟用幾個(gè)常用的解碼
--enable-decoder=aac \
--enable-decoder=aac_latm \
--enable-decoder=h264 \
--enable-decoder=mpeg4 \
--enable-decoder=mjpeg \
--enable-decoder=png \
--disable-demuxers \
--enable-demuxer=image2 \
--enable-demuxer=h264 \
--enable-demuxer=aac \
--enable-demuxer=avi \
--enable-demuxer=mpc \
--enable-demuxer=mov \
--disable-parsers \
--enable-parser=aac \
--enable-parser=ac3 \
--enable-parser=h264 \
# 這幾個(gè)庫應(yīng)該需要,沒怎么測(cè)試歌粥,反正很小就加上了
--enable-avresample \
--enable-small \
--enable-avfilter \
# 這兩個(gè)是鏈接 x264 靜態(tài)庫需要
--enable-gpl \
--enable-yasm \
# 編譯輸出前綴
--prefix=$PREFIX \
--cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
--target-os=linux \
--arch=arm \
--enable-cross-compile \
--sysroot=$SYSROOT \
--extra-cflags="$FF_CFLAGS $FF_EXTRA_CFLAGS" \
# 指定 x264 靜態(tài)庫位置
--extra-ldflags="-Wl,-L$LIB"
make clean
make -j16
make install
}
build_arm
這次編譯不用靜態(tài)庫的原因是塌忽,靜態(tài)庫鏈接是有順序要求的,這里模塊太多失驶,我也不知道哪個(gè)模塊依賴哪個(gè)模塊土居,所以直接上動(dòng)態(tài)庫
腳本寫完后,就可以 run 了嬉探,編譯時(shí)間有點(diǎn)久擦耀,可以學(xué)學(xué)我的某個(gè)同學(xué),一編譯就起來泡泡妹子涩堤,有說有笑眷蜓。
編譯完成后你的目錄應(yīng)該是下面那個(gè)樣子:
--- FFmpegAndroid
|-- ffmpeg
|-- x264
|-- build
|-- build_ffmpeg.sh
|-- build_x264.sh
|-- lib
|-- ffmpeg/armv7-a
|-- include (ffmpeg so庫的頭文件)
|-- lib (ffmpeg so庫)
|-- libavcodec-57.so
|-- libavdevice-57.so
|-- libavcodec-57.so
|-- libavfilter-6.so
|-- libavformat-57.so
|-- libavresample-3.so
|-- libavutil-55.so
|-- libpostproc-54.so
|-- libresample-2.so
|-- libswscale-4.so
|-- x264 (x264的靜態(tài)庫和頭文件)
后面的版本號(hào)不一樣沒關(guān)系,這由
ffmpeg
版本決定的
庫編譯完了胎围,這些 so 庫就是在 Android 可用的動(dòng)態(tài)庫吁系,接下來就可以準(zhǔn)備 JNI 編程了
三、在 Android 里使用 FFmpeg
前面已經(jīng)把 FFmpeg
各個(gè)核心庫編譯出來了白魂,但是我肯定不會(huì)在里面直接用核心庫內(nèi)的函數(shù)來用汽纤,ffmpeg
本來是一個(gè)在 pc 端的命令,命令里面可以填寫各種參數(shù)碧聪,比如 ffmpeg -i a.mp4 -c:v x264 -c:a aac b.mp4
冒版,就是把 a.mp4 用 x264
(視頻)、aac
(音頻) 編碼成 b.mp4
逞姿。
ffmpeg
是由 ffmpeg.c
編譯出來的辞嗡,想要在 Android 里面用 ffmpeg
命令捆等,只要修改 ffmpeg.c
里面的 main 函數(shù),比如修改成 int run_ffmpeg_command(int args, char **argv)
续室,然后用 JNI 暴露給 java 調(diào)用栋烤,就可以在 Android 使用 ffmpeg
命令了
在 FFmpegAndroid 建立一個(gè) Android 工程,然后新建一個(gè) ffmpeg 的 lib module
對(duì)于 NDK 開發(fā)挺狰,AndroidStudio 2.2 以后就有較好的支持明郭,直接修改支持庫的 build.gradle 文件
apply plugin: 'com.android.library'
android {
...
defaultConfig {
...
// 啟用 c++ 支持
externalNativeBuild {
cmake {
cppFlags "-std=c++11"
}
ndk {
abiFilters "armeabi-v7a"
}
}
}
...
// 指定 CMakeList 文件
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
}
這樣 lib module 就支持 c++ 了,方便吧丰泊!比以前的 Android.mk 不知道方便多少
然后在模塊的 src/main
下面新建一個(gè) cpp
目錄薯定,用于存放 c++ 代碼,從ffmpeg
拷貝以下文件:
cmdutils_common_opts.h
cmdutils.c
cmdutils.h
config.h
ffmpeg_filter.c
ffmpeg_opt.c
ffmpeg-lib.c
ffmpeg.c
ffmpeg.h
然后在 CMakeList.txt 里面配置這些文件瞳购,好讓 AndroidStudio 認(rèn)識(shí)它們
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html
# Sets the minimum version of CMake required to build the native library.
cmake_minimum_required(VERSION 3.4.1)
# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.
add_library( # Sets the name of the library.
ffmpeg-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
src/main/cpp/cmdutils.c
src/main/cpp/ffmpeg.c
src/main/cpp/ffmpeg_filter.c
src/main/cpp/ffmpeg_opt.c
# 此文件是用于暴露 ffmpeg.c 的 main 函數(shù)用
src/main/cpp/ffmpeg-lib.c)
set(FFMPEG_LIB_DIR /Users/qigengxin/Documents/Github/FFmpegAndroid/build/lib/ffmpeg/armv7-a/lib)
add_library(
avcodec
SHARED
IMPORTED
)
set_target_properties(
avcodec
PROPERTIES IMPORTED_LOCATION
${FFMPEG_LIB_DIR}/libavcodec-57.so
)
add_library(
avdevice
SHARED
IMPORTED
)
set_target_properties(
avdevice
PROPERTIES IMPORTED_LOCATION
${FFMPEG_LIB_DIR}/libavdevice-57.so
)
add_library(
avfilter
SHARED
IMPORTED
)
set_target_properties(
avfilter
PROPERTIES IMPORTED_LOCATION
${FFMPEG_LIB_DIR}/libavfilter-6.so
)
add_library(
avformat
SHARED
IMPORTED
)
set_target_properties(
avformat
PROPERTIES IMPORTED_LOCATION
${FFMPEG_LIB_DIR}/libavformat-57.so
)
add_library(
avresample
SHARED
IMPORTED
)
set_target_properties(
avresample
PROPERTIES IMPORTED_LOCATION
${FFMPEG_LIB_DIR}/libavresample-3.so
)
add_library(
avutil
SHARED
IMPORTED
)
set_target_properties(
avutil
PROPERTIES IMPORTED_LOCATION
${FFMPEG_LIB_DIR}/libavutil-55.so
)
add_library(
postproc
SHARED
IMPORTED
)
set_target_properties(
postproc
PROPERTIES IMPORTED_LOCATION
${FFMPEG_LIB_DIR}/libpostproc-54.so
)
add_library(
swresample
SHARED
IMPORTED
)
set_target_properties(
swresample
PROPERTIES IMPORTED_LOCATION
${FFMPEG_LIB_DIR}/libswresample-2.so
)
add_library(
swscale
SHARED
IMPORTED
)
set_target_properties(
swscale
PROPERTIES IMPORTED_LOCATION
${FFMPEG_LIB_DIR}/libswscale-4.so
)
include_directories(
../../ffmpeg
)
# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log )
# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.
target_link_libraries( # Specifies the target library.
ffmpeg-lib
avcodec
avutil
avfilter
swscale
swresample
avresample
postproc
avformat
avdevice
# Links the target library to the log library
# included in the NDK.
${log-lib} )
刷新下 gradle话侄,就可以寫 c++ 代碼了。先看下 ffmpeg.c
這個(gè)文件学赛,原先的指令其實(shí)調(diào)用的就是 main 函數(shù)年堆,我們先把 main 函數(shù)改成自己自定義的函數(shù) run_ffmpeg_command
:
int run_ffmpeg_command(int argc, char **argv){
...
}
改了以后,我們就可以調(diào)用 run_ffmpeg_command
然后傳入?yún)?shù)盏浇,相當(dāng)于在 pc 執(zhí)行 ffmpeg
命令变丧。不過現(xiàn)在還不能執(zhí)行,這是個(gè)坑點(diǎn)绢掰,仔細(xì)看 run_ffmpeg_command
函數(shù)痒蓬,在程序結(jié)束的時(shí)候,或者中途出現(xiàn)錯(cuò)誤的時(shí)候滴劲,都會(huì)調(diào)用 exit_program(int)
谊却,這個(gè)函數(shù):
int run_ffmpeg_command(int argc, char **argv){
...
/* parse options and open all input/output files */
ret = ffmpeg_parse_options(argc, argv);
if (ret < 0){
exit_program(1);
}
...
if (nb_output_files <= 0 && nb_input_files == 0) {
show_usage();
av_log(NULL, AV_LOG_WARNING, "Use -h to get full help or, even better, run 'man %s'\n", program_name);
exit_program(1);
}
exit_program(received_nb_signals ? 255 : main_return_code);
return main_return_code;
}
exit_program(int)
函數(shù)是什么,跳過去看一下發(fā)現(xiàn)里面就是清理資源然后 exit(int)
哑芹,這里就要注意這個(gè) exit 函數(shù)了炎辨,除非我們是多進(jìn)程方式調(diào)用 run_ffmpeg_command
,如果我們?cè)?app 的進(jìn)程調(diào)用聪姿,執(zhí)行了 exit 就會(huì)結(jié)束 app 的進(jìn)程碴萧!
這不是我想看到的,最好的方法是另開一個(gè)進(jìn)程調(diào)用末购,但是這樣就涉及到了進(jìn)程間的通信問題破喻,麻煩,不想寫盟榴!反正只是跑一個(gè)壓縮指令嘛曹质,直接改 ffmpeg.c
,首先把 exit(int)
函數(shù)給注釋掉,然后返回一個(gè) code羽德,run_ffmpeg_command
函數(shù)里面只要涉及到 exit_program(int)
函數(shù)調(diào)用的地方都寫成 return exit_program(int)
几莽,不過要注意,有如下幾個(gè)坑點(diǎn):
修改 ffmpeg.c 坑點(diǎn)一
調(diào)試的時(shí)候發(fā)現(xiàn) return exit_program(int);
語句并不會(huì)結(jié)束當(dāng)前函數(shù)并返回宅静,而是繼續(xù)往下執(zhí)行了章蚣,當(dāng)時(shí)一臉楞逼,我艸R碳小纤垂!這是什么鬼?磷账?為什么我 return 了沒有用峭沦?找了半天后才發(fā)現(xiàn)是 exit_program(int)
這個(gè)函數(shù)聲明的鍋!看下面這個(gè)函數(shù)的聲明:
/**
* Wraps exit with a program-specific cleanup routine.
*/
int exit_program(int ret) av_noreturn;
函數(shù)后面有個(gè)奇怪的 av_noreturn
聲明逃糟,網(wǎng)上查了一下才知道熙侍,這個(gè)是給編譯器的注解,這貨的鍋履磨,去掉就好了。
修改 ffmpeg.c 坑點(diǎn)二
其實(shí) exit_program(int)
這個(gè)函數(shù)不只是在 run_ffmpeg_command
里面調(diào)用庆尘,其它各種函數(shù)里面都有剃诅,如果都要修改的話必須一層一層的 return (C語言里面沒有異常啊),很麻煩驶忌,但是如果沒有改好的話就很容易 crash矛辕,這是個(gè)要解決的問題,首先 run_ffmpeg_command
里面的 exit_program
都要改成 return 方式
然后因?yàn)樽罱K目的是壓縮視頻付魔,參數(shù)集是固定的聊品,所以不用考慮編碼不支持,或參數(shù)匹配不到的情況几苍,只需要考慮文件讀寫的問題翻屈,就是輸入文件不存在的時(shí)候,或者輸出路徑不合法的時(shí)候妻坝,不能讓程序異常退出伸眶,而是返回錯(cuò)誤碼,這個(gè)需要改 ffmpeg_opt.c
這個(gè)文件
ffmpeg_opt.c
static int open_files(OptionGroupList *l, const char *inout, int (*open_file)(OptionsContext*, const char*)){
...
}
static int open_input_file(OptionsContext *o, const char *filename){
...
}
static int open_outout_file(OptionsContext *o, const char *filename){
...
}
static int init_output_filter(OutputFilter *ofilter, OptionsContext *o, AVFormatContext *oc){
...
}
目前我項(xiàng)目中就只改了這幾個(gè)函數(shù)內(nèi)的 exit_program
刽宪,測(cè)試可行厘贼,也可以參考本項(xiàng)目的代碼,鏈接在文末
最后就是暴露 run_ffmpeg_command
方法給 java 調(diào)用了圣拄,這個(gè)和普通的 JNI 編程一樣嘴秸,建一個(gè) native 的方法,創(chuàng)建 cpp 代碼。岳掐。凭疮。沒啥東西,直接上代碼
FFmpegNativeBridge
public class FFmpegNativeBridge {
static {
System.loadLibrary("ffmpeg-lib");
}
/**
* 執(zhí)行指令
* @param command
* @return 命令返回結(jié)果
*/
public static native int runCommand(String[] command);
}
ffmpeg-lib.c
#include <jni.h>
#include "ffmpeg.h"
JNIEXPORT jint JNICALL
Java_org_voiddog_ffmpeg_FFmpegNativeBridge_runCommand(JNIEnv *env, jclass type,
jobjectArray command) {
int argc = (*env)->GetArrayLength(env, command);
char *argv[argc];
jstring jsArray[argc];
int i;
for (i = 0; i < argc; i++) {
jsArray[i] = (jstring) (*env)->GetObjectArrayElement(env, command, i);
argv[i] = (char *) (*env)->GetStringUTFChars(env, jsArray[i], 0);
}
int ret = run_ffmpeg_command(argc,argv);
for (i = 0; i < argc; ++i) {
(*env)->ReleaseStringUTFChars(env, jsArray[i], argv[i]);
}
return ret;
}
運(yùn)行前先需要把 ffmpeg
編譯出來的一堆 so
庫放到 jniLibs
內(nèi)岩四,不然運(yùn)行的時(shí)候會(huì)出現(xiàn)動(dòng)態(tài)庫無法加載的異常哭尝。最后就可以在 Android
內(nèi)用 ffmpeg
的命令了:
int ret = FFmpegNativeBridge.runCommand(new String[]{"ffmpeg",
"-i", "/storage/emulated/0/DCIM/Camera/VID_20170527_175421.mp4",
"-y",
"-c:v", "libx264",
"-c:a", "aac",
"-vf", "scale=480:-2",
"-preset", "ultrafast",
"-crf", "28",
"-b:a", "128k",
"/storage/emulated/0/Download/a.mp4"});
關(guān)于這些參數(shù),可以去查
FFmpeg
的官網(wǎng)剖煌,本項(xiàng)目源碼地址Github