+ 

雖然 Android framework 已經有不錯的函式庫,但總是會有不足之處。這時就先來玩玩 FFmpeg 吧,首先要做的事就是編譯出可以在 Android 執行的函式庫,網路上不少編譯 FFmpeg for Android(ARM) 的文章,最後我就在 Ubuntu 12.04 64Bit 上試編一下,並在 Mac OS 10.8 上把玩 Eclipse 囉

相關資源:

首先,就在 Ubuntu 下載好 Android NDK 後,安裝一些基本環境:

$ sudo apt-get install ia32-libs git make

接著取出 github.com/vecio/FFmpeg-Android 後,直接修改 FFmpeg-Android.sh:

- cd ffmpeg && patch -p1 <../FFmpeg-VPlayer.patch
+ cd ffmpeg && git checkout 5e99df019a850e9ffa96d73e72b8a47a93a61de8
+ #cd ffmpeg && patch -p1 <../FFmpeg-VPlayer.patch

-export CC="ccache arm-linux-androideabi-gcc"
+#export CC="ccache arm-linux-androideabi-gcc"
+export CC=arm-linux-androideabi-gcc

-for version in neon armv7 vfp armv6; do
+#for version in neon armv7 vfp armv6; do
+for version in armv7 armv6; do

- [ $PIPESTATUS == 0 ] || exit 1
+ #[ $PIPESTATUS == 0 ] || exit 1

接著設定好 ANDROID_NDK 環境變數後,就可以開始編譯了,在我的 VM 中,大概跑了好一陣子,約 20 分鐘:

$ export ANDROID_NDK=~/android-ndk-r8d
$ cd ~/FFmpeg-Android
$ sh FFmpeg-Android.sh
$ ls ~/FFmpeg-Android/build/ffmpeg/
armv6  armv7

在把 ~/FFmpeg-Android/build/ffmpeg/ 複製到 Mac OS X 使用。而在 Mac OS X 10.8 上,就單純用 Eclipse 跟 Androd NDK 相關的設置,建立一個 Android Project 出來,此例為 HelloNDKWithFFmpeg ,使用 Android 4.0 SDK,並新增一個 jni 目錄,裡頭擺上之前編好的 ffmpeg 項目,以 Android.mk 和 ffmpeg-jni.c (其他如自動編譯的設定請參考 Android 開發筆記 - 使用 Android NDK ):

android_ffmpeg_eclipse

Android.mk:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE := ffmpeg-prebuilt
LOCAL_SRC_FILES := ffmpeg/armv7/libffmpeg.so
LOCAL_EXPORT_C_INCLUDES := ffmpeg/armv7/include
LOCAL_EXPORT_LDLIBS := ffmpeg/armv7/libffmpeg.so
LOCAL_PRELINK_MODULE := true
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := ffmpeg-jni
LOCAL_SRC_FILES := ffmpeg-jni.c
LOCAL_C_INCLUDES := $(LOCAL_PATH)/ffmpeg/armv7/include
LOCAL_LDLIBS := -lm -llog $(LOCAL_PATH)/ffmpeg/armv7/libffmpeg.so
#LOCAL_SHARED_LIBRARY := ffmpeg-prebuilt

include $(BUILD_SHARED_LIBRARY)

ffmpeg-jni.c:

#include <string.h>
#include <jni.h>
#include <android/log.h>

#include "libavformat/avformat.h"

#define LOG_TAG "FFmpegJNI"
#define LOGI(...) {__android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__);}
#define LOGE(...) {__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__);}

jstring Java_com_example_hellondkwithffmpeg_MainActivity_stringFromJNI( JNIEnv* env, jobject thiz )
{
    return (*env)->NewStringUTF(env, "Hello from My JNI !");
}

void Java_com_example_hellondkwithffmpeg_MainActivity_getVersions(JNIEnv *env, jclass jc, jobject jvers)
{
    int *vers = (*env)->GetDirectBufferAddress(env, jvers);
    vers[0] = LIBAVFORMAT_VERSION_MAJOR;
    vers[1] = LIBAVCODEC_VERSION_MAJOR;
    vers[2] = LIBAVUTIL_VERSION_MAJOR;
}

MainActivity.java:

package com.example.hellondkwithffmpeg;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;

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

public class MainActivity extends Activity {

   @Override
   public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      //setContentView(R.layout.activity_main);
      TextView tv = new TextView(this);
      //tv.setText( stringFromJNI() );
      tv.setText( getVersions() );
      setContentView(tv);
   }

   String getVersions() {
      ByteBuffer bvers = ByteBuffer.allocateDirect(4 * 3).order(ByteOrder.nativeOrder());
      getVersions(bvers);
      int[] vers = new int[3];
      bvers.asIntBuffer().get(vers);
      return "LIBAVFORMAT_VERSION_MAJOR: "+vers[2]+"\nLIBAVCODEC_VERSION_MAJOR: "+vers[1]+"\nLIBAVUTIL_VERSION_MAJOR: "+vers[0];
   }

   public native String stringFromJNI();
   public native void getVersions(ByteBuffer b);
   static {
      System.loadLibrary("ffmpeg");
      System.loadLibrary("ffmpeg-jni");
   }
}

成果(Nexus S實機):

android_ffmepg

整體上的使用心得是在如何編譯出第三方函式庫以及 Android.mk 的設定,例如該去哪編找 header files 等,其他跟一般 Android NDK 教學文沒啥兩樣囉。


文章標籤
創作者介紹

第二十四個夏天後

changyy 發表在 痞客邦 PIXNET 留言(0) 人氣()