Android初探FFmpeg(1)--在Windows下編譯FFmpeg

之前在博客中提到視頻的裁剪和合并功能,用的是FFmpeg這塊的東西,由于是從網(wǎng)上直接拔過來的東西,雖然功能算是實現(xiàn)了,但是心里總是感覺怪怪的,畢竟沒有自己動手!自己也討厭“伸手主義”,加之最近項目不是特別緊張,就自己動手編譯了一遍,并在各種各樣異常的情況下,總算在Android studio下跑成功了!本來打算把一些知識點再挖深一點,但是最近項目可能要迭代新版本,所以怕是要小忙一陣!為了避免把之前的忘了,所以還是需要草草的記錄一下!下面開始。

準備環(huán)境:
VMware workstation 12 player
最新版下載地址:
https://my.vmware.com/cn/web/vmware/free#desktop_end_user_computing/vmware_workstation_player/12_0

Ubuntu 64(我存一份到我的云盤中了,大家可以到那下載)
下載地址:
http://pan.baidu.com/s/1bp8JG2j

安裝完后打開界面如下:

這里寫圖片描述

OK,到這,就可以開始準備工作了!

由于之前家里的電腦也沒下載NDK和FFmpeg,所以,我就打算在這個工作區(qū)間直接下載了(說到底是不會VMware的共享文件(大家可以自行谷歌或者百度,有解))

最新版的NDK下載地址:
https://dl.google.com/android/repository/android-ndk-r15b-linux-x86_64.zip

最新版的FFmpeg下載地址:
http://ffmpeg.org/releases/ffmpeg-3.3.2.tar.bz2

下載完之后,就可以開始編譯了!
這里,我把兩個壓縮包全都放在home路徑下了!

這里寫圖片描述

點擊左鍵Extract File,進行解壓文件夾(或者用命令行進行解壓,都OK)

Ctrl+Alt+F2可打開命令行
Ctrl+Alt+F7可關(guān)閉命令行

接著打開FFmpeg的文件夾,打開configure文件,修改該屬性為:

SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(FULLNAME)-$(LIBMAJOR)$(SLIBSUF)'
LIB_INSTALL_EXTRA_CMD='$$(RANLIB)"$(LIBDIR)/$(LIBNAME)"'
SLIB_INSTALL_NAME='$(SLIBNAME_WITH_MAJOR)'
SLIB_INSTALL_LINKS='$(SLIBNAME)'

在接著創(chuàng)建文件build_android.sh文件,內(nèi)容為:

#!/bin/bash
cd ffmpeg
export TMPDIR=/home/tianchuangxin/ffmpeg-3.3.2
NDK=/home/tianchuangxin/android-ndk-r15b
SYSROOT=$NDK/platforms/android-16/arch-arm/
TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64
CPU=arm
PREFIX=/home/tianchuangxin/ffmpeg-3.3.2/$CPU
ADDI_CFLAGS="-marm"
function build_one
{
    ./configure \
        --prefix=$PREFIX \
        --enable-shared \
        --disable-static \
        --disable-doc \
        --disable-ffmpeg \
        --disable-ffplay \
        --disable-ffprobe \
        --disable-ffserver \
        --disable-doc \
        --disable-symver \
        --enable-small \
        --cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
        --target-os=linux \
        --arch=arm \
        --enable-cross-compile \
        --sysroot=$SYSROOT \
        --extra-cflags="-Os -fpic $ADDI_CFLAGS" \
        --extra-ldflags="$ADDI_LDFLAGS" \
        $ADDITIONAL_CONFIGURE_FLAG
    make clean
    make
    make install
}
build_one
cd ../

創(chuàng)建的這個文件需要注意的是,你自己需要修改一些東西:


這里寫圖片描述

圈出的這三處需要改成你自己的路徑。
小提示:你最好先打開自己的命令行cd一下,看看能不能到這些文件路徑下面,不然會一直報文件找不到的警告

接著給build_android.sh添加執(zhí)行權(quán)限命令行如下:

$chmod+x build_android.sh 

接著執(zhí)行.sh文件:

$./build_android.sh 

ok ,到這里,如果的你的配置都沒有問題的話,已經(jīng)開始生成.so文件了!

當你再打開ffmpeg的文件夾的時候多了一個文件夾 arm!

接著把arm文件夾copy出來之后開始在Android studio中測試一下咯!

在創(chuàng)建新的Android項目的的時候在,首頁面需勾選:

這里寫圖片描述

接著一路next知道創(chuàng)建完成新的項目!

創(chuàng)建好新的項目,將之前的生成的arm包中的東西復制到工程下的libs文件夾下:


這里寫圖片描述

注意:現(xiàn)在是arm架構(gòu)類型的CPU

接著開始配置native_lib.cpp文件,它在main目錄下

這里寫圖片描述

#include <jni.h>
#include <string>

extern "C"
{

#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavfilter/avfilter.h>

JNIEXPORT jstring JNICALL
Java_com_example_ffmpegtest_MainActivity_stringFromJNI(
        JNIEnv* env,
        jobject /* this */) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());

}



JNIEXPORT jstring JNICALL
    Java_com_example_ffmpegtest_MainActivity_urlprotocolinfo(
            JNIEnv *env, jobject) {
        char info[40000] = {0};
        av_register_all();

        struct URLProtocol *pup = NULL;

        struct URLProtocol **p_temp = &pup;
        avio_enum_protocols((void **) p_temp, 0);

        while ((*p_temp) != NULL) {
            sprintf(info, "%sInput: %s\n", info, avio_enum_protocols((void **) p_temp, 0));
        }
        pup = NULL;
        avio_enum_protocols((void **) p_temp, 1);
        while ((*p_temp) != NULL) {
            sprintf(info, "%sInput: %s\n", info, avio_enum_protocols((void **) p_temp, 1));
        }
        return env->NewStringUTF(info);
    }

JNIEXPORT jstring JNICALL
    Java_com_example_ffmpegtest_MainActivity_avformatinfo(
            JNIEnv *env, jobject) {
        char info[40000] = {0};

        av_register_all();

        AVInputFormat *if_temp = av_iformat_next(NULL);
        AVOutputFormat *of_temp = av_oformat_next(NULL);
        while (if_temp != NULL) {
            sprintf(info, "%sInput: %s\n", info, if_temp->name);
            if_temp = if_temp->next;
        }
        while (of_temp != NULL) {
            sprintf(info, "%sOutput: %s\n", info, of_temp->name);
            of_temp = of_temp->next;
        }
        return env->NewStringUTF(info);
    }

JNIEXPORT jstring JNICALL
    Java_com_example_ffmpegtest_MainActivity_avcodecinfo(
            JNIEnv *env, jobject) {
        char info[40000] = {0};

        av_register_all();

        AVCodec *c_temp = av_codec_next(NULL);

        while (c_temp != NULL) {
            if (c_temp->decode != NULL) {
                sprintf(info, "%sdecode:", info);
            } else {
                sprintf(info, "%sencode:", info);
            }
            switch (c_temp->type) {
                case AVMEDIA_TYPE_VIDEO:
                    sprintf(info, "%s(video):", info);
                    break;
                case AVMEDIA_TYPE_AUDIO:
                    sprintf(info, "%s(audio):", info);
                    break;
                default:
                    sprintf(info, "%s(other):", info);
                    break;
            }
            sprintf(info, "%s[%10s]\n", info, c_temp->name);
            c_temp = c_temp->next;
        }

        return env->NewStringUTF(info);
    }

JNIEXPORT jstring JNICALL
    Java_com_example_ffmpegtest_MainActivity_avfilterinfo(
            JNIEnv *env, jobject) {
        char info[40000] = {0};
        avfilter_register_all();

        AVFilter *f_temp = (AVFilter *)avfilter_next(NULL);
        while(f_temp != NULL) {
            sprintf(info, "%s%s\n", info, f_temp->name);
            f_temp = f_temp->next;
        }
        return env->NewStringUTF(info);
    }
}

注意的是native的寫法,你的函數(shù)名稱可能跟我的不太一樣哦!

接著配置CMakeLists.txt文件:

# Sets the minimum version of CMake required to build the native
# library. You should either keep the default value or only pass a
# value of 3.4.0 or lower.

cmake_minimum_required(VERSION 3.4.1)

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(distribution_DIR ${CMAKE_SOURCE_DIR}/../../../../libs)

add_library( avutil-55
            SHARED
            IMPORTED )
set_target_properties( avutil-55
             PROPERTIES IMPORTED_LOCATION
             ../../../../libs/armeabi-v7a/libavutil-55.so )

add_library( swresample-2
             SHARED
             IMPORTED )
set_target_properties( swresample-2
             PROPERTIES IMPORTED_LOCATION
             ../../../../libs/armeabi-v7a/libswresample-2.so )
add_library( avcodec-57
             SHARED
             IMPORTED )
set_target_properties( avcodec-57
             PROPERTIES IMPORTED_LOCATION
             ../../../../libs/armeabi-v7a/libavcodec-57.so )
add_library( avfilter-6
             SHARED
             IMPORTED)
set_target_properties( avfilter-6
             PROPERTIES IMPORTED_LOCATION
             ../../../../libs/armeabi-v7a/libavfilter-6.so )
add_library( swscale-4
            SHARED
             IMPORTED)
set_target_properties( swscale-4
            PROPERTIES IMPORTED_LOCATION
             ../../../../libs/armeabi-v7a/libswscale-4.so )
add_library( avdevice-57
            SHARED
            IMPORTED)
set_target_properties( avdevice-57
            PROPERTIES IMPORTED_LOCATION
            ../../../../libs/armeabi-v7a/libavdevice-57.so )
add_library( avformat-57
            SHARED
            IMPORTED)
set_target_properties( avformat-57
            PROPERTIES IMPORTED_LOCATION
             ../../../../libs/armeabi-v7a/libavformat-57.so )

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")

add_library( native-lib
            SHARED
             src/main/cpp/native-lib.cpp )

include_directories(libs/include)

             #target_include_directories(native-lib PRIVATE libs/include)

target_link_libraries( native-lib swresample-2 avcodec-57 avfilter-6 swscale-4 avdevice-57 avformat-57
             ${log-lib} )

接著是build.gradle的文件配置:

這里寫圖片描述
這里寫圖片描述

這兩個千萬別忘了,不然就跑不起來了!

哈哈,到這基本就完了!

這是跑出來的結(jié)果圖:

這里寫圖片描述

文章參考:
http://blog.csdn.net/gobitan/article/details/22750719
http://blog.csdn.net/eastmoon502136/article/details/52806640
感謝作者的無私技術(shù)分享!

如有問題請指正,共同進步,謝謝!

每天進步一點點,時間會讓你成為巨人!加油!

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

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