diff --git a/.gitignore b/.gitignore index 61180d3..9036777 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,5 @@ output sources stats .DS_Store +.idea +*.iml \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index 361df3e..0336662 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,4 +17,4 @@ install: - curl http://archive.ubuntu.com/ubuntu/pool/universe/n/nasm/nasm_2.14.02-1_amd64.deb --output $HOME/nasm_2.14.02-1_amd64.deb - sudo dpkg -i $HOME/nasm_2.14.02-1_amd64.deb script: - - bash -e ffmpeg-android-maker.sh --enable-libdav1d --enable-libmp3lame --enable-libaom + - ./ffmpeg-android-maker.sh -dav1d diff --git a/README.md b/README.md index c53078e..b3d6c93 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ # ffmpeg-android-maker +[![Codacy Badge](https://api.codacy.com/project/badge/Grade/6b9a9fe4c6874e65a5e2a3f9beb15605)](https://app.codacy.com/manual/Javernaut/ffmpeg-android-maker) [![Build Status](https://travis-ci.org/Javernaut/ffmpeg-android-maker.svg?branch=master)](https://travis-ci.org/Javernaut/ffmpeg-android-maker) [![Android Weekly #378](https://androidweekly.net/issues/issue-378/badge)](https://androidweekly.net/issues/issue-378) [![Android Weekly #396](https://androidweekly.net/issues/issue-396/badge)](https://androidweekly.net/issues/issue-396) @@ -10,9 +11,9 @@ Here is a script that downloads the source code of [FFmpeg](https://www.ffmpeg.o The script also produces `ffmpeg` and `ffprobe` executables that can be used in Android's terminal directly or can even be embedded into an Android app. They can be found in `build` directory after the successful build. -The main focus of ffmpeg-android-maker is to prepare shared libraries for seamless integration into an Android project. And it's not the only thing this project does. +The main focus of ffmpeg-android-maker is to prepare shared libraries for seamless integration into an Android project. The script prepares the `output` directory that is meant to be used. And it's not the only thing this project does. -By default this script downloads and build the FFmpeg **4.2.2**, but the version can be overridden. +By default this script downloads and builds the FFmpeg **4.2.2**, but the version can be overridden. The details of how this script is implemented are described in this series of posts: * [Part 1](https://proandroiddev.com/a-story-about-ffmpeg-in-android-part-i-compilation-898e4a249422) @@ -23,9 +24,13 @@ The [WIKI](https://github.com/Javernaut/ffmpeg-android-maker/wiki) contains a lo ## Customization -The actual content of `output` directory depends on how the FFmpeg was configured before assembling. The [master](https://github.com/Javernaut/ffmpeg-android-maker) branch of ffmpeg-android-maker builds 'vanilla' version of FFmpeg. This means all default components and libraries are built (according to the image). +The actual content of `output` directory depends on how the FFmpeg was configured before assembling. The [master](https://github.com/Javernaut/ffmpeg-android-maker) branch of ffmpeg-android-maker builds 'vanilla' version of FFmpeg. This means all default components and shared libraries are built (according to the image). -The [what-the-codec](https://github.com/Javernaut/ffmpeg-android-maker/tree/what-the-codec) branch contains certain customizations in build scripts of FFmpeg and certain external libraries. These customizations are meant to be an example of how this project can be tuned to obtain the only functionality that is actually needed. The [WhatTheCodec](https://github.com/Javernaut/WhatTheCodec) Android app uses only a subset of FFmpeg's functionality, so the redundant parts are not even compiled. This gives much smaller output binaries. +The [what-the-codec](https://github.com/Javernaut/ffmpeg-android-maker/tree/what-the-codec) branch contains certain customizations in build scripts of FFmpeg and certain external libraries. These customizations are meant to be an example of how this project can be tuned to obtain the only functionality that is actually needed. What is actually customized can be seen [here](https://github.com/Javernaut/ffmpeg-android-maker/commit/734a4e98c41576b8b9fcf032e0754315b5b77a82). + +The [WhatTheCodec](https://github.com/Javernaut/WhatTheCodec) Android app uses only a subset of FFmpeg's functionality, so the redundant parts are not even compiled. This gives much smaller output binaries. + +Also there are a lot of arguments that you can pass to the `ffmpeg-android-maker.sh` script for tuning certain features. Check this [WIKI page](https://github.com/Javernaut/ffmpeg-android-maker/wiki/Available-script-arguments) out for more info. ## Supported Android ABIs @@ -34,13 +39,18 @@ The [what-the-codec](https://github.com/Javernaut/ffmpeg-android-maker/tree/what * x86 * x86_64 +You can build only some of these ABIs by specifying a [flag](https://github.com/Javernaut/ffmpeg-android-maker/wiki/Available-script-arguments#desired-abis-to-build). + ## Supported host OS On **macOS** or **Linux** just execute the ffmpeg-android-maker.sh script in terminal. Please follow the instructions in [Requirements](#Requirements) section. ~~It is also possible to execute this script on a **Windows** machine with [MSYS2](https://www.msys2.org). You also need to install specific packages to it: *make*, *git*, *diffutils* and *tar*. The script supports both 32-bit and 64-bit versions of Windows. Also see Prerequisites section for necessary software.~~ -Since v2.0.0 the **Windows** support is temporary absent, but soon a Docker image will be available to be used on any host OS. +Since v2.0.0 the MSYS2 support is temporary absent. + +Since v2.1.1 the **Windows** support is done with [Docker](https://www.docker.com) tool. +Check [this WIKI page](https://github.com/Javernaut/ffmpeg-android-maker/wiki/Docker-support) for more info. ## Requirements @@ -50,11 +60,7 @@ Before the script is executed you have to define two environment variables: * `ANDROID_SDK_HOME` - path to your Android SDK * `ANDROID_NDK_HOME` - path to your Android NDK -Certain external libraries require additional software to be installed: -* **libaom** requires the 'cmake;3.10.2.4988404' package to be installed via Android SDK. -* For **libdav1d** building you also need to install *ninja* and *meson* tools. - -Note that if you don't need these external libraries then you also don't need to install the additional software. These external libraries are not built by default. +Certain external libraries require additional software to be installed. Check this [WIKI page](https://github.com/Javernaut/ffmpeg-android-maker/wiki/Supported-external-libraries) out for more info. Note that if you don't need these external libraries then you also don't need to install the additional software. These external libraries are not built by default. ## Features diff --git a/ffmpeg-android-maker.sh b/ffmpeg-android-maker.sh index 8cba281..8f83171 100755 --- a/ffmpeg-android-maker.sh +++ b/ffmpeg-android-maker.sh @@ -97,12 +97,8 @@ do cd ${BASE_DIR} done -# ABIs to build FFmpeg for. -# x86 is the first, because it is likely to have Text Relocations. -# In this case the rest ABIs will not be assembled at all. -ABIS_TO_BUILD=( "x86" "x86_64" "armeabi-v7a" "arm64-v8a" ) - -for ABI in ${ABIS_TO_BUILD[@]} +# Main build loop +for ABI in ${FFMPEG_ABIS_TO_BUILD[@]} do # Exporting variables for the current ABI source ${SCRIPTS_DIR}/export-build-variables.sh ${ABI} @@ -116,13 +112,13 @@ do cd ${!COMPONENT_SOURCES_DIR_VARIABLE} # and executing the component-specific build script - ${SCRIPTS_DIR}/${COMPONENT}/build.sh + source ${SCRIPTS_DIR}/${COMPONENT}/build.sh || exit 1 # Returning to the root directory. Just in case. cd ${BASE_DIR} done - checkTextRelocations + checkTextRelocations || exit 1 prepareOutput done diff --git a/scripts/common-functions.sh b/scripts/common-functions.sh new file mode 100755 index 0000000..045a830 --- /dev/null +++ b/scripts/common-functions.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash + +# Function that downloads an archive with the source code by the given url, +# extracts its files and exports a variable SOURCES_DIR_${LIBRARY_NAME} +function downloadTarArchive() { + # The full name of the library + LIBRARY_NAME=$1 + # The url of the source code archive + DOWNLOAD_URL=$2 + # Optional. If 'true' then the function creates an extra directory for archive extraction. + NEED_EXTRA_DIRECTORY=$3 + + ARCHIVE_NAME=${DOWNLOAD_URL##*/} + # File name without extension + LIBRARY_SOURCES="${ARCHIVE_NAME%.tar.*}" + + echo "Ensuring sources of ${LIBRARY_NAME} in ${LIBRARY_SOURCES}" + + if [[ ! -d "$LIBRARY_SOURCES" ]]; then + curl -O ${DOWNLOAD_URL} + + EXTRACTION_DIR="." + if [ "$NEED_EXTRA_DIRECTORY" = true ] ; then + EXTRACTION_DIR=${LIBRARY_SOURCES} + mkdir ${EXTRACTION_DIR} + fi + + tar xf ${ARCHIVE_NAME} -C ${EXTRACTION_DIR} + rm ${ARCHIVE_NAME} + fi + + export SOURCES_DIR_${LIBRARY_NAME}=$(pwd)/${LIBRARY_SOURCES} +} diff --git a/scripts/export-build-variables.sh b/scripts/export-build-variables.sh index f18b5fc..843bd70 100755 --- a/scripts/export-build-variables.sh +++ b/scripts/export-build-variables.sh @@ -54,18 +54,18 @@ export TARGET_TRIPLE_MACHINE_CC=$TARGET_TRIPLE_MACHINE_CC export CPU_FAMILY=$CPU_FAMILY # Common prefix for ld, as, etc. -export CROSS_PREFIX=${TARGET_TRIPLE_MACHINE_BINUTILS}-linux-${TARGET_TRIPLE_OS}- +if [ $DESIRED_BINUTILS = "gnu" ] ; then + export CROSS_PREFIX=${TARGET_TRIPLE_MACHINE_BINUTILS}-linux-${TARGET_TRIPLE_OS}- +else + export CROSS_PREFIX=llvm- +fi + export CROSS_PREFIX_WITH_PATH=${TOOLCHAIN_PATH}/bin/${CROSS_PREFIX} # Exporting Binutils paths, if passing just CROSS_PREFIX_WITH_PATH is not enough # The FAM_ prefix is used to eliminate passing those values implicitly to build systems export FAM_ADDR2LINE=${CROSS_PREFIX_WITH_PATH}addr2line export FAM_AR=${CROSS_PREFIX_WITH_PATH}ar -export FAM_AS=${CROSS_PREFIX_WITH_PATH}as -export FAM_DWP=${CROSS_PREFIX_WITH_PATH}dwp -export FAM_ELFEDIT=${CROSS_PREFIX_WITH_PATH}elfedit -export FAM_GPROF=${CROSS_PREFIX_WITH_PATH}gprof -export FAM_LD=${CROSS_PREFIX_WITH_PATH}ld export FAM_NM=${CROSS_PREFIX_WITH_PATH}nm export FAM_OBJCOPY=${CROSS_PREFIX_WITH_PATH}objcopy export FAM_OBJDUMP=${CROSS_PREFIX_WITH_PATH}objdump @@ -79,6 +79,9 @@ export TARGET=${TARGET_TRIPLE_MACHINE_CC}-linux-${TARGET_TRIPLE_OS}${ANDROID_PLA # The name for compiler is slightly different, so it is defined separatly. export FAM_CC=${TOOLCHAIN_PATH}/bin/${TARGET}-clang export FAM_CXX=${FAM_CC}++ +export FAM_LD=${FAM_CC} +export FAM_AS=${FAM_CC} + # TODO consider abondaning this strategy of defining the name of the clang wrapper # in favour of just passing -mstackrealign and -fno-addrsig depending on # ANDROID_ABI, ANDROID_PLATFORM and NDK's version diff --git a/scripts/ffmpeg/build.sh b/scripts/ffmpeg/build.sh index 603d79c..b354902 100755 --- a/scripts/ffmpeg/build.sh +++ b/scripts/ffmpeg/build.sh @@ -33,8 +33,14 @@ DEP_LD_FLAGS="-L${BUILD_DIR_EXTERNAL}/${ANDROID_ABI}/lib $FFMPEG_EXTRA_LD_FLAGS" --target-os=android \ --arch=${TARGET_TRIPLE_MACHINE_BINUTILS} \ --sysroot=${SYSROOT_PATH} \ - --cross-prefix=${CROSS_PREFIX_WITH_PATH} \ --cc=${FAM_CC} \ + --cxx=${FAM_CXX} \ + --ld=${FAM_LD} \ + --ar=${FAM_AR} \ + --as=${FAM_AS} \ + --nm=${FAM_NM} \ + --ranlib=${FAM_RANLIB} \ + --strip=${FAM_STRIP} \ --extra-cflags="-O3 -fPIC $DEP_CFLAGS" \ --extra-ldflags="$DEP_LD_FLAGS" \ --enable-shared \ @@ -54,7 +60,7 @@ DEP_LD_FLAGS="-L${BUILD_DIR_EXTERNAL}/${ANDROID_ABI}/lib $FFMPEG_EXTRA_LD_FLAGS" --disable-pthreads \ --disable-network \ --disable-bsfs \ - $ADDITIONAL_COMPONENTS + $ADDITIONAL_COMPONENTS || exit 1 ${MAKE_EXECUTABLE} clean ${MAKE_EXECUTABLE} -j${HOST_NPROC} diff --git a/scripts/ffmpeg/download.sh b/scripts/ffmpeg/download.sh index bdb5819..590b3fa 100755 --- a/scripts/ffmpeg/download.sh +++ b/scripts/ffmpeg/download.sh @@ -9,17 +9,11 @@ # Getting sources of a particular FFmpeg release. # Same argument (FFmpeg version) produces the same source set. function ensureSourcesTar() { - FFMPEG_SOURCES=ffmpeg-${FFMPEG_SOURCE_VALUE} + source ${SCRIPTS_DIR}/common-functions.sh - if [[ ! -d "$FFMPEG_SOURCES" ]]; then - TARGET_FILE_NAME=ffmpeg-${FFMPEG_SOURCE_VALUE}.tar.bz2 - - curl https://www.ffmpeg.org/releases/${TARGET_FILE_NAME} --output ${TARGET_FILE_NAME} - tar xf ${TARGET_FILE_NAME} -C . - rm ${TARGET_FILE_NAME} - fi - - export SOURCES_DIR_ffmpeg=$(pwd)/${FFMPEG_SOURCES} + downloadTarArchive \ + "ffmpeg" \ + "https://www.ffmpeg.org/releases/ffmpeg-${FFMPEG_SOURCE_VALUE}.tar.bz2" } # Getting sources of a particular branch or a tag of FFmpeg's git repository. diff --git a/scripts/libaom/android.cmake b/scripts/libaom/android.cmake index 0ac7225..06fcbdb 100644 --- a/scripts/libaom/android.cmake +++ b/scripts/libaom/android.cmake @@ -10,8 +10,8 @@ include("$ENV{ANDROID_NDK_HOME}/build/cmake/android.toolchain.cmake") # AS_EXECUTABLE (AV1 Codec Library's variable) should point to an assembler # For x86 and x86_64 ABIs it needs yasm -# For armeabi-v7a and arm64-v8a is is ok to use GNU assembler -# When ANDROID_ABI is x86 or _86_64, +# For armeabi-v7a and arm64-v8a it is ok to use GNU assembler +# When ANDROID_ABI is x86 or x86_64, # then CMAKE_ASM_NASM_COMPILER variable will point to the yasm compiler (it is set by android.toolchain.cmake) if(DEFINED CMAKE_ASM_NASM_COMPILER) set(AS_EXECUTABLE ${CMAKE_ASM_NASM_COMPILER}) diff --git a/scripts/libaom/download.sh b/scripts/libaom/download.sh index 4229dea..c233fba 100755 --- a/scripts/libaom/download.sh +++ b/scripts/libaom/download.sh @@ -1,24 +1,10 @@ #!/usr/bin/env bash -# Script to download AV1 Codec Library's source code +source ${SCRIPTS_DIR}/common-functions.sh -# Exports SOURCES_DIR_libaom - path where actual sources are stored +AOM_VERSION=v1.0.0-errata1-avif -# This 2 variables have to be changed at once. -# The first one is produced by 'git describe' command while being in the commit represented by the second one. -AOM_VERSION=v1.0.0-2780-ge1ec46ae2 -AOM_HASH=e1ec46ae24bb406057c3c256e69cd359b342a8d3 - -echo "Using libaom $AOM_VERSION" -AOM_SOURCES=libaom-${AOM_VERSION} - -if [[ ! -d "$AOM_SOURCES" ]]; then - TARGET_FILE_NAME=${AOM_VERSION}.tar.gz - - curl https://aomedia.googlesource.com/aom/+archive/${AOM_HASH}.tar.gz --output ${TARGET_FILE_NAME} - mkdir $AOM_SOURCES - tar xf ${TARGET_FILE_NAME} -C $AOM_SOURCES - rm ${TARGET_FILE_NAME} -fi - -export SOURCES_DIR_libaom=$(pwd)/${AOM_SOURCES} +downloadTarArchive \ + "libaom" \ + "https://aomedia.googlesource.com/aom/+archive/${AOM_VERSION}.tar.gz" \ + true diff --git a/scripts/libdav1d/download.sh b/scripts/libdav1d/download.sh index ec0a7c5..9697551 100755 --- a/scripts/libdav1d/download.sh +++ b/scripts/libdav1d/download.sh @@ -1,19 +1,9 @@ #!/usr/bin/env bash -# Script to download Dav1d's source code - -# Exports SOURCES_DIR_libdav1d - path where actual sources are stored +source ${SCRIPTS_DIR}/common-functions.sh DAV1D_VERSION=0.6.0 -echo "Using libdav1d $DAV1D_VERSION" -DAV1D_SOURCES=dav1d-${DAV1D_VERSION} - -if [[ ! -d "$DAV1D_SOURCES" ]]; then - TARGET_FILE_NAME=dav1d-${DAV1D_VERSION}.tar.gz - - curl https://code.videolan.org/videolan/dav1d/-/archive/${DAV1D_VERSION}/dav1d-${DAV1D_VERSION}.tar.gz --output ${TARGET_FILE_NAME} - tar xf ${TARGET_FILE_NAME} -C . - rm ${TARGET_FILE_NAME} -fi -export SOURCES_DIR_libdav1d=$(pwd)/${DAV1D_SOURCES} +downloadTarArchive \ + "libdav1d" \ + "https://code.videolan.org/videolan/dav1d/-/archive/${DAV1D_VERSION}/dav1d-${DAV1D_VERSION}.tar.gz" diff --git a/scripts/libmp3lame/build.sh b/scripts/libmp3lame/build.sh index 2975b36..1bece1a 100755 --- a/scripts/libmp3lame/build.sh +++ b/scripts/libmp3lame/build.sh @@ -13,9 +13,7 @@ --disable-frontend \ CC=${FAM_CC} \ AR=${FAM_AR} \ - RANLIB=${FAM_RANLIB} - -export FFMPEG_EXTRA_LD_FLAGS="${FFMPEG_EXTRA_LD_FLAGS} -lmp3lame" + RANLIB=${FAM_RANLIB} || exit 1 ${MAKE_EXECUTABLE} clean ${MAKE_EXECUTABLE} -j${HOST_NPROC} diff --git a/scripts/libmp3lame/download.sh b/scripts/libmp3lame/download.sh index 46cf5d6..fe58d48 100755 --- a/scripts/libmp3lame/download.sh +++ b/scripts/libmp3lame/download.sh @@ -1,19 +1,9 @@ #!/usr/bin/env bash -# Script to download Lame's source code - -# Exports SOURCES_DIR_libmp3lame - path where actual sources are stored +source ${SCRIPTS_DIR}/common-functions.sh LAME_VERSION=3.100 -echo "Using libmp3lame $LAME_VERSION" -LAME_SOURCES=lame-${LAME_VERSION} - -if [[ ! -d "$LAME_SOURCES" ]]; then - TARGET_FILE_NAME=lame-${LAME_VERSION}.tar.gz - - curl http://downloads.videolan.org/pub/contrib/lame/${TARGET_FILE_NAME} --output ${TARGET_FILE_NAME} - tar xf ${TARGET_FILE_NAME} -C . - rm ${TARGET_FILE_NAME} -fi -export SOURCES_DIR_libmp3lame=$(pwd)/${LAME_SOURCES} +downloadTarArchive \ + "libmp3lame" \ + "http://downloads.videolan.org/pub/contrib/lame/lame-${LAME_VERSION}.tar.gz" diff --git a/scripts/libopus/build.sh b/scripts/libopus/build.sh new file mode 100755 index 0000000..4d4a353 --- /dev/null +++ b/scripts/libopus/build.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash + +./configure \ + --prefix=${INSTALL_DIR} \ + --host=${TARGET} \ + --disable-shared \ + --enable-static \ + --disable-fast-install \ + --with-pic \ + --with-sysroot=${SYSROOT_PATH} \ + --enable-asm \ + --enable-check-asm \ + --disable-rtcd \ + --disable-doc \ + --disable-extra-programs \ + CC=${FAM_CC} \ + CCLD=${FAM_LD} \ + CCAS=${FAM_AS} \ + RANLIB=${FAM_RANLIB} \ + AR=${FAM_AR} + +export FFMPEG_EXTRA_LD_FLAGS="${FFMPEG_EXTRA_LD_FLAGS} -lm" + +${MAKE_EXECUTABLE} clean +${MAKE_EXECUTABLE} -j${HOST_NPROC} +${MAKE_EXECUTABLE} install diff --git a/scripts/libopus/download.sh b/scripts/libopus/download.sh new file mode 100755 index 0000000..701323f --- /dev/null +++ b/scripts/libopus/download.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +source ${SCRIPTS_DIR}/common-functions.sh + +OPUS_VERSION=1.3.1 + +downloadTarArchive \ + "libopus" \ + "https://archive.mozilla.org/pub/opus/opus-${OPUS_VERSION}.tar.gz" diff --git a/scripts/libspeex/build.sh b/scripts/libspeex/build.sh new file mode 100755 index 0000000..e319495 --- /dev/null +++ b/scripts/libspeex/build.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash + +ADDITIONAL_FLAGS= +if [[ $ANDROID_ABI = "x86" ]] || [[ $ANDROID_ABI = "x86_64" ]]; then + ADDITIONAL_FLAGS=--enable-sse +fi + +./configure \ + --prefix=${INSTALL_DIR} \ + --host=${TARGET} \ + --with-sysroot=${SYSROOT_PATH} \ + --disable-shared \ + --enable-static \ + --with-pic \ + CC=${FAM_CC} \ + AR=${FAM_AR} \ + RANLIB=${FAM_RANLIB} \ + ${ADDITIONAL_FLAGS} || exit 1 + +export FFMPEG_EXTRA_LD_FLAGS="${FFMPEG_EXTRA_LD_FLAGS} -lm" + +${MAKE_EXECUTABLE} clean +${MAKE_EXECUTABLE} -j${HOST_NPROC} +${MAKE_EXECUTABLE} install diff --git a/scripts/libspeex/download.sh b/scripts/libspeex/download.sh new file mode 100755 index 0000000..e03ea81 --- /dev/null +++ b/scripts/libspeex/download.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +source ${SCRIPTS_DIR}/common-functions.sh + +SPEEX_VERSION=1.2.0 + +downloadTarArchive \ + "libspeex" \ + "https://ftp.osuosl.org/pub/xiph/releases/speex/speex-${SPEEX_VERSION}.tar.gz" diff --git a/scripts/libtwolame/build.sh b/scripts/libtwolame/build.sh new file mode 100755 index 0000000..47404e5 --- /dev/null +++ b/scripts/libtwolame/build.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +# TODO Consider adding a dependency - libsndfile + +./configure \ + --prefix=${INSTALL_DIR} \ + --host=${TARGET} \ + --with-sysroot=${SYSROOT_PATH} \ + --disable-shared \ + --enable-static \ + --with-pic \ + --disable-sndfile \ + CC=${FAM_CC} \ + AR=${FAM_AR} \ + RANLIB=${FAM_RANLIB} || exit 1 + +export FFMPEG_EXTRA_LD_FLAGS="${FFMPEG_EXTRA_LD_FLAGS} -lm" + +${MAKE_EXECUTABLE} clean +${MAKE_EXECUTABLE} -j${HOST_NPROC} +${MAKE_EXECUTABLE} install diff --git a/scripts/libtwolame/download.sh b/scripts/libtwolame/download.sh new file mode 100755 index 0000000..e3c80f7 --- /dev/null +++ b/scripts/libtwolame/download.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +source ${SCRIPTS_DIR}/common-functions.sh + +TWOLAME_VERSION=0.4.0 + +downloadTarArchive \ + "libtwolame" \ + "https://netix.dl.sourceforge.net/project/twolame/twolame/${TWOLAME_VERSION}/twolame-${TWOLAME_VERSION}.tar.gz" diff --git a/scripts/libwavpack/build.sh b/scripts/libwavpack/build.sh new file mode 100755 index 0000000..45815f2 --- /dev/null +++ b/scripts/libwavpack/build.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash + +# The Wavpack may reqire libiconv for proper work +# Consider building it and passing via --with-iconv + +if [[ $ANDROID_ABI = "arm64-v8a" ]]; then + ADDITIONAL_FLAGS=--disable-asm +fi + +./configure \ + --prefix=${INSTALL_DIR} \ + --host=${TARGET} \ + --with-sysroot=${SYSROOT_PATH} \ + --disable-shared \ + --enable-static \ + --with-pic \ + --disable-apps \ + --disable-tests \ + --disable-man \ + CC=${FAM_CC} \ + AR=${FAM_AR} \ + RANLIB=${FAM_RANLIB} \ + ${ADDITIONAL_FLAGS} || exit 1 + +export FFMPEG_EXTRA_LD_FLAGS="${FFMPEG_EXTRA_LD_FLAGS} -lm" + +${MAKE_EXECUTABLE} clean +${MAKE_EXECUTABLE} -j${HOST_NPROC} +${MAKE_EXECUTABLE} install diff --git a/scripts/libwavpack/download.sh b/scripts/libwavpack/download.sh new file mode 100755 index 0000000..e36de8f --- /dev/null +++ b/scripts/libwavpack/download.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +source ${SCRIPTS_DIR}/common-functions.sh + +WAVPACK_VERSION=5.3.0 + +downloadTarArchive \ + "libwavpack" \ + "http://www.wavpack.com/wavpack-${WAVPACK_VERSION}.tar.bz2" diff --git a/scripts/parse-arguments.sh b/scripts/parse-arguments.sh index bf89b6f..0ab1d01 100755 --- a/scripts/parse-arguments.sh +++ b/scripts/parse-arguments.sh @@ -3,66 +3,116 @@ # This script parses arguments that were passed to ffmpeg-android-maker.sh # and exports a bunch of varables that are used elsewhere. -# Local variables with default values. Can be overridden with specific arguments -# See the end of this file for more description -EXTERNAL_LIBRARIES=() +# Local variables with default values (except ABIS_TO_BUILD). +# Can be overridden with specific arguments. +# See the end of this file for more description. +ABIS_TO_BUILD=() +API_LEVEL=16 SOURCE_TYPE=TAR SOURCE_VALUE=4.2.2 -API_LEVEL=16 +BINUTILS=gnu +EXTERNAL_LIBRARIES=() -for artument in "$@" -do - case $artument in +for argument in "$@"; do + case $argument in + # Build for only specified ABIs (separated by comma) + --target-abis=*|-abis=*) + IFS=',' read -ra ABIS <<< "${argument#*=}" + for abi in "${ABIS[@]}"; do + case $abi in + x86|x86_64|armeabi-v7a|arm64-v8a) + ABIS_TO_BUILD+=( "$abi" ) + ;; + arm) + ABIS_TO_BUILD+=( "armeabi-v7a" ) + ;; + arm64) + ABIS_TO_BUILD+=( "arm64-v8a" ) + ;; + *) + echo "Unknown ABI: $abi" + ;; + esac + done + ;; # Use this value as Android platform version during compilation. - --android-api-level=*) - API_LEVEL="${artument#*=}" - shift + --android-api-level=*|-android=*) + API_LEVEL="${argument#*=}" ;; # Checkout the particular tag in the FFmpeg's git repository --source-git-tag=*) SOURCE_TYPE=GIT_TAG - SOURCE_VALUE="${artument#*=}" - shift + SOURCE_VALUE="${argument#*=}" ;; # Checkout the particular branch in the FFmpeg's git repository --source-git-branch=*) SOURCE_TYPE=GIT_BRANCH - SOURCE_VALUE="${artument#*=}" - shift + SOURCE_VALUE="${argument#*=}" ;; # Download the particular tar archive by its version --source-tar=*) SOURCE_TYPE=TAR - SOURCE_VALUE="${artument#*=}" - shift + SOURCE_VALUE="${argument#*=}" + ;; + # Which binutils to use (gnu or llvm) + --binutils=*|-binutils=*) + binutils_value="${argument#*=}" + case $binutils_value in + gnu|llvm) + BINUTILS=$binutils_value + ;; + *) + echo "Unknown binutils: $binutils_value" + ;; + esac ;; # Arguments below enable certain external libraries to build into FFmpeg - --enable-libaom) + --enable-libaom|-aom) EXTERNAL_LIBRARIES+=( "libaom" ) - shift ;; - --enable-libdav1d) + --enable-libdav1d|-dav1d) EXTERNAL_LIBRARIES+=( "libdav1d" ) - shift ;; - --enable-libmp3lame) + --enable-libmp3lame|-mp3lame|-lame) EXTERNAL_LIBRARIES+=( "libmp3lame" ) - shift + ;; + --enable-libopus|-opus) + EXTERNAL_LIBRARIES+=( "libopus" ) + ;; + --enable-libwavpack|-wavpack) + EXTERNAL_LIBRARIES+=( "libwavpack" ) + ;; + --enable-libtwolame|-twolame) + EXTERNAL_LIBRARIES+=( "libtwolame" ) + ;; + --enable-libspeex|-speex) + EXTERNAL_LIBRARIES+=( "libspeex" ) ;; *) - echo "Unknown argument $artument" + echo "Unknown argument $argument" ;; esac + shift done +# if ABIS_TO_BUILD list is empty, then fill it with all supported ABIs +# The x86 is the first, because it is more likely to have Text Relocations. +# In this case the rest ABIs will not be assembled at all. +if [ ${#ABIS_TO_BUILD[@]} -eq 0 ]; then + ABIS_TO_BUILD=( "x86" "x86_64" "armeabi-v7a" "arm64-v8a" ) +fi +# The FFmpeg will be build for ABIs in this list +export FFMPEG_ABIS_TO_BUILD=${ABIS_TO_BUILD[@]} + # Saving the information FFmpeg's source code downloading export FFMPEG_SOURCE_TYPE=$SOURCE_TYPE export FFMPEG_SOURCE_VALUE=$SOURCE_VALUE -# A list of external libraries to build into the FFMpeg +# A list of external libraries to build into the FFmpeg # Elements from this list are used for strings substitution export FFMPEG_EXTERNAL_LIBRARIES=${EXTERNAL_LIBRARIES[@]} # Desired Android API level to use during compilation # Will be replaced with 21 for 64bit ABIs if the value is less than 21 export DESIRED_ANDROID_API_LEVEL=${API_LEVEL} +export DESIRED_BINUTILS=${BINUTILS} diff --git a/tools/docker/Dockerfile b/tools/docker/Dockerfile new file mode 100644 index 0000000..7e1d329 --- /dev/null +++ b/tools/docker/Dockerfile @@ -0,0 +1,70 @@ +FROM ubuntu:20.04 + +# Arguments that can be overridden in 'docker build' command: +# Versions of Android SDK and NDK. The CMake is installed via NDK. +ARG VERSION_SDK=6200805 +ARG VERSION_NDK=21.0.6113669 +ARG VERSION_CMAKE=3.10.2.4988404 + +# Packages to install via apt-get +ARG VERSION_PYTHON3=3.8.2-0ubuntu2 +ARG VERSION_PYTHON3_PIP=20.0.2-5ubuntu1 +ARG VERSION_PYTHON3_SETUPTOOLS=45.2.0-1 +ARG VERSION_PYTHON3_WHEEL=0.34.2-1 +ARG VERSION_NINJA_BUILD=1.10.0-1build1 +ARG VERSION_BUILD_ESSENTIAL=12.8ubuntu1 +ARG VERSION_OPENJDK_8_JDK_HEADLESS=8u252-b09-1ubuntu1 +ARG VERSION_CURL=7.68.0-1ubuntu2 +ARG VERSION_UNZIP=6.0-25ubuntu1 +ARG VERSION_BASH=5.0-6ubuntu1 +ARG VERSION_NASM=2.14.02-1 +ARG VERSION_PKG_CONFIG=0.29.1-0ubuntu4 +ARG VERSION_MAKE=4.2.1-1.2 + +# Package to install via pip3 +ARG VERSION_MESON=0.53.2 + +# The HOME variable isn't available for ENV directive (during building an image). +# So we define one manually. For alpine and ubuntu it should be '/root' +ARG HOME_TWIN=/root + +# Creating mandatory environment variables +ENV ANDROID_SDK_HOME=${HOME_TWIN}/android-sdk +ENV ANDROID_NDK_HOME=${ANDROID_SDK_HOME}/ndk/${VERSION_NDK} + +# Installing basic software +RUN apt-get update && apt-get install -y --no-install-recommends \ + python3=$VERSION_PYTHON3 \ + python3-pip=$VERSION_PYTHON3_PIP \ + python3-setuptools=$VERSION_PYTHON3_SETUPTOOLS \ + python3-wheel=$VERSION_PYTHON3_WHEEL \ + ninja-build=$VERSION_NINJA_BUILD \ + build-essential=$VERSION_BUILD_ESSENTIAL \ + openjdk-8-jdk-headless=$VERSION_OPENJDK_8_JDK_HEADLESS \ + curl=$VERSION_CURL \ + unzip=$VERSION_UNZIP \ + bash=$VERSION_BASH \ + nasm=$VERSION_NASM \ + pkg-config=$VERSION_PKG_CONFIG \ + make=$VERSION_MAKE \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +# Meson has to be installed in a different way +RUN pip3 install meson==$VERSION_MESON + +# Download the Android SDK +RUN curl https://dl.google.com/android/repository/commandlinetools-linux-${VERSION_SDK}_latest.zip --output ${HOME_TWIN}/android-sdk.zip +# Unzip it and remove the archive +RUN mkdir -p ${HOME_TWIN}/android-sdk && \ + unzip -qq ${HOME_TWIN}/android-sdk.zip -d ${HOME_TWIN}/android-sdk && \ + rm ${HOME_TWIN}/android-sdk.zip + +# Installing components through the Android SDK +RUN installAndroidComponent() { yes | ${ANDROID_SDK_HOME}/tools/bin/sdkmanager --sdk_root=${ANDROID_SDK_HOME} "$1" > /dev/null; } && \ + installAndroidComponent "ndk;${VERSION_NDK}" && \ + installAndroidComponent "cmake;${VERSION_CMAKE}" + +# The command to be executed when a container is running +# Passing additional arguments to the script is done via FAM_ARGS environment variable +CMD cd /mnt/ffmpeg-android-maker && ./ffmpeg-android-maker.sh ${FAM_ARGS}