網(wǎng)站設(shè)置訪問(wèn)密碼達(dá)內(nèi)教育
系列文章目錄
- 基于 FFmpeg 的跨平臺(tái)視頻播放器簡(jiǎn)明教程(一):FFMPEG + Conan 環(huán)境集成
- 基于 FFmpeg 的跨平臺(tái)視頻播放器簡(jiǎn)明教程(二):基礎(chǔ)知識(shí)和解封裝(demux)
- 基于 FFmpeg 的跨平臺(tái)視頻播放器簡(jiǎn)明教程(三):視頻解碼
- 基于 FFmpeg 的跨平臺(tái)視頻播放器簡(jiǎn)明教程(四):像素格式與格式轉(zhuǎn)換
- 基于 FFmpeg 的跨平臺(tái)視頻播放器簡(jiǎn)明教程(五):使用 SDL 播放視頻
- 基于 FFmpeg 的跨平臺(tái)視頻播放器簡(jiǎn)明教程(六):使用 SDL 播放音頻和視頻
- 基于 FFmpeg 的跨平臺(tái)視頻播放器簡(jiǎn)明教程(七):使用多線程解碼視頻和音頻
- 基于 FFmpeg 的跨平臺(tái)視頻播放器簡(jiǎn)明教程(八):音畫(huà)同步
- 基于 FFmpeg 的跨平臺(tái)視頻播放器簡(jiǎn)明教程(九):Seek 策略
前言
在前九章的學(xué)習(xí)中,我們已經(jīng)成功地實(shí)現(xiàn)了一個(gè)基礎(chǔ)的播放器,它擁有視頻播放、音畫(huà)同步、快進(jìn)/快退等基本功能。當(dāng)然,這個(gè)簡(jiǎn)易的示例還有許多可以優(yōu)化的地方,比如添加更美觀的用戶界面,或者增加字幕功能等。然而,這并不是本教程的主要關(guān)注點(diǎn)。本系列文章更關(guān)注于跨平臺(tái)播放器框架的構(gòu)建,特別是在移動(dòng)端。因此,從本章開(kāi)始,我們將把重點(diǎn)轉(zhuǎn)向 Android 端播放器的開(kāi)發(fā)。
前置知識(shí)包括一些 Android 的基本開(kāi)發(fā),以及 JNI 開(kāi)發(fā)等。這些前置知識(shí)默認(rèn)你有所了解,本文不會(huì)涉及。關(guān)于 JNI 可以參考筆者之前寫(xiě)的 JNI 簡(jiǎn)明教程之手把手教你入門(mén)
本文代碼在 android/tutorial01。
FFmpeg Android 編譯
FFmpeg 的跨端編譯也是老生常談的話題了,本文不去討論那些細(xì)節(jié)問(wèn)題,只想提供一種最便捷的編譯方法。在 CompilationGuide/Android 中給出了一些指導(dǎo)意見(jiàn),例如直接使用已經(jīng)編譯好的 so,或者使用別人寫(xiě)好的腳本。對(duì)比了這幾個(gè)方法,ffmpeg-android-maker 比較合適,優(yōu)勢(shì)包括:
- 網(wǎng)上那些已經(jīng)編譯好的 ffmpeg so,ffmepg 版本可能太老了。ffmpeg-android-maker 則是從源碼直接編譯
- ffmpeg-android-maker 能夠自動(dòng)拉取 ffmpeg 源碼,只需要設(shè)置少量的變量就能開(kāi)始編譯
- ffmpeg-android-maker 功能、文檔寫(xiě)的比較清楚,用起來(lái)沒(méi)有卡點(diǎn)。
那么基于 ffmpeg-android-maker 要如何編譯 android ffmpeg 呢?非常簡(jiǎn)單,步驟如下。
- 下載 ffmpeg-android-marker 倉(cāng)庫(kù)
git clone git@github.com:Javernaut/ffmpeg-android-maker.git
cd ffmpeg-android-maker
- 設(shè)置環(huán)境變量
export ANDROID_SDK_HOME=/Users/user/Library/Android/sdk
export ANDROID_NDK_HOME=/Users/user/Library/Android/sdk/ndk/25.2.9519653
- 運(yùn)行腳本
./ffmpeg-android-maker.sh
編譯成功后,你可以在當(dāng)前文件夾的 build
目錄下找到各個(gè)架構(gòu)的 ffmpeg 庫(kù):
build
└── ffmpeg├── arm64-v8a│ ├── bin│ ├── include│ ├── lib│ └── share├── armeabi-v7a│ ├── bin│ ├── include│ ├── lib│ └── share├── x86│ ├── bin│ ├── include│ ├── lib│ └── share└── x86_64├── bin├── include├── lib└── share
其中 include 和 lib 是我們需要的。
FFmpeg so 導(dǎo)入 Android 項(xiàng)目
將 so 文件放置在正確的位置
第一步當(dāng)然是將編譯好的 ffmpeg so 文件和頭文件拷貝到我們的項(xiàng)目中。在編譯產(chǎn)物中,我們只需要 include 和 lib 文件夾即可,將它們拷貝至 3rdparty/ffmpeg/android 目錄下。當(dāng)然你也可以選擇其他地方,這只是我個(gè)人的選擇。
android
├── arm64-v8a
│ ├── include
│ └── lib
├── armeabi-v7a
│ ├── include
│ └── lib
├── x86
│ ├── include
│ └── lib
└── x86_64├── include└── lib
寫(xiě) CMake 將 FFmpeg so 引入項(xiàng)目
ffmpeg 有多個(gè) so 文件,在編譯項(xiàng)目的過(guò)程中,如果一個(gè)一個(gè)地去寫(xiě) link 命令有點(diǎn)麻煩。通常的做法是,創(chuàng)建一個(gè)新的 library,例如叫 ffmpeg_libs
,讓 ffmpeg_libs
去 link 這些 so 文件,然后其他模塊 link ffmpeg_libs
就能夠鏈?zhǔn)降貙⑺幸蕾嚩紟狭恕?/p>
這部分屬于 CMake 的知識(shí)范疇,不細(xì)說(shuō)了,可以參考筆者之前寫(xiě)的 現(xiàn)代 CMake 簡(jiǎn)明教程(一)- CMake 基礎(chǔ)。具體 CMake 源碼在 CMakeLists.txt 大家自己看。
寫(xiě) Kotlin 和 JNI 調(diào)用 FFmpeg API
Android app 想要調(diào)用 C/C++ 的接口就必須通過(guò) JNI 接口來(lái)實(shí)現(xiàn)。首先,在應(yīng)用層定義一個(gè) native method 叫 stringFromFFMPEG
external fun stringFromFFMPEG(): String
接著定義 JNI 層接口,新建 src/cpp/native-lib.cpp
文件,并完成 JNI 層代碼:
#include <jni.h>
#include <string>
extern "C"
{
#include <libavutil/avutil.h>
}extern "C" JNIEXPORT jstring JNICALL
Java_com_test_tutorial01_MainActivity_stringFromFFMPEG(JNIEnv* env,jobject /* this */) {std::string hello = "Hello from ffmpeg: " + std::string(av_version_info());return env->NewStringUTF(hello.c_str());
}
最后,我們將 UI 上的 TextView 中的字符串內(nèi)容修改為這個(gè)函數(shù)的返回值即可:
binding.sampleText.text = stringFromFFMPEG()
最終呈現(xiàn)的效果如下圖:
總結(jié)
本文介紹了一種非常便捷的編譯 android ffmpeg 的方法:ffmpeg-android-maker。說(shuō)明如何將 ffmpeg so 庫(kù)導(dǎo)入至 android 項(xiàng)目中,并提供了實(shí)例代碼(代碼地址:這里)
參考
- JNI 簡(jiǎn)明教程之手把手教你入門(mén)
- CompilationGuide/Android
- 現(xiàn)代 CMake 簡(jiǎn)明教程(一)- CMake 基礎(chǔ)