Implement IamfDecoder and LibiamfAudioRenderer configuration.
PiperOrigin-RevId: 655212678
This commit is contained in:
parent
b77f1d0f99
commit
2793ba845e
@ -18,6 +18,7 @@ package androidx.media3.decoder.iamf;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@ -25,6 +26,17 @@ import org.junit.runner.RunWith;
|
||||
/** Test IAMF native functions. */
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public final class IamfDecoderTest {
|
||||
private static final int DEFAULT_BINAURAL_LAYOUT_CHANNEL_COUNT = 2;
|
||||
|
||||
// Sample configOBUs data from sample_iamf.mp4 file.
|
||||
private static final byte[] IACB_OBUS = {
|
||||
-8, 6, 105, 97, 109, 102, 0, 0, 0, 15, -56, 1, 105, 112, 99, 109, 64, 0, 0, 1, 16, 0, 0, 62,
|
||||
-128, 8, 12, -84, 2, 0, -56, 1, 1, 0, 0, 32, 16, 1, 1, 16, 78, 42, 1, 101, 110, 45, 117, 115, 0,
|
||||
116, 101, 115, 116, 95, 109, 105, 120, 95, 112, 114, 101, 115, 0, 1, 1, -84, 2, 116, 101, 115,
|
||||
116, 95, 115, 117, 98, 95, 109, 105, 120, 95, 48, 95, 97, 117, 100, 105, 111, 95, 101, 108, 101,
|
||||
109, 101, 110, 116, 95, 48, 0, 0, 0, 100, -128, 125, -128, 0, 0, 100, -128, 125, -128, 0, 0, 1,
|
||||
-128, 0, -54, 81, -51, -79
|
||||
};
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
@ -32,8 +44,10 @@ public final class IamfDecoderTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void iamfLayoutBinauralChannelsCountTest() {
|
||||
IamfDecoder iamf = new IamfDecoder();
|
||||
assertThat(iamf.getBinauralLayoutChannelCount()).isEqualTo(2);
|
||||
public void iamfBinauralLayoutChannelsCount_equalsTwo() throws Exception {
|
||||
IamfDecoder iamf = new IamfDecoder(ImmutableList.of(IACB_OBUS));
|
||||
|
||||
assertThat(iamf.getBinauralLayoutChannelCount())
|
||||
.isEqualTo(DEFAULT_BINAURAL_LAYOUT_CHANNEL_COUNT);
|
||||
}
|
||||
}
|
||||
|
@ -21,14 +21,31 @@ import androidx.annotation.VisibleForTesting;
|
||||
import androidx.media3.decoder.DecoderInputBuffer;
|
||||
import androidx.media3.decoder.SimpleDecoder;
|
||||
import androidx.media3.decoder.SimpleDecoderOutputBuffer;
|
||||
import java.util.List;
|
||||
|
||||
/** IAMF decoder. */
|
||||
@VisibleForTesting(otherwise = PACKAGE_PRIVATE)
|
||||
public final class IamfDecoder
|
||||
extends SimpleDecoder<DecoderInputBuffer, SimpleDecoderOutputBuffer, IamfDecoderException> {
|
||||
|
||||
public IamfDecoder() {
|
||||
/**
|
||||
* Creates an IAMF decoder.
|
||||
*
|
||||
* @param initializationData ConfigOBUs data for the decoder.
|
||||
* @throws IamfDecoderException Thrown if an exception occurs when initializing the decoder.
|
||||
*/
|
||||
public IamfDecoder(List<byte[]> initializationData) throws IamfDecoderException {
|
||||
super(new DecoderInputBuffer[0], new SimpleDecoderOutputBuffer[0]);
|
||||
int status = iamfConfigDecoder(initializationData.get(0));
|
||||
if (status != 0) {
|
||||
throw new IamfDecoderException("Failed to configure decoder with returned status: " + status);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void release() {
|
||||
super.release();
|
||||
iamfClose();
|
||||
}
|
||||
|
||||
public int getBinauralLayoutChannelCount() {
|
||||
@ -42,17 +59,17 @@ public final class IamfDecoder
|
||||
|
||||
@Override
|
||||
protected DecoderInputBuffer createInputBuffer() {
|
||||
throw new UnsupportedOperationException();
|
||||
return new DecoderInputBuffer(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_DIRECT);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SimpleDecoderOutputBuffer createOutputBuffer() {
|
||||
throw new UnsupportedOperationException();
|
||||
return new SimpleDecoderOutputBuffer(this::releaseOutputBuffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IamfDecoderException createUnexpectedDecodeException(Throwable error) {
|
||||
throw new UnsupportedOperationException();
|
||||
return new IamfDecoderException("Unexpected decode error", error);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -62,4 +79,8 @@ public final class IamfDecoder
|
||||
}
|
||||
|
||||
private native int iamfLayoutBinauralChannelsCount();
|
||||
|
||||
private native int iamfConfigDecoder(byte[] initializationData);
|
||||
|
||||
private native void iamfClose();
|
||||
}
|
||||
|
@ -15,25 +15,67 @@
|
||||
*/
|
||||
package androidx.media3.decoder.iamf;
|
||||
|
||||
import android.os.Handler;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.media3.common.C;
|
||||
import androidx.media3.common.Format;
|
||||
import androidx.media3.common.MimeTypes;
|
||||
import androidx.media3.common.audio.AudioProcessor;
|
||||
import androidx.media3.common.util.TraceUtil;
|
||||
import androidx.media3.decoder.CryptoConfig;
|
||||
import androidx.media3.decoder.DecoderException;
|
||||
import androidx.media3.exoplayer.audio.AudioRendererEventListener;
|
||||
import androidx.media3.exoplayer.audio.AudioSink;
|
||||
import androidx.media3.exoplayer.audio.DecoderAudioRenderer;
|
||||
|
||||
/** Decodes and renders audio using the native IAMF decoder. */
|
||||
public class LibiamfAudioRenderer extends DecoderAudioRenderer<IamfDecoder> {
|
||||
public LibiamfAudioRenderer() {}
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param eventHandler A handler to use when delivering events to {@code eventListener}. May be
|
||||
* null if delivery of events is not required.
|
||||
* @param eventListener A listener of events. May be null if delivery of events is not required.
|
||||
* @param audioProcessors Optional {@link AudioProcessor}s that will process audio before output.
|
||||
*/
|
||||
public LibiamfAudioRenderer(
|
||||
@Nullable Handler eventHandler,
|
||||
@Nullable AudioRendererEventListener eventListener,
|
||||
AudioProcessor... audioProcessors) {
|
||||
super(eventHandler, eventListener, audioProcessors);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param eventHandler A handler to use when delivering events to {@code eventListener}. May be
|
||||
* null if delivery of events is not required.
|
||||
* @param eventListener A listener of events. May be null if delivery of events is not required.
|
||||
* @param audioSink The sink to which audio will be output.
|
||||
*/
|
||||
public LibiamfAudioRenderer(
|
||||
@Nullable Handler eventHandler,
|
||||
@Nullable AudioRendererEventListener eventListener,
|
||||
AudioSink audioSink) {
|
||||
super(eventHandler, eventListener, audioSink);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int supportsFormatInternal(Format format) {
|
||||
throw new UnsupportedOperationException();
|
||||
return !IamfLibrary.isAvailable()
|
||||
|| !java.util.Objects.equals(format.sampleMimeType, MimeTypes.AUDIO_IAMF)
|
||||
? C.FORMAT_UNSUPPORTED_TYPE
|
||||
: C.FORMAT_HANDLED;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IamfDecoder createDecoder(Format format, @Nullable CryptoConfig cryptoConfig)
|
||||
throws DecoderException {
|
||||
throw new UnsupportedOperationException();
|
||||
TraceUtil.beginSection("createIamfDecoder");
|
||||
IamfDecoder decoder = new IamfDecoder(format.initializationData);
|
||||
TraceUtil.endSection();
|
||||
return decoder;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -43,6 +85,6 @@ public class LibiamfAudioRenderer extends DecoderAudioRenderer<IamfDecoder> {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
throw new UnsupportedOperationException();
|
||||
return "LibiamfAudioRenderer";
|
||||
}
|
||||
}
|
||||
|
@ -53,3 +53,29 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved) {
|
||||
DECODER_FUNC(jint, iamfLayoutBinauralChannelsCount) {
|
||||
return IAMF_layout_binaural_channels_count();
|
||||
}
|
||||
|
||||
IAMF_DecoderHandle handle;
|
||||
|
||||
DECODER_FUNC(jint, iamfConfigDecoder, jbyteArray initializationDataArray) {
|
||||
handle = IAMF_decoder_open();
|
||||
IAMF_decoder_peak_limiter_enable(handle, 0);
|
||||
IAMF_decoder_peak_limiter_set_threshold(handle, -1.0f);
|
||||
IAMF_decoder_set_normalization_loudness(handle, 0.0f);
|
||||
IAMF_decoder_set_bit_depth(handle, 16);
|
||||
IAMF_decoder_set_sampling_rate(handle, 48000);
|
||||
IAMF_decoder_output_layout_set_binaural(handle);
|
||||
IAMF_decoder_set_pts(handle, 0, 90000);
|
||||
|
||||
uint32_t* bytes_read = nullptr;
|
||||
jbyte* initializationDataBytes =
|
||||
env->GetByteArrayElements(initializationDataArray, 0);
|
||||
|
||||
int status = IAMF_decoder_configure(
|
||||
handle, reinterpret_cast<uint8_t*>(initializationDataBytes),
|
||||
env->GetArrayLength(initializationDataArray), bytes_read);
|
||||
env->ReleaseByteArrayElements(initializationDataArray,
|
||||
initializationDataBytes, 0);
|
||||
return status;
|
||||
}
|
||||
|
||||
DECODER_FUNC(void, iamfClose) { IAMF_decoder_close(handle); }
|
||||
|
Loading…
x
Reference in New Issue
Block a user