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
This commit is contained in:
rohks 2024-10-10 10:20:45 -07:00 committed by Copybara-Service
parent 2640ebd58f
commit a2eda3348b
7 changed files with 86 additions and 186 deletions

View File

@ -1,7 +1,7 @@
# Opus decoder module # Opus decoder module
The Opus module provides `LibopusAudioRenderer`, which uses libopus (the Opus The Opus module provides `LibopusAudioRenderer`, which uses the libopus native
decoding library) to decode Opus audio. library to decode Opus audio.
## License note ## 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 modules locally. Instructions for doing this can be found in the
[top level README][]. [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: * Set the following environment variables:
@ -26,13 +26,6 @@ cd "<path to project checkout>"
OPUS_MODULE_PATH="$(pwd)/libraries/decoder_opus/src/main" 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="<path to Android NDK>"
```
* Fetch libopus: * Fetch libopus:
``` ```
@ -40,21 +33,17 @@ cd "${OPUS_MODULE_PATH}/jni" && \
git clone https://gitlab.xiph.org/xiph/opus.git libopus git clone https://gitlab.xiph.org/xiph/opus.git libopus
``` ```
* Run the script to convert arm assembly to NDK compatible format: * [Install CMake][]
``` Having followed these steps, gradle will build the module automatically when run
cd ${OPUS_MODULE_PATH}/jni && ./convert_android_asm.sh on the command line or via Android Studio, using [CMake][] and [Ninja][] to
``` configure and build libopus and the module's [JNI wrapper library][].
* Build the JNI native libraries from the command line:
```
cd "${OPUS_MODULE_PATH}"/jni && \
${NDK_PATH}/ndk-build APP_ABI=all -j4
```
[top level README]: ../../README.md [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) ## 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 [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 ## Using the module with ExoPlayer
Once you've followed the instructions above to check out, build and depend on Once you've followed the instructions above to check out, build and depend on

View File

@ -17,13 +17,17 @@ android {
namespace 'androidx.media3.decoder.opus' namespace 'androidx.media3.decoder.opus'
sourceSets { 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' androidTest.assets.srcDir '../test_data/src/test/assets'
} }
defaultConfig {
externalNativeBuild {
cmake {
targets "opusV2JNI"
}
}
}
// TODO(Internal: b/372449691): Remove packagingOptions once AGP is updated // TODO(Internal: b/372449691): Remove packagingOptions once AGP is updated
// to version 8.5.1 or higher. // to version 8.5.1 or higher.
packagingOptions { 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 { dependencies {
implementation project(modulePrefix + 'lib-decoder') implementation project(modulePrefix + 'lib-decoder')
// TODO(b/203752526): Remove this dependency. // TODO(b/203752526): Remove this dependency.

View File

@ -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)

View File

@ -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

View File

@ -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")

View File

@ -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."

View File

@ -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)