雖然 Android framework 已經有不錯的函式庫,但總是會有不足之處。這時就先來玩玩 FFmpeg 吧,首先要做的事就是編譯出可以在 Android 執行的函式庫,網路上不少編譯 FFmpeg for Android(ARM) 的文章,最後我就在 Ubuntu 12.04 64Bit 上試編一下,並在 Mac OS 10.8 上把玩 Eclipse 囉
相關資源:
- How to build FFmpeg with Android NDK
- github.com/vecio/FFmpeg-Android
- jjmpeg - Java binding to FFmpeg libraries.
- Android 開發筆記 - 使用 Android NDK (Native Development Kit)
首先,就在 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.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.mk 的設定,例如該去哪編找 header files 等,其他跟一般 Android NDK 教學文沒啥兩樣囉。
沒有留言:
張貼留言