- Building FFmpeg for Android
- Originally was posted at my blog here. This article has an continuation with CLang and FFmpeg 4.0 integration explained. Check it out here!
- Preambule
- FFmpeg Development Kit
- VideoKit
- Getting to work
- Components
- Dictionary
- Configure
- Versioning
- NDK module
- JNI interface
- Java part
- C code
- NDK-build
- Libraries loading
- Congratulations
- Somethings
- воскресенье, 19 сентября 2010 г.
- Собираем ffmpeg для Android
- Требования
- Процесс
- Создаем проект
- Получаем исходники ffmpeg
- Конфигурируем ffmpeg
- config.sh
- Адаптируем к NDK
- /jni/ffmpeg/av.mk
- /jni/Android.mk
- /jni/ffmpeg/Android.mk
- /jni/ffmpeg/libavformat/Android.mk
- /jni/ffmpeg/libavcodec/Android.mk
- Android.mk
- Компилируем
- А дальше?
- mylib.c
- Android.mk
- MainActivity.java
- Заключение
- Ссылки
- 18 комментариев:
- Говорящая панда или что можно сделать с FFmpeg и OpenCV на Android
- Дисклеймер
- Предыстория
- Выбор технологий
- FFmpeg, Android, NDK, Eclipse, Windows
- 0. Предустановки
- 1. Подготавливаем проект
- 2. Make-файлы, компиляция и сборка
- Android ffmpeg build windows
Building FFmpeg for Android
Originally was posted at my blog here. This article has an continuation with CLang and FFmpeg 4.0 integration explained. Check it out here!
Mar 2, 2017 · 8 min read
Preambule
Some time ago, I got task on my work which required processing of video on Android. As you probably aware — Android doesn’t deliver built-in tool for such task (Ok-ok, there actually is MediaCodec, which, in a way, allows you to perform video processing, but about it in the next post). After some googe’ing, I came to conclusion that FFmpeg ideally fits requirements of the task. Those requirements, by the way, were following: application had to trim video down to 30 seconds, lower its bitrate and crop it to square. And everything in time less then 30 seconds.
“W e ll, now all we need is to build FFmpeg and link it to the application. Like shooting fish in a barrel!”, — thought me.
“Good luck!”, — said FFmpeg.
In the next sections, I will try to step-by-step explain how to build FFmpeg for Android, but, first of all, I would like to present developed by me Kit that should make this process much easier.
FFmpeg Development Kit
You can found this Kit on my GitHub here: FFmpeg Development Kit
VideoKit
Another library, prepared by me, that you might find useful: VideoKit, basically, is a result of steps described in this article — it allows you to execute standard FFmpeg commands to process video file.
You can find it here: VideoKit
Getting to work
First of all, you have to decide in which way you want to embed FFmpeg into your application. I know three ways to do so:
In the rest of this post I will try to explain how to embed FFmpeg with second way, since from my point of view it’s the best way to achieve necessary functionality.
Components
You will need following components:
I was able to build FFmpeg on OSX (Sierra) and Ubuntu (12.04). While, theoretically, it should be possible to build FFmpeg in Windows with Cygwin, I highly would recommend to don’t go that way. Even if you don’t have Mac and using only Windows OS for development — consider installing Ubuntu as second system or in virtual environment and build FFmpeg in it. As per my experience, it will avoid many hours of frustration and weird errors happening all around you.
After you get everything downloaded — extract NDK somewhere on the disc. Then put FFmpeg sources under NDK/sources path. Note, this is very important for building your own JNI interface later on.
Dictionary
In next sections few terms may appear, that might not be known to reader, who didn’t work with gcc and building of open source libraries previously, in general.
There is a list of such terms with short explanation:
Configure
First step for FFmpeg building is configuring it. FFmpeg, thru special script called “configure”, allows you to choose which features you need, for which architecture you’re going and so on.
For example, let me present configuration for armeabi (arm-v5):
It looks a bit messy, but, unfortunately, it how it looks like in real world.
to get full list of available components and flags that might be used.
If you configured everything properly, you should be able to run following commands:
Versioning
While it’s ok for usage on desktop systems like OSX or Ubunty or any other — Android will not accept such libraries. In order to remove versioning you have to edit configure script.
Open configure with any text editor and find following lines:
NDK module
This file will tell NDK from where it have to take headers and library files.
JNI interface
JNI stands for Java Native Interface and it’s basically a bridge between Java code and native C code. Note that it’s not entirely usual Java and C code — it have to follow certain conventions to make everything work together. Let’s start from Java code.
Java part
It’s pretty usual, beside fact that you have to pay attention to package, in which class is located and also it must contain special functions marked with keyword “native”.
Lets consider class named D that is located in package a.b.c and that have native function called “run”:
This class is similar to interface in a way that native functions doesn’t require implementation. When you will call this function, implementation in C counterpart of code actually will be executed.
Beside special functions — it’s normal class that might contain arbitrary Java code.
This pretty much it as for Java part. Let me present C part of the code.
C code
Your C code that actually uses FFmpeg must match your Java interface. Basically, for class defined above — C part would look as follow:
Looks a bit scary, but if you look more closer — there is nothing special about it. Function name encodes location of class and function in Java part of code (it’s why you should choose package carefully).
When you call “run” in your Java code, “Java_a_b_c_D_run” actually will be called in C part.
Beside some naming conventions — there is no restrictions on C code as well. You can even use C++, however, I should aware you that support of C++ on Android is not full (it’s partially support C++11 standard, if I remember correctly).
NDK-build
Android.mk is responsible for defining all paths and pulling everything together. Example is below:
Application.mk defines general configuration of produced library:
When both files are prepared and configured — navigate to this folder in command line and run ndk-build. Make sure that NDK folder is added to the PATH.
If everything was configured properly — you should get your library and copied FFmpeg libraries in libs folder.
Libraries loading
After you got everything prepared you must load libraries in memory of your application. First of all, make sure that libraries located in right folder in the project. It have to be in /src/main/jniLibs//. If you will not put it there — Android system will not be able to locate libraries.
Loading is rather easy step, but it may have some pitfalls in it. Basically, it may look as follows:
Try-catch construction is rather optional. But may safe your application from unexpected crash on new architecture or unexpected architecture.
Important note: order matters. If library will not find its dependency already loaded in memory — it will crash. So you have to load first library with no dependencies, then library that depends on first and so on.
Congratulations
If you survived up to this point — you successfully embedded FFmpeg into your application. I know that it’s hard work and sincerely congratulate you with it.
If you, unfortunately, didn’t achieve this goal — you always can ask for help in the comment section and I will try my best to help you.
Somethings
problems and solutions
воскресенье, 19 сентября 2010 г.
Собираем ffmpeg для Android
Требования
Процесс
Создаем проект
Получаем исходники ffmpeg
Конфигурируем ffmpeg
config.sh
Адаптируем к NDK
/jni/ffmpeg/av.mk
/jni/Android.mk
/jni/ffmpeg/Android.mk
/jni/ffmpeg/libavformat/Android.mk
/jni/ffmpeg/libavcodec/Android.mk
Android.mk
Компилируем
А дальше?
mylib.c
Android.mk
MainActivity.java
Заключение
Ссылки
18 комментариев:
Тут главный момент в том, что ffmpeg распространяется под LGPL. Т.е. библиотеку можно линковать с приложением, распространяемым под любой лицензией
Вставлю свои пять копеек.
Тоже собирал ffmpeg под Android, но его возможности использовал не через API, а сделал обертку вокруг функции main и далее обращался к собранной либе как из командной строки. Это намного удобнее, т.к. документации по командам ffmpeg’а во много раз больше.
Кстати, господа, мне тут недавно сообщили, что по данной инструкции ffmpeg собирается только для NDK r4. А так как править ее я буду не раньше, чем снова столкнусь с подобной задачей, прошу иметь в виду и разбираться самостоятельно.
А есть продолжение файлика mylib.c, а то я как явер не знаю С++, а либа эта очень заинтересовала?
Народ, подскажите новичку. В сях я совсем не силен, но придется, похоже, разбираться с ffmpeg для Android.
Мне не понятен такой момент. Если библиотека компилируется для определенной архитектуры процессоров, то как насчет совместимости? Смартфоны то на разных процах постороены.
а где
env->ReleaseStringUTFChars(filename, str);
Вы пробовали запись аудио на OpenAl?
(не удалось alcCaptureOpenDevice с NULL именем)
полсе этого сам ffmpeg соберется. Далее все получившиеся *.a файлы складываем в папку jni/lib нашего проекта где мы будем использовать ffmpeg и изменяем приведенный в статье Anroid.mk на следующий
LOCAL_MODULE := libavformat
LOCAL_SRC_FILES := lib/libavformat.a
LOCAL_MODULE := libavcodec
LOCAL_SRC_FILES := lib/libavcodec.a
LOCAL_MODULE := libpostproc
LOCAL_SRC_FILES := lib/libpostproc.a
LOCAL_MODULE := libswscale
LOCAL_SRC_FILES := lib/libswscale.a
LOCAL_MODULE := libavutil
LOCAL_SRC_FILES := lib/libavutil.a
надеюсь кому-нибудь помог
А у кого-нибудь собралось в NDK без опции:
—disable-asm
Дело в том, что эта опция убирает все ARM-оптимизации процессора и код работает в разы медленнее, как минимум в 2 раза медленнее.
У меня, если убирается эта опция не компилится под NDK. Вываливается ошибка что такая-то ассемблерная команда не поддерживается выбранным процессором.
Есть какие-нибудь идеи как этого избежать?
Добрый день.
Дарья, спасибо. По вашей статье таки собрал ffmpeg под android.
Но у меня есть вопрос:
jeck_landin пишет что написал обертку и теперь использует ffmpeg как из командной строки. Кто нибудь подскажет как это можно сделать? Что то я не разбирусь 🙁
А то перекопал кучу инфы но с API разбираться тяжело. я далек от СИ.
У меня благодаря Дарье получилось собрать FFMPEG в таком виде, для NDK r5 пришлось ещё пошаманить.
Для сборки с ARM-оптимизациями очень долго плясал с бубном, переделывая config.mak и config.h. Потом для включения ARM-версий исходников для libavcodec потребовалось кусок arm/Makefile переносить на верхний уровень.
Браво! Не «хило» так, как для убежденного адепта Майкрософта!
Говорящая панда или что можно сделать с FFmpeg и OpenCV на Android
Дисклеймер
Некоторые описываемые вещи наверняка покажутся многим очевидными, тем не менее, для меня, как для разработчика под Windows, эти задачи оказались новыми и их решение было не очевидным, поэтому описание технических деталей я постарался сделать максимально простым и понятным для людей, не имеющих большого опыта работы с Android NDK и всем, что с ним связано. Некоторые решения были найдены интуитивно, и поэтому, скорее всего, они не совсем «красивые».
Предыстория
Идея Android приложения, где бы использовались FFmpeg и OpenCV, появилась после просмотра одного рекламного ролика про минеральную воду Витутас (можете поискать на Youtube). В этом ролике иногда мелькали фото разных животных, которые вращали человеческими глазами, шевелили губами и уговаривали зрителя купить эту воду. Выглядело это довольно забавно. В общем, возникла мысль: что если дать пользователю возможность самому делать подобные ролики, причем не с компьютера, а с помощью своего телефона?
Разумеется, сперва поискали аналоги. Что-то более или менее похожее было найдено в AppStore для iPhone, причем там процесс создания ролика был не очень удачным: выбираешь картинку, размечаешь на ней одну область, и потом камерой в этой области что-то снимаешь, то есть речь о том, чтобы наложить на картинку в разных местах хотя бы два глаза и рот вообще не шла. В Google Play же вообще ничего такого не было. Максимально близкие программы с похожим функционалом были такие, где на фото можно наложить анимированные элементы из ограниченных наборов.
Одним словом, конкурентов мало, поэтому было принято решение приложение всё же делать.
Выбор технологий
Сразу возник логичный вопрос: «А как это все сделать?». Потратив дня два на изучение всяких библиотек для обработки видео и изображений, остановился на FFmpeg и OpenCV.
Надо признаться в том, что так как опыта разработки под Android было мало, а под Windows много, то прежде чем начать ковыряться в Eclipse и NDK я сделал маленькую программку в Visual Studio, которая доказала, что сама идея использовать FFmpeg и OpenCV имеет право на жизнь и, самое главное, что есть способ реализовать их взаимодействие. Но о реализации взаимодействия этих библиотек будет написано чуть позже, а это скорее легкая рекомендация на тему того, что лучше все же потратить время и проверить какую-то идею на технологиях, в которых разбираешься лучше всего, чем сразу с головой лезть во что-то новое.
Насчет же компиляции FFmpeg в Visual Studio — сделать это оказалось на удивление легко, но эта статья все же об Android, поэтому если тема FFmpeg в Visual Studio интересна, то напишите об этом, и я постараюсь найти время и написать инструкцию о том, как это сделать.
Итак, проверив, что идея объеденить FFmpeg и OpenCV работает, я приступил к разработке непосредственно Android приложения.
Делать это все решил в 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 и вводим приведенные ниже наборы команд.
Для устройств MIPS:
Скрипт сгенерирует в папке «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-файлы с комментариями и инклюдами.
Android ffmpeg build windows
FFmpeg for Android, iOS and tvOS
Includes both FFmpeg and FFprobe
Use binaries available at Github / Maven Central / CocoaPods or build your own version with external libraries you need
Android, iOS and tvOS
29 external libraries
5 external libraries with GPL license
Exposes both FFmpeg library and MobileFFmpeg wrapper library capabilities
Includes cross-compile instructions for 47 open-source libraries
Licensed under LGPL 3.0, can be customized to support GPL v3.0
Prebuilt binaries are available at Github, Maven Central and CocoaPods.
There are eight different mobile-ffmpeg packages. Below you can see which system libraries and external libraries are enabled in each of them.
Please remember that some parts of FFmpeg are licensed under the GPL and only GPL licensed mobile-ffmpeg packages include them.
min | min-gpl | https | https-gpl | audio | video | full | full-gpl | |
---|---|---|---|---|---|---|---|---|
external libraries | — | vid.stab x264 x265 xvidcore | gmp gnutls | gmp gnutls vid.stab x264 x265 xvidcore | lame libilbc libvorbis opencore-amr opus shine soxr speex twolame vo-amrwbenc wavpack | fontconfig freetype fribidi kvazaar libaom libass libiconv libtheora libvpx libwebp snappy | fontconfig freetype fribidi gmp gnutls kvazaar lame libaom libass libiconv libilbc libtheora libvorbis libvpx libwebp libxml2 opencore-amr opus shine snappy soxr speex twolame vo-amrwbenc wavpack | fontconfig freetype fribidi gmp gnutls kvazaar lame libaom libass libiconv libilbc libtheora libvorbis libvpx libwebp libxml2 opencore-amr opus shine snappy soxr speex twolame vid.stab vo-amrwbenc wavpack x264 x265 xvidcore |
android system libraries | zlib MediaCodec | |||||||
ios system libraries | zlib AudioToolbox AVFoundation iconv VideoToolbox bzip2 | |||||||
tvos system libraries | zlib AudioToolbox iconv VideoToolbox bzip2 |
libaom and soxr are supported since v2.0
vo-amrwbenc is supported since v4.4
Add MobileFFmpeg dependency to your build.gradle in mobile-ffmpeg-
Execute synchronous FFmpeg commands.
Execute asynchronous FFmpeg commands.
Execute FFprobe commands.
Check execution output later.
Stop ongoing FFmpeg operations.
Get media information for a file.
Record video using Android camera.
Enable log callback.
Enable statistics callback.
Ignore the handling of a signal.
List ongoing executions.
Set default log level.
Register custom fonts directory.
Add MobileFFmpeg dependency to your Podfile in mobile-ffmpeg-
Execute synchronous FFmpeg commands.
Execute asynchronous FFmpeg commands.
Execute FFprobe commands.
Check execution output later.
Stop ongoing FFmpeg operations.
Get media information for a file.
Enable log callback.
Enable statistics callback.
Ignore the handling of a signal.
List ongoing executions.
Set default log level.
Register custom fonts directory.
2.4 Manual Installation
iOS and tvOS frameworks can be installed manually using the Importing Frameworks guide. If you want to use universal binaries please refer to Using Universal Binaries guide.
2.5 Test Application
You can see how MobileFFmpeg is used inside an application by running test applications provided. There is an Android test application under the android/test-app folder, an iOS test application under the ios/test-app folder and a tvOS test application under the tvos/test-app folder.
All applications are identical and supports command execution, video encoding, accessing https, encoding audio, burning subtitles, video stabilisation, pipe operations and concurrent command execution.
In previous versions, MobileFFmpeg version of a release and FFmpeg version included in that release was different. The following table lists FFmpeg versions used in MobileFFmpeg releases.
Main releases include complete functionality of the library and support the latest SDK/API features.
LTS releases are customized to support a wider range of devices. They are built using older API/SDK versions, so some features are not available on them.
This table shows the differences between two variants.
Main Release | LTS Release | |
---|---|---|
Android API Level | 24 | 16 |
Android Camera Access | Yes | — |
Android Architectures | arm-v7a-neon arm64-v8a x86 x86-64 | arm-v7a arm-v7a-neon arm64-v8a x86 x86-64 |
Xcode Support | 10.1 | 7.3.1 |
iOS SDK | 12.1 | 9.3 |
iOS AVFoundation | Yes | — |
iOS Architectures | arm64 arm64e 1 x86-64 x86-64-mac-catalyst 2 | armv7 arm64 i386 x86-64 |
tvOS SDK | 10.2 | 9.2 |
tvOS Architectures | arm64 x86-64 | arm64 x86-64 |
Build scripts from master and development branches are tested periodically. See the latest status from the table below.
branch | status |
---|---|
master | |
development |
Use your package manager (apt, yum, dnf, brew, etc.) to install the following packages.
Some of these packages are not mandatory for the default build. Please visit Android Prerequisites, iOS Prerequisites and tvOS Prerequisites for the details.
Android builds require these additional packages.
iOS builds need these extra packages and tools.
tvOS builds need these extra packages and tools.
All three scripts support additional options and can be customized to enable/disable specific external libraries and/or architectures. Please refer to wiki pages of android.sh, ios.sh and tvos.sh to see all available build options.
5.2.4 Building LTS Binaries
5.5 External Libraries
CPU optimizations ( ASM ) are enabled for most of the external libraries. Details and exceptions can be found under the ASM Support wiki page.
A more detailed documentation is available at Wiki.
7.1 Code Contributors
This project exists thanks to all the people who contribute. [Contribute].
7.2 Financial Contributors
Become a financial contributor and help us sustain our community. [Contribute]
Support this project with your organization. Your logo will show up here with a link to your website. [Contribute]
The source code of all external libraries included is in compliance with their individual licenses.
openh264 source code included in this repository is licensed under the 2-clause BSD License but this license does not cover the MPEG LA licensing fees. If you build mobile-ffmpeg with openh264 and distribute that library, then you are subject to pay MPEG LA licensing fees. Refer to OpenH264 FAQ page for the details. Please note that mobile-ffmpeg does not publish a binary with openh264 inside.
strip-frameworks.sh script included and distributed (until v4.x) is published under the Apache License version 2.0.
In test applications; embedded fonts are licensed under the SIL Open Font License, other digital assets are published in the public domain.
Please visit License page for the details.
openh264 clearly states that it uses patented algorithms. Therefore, if you build mobile-ffmpeg with openh264 and distribute that library, then you are subject to pay MPEG LA licensing fees. Refer to OpenH264 FAQ page for the details.
Feel free to submit issues or pull requests.