12、ffmpeg筆記-使用Android Studio編寫第一個ffmpeg程序



所需材料
1、android studio 2.3
2、android-ndk-r13
3、ffmpeg編譯結果(include,libs)

    本文實例中需要使用到上次編譯的ffmpeg頭文件和靜態庫,如果沒有的話,請參看上一篇文章。
    本文使用Android Studio2.3 來開發,主要是考慮到Android Studio對NDK開發已經支持得很好了。
    Android Sutdio 既可以支持ndk-build構建,又支持新的CMake構建,而且代碼提示、單步調試等功能也大大提高了開發效率。

1、創建一個NDK工程


    打開Android Studio,新建一個工程,勾選“Include C++support”,使工程支持C++開發。如下圖:

    下一步,
 
    下一步,
 
    下一步,
 
    C++編譯選項採用默認的就可以了,以後可以在“build.gradle裏面進行更改。
 
     完成工程的創建。

2、安裝CMake


    新建工程後,出現如下錯誤,原因是:新版本的Android Studio默認使用CMake進行構建,與以往使用mk和ndk-build不一樣,需要下載CMake工具才行。

    
    點擊上面的鏈接“Install CMake and sync project”,自動下載所需的組件。
    
    完成後,點擊“Finish”即可。

3、配置NDK

    
    
    
    NDK沒配置好的話,會提示上面的錯誤。
    使用CMake構建C++程序的話,需要使用NDK>=12r,如果沒有的話,請自行百度搜索下載。

    打開工程中的“local.properties”文件,追加一行代碼“ndk.dir=NDK的目錄”,如下所示:
 
     sync一下,即可解決NDK編譯環境的問題。

4、導入ffmpeg編譯結果


   將前面編譯的ffmpeg結果拷貝到工程目錄中,路徑“app/src/main/cpp/ffmpeg”,結構如下圖所示:
    
 
     其中“native-lib.cpp”是這個IDE自動生成的源文件,CMakeLists.txt”是這個IED自動生成的構建腳本文件。

5、編寫構建腳本

    由於我們採用的是CMake構建,對應需要編寫的構建腳本是“CMakeList.txt”,位於"<project>/app/"目錄下。(Android Studio也支持使用原來的*.mk構建)
    上面帶有中文註釋的語句是需要新增的,主要包括:
  • 指定ffmpeg頭文件的搜索路徑;
  • 將ffmpeg的靜態庫添加到構建中。
    比較坑的一點時,一定要使用準確的依賴順序才行,否則會報錯。這個依賴關係可以在“ffmpeg/lib/pkgconfig”中找到。

6、編寫代碼


    任何事情都需要從最簡單的開始,這裏我們就嘗試調用ffmpeg的"avcodec_configuration()"方法來構建時的信息。
    打開native-lib.cpp”文件,修改爲:
1
#include <jni.h>
2
#include "libavcodec/avcodec.h"
3
extern "C"
4
JNIEXPORT jstring JNICALL
5
Java_cn_bassy_ffmpeg01_MainActivity_stringFromJNI(JNIEnv* env, jobject /* this */) {
6
    return env->NewStringUTF(avcodec_configuration());
7
}
    
Android Studio 有代碼提示功能,鼠標放在“”函數上面,可以看到相關注釋。

    
     
如果沒有顯示,請進入Settings配置,如下圖所示。
    
     

7、編譯程序


    編譯程序很簡單,Android Studio已經集成了NDK開發,只需要點擊“Run App”就可以了。
    
    當然,肯定還會有很多錯誤的,所以下面給出了常見錯誤及解決方法。 

8、錯誤問題及解決方法


    注意,編譯ffmpeg時所指定的Android Platform版本,與使用ffmpeg時指定的minSdkVersion有很大的關係,大部分錯誤都是因爲minSdkVersion大於編譯ffmpeg時指定的Android Platform版本所導致的!!

    1、ffmpeg函數不能被識別
    編譯是出現" undefined reference to 'avcodec_register_all()"和“Error:(15) undefined reference to 'avcodec_configuration()”,錯誤如下:
    這是因爲ffmpeg是一個純C語言編寫的庫,使用C++調用C代碼時候,需要使用“extern "C"”包圍頭文件“avcodec.h”和相關代碼,如下:
1
#include <jni.h>
2
#include <string>
3
4
#ifdef __cplusplus
5
extern "C" {
6
#endif
7
8
#include "libavcodec/avcodec.h"
9
10
11
JNIEXPORT jstring JNICALL
12
Java_cn_bassy_ffmpeg01_MainActivity_stringFromJNI(JNIEnv* env, jobject /* this */) {
13
    return env->NewStringUTF(avcodec_configuration());
14
}
15
16
#ifdef __cplusplus
17
};
18
#endif

    其它類似的錯誤,都應該將ffmpeg的頭文件使用extern "C"”包圍。

   2、“error:undefined reference to 'av_log'”錯誤:
    出現如下錯誤:
    這是因爲依賴順序不對,正確的依賴順序是(具體請看ffmpeg/lib/pkgconfig目錄內容):
1
target_link_libraries( # Specifies the target library.
2
                       native-lib
3
                       #增加ffmpeg庫,注意順序(具體看lib/pkgconfig的依賴關係)
4
                       ${CMAKE_SOURCE_DIR}/src/main/cpp/ffmpeg/lib/libavfilter.a
5
                       ${CMAKE_SOURCE_DIR}/src/main/cpp/ffmpeg/lib/libavformat.a
6
                       ${CMAKE_SOURCE_DIR}/src/main/cpp/ffmpeg/lib/libavcodec.a
7
                       ${CMAKE_SOURCE_DIR}/src/main/cpp/ffmpeg/lib/libswresample.a
8
                       ${CMAKE_SOURCE_DIR}/src/main/cpp/ffmpeg/lib/libswscale.a
9
                       ${CMAKE_SOURCE_DIR}/src/main/cpp/ffmpeg/lib/libavutil.a
10
                       #增加ffmpeg所需要的依賴庫
11
                       -lm -lz 
12
                       # Links the target library to the log library
13
                       # included in the NDK.
14
                       ${log-lib}
15
                       )

    3、posix_memalign錯誤:
    出現“undefined reference to 'posix_memalign'”錯誤。
    這是由於Android原來是不支持posix的,直到android-16才提供posix支持,所以,需要通過APP_PLATFORM指定版本爲“android-16”及以上。
    直接修改gradle文件,指定“minSdkVersion 16”,如:
    如果使用ndk-build命令的話,需要修改Application.mk文件,通過APP_PLATFORM指定Android版本,如下:
1
APP_STL := gnustl_static
2
APP_PLATFORM := android-17
3
APP_ABI := armeabi
    
    4、出現”UINT64_C“等錯誤
    出現以下錯誤:
    解決方法,打開“ffmpeg\include\libavutil\common.h”追加以下內容:
1
#ifdef __cplusplus
2
#define __STDC_CONSTANT_MACROS
3
#ifdef _STDINT_H
4
#undef _STDINT_H
5
#endif
6
# include "stdint.h"
7
#endif
8
9
10
#ifndef INT64_C
11
#define INT64_C(c) (c ## LL)
12
#define UINT64_C(c) (c ## ULL)
13
#endif

9、運行效果

    
    運行成功之後,會看到下面的結果。
    
 
    恭喜,你的第一個ffmpeg程序已經成功跳起來!~~



    
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章