[Из песочницы] Говорящая панда или что можно сделать с FFmpeg и OpenCV на Android

Эта публикация о том, как можно в Windows скомпилировать библиотеку для обработки видео и аудио FFmpeg под Android в Eclipse с помощью NDK. Вы узнаете, как связать FFmpeg с библиотекой для обработки изображений OpenCV и как это всё можно использовать в Java-коде Android приложения. Всё это будет рассказано в контексте процесса создания Android приложения, основной функционал которого как раз и завязан на использовании этих библиотек и их взаимодействии. Итак, заинтересованных прошу под кат.ДисклеймерНекоторые описываемые вещи наверняка покажутся многим очевидными, тем не менее, для меня, как для разработчика под Windows, эти задачи оказались новыми и их решение было не очевидным, поэтому описание технических деталей я постарался сделать максимально простым и понятным для людей, не имеющих большого опыта работы с Android NDK и всем, что с ним связано. Некоторые решения были найдены интуитивно, и поэтому, скорее всего, они не совсем «красивые».Предыстория Идея Android приложения, где бы использовались FFmpeg и OpenCV, появилась после просмотра одного рекламного ролика про минеральную воду Витутас (можете поискать на Youtube). В этом ролике иногда мелькали фото разных животных, которые вращали человеческими глазами, шевелили губами и уговаривали зрителя купить эту воду. Выглядело это довольно забавно. В общем, возникла мысль: что если дать пользователю возможность самому делать подобные ролики, причем не с компьютера, а с помощью своего телефона? Разумеется, сперва поискали аналоги. Что-то более или менее похожее было найдено в AppStore для iPhone, причем там процесс создания ролика был не очень удачным: выбираешь картинку, размечаешь на ней одну область, и потом камерой в этой области что-то снимаешь, то есть речь о том, чтобы наложить на картинку в разных местах хотя бы два глаза и рот вообще не шла. В Google Play же вообще ничего такого не было. Максимально близкие программы с похожим функционалом были такие, где на фото можно наложить анимированные элементы из ограниченных наборов.

Одним словом, конкурентов мало, поэтому было принято решение приложение всё же делать.

Выбор технологий Сразу возник логичный вопрос: «А как это все сделать?». Потратив дня два на изучение всяких библиотек для обработки видео и изображений, остановился на FFmpeg и OpenCV.Из плюсов можно перечислить следующие:

обе библиотеки написаны на C/C++, то есть объединить их уже теоретически можно; бесплатные с открытым кодом: FFmpeg можно собрать под LGPL, а OpenCV вообще распространяется под лицензией BSD; очень быстрые, да и вообще крутые с какой стороны не посмотри. Из минусов: написаны на C/C++; все же FFmpeg сложноватый для того, чтобы в его коде быстро разобраться и понять, где надо что поменять. Схема использования вырисовывалась такая: OpenCV формирует каждый кадр видео ряда (например, помещает на картинку, глаза и рот), передает этот кадр каким-то образом в FFmpeg, а тот в свою очередь формирует из этих кадров видеопоток, параллельно не забывая про аудио.Надо признаться в том, что так как опыта разработки под Android было мало, а под Windows много, то прежде чем начать ковыряться в Eclipse и NDK я сделал маленькую программку в Visual Studio, которая доказала, что сама идея использовать FFmpeg и OpenCV имеет право на жизнь и, самое главное, что есть способ реализовать их взаимодействие. Но о реализации взаимодействия этих библиотек будет написано чуть позже, а это скорее легкая рекомендация на тему того, что лучше все же потратить время и проверить какую-то идею на технологиях, в которых разбираешься лучше всего, чем сразу с головой лезть во что-то новое.

Насчет же компиляции FFmpeg в Visual Studio — сделать это оказалось на удивление легко, но эта статья все же об Android, поэтому если тема FFmpeg в Visual Studio интересна, то напишите об этом, и я постараюсь найти время и написать инструкцию о том, как это сделать.

Итак, проверив, что идея объеденить FFmpeg и OpenCV работает, я приступил к разработке непосредственно Android приложения.

План был таков:

Компилируем и собираем FFmpeg и OpenCV под Android. Пишем код их взаимодействия. Используем это все в Java коде приложения. Делать это все решил в Eclipse, а не в Android Studio — как-то она мне на момент начала разработки показалась сыроватой и не очень удобной.

FFmpeg, Android, NDK, Eclipse, Windows Первым делом, как все нормальные люди, я стал искать в интернете инструкции о том, как сделать кросс-компиляцию FFmpeg для Android в Windows. Статьи есть, предлагаются даже какие-то наборы make-файлов, есть что-то на гитхабе, но по ним мне не удалось это сделать. Возможно из-за отсутсвия опыта работы с этим всем, возможно из-за ошибок в этих инструкциях и make-файлах. Обычно подобные инструкции пишет человек, который хорошо разбирается в описываемых технологиях и поэтому опускает какие-то «очевидные» нюансы, и получается, что новичку этим невозможно пользоваться.В общем, пришлось с нуля сделать все самому. Ниже приводится примерная последовательность действий.

0. Предустановки Скачиваем и устанавливаем: Eclipse с CDT, Android SDK, NDK, cygwin и OpenCV Android SDK. Если есть необходимость поддержать Android на x86, то следует скачать еще и yasm — он нужен, чтобы сделать кросс-компиляцию *.asm файлов, но об этом позже.Инструкции по установке и настройке этого всего находятся на сайтах, откуда они собственно и скачиваются, а насчет установки и настройки NDK в Eclipse есть отличная статья на сайте opencv.org, которая выдается в гугле по запросу «OpenCV Introduction into Android Development», обязательно зайдите на нее.

1. Подготавливаем проект Создаем в Eclipse новый проект Android приложения и ковертируем его в C/C++ проект (смотрите статью «OpenCV Introduction into Android Development»). На самом деле Android проект не сконвертируется полностью в C/C++, а в него просто добавится возможность работать с C/C++.Скачиваем и распаковываем архив с кодом FFmpeg с сайта ffmpeg.org. Папку с кодом вида «ffmpeg-2.6.1» кидаем в папку «jni» проекта (если ее нет — создаем там же где лежат «res», «scr» и т. п.).

Теперь необходимо создать конфигурационные файлы (самый важный из них «config.h») и make-файлы для FFmpeg. Здесь возникает первый нюанс: существуюет три платформы Android устройств — Arm, x86, MIPS. Для каждой из этих архитектур нужны собрать свои файлы библиотек *.so (аналог *.dll в Windows). NDK позволяет это сделать — в него включены компилятор и линковщик для каждой платформы.

Для того, чтобы сгенерировать конфигурационные файлы в FFmpeg есть специальный скрипт, для запуска которого нам и нужно было установить cygwin. Итак, запускаем командную строку Cygwin Terminal и вводим приведенные ниже наборы команд.

Bash-скрипты с пояснениями Для устройств ARM: $ cd D: $ cd MyProject/jni/ffmpeg-2.1.3/ $ PREBUILT=D:/ndk/android-ndk-r9c/toolchains/arm-linux-androideabi-4.6/prebuilt/windows-x86_64 $ PLATFORM=D:/ndk/android-ndk-r9c/platforms/android-8/arch-arm $ TMPDIR=D:/ $ ./configure --enable-version3 --enable-shared --disable-static --disable-ffmpeg --disable-ffplay --disable-ffprobe --disable-ffserver --disable-network --enable-cross-compile --target-os=linux --arch=arm --cross-prefix=$PREBUILT/bin/arm-linux-androideabi- --cc=$PREBUILT/bin/arm-linux-androideabi-gcc --ld=$PREBUILT/bin/arm-linux-androideabi-ld --tempprefix=D:/ Для устройств x86: $ cd D: $ cd MyProject/jni/ffmpeg-2.1.3/ $ PREBUILT=D:/ndk/android-ndk-r9c/toolchains/x86–4.6/prebuilt/windows-x86_64 $ PLATFORM=D:/ndk/android-ndk-r9c/platforms/android-9/arch-x86 $ TMPDIR=D:/ $ ./configure --enable-version3 --enable-shared --disable-static --disable-ffmpeg --disable-ffplay --disable-ffprobe --disable-ffserver --disable-network --enable-cross-compile --target-os=linux --arch=x86 --cross-prefix=$PREBUILT/bin/i686-linux-android- --cc=$PREBUILT/bin/i686-linux-android-gcc --ld=$PREBUILT/bin/i686-linux-android-ld --tempprefix=D:/ Для устройств MIPS: $ cd D: $ cd MyProject/jni/ffmpeg-2.1.3/ $ PREBUILT=D:/ndk/android-ndk-r9c/toolchains/mipsel-linux-android-4.6/prebuilt/windows-x86_64 $ PLATFORM=D:/ndk/android-ndk-r9c/platforms/android-9/arch-mips $ TMPDIR=D:/ $ ./configure --enable-version3 --enable-shared --disable-static --disable-ffmpeg --disable-ffplay --disable-ffprobe --disable-ffserver --disable-network --enable-cross-compile --target-os=linux --arch=mips --cross-prefix=$PREBUILT/bin/mipsel-linux-android- --cc=$PREBUILT/bin/mipsel-linux-android-gcc --ld=$PREBUILT/bin/mipsel-linux-android-ld --tempprefix=D:/ Пояснения: Первые две команды — переход в папку с кодом FFmpeg, где лежит файл «configure» — это bash скрипт, который генерирует нужные нам файлы, в том числе и «config.h», который используется при компиляции; Далее мы создаем три временные переменные окружения PREBUILT, PLATFORM, TMPDIR, в первые две записываются пути к папкам в NDK, где лежат утилиты для кросс-компиляции под разные платформы, если в эти папки зайти, то там будет среди множества папок будет и папка «bin», в окторой и лежат компилятор и линковщик. TMPDIR — путь во временную папку, где скрипт при работе будет хранить временные свои файлы; Последняя команда это собственно запуск скрипта «configure» из папки «ffmpeg-2.6.1» с параметрами. Список всех возможных параметров скрипта с пояснениями выводятся по команде »./configure -h». Ниже описание тех параметров, которые мы используем: параметр --enable-version3 — говорим скрипту, чтобы он сгенерировал такой конфигурационный файл, чтобы с помощью него можно было скомпилировать библиотеки FFmpeg которы будут под лицензией LGPL 3.0; параметры --enable-shared и --disable-static — говорим скрипту, что хотим на выходе получить *.so файлы. Сделав это, то по идее в купе с LGPL мы сможем их линковать к своему коду на который LGPL не будет распространяться; параметры --disable-ffmpeg --disable-ffplay --disable-ffprobe --disable-ffserver --disable-network — этими параметрами мы говорим скрипту, что нам не нужно создавать консольные программы (другими словами ffmpeg.exe, ffplay.exe и другие); оставшиеся параметры понятны по своим названиям — мы говорим, что хотим сделать кросс-компиляцию, назначаем платформу (linux arm, mips или x86), прописываем скрипту пути к компилятору и линковщику, задаем путь к временной папке. Скрипт сгенерирует в папке «jni/ffmpeg-2.1.3» файл «config.h», «config.asm» и несколько make-файлов. 2. Make-файлы, компиляция и сборка Итак, на данном этапе у нас уже есть: проект Android-приложения в Eclipse, в папке «jni/ffmpeg-2.1.3» лежит код с FFmpeg, и только что мы сгенерировали нужный нам файл «config.h». Теперь надо сделать make-файлы, чтобы это все можно было скомпилировать и получить *.so файлы которые мы сможем использовать в Android приложении.Я пробовал использовать для компиляции make-файлы, сгенерированные скриптом, но у меня не получилось, скорее всего, по причине кривизны рук. Поэтому я решил сделать свои собственные make-файлы с комментариями и инклюдами.

Для компиляции с помощью NDK необходимо минимум два make-файла: Android.mk и Application.mk, которые должны находиться в папке «jni» проекта. Application.mk обычно содержит не более десятка параметров и настраивает, если можно так выразиться, «глобальные» параметры компиляции. Android.mk отвечает за все остальное.

Также есть ряд моментов, связанные с некоторыми ошибками в момент компиляции. Они решались либо с помощью Google, либо исправлением на основе информации, выданной NDK в консоли (ошибки хорошо сформулированны и исправление их не должно составить труда). К сожалению, все здесь привести я не могу (банально забыл толком что исправлял), но вот список некоторых:

компилятор ругается на символ «av_restrict»: надо открыть файл «config.h» в папке «ffmpeg-2.1.3» и заменить строку »#define av_restrict restrict» на »#define av_restrict __restrict»; на некоторых машинах компилятор ругается на «getenv ()»: это решается комментированием строки «extern char *getenv (const char *);» в файле «ndk\android-ndk-r9c\platforms\android-9\arch-arm\usr\include\stdlib.h». Обратите внимание, на путь — в нем есть папка зависимая от целевой архитектуры: «arch-arm» если вы компилируете под для Arm, «arch-mips» для MIPS и «arch-x86» для x86; для избежания конфликтов лучше переименовать в файле «ffmpeg.c» функцию main () в ffmpeg_main (). Ее мы будем вызывать из Java кода Android приложения. Еще при компиляции были пару ошибок непосредственно в коде какого-нибудь из файлов FFmpeg. Я просто комментировал это место (разумеется, более-менее убедившись не поломается ли что). К примеру, какие-то места, где что-то выводится на консоль. Возможно было что-то и еще, к сожалению, я не помню, но на самом деле ошибки компиляции легко исправимы.Make-файлы и bat-скрипты с пояснениями. Нюансы: помимо непосредственно модулей библиотеки FFmpeg, таких как libavcodec, libavfilter и так далее, еще нам надо будет скомпилировать код самой программы ffmpeg.exe как библиотеку ffmpeg.so. Мы будем вызывать ее main () функцию (которую мы переименовали в ffmpeg_main ()) из Java-кода и передавать туда нужные нам параметры, а она будет делать для нас нужную работу; NDK не умеет компилировать *.asm файлы для x86 архитектуры, поэтому нам надо в начале с помощью yasm скомпилировать *.asm файлы, которые лежат в папках вида «jni\ffmpeg-2.1.3\libavcodec\x86», «jni\ffmpeg-2.1.3\libavfilter\x86» и так далее. Ниже будут приведены *.bat файлы, которые это делают. На выходе мы получим объектные файлы *.a, путь к которым мы укажем линковщику при компиляции под x86. Это надо сделать только если вы собираетесь поддерживать эту архитектуру; в make-файле практически для каждого модуля включается еще один make-файл вида «libavfilter_ignore.mk». В них для каждого модуля прописаны *.c файлы, которые не надо компилировать. Что это за файлы: часть из них, как я понял из содержимого, что-то вроде тестовых программок (как, например, mpegaudio_tablegen.c). Часть из них не предназначенны для компиляции, а просто подключаются через include (например h264qpel_template.c подключается в файле h264qpel.c). Наверняка в make-файлах, сгенерированных после работы скрипта confgiure (с которыми у меня ничего не сложилось) они все тоже игнорируются; в make-файл включена так же и сборка модуля OpenCV. Там все просто, читайте статью на сайте opencv.org под названием «OpenCV Introduction into Android Development». Он нужен для как раз для упомянутого взаимодействия FFmpeg-OpenCV. Об этом взаимодействии будет рассказано ниже; все модули FFmpeg с нуля у меня собираются полтора часа. Во время разработки просто невозможно работать, особенно если приходится часто что-то менять в какой-то модуле FFmpeg. Чтобы этого избежать, ниже будет приведен еще один make-файл. В нем с нуля будет компилироваться только один какой-нибудь модуль FFmpeg, а остальные будут использоваться уже ранее скомпилированные. Например, вы работаете в модуле libavfilter, что-то там программируете и постоянно меняете, вам нет нужды постоянно пересобирать еще и libavcodec и другие, достаточно взять уже ранее скомпилированные и нужным образом об этом указать в make-файле; в make-файле есть поясняющие комментарии, но так как там компилируется несоклько модулей, причем процедура компиляции похожа, то дублирующиеся команды в make-файле не поясняются. Android.mk — из него NDK берет список файлов кода для компиляции ################################################################################ # записываем в переменную LOCAL_PATH текущий каталог проекта LOCAL_PATH:= $(call my-dir) # записываем в переменную FFMPEG_DIR имя папки где лежит код FFmpeg FFMPEG_DIR:= ffmpeg-2.1.3 # записываем в переменную OPENCVROOT путь к папке с OpenCV Anroid SDK OPENCVROOT:= D:\OpenCV-2.4.7.1-android-sdk

# блок ниже нужен только для сборки под архитектуру x86 # дело в том, что для x86 есть на ассемблере написаны оптимизированные функции для большинства FFmpeg модулей #, но сам NDK не умеет компилировать *.asm файл, для этого мы будем использовать скаченный ранее yasm # до сборки нам надо с помощью yasm скомпилировать эти *.asm файлы и получить объектные *.a файлы, которые мы при компиляции будем подключать # пример компиляции *.asm файлов смотрите в bat-скриптах ifeq ($(TARGET_ARCH), x86) ################################################################################ include $(CLEAR_VARS)

LOCAL_MODULE:= avcodec_asm LIBAVCODEC_ASM_A_FILE_PATH:= $(LOCAL_PATH)/…/obj/local/x86/objs/avcodec/ffmpeg-2.1.3/libavcodec/x86/libavcodec_asm.a LOCAL_SRC_FILES:= $(subst jni/,,$(LIBAVCODEC_ASM_A_FILE_PATH))

include $(PREBUILT_STATIC_LIBRARY) ################################################################################ include $(CLEAR_VARS)

LOCAL_MODULE:= avfilter_asm LIBAVFILTER_ASM_A_FILE_PATH:= $(LOCAL_PATH)/…/obj/local/x86/objs/avfilter/ffmpeg-2.1.3/libavfilter/x86/libavfilter_asm.a LOCAL_SRC_FILES:= $(subst jni/,,$(LIBAVFILTER_ASM_A_FILE_PATH))

include $(PREBUILT_STATIC_LIBRARY) ################################################################################ include $(CLEAR_VARS)

LOCAL_MODULE:= avresample_asm LIBAVRESAMPLE_ASM_A_FILE_PATH:= $(LOCAL_PATH)/…/obj/local/x86/objs/avresample/ffmpeg-2.1.3/libavresample/x86/libavresample_asm.a LOCAL_SRC_FILES:= $(subst jni/,,$(LIBAVRESAMPLE_ASM_A_FILE_PATH))

include $(PREBUILT_STATIC_LIBRARY) ################################################################################ include $(CLEAR_VARS)

LOCAL_MODULE:= avutil_asm LIBAVUTIL_ASM_A_FILE_PATH:= $(LOCAL_PATH)/…/obj/local/x86/objs/avutil/ffmpeg-2.1.3/libavutil/x86/libavutil_asm.a LOCAL_SRC_FILES:= $(subst jni/,,$(LIBAVUTIL_ASM_A_FILE_PATH))

include $(PREBUILT_STATIC_LIBRARY) ################################################################################ include $(CLEAR_VARS)

LOCAL_MODULE:= swresample_asm LIBSWRESAMPLE_ASM_A_FILE_PATH:= $(LOCAL_PATH)/…/obj/local/x86/objs/swresample/ffmpeg-2.1.3/libswresample/x86/libswresample_asm.a LOCAL_SRC_FILES:= $(subst jni/,,$(LIBSWRESAMPLE_ASM_A_FILE_PATH))

include $(PREBUILT_STATIC_LIBRARY) ################################################################################ include $(CLEAR_VARS)

LOCAL_MODULE:= swscale_asm LIBSWSCALE_ASM_A_FILE_PATH:= $(LOCAL_PATH)/…/obj/local/x86/objs/swscale/ffmpeg-2.1.3/libswscale/x86/libswscale_asm.a LOCAL_SRC_FILES:= $(subst jni/,,$(LIBSWSCALE_ASM_A_FILE_PATH))

include $(PREBUILT_STATIC_LIBRARY) ################################################################################ endif

# ниже мы по-модульно собираем FFmpeg ################################################################################ # собираем модуль FFmpeg avutils.so

# это троку надо вызывать перед сборкой каждого модуля include $(CLEAR_VARS)

# в соответствующие переменные записываются пути к файлам по максам *.asm, *.c и т.д. из соответствующих папок # обратите внимание на часть пути »$(TARGET_ARCH)» — в этой пеерменной содержится имя текущей архитектуры для которой происходит компиляция # некоторые модули ffmpeg содержат код оптимизированный для каждой из архитектуры, который лежит в соответствующих папках LIBAVUTIL_LIB_ARCH_ASM_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libavutil/$(TARGET_ARCH)/*.asm) LIBAVUTIL_LIB_ARCH_C_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libavutil/$(TARGET_ARCH)/*.c) LIBAVUTIL_LIB_ARCH_S_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libavutil/$(TARGET_ARCH)/*.S) LIBAVUTIL_LIB_ASM_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libavutil/*.asm) LIBAVUTIL_LIB_C_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libavutil/*.c) LIBAVUTIL_LIB_S_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libavutil/*.S) LIBAVUTIL_LIB_CPP_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libavutil/*.cpp)

# оказалось, что в переменных выше пути к файлам для компиляции прописаны неверно и NDK ругается, что не может эти файлы найти # поэтому команды ниже просто из путей записанных в переменные удаляют строчку «jni/» это исправляет путь LIBAVUTIL_LIB_ARCH_ASM_FILES:= $(subst jni/,,$(LIBAVUTIL_LIB_ARCH_ASM_FILES)) LIBAVUTIL_LIB_ARCH_C_FILES:= $(subst jni/,,$(LIBAVUTIL_LIB_ARCH_C_FILES)) LIBAVUTIL_LIB_ARCH_S_FILES:= $(subst jni/,,$(LIBAVUTIL_LIB_ARCH_S_FILES)) LIBAVUTIL_LIB_ASM_FILES:= $(subst jni/,,$(LIBAVUTIL_LIB_ASM_FILES)) LIBAVUTIL_LIB_C_FILES:= $(subst jni/,,$(LIBAVUTIL_LIB_C_FILES)) LIBAVUTIL_LIB_S_FILES:= $(subst jni/,,$(LIBAVUTIL_LIB_S_FILES)) LIBAVUTIL_LIB_CPP_FILES:= $(subst jni/,,$(LIBAVUTIL_LIB_CPP_FILES))

# здесь подключается дополнительный make-файл, в котором прописаны файлы, которые компилировать не нужно, об этом ниже include $(LOCAL_PATH)/libavutil_ignore.mk

# собираем все файлы в одну кучу, теперь в переменной LIBAVUTIL_FILES записаны пути ко всем файлам исходников компонента avutils, которые надо скомпилировать LIBAVUTIL_FILES:= $(sort $(LIBAVUTIL_LIB_ARCH_ASM_FILES)) $(sort $(LIBAVUTIL_LIB_ARCH_C_FILES)) $(sort $(LIBAVUTIL_LIB_ARCH_S_FILES)) $(sort $(LIBAVUTIL_LIB_ASM_FILES)) $(sort $(LIBAVUTIL_LIB_C_FILES)) $(sort $(LIBAVUTIL_LIB_S_FILES)) $(sort $(LIBAVUTIL_LIB_CPP_FILES))

# здесь заполняются последовательно переменные для компиляции # список файлов для компиляции LOCAL_SRC_FILES:= $(LIBAVUTIL_FILES) # список папок с заголовочными файлами LOCAL_C_INCLUDES += $(LOCAL_PATH)/$(FFMPEG_DIR) $(LOCAL_PATH)/$(FFMPEG_DIR)/libavutil/$(TARGET_ARCH) # где-то в FFmpeg исопльзуются функции из стандартных библиотек zlib и log, этой строкой мы ее подключаем LOCAL_LDLIBS += -lz -llog # даем имя файлу, который мы получим на выходе libavutil.so LOCAL_MODULE:= avutil # самое интересное, в переменной TARGET_ARCH в момент компилирования содержится название текущей архитектуры для которой происходит компиляция # здесь мы в зависимости от архитектуры назначаем переменной LOCAL_CFLAGS нужные флаги для компиляции # большинство из них были подобраны методом проб, гугления и т.п. ifeq ($(TARGET_ARCH), arm) LOCAL_CFLAGS += -O3 -fpic -DANDROID LOCAL_ARM_MODE:= arm else ifeq ($(TARGET_ARCH), x86) LOCAL_CFLAGS += -O3 -fpic -DANDROID # здесь мы и подключаем для x86 скомпилированные с помощью yasm объектные файлы LOCAL_STATIC_LIBRARIES += avutil_asm else ifeq ($(TARGET_ARCH), mips) LOCAL_CFLAGS += -O3 -DANDROID -Wfatal-errors -Wno-deprecated -std=c99 -fomit-frame-pointer -mips32r2 -mdsp -mdspr2 -mhard-float -g -Wdeclaration-after-statement -Wall -Wno-parentheses -Wno-switch -Wno-format-zero-length -Wdisabled-optimization -Wpointer-arith -Wredundant-decls -Wno-pointer-sign -Wwrite-strings -Wtype-limits -Wundef -Wmissing-prototypes -Wno-pointer-to-int-cast -Wstrict-prototypes -fno-math-errno -fno-signed-zeros -fno-tree-vectorize -Werror=missing-prototypes -Werror=return-type -Werror=vla endif

# этой строкой мы подключаем make-файл из NDK, который компилирует нам shared-библиотеку, или *.so файл include $(BUILD_SHARED_LIBRARY) ################################################################################ # собираем модуль FFmpeg avcodec.so include $(CLEAR_VARS)

LIBAVCODEC_LIB_ARCH_ASM_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libavcodec/$(TARGET_ARCH)/*.asm) LIBAVCODEC_LIB_ARCH_C_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libavcodec/$(TARGET_ARCH)/*.c) LIBAVCODEC_LIB_ARCH_S_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libavcodec/$(TARGET_ARCH)/*.S) LIBAVCODEC_LIB_ASM_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libavcodec/*.asm) LIBAVCODEC_LIB_C_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libavcodec/*.c) LIBAVCODEC_LIB_S_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libavcodec/*.S) LIBAVCODEC_LIB_CPP_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libavcodec/*.cpp)

LIBAVCODEC_LIB_ARCH_ASM_FILES:= $(subst jni/,,$(LIBAVCODEC_LIB_ARCH_ASM_FILES)) LIBAVCODEC_LIB_ARCH_C_FILES:= $(subst jni/,,$(LIBAVCODEC_LIB_ARCH_C_FILES)) LIBAVCODEC_LIB_ARCH_S_FILES:= $(subst jni/,,$(LIBAVCODEC_LIB_ARCH_S_FILES)) LIBAVCODEC_LIB_ASM_FILES:= $(subst jni/,,$(LIBAVCODEC_LIB_ASM_FILES)) LIBAVCODEC_LIB_C_FILES:= $(subst jni/,,$(LIBAVCODEC_LIB_C_FILES)) LIBAVCODEC_LIB_S_FILES:= $(subst jni/,,$(LIBAVCODEC_LIB_S_FILES)) LIBAVCODEC_LIB_CPP_FILES:= $(subst jni/,,$(LIBAVCODEC_LIB_CPP_FILES))

include $(LOCAL_PATH)/libavcodec_ignore.mk

LIBAVCODEC_FILES:= $(sort $(LIBAVCODEC_LIB_ARCH_ASM_FILES)) $(sort $(LIBAVCODEC_LIB_ARCH_C_FILES)) $(sort $(LIBAVCODEC_LIB_ARCH_S_FILES)) $(sort $(LIBAVCODEC_LIB_ASM_FILES)) $(sort $(LIBAVCODEC_LIB_C_FILES)) $(sort $(LIBAVCODEC_LIB_S_FILES)) $(sort $(LIBAVCODEC_LIB_CPP_FILES))

LOCAL_SRC_FILES:= $(LIBAVCODEC_FILES) LOCAL_C_INCLUDES += $(LOCAL_PATH)/$(FFMPEG_DIR) $(LOCAL_PATH)/$(FFMPEG_DIR)/libavcodec $(LOCAL_PATH)/$(FFMPEG_DIR)/libavcodec/$(TARGET_ARCH) LOCAL_LDLIBS += -lz -llog # так как модули ffmpeg используют друг друга, то здесь мы добавляем для компиляции и сборки каждого следующего модуля предыдущий уже скопилированный, # это надо, чтобы линковщик не ругался при сборке, что не может найти какие-то функции LOCAL_SHARED_LIBRARIES += libavutil LOCAL_MODULE:= avcodec ifeq ($(TARGET_ARCH), arm) LOCAL_CFLAGS += -O3 -fpic -DANDROID LOCAL_ARM_MODE:= arm else ifeq ($(TARGET_ARCH), x86) LOCAL_CFLAGS += -O3 -fno-pic -DANDROID LOCAL_STATIC_LIBRARIES += avutil_asm avcodec_asm LOCAL_SHARED_LIBRARIES += libavutil_asm libavcodec_asm else ifeq ($(TARGET_ARCH), mips) LOCAL_CFLAGS += -O3 -DANDROID -Wfatal-errors -Wno-deprecated -std=c99 -fomit-frame-pointer -mips32r2 -mdsp -mdspr2 -mhard-float -g -Wdeclaration-after-statement -Wall -Wno-parentheses -Wno-switch -Wno-format-zero-length -Wdisabled-optimization -Wpointer-arith -Wredundant-decls -Wno-pointer-sign -Wwrite-strings -Wtype-limits -Wundef -Wmissing-prototypes -Wno-pointer-to-int-cast -Wstrict-prototypes -fno-math-errno -fno-signed-zeros -fno-tree-vectorize -Werror=missing-prototypes -Werror=return-type -Werror=vla endif

include $(BUILD_SHARED_LIBRARY) ################################################################################ # собираем модуль FFmpeg avformat.so include $(CLEAR_VARS)

LIBAVFORMAT_LIB_ARCH_ASM_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libavformat/$(TARGET_ARCH)/*.asm) LIBAVFORMAT_LIB_ARCH_C_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libavformat/$(TARGET_ARCH)/*.c) LIBAVFORMAT_LIB_ARCH_S_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libavformat/$(TARGET_ARCH)/*.S) LIBAVFORMAT_LIB_ASM_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libavformat/*.asm) LIBAVFORMAT_LIB_C_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libavformat/*.c) LIBAVFORMAT_LIB_S_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libavformat/*.S) LIBAVFORMAT_LIB_CPP_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libavformat/*.cpp)

LIBAVFORMAT_LIB_ARCH_ASM_FILES:= $(subst jni/,,$(LIBAVFORMAT_LIB_ARCH_ASM_FILES)) LIBAVFORMAT_LIB_ARCH_C_FILES:= $(subst jni/,,$(LIBAVFORMAT_LIB_ARCH_C_FILES)) LIBAVFORMAT_LIB_ARCH_S_FILES:= $(subst jni/,,$(LIBAVFORMAT_LIB_ARCH_S_FILES)) LIBAVFORMAT_LIB_ASM_FILES:= $(subst jni/,,$(LIBAVFORMAT_LIB_ASM_FILES)) LIBAVFORMAT_LIB_C_FILES:= $(subst jni/,,$(LIBAVFORMAT_LIB_C_FILES)) LIBAVFORMAT_LIB_S_FILES:= $(subst jni/,,$(LIBAVFORMAT_LIB_S_FILES)) LIBAVFORMAT_LIB_CPP_FILES:= $(subst jni/,,$(LIBAVFORMAT_LIB_CPP_FILES))

include $(LOCAL_PATH)/libavformat_ignore.mk

LIBAVFORMAT_FILES:= $(sort $(LIBAVFORMAT_LIB_ARCH_ASM_FILES)) $(sort $(LIBAVFORMAT_LIB_ARCH_C_FILES)) $(sort $(LIBAVFORMAT_LIB_ARCH_S_FILES)) $(sort $(LIBAVFORMAT_LIB_ASM_FILES)) $(sort $(LIBAVFORMAT_LIB_C_FILES)) $(sort $(LIBAVFORMAT_LIB_S_FILES)) $(sort $(LIBAVFORMAT_LIB_CPP_FILES))

LOCAL_SRC_FILES:= $(LIBAVFORMAT_FILES) LOCAL_C_INCLUDES += $(LOCAL_PATH)/$(FFMPEG_DIR) $(LOCAL_PATH)/$(FFMPEG_DIR)/libavformat $(LOCAL_PATH)/$(FFMPEG_DIR)/libavformat/$(TARGET_ARCH) LOCAL_LDLIBS += -lz -llog LOCAL_SHARED_LIBRARIES += libavutil libavcodec LOCAL_MODULE:= avformat ifeq ($(TARGET_ARCH), arm) LOCAL_CFLAGS += -O3 -fpic -DANDROID LOCAL_ARM_MODE:= arm else ifeq ($(TARGET_ARCH), x86) LOCAL_CFLAGS += -O3 -fpic -DANDROID else ifeq ($(TARGET_ARCH), mips) LOCAL_CFLAGS += -O3 -DANDROID -Wfatal-errors -Wno-deprecated -std=c99 -fomit-frame-pointer -mips32r2 -mdsp -mdspr2 -mhard-float -g -Wdeclaration-after-statement -Wall -Wno-parentheses -Wno-switch -Wno-format-zero-length -Wdisabled-optimization -Wpointer-arith -Wredundant-decls -Wno-pointer-sign -Wwrite-strings -Wtype-limits -Wundef -Wmissing-prototypes -Wno-pointer-to-int-cast -Wstrict-prototypes -fno-math-errno -fno-signed-zeros -fno-tree-vectorize -Werror=missing-prototypes -Werror=return-type -Werror=vla endif

include $(BUILD_SHARED_LIBRARY) ################################################################################ # собираем модуль FFmpeg swscale.so include $(CLEAR_VARS)

LIBSWSCALE_LIB_ARCH_ASM_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libswscale/$(TARGET_ARCH)/*.asm) LIBSWSCALE_LIB_ARCH_C_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libswscale/$(TARGET_ARCH)/*.c) LIBSWSCALE_LIB_ARCH_S_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libswscale/$(TARGET_ARCH)/*.S) LIBSWSCALE_LIB_ASM_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libswscale/*.asm) LIBSWSCALE_LIB_C_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libswscale/*.c) LIBSWSCALE_LIB_S_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libswscale/*.S) LIBSWSCALE_LIB_CPP_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libswscale/*.cpp)

LIBSWSCALE_LIB_ARCH_ASM_FILES:= $(subst jni/,,$(LIBSWSCALE_LIB_ARCH_ASM_FILES)) LIBSWSCALE_LIB_ARCH_C_FILES:= $(subst jni/,,$(LIBSWSCALE_LIB_ARCH_C_FILES)) LIBSWSCALE_LIB_ARCH_S_FILES:= $(subst jni/,,$(LIBSWSCALE_LIB_ARCH_S_FILES)) LIBSWSCALE_LIB_ASM_FILES:= $(subst jni/,,$(LIBSWSCALE_LIB_ASM_FILES)) LIBSWSCALE_LIB_C_FILES:= $(subst jni/,,$(LIBSWSCALE_LIB_C_FILES)) LIBSWSCALE_LIB_S_FILES:= $(subst jni/,,$(LIBSWSCALE_LIB_S_FILES)) LIBSWSCALE_LIB_CPP_FILES:= $(subst jni/,,$(LIBSWSCALE_LIB_CPP_FILES))

include $(LOCAL_PATH)/libswscale_ignore.mk

LIBSWSCALE_FILES:= $(sort $(LIBSWSCALE_LIB_ARCH_ASM_FILES)) $(sort $(LIBSWSCALE_LIB_ARCH_C_FILES)) $(sort $(LIBSWSCALE_LIB_ARCH_S_FILES)) $(sort $(LIBSWSCALE_LIB_ASM_FILES)) $(sort $(LIBSWSCALE_LIB_C_FILES)) $(sort $(LIBSWSCALE_LIB_S_FILES)) $(sort $(LIBSWSCALE_LIB_CPP_FILES))

LOCAL_SRC_FILES:= $(LIBSWSCALE_FILES) LOCAL_C_INCLUDES += $(LOCAL_PATH)/$(FFMPEG_DIR) $(LOCAL_PATH)/$(FFMPEG_DIR)/libswscale $(LOCAL_PATH)/$(FFMPEG_DIR)/libswscale/$(TARGET_ARCH) LOCAL_LDLIBS += -lz -llog LOCAL_SHARED_LIBRARIES += libavutil LOCAL_MODULE:= swscale ifeq ($(TARGET_ARCH), arm) LOCAL_CFLAGS += -O3 -fpic -DANDROID LOCAL_ARM_MODE:= arm else ifeq ($(TARGET_ARCH), x86) LOCAL_CFLAGS += -O3 -fno-pic -DANDROID LOCAL_STATIC_LIBRARIES += avutil_asm swscale_asm else ifeq ($(TARGET_ARCH), mips) LOCAL_CFLAGS += -O3 -DANDROID -Wfatal-errors -Wno-deprecated -std=c99 -fomit-frame-pointer -mips32r2 -mdsp -mdspr2 -mhard-float -g -Wdeclaration-after-statement -Wall -Wno-parentheses -Wno-switch -Wno-format-zero-length -Wdisabled-optimization -Wpointer-arith -Wredundant-decls -Wno-pointer-sign -Wwrite-strings -Wtype-limits -Wundef -Wmissing-prototypes -Wno-pointer-to-int-cast -Wstrict-prototypes -fno-math-errno -fno-signed-zeros -fno-tree-vectorize -Werror=missing-prototypes -Werror=return-type -Werror=vla endif

include $(BUILD_SHARED_LIBRARY) ################################################################################ # собираем модуль FFmpeg postproc.so include $(CLEAR_VARS)

LIBPOSTPROC_LIB_ARCH_ASM_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libpostproc/$(TARGET_ARCH)/*.asm) LIBPOSTPROC_LIB_ARCH_C_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libpostproc/$(TARGET_ARCH)/*.c) LIBPOSTPROC_LIB_ARCH_S_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libpostproc/$(TARGET_ARCH)/*.S) LIBPOSTPROC_LIB_ASM_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libpostproc/*.asm) LIBPOSTPROC_LIB_C_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libpostproc/*.c) LIBPOSTPROC_LIB_S_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libpostproc/*.S) LIBPOSTPROC_LIB_CPP_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libpostproc/*.cpp)

LIBPOSTPROC_LIB_ARCH_ASM_FILES:= $(subst jni/,,$(LIBPOSTPROC_LIB_ARCH_ASM_FILES)) LIBPOSTPROC_LIB_ARCH_C_FILES:= $(subst jni/,,$(LIBPOSTPROC_LIB_ARCH_C_FILES)) LIBPOSTPROC_LIB_ARCH_S_FILES:= $(subst jni/,,$(LIBPOSTPROC_LIB_ARCH_S_FILES)) LIBPOSTPROC_LIB_ASM_FILES:= $(subst jni/,,$(LIBPOSTPROC_LIB_ASM_FILES)) LIBPOSTPROC_LIB_C_FILES:= $(subst jni/,,$(LIBPOSTPROC_LIB_C_FILES)) LIBPOSTPROC_LIB_S_FILES:= $(subst jni/,,$(LIBPOSTPROC_LIB_S_FILES)) LIBPOSTPROC_LIB_CPP_FILES:= $(subst jni/,,$(LIBPOSTPROC_LIB_CPP_FILES))

include $(LOCAL_PATH)/libpostproc_ignore.mk

LIBPOSTPROC_FILES:= $(sort $(LIBPOSTPROC_LIB_ARCH_ASM_FILES)) $(sort $(LIBPOSTPROC_LIB_ARCH_C_FILES)) $(sort $(LIBPOSTPROC_LIB_ARCH_S_FILES)) $(sort $(LIBPOSTPROC_LIB_ASM_FILES)) $(sort $(LIBPOSTPROC_LIB_C_FILES)) $(sort $(LIBPOSTPROC_LIB_S_FILES)) $(sort $(LIBPOSTPROC_LIB_CPP_FILES))

LOCAL_SRC_FILES:= $(LIBPOSTPROC_FILES) LOCAL_C_INCLUDES += $(LOCAL_PATH)/$(FFMPEG_DIR) $(LOCAL_PATH)/$(FFMPEG_DIR)/libpostproc $(LOCAL_PATH)/$(FFMPEG_DIR)/libpostproc/$(TARGET_ARCH) LOCAL_LDLIBS += -lz -llog LOCAL_SHARED_LIBRARIES += libavutil LOCAL_MODULE:= postproc ifeq ($(TARGET_ARCH), arm) LOCAL_CFLAGS += -O3 -fpic -DANDROID LOCAL_ARM_MODE:= arm else ifeq ($(TARGET_ARCH), x86) LOCAL_CFLAGS += -O3 -fno-pic -DANDROID else ifeq ($(TARGET_ARCH), mips) LOCAL_CFLAGS += -O3 -DANDROID -Wfatal-errors -Wno-deprecated -std=c99 -fomit-frame-pointer -mips32r2 -mdsp -mdspr2 -mhard-float -g -Wdeclaration-after-statement -Wall -Wno-parentheses -Wno-switch -Wno-format-zero-length -Wdisabled-optimization -Wpointer-arith -Wredundant-decls -Wno-pointer-sign -Wwrite-strings -Wtype-limits -Wundef -Wmissing-prototypes -Wno-pointer-to-int-cast -Wstrict-prototypes -fno-math-errno -fno-signed-zeros -fno-tree-vectorize -Werror=missing-prototypes -Werror=return-type -Werror=vla endif

include $(BUILD_SHARED_LIBRARY) ################################################################################ # собираем модуль FFmpeg swresample.so include $(CLEAR_VARS)

LIBSWRESAMPLE_LIB_ARCH_ASM_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libswresample/$(TARGET_ARCH)/*.asm) LIBSWRESAMPLE_LIB_ARCH_C_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libswresample/$(TARGET_ARCH)/*.c) LIBSWRESAMPLE_LIB_ARCH_S_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libswresample/$(TARGET_ARCH)/*.S) LIBSWRESAMPLE_LIB_ASM_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libswresample/*.asm) LIBSWRESAMPLE_LIB_C_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libswresample/*.c) LIBSWRESAMPLE_LIB_S_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libswresample/*.S) LIBSWRESAMPLE_LIB_CPP_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libswresample/*.cpp)

LIBSWRESAMPLE_LIB_ARCH_ASM_FILES:= $(subst jni/,,$(LIBSWRESAMPLE_LIB_ARCH_ASM_FILES)) LIBSWRESAMPLE_LIB_ARCH_C_FILES:= $(subst jni/,,$(LIBSWRESAMPLE_LIB_ARCH_C_FILES)) LIBSWRESAMPLE_LIB_ARCH_S_FILES:= $(subst jni/,,$(LIBSWRESAMPLE_LIB_ARCH_S_FILES)) LIBSWRESAMPLE_LIB_ASM_FILES:= $(subst jni/,,$(LIBSWRESAMPLE_LIB_ASM_FILES)) LIBSWRESAMPLE_LIB_C_FILES:= $(subst jni/,,$(LIBSWRESAMPLE_LIB_C_FILES)) LIBSWRESAMPLE_LIB_S_FILES:= $(subst jni/,,$(LIBSWRESAMPLE_LIB_S_FILES)) LIBSWRESAMPLE_LIB_CPP_FILES:= $(subst jni/,,$(LIBSWRESAMPLE_LIB_CPP_FILES))

include $(LOCAL_PATH)/libswresample_ignore.mk

LIBSWRESAMPLE_FILES:= $(sort $(LIBSWRESAMPLE_LIB_ARCH_ASM_FILES)) $(sort $(LIBSWRESAMPLE_LIB_ARCH_C_FILES)) $(sort $(LIBSWRESAMPLE_LIB_ARCH_S_FILES)) $(sort $(LIBSWRESAMPLE_LIB_ASM_FILES)) $(sort $(LIBSWRESAMPLE_LIB_C_FILES)) $(sort $(LIBSWRESAMPLE_LIB_S_FILES)) $(sort $(LIBSWRESAMPLE_LIB_CPP_FILES))

LOCAL_SRC_FILES:= $(LIBSWRESAMPLE_FILES) LOCAL_C_INCLUDES += $(LOCAL_PATH)/$(FFMPEG_DIR) $(LOCAL_PATH)/$(FFMPEG_DIR)/libswresample $(LOCAL_PATH)/$(FFMPEG_DIR)/libswresample/$(TARGET_ARCH) LOCAL_LDLIBS += -lz -llog LOCAL_SHARED_LIBRARIES += libavutil LOCAL_MODULE:= swresample ifeq ($(TARGET_ARCH), arm) LOCAL_CFLAGS += -O3 -fpic -DANDROID LOCAL_ARM_MODE:= arm else ifeq ($(TARGET_ARCH), x86) LOCAL_CFLAGS += -O3 -fpic -DANDROID LOCAL_STATIC_LIBRARIES += avutil_asm swresample_asm else ifeq ($(TARGET_ARCH), mips) LOCAL_CFLAGS += -O3 -DANDROID -Wfatal-errors -Wno-deprecated -std=c99 -fomit-frame-pointer -mips32r2 -mdsp -mdspr2 -mhard-float -g -Wdeclaration-after-statement -Wall -Wno-parentheses -Wno-switch -Wno-format-zero-length -Wdisabled-optimization -Wpointer-arith -Wredundant-decls -Wno-pointer-sign -Wwrite-strings -Wtype-limits -Wundef -Wmissing-prototypes -Wno-pointer-to-int-cast -Wstrict-prototypes -fno-math-errno -fno-signed-zeros -fno-tree-vectorize -Werror=missing-prototypes -Werror=return-type -Werror=vla endif

include $(BUILD_SHARED_LIBRARY) ################################################################################ # собираем модуль FFmpeg avresample.so include $(CLEAR_VARS)

LIBAVRESAMPLE_LIB_ARCH_ASM_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libavresample/$(TARGET_ARCH)/*.asm) LIBAVRESAMPLE_LIB_ARCH_C_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libavresample/$(TARGET_ARCH)/*.c) LIBAVRESAMPLE_LIB_ARCH_S_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libavresample/$(TARGET_ARCH)/*.S) LIBAVRESAMPLE_LIB_ASM_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libavresample/*.asm) LIBAVRESAMPLE_LIB_C_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libavresample/*.c) LIBAVRESAMPLE_LIB_S_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libavresample/*.S) LIBAVRESAMPLE_LIB_CPP_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libavresample/*.cpp)

LIBAVRESAMPLE_LIB_ARCH_ASM_FILES:= $(subst jni/,,$(LIBAVRESAMPLE_LIB_ARCH_ASM_FILES)) LIBAVRESAMPLE_LIB_ARCH_C_FILES:= $(subst jni/,,$(LIBAVRESAMPLE_LIB_ARCH_C_FILES)) LIBAVRESAMPLE_LIB_ARCH_S_FILES:= $(subst jni/,,$(LIBAVRESAMPLE_LIB_ARCH_S_FILES)) LIBAVRESAMPLE_LIB_ASM_FILES:= $(subst jni/,,$(LIBAVRESAMPLE_LIB_ASM_FILES)) LIBAVRESAMPLE_LIB_C_FILES:= $(subst jni/,,$(LIBAVRESAMPLE_LIB_C_FILES)) LIBAVRESAMPLE_LIB_S_FILES:= $(subst jni/,,$(LIBAVRESAMPLE_LIB_S_FILES)) LIBAVRESAMPLE_LIB_CPP_FILES:= $(subst jni/,,$(LIBAVRESAMPLE_LIB_CPP_FILES))

include $(LOCAL_PATH)/libavresample_ignore.mk

LIBAVRESAMPLE_FILES:= $(sort $(LIBAVRESAMPLE_LIB_ARCH_ASM_FILES)) $(sort $(LIBAVRESAMPLE_LIB_ARCH_C_FILES)) $(sort $(LIBAVRESAMPLE_LIB_ARCH_S_FILES)) $(sort $(LIBAVRESAMPLE_LIB_ASM_FILES)) $(sort $(LIBAVRESAMPLE_LIB_C_FILES)) $(sort $(LIBAVRESAMPLE_LIB_S_FILES)) $(sort $(LIBAVRESAMPLE_LIB_CPP_FILES))

LOCAL_SRC_FILES:= $(LIBAVRESAMPLE_FILES) LOCAL_C_INCLUDES += $(LOCAL_PATH)/$(FFMPEG_DIR) $(LOCAL_PATH)/$(FFMPEG_DIR)/libavresample $(LOCAL_PATH)/$(FFMPEG_DIR)/libavresample/$(TARGET_ARCH) LOCAL_LDLIBS += -lz -llog LOCAL_SHARED_LIBRARIES += libavutil LOCAL_MODULE:= avresample ifeq ($(TARGET_ARCH), arm) LOCAL_CFLAGS += -O3 -fpic -DANDROID LOCAL_ARM_MODE:= arm else ifeq ($(TARGET_ARCH), x86) LOCAL_CFLAGS += -O3 -fpic -DANDROID LOCAL_STATIC_LIBRARIES += avutil_asm avresample_asm else ifeq ($(TARGET_ARCH), mips) LOCAL_CFLAGS += -O3 -DANDROID -Wfatal-errors -Wno-deprecated -std=c99 -fomit-frame-pointer -mips32r2 -mdsp -mdspr2 -mhard-float -g -Wdeclaration-after-statement -Wall -Wno-parentheses -Wno-switch -Wno-format-zero-length -Wdisabled-optimization -Wpointer-arith -Wredundant-decls -Wno-pointer-sign -Wwrite-strings -Wtype-limits -Wundef -Wmissing-prototypes -Wno-pointer-to-int-cast -Wstrict-prototypes -fno-math-errno -fno-signed-zeros -fno-tree-vectorize -Werror=missing-prototypes -Werror=return-type -Werror=vla endif

include $(BUILD_SHARED_LIBRARY) ################################################################################ # собираем модуль OpenCV include $(CLEAR_VARS)

OPENCV_CAMERA_MODULES:= off OPENCV_INSTALL_MODULES:= on

include $(OPENCVROOT)/sdk/native/jni/OpenCV.mk ################################################################################ # собираем модуль FFmpeg avfilter.so include $(CLEAR_VARS)

LIBAVFILTER_LIB_ARCH_ASM_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libavfilter/$(TARGET_ARCH)/*.asm) LIBAVFILTER_LIB_ARCH_C_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libavfilter/$(TARGET_ARCH)/*.c) LIBAVFILTER_LIB_ARCH_S_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libavfilter/$(TARGET_ARCH)/*.S) LIBAVFILTER_LIB_ASM_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libavfilter/*.asm) LIBAVFILTER_LIB_C_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libavfilter/*.c) LIBAVFILTER_LIB_S_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libavfilter/*.S) LIBAVFILTER_LIB_CPP_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libavfilter/*.cpp) LIBAVFILTER_LIB_EX_C_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libavfilter/libmpcodecs/*.c)

LIBAVFILTER_LIB_ARCH_ASM_FILES:= $(subst jni/,,$(LIBAVFILTER_LIB_ARCH_ASM_FILES)) LIBAVFILTER_LIB_ARCH_C_FILES:= $(subst jni/,,$(LIBAVFILTER_LIB_ARCH_C_FILES)) LIBAVFILTER_LIB_ARCH_S_FILES:= $(subst jni/,,$(LIBAVFILTER_LIB_ARCH_S_FILES)) LIBAVFILTER_LIB_ASM_FILES:= $(subst jni/,,$(LIBAVFILTER_LIB_ASM_FILES)) LIBAVFILTER_LIB_C_FILES:= $(subst jni/,,$(LIBAVFILTER_LIB_C_FILES)) LIBAVFILTER_LIB_S_FILES:= $(subst jni/,,$(LIBAVFILTER_LIB_S_FILES)) LIBAVFILTER_LIB_CPP_FILES:= $(subst jni/,,$(LIBAVFILTER_LIB_CPP_FILES)) LIBAVFILTER_LIB_EX_C_FILES:= $(subst jni/,,$(LIBAVFILTER_LIB_EX_C_FILES))

include $(LOCAL_PATH)/libavfilter_ignore.mk

LIBAVFILTER_FILES:= $(sort $(LIBAVFILTER_LIB_ARCH_ASM_FILES)) $(sort $(LIBAVFILTER_LIB_ARCH_C_FILES)) $(sort $(LIBAVFILTER_LIB_ARCH_S_FILES)) $(sort $(LIBAVFILTER_LIB_ASM_FILES)) $(sort $(LIBAVFILTER_LIB_C_FILES)) $(sort $(LIBAVFILTER_LIB_S_FILES)) $(sort $(LIBAVFILTER_LIB_CPP_FILES)) $(sort $(LIBAVFILTER_LIB_EX_C_FILES))

LOCAL_SRC_FILES:= $(LIBAVFILTER_FILES) LOCAL_C_INCLUDES += $(OPENCVROOT)/sdk/native/jni/include $(LOCAL_PATH)/$(FFMPEG_DIR) $(LOCAL_PATH)/$(FFMPEG_DIR)/libavfilter $(LOCAL_PATH)/$(FFMPEG_DIR)/libavfilter/$(TARGET_ARCH) $(LOCAL_PATH)/$(FFMPEG_DIR)/libavfilter/libmpcodecs $(LOCAL_PATH)/$(FFMPEG_DIR)/libavfilter/libmpcodecs/libvo LOCAL_LDLIBS += -lz -llog LOCAL_SHARED_LIBRARIES += libavutil libavcodec libavformat libswresample libpostproc libswscale libavresample libopencv_java LOCAL_MODULE:= avfilter ifeq ($(TARGET_ARCH), arm) LOCAL_CFLAGS += -D__STDC_CONSTANT_MACROS -O3 -fpic -DANDROID LOCAL_ARM_MODE:= arm else ifeq ($(TARGET_ARCH), x86) LOCAL_CFLAGS += -D__STDC_CONSTANT_MACROS -O3 -fno-pic -DANDROID LOCAL_STATIC_LIBRARIES += avutil_asm avfilter_asm else ifeq ($(TARGET_ARCH), mips) LOCAL_CFLAGS += -D__STDC_CONSTANT_MACROS -O3 -DANDROID -Wfatal-errors -Wno-deprecated -std=c99 -fomit-frame-pointer -mips32r2 -mdsp -mdspr2 -mhard-float -g -Wdeclaration-after-statement -Wall -Wno-parentheses -Wno-switch -Wno-format-zero-length -Wdisabled-optimization -Wpointer-arith -Wredundant-decls -Wno-pointer-sign -Wwrite-strings -Wtype-limits -Wundef -Wmissing-prototypes -Wno-pointer-to-int-cast -Wstrict-prototypes -fno-math-errno -fno-signed-zeros -fno-tree-vectorize -Werror=missing-prototypes -Werror=return-type -Werror=vla endif

include $(BUILD_SHARED_LIBRARY) ################################################################################ # собираем модуль FFmpeg avdevice.so include $(CLEAR_VARS)

LIBAVDEVICE_LIB_ARCH_ASM_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libavdevice/$(TARGET_ARCH)/*.asm) LIBAVDEVICE_LIB_ARCH_C_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libavdevice/$(TARGET_ARCH)/*.c) LIBAVDEVICE_LIB_ARCH_S_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libavdevice/$(TARGET_ARCH)/*.S) LIBAVDEVICE_LIB_ASM_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libavdevice/*.asm) LIBAVDEVICE_LIB_C_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libavdevice/*.c) LIBAVDEVICE_LIB_S_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libavdevice/*.S) LIBAVDEVICE_LIB_CPP_FILES:= $(wildcard $(LOCAL_PATH)/$(FFMPEG_DIR)/libavdevice/*.cpp)

LIBAVDEVICE_LIB_ARCH_ASM_FILES:= $(subst jni/,,$(LIBAVDEVICE_LIB_ARCH_ASM_FILES)) LIBAVDEVICE_LIB_ARCH_C_FILES:= $(subst jni/,,$(LIBAVDEVICE_LIB_ARCH_C_FILES)) LIBAVDEVICE_LIB_ARCH_S_FILES:= $(subst jni/,,$(LIBAVDEVICE_LIB_ARCH_S_FILES)) LIBAVDEVICE_LIB_ASM_FILES:= $(subst jni/,,$(LIBAVDEVICE_LIB_ASM_FILES)) LIBAVDEVICE_LIB_C_FILES:= $(subst jni/,,$(LIBAVDEVICE_LIB_C_FILES)) LIBAVDEVICE_LIB_S_FILES:= $(subst jni/,,$(LIBAVDEVICE_LIB_S_FILES)) LIBAVDEVICE_LIB_CPP_FILES:= $(subst jni/,,$(LIBAVDEVICE_LIB_CPP_FILES))

include $(LOCAL_PATH)/libavdevice_ignore.mk

LIBAVDEVICE_FILES:= $(sort $(LIBAVDEVICE_LIB_ARCH_ASM_FILES)) $(sort $(LIBAVDEVICE_LIB_ARCH_C_FILES)) $(sort $(LIBAVDEVICE_LIB_ARCH_S_FILES)) $(sort $(LIBAVDEVICE_LIB_ASM_FILES)) $(sort $(LIBAVDEVICE_LIB_C_FILES)) $(sort $(LIBAVDEVICE_LIB_S_FILES)) $(sort $(LIBAVDEVICE_LIB_CPP_FILES))

LOCAL_SRC_FILES:= $(LIBAVDEVICE_FILES) LOCAL_C_INCLUDES += $(LOCAL_PATH)/$(FFMPEG_DIR) $(LOCAL_PATH)/$(FFMPEG_DIR)/libavdevice $(LOCAL_PATH)/$(FFMPEG_DIR)/libavdevice/$(TARGET_ARCH) LOCAL_LDLIBS += -lz -llog LOCAL_SHARED_LIBRARIES += libavutil libavcodec libavformat libavfilter LOCAL_MODULE:= avdevice ifeq ($(TARGET_ARCH), arm) LOCAL_CFLAGS += -O3 -fpic -DANDROID LOCAL_ARM_MODE:= arm else ifeq ($(TARGET_ARCH), x86) LOCAL_CFLAGS += -O3 -fpic -DANDROID else ifeq ($(TARGET_ARCH), mips) LOCAL_CFLAGS += -O3 -DANDROID -Wfatal-errors -Wno-deprecated -std=c99 -fomit-frame-pointer -mips32r2 -mdsp -mdspr2 -mhard-float -g -Wdeclaration-after-statement -Wall -Wno-parentheses -Wno-switch -Wno-format-zero-length -Wdisabled-optimization -Wpointer-arith -Wredundant-decls -Wno-pointer-sign -Wwrite-strings -Wtype-limits -Wundef -Wmissing-prototypes -Wno-pointer-to-int-cast -Wstrict-prototypes -fno-math-errno -fno-signed-zeros -fno-tree-vectorize -Werror=missing-prototypes -Werror=return-type -Werror=vla endif

include $(BUILD_SHARED_LIBRARY) ################################################################################ # собираем ffmpeg.exe программу как *.so файл include $(CLEAR_VARS)

LOCAL_SRC_FILES:= $(subst jni/,,$(LOCAL_PATH)/$(FFMPEG_DIR)/cmdutils.c) $(subst jni/,,$(LOCAL_PATH)/$(FFMPEG_DIR)/ffmpeg.c) $(subst jni/,,$(LOCAL_PATH)/$(FFMPEG_DIR)/ffmpeg_opt.c) $(subst jni/,,$(LOCAL_PATH)/$(FFMPEG_DIR)/ffmpeg_filter.c) LOCAL_C_INCLUDES += $(LOCAL_PATH)/$(FFMPEG_DIR) $(OPENCVROOT)/sdk/native/jni/include LOCAL_LDLIBS += -llog -ldl LOCAL_SHARED_LIBRARIES += libavcodec libavfilter libavformat libavresample libavutil libpostproc libswresample libswscale libopencv_java LOCAL_MODULE:= ffmpeg ifeq ($(TARGET_ARCH), arm) LOCAL_CFLAGS += -D__STDC_CONSTANT_MACROS -O3 -DANDROID -DCONFIG_ARM_ARCH -fpic LOCAL_ARM_MODE:= arm else ifeq ($(TARGET_ARCH), x86) LOCAL_CFLAGS += -D__STDC_CONSTANT_MACROS -O3 -DANDROID -DCONFIG_X86_ARCH -fpic else ifeq ($(TARGET_ARCH), mips) LOCAL_CFLAGS += -D__STDC_CONSTANT_MACROS -O3 -DANDROID -Wfatal-errors -Wno-deprecated -std=c99 -fomit-frame-pointer -mips32r2 -mdsp -mdspr2 -mhard-float -g -Wdeclaration-after-statement -Wall -Wno-parentheses -Wno-switch -Wno-format-zero-length -Wdisabled-optimization -Wpointer-arith -Wredundant-decls -Wno-pointer-sign -Wwrite-strings -Wtype-limits -Wundef -Wmissing-prototypes -Wno-pointer-to-int-cast -Wstrict-prototypes -fno-math-errno -fno-signed-zeros -fno-tree-vectorize -Werror=return-type -Werror=vla endif

include $(BUILD_SHARED_LIBRARY) Application.mk — настраиваем целевую платформу # говорим, в каком виде будем использовать STL APP_STL:= gnustl_static # общие для всех флаги APP_CPPFLAGS:= -frtti -fexceptions # можно собрать для каждой архитектуры вместе, перечислив через пробел, например: «APP_ABI:= armeabi x86 mips» #, но здесь мы собираем отдельно для каждой архитектуры APP_ABI:= armeabi # APP_ABI:= x86 # APP_ABI:= mips APP_PLATFORM:= android-9 libavfilter_ignore.mk — пример одного из подключаемых файлов в котором прописаны файлы, которые не должны компилироваться # игнорируем следующие файлы: af_ladspa.c, asrc_flite.c, deshake_opencl.c, f_zmq.c, unsharp_opencl.c, unsharp_opencl_kernel.c, vf_drawtext.c, vf_frei0r.c, vf_libopencv.c, vf_subtitles.c, vf_vidstabdetect.c, vf_vidstabtransform.c, vidstabutils.c

LIBAVFILTER_LIB_FILEPATH_af_ladspa_c:= $(FFMPEG_DIR)/libavfilter/af_ladspa.c LIBAVFILTER_LIB_C_FILES:= $(subst $(LIBAVFILTER_LIB_FILEPATH_af_ladspa_c),,$(LIBAVFILTER_LIB_C_FILES))

LIBAVFILTER_LIB_FILEPATH_asrc_flite_c:= $(FFMPEG_DIR)/libavfilter/asrc_flite.c LIBAVFILTER_LIB_C_FILES:= $(subst $(LIBAVFILTER_LIB_FILEPATH_asrc_flite_c),,$(LIBAVFILTER_LIB_C_FILES))

LIBAVFILTER_LIB_FILEPATH_deshake_opencl_c:= $(FFMPEG_DIR)/libavfilter/deshake_opencl.c LIBAVFILTER_LIB_C_FILES:= $(subst $(LIBAVFILTER_LIB_FILEPATH_deshake_opencl_c),,$(LIBAVFILTER_LIB_C_FILES))

LIBAVFILTER_LIB_FILEPATH_f_zmq_c:= $(FFMPEG_DIR)/libavfilter/f_zmq.c LIBAVFILTER_LIB_C_FILES:= $(subst $(LIBAVFILTER_LIB_FILEPATH_f_zmq_c),,$(LIBAVFILTER_LIB_C_FILES))

LIBAVFILTER_LIB_FILEPATH_unsharp_opencl_c:= $(FFMPEG_DIR)/libavfilter/unsharp_opencl.c LIBAVFILTER_LIB_C_FILES:= $(subst $(LIBAVFILTER_LIB_FILEPATH_unsharp_opencl_c),,$(LIBAVFILTER_LIB_C_FILES))

LIBAVFILTER_LIB_FILEPATH_unsharp_opencl_kernel_c:= $(FFMPEG_DIR)/libavfilter/unsharp_opencl_kernel.c LIBAVFILTER_LIB_C_FILES:= $(subst $(LIBAVFILTER_LIB_FILEPATH_unsharp_opencl_kernel_c),,$(LIBAVFILTER_LIB_C_FILES))

LIBAVFILTER_LIB_FILEPATH_vf_drawtext_c:= $(FFMPEG_DIR)/libavfilter/vf_drawtext.c LIBAVFILTER_LIB_C_FILES:= $(subst $(LIBAVFILTER_LIB_FILEPATH_vf_drawtext_c),,$(LIBAVFILTER_LIB_C_FILES))

LIBAVFILTER_LIB_FILEPATH_vf_frei0r_c:= $(FFMPEG_DIR)/libavfilter/vf_frei0r.c LIBAVFILTER_LIB_C_FILES:= $(subst $(LIBAVFILTER_LIB_FILEPATH_vf_frei0r_c),,$(LIBAVFILTER_LIB_C_FILES))

LIBAVFILTER_LIB_FILEPATH_vf_libopencv_c:= $(FFMPEG_DIR)/libavfilter/vf_libopencv.c LIBAVFILTER_LIB_C_FILES:= $(subst $(LIBAVFILTER_LIB_FILEPATH_vf_libopencv_c),,$(LIBAVFILTER_LIB_C_FILES))

LIBAVFILTER_LIB_FILEPATH_vf_subtitles_c:= $(FFMPEG_DIR)/libavfilter/vf_subtitles.c LIBAVFILTER_LIB_C_FILES:= $(subst $(LIBAVFILTER_LIB_FILEPATH_vf_subtitles_c),,$(LIBAVFILTER_LIB_C_FILES))

LIBAVFILTER_LIB_FILEPATH_vf_vidstabdetect_c:= $(FFMPEG_DIR)/libavfilter/vf_vidstabdetect.c LIBAVFILTER_LIB_C_FILES:= $(subst $(LIBAVFILTER_LIB_FILEPATH_vf_vidstabdetect_c),,$(LIBAVFILTER_LIB_C_FILES))

LIBAVFILTER_LIB_FILEPATH_vf_vidstabtransform_c:= $(FFMPEG_DIR)/libavfilter/vf_vidstabtransform.c LIBAVFILTER_LIB_C_FILES:= $(subst $(LIBAVFILTER_LIB_FILEPATH_vf_vidstabtransform_c),,$(LIBAVFILTER_LIB_C_FILES))

LIBAVFILTER_LIB_FILEPATH_vidstabutils_c:= $(FFMPEG_DIR)/libavfilter/vidstabutils.c LIBAVFILTER_LIB_C_FILES:= $(subst $(LIBAVFILTER_LIB_FILEPATH_vidstabutils_c),,$(LIBAVFILTER_LIB_C_FILES)) yasm_compile_asm_libavfilter.bat — пример bat-скрипта, который компилирует *.asm файлы для x86 REM комп

© Habrahabr.ru