Trim CodecDelay/PreSkip In New OpusDecoder Instances By Default
PiperOrigin-RevId: 427819209
This commit is contained in:
parent
1af8d57032
commit
8d09da4abf
@ -99,6 +99,7 @@ public final class OpusDecoder
|
|||||||
}
|
}
|
||||||
preSkipSamples = getPreSkipSamples(initializationData);
|
preSkipSamples = getPreSkipSamples(initializationData);
|
||||||
seekPreRollSamples = getSeekPreRollSamples(initializationData);
|
seekPreRollSamples = getSeekPreRollSamples(initializationData);
|
||||||
|
skipSamples = preSkipSamples;
|
||||||
|
|
||||||
byte[] headerBytes = initializationData.get(0);
|
byte[] headerBytes = initializationData.get(0);
|
||||||
if (headerBytes.length < 19) {
|
if (headerBytes.length < 19) {
|
||||||
|
@ -17,11 +17,16 @@ package androidx.media3.decoder.opus;
|
|||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
import androidx.media3.common.C;
|
import androidx.media3.common.C;
|
||||||
|
import androidx.media3.common.util.LibraryLoader;
|
||||||
|
import androidx.media3.decoder.DecoderInputBuffer;
|
||||||
|
import androidx.media3.decoder.SimpleDecoderOutputBuffer;
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.ByteOrder;
|
import java.nio.ByteOrder;
|
||||||
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
@ -29,9 +34,14 @@ import org.junit.runner.RunWith;
|
|||||||
@RunWith(AndroidJUnit4.class)
|
@RunWith(AndroidJUnit4.class)
|
||||||
public final class OpusDecoderTest {
|
public final class OpusDecoderTest {
|
||||||
|
|
||||||
|
private static final LibraryLoader LOADER = new LibraryLoader("opusV2JNI");
|
||||||
|
|
||||||
private static final byte[] HEADER =
|
private static final byte[] HEADER =
|
||||||
new byte[] {79, 112, 117, 115, 72, 101, 97, 100, 0, 2, 1, 56, 0, 0, -69, -128, 0, 0, 0};
|
new byte[] {79, 112, 117, 115, 72, 101, 97, 100, 0, 2, 1, 56, 0, 0, -69, -128, 0, 0, 0};
|
||||||
|
|
||||||
|
private static final byte[] ENCODED_DATA = new byte[] {-4};
|
||||||
|
private static final int DECODED_DATA_SIZE = 3840;
|
||||||
|
|
||||||
private static final int HEADER_PRE_SKIP_SAMPLES = 14337;
|
private static final int HEADER_PRE_SKIP_SAMPLES = 14337;
|
||||||
|
|
||||||
private static final int DEFAULT_SEEK_PRE_ROLL_SAMPLES = 3840;
|
private static final int DEFAULT_SEEK_PRE_ROLL_SAMPLES = 3840;
|
||||||
@ -39,6 +49,7 @@ public final class OpusDecoderTest {
|
|||||||
private static final ImmutableList<byte[]> HEADER_ONLY_INITIALIZATION_DATA =
|
private static final ImmutableList<byte[]> HEADER_ONLY_INITIALIZATION_DATA =
|
||||||
ImmutableList.of(HEADER);
|
ImmutableList.of(HEADER);
|
||||||
|
|
||||||
|
private static final long PRE_SKIP_NANOS = 6_500_000;
|
||||||
private static final long CUSTOM_PRE_SKIP_SAMPLES = 28674;
|
private static final long CUSTOM_PRE_SKIP_SAMPLES = 28674;
|
||||||
private static final byte[] CUSTOM_PRE_SKIP_BYTES =
|
private static final byte[] CUSTOM_PRE_SKIP_BYTES =
|
||||||
buildNativeOrderByteArray(sampleCountToNanoseconds(CUSTOM_PRE_SKIP_SAMPLES));
|
buildNativeOrderByteArray(sampleCountToNanoseconds(CUSTOM_PRE_SKIP_SAMPLES));
|
||||||
@ -50,6 +61,11 @@ public final class OpusDecoderTest {
|
|||||||
private static final ImmutableList<byte[]> FULL_INITIALIZATION_DATA =
|
private static final ImmutableList<byte[]> FULL_INITIALIZATION_DATA =
|
||||||
ImmutableList.of(HEADER, CUSTOM_PRE_SKIP_BYTES, CUSTOM_SEEK_PRE_ROLL_BYTES);
|
ImmutableList.of(HEADER, CUSTOM_PRE_SKIP_BYTES, CUSTOM_SEEK_PRE_ROLL_BYTES);
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
assertThat(LOADER.isAvailable()).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getChannelCount() {
|
public void getChannelCount() {
|
||||||
int channelCount = OpusDecoder.getChannelCount(HEADER);
|
int channelCount = OpusDecoder.getChannelCount(HEADER);
|
||||||
@ -80,11 +96,56 @@ public final class OpusDecoderTest {
|
|||||||
assertThat(seekPreRollSamples).isEqualTo(DEFAULT_SEEK_PRE_ROLL_SAMPLES);
|
assertThat(seekPreRollSamples).isEqualTo(DEFAULT_SEEK_PRE_ROLL_SAMPLES);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void decode_removesPreSkipFromOutput() throws OpusDecoderException {
|
||||||
|
OpusDecoder decoder =
|
||||||
|
new OpusDecoder(
|
||||||
|
/* numInputBuffers= */ 0,
|
||||||
|
/* numOutputBuffers= */ 0,
|
||||||
|
/* initialInputBufferSize= */ 0,
|
||||||
|
createInitializationData(/* preSkipNanos= */ PRE_SKIP_NANOS),
|
||||||
|
/* cryptoConfig= */ null,
|
||||||
|
/* outputFloat= */ false);
|
||||||
|
DecoderInputBuffer input =
|
||||||
|
createInputBuffer(decoder, ENCODED_DATA, /* supplementalData= */ null);
|
||||||
|
SimpleDecoderOutputBuffer output = decoder.createOutputBuffer();
|
||||||
|
assertThat(decoder.decode(input, output, false)).isNull();
|
||||||
|
assertThat(output.data.remaining())
|
||||||
|
.isEqualTo(DECODED_DATA_SIZE - nanosecondsToBytes(PRE_SKIP_NANOS));
|
||||||
|
}
|
||||||
|
|
||||||
private static long sampleCountToNanoseconds(long sampleCount) {
|
private static long sampleCountToNanoseconds(long sampleCount) {
|
||||||
return (sampleCount * C.NANOS_PER_SECOND) / OpusDecoder.SAMPLE_RATE;
|
return (sampleCount * C.NANOS_PER_SECOND) / OpusDecoder.SAMPLE_RATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static long nanosecondsToSampleCount(long nanoseconds) {
|
||||||
|
return (nanoseconds * OpusDecoder.SAMPLE_RATE) / C.NANOS_PER_SECOND;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static long nanosecondsToBytes(long nanoseconds) {
|
||||||
|
return nanosecondsToSampleCount(nanoseconds) * 4;
|
||||||
|
}
|
||||||
|
|
||||||
private static byte[] buildNativeOrderByteArray(long value) {
|
private static byte[] buildNativeOrderByteArray(long value) {
|
||||||
return ByteBuffer.allocate(8).order(ByteOrder.nativeOrder()).putLong(value).array();
|
return ByteBuffer.allocate(8).order(ByteOrder.nativeOrder()).putLong(value).array();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static ImmutableList<byte[]> createInitializationData(long preSkipNanos) {
|
||||||
|
byte[] preSkip = buildNativeOrderByteArray(preSkipNanos);
|
||||||
|
return ImmutableList.of(HEADER, preSkip, CUSTOM_SEEK_PRE_ROLL_BYTES);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static DecoderInputBuffer createInputBuffer(
|
||||||
|
OpusDecoder decoder, byte[] data, @Nullable byte[] supplementalData) {
|
||||||
|
DecoderInputBuffer input = decoder.createInputBuffer();
|
||||||
|
input.ensureSpaceForWrite(data.length);
|
||||||
|
input.data.put(data);
|
||||||
|
input.data.position(0).limit(data.length);
|
||||||
|
if (supplementalData != null) {
|
||||||
|
input.resetSupplementalData(supplementalData.length);
|
||||||
|
input.supplementalData.put(supplementalData).rewind();
|
||||||
|
input.addFlag(C.BUFFER_FLAG_HAS_SUPPLEMENTAL_DATA);
|
||||||
|
}
|
||||||
|
return input;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user