diff --git a/libraries/decoder_iamf/src/README.md b/libraries/decoder_iamf/src/README.md
new file mode 100644
index 0000000000..1521829a01
--- /dev/null
+++ b/libraries/decoder_iamf/src/README.md
@@ -0,0 +1,5 @@
+# IAMF support in ExoPlayer
+
+This is a Work-In-Progress for an extension which shall provide support for IAMF
+in Exoplayer. Please await further announcements via Release Notes for
+information on the full integration into the library.
diff --git a/libraries/decoder_iamf/src/androidTest/AndroidManifest.xml b/libraries/decoder_iamf/src/androidTest/AndroidManifest.xml
new file mode 100644
index 0000000000..6ce4dad5d8
--- /dev/null
+++ b/libraries/decoder_iamf/src/androidTest/AndroidManifest.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/libraries/decoder_iamf/src/androidTest/java/androidx/media3/decoder/iamf/IamfDecoderTest.java b/libraries/decoder_iamf/src/androidTest/java/androidx/media3/decoder/iamf/IamfDecoderTest.java
new file mode 100644
index 0000000000..6fe1ffcd19
--- /dev/null
+++ b/libraries/decoder_iamf/src/androidTest/java/androidx/media3/decoder/iamf/IamfDecoderTest.java
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+package androidx.media3.decoder.iamf;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/** Test IAMF native functions. */
+@RunWith(AndroidJUnit4.class)
+public final class IamfDecoderTest {
+
+ @Before
+ public void setUp() {
+ assertThat(IamfLibrary.isAvailable()).isTrue();
+ }
+
+ @Test
+ public void iamfLayoutBinauralChannelsCountTest() {
+ IamfDecoder iamf = new IamfDecoder();
+ assertThat(iamf.getBinauralLayoutChannelCount()).isEqualTo(2);
+ }
+}
diff --git a/libraries/decoder_iamf/src/main/java/androidx/media3/decoder/iamf/IamfDecoder.java b/libraries/decoder_iamf/src/main/java/androidx/media3/decoder/iamf/IamfDecoder.java
new file mode 100644
index 0000000000..cbea45637c
--- /dev/null
+++ b/libraries/decoder_iamf/src/main/java/androidx/media3/decoder/iamf/IamfDecoder.java
@@ -0,0 +1,65 @@
+/*
+ * 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.
+ */
+package androidx.media3.decoder.iamf;
+
+import static android.support.annotation.VisibleForTesting.PACKAGE_PRIVATE;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.media3.decoder.DecoderInputBuffer;
+import androidx.media3.decoder.SimpleDecoder;
+import androidx.media3.decoder.SimpleDecoderOutputBuffer;
+
+/** IAMF decoder. */
+@VisibleForTesting(otherwise = PACKAGE_PRIVATE)
+public final class IamfDecoder
+ extends SimpleDecoder {
+
+ public IamfDecoder() {
+ super(new DecoderInputBuffer[0], new SimpleDecoderOutputBuffer[0]);
+ }
+
+ public int getBinauralLayoutChannelCount() {
+ return iamfLayoutBinauralChannelsCount();
+ }
+
+ @Override
+ public String getName() {
+ return "libiamf";
+ }
+
+ @Override
+ protected DecoderInputBuffer createInputBuffer() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ protected SimpleDecoderOutputBuffer createOutputBuffer() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ protected IamfDecoderException createUnexpectedDecodeException(Throwable error) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ protected IamfDecoderException decode(
+ DecoderInputBuffer inputBuffer, SimpleDecoderOutputBuffer outputBuffer, boolean reset) {
+ throw new UnsupportedOperationException();
+ }
+
+ private native int iamfLayoutBinauralChannelsCount();
+}
diff --git a/libraries/decoder_iamf/src/main/java/androidx/media3/decoder/iamf/IamfDecoderException.java b/libraries/decoder_iamf/src/main/java/androidx/media3/decoder/iamf/IamfDecoderException.java
new file mode 100644
index 0000000000..18c25601d1
--- /dev/null
+++ b/libraries/decoder_iamf/src/main/java/androidx/media3/decoder/iamf/IamfDecoderException.java
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+package androidx.media3.decoder.iamf;
+
+import androidx.media3.decoder.DecoderException;
+
+/** Thrown when an IAMF decoder error occurs. */
+final class IamfDecoderException extends DecoderException {
+
+ /* package */ IamfDecoderException(String message) {
+ super(message);
+ }
+
+ /* package */ IamfDecoderException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/libraries/decoder_iamf/src/main/java/androidx/media3/decoder/iamf/IamfLibrary.java b/libraries/decoder_iamf/src/main/java/androidx/media3/decoder/iamf/IamfLibrary.java
new file mode 100644
index 0000000000..41a6c75959
--- /dev/null
+++ b/libraries/decoder_iamf/src/main/java/androidx/media3/decoder/iamf/IamfLibrary.java
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+package androidx.media3.decoder.iamf;
+
+import androidx.media3.common.C;
+import androidx.media3.common.MediaLibraryInfo;
+import androidx.media3.common.util.LibraryLoader;
+import androidx.media3.common.util.UnstableApi;
+
+/** Configures and queries the underlying native library. */
+@UnstableApi
+public final class IamfLibrary {
+
+ static {
+ MediaLibraryInfo.registerModule("media3.decoder.iamf");
+ }
+
+ private static final LibraryLoader LOADER =
+ new LibraryLoader("iamfJNI") {
+ @Override
+ protected void loadLibrary(String name) {
+ System.loadLibrary(name);
+ }
+ };
+
+ private IamfLibrary() {}
+
+ /**
+ * Override the names of the IAMF native libraries. If an application wishes to call this method,
+ * it must do so before calling any other method defined by this class, and before instantiating a
+ * {@link LibiamfAudioRenderer} instance.
+ *
+ * @param cryptoType The {@link C.CryptoType} for which the decoder library supports decrypting
+ * protected content, or {@link C#CRYPTO_TYPE_UNSUPPORTED} if the library does not support
+ * decryption.
+ * @param libraries The names of the IAMF native libraries.
+ */
+ public static void setLibraries(@C.CryptoType int cryptoType, String... libraries) {
+ LOADER.setLibraries(libraries);
+ }
+
+ /** Returns whether the underlying library is available, loading it if necessary. */
+ public static boolean isAvailable() {
+ return LOADER.isAvailable();
+ }
+}
diff --git a/libraries/decoder_iamf/src/main/java/androidx/media3/decoder/iamf/LibiamfAudioRenderer.java b/libraries/decoder_iamf/src/main/java/androidx/media3/decoder/iamf/LibiamfAudioRenderer.java
new file mode 100644
index 0000000000..18c0abf511
--- /dev/null
+++ b/libraries/decoder_iamf/src/main/java/androidx/media3/decoder/iamf/LibiamfAudioRenderer.java
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+package androidx.media3.decoder.iamf;
+
+import androidx.annotation.Nullable;
+import androidx.media3.common.Format;
+import androidx.media3.decoder.CryptoConfig;
+import androidx.media3.decoder.DecoderException;
+import androidx.media3.exoplayer.audio.DecoderAudioRenderer;
+
+/** Decodes and renders audio using the native IAMF decoder. */
+public class LibiamfAudioRenderer extends DecoderAudioRenderer {
+ public LibiamfAudioRenderer() {}
+
+ @Override
+ protected int supportsFormatInternal(Format format) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ protected IamfDecoder createDecoder(Format format, @Nullable CryptoConfig cryptoConfig)
+ throws DecoderException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ protected Format getOutputFormat(IamfDecoder decoder) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public String getName() {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/libraries/decoder_iamf/src/main/java/androidx/media3/decoder/iamf/package-info.java b/libraries/decoder_iamf/src/main/java/androidx/media3/decoder/iamf/package-info.java
new file mode 100644
index 0000000000..036d745506
--- /dev/null
+++ b/libraries/decoder_iamf/src/main/java/androidx/media3/decoder/iamf/package-info.java
@@ -0,0 +1,19 @@
+/*
+ * 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.
+ */
+@NonNullApi
+package androidx.media3.decoder.iamf;
+
+import androidx.media3.common.util.NonNullApi;
diff --git a/libraries/decoder_iamf/src/main/jni/iamf_jni.cc b/libraries/decoder_iamf/src/main/jni/iamf_jni.cc
new file mode 100644
index 0000000000..fbd7f2fda5
--- /dev/null
+++ b/libraries/decoder_iamf/src/main/jni/iamf_jni.cc
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+
+#ifdef __ANDROID__
+#include
+#endif
+#include
+
+#include
+#include
+
+#include "IAMF_decoder.h"
+#include "IAMF_defines.h"
+
+#ifdef __ANDROID__
+#define LOG_TAG "iamf_jni"
+#define LOGE(...) \
+ ((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__))
+#else // __ANDROID__
+#define LOGE(...) \
+ do { \
+ } while (0)
+#endif // __ANDROID__
+
+#define DECODER_FUNC(RETURN_TYPE, NAME, ...) \
+ extern "C" { \
+ JNIEXPORT RETURN_TYPE Java_androidx_media3_decoder_iamf_IamfDecoder_##NAME( \
+ JNIEnv* env, jobject thiz, ##__VA_ARGS__); \
+ } \
+ JNIEXPORT RETURN_TYPE Java_androidx_media3_decoder_iamf_IamfDecoder_##NAME( \
+ JNIEnv* env, jobject thiz, ##__VA_ARGS__)
+
+jint JNI_OnLoad(JavaVM* vm, void* reserved) {
+ JNIEnv* env;
+ if (vm->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_6) != JNI_OK) {
+ return -1;
+ }
+ return JNI_VERSION_1_6;
+}
+DECODER_FUNC(jint, iamfLayoutBinauralChannelsCount) {
+ return IAMF_layout_binaural_channels_count();
+}
diff --git a/libraries/decoder_iamf/src/main/proguard-rules.txt b/libraries/decoder_iamf/src/main/proguard-rules.txt
new file mode 100755
index 0000000000..7b4eaa0243
--- /dev/null
+++ b/libraries/decoder_iamf/src/main/proguard-rules.txt
@@ -0,0 +1,6 @@
+# Proguard rules specific to the IAMF extension.
+
+# This prevents the names of native methods from being obfuscated.
+-keepclasseswithmembernames class * {
+ native ;
+}