Skip to content

Commit

Permalink
Build IAMF libraries with gradle and ndk-build.
Browse files Browse the repository at this point in the history
In order to support building with `gradle` a new `build.gradle` file was added together with `Android.mk`, `Application.mk`, and `libiamf.mk` necessary for local builds with NDK.

After this change, IAMF files may also be played in the ExoPlayer demo built locally (without blaze).

PiperOrigin-RevId: 664841684
  • Loading branch information
kristinatrajkovski authored and copybara-github committed Aug 19, 2024
1 parent ba00798 commit 63b45b7
Show file tree
Hide file tree
Showing 9 changed files with 249 additions and 7 deletions.
2 changes: 2 additions & 0 deletions core_settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ include modulePrefix + 'lib-decoder-ffmpeg'
project(modulePrefix + 'lib-decoder-ffmpeg').projectDir = new File(rootDir, 'libraries/decoder_ffmpeg')
include modulePrefix + 'lib-decoder-flac'
project(modulePrefix + 'lib-decoder-flac').projectDir = new File(rootDir, 'libraries/decoder_flac')
include modulePrefix + 'lib-decoder-iamf'
project(modulePrefix + 'lib-decoder-iamf').projectDir = new File(rootDir, 'libraries/decoder_iamf')
if (gradle.ext.has('androidxMediaEnableMidiModule') && gradle.ext.androidxMediaEnableMidiModule) {
include modulePrefix + 'lib-decoder-midi'
project(modulePrefix + 'lib-decoder-midi').projectDir = new File(rootDir, 'libraries/decoder_midi')
Expand Down
1 change: 1 addition & 0 deletions demos/main/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ dependencies {
withDecoderExtensionsImplementation project(modulePrefix + 'lib-decoder-ffmpeg')
withDecoderExtensionsImplementation project(modulePrefix + 'lib-decoder-flac')
withDecoderExtensionsImplementation project(modulePrefix + 'lib-decoder-opus')
withDecoderExtensionsImplementation project(modulePrefix + 'lib-decoder-iamf')
withDecoderExtensionsImplementation project(modulePrefix + 'lib-decoder-vp9')
withDecoderExtensionsImplementation project(modulePrefix + 'lib-decoder-midi')
withDecoderExtensionsImplementation project(modulePrefix + 'lib-datasource-rtmp')
Expand Down
120 changes: 120 additions & 0 deletions libraries/decoder_iamf/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
# IAMF decoder module

The IAMF module provides `LibiamfAudioRenderer`, which uses libiamf (the IAMF
decoding library) to decode IAMF audio.

## License note

Please note that whilst the code in this repository is licensed under
[Apache 2.0][], using this module also requires building and including one or
more external libraries as described below. These are licensed separately.

[Apache 2.0]: ../../LICENSE

## Build instructions (Linux, macOS)

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:

* Set the following environment variables:

```
cd "<path to project checkout>"
IAMF_MODULE_PATH="$(pwd)/libraries/decoder_iamf/src/main"
```

* Download the [Android NDK][] and set its location in an environment
variable. This build configuration has been tested on NDK r27.

```
NDK_PATH="<path to Android NDK>"
```

* Fetch libiamf:

Clone the repository containing libiamf to a local folder of choice - preferably
outside of the project checkout. Link it to the project's jni folder through
symlink.

```
cd <preferred location for libiamf>
git clone https://github.com/AOMediaCodec/libiamf.git libiamf && \
cd libiamf && \
LIBIAMF_PATH=$(pwd)
```

* Symlink the folder containing libiamf to the project's JNI folder and run
the script to convert libiamf code to NDK compatible format:

```
cd "${IAMF_MODULE_PATH}"/jni && \
ln -s $LIBIAMF_PATH libiamf && \
cd libiamf/code &&\
cmake . && \
make
```

* Build the JNI native libraries from the command line:

```
cd "${IAMF_MODULE_PATH}"/jni && \
${NDK_PATH}/ndk-build APP_ABI=all -j4
```

[top level README]: ../../README.md
[Android NDK]: https://developer.android.com/tools/sdk/ndk/index.html

## Build instructions (Windows)

We do not provide support for building this module on Windows, however it should
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 libiamf checkout clean and re-build the
project.
* If you want to use your own version of libiamf, place it in
`${IAMF_MODULE_PATH}/jni/libiamf`.

## Using the module with ExoPlayer

Once you've followed the instructions above to check out, build and depend on
the module, the next step is to tell ExoPlayer to use `LibiamfAudioRenderer`.
How you do this depends on which player API you're using:

* If you're passing a `DefaultRenderersFactory` to `ExoPlayer.Builder`, you
can enable using the module by setting the `extensionRendererMode` parameter
of the `DefaultRenderersFactory` constructor to
`EXTENSION_RENDERER_MODE_ON`. This will use `LibiamfAudioRenderer` for
playback if `MediaCodecAudioRenderer` doesn't support the input format. Pass
`EXTENSION_RENDERER_MODE_PREFER` to give `LibiamfAudioRenderer` priority
over `MediaCodecAudioRenderer`.
* If you've subclassed `DefaultRenderersFactory`, add a `LibiamfAudioRenderer`
to the output list in `buildAudioRenderers`. ExoPlayer will use the first
`Renderer` in the list that supports the input media format.
* If you've implemented your own `RenderersFactory`, return a
`LibiamfAudioRenderer` instance from `createRenderers`. ExoPlayer will use
the first `Renderer` in the returned array that supports the input media
format.
* If you're using `ExoPlayer.Builder`, pass a `LibiamfAudioRenderer` in the
array of `Renderer`s. ExoPlayer will use the first `Renderer` in the list
that supports the input media format.

Note: These instructions assume you're using `DefaultTrackSelector`. If you have
a custom track selector the choice of `Renderer` is up to your implementation,
so you need to make sure you are passing a `LibiamfAudioRenderer` to the
player, then implement your own logic to use the renderer for a given track.

## Links

* [Troubleshooting using decoding extensions][]

[Troubleshooting using decoding extensions]: https://developer.android.com/media/media3/exoplayer/troubleshooting#how-can-i-get-a-decoding-library-to-load-and-be-used-for-playback
39 changes: 39 additions & 0 deletions libraries/decoder_iamf/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright (C) 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.
apply from: "$gradle.ext.androidxMediaSettingsDir/common_library_config.gradle"

android {
namespace 'androidx.media3.decoder.iamf'

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'
}
}

dependencies {
implementation project(modulePrefix + 'lib-decoder')
// TODO(b/203752526): Remove this dependency.
implementation project(modulePrefix + 'lib-exoplayer')
implementation 'androidx.annotation:annotation:' + androidxAnnotationVersion
compileOnly 'org.jetbrains.kotlin:kotlin-annotations-jvm:' + kotlinAnnotationsVersion
testImplementation project(modulePrefix + 'test-utils')
testImplementation 'org.robolectric:robolectric:' + robolectricVersion
androidTestImplementation project(modulePrefix + 'test-utils')
androidTestImplementation 'androidx.test:runner:' + androidxTestRunnerVersion
androidTestImplementation 'androidx.test.ext:junit:' + androidxTestJUnitVersion
}
5 changes: 0 additions & 5 deletions libraries/decoder_iamf/src/README.md

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@
*/
package androidx.media3.decoder.iamf;

import static android.support.annotation.VisibleForTesting.PACKAGE_PRIVATE;
import static androidx.annotation.VisibleForTesting.PACKAGE_PRIVATE;

import android.media.AudioFormat;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.media3.common.C;
import androidx.media3.common.util.Util;
Expand All @@ -26,7 +27,6 @@
import androidx.media3.decoder.SimpleDecoderOutputBuffer;
import java.nio.ByteBuffer;
import java.util.List;
import javax.annotation.Nullable;

/** IAMF decoder. */
@VisibleForTesting(otherwise = PACKAGE_PRIVATE)
Expand Down
32 changes: 32 additions & 0 deletions libraries/decoder_iamf/src/main/jni/Android.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#
# Copyright (C) 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.
#
WORKING_DIR := $(call my-dir)
include $(CLEAR_VARS)

# build libiamf.a
LOCAL_PATH := $(WORKING_DIR)
include libiamf.mk

# build libiamfJNI.so
include $(CLEAR_VARS)
LOCAL_PATH := $(WORKING_DIR)
LOCAL_MODULE := libiamfJNI
LOCAL_ARM_MODE := arm
LOCAL_CPP_EXTENSION := .cc
LOCAL_SRC_FILES := iamf_jni.cc
LOCAL_LDLIBS := -llog -lz -lm
LOCAL_STATIC_LIBRARIES := libiamf
include $(BUILD_SHARED_LIBRARY)
18 changes: 18 additions & 0 deletions libraries/decoder_iamf/src/main/jni/Application.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#
# Copyright (C) 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.
#

APP_ABI := all
APP_PLATFORM := android-21
35 changes: 35 additions & 0 deletions libraries/decoder_iamf/src/main/jni/libiamf.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#
# Copyright (C) 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.
#

LOCAL_PATH := $(WORKING_DIR)/libiamf

include $(CLEAR_VARS)

LOCAL_MODULE := libiamf
LOCAL_ARM_MODE := arm
LOCAL_C_INCLUDES := $(LOCAL_PATH)/code/include \
$(LOCAL_PATH)/code/src/iamf_dec \
$(LOCAL_PATH)/code/src/common \
$(LOCAL_PATH)/code/dep_codecs/include \
$(LOCAL_PATH)/code/dep_external/include
LOCAL_SRC_FILES := $(shell find $(LOCAL_PATH)/code/src -name "*.c")
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/code/include \
$(LOCAL_PATH)/code/src/iamf_dec \
$(LOCAL_PATH)/code/src/common \
$(LOCAL_PATH)/code/dep_codecs/include \
$(LOCAL_PATH)/code/dep_external/include

include $(BUILD_STATIC_LIBRARY)

0 comments on commit 63b45b7

Please sign in to comment.