воскресенье, 2 июня 2013 г.

Собираем ffmpeg под Android

Рабочее окружение

  1. Ubuntu 13.04 x86_64
  2. Eclipse
  3. android-ndk-r8e
  4. arm-linux-androideabi

Сборка

1. Скачиваем скрипт для сборки ffmpeg
git clone git://github.com/yixia/FFmpeg-Android.git
2. Переходим FFmpeg-Android.

В скрипте FFmpeg-Android.sh 
Добавим размещение ANDROID_NDK
ANDROID_NDK=~/android-ndk
К списку параметров make-standalone-toolchain.sh добавить параметр
--system=linux-x86_64
Где linux-x86_64 разрядность системы.

Изменим строку
export CC="ccache arm-linux-androideabi-gcc"
на
export CC="arm-linux-androideabi-gcc"
 В цикле
for version in neon armv7 vfp armv6; do
можно убрать неиспользуемые платформы. Например
 for version in armv7; do
Запустить FFmpeg-Android.sh. Скрипт сольет и соберет ffmpeg. Результат компиляции будет в build/ffmpeg.

Использование ffmpeg под Android

1. Создаем новый проект в Eclipse

2. Добавим поддержку Native. Правой кнопкой по проекту, Android Tools-Add Native Support

3. Добавим вызов нашей библиотеки из MainActivity

public class MainActivity extends Activity {

    private static native int logFileInfo(String filename);

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        logFileInfo("/sdcard/Download/Flipped.2010.HDRip_mvo.x264.RG.tru.mkv");
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    static {
        // load first libffmpeg.so
        System.loadLibrary("ffmpeg");
        System.loadLibrary("FfmpegAndroid");
    }
}

Адрес видео файла необходимо исправить на свой.

4. Cоздадим заголовочный файл функции logFileInfo для c++.

Для этого переходим в папку из которой в терминале вызываем команду 
javah полный.путь.до.класса
Например
javah com.example.ffmpegandroid.MainActivity
Полученный файл переместим в папку jni.
5. Изменим Android.mk. Содержимое моего Android.mk:
LOCAL_PATH := $(call my-dir)

FFMPEG=/home/vadim/FFmpeg-Android/build/ffmpeg/armv7

include $(CLEAR_VARS)

LOCAL_MODULE := prebuild-ffmpeg
LOCAL_SRC_FILES := $(FFMPEG)/libffmpeg.so

include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)

LOCAL_C_INCLUDES := $(FFMPEG)/include
LOCAL_CFLAGS += -D__STDC_CONSTANT_MACROS
LOCAL_LDLIBS += -llog -ljnigraphics -lz -lm $(FFMPEG)/libffmpeg.so
LOCAL_CFLAGS += -march=armv7-a -mfloat-abi=softfp -mfpu=neon
LOCAL_MODULE    := FfmpegAndroid
LOCAL_SRC_FILES := FfmpegAndroid.cpp

include $(BUILD_SHARED_LIBRARY)
 6. В c++ будем вызывать ffmpeg. Хейдеры ffmpeg нужно обернуть в extern "C".
#include <jni.h>

#include "com_example_ffmpegandroid_MainActivity.h"

#include <android/log.h>

extern "C" {
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
}

#define LOG_TAG "mylib"
#define LOGI(...)  __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOGE(...)  __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)

jint JNICALL Java_com_example_ffmpegandroid_MainActivity_logFileInfo(
        JNIEnv *env, jclass, jstring filename) {
    // init ffmpeg
    av_register_all();
    avcodec_register_all();

    LOGI("Hello from ffmpeg");

    const char *str = env->GetStringUTFChars(filename, 0);
    AVFormatContext *pFormatCtx = avformat_alloc_context();

    const int res = avformat_open_input(&pFormatCtx, str, 0, 0);
    LOGI("result %d", res);

    if (res != 0) {
        LOGE("Can't open file '%s'\n", str);
        return 1;
    } else if (res >= 0) {
        LOGI("File was opened\n");
        LOGI("File '%s', Codec %s", pFormatCtx->filename,
                pFormatCtx->iformat->name);
        LOGI("Duration %d", pFormatCtx->duration);
    }

    return 0;
}
Если все верно, то LogCat должен вводить примерно следующее:
I/mylib(24494): Hello from ffmpeg
I/mylib(24494): result 0
I/mylib(24494): File was opened
I/mylib(24494): File '/sdcard/Download/Flipped.2010.HDRip_mvo.x264.RG.tru.mkv', Codec matroska,webm
I/mylib(24494): Duration 1694753600

Проект в Eclipse
http://yadi.sk/d/nZzMNzj85R7IG
Скрипт сборки ffmpeg
http://yadi.sk/d/ichI1kzj5R7IA