воскресенье, 15 апреля 2012 г.

Компиляция ffmpeg для Android-приложения

Привычная для меня среда обитания — Windows. И вдруг оказывается, что компиляция ffmpeg под Android в операционной системе Windows невозможна. Нет, вести разработку с применением откомпилированной библиотеки и заголовочных файлов ffmpeg можно, но чтобы получить эту библиотеку придётся развёртывать Linux. Может я излишне категоричен, и кому-то это удавалось, но я таких примеров не встретил. Наоборот есть много повисших в воздухе вопросов на форумах. Общее направление рекомендаций сводится к переходу на Linux.
Пришлось устанавливать Ubuntu и настраивать в ней среду разработки. Об этом я писал в своей статье «Обустройство в Ubuntu».
Итак, как я компилировал ffmpeg...



Установка Android NDK

Загрузка и установка Android NDK подробно описаны тут. Я использовал Android NDK, Revision 7c (April 2012): android-ndk-r7c-linux-x86.tar.bz2
Внутри архива папка «android-ndk-r7c». Можно просто разархивировать её в Домашнюю папку. Я ещё переименовал её в «android-ndk».

Компиляция ffmpeg

В Eclipse надо cоздать новый Android-проект и добавить в него папку jni.
Называю проект «MyFfmpeg». При создании выбираю «build target» Google APIs 2.3.3 (level 10). Затем:


И Finish.
Далее в проект добавляем папку jni:



Со страницы загрузки ffmpeg я скачал архив стабильного релиза FFmpeg 0.8.11 "Love", разархивировал во временный каталог, переименовал папку «ffmpeg-0.8.11» в «ffmpeg» и прямо drag&drop-ом перенёс её в папку jni моего проекта в Eclipse.
"Love" — самая поздняя версия, которую мне удалось откомпилировать. Я пробовал версии FFmpeg 0.9.1 "Harmony", FFmpeg 0.10 "Freedom" и FFmpeg 0.10.2 "Freedom", но безрезультатно. Получаю ошибку компиляции «error: libavcodec/codec_names.h: No such file or directory». Причём не работает именно компиляция средствами Android NDK. Описание этого бага я нашёл здесь. Решения пока нет (на сегодняшний день уже три месяца). Думаю, эта проблема решаема, но и я не стал сильно упираться — меня вполне устраивает и версия 0.8.11.
Далее файлу …/MyFfmpeg/jni/ffmpeg/configure необходимо установить атрибут разрешения исполнения как программы.
Для конфигурирования ffmpeg и компиляции библиотеки создадим скрипт "build4android.sh" в каталоге «…/MyFfmpeg/jni/ffmpeg». Идею написания такого скрипта я подсмотрел в одном проекте с открытым кодом. Вот текст моего "build4android.sh":

#!/bin/bash
# Author: Dmitry Dzakhov (based on Guo Mingyu's script)

# Creating conf.sh in ffmpeg directory
NDK=/home/dmitrydzz/android-ndk
PLATFORM=$NDK/platforms/android-8/arch-arm
PREBUILT=$NDK/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86
output="conf.sh"

[ -f conf.sh ] && echo "Old $output has been removed."
echo '#!/bin/bash' > $output
echo "PREBUILT=$PREBUILT" >> $output
echo "PLATFORM=$PLATFORM" >> $output
echo './configure --target-os=linux \
    --prefix=./android/armv7-a \
    --enable-cross-compile \
    --extra-libs="-lgcc" \
    --arch=arm \
    --cc=$PREBUILT/bin/arm-linux-androideabi-gcc \
    --cross-prefix=$PREBUILT/bin/arm-linux-androideabi- \
    --nm=$PREBUILT/bin/arm-linux-androideabi-nm \
    --sysroot=$PLATFORM \
    --extra-cflags=" -O3 -fpic -DANDROID -DHAVE_SYS_UIO_H=1 -Dipv6mr_interface=ipv6mr_ifindex -fasm -Wno-psabi -fno-short-enums -fno-strict-aliasing -finline-limit=300 -mfloat-abi=softfp -mfpu=neon -marm -march=armv7-a -mtune=cortex-a8 " \
    --disable-shared \
    --enable-static \
    --extra-ldflags="-Wl,-rpath-link=$PLATFORM/usr/lib -L$PLATFORM/usr/lib -nostdlib -lc -lm -ldl -llog" \
    --enable-parsers \
    --enable-encoders \
    --enable-decoders \
    --enable-muxers \
    --enable-demuxers \
    --enable-swscale \
    --enable-swscale-alpha \
    --disable-ffplay \
    --disable-ffprobe \
    --enable-ffserver \
    --enable-network \
    --enable-indevs \
    --disable-bsfs \
    --enable-filters \
    --enable-avfilter \
    --enable-protocols \
    --disable-asm \
    --enable-neon' >> $output

# start configure
sudo chmod +x $output
echo "configuring..."
./$output || (echo configure failed && exit 1)

# modify the config.h
echo "modifying the config.h..."
sed -i "s/#define restrict restrict/#define restrict/g" config.h

# remove static functions in libavutil/libm.h
echo "removing static functions in libavutil/libm.h..."
sed -i "/static/,/}/d" libavutil/libm.h

# modify Makefiles
echo "modifying Makefiles..."
sed -i "/include \$(SUBDIR)..\/subdir.mak/d" libavcodec/Makefile
sed -i "/include \$(SUBDIR)..\/config.mak/d" libavcodec/Makefile
sed -i "/include \$(SUBDIR)..\/subdir.mak/d" libavfilter/Makefile
sed -i "/include \$(SUBDIR)..\/config.mak/d" libavfilter/Makefile
sed -i "/include \$(SUBDIR)..\/subdir.mak/d" libavformat/Makefile
sed -i "/include \$(SUBDIR)..\/config.mak/d" libavformat/Makefile
sed -i "/include \$(SUBDIR)..\/subdir.mak/d" libavutil/Makefile
sed -i "/include \$(SUBDIR)..\/config.mak/d" libavutil/Makefile
sed -i "/include \$(SUBDIR)..\/subdir.mak/d" libpostproc/Makefile
sed -i "/include \$(SUBDIR)..\/config.mak/d" libpostproc/Makefile
sed -i "/include \$(SUBDIR)..\/subdir.mak/d" libswscale/Makefile
sed -i "/include \$(SUBDIR)..\/config.mak/d" libswscale/Makefile

# generate av.mk in ffmpeg
echo "generating av.mk in ffmpeg..."
echo '# LOCAL_PATH is one of libavutil, libavcodec, libavformat, or libswscale

#include $(LOCAL_PATH)/../config-$(TARGET_ARCH).mak
include $(LOCAL_PATH)/../config.mak

OBJS :=
OBJS-yes :=
MMX-OBJS-yes :=
include $(LOCAL_PATH)/Makefile

# collect objects
OBJS-$(HAVE_MMX) += $(MMX-OBJS-yes)
OBJS += $(OBJS-yes)

FFNAME := lib$(NAME)
FFLIBS := $(foreach,NAME,$(FFLIBS),lib$(NAME))
FFCFLAGS  = -DHAVE_AV_CONFIG_H -Wno-sign-compare -Wno-switch -Wno-pointer-sign
FFCFLAGS += -DTARGET_CONFIG=\"config-$(TARGET_ARCH).h\"

ALL_S_FILES := $(wildcard $(LOCAL_PATH)/$(TARGET_ARCH)/*.S)
ALL_S_FILES := $(addprefix $(TARGET_ARCH)/, $(notdir $(ALL_S_FILES)))

ifneq ($(ALL_S_FILES),)
ALL_S_OBJS := $(patsubst %.S,%.o,$(ALL_S_FILES))
C_OBJS := $(filter-out $(ALL_S_OBJS),$(OBJS))
S_OBJS := $(filter $(ALL_S_OBJS),$(OBJS))
else
C_OBJS := $(OBJS)
S_OBJS :=
endif

C_FILES := $(patsubst %.o,%.c,$(C_OBJS))
S_FILES := $(patsubst %.o,%.S,$(S_OBJS))

FFFILES := $(sort $(S_FILES)) $(sort $(C_FILES))' > av.mk

echo 'include $(all-subdir-makefiles)' > ../Android.mk

echo 'LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_STATIC_LIBRARIES := libavformat libavcodec libavutil libpostproc libswscale
LOCAL_MODULE := ffmpeg
include $(BUILD_SHARED_LIBRARY)
include $(call all-makefiles-under,$(LOCAL_PATH))' > Android.mk

echo 'LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
include $(LOCAL_PATH)/../av.mk
LOCAL_SRC_FILES := $(FFFILES)
LOCAL_C_INCLUDES :=        \
    $(LOCAL_PATH)        \
    $(LOCAL_PATH)/..
LOCAL_CFLAGS += $(FFCFLAGS)
LOCAL_CFLAGS += -include "string.h" -Dipv6mr_interface=ipv6mr_ifindex
LOCAL_LDLIBS := -lz
LOCAL_STATIC_LIBRARIES := $(FFLIBS)
LOCAL_MODULE := $(FFNAME)
include $(BUILD_STATIC_LIBRARY)' > libavformat/Android.mk

echo 'LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
include $(LOCAL_PATH)/../av.mk
LOCAL_SRC_FILES := $(FFFILES)
LOCAL_C_INCLUDES :=        \
    $(LOCAL_PATH)        \
    $(LOCAL_PATH)/..
LOCAL_CFLAGS += $(FFCFLAGS)
LOCAL_CFLAGS += -std=c99
LOCAL_LDLIBS := -lz
LOCAL_STATIC_LIBRARIES := $(FFLIBS)
LOCAL_MODULE := $(FFNAME)
include $(BUILD_STATIC_LIBRARY)' > libavcodec/Android.mk

echo 'LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
include $(LOCAL_PATH)/../av.mk
LOCAL_SRC_FILES := $(FFFILES)
LOCAL_C_INCLUDES :=        \
    $(LOCAL_PATH)        \
    $(LOCAL_PATH)/..
LOCAL_CFLAGS += $(FFCFLAGS)
LOCAL_STATIC_LIBRARIES := $(FFLIBS)
LOCAL_MODULE := $(FFNAME)
include $(BUILD_STATIC_LIBRARY)' > libavfilter/Android.mk

echo 'LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
include $(LOCAL_PATH)/../av.mk
LOCAL_SRC_FILES := $(FFFILES)
LOCAL_C_INCLUDES :=        \
    $(LOCAL_PATH)        \
    $(LOCAL_PATH)/..
LOCAL_CFLAGS += $(FFCFLAGS)
LOCAL_STATIC_LIBRARIES := $(FFLIBS)
LOCAL_MODULE := $(FFNAME)
include $(BUILD_STATIC_LIBRARY)' > libavutil/Android.mk

echo 'LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
include $(LOCAL_PATH)/../av.mk
LOCAL_SRC_FILES := $(FFFILES)
LOCAL_C_INCLUDES :=        \
    $(LOCAL_PATH)        \
    $(LOCAL_PATH)/..
LOCAL_CFLAGS += $(FFCFLAGS)
LOCAL_STATIC_LIBRARIES := $(FFLIBS)
LOCAL_MODULE := $(FFNAME)
include $(BUILD_STATIC_LIBRARY)' > libpostproc/Android.mk

echo 'LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
include $(LOCAL_PATH)/../av.mk
LOCAL_SRC_FILES := $(FFFILES)
LOCAL_C_INCLUDES :=        \
    $(LOCAL_PATH)        \
    $(LOCAL_PATH)/..
LOCAL_CFLAGS += $(FFCFLAGS)
LOCAL_STATIC_LIBRARIES := $(FFLIBS)
LOCAL_MODULE := $(FFNAME)
include $(BUILD_STATIC_LIBRARY)' > libswscale/Android.mk

# start build!
echo "start ndk-building..."
cd ../..
$NDK/ndk-build
# Change previous line to "$NDK/ndk-build V=1" if you'll get errors. This will give some more information.

Не забываем установить атрибут исполнения для этого скрипта!
Запускаю терминал и перехожу в каталог …/MyFfmpeg/jni/ffmpeg. Выполняю команду:

./build4android.sh 

Sudo запросит пароль пользователя, а дальше жду. Долго. На моём ноутбуке компиляция заняла 13 минут.
В процессе компиляции будет довольно много предупреждений, но с ними надо смириться. Это вопрос к разработчикам ffmpeg, как я понимаю.

Демонстрация работы

Итак, на предыдущем шаге Android NDK откомпилировал нам библиотеку, в результате чего в нашем проекте MyFfmpeg появились папки …/MyFfmpeg/libs и …/MyFfmpeg/obj. Последняя пригодится в дальнейшем. Для демонстрации использования откомпилированной под Android библиотеки, создадим отдельный проект, в котором будем вызывать функции этой библиотеки.
Говорят, желающие могут на этом шаге вернуться в Windows. Я желающий, но пока остался в Ubuntu.
Новый проект пусть будет называться MyFfmpegTest. После его создания выполняем следующие действия:

1. Копируем в него папку obj из проекта MyFfmpeg.
2. Создаём папку …/MyFfmpegTest/jni. Здесь будет наш код-обёртка, написанный на C.
3. Копируем в папку jni заголовочные файлы ffmpeg. Точнее, я скопировал в jni всю папку …/MyFfmpeg/jni/ffmpeg, а затем почистил её, оставив только файлы с расширением h, S и asm. Для этого в терминале выполнил такую команду:
find ~/robot-mitya/Android/MyFfmpegTest/jni/ffmpeg/ -type f -not \( -name "*.asm" -or -name "*.h" -or -name "*.S" \) -exec rm {} \;
ОСТОРОЖНО: команда удаляет все файлы кроме *.asm, *.h и *.S во всех подкаталогах пути, указанного первым параметром.


4. В папке jni создаём файл mylib.c следующего содержания:


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

#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 Java_ru_dzakhov_ffmpeg_test_MainActivity_logFileInfo(JNIEnv * env, jobject this, jstring filename)
{
    av_register_all();

    AVFormatContext *pFormatCtx;
    const jbyte *str;
    str = (*env)->GetStringUTFChars(env, filename, NULL);

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

5. Там же, в jni создаём файл Android.mk:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_LDFLAGS := -Wl,-rpath-link=/home/dmitrydzz/android-ndk/platforms/android-14/arch-arm/usr/lib/ -rpath-link=/home/dmitrydzz/android-ndk/platforms/android-14/arch-arm/usr/lib/
LOCAL_MODULE := libavformat
LOCAL_SRC_FILES := ../obj/local/armeabi/libavformat.a
LOCAL_CFLAGS := -march=armv7-a -mfloat-abi=softfp -mfpu=neon #надо именно эти 3 параметра! Нашёл это в android-ndk/docs/STANDALONE-TOOLCHAIN.html
LOCAL_LDLIBS := -lz -lm -llog -lc -L$(call host-path, $(LOCAL_PATH))/$(TARGET_ARCH_ABI) -landprof

include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)

LOCAL_LDFLAGS := -Wl,-rpath-link=/home/dmitrydzz/android-ndk/platforms/android-14/arch-arm/usr/lib/ -rpath-link=/home/dmitrydzz/android-ndk/platforms/android-14/arch-arm/usr/lib/
LOCAL_MODULE := libavcodec
LOCAL_SRC_FILES := ../obj/local/armeabi/libavcodec.a
LOCAL_CFLAGS := -march=armv7-a -mfloat-abi=softfp -mfpu=neon
LOCAL_LDLIBS := -lz -lm -llog -lc -L$(call host-path, $(LOCAL_PATH))/$(TARGET_ARCH_ABI) -landprof

include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)

LOCAL_MODULE := libpostproc
LOCAL_SRC_FILES := ../obj/local/armeabi/libpostproc.a
LOCAL_CFLAGS := -march=armv7-a -mfloat-abi=softfp -mfpu=neon

include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)

LOCAL_MODULE := libswscale
LOCAL_SRC_FILES := ../obj/local/armeabi/libswscale.a
LOCAL_CFLAGS := -march=armv7-a -mfloat-abi=softfp -mfpu=neon

include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)

LOCAL_MODULE := libavutil
LOCAL_SRC_FILES := ../obj/local/armeabi/libavutil.a
LOCAL_CFLAGS := -march=armv7-a -mfloat-abi=softfp -mfpu=neon

include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)

LOCAL_LDLIBS += -llog -lz
LOCAL_STATIC_LIBRARIES := libavformat libavcodec libpostproc libswscale libavutil
LOCAL_C_INCLUDES += $(LOCAL_PATH)/ffmpeg
LOCAL_SRC_FILES := mylib.c
LOCAL_CFLAGS := -march=armv7-a -mfloat-abi=softfp -mfpu=neon
LOCAL_MODULE := mylib

include $(BUILD_SHARED_LIBRARY)

LOCAL_PATH := $(call my-dir)
LOCAL_C_INCLUDES += $(LOCAL_PATH)/ffmpeg
include $(all-subdir-makefiles)

6. Компилируем динамическую библиотеку libmylib.so с помощью Android NDK. Для этого запускаем терминал, переходим в папку …/MyFfmpegTest/jni и выполняем команду:
~/android-ndk/ndk-build.


Библиотека скомпилирована, для демонстрации осталось немного подкрутить активити нашего Android-приложения. Добавляем несколько строк в активити:


package ru.dzakhov.ffmpeg.test;

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

public class MainActivity extends Activity {
    private static native int logFileInfo(String filename);
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        logFileInfo("/sdcard/VIDEO0050.mp4");
    }

    static
    {
        System.loadLibrary("mylib");
    }
}

Файл, естественно, укажите какой-нибудь свой. Запускал приложение я сразу на телефоне. В окне LogCat (тег "mylib") проскочили две замечательные строчки, после чего я стал светиться как медный таз:

04-08 19:20:09.999: I/mylib(26025): File was opened
04-08 19:20:09.999: I/mylib(26025): File '/sdcard/VIDEO0050.mp4', Codec mov,mp4,m4a,3gp,3g2,mj2

Путь к этим двум строчкам дался мне с трудом.

Заключение

Сейчас всё выглядит не так уж и сложно, но на компиляцию ffmpeg я потратил уйму сил и времени: пришлось развёртывать невиданную мной ранее Ubuntu, осмысливать Android NDK, искать, искать и искать в интернете крохи информации о компиляции ffmpeg под Android.
В ходе своего поиска пути решения задачи передачи видео от Android к компьютеру, я пытался найти и альтернативные варианты. Они есть и я их рассматривал:

  1. Есть libav. Это «форк» от ffmpeg. Есть мнение, что он лучше, но информации по нему ещё меньше, чем по ffmpeg.
  2. Я встречал проекты под Android с открытым исходным кодом, реализующие передачу видео и аудио по протоколу SIP. Самый известный — Sipdroid. Он даже самостоятельно реализует протокол RTP. Я, конечно, заглянул в исходники и сразу вернулся к идее об ffmpeg.
  3. Я нашёл платный SDK под Android, предназначенный для работы с видео, аудио и SIP. Но он использует ffmpeg. Причём старый — я смотрел исходный код. Стоимость я не выяснил, документацию не нашёл, но по крайней мере, есть у кого её запросить.
  4. Откомпилировать исполняемый файл ffmpeg, а не библиотеку, и работать с ним из моего приложения. Тем более, что работа с ffmpeg из командной строки описана в интернете вполне сносно. Решение какое-то корявое, мне кажется.
  5. Использовать бесплатное приложение IP Webcam. Прекрасный вариант, но уж больно мне хотелось реализовать всё полностью в моём приложении (ffmpeg не в счёт). Работа с ffmpeg это полезный опыт, который пригодится мне в будущем. Тем более, посмотрите, сколько тем пришлось уже для этого поднять.
  6. И самый запасной вариант. Если у меня не получится передача видео, я вполне могу организовать передачу изображений. По моим расчётам, на 5 кадров в секунду вполне можно рассчитывать. Но очень уж хочется потокового видео.
В результате, всё-таки я остался на варианте с ffmpeg, встроенным в мой проект.

На всякий случай вот ссылки на скрипт build4android.sh конфигурирования и компиляции ffmpeg и тестовый проект MyFfmpegTest.

И последнее, что я обязан сказать... Огромное спасибо Дарье Ряжских за её статью «Собираем ffmpeg для Android» и Guo Mingyu (за прекрасную идею и прообраз моего скрипта конфигурирования и компиляции ffmpeg вместо кучи ручных операций), хоть эти люди меня и не знают. Мой труд сводился только к «осовремениваю» их работы и расширению конфигурации ffmpeg. Но поверьте, мне этого более чем хватило.


17 комментариев:

  1. спасибо за информацию, давно слежу за ffmpeg для андроида

    ОтветитьУдалить
  2. В скриптах лучше исправить /home/dmitrydzz/ на ~/
    ~/ - домашняя папка текущего пользователя. В итоге тем, кто будет использовать твой скрипт не понадобится его править.

    ОтветитьУдалить
  3. проще было использовать cygwin для сборки из под Windows.

    ОтветитьУдалить
    Ответы
    1. Очень сомневаюсь. Перед тем, как я решился связаться с Ubuntu, я искал как бы откомпилироваться из-под Windows. Я знаю о Cygwin, но ни одного успешного примера компиляции ffmpeg под Android в Windows я не встретил. Наоборот, только вопросы как бы это сделать и ответы, что это невозможно.

      Сейчас опять погуглил... Кажется, тут что-то изменилось, вот пример: http://ffmpeg.org/pipermail/ffmpeg-user/2012-April/005973.html

      Апрель 2012 года. В это время я уже сидел глубоко в Ubuntu. Здорово, если теперь компилировать ffmpeg можно не выходя из Windows. Правда, по-прежнему, статей "как я собрал ffmpeg под Windows" я не вижу.

      Удалить
  4. Добрый день.
    Есть вопросик.
    Скомпилировать ffmpeg получилось.
    Скомпилировать пример тоже получилось.
    Но при запуске тестового проекта в эмуляторе ничего похожего на
    File was opened
    File '/sdcard/VIDEO0050.mp4', Codec mov,mp4,m4a,3gp,3g2,mj2
    нет.
    Есть только:
    05-17 12:18:54.732: D/dalvikvm(336): Trying to load lib /data/data/my.test/lib/libmylib.so 0x405140f8
    05-17 12:18:54.830: I/ARMAssembler(70): generated scanline__00000177:03515104_00001002_00000000 [ 87 ipp] (110 ins) at [0x445ed520:0x445ed6d8] in 1531341 ns
    05-17 12:18:54.920: D/dalvikvm(336): Added shared lib /data/data/my.test/lib/libmylib.so 0x405140f8
    05-17 12:18:54.920: D/dalvikvm(336): No JNI_OnLoad found in /data/data/my.test/lib/libmylib.so 0x405140f8, skipping init

    потом куча дебаг сообщений и в конце:
    05-17 12:18:57.630: D/Zygote(33): Process 336 terminated by signal (4)
    05-17 12:18:57.643: I/ActivityManager(70): Process my.test (pid 336) has died.

    Что я делаю не так?
    И вопрос, а можно как то использовать ffmpeg как из командной строки? Потому как от С я далек, а описания API толкового так нигде и не нашел :(

    ОтветитьУдалить
    Ответы
    1. Вы знаете, я почему-то не пробовал запускать это тестовое приложение в эмуляторе. Отлаживался сразу на своём аппарате.

      Есть ли у Вас возможность проверить на физическом устройстве? Подозреваю, что на провал в эмуляторе могут влиять флаги компиляции ffmpeg. Там есть несколько волшебных слов типа "neon" и "armv7-a". Возможно эмулятор не может справиться с ними.

      К сожалению, не могу сейчас проверить эту свою теорию - в ближайшие несколько дней Ubuntu у меня не будет. Я сейчас окопался в другом проекте.

      Напишите, пожалуйста, если что-то получится. Мне очень интересно. Если что, я готов буду вернуться к Вашему вопросу. Дело в том, что подобный вопрос мне задали в английском варианте этого поста (по почте, кажется), а посмотреть что к чему возможности сейчас нет.

      Удалить
    2. Пока такой возможности нет :(
      Буду играться с конфигурацией компиляции ffmpeg.

      А не подскажите по второму вопросу?
      На stackovrflow по этому поводу вот что есть:
      ==============================
      If you just wanted to make a call to ffmpeg as function rather than a system call, you can do that pretty easily.

      in ffmpeg.c, change:

      int main(int argc, char **argv) to int ffmpeg((int argc, char **argv)
      Then in your call the ffmpeg function and pass in an array that mimics the command line.
      ==================================
      вроде все просто, и все собралось, но вот как вызвать этот ffmpeg и передать ему параметры?

      Удалить
    3. Да, извините, забыл про второй вопрос.
      Направление я понимаю, а вот сделать такое самостоятельно пока не пытался. Надо будет с типами данных разбираться.

      Так же, как и в примере в посте, Вы должны будете сделать в папке jni файл с расширением С, содержащий функцию-обёртку наподобие функции из примера Java_ru_dzakhov_ffmpeg_test_MainActivity_logFileInfo. Функцию можно добавить в mylib.c. Типы данных в этой функции уже будут из NDK ().

      Очень прошу Вас потом поделиться опытом и исходником. Тема довольна актуальна, когда смотрю статистику по блогу у этого поста много просмотров. Я пока не могу продолжить свои изыскания, поэтому буду очень признателен, если Вы поделитесь накопленным опытом здесь в комментариях.

      Удалить
    4. Здравствуйте, вроде разобрался как откомпилировать под эмулятор (я пробовал под 2.1 и под древним HTC Magic)
      из скрипта build4android.sh убрать строку
      --prefix=./android/armv7-a \

      из скрипта android.mk убрать _все_ строки
      LOCAL_CFLAGS := -march=armv7-a -mfloat-abi=softfp -mfpu=neon

      Если надо, сделать build4android заново.
      думаю что это отключит оптимизации, но по крайней мере будет работать везде.

      Удалить
  5. пробовал скомпилировать на ubuntu 64 ничего не получилось, на 32 все ок

    ОтветитьУдалить
  6. Здравствуйте,
    кто нибудь подскажите, как откомпилить ffmpeg так что бы можно было в коде работать как будто с консолью. Например задать что то типа

    char *params[] = {"ffmpeg", "-param1",param1,"param2", "param2" ,};

    ffmpeg(5, params);

    Данный код я взял из головы.

    Не получается у меня скомпилировать ffmpeg.c Вываливается с 1000 и одной ошибкой.

    ОтветитьУдалить
  7. Собрал на Cygwin (win7x64)...
    ffmpeg 0.11.1, ndk8
    Если кто решится - никому не советую.

    Удивительная вещь, которую я обнаружил-это то, что gcc не видит имена в linux-формате, а ld в windows формате. Никак не смог это побороть. Отключил скрипты для линкера (кажется, у автора их тоже нет).

    Пришлось вручную генерировать codec_names.h, так как ndk-build не хотел понимать перенаправление ввода-вывода в Android.mk (эта проблема описана в посте).

    Плюс ко всему была проблема с #include в avutils. Там есть свой time.h, который и включал компилятор.

    ОтветитьУдалить
  8. You may want to check this project
    http://sourceforge.net/p/ffmpeg4android

    ОтветитьУдалить
  9. спасибо автору и ребятам, которые отвечали

    ОтветитьУдалить
  10. Этот комментарий был удален автором.

    ОтветитьУдалить
    Ответы
    1. Этот комментарий был удален автором.

      Удалить
    2. Этот комментарий был удален автором.

      Удалить