引言
目前在學習FFmpeg的使用较坛,肯定是要從源碼編譯開始一步步摸啦喜命,編譯過程中也是遇到了大大小小很多問題籽腕,查到的資料基本也都是比較老舊的版本爱葵,經(jīng)過各種試錯吧施戴,終于是編譯成功了,現(xiàn)在就來記錄一下編譯的過程萌丈,也希望能幫助到看這篇文章的你赞哗。
源碼與環(huán)境
編譯安卓系統(tǒng)使用的庫,需要用到NDK的工具鏈進行交叉編譯辆雾,我們這里使用的是 r20b 版本肪笋。
還有就是需要下載的源碼了,包括 FFmpeg 和 OpenSSL 的源代碼度迂,我們直接去官網(wǎng)下載最新的版本藤乙。
NDK歷史版本:https://developer.android.google.cn/ndk/downloads/revision_history
FFmpeg源碼:http://www.ffmpeg.org/download.html
OpenSSL源碼:https://www.openssl.org/source/snapshot/
準備編譯腳本
哎呀,現(xiàn)在還沒有時間寫詳細介紹惭墓,就先把腳本直接貼到這里吧坛梁。挖個坑,后面有時間再補腊凶,放個狗頭保命??
OpenSSL腳本
當然如果你不需要支持https划咐,就可以跳過openssl,直接去編譯ffmpeg钧萍。
#!/bin/bash
set -x
# NDK的路徑褐缠,根據(jù)自己的NDK位置進行設置
export ANDROID_NDK_ROOT=/Users/xxx/env/android-sdk/ndk/android-ndk-r20b
# 編譯工具鏈路徑
TOOLCHAIN=$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/darwin-x86_64
# 編譯環(huán)境
SYSROOT=$TOOLCHAIN/sysroot
# 目標Android版本
API=21
# 目標指令集
ARCH=NONE
#so庫輸出目錄
OUTPUT_DIR=NONE
function build_armv7a() {
ARCH=android-arm
OUTPUT_DIR=$PWD/outputs/armeabi-v7a
build_one
}
function build_aarch64() {
ARCH=android-arm64
OUTPUT_DIR=$PWD/outputs/arm64-v8a
build_one
}
function build_one() {
CC=clang
export PATH=$TOOLCHAIN/bin:$PATH
./configure \
$ARCH \
-D__ANDROID_API__=$API \
--prefix=$OUTPUT_DIR
make clean all
# 這里是定義用幾個CPU編譯
make -j12
make install
}
# 懶,就這么寫吧划煮,編哪個就放開哪個
build_armv7a
#build_aarch64
放在OpenSSL源碼更目錄下送丰,命令行進入文件夾并執(zhí)行該腳本,成功后會在當前目錄下生成如下目錄弛秋,需要用到的頭文件和靜態(tài)器躏、動態(tài)庫俐载,就在對應的 include 和 lib 文件夾下。
FFmpeg腳本
#!/bin/bash
set -x
# NDK的路徑遏佣,根據(jù)自己的NDK位置進行設置
NDK=/Users/wwf/Desktop/env/android-sdk/ndk/android-ndk-r20b
# 編譯工具鏈路徑
TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/darwin-x86_64
# 編譯環(huán)境
SYSROOT=$TOOLCHAIN/sysroot
# 目標Android版本
API=21
# 目標指令集
ARCH=NONE
#so庫輸出目錄
OUTPUT_DIR=NONE
# 交叉編譯命令前綴
CROSS_PREFIX=NONE
CROSS_PREFIX_CLANG=NONE
# 若不添加 openssl 支持,這項不需要配置
OPENSSL_DIR=NONE
function build_armv7a() {
ARCH=arm
OUTPUT_DIR=$PWD/outputs/armeabi-v7a
CROSS_PREFIX=$TOOLCHAIN/bin/arm-linux-androideabi-
CROSS_PREFIX_CLANG=$TOOLCHAIN/bin/armv7a-linux-androideabi$API-
OPENSSL_DIR=$PWD/openssl/armeabi-v7a
del_temp_config
build_one
}
function build_aarch64() {
ARCH=aarch64
OUTPUT_DIR=$PWD/outputs/arm64-v8a
CROSS_PREFIX=$TOOLCHAIN/bin/aarch64-linux-android-
CROSS_PREFIX_CLANG=$TOOLCHAIN/bin/aarch64-linux-android$API-
OPENSSL_DIR=$PWD/openssl/arm64-v8a
del_temp_config
build_one
}
function del_temp_config {
rm -rf config_components.h
rm -rf config.h
}
function build_one() {
./configure \
--prefix=$OUTPUT_DIR \
--target-os=android \
--arch=$ARCH \
--enable-asm \
--enable-neon \
--enable-cross-compile \
--enable-shared \
--disable-static \
--disable-doc \
--disable-ffplay \
--disable-ffprobe \
--disable-symver \
--disable-ffmpeg \
--sysroot=$SYSROOT \
--cc=${CROSS_PREFIX_CLANG}clang \
--cxx=${CROSS_PREFIX_CLANG}clang++ \
--cross-prefix=$CROSS_PREFIX \
--enable-openssl \
--enable-protocols \
--enable-protocol=https \
--enable-nonfree \
--extra-cflags="-I$OPENSSL_DIR/include -fPIC" \
--extra-ldflags="-L$OPENSSL_DIR/lib -lssl -lcrypto" \
# 若不添加 openssl 支持揽浙,上面幾項不需要配置状婶,替換成下面這句
# --extra-cflags="-fPIC"
make clean all
# 這里是定義用幾個CPU編譯
make -j12
make install
}
# 懶,就這么寫吧馅巷,編哪個就放開哪個
build_armv7a
#build_aarch64
其中與openssl相關的部分就是 --enable-openssl 及后面的幾句膛虫,作用是允許使用openssl和執(zhí)行要鏈接的頭文件和靜態(tài)庫路徑。
如果不需要鏈接編譯 openssl 的話钓猬,腳本中的這一部分就是這樣的:
function build_one() {
./configure \
--prefix=$OUTPUT_DIR \
...... 忽略部分 ......
--cross-prefix=$CROSS_PREFIX \
--extra-cflags="-fPIC" \
make clean all
# 這里是定義用幾個CPU編譯
make -j12
make install
}
安卓項目使用與 CMakeList 編寫
還是這句話稍刀,直接把腳本貼上吧,有時間在補充詳細說明敞曹。
# 最低版本支持
cmake_minimum_required(VERSION 3.18.1)
# 項目名账月,就是編譯后生成的 so 庫名字
project("ffmpegdemo")
# 支持gnu++11
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")
# 1. 添加頭文件目錄, 定義so庫和頭文件所在目錄
include_directories(${CMAKE_SOURCE_DIR}/ffmpeg/include)
set(lib_dir ${CMAKE_SOURCE_DIR}/ffmpeg/lib/${ANDROID_ABI})
add_library( avcodec
SHARED
IMPORTED )
set_target_properties( avcodec
PROPERTIES IMPORTED_LOCATION
${lib_dir}/libavcodec.so )
add_library( avfilter
SHARED
IMPORTED )
set_target_properties( avfilter
PROPERTIES IMPORTED_LOCATION
${lib_dir}/libavfilter.so )
add_library( avformat
SHARED
IMPORTED )
set_target_properties( avformat
PROPERTIES IMPORTED_LOCATION
${lib_dir}/libavformat.so )
add_library( avutil
SHARED
IMPORTED )
set_target_properties( avutil
PROPERTIES IMPORTED_LOCATION
${lib_dir}/libavutil.so )
add_library( swresample
SHARED
IMPORTED )
set_target_properties( swresample
PROPERTIES IMPORTED_LOCATION
${lib_dir}/libswresample.so )
add_library( swscale
SHARED
IMPORTED )
set_target_properties( swscale
PROPERTIES IMPORTED_LOCATION
${lib_dir}/libswscale.so )
add_library( avdevice
SHARED
IMPORTED )
set_target_properties( avdevice
PROPERTIES IMPORTED_LOCATION
${lib_dir}/libavdevice.so )
add_library( ssl
SHARED
IMPORTED )
set_target_properties( ssl
PROPERTIES IMPORTED_LOCATION
${lib_dir}/libssl.so )
add_library( crypto
SHARED
IMPORTED )
set_target_properties( crypto
PROPERTIES IMPORTED_LOCATION
${lib_dir}/libcrypto.so )
# 當前cmake文件所在目錄下搜索所有源碼文件,命名為 SRC_LIST 供下面使用
aux_source_directory(. SRC_ROOT)
aux_source_directory(./audiosample SRC_AUDIO)
add_library( # Sets the name of the library.
ffmpegdemo
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
${SRC_ROOT}
${SRC_AUDIO}
# native-lib.cpp
)
# 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.
ffmpegdemo
# ffmpeg
avcodec
avfilter
avformat
avutil
swresample
swscale
avdevice
ssl
crypto
OpenSLES
# Links the target library to the log library
# included in the NDK.
${log-lib})
這里再貼一下我的目錄結構吧澳迫,這些東西怎么放其實都無所謂局齿,主要是要跟 gradle 和 cmake 文件中用到的路徑對得上號。
先寫到這里吧抓歼,沒有詳細說明很是慚愧,后面有時間一定補上拢锹。