Android Studio下編譯FFmpeg so文件

不知道以前誰說過,圖片太單調(diào)文字太枯燥,小視頻剛剛好。現(xiàn)在各種自拍APP,直播APP都火的一塌糊涂,一年時間過大半,我都不記得上次寫文章是什么時候了,廢話不多說,今天這里就是分享給一下我自己學(xué)習(xí)用FFmepg來做小視頻的過程,內(nèi)容估計有點多,準(zhǔn)備分兩篇來完成,炎炎夏日就別嗑瓜子了,帶上小板凳和西瓜跟著來。

目標(biāo)功能:
1.編譯出ffmpeg的so文件
2.可通過傳遞命令的方式調(diào)用ffmpeg功能。

1.新建一個項目FFmpegVideo

截一張圖表示一下


QQ20170801-101508@2x.png
2.下載ndk以及ffmepg

我這里下載的ndk版本是android-ndk_r14b
ffmepg版本是ffmpeg-3.3.2

也許當(dāng)你看到這邊篇文的時候最新版本已經(jīng)比這個更高了,如果后面編譯出現(xiàn)問題,很有可能跟版本有關(guān)系,所以如果你編譯其他版本出現(xiàn)問題,需要你自己看懂腳本靈活變動。
QQ20170801-102731@2x.png

ndk的環(huán)境變量的配置我這里就不多說了,不同的系統(tǒng)配置不一樣,自行百度。

3.NDK配置好了嗎?配置好了開始準(zhǔn)備編譯ffmpeg相關(guān)腳本文件。

打開ffmpeg-3.3.2文件夾并且創(chuàng)建一個文件夾(ffmpegtemp)和一個文件(build_android_armeabi_armeabi-v7a.sh)
(2)這里最主要的就是build_android_armeabi_armeabi-v7a.sh這個文件的內(nèi)容,非常非常非常重要,把以下內(nèi)容復(fù)制到你的這個文件中

#!/bin/bash
export TMPDIR=/Users/tangyx/Documents/ffmpeg-3.3.2/ffmpegtemp #這句很重要,不然會報錯 unable to create temporary file in
# NDK的路徑,根據(jù)自己的安裝位置進行設(shè)置
NDK=/Users/tangyx/Documents/android-ndk_r14b
# 編譯針對的平臺,可以根據(jù)自己的需求進行設(shè)置
# 這里選擇最低支持android-14, arm架構(gòu),生成的so庫是放在
# libs/armeabi文件夾下的,若針對x86架構(gòu),要選擇arch-x86
PLATFORM=$NDK/platforms/android-14/arch-arm
# 工具鏈的路徑,根據(jù)編譯的平臺不同而不同
# arm-linux-androideabi-4.9與上面設(shè)置的PLATFORM對應(yīng),4.9為工具的版本號,
# 根據(jù)自己安裝的NDK版本來確定,一般使用最新的版本
TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64
function build_one
{
./configure \
    --prefix=$PREFIX \
    --target-os=linux \
    --cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
    --arch=arm \
    --sysroot=$PLATFORM \
    --extra-cflags="-I$PLATFORM/usr/include" \
    --cc=$TOOLCHAIN/bin/arm-linux-androideabi-gcc \
    --nm=$TOOLCHAIN/bin/arm-linux-androideabi-nm \
    --disable-shared \
    --enable-runtime-cpudetect \
    --enable-gpl \
    --enable-small \
    --enable-cross-compile \
    --disable-debug \
    --enable-static \
    --disable-doc \
    --disable-asm \
    --disable-ffmpeg \
    --disable-ffplay \
    --disable-ffprobe \
    --disable-ffserver \
    --disable-postproc \
    --disable-avdevice \
    --disable-symver \
    --disable-stripping \
$ADDITIONAL_CONFIGURE_FLAG
sed -i '' 's/HAVE_LRINT 0/HAVE_LRINT 1/g' config.h
sed -i '' 's/HAVE_LRINTF 0/HAVE_LRINTF 1/g' config.h
sed -i '' 's/HAVE_ROUND 0/HAVE_ROUND 1/g' config.h
sed -i '' 's/HAVE_ROUNDF 0/HAVE_ROUNDF 1/g' config.h
sed -i '' 's/HAVE_TRUNC 0/HAVE_TRUNC 1/g' config.h
sed -i '' 's/HAVE_TRUNCF 0/HAVE_TRUNCF 1/g' config.h
sed -i '' 's/HAVE_CBRT 0/HAVE_CBRT 1/g' config.h
sed -i '' 's/HAVE_RINT 0/HAVE_RINT 1/g' config.h
make clean
make -j4
make install
$TOOLCHAIN/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 \
    -lc -lm -lz -ldl -llog --dynamic-linker=/system/bin/linker \
    $TOOLCHAIN/lib/gcc/arm-linux-androideabi/4.9.x/libgcc.a
}
# arm v7vfp
CPU=armv7-a
OPTIMIZE_CFLAGS="-mfloat-abi=softfp -mfpu=vfp -marm -march=$CPU "
PREFIX=./android/$CPU-vfp
ADDITIONAL_CONFIGURE_FLAG=
build_one

這里提醒吃瓜的朋友還是耐心看一下這個腳本的內(nèi)容,因為我這次文章只會編譯arm的so,其他框架(x86,arm64等)下的腳本我暫時不會提供,所以大概解釋一下這個腳本的重要地方

318C2573-541B-4ECC-AF9F-1E782D0B5292.png
圖中紅色地方就是每次需要編譯不同框架下修改的地方。

這些對應(yīng)的文件路徑主要是你的ndk文件路徑,其他不需要你去改動。

下半部分:

651D6884-ADEB-464D-8D79-C52FFB6A1305.png

特別是第一個紅色框中的lib這里默認是lib,我在編譯x86_64框架的so時候忽略了這里,然后無論怎么樣也編譯不過,真的差點哭到放棄。

這里的lib的同級文件夾還有l(wèi)ib64,所以當(dāng)你編譯64位的框架(x86_64)的時候一定要修改引用到lib64的文件夾,否則會出現(xiàn)報錯,出現(xiàn)一大堆找不到內(nèi)容的錯誤。
CC38A389-0DDD-4311-9359-377619C1AF87.png
4.好了腳本準(zhǔn)備就緒了,我這里的腳本是編譯出支持arm以及arm-v7a的so。

打開你的終端cd切換到你的ffmpeg-3.3.2下

QQ20170801-111521@2x.png

切換完成后,就直接執(zhí)行寫好的腳本。
先這樣

chmod +x build_android_armeabi_armeabi-v7a.sh

然后這樣

./build_android_armeabi_armeabi-v7a.sh

最后這樣感覺卡住了一樣(耐心等待)

QQ20170801-112054@2x.png

差不多你接杯水的時間回來,然后就這樣了

ffmpeg_sh.gif

這里編譯的速度根據(jù)各自的電腦性能,我這里把水接好,在泡上咖啡時間剛剛差不多。

5等待編譯完成后,打開ffmpeg-3.3.2文件夾發(fā)現(xiàn)多了一個文件夾(android)和文件(config.h)

文件就不管了,但是也不能刪除,打開android文件夾不出意外是這樣的

F48E0A72-B7CF-495A-BB1A-D577A1022997.png

看見紅色部分沒有?看見沒有?這就是最重要的成果,下面就需要把他放在我們對應(yīng)的項目中去編譯出可用的so文件,這個文件只是用來動態(tài)生成框架的so包,還不能直接在android中調(diào)用。

6回到Android Studio的新家項目FFmpegVideo中,在main下面新建文件夾jni

在這里需要說明一下,jni下編譯so文件對應(yīng)我們java類的native方法提供調(diào)用,一般情況都是需要編寫c++和java對應(yīng)的方法來進行調(diào)用,在這里如果按照方法的調(diào)用的模式,對于新手或者剛接觸的人來說簡直就是噩夢,所以這里有大神提供修改了ffmepg的c++源文件,直接可以通過命令的方式來調(diào)用ffmpeg的功能,真是前人栽樹,后人乘涼,極大省去了很多麻煩,這樣只需要了解學(xué)習(xí)ffmpeg的命令你就可以完成很多事情。

關(guān)于修改源碼的內(nèi)容和地方請通過這里查看(如果你感興趣可以了解一下,反正我對c是個半吊子水平。)

接下來繼續(xù)我們的搭建開發(fā)流程

  1. 新建一個包名和一個用來調(diào)用ffmpeg的類
5A160EDE-DFEE-4004-947D-793337000983.png

2.獲取c語言接口的函數(shù)聲明
點擊Android Studio最下方的Terminal窗口
切換到項目下的java目錄下

然后執(zhí)行以下命令

javah com.ihubin.ffmpegstudy.FFmpegKit
D6F00C24-ED7A-4E89-9336-E8949F21B140.png

執(zhí)行完成以后,刷新一下,src/main/java下會生成一個文件(根據(jù)項目不同的包名生成的文件名字不一樣)com_tangyx_video_ffmpeg_FFmpegRun.h</b>

把這個文件移動到j(luò)ni文件下

還記得上面ffmpeg-3.3.2下android文件夾armv7-a-vfp中生成的那個libffmpeg.so文件么,拷貝它到項目的jni目錄下

復(fù)制FFmpeg源碼文件 ffmpeg.h, ffmpeg.c, ffmpeg_opt.c, ffmpeg_filter.c,cmdutils.c, cmdutils.h, cmdutils_common_opts.h 到j(luò)ni目錄下。
我這里的復(fù)制的ffmpeg.c和ffmpeg.h兩個文件已經(jīng)根據(jù)上面大神指導(dǎo)的方式修改好了,可以直接使用,最后的源碼我也會上傳,各位吃瓜群眾可以直接使用。

在jni目錄下手動創(chuàng)建三個文件
Android.mk
Application.mk
com_tangyx_video_ffmpeg_FFmpegRun.c(根據(jù)項目不同的包名生成的文件名字不一樣,對應(yīng)上面的.h文件)

**Android.mk **的內(nèi)容:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := ffmpeg
LOCAL_SRC_FILES := libffmpeg.so
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := ffmpeginvoke
LOCAL_SRC_FILES := com_tangyx_video_ffmpeg_FFmpegRun.c ffmpeg.c ffmpeg_opt.c cmdutils.c ffmpeg_filter.c
LOCAL_C_INCLUDES := /Users/tangyx/Documents/ffmpeg-3.3.2
LOCAL_LDLIBS := -llog -lz -ldl
LOCAL_SHARED_LIBRARIES := ffmpeg

include $(BUILD_SHARED_LIBRARY)

LOCAL_C_INCLUDES的路徑記得修改為你當(dāng)前ffmepg文件夾的路徑。
LOCAL_SRC_FILES第一個c文件的引用記得改為你當(dāng)前jni下生成的c文件。

** Application.mk **的內(nèi)容:

APP_ABI := armeabi armeabi-v7a
APP_BUILD_SCRIPT := Android.mk
APP_PLATFORM := android-15

這里能夠支持生成arm可用的so文件(不支持arm64)

com_tangyx_video_ffmpeg_FFmpegRun.c的內(nèi)容:

#include "com_tangyx_video_ffmpeg_FFmpegRun.h"
#include "ffmpeg.h"
#include <string.h>
/*
 * Class:     com_example_ffmpeg_FFmpegKit
 * Method:    run
 * Signature: (Ljava/lang/String;)I
 */
JNIEXPORT jint JNICALL Java_com_tangyx_video_ffmpeg_FFmpegRun_run(JNIEnv *env,
        jclass obj, jobjectArray commands) {

    int argc = (*env)->GetArrayLength(env, commands);
    char *argv[argc];

    int i;
    for (i = 0; i < argc; i++) {
        jstring js = (jstring) (*env)->GetObjectArrayElement(env, commands, i);
        argv[i] = (char*) (*env)->GetStringUTFChars(env, js, 0);
    }
    return run(argc, argv);
}

第一行的include引用你當(dāng)前jni下生成的.h文件
Java_com_tangyx_video_ffmpeg_FFmpegRun_run需要改成你項目對應(yīng)的包名和方法名(聰明的你仔細看一下就知道這個規(guī)則)

上面就是jni目錄所有的文件以及需要你手動改動的地方,一個都不能少,一個都不能錯,如果出錯,根據(jù)錯誤提示進行修改。

6開始編譯(最激動人心的時刻)

還是打開Terminal窗口并且切換到j(luò)ni文件目錄下
執(zhí)行命令

ndk-build

等待編譯完成,只要沒有出現(xiàn)stop的情況,基本上沒有任何問題

9C980BA9-EDE9-4176-AFB3-0D26D2B66F4D.png

如果走到這里,那么恭喜你編譯成功,刷新main目錄,會多出2個文件夾分別是lib和obj

A793812B-7DE3-48AD-B068-E0176739DBA4.png

lib下的生成了對應(yīng)框架下需要用到的so文件,把armeabi和armeabi-v7a兩個文件夾考到j(luò)niLib或者main下面自己創(chuàng)建的libs文件夾下

我這里是自己創(chuàng)建的lib文件夾,所以在app module下build.gradle文件中新增內(nèi)容

sourceSets {
        main {
            jniLibs.srcDirs = ['libs']
            jni.srcDirs = []
        }
    }

到這里基本上我們項目中集成ffmpeg相關(guān)的工作已經(jīng)完成,其他框架的so文件大家自己嘗試編譯,有問題再說,后面主要就是android 應(yīng)用端怎么去使用ffmepg。

使用ffmpeg實現(xiàn)小視頻制作
Android通過FFmpeg實現(xiàn)多段小視頻合成

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,431評論 6 544
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,637評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,555評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,900評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 72,629評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,976評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,976評論 3 448
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 43,139評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,686評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 41,411評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,641評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,129評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,820評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,233評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,567評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,362評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 48,604評論 2 380

推薦閱讀更多精彩內(nèi)容