Collect configuration values in IamfDecoder
.
Instead of hard-coding values in multiple files, all default values are declared in `IamfDecoder`. Additionally, the max number of frames used for output buffer initialisation is fetched from `libiamf` native functions. PiperOrigin-RevId: 658772175
This commit is contained in:
parent
9ace81bf2f
commit
20df8b282a
@ -2315,19 +2315,30 @@ public final class Util {
|
||||
*/
|
||||
@UnstableApi
|
||||
public static int getPcmFrameSize(@C.PcmEncoding int pcmEncoding, int channelCount) {
|
||||
return getByteDepth(pcmEncoding) * channelCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the byte depth for audio with the specified encoding.
|
||||
*
|
||||
* @param pcmEncoding The encoding of the audio data.
|
||||
* @return The byte depth of the audio.
|
||||
*/
|
||||
@UnstableApi
|
||||
public static int getByteDepth(@C.PcmEncoding int pcmEncoding) {
|
||||
switch (pcmEncoding) {
|
||||
case C.ENCODING_PCM_8BIT:
|
||||
return channelCount;
|
||||
return 1;
|
||||
case C.ENCODING_PCM_16BIT:
|
||||
case C.ENCODING_PCM_16BIT_BIG_ENDIAN:
|
||||
return channelCount * 2;
|
||||
return 2;
|
||||
case C.ENCODING_PCM_24BIT:
|
||||
case C.ENCODING_PCM_24BIT_BIG_ENDIAN:
|
||||
return channelCount * 3;
|
||||
return 3;
|
||||
case C.ENCODING_PCM_32BIT:
|
||||
case C.ENCODING_PCM_32BIT_BIG_ENDIAN:
|
||||
case C.ENCODING_PCM_FLOAT:
|
||||
return channelCount * 4;
|
||||
return 4;
|
||||
case C.ENCODING_INVALID:
|
||||
case Format.NO_VALUE:
|
||||
default:
|
||||
|
@ -18,6 +18,7 @@ package androidx.media3.decoder.iamf;
|
||||
import static android.support.annotation.VisibleForTesting.PACKAGE_PRIVATE;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.media3.common.C;
|
||||
import androidx.media3.common.util.Util;
|
||||
import androidx.media3.decoder.DecoderInputBuffer;
|
||||
import androidx.media3.decoder.SimpleDecoder;
|
||||
@ -30,9 +31,10 @@ import javax.annotation.Nullable;
|
||||
@VisibleForTesting(otherwise = PACKAGE_PRIVATE)
|
||||
public final class IamfDecoder
|
||||
extends SimpleDecoder<DecoderInputBuffer, SimpleDecoderOutputBuffer, IamfDecoderException> {
|
||||
|
||||
// TODO(ktrajkovski): Find the maximum acceptable output buffer size.
|
||||
private static final int DEFAULT_OUTPUT_BUFFER_SIZE = 4096;
|
||||
// TODO(ktrajkovski): Fetch channel count from the device instead of hardcoding.
|
||||
/* package */ static final int DEFAULT_CHANNEL_COUNT = 2;
|
||||
/* package */ static final int DEFAULT_OUTPUT_SAMPLE_RATE = 48000;
|
||||
/* package */ static final @C.PcmEncoding int DEFAULT_PCM_ENCODING = C.ENCODING_PCM_16BIT;
|
||||
|
||||
private final byte[] initializationData;
|
||||
|
||||
@ -48,7 +50,12 @@ public final class IamfDecoder
|
||||
throw new IamfDecoderException("Initialization data must contain a single element.");
|
||||
}
|
||||
this.initializationData = initializationData.get(0);
|
||||
int status = iamfConfigDecoder(this.initializationData);
|
||||
int status =
|
||||
iamfConfigDecoder(
|
||||
this.initializationData,
|
||||
Util.getByteDepth(DEFAULT_PCM_ENCODING) * C.BITS_PER_BYTE,
|
||||
DEFAULT_OUTPUT_SAMPLE_RATE,
|
||||
DEFAULT_CHANNEL_COUNT);
|
||||
if (status != 0) {
|
||||
throw new IamfDecoderException("Failed to configure decoder with returned status: " + status);
|
||||
}
|
||||
@ -90,9 +97,15 @@ public final class IamfDecoder
|
||||
DecoderInputBuffer inputBuffer, SimpleDecoderOutputBuffer outputBuffer, boolean reset) {
|
||||
if (reset) {
|
||||
iamfClose();
|
||||
iamfConfigDecoder(this.initializationData); // reconfigure
|
||||
iamfConfigDecoder(
|
||||
this.initializationData,
|
||||
Util.getByteDepth(DEFAULT_PCM_ENCODING) * C.BITS_PER_BYTE,
|
||||
DEFAULT_OUTPUT_SAMPLE_RATE,
|
||||
DEFAULT_CHANNEL_COUNT); // reconfigure
|
||||
}
|
||||
outputBuffer.init(inputBuffer.timeUs, DEFAULT_OUTPUT_BUFFER_SIZE);
|
||||
int bufferSize =
|
||||
iamfGetMaxFrameSize() * DEFAULT_CHANNEL_COUNT * Util.getByteDepth(DEFAULT_PCM_ENCODING);
|
||||
outputBuffer.init(inputBuffer.timeUs, bufferSize);
|
||||
ByteBuffer outputData = Util.castNonNull(outputBuffer.data);
|
||||
ByteBuffer inputData = Util.castNonNull(inputBuffer.data);
|
||||
int ret = iamfDecode(inputData, inputData.limit(), outputData);
|
||||
@ -100,17 +113,22 @@ public final class IamfDecoder
|
||||
return new IamfDecoderException("Failed to decode error= " + ret);
|
||||
}
|
||||
outputData.position(0);
|
||||
// TODO(ktrajkovski): Extract the outputData limit from the iamfDecode return value, given
|
||||
// channel count, and given bit depth.
|
||||
outputData.limit(ret * 4); // x2 for expected bit depth, x2 for channel count
|
||||
outputData.limit(ret * DEFAULT_CHANNEL_COUNT * Util.getByteDepth(DEFAULT_PCM_ENCODING));
|
||||
return null;
|
||||
}
|
||||
|
||||
private native int iamfLayoutBinauralChannelsCount();
|
||||
|
||||
private native int iamfConfigDecoder(byte[] initializationData);
|
||||
private native int iamfConfigDecoder(
|
||||
byte[] initializationData, int bitDepth, int sampleRate, int channelCount);
|
||||
|
||||
private native void iamfClose();
|
||||
|
||||
private native int iamfDecode(ByteBuffer inputBuffer, int inputSize, ByteBuffer outputBuffer);
|
||||
|
||||
/**
|
||||
* Returns the maximum expected number of PCM samples per channel in a compressed audio frame.
|
||||
* Used to initialize the output buffer.
|
||||
*/
|
||||
private native int iamfGetMaxFrameSize();
|
||||
}
|
||||
|
@ -33,12 +33,6 @@ import java.util.Objects;
|
||||
/** Decodes and renders audio using the native IAMF decoder. */
|
||||
public class LibiamfAudioRenderer extends DecoderAudioRenderer<IamfDecoder> {
|
||||
|
||||
// TODO(ktrajkovski): Values need to be configured and must come from the same source of truth as
|
||||
// in {@link IamfDecoder}.
|
||||
private static final int BINAURAL_CHANNEL_COUNT = 2;
|
||||
private static final int DEFAULT_OUTPUT_SAMPLE_RATE = 48000;
|
||||
private static final int DEFAULT_PCM_ENCODING = C.ENCODING_PCM_16BIT;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
@ -89,7 +83,9 @@ public class LibiamfAudioRenderer extends DecoderAudioRenderer<IamfDecoder> {
|
||||
@Override
|
||||
protected Format getOutputFormat(IamfDecoder decoder) {
|
||||
return Util.getPcmFormat(
|
||||
DEFAULT_PCM_ENCODING, BINAURAL_CHANNEL_COUNT, DEFAULT_OUTPUT_SAMPLE_RATE);
|
||||
IamfDecoder.DEFAULT_PCM_ENCODING,
|
||||
IamfDecoder.DEFAULT_CHANNEL_COUNT,
|
||||
IamfDecoder.DEFAULT_OUTPUT_SAMPLE_RATE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -56,18 +56,17 @@ DECODER_FUNC(jint, iamfLayoutBinauralChannelsCount) {
|
||||
|
||||
IAMF_DecoderHandle handle;
|
||||
|
||||
DECODER_FUNC(jint, iamfConfigDecoder, jbyteArray initializationDataArray) {
|
||||
DECODER_FUNC(jint, iamfConfigDecoder, jbyteArray initializationDataArray,
|
||||
jint bitDepth, jint sampleRate, jint channelCount) {
|
||||
handle = IAMF_decoder_open();
|
||||
|
||||
// TODO(ktrajkovski): Values need to be aligned with IamfDecoder and
|
||||
// LibiamfAudioRenderer and/or extracted from ConfigOBUs.
|
||||
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);
|
||||
IAMF_decoder_set_bit_depth(handle, bitDepth);
|
||||
IAMF_decoder_set_sampling_rate(handle, sampleRate);
|
||||
if (channelCount == 2) {
|
||||
IAMF_decoder_output_layout_set_binaural(handle);
|
||||
} else {
|
||||
IAMF_decoder_output_layout_set_sound_system(handle, SOUND_SYSTEM_INVALID);
|
||||
}
|
||||
|
||||
uint32_t* bytes_read = nullptr;
|
||||
jbyte* initializationDataBytes =
|
||||
@ -92,4 +91,8 @@ DECODER_FUNC(jint, iamfDecode, jobject inputBuffer, jint inputSize,
|
||||
reinterpret_cast<void*>(env->GetDirectBufferAddress(outputBuffer)));
|
||||
}
|
||||
|
||||
DECODER_FUNC(jint, iamfGetMaxFrameSize) {
|
||||
return IAMF_decoder_get_stream_info(handle)->max_frame_size;
|
||||
}
|
||||
|
||||
DECODER_FUNC(void, iamfClose) { IAMF_decoder_close(handle); }
|
||||
|
Loading…
x
Reference in New Issue
Block a user