FFmpeg系列(二)-Android項目引入FFmpeg庫播放視頻

系列一中講述瞭如何編譯FFmpeg的源碼,如今就在Android項目中引入咱們編譯出來的庫,並實現播放一個在線視頻的功能java

新建Android工程

新建一個支持ndk的Android工程,在AS中新建工程就再也不詳述了,詳細的新建ndk工程,能夠參考AndroidStudio中使用JNI/NDK示例 須要注意的一點就是在新建導航中注意勾選Support C++這個選項,這樣新建的Android工程就會有CMakeLists等進行NDK編譯時必要的東東了。android

修改gradle配置

新建的Android工程須要對項目中的app/build.gradle作一些修改,其中主要修改的地方以下:git

android {
    ……
    defaultConfig {
        ……
        externalNativeBuild {
            // -Wno-deprecated-declarations 添加這個保證編譯出的不少文件再也不報錯
            cmake {
                cppFlags "-frtti -fexceptions -Wno-deprecated-declarations"
                cFlags "-DSTDC_HEADERS"
            }
        }
        ndk { // 聲明編譯的架構類型,指定爲armeabi-v7a便可
            abiFilters "armeabi-v7a"
        }
    }

    externalNativeBuild {
        cmake { // 配置咱們本身的CMakeLists文件
            path file('CMakeLists.txt')
        }
    }
    
    sourceSets {
        main {
            // 指定存放native代碼的目錄,這裏指定爲jni和cpp皆可
            jni.srcDirs = ['src/main/jni', 'src/main/cpp/'] 
            // 指定jni庫的存放目錄爲libs
            jniLibs.srcDirs = ['libs'] 
        }
    }
}
複製代碼

上面配置須要特別說明的一點是,在cmake配置中的cppFlags務必添加-Wno-deprecated-declarations,這樣確保咱們能使用一些過時的接口。另外在後面導入FFmpeg編譯生成的代碼到AS中會有不少標紅,添加了這個配置屬性後,各類討厭的標紅就去無蹤了😏。github

導入FFmpeg代碼和庫文件

導入以前,先在咱們工程中的app/下新建libs文件夾,而後繼續在libs下新建armeabi-v7a和include兩個文件夾 架構

此外再在src/main/中新建jni文件
接着進入咱們以前編譯好的FFmpeg文件目錄中

  1. 將include下的文件所有拷貝到剛纔新建的libs/include中
  2. 將lib下的幾個so文件所有拷貝到剛纔新建的libs/armeabi-v7a中

編寫native代碼使用FFmpeg

咱們編寫一個NDK的橋接類NDKBridge,並在其中定義咱們本身的native庫:
NDKBridge.javaapp

public class NDKBridge {
    static {
        // 自定義的native庫
        System.loadLibrary("ndk_test_jni");
    }
    ……
}
複製代碼

定義一個簡單的播放器類FFVideoPlayer,並在其中聲明一個名爲render的native方法:
FFVideoPlayer.javaide

public class FFVideoPlayer extends SurfaceView {
    ……
    public void play(final String url) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                render(url, FFVideoPlayer.this.getHolder().getSurface());
            }
        }).start();
    }
    // 播放器渲染的方法,須要在native層中實現
    public native void render(String url, Surface surface);
}
複製代碼

此時咱們尚未配置CMakeLists文件,也沒有新建任何native代碼,因此上面聲明的native方法是會標紅報錯的post

配置CMakeLists

配置CMakeLists文件,指定咱們的native代碼入口,並指定編譯成的native庫,以及引用的哪些native代碼。下面列出一些須要注意的點,詳細內容能夠到項目工程中查看gradle

# 添加庫——本身編寫的庫
# 庫名稱:ndk_test_jni
# 庫類型:SHARED,表示動態庫,後綴爲.so(若是是STATIC,則表示靜態庫,後綴爲.a)
# 庫源碼文件:src/main/jni/ndk_test_jni.cpp
add_library(ndk_test_jni
        SHARED
        src/main/jni/ndk_test_jni.cpp)

……
# 引入頭文件,不然沒法在ndk_test_jni.cpp中導入FFmpeg編譯出的源文件
include_directories(libs/include)
複製代碼

暫時先別執行syc操做,由於都沒有ndk_test_jni.cpp文件,確定會失敗!ui

編寫native代碼

根據CMakeLists中的配置,咱們須要在工程的src/main/jni中新建一個ndk_test_jni.cpp文件,而後再執行syc操做。
到上面聲明native方法的地方,此時應該仍是標紅報錯。用鼠標點擊右邊標紅的地方,使錯誤處於選中狀態,而後點擊ALT+Enter快捷鍵,此時AS會彈出建立須要的native方法,點擊確認後就會自動在咱們的ndk_test_jni.cpp中新建一個空的Java_cain_tencent_com_androidexercisedemo_ffmpeg_FFVideoPlayer_render方法,這就是咱們在java層聲明的native方法的實現。而後就能夠愉快地到ndk_test_jni.cpp中去盡情發揮,實現各個native方法了。
具體的代碼這裏就不貼出來了,具體的能夠到項目查看,當中註釋也寫得很明朗了。這裏須要注意的一點就是咱們須要將各個native方法包裹在extern "C" {}中

extern "C" {
#include <cstdio>
#include "lame/lame.h"
//封裝格式處理
#include <libavformat/avformat.h>
#include <android/native_window_jni.h>
#include <libavfilter/avfilter.h>
#include <libavcodec/avcodec.h>
//封裝格式處理
#include <libavformat/avformat.h>
//像素處理
#include <libswscale/swscale.h>
#include <unistd.h>
/** * 解碼視頻播,渲染播放 */
extern "C"
JNIEXPORT void JNICALL Java_cain_tencent_com_androidexercisedemo_ffmpeg_FFVideoPlayer_render(JNIEnv *env, jobject instance,jstring url_,jobject surface) {
    ……
}
}
複製代碼

不然在編譯時會報各類unresolved錯誤
這裏須要播放在線視頻,所以也須要記得申請聯網權限

播放效果

附錄

項目地址

參考

AndroidStudio中使用JNI/NDK示例
在Mac上編譯移植FFmpeg-4.0.3到Android平臺

相關文章
相關標籤/搜索