FFmpeg:初步編譯使用[Android]


1.安裝NDK:http://dl.google.com/android/ndk/android-ndk-r9-linux-x86.tar.bz2

 sudo gedit ~/.bashrc
 末尾添加:
 #add NDK
 PATH=$PATH:/home/sheldon/Android/android-ndk-r9/

 source ~/.bashrc  : 立即生效配置,可以使用"ndk-build"指令

2.FFmpeg官方網站 http://www.ffmpeg.org/  下載源代碼.

3.修改configure,將生成lib的版本號置於.so之前,以防Android無法加載:
#SLIBNAME_WITH_MAJOR='$(SLIBNAME).$(LIBMAJOR)'
#LIB_INSTALL_EXTRA_CMD='$$(RANLIB) "$(LIBDIR)/$(LIBNAME)"'
#SLIB_INSTALL_NAME='$(SLIBNAME_WITH_VERSION)'
#SLIB_INSTALL_LINKS='$(SLIBNAME_WITH_MAJOR) $(SLIBNAME)'
SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(FULLNAME)-$(LIBMAJOR)$(SLIBSUF)'
LIB_INSTALL_EXTRA_CMD='$$(RANLIB)"$(LIBDIR)/$(LIBNAME)"'
SLIB_INSTALL_NAME='$(SLIBNAME_WITH_MAJOR)'
SLIB_INSTALL_LINKS='$(SLIBNAME)'
VERSION_SCRIPT_POSTPROCESS_CMD="cat"

4.編寫build_android.sh腳本文件,如果從網上直接copy過去可能會是dos格式,使用dos2unix build_android.sh 轉換一下,刪掉多余空格:
#!/bin/bash   : 以下三個變量根據自己系統環境配置
NDK=/home/sheldon/Android/android-ndk-r9/
SYSROOT=$NDK/platforms/android-9/arch-arm/
TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86

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
}  

CPU=arm
PREFIX=$(pwd)/android/$CPU
ADDI_CFLAGS="-marm"
build_one

5.增加執行權限,執行:
$chmod a+x build_android.sh  
$./build_android.sh  

生成:[頭文件]android/arm/include/*.h 和  [動態庫文件]android/arm/lib/*.so

6.創建Android工程使用lib:
(1)創建一個新的Android工程FFmpeg4android。
(2)在工程目錄下創建jni文件夾,與java目錄同級。
(3)在jni下創建prebuilt/armeabi目錄,然后:
   將上面FFmpeg source code編譯生成的so文件(帶版號的真實庫而不是鏈接文件)放入到該目錄下的armeabi目錄;
   將android/arm/include/下的所有頭文件夾拷貝到該jni目錄下.
(4)創建包含native方法的類(java層直接調用的接口),先在src/main/java/下創建FFmpegNative.java類文件。主要包括加載so庫文件和一個native測試方法兩部分,其內容如下:

package com.li.sheldon.ffmpeg4android;

/**
* Created by sheldon on 17-1-4.
*/
public class FFmpegNative {
static{
 System.loadLibrary("avcodec-57");
 System.loadLibrary("avdevice-57");
  System.loadLibrary("avfilter-6");
 System.loadLibrary("avformat-57");
 System.loadLibrary("avutil-55");
System.loadLibrary("swresample-2");
System.loadLibrary("swscale-4");
System.loadLibrary("ffmpegjni");
}
private native int ffmpeg_h264(int codecID);

public int test_h246(int id){
return ffmpeg_h264(id);
}
}

(5)用javah創建.頭文件:

  -classpath <路徑> 用於裝入類的路徑
  -d <目錄> 輸出目錄
  -jni 生成 JNI樣式的頭文件(默認)

     javah -classpath /FFmpeg4android/app/src/main/java/ -d ./ -jni com.li.sheldon.ffmpeg4android.FFmpegNative
     -classpath 后面的路徑是指包”com.li.sheldon.ffmpeg4android”所在的根路徑
    會在當前目錄產生com_li_sheldon_ffmpeg4android_FFmpegNative.h的C頭文件;

(6)根據頭文件名,建立相同名字才C源文件com_li_sheldon_ffmpeg4android_FFmpegNative.c
    在這個源文件中實現頭文件中定義的方法,核心部分代碼如下:

#include "com_li_sheldon_ffmpeg4android_FFmpegNative.h"
JNIEXPORT jint JNICALL Java_com_li_sheldon_ffmpeg4android_FFmpegNative_ffmpeg_1h264
(JNIEnv* env, jobject thiz, jint codecID)
{
AVCodec* codec = NULL;
av_register_all();//該函數在所有基於ffmpeg的應用程序中幾乎都是第一個被調用的。只有調用了該函數,才能使用復用器,編碼器等
 codec = avcodec_find_decoder(codecID);//通過code ID查找一個已經注冊的音視頻編碼器。H264codecID28,所以我們java那邊傳28下來如果檢測到H264注冊過了這邊codec就不為空,返回0
  if(codec != NULL){
 return 0;
}else{
return -1;
}
}
 
        


(7)編寫Android.mk,內容如下:
#APP_ABI := armeabi armeabi-v7a x86
ifeq ($(APP_ABI), x86)
LIB_NAME_PLUS := x86
else
LIB_NAME_PLUS := armeabi
endif

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE:= avcodec-prebuilt-$(LIB_NAME_PLUS)
LOCAL_SRC_FILES:= prebuilt/$(LIB_NAME_PLUS)/libavcodec-57.so
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE:= avdevice-prebuilt-$(LIB_NAME_PLUS)
LOCAL_SRC_FILES:= prebuilt/$(LIB_NAME_PLUS)/libavdevice-57.so
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE:= avfilter-prebuilt-$(LIB_NAME_PLUS)
LOCAL_SRC_FILES:= prebuilt/$(LIB_NAME_PLUS)/libavfilter-6.so
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE:= avformat-prebuilt-$(LIB_NAME_PLUS)
LOCAL_SRC_FILES:= prebuilt/$(LIB_NAME_PLUS)/libavformat-57.so
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE :=  avutil-prebuilt-$(LIB_NAME_PLUS)
LOCAL_SRC_FILES := prebuilt/$(LIB_NAME_PLUS)/libavutil-55.so
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := swresample-prebuilt-$(LIB_NAME_PLUS)
LOCAL_SRC_FILES := prebuilt/$(LIB_NAME_PLUS)/libswresample-2.so
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := swscale-prebuilt-$(LIB_NAME_PLUS)
LOCAL_SRC_FILES := prebuilt/$(LIB_NAME_PLUS)/libswscale-4.so
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
ifeq ($(APP_ABI), x86)
TARGET_ARCH:=x86
TARGET_ARCH_ABI:=x86
else
LOCAL_ARM_MODE := arm
endif

LOCAL_MODULE := libffmpegjni
LOCAL_SRC_FILES := com_li_sheldon_ffmpeg4android_FFmpegNative.c
LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog -lz
LOCAL_SHARED_LIBRARIES:= avcodec-prebuilt-$(LIB_NAME_PLUS) \
                         avdevice-prebuilt-$(LIB_NAME_PLUS) \
                         avfilter-prebuilt-$(LIB_NAME_PLUS) \
                         avformat-prebuilt-$(LIB_NAME_PLUS) \
                         avutil-prebuilt-$(LIB_NAME_PLUS) \
                         swresample-prebuilt-$(LIB_NAME_PLUS) \
                         swscale-prebuilt-$(LIB_NAME_PLUS)
LOCAL_C_INCLUDES += -L$(SYSROOT)/usr/include
LOCAL_C_INCLUDES += $(LOCAL_PATH)/include

ifeq ($(APP_ABI), x86)
LOCAL_CFLAGS := -DUSE_X86_CONFIG
else
LOCAL_CFLAGS := -DUSE_ARM_CONFIG
endif
include $(BUILD_SHARED_LIBRARY)


(8) 編寫Application.mk, 指定編譯平台[可省略]
    APP_PROJECT_PATH := $(call my-dir)/..
    APP_MODULES := libffmpegjni
-------------------
    編譯so文件:
    打開cmd命令行,進入FFmpeg4Android\jni目錄下,執行如下命令:
    ndk-build  
    截止本步驟完成,將在FFmpeg4android/app/src/main/libs/armeabi/下另外生成了libffmpegjni.so文件, cp到FFmpeg4android/app/libs/armeabi/下由java類加載。
    ps:共享庫將被拷貝到 $PROJECT/obj/local 和 $PROJECT/libs/<abi> (stripped)  主要是用在將已經編譯好的第三方庫.

-------------------------如果ndk編譯報錯,加下面一段

build.greadle(app):

sourceSets.main{
  jniLibs.srcDir 'libs'
  jni.srcDirs = [] //disable automatic ndk-build call
}


(9)修改layout/main.xml,給TextView增加id,以便在代碼中操作它:

 
        
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.li.sheldon.ffmpeg4android.MainActivity">

<TextView
android:id="@+id/hello_ffmpeg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!" />
</RelativeLayout>
(10)增加一個Activity實現類FFmpeg4AndroidActivity,在OnCreate方法中調用native函數將值傳給TextView控件,打包運行即可。FFmpeg4AndroidActivity代碼如下:
 
        
package com.li.sheldon.ffmpeg4android;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
int codec_id=28;
FFmpegNative ffmpeg = new FFmpegNative();
int tmp = ffmpeg.test_h246(codec_id); //28 is the H264 Codec ID
TextView tv = (TextView)this.findViewById(R.id.hello_ffmpeg);
tv.setText(tmp==0?"Support Codec ID:"+codec_id:"Not support Codec ID:"+codec_id);
}
}

代碼中的28是H264的編解碼枚舉類型定義的ID,如果能找到H264編解碼,表明可以成功使用FFmpeg庫文件。

android 代碼和動態庫已傳至github : https://github.com/dragonforgithub/FFmpeg4Android.git

記錄FFmpeg 雷神博客:http://blog.csdn.net/leixiaohua1020/article/details/44226355  (致敬永遠的雷神)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM