From a2eda3348b40025ef77f0da769164c4cc5b50255 Mon Sep 17 00:00:00 2001 From: rohks Date: Thu, 10 Oct 2024 10:20:45 -0700 Subject: [PATCH] Simplify Opus extension build process Removed `Android.mk` and `Application.mk`, allowing `CMake` to run directly from the build.gradle file. Users no longer need to check out `NDK` or depend on it, simplifying the usage of the Opus extension. PiperOrigin-RevId: 684489927 --- libraries/decoder_opus/README.md | 41 ++++----------- libraries/decoder_opus/build.gradle | 28 ++++++++-- .../decoder_opus/src/main/jni/Android.mk | 35 ------------- .../decoder_opus/src/main/jni/Application.mk | 20 -------- .../decoder_opus/src/main/jni/CMakeLists.txt | 51 +++++++++++++++++++ .../src/main/jni/convert_android_asm.sh | 47 ----------------- .../decoder_opus/src/main/jni/libopus.mk | 50 ------------------ 7 files changed, 86 insertions(+), 186 deletions(-) delete mode 100644 libraries/decoder_opus/src/main/jni/Android.mk delete mode 100644 libraries/decoder_opus/src/main/jni/Application.mk create mode 100644 libraries/decoder_opus/src/main/jni/CMakeLists.txt delete mode 100755 libraries/decoder_opus/src/main/jni/convert_android_asm.sh delete mode 100644 libraries/decoder_opus/src/main/jni/libopus.mk diff --git a/libraries/decoder_opus/README.md b/libraries/decoder_opus/README.md index 2456081e67..5b01e655a9 100644 --- a/libraries/decoder_opus/README.md +++ b/libraries/decoder_opus/README.md @@ -1,7 +1,7 @@ # Opus decoder module -The Opus module provides `LibopusAudioRenderer`, which uses libopus (the Opus -decoding library) to decode Opus audio. +The Opus module provides `LibopusAudioRenderer`, which uses the libopus native +library to decode Opus audio. ## License note @@ -17,7 +17,7 @@ To use the module you need to clone this GitHub project and depend on its modules locally. Instructions for doing this can be found in the [top level README][]. -In addition, it's necessary to build the module's native components as follows: +In addition, it's necessary to fetch libopus as follows: * Set the following environment variables: @@ -26,13 +26,6 @@ cd "" OPUS_MODULE_PATH="$(pwd)/libraries/decoder_opus/src/main" ``` -* Download the [Android NDK][] and set its location in an environment variable. - This build configuration has been tested on NDK r21. - -``` -NDK_PATH="" -``` - * Fetch libopus: ``` @@ -40,21 +33,17 @@ cd "${OPUS_MODULE_PATH}/jni" && \ git clone https://gitlab.xiph.org/xiph/opus.git libopus ``` -* Run the script to convert arm assembly to NDK compatible format: +* [Install CMake][] -``` -cd ${OPUS_MODULE_PATH}/jni && ./convert_android_asm.sh -``` - -* Build the JNI native libraries from the command line: - -``` -cd "${OPUS_MODULE_PATH}"/jni && \ -${NDK_PATH}/ndk-build APP_ABI=all -j4 -``` +Having followed these steps, gradle will build the module automatically when run +on the command line or via Android Studio, using [CMake][] and [Ninja][] to +configure and build libopus and the module's [JNI wrapper library][]. [top level README]: ../../README.md -[Android NDK]: https://developer.android.com/tools/sdk/ndk/index.html +[Install CMake]: https://developer.android.com/studio/projects/install-ndk +[CMake]: https://cmake.org/ +[Ninja]: https://ninja-build.org +[JNI wrapper library]: src/main/jni/opus_jni.cc ## Build instructions (Windows) @@ -63,14 +52,6 @@ be possible to follow the Linux instructions in [Windows PowerShell][]. [Windows PowerShell]: https://docs.microsoft.com/en-us/powershell/scripting/getting-started/getting-started-with-windows-powershell -## Notes - -* Every time there is a change to the libopus checkout: - * Arm assembly should be converted by running `convert_android_asm.sh` - * Clean and re-build the project. -* If you want to use your own version of libopus, place it in - `${OPUS_MODULE_PATH}/jni/libopus`. - ## Using the module with ExoPlayer Once you've followed the instructions above to check out, build and depend on diff --git a/libraries/decoder_opus/build.gradle b/libraries/decoder_opus/build.gradle index 763eba00b1..8c1f7731c4 100644 --- a/libraries/decoder_opus/build.gradle +++ b/libraries/decoder_opus/build.gradle @@ -17,13 +17,17 @@ android { namespace 'androidx.media3.decoder.opus' sourceSets { - main { - jniLibs.srcDir 'src/main/libs' - jni.srcDirs = [] // Disable the automatic ndk-build call by Android Studio. - } androidTest.assets.srcDir '../test_data/src/test/assets' } + defaultConfig { + externalNativeBuild { + cmake { + targets "opusV2JNI" + } + } + } + // TODO(Internal: b/372449691): Remove packagingOptions once AGP is updated // to version 8.5.1 or higher. packagingOptions { @@ -33,6 +37,22 @@ android { } } +// Configure the native build only if libopus is present to avoid gradle sync +// failures if libopus hasn't been built according to the README instructions. +if (project.file('src/main/jni/libopus').exists()) { + android.externalNativeBuild.cmake { + path = 'src/main/jni/CMakeLists.txt' + version = '3.21.0+' + if (project.hasProperty('externalNativeBuildDir')) { + if (!new File(externalNativeBuildDir).isAbsolute()) { + ext.externalNativeBuildDir = + new File(rootDir, it.externalNativeBuildDir) + } + buildStagingDirectory = "${externalNativeBuildDir}/${project.name}" + } + } +} + dependencies { implementation project(modulePrefix + 'lib-decoder') // TODO(b/203752526): Remove this dependency. diff --git a/libraries/decoder_opus/src/main/jni/Android.mk b/libraries/decoder_opus/src/main/jni/Android.mk deleted file mode 100644 index 676774ed49..0000000000 --- a/libraries/decoder_opus/src/main/jni/Android.mk +++ /dev/null @@ -1,35 +0,0 @@ -# -# Copyright (C) 2016 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -WORKING_DIR := $(call my-dir) -include $(CLEAR_VARS) - -# build libopus.a -LOCAL_PATH := $(WORKING_DIR) -include libopus.mk - -# build libopusV2JNI.so -include $(CLEAR_VARS) -LOCAL_PATH := $(WORKING_DIR) -LOCAL_MODULE := libopusV2JNI -LOCAL_ARM_MODE := arm -LOCAL_CPP_EXTENSION := .cc -LOCAL_SRC_FILES := opus_jni.cc -LOCAL_LDLIBS := -llog -lz -lm -LOCAL_STATIC_LIBRARIES := libopus -# Enable 16 KB ELF alignment. -LOCAL_LDFLAGS += "-Wl,-z,max-page-size=16384" -include $(BUILD_SHARED_LIBRARY) diff --git a/libraries/decoder_opus/src/main/jni/Application.mk b/libraries/decoder_opus/src/main/jni/Application.mk deleted file mode 100644 index 7d6f732548..0000000000 --- a/libraries/decoder_opus/src/main/jni/Application.mk +++ /dev/null @@ -1,20 +0,0 @@ -# -# Copyright (C) 2016 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -APP_OPTIM := release -APP_STL := c++_static -APP_CPPFLAGS := -frtti -APP_PLATFORM := android-9 diff --git a/libraries/decoder_opus/src/main/jni/CMakeLists.txt b/libraries/decoder_opus/src/main/jni/CMakeLists.txt new file mode 100644 index 0000000000..de5b62b830 --- /dev/null +++ b/libraries/decoder_opus/src/main/jni/CMakeLists.txt @@ -0,0 +1,51 @@ +# +# Copyright 2024 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +cmake_minimum_required(VERSION 3.21.0 FATAL_ERROR) + +# Enable C++11 features. +set(CMAKE_CXX_STANDARD 11) + +# Define project name for your JNI module +project(libopusJNI C CXX) + +set(libopus_jni_root "${CMAKE_CURRENT_SOURCE_DIR}") + +# Build libopus. +add_subdirectory("${libopus_jni_root}/libopus" + EXCLUDE_FROM_ALL) + +# Add the include directory from libopus. +include_directories ("${libopus_jni_root}/libopus/include") + +# Build libopusJNI. +add_library(opusV2JNI + SHARED + opus_jni.cc) + +# Locate NDK log library. +find_library(android_log_lib log) + +# Link libgav1JNI against used libraries. +target_link_libraries(opusV2JNI + PRIVATE android + PRIVATE opus + PRIVATE ${android_log_lib}) + +# Enable 16 KB ELF alignment. +target_link_options(opusV2JNI + PRIVATE "-Wl,-z,max-page-size=16384") + diff --git a/libraries/decoder_opus/src/main/jni/convert_android_asm.sh b/libraries/decoder_opus/src/main/jni/convert_android_asm.sh deleted file mode 100755 index 48b141dca2..0000000000 --- a/libraries/decoder_opus/src/main/jni/convert_android_asm.sh +++ /dev/null @@ -1,47 +0,0 @@ -#!/bin/bash -# -# Copyright (C) 2016 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -set -eu -ASM_CONVERTER="./libopus/celt/arm/arm2gnu.pl" - -if [[ ! -x "${ASM_CONVERTER}" ]]; then - echo "Please make sure you have checked out libopus." - exit -fi - -while read file; do - # This check is required because the ASM conversion script doesn't seem to be - # idempotent. - if [[ ! "${file}" =~ .*_gnu\.s$ ]]; then - gnu_file="${file%.s}_gnu.s" - ${ASM_CONVERTER} "${file}" > "${gnu_file}" - # The ASM conversion script replaces includes with *_gnu.S. So, replace - # occurences of "*-gnu.S" with "*_gnu.s". - perl -pi -e "s/-gnu\.S/_gnu\.s/g" "${gnu_file}" - rm -f "${file}" - fi -done < <(find -L . -iname '*.s') - -# Generate armopts.s from armopts.s.in -sed \ - -e "s/@OPUS_ARM_MAY_HAVE_EDSP@/1/g" \ - -e "s/@OPUS_ARM_MAY_HAVE_MEDIA@/1/g" \ - -e "s/@OPUS_ARM_MAY_HAVE_NEON@/1/g" \ - libopus/celt/arm/armopts.s.in > libopus/celt/arm/armopts.s.temp -${ASM_CONVERTER} "libopus/celt/arm/armopts.s.temp" > "libopus/celt/arm/armopts_gnu.s" -rm "libopus/celt/arm/armopts.s.temp" -echo "Converted all ASM files and generated armopts.s successfully." diff --git a/libraries/decoder_opus/src/main/jni/libopus.mk b/libraries/decoder_opus/src/main/jni/libopus.mk deleted file mode 100644 index 672df600c0..0000000000 --- a/libraries/decoder_opus/src/main/jni/libopus.mk +++ /dev/null @@ -1,50 +0,0 @@ -# -# Copyright (C) 2016 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -LOCAL_PATH := $(call my-dir)/libopus - -include $(CLEAR_VARS) - -include $(LOCAL_PATH)/celt_headers.mk -include $(LOCAL_PATH)/celt_sources.mk -include $(LOCAL_PATH)/opus_headers.mk -include $(LOCAL_PATH)/opus_sources.mk -include $(LOCAL_PATH)/silk_headers.mk -include $(LOCAL_PATH)/silk_sources.mk - -LOCAL_MODULE := libopus -LOCAL_ARM_MODE := arm -LOCAL_CFLAGS := -DOPUS_BUILD -DFIXED_POINT -DUSE_ALLOCA -DHAVE_LRINT \ - -DHAVE_LRINTF -LOCAL_C_INCLUDES := $(LOCAL_PATH)/include $(LOCAL_PATH)/src \ - $(LOCAL_PATH)/silk $(LOCAL_PATH)/celt \ - $(LOCAL_PATH)/silk/fixed -LOCAL_SRC_FILES := $(CELT_SOURCES) $(OPUS_SOURCES) $(OPUS_SOURCES_FLOAT) \ - $(SILK_SOURCES) $(SILK_SOURCES_FIXED) - -ifneq ($(findstring armeabi-v7a, $(TARGET_ARCH_ABI)),) -LOCAL_SRC_FILES += $(CELT_SOURCES_ARM) -LOCAL_SRC_FILES += celt/arm/armopts_gnu.s.neon -LOCAL_SRC_FILES += $(subst .s,_gnu.s.neon,$(CELT_SOURCES_ARM_ASM)) -LOCAL_CFLAGS += -DOPUS_ARM_ASM -DOPUS_ARM_INLINE_ASM -DOPUS_ARM_INLINE_EDSP \ - -DOPUS_ARM_INLINE_MEDIA -DOPUS_ARM_INLINE_NEON \ - -DOPUS_ARM_MAY_HAVE_NEON -DOPUS_ARM_MAY_HAVE_MEDIA \ - -DOPUS_ARM_MAY_HAVE_EDSP -endif - -LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include - -include $(BUILD_STATIC_LIBRARY)