本人第一次寫(xiě)文章试躏,因?yàn)閷?duì)于一個(gè)剛接觸ffmpeg的人來(lái)說(shuō)編譯SO和在Android studio上編譯中遇到了很多坑,所以身心體會(huì)了里面的很多坑设褐,所以寫(xiě)這篇文章颠蕴,希望對(duì)大家有用
本文中又多個(gè)庫(kù)和單個(gè)庫(kù)的編譯,大家可以自由選擇
首先編譯FFmpeg推薦裝個(gè)虛擬機(jī)然后用Ubuntu來(lái)編譯
首先去FFmpeg官網(wǎng)去下載Download FFmpeg 4.0版的助析,然后在Android官網(wǎng)下載NDK建議使用r14版本犀被,高的版本會(huì)出現(xiàn)問(wèn)題NDK r14版本下載地方
在很多文章中需要修改ffmpeg里面configure文件,但也可以不用修改外冀,在創(chuàng)建編譯腳本得時(shí)候加上--target-os=android \寡键,就可以編譯需要得編譯庫(kù)
下面是創(chuàng)建build_android.sh腳本
#!/bin/sh
export NDK_HOME=/home/guoliang/Downloads/android-ndk-r14b
export NDK_HOST_PLATFORM=linux-x86_64
PREFIX=android-build
COMMON_OPTIONS="\
--prefix=android/ \
--target-os=android \
--disable-static \
--enable-shared \
--enable-small \
--disable-programs \
--disable-ffmpeg \
--disable-ffplay \
--disable-ffprobe \
--disable-doc \
--disable-symver \
--disable-asm \
"
function build_android {
./configure \
--libdir=${PREFIX}/libs/armeabi-v7a \
--incdir=${PREFIX}/includes/armeabi-v7a \
--pkgconfigdir=${PREFIX}/pkgconfig/armeabi-v7a \
--arch=arm \
--cpu=armv7-a \
--cross-prefix="${NDK_HOME}/toolchains/arm-linux-androideabi-4.9/prebuilt/${NDK_HOST_PLATFORM}/bin/arm-linux-androideabi-" \
--sysroot="${NDK_HOME}/platforms/android-19/arch-arm/" \
--extra-cflags="-march=armv7-a -mfloat-abi=softfp -mfpu=neon" \
--extra-ldexeflags=-pie \
${COMMON_OPTIONS}
make clean
make -j8 && make install
./configure \
--libdir=${PREFIX}/libs/arm64-v8a \
--incdir=${PREFIX}/includes/arm64-v8a \
--pkgconfigdir=${PREFIX}/pkgconfig/arm64-v8a \
--arch=aarch64 \
--cpu=armv8-a \
--cross-prefix="${NDK_HOME}/toolchains/aarch64-linux-android-4.9/prebuilt/${NDK_HOST_PLATFORM}/bin/aarch64-linux-android-" \
--sysroot="${NDK_HOME}/platforms/android-21/arch-arm64/" \
--extra-ldexeflags=-pie \
${COMMON_OPTIONS}
make clean
make -j8 && make install
./configure \
--libdir=${PREFIX}/libs/x86 \
--incdir=${PREFIX}/includes/x86 \
--pkgconfigdir=${PREFIX}/pkgconfig/x86 \
--arch=x86 \
--cpu=i686 \
--cross-prefix="${NDK_HOME}/toolchains/x86-4.9/prebuilt/${NDK_HOST_PLATFORM}/bin/i686-linux-android-" \
--sysroot="${NDK_HOME}/platforms/android-19/arch-x86/" \
--extra-ldexeflags=-pie \
${COMMON_OPTIONS}
make clean
make -j8 && make install
./configure \
--libdir=${PREFIX}/libs/x86_64 \
--incdir=${PREFIX}/includes/x86_64 \
--pkgconfigdir=${PREFIX}/pkgconfig/x86_64 \
--arch=x86_64 \
--cpu=x86_64 \
--cross-prefix="${NDK_HOME}/toolchains/x86_64-4.9/prebuilt/${NDK_HOST_PLATFORM}/bin/x86_64-linux-android-" \
--sysroot="${NDK_HOME}/platforms/android-21/arch-x86_64/" \
--extra-ldexeflags=-pie \
${COMMON_OPTIONS}
make clean
make -j8 && make install
};
build_android
NDK_HOME配置你的文件目錄
NDK_HOST_PLATFORM配置64位
在ffmpeg文件目錄下打開(kāi)終端運(yùn)行,下面兩條命令
chmod +x build_android.sh
./build_android.sh
下面是得到得文件
下來(lái)把includes和libs拷貝出來(lái)(記得要壓縮雪隧,虛擬機(jī)拷貝需要是壓縮文件才行)
創(chuàng)建一個(gè)支持C++的項(xiàng)目把編譯出來(lái)的文件放入項(xiàng)目中
下面這個(gè)是獲取8個(gè)庫(kù)的包和一個(gè)so庫(kù)(FFmpeg3.3.7版本)
make clean
export NDK=/home/guoliang/Downloads/android-ndk-r14b
export PREBUILT=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt
export PLATFORM=$NDK/platforms/android-14/arch-arm
export PREFIX=./android/$CPU-vfp
build_one(){
./configure --target-os=linux --prefix=$PREFIX \
--enable-cross-compile \
--enable-runtime-cpudetect \
--disable-asm \
--arch=arm \
--cc=$PREBUILT/linux-x86_64/bin/arm-linux-androideabi-gcc \
--cross-prefix=$PREBUILT/linux-x86_64/bin/arm-linux-androideabi- \
--disable-stripping \
--nm=$PREBUILT/linux-x86_64/bin/arm-linux-androideabi-nm \
--sysroot=$PLATFORM \
--enable-gpl --enable-static --disable-shared --enable-nonfree --enable-version3 --enable-small \
--enable-zlib --disable-ffprobe --disable-ffplay --disable-ffmpeg --disable-ffserver --disable-debug \
--extra-cflags="-fPIC -DANDROID -D__thumb__ -mthumb -Wfatal-errors -Wno-deprecated -mfloat-abi=softfp -marm -march=armv7-a"
}
build_one
make
make install
$PREBUILT/linux-x86_64/bin/arm-linux-androideabi-ld -rpath-link=$PLATFORM/usr/lib -L$PLATFORM/usr/lib -L$PREFIX/lib -soname libffmpeg.so -shared -nostdlib -Bsymbolic --whole-archive --no-undefined -o $PREFIX/libffmpeg.so libavcodec/libavcodec.a libavfilter/libavfilter.a libswresample/libswresample.a libavformat/libavformat.a libavutil/libavutil.a libswscale/libswscale.a libpostproc/libpostproc.a libavdevice/libavdevice.a -lc -lm -lz -ldl -llog --dynamic-linker=/system/bin/linker $PREBUILT/linux-x86_64/lib/gcc/arm-linux-androideabi/4.9.x/libgcc.a
cd ..
export PREFIX=./android/$CPU-vfp
這個(gè)字段后面是生成文件的所在地
上面獲取8個(gè)包和單個(gè)SO庫(kù)西轩,效果是一樣的员舵,但對(duì)于后面的步驟來(lái)說(shuō)更為方便(都是針對(duì)于arm,如需其他可以替換上面的字段)
切記把整個(gè)ffmpeg文件壓縮藕畔,不是單獨(dú)壓縮編譯好的文件马僻,因?yàn)楹竺娌襟E需要ffmpeg源碼里面的文件
下面是配置Android studio如何加載編譯好的文件
第一步創(chuàng)建新的項(xiàng)目
勾選位包涵c++項(xiàng)目,省去很多步驟
這一步看各自的需求來(lái)勾選注服,本人是這樣勾選的
第二步copy文件
畫(huà)紅線的是接下來(lái)會(huì)修改的文件韭邓,下面就是把咱們編譯好的文件copy進(jìn)入
畫(huà)圈的地方就是需要咱們編譯好的文件copy進(jìn)去,是不是感覺(jué)很簡(jiǎn)單祠汇,其實(shí)這才是剛剛開(kāi)始仍秤,大家會(huì)注意到我有兩個(gè)地方劃了紅線,這兩個(gè)文件需要大家自己建立可很,(這個(gè)時(shí)候就是需要咱們壓縮好的ffmpeg源碼的壓縮文件了)然后從咱們ffmpeg里面獲取這幾個(gè)文件然后copy進(jìn)入就可以了(因?yàn)楹笃诰幾g會(huì)遇到一些文件诗力,提前放進(jìn)去)
第三部 修改文件
修改app下build.gradle文件
紅框的地方是需要添加的
abiFilters 后面配置需要用armeabi-v7a ,因?yàn)锳ndroid studio3.1.3已經(jīng)不讓用 armeabi
下來(lái)需要修改CMakeLists.txt文件
cmake_minimum_required(VERSION 3.4.1)
add_library( # Sets the name of the library.
native-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
src/main/cpp/native-lib.cpp )
add_library( ffmpeg #切記不要用libffmpeg
SHARED
IMPORTED )
set_target_properties( ffmpeg
PROPERTIES IMPORTED_LOCATION
../../../../libs/${ANDROID_ABI}/libffmpeg.so)
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 )
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")
include_directories(src/main/cpp)
include_directories(src/main/cpp/include)
target_link_libraries( # Specifies the target library.
native-lib
ffmpeg
# Links the target library to the log library
# included in the NDK.
${log-lib} )
切記不要用libffmpeg起別名我抠,因?yàn)橛盟脑挄?huì)編譯的時(shí)候會(huì)報(bào)錯(cuò)苇本,本人就是被坑了
下面點(diǎn)擊一下
然后運(yùn)行一下項(xiàng)目看有沒(méi)有錯(cuò)誤,如果按上面的步驟走的
當(dāng)出現(xiàn)這個(gè)頁(yè)面那說(shuō)明上面的步驟都已經(jīng)沒(méi)有問(wèn)題了菜拓,如果出現(xiàn)錯(cuò)誤請(qǐng)檢查代碼和步驟
下面需要從ffmepg文件里面copy這幾個(gè)文件瓣窄,cmdutils.c、cmdutils.h纳鼎、cmdutils_common_opts.h俺夕、config.h、ffmpeg.c贱鄙、ffmpeg.h劝贸、ffmpeg_filter.c、ffmpeg_opt.c
然后修改CMakeLists.txt文件
cmake_minimum_required(VERSION 3.4.1)
add_library( # Sets the name of the library.
native-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
src/main/cpp/ffmpeg/cmdutils.c
src/main/cpp/ffmpeg/ffmpeg.c
src/main/cpp/ffmpeg/ffmpeg_filter.c
src/main/cpp/ffmpeg/ffmpeg_opt.c
src/main/cpp/native-lib.cpp )
add_library( ffmpeg #切記不要用libffmpeg
SHARED
IMPORTED )
set_target_properties( ffmpeg
PROPERTIES IMPORTED_LOCATION
../../../../libs/${ANDROID_ABI}/libffmpeg.so)
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 )
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")
include_directories(src/main/cpp)
include_directories(src/main/cpp/include)
target_link_libraries( # Specifies the target library.
native-lib
ffmpeg
# Links the target library to the log library
# included in the NDK.
${log-lib} )
然后點(diǎn)擊Refresh Linked C++ Projects 選項(xiàng)逗宁,然后點(diǎn)擊Rebuild Project選項(xiàng)映九,接下在會(huì)報(bào)一些錯(cuò)誤
然后從ffmpeg文件中copy這些沒(méi)有的文件到項(xiàng)目中,等沒(méi)有引入包錯(cuò)誤的時(shí)候瞎颗,有的時(shí)候還會(huì)報(bào)錯(cuò)件甥,比如
這個(gè)時(shí)候不要點(diǎn)藍(lán)色的區(qū)域這樣?xùn)|西是永遠(yuǎn)改不完的,這是時(shí)候你需要看紅線上面的錯(cuò)誤哼拔,它的錯(cuò)誤的意思是包的路徑?jīng)]有給正確
把上面的修改一下再點(diǎn)擊Rebuild Project選項(xiàng)編譯就好了引有,這個(gè)時(shí)候咱們已經(jīng)離成功不遠(yuǎn)了
第三步使用命令編輯視頻
下面我們?cè)谶@里寫(xiě)入一個(gè)方法
然后ALT+Enter就生成文件了,下面我們要修文件
把native-lib.cpp修改為native-lib.c,切記也要修改CmakeList.text里面的代碼倦逐,要不然會(huì)出問(wèn)題
下面添加代碼如下
#include
#include
JNIEXPORT jint JNICALL
Java_com_example_myapplication_MainActivity_ffmpegRun(JNIEnv *env, jobject instance,
jobjectArray cmd) {
int argc = (*env)->GetArrayLength(env, cmd);
char *argv[argc];
int i;
for (i =0; i < argc; i++) {
jstring js = (jstring) (*env)->GetObjectArrayElement(env, cmd, i);
argv[i] = (char*) (*env)->GetStringUTFChars(env, js, 0);
}
return run(argc, argv);
}
編譯一下報(bào)紅線的會(huì)消失譬正,下面我們就可以添加水印了,準(zhǔn)備一個(gè)視頻和圖片在根目錄下,下來(lái)修改MainActivity文件
package com.example.myapplication;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivityextends AppCompatActivity {
// Used to load the 'native-lib' library on application startup.
static {
System.loadLibrary("native-lib");
System.loadLibrary("ffmpeg");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Example of a call to a native method
TextView tv = (TextView) findViewById(R.id.sample_text);
tv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String base = Environment.getExternalStorageDirectory().getPath();
Log.e("PATH", base);
String[] commands =new String[9];
commands[0] ="ffmpeg";
//輸入
commands[1] ="-i";
commands[2] = base +"/input.mp4";
//水印
commands[3] ="-i";
commands[4] = base +"/ic_launcher.png";//此處的圖片地址換成帶透明通道的視頻就可以合成動(dòng)態(tài)視頻遮罩导帝。
commands[5] ="-filter_complex";
commands[6] ="[1:v]scale=300:300[s];[0:v][s]overlay=50:10";
//覆蓋輸出
commands[7] ="-y";//直接覆蓋輸出文件
//輸出文件
commands[8] = base +"/merge.mp4";
int result = ffmpegRun(commands);
if (result==0){
Toast.makeText(MainActivity.this, "命令執(zhí)行完成", Toast.LENGTH_SHORT).show();
}
}
});
}
public native int ffmpegRun(String[] cmd);
}
運(yùn)行的時(shí)候會(huì)卡主守谓,過(guò)一會(huì)就好了,因?yàn)樵谥骶€程操作的您单,這個(gè)可以由大家自由修改
切記要加這兩個(gè)權(quán)限斋荞,6.0以上把動(dòng)態(tài)權(quán)限給上
然后就成功添加水印
這個(gè)是項(xiàng)目地址大家可以作為參考
git :https://github.com/GuoLiangGod/MyFFmpeg
第一次寫(xiě)文章因?yàn)檫@個(gè)地方小坑有的多,所以才寫(xiě)這篇文件虐秦,希望對(duì)大家又幫助平酿,如果遇到問(wèn)題可以留言