Round bytesToNextSpeedChange up instead of down
Rounding down means that very small diferrences (e.g. 1 us) result in bytesToNextSpeedChange==0, which stalls progress forever as no new bytes are read. Rounding up instead ensures that we always read at least one audio frame if nextSpeedChangeTimeUs is in the future. PiperOrigin-RevId: 632116560
This commit is contained in:
parent
49fa343127
commit
971486f5f9
@ -27,6 +27,7 @@ import androidx.media3.common.util.SpeedProviderUtil;
|
|||||||
import androidx.media3.common.util.TimestampConsumer;
|
import androidx.media3.common.util.TimestampConsumer;
|
||||||
import androidx.media3.common.util.UnstableApi;
|
import androidx.media3.common.util.UnstableApi;
|
||||||
import androidx.media3.common.util.Util;
|
import androidx.media3.common.util.Util;
|
||||||
|
import java.math.RoundingMode;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.ArrayDeque;
|
import java.util.ArrayDeque;
|
||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
@ -117,11 +118,12 @@ public final class SpeedChangingAudioProcessor extends BaseAudioProcessor {
|
|||||||
if (nextSpeedChangeTimeUs != C.TIME_UNSET) {
|
if (nextSpeedChangeTimeUs != C.TIME_UNSET) {
|
||||||
bytesToNextSpeedChange =
|
bytesToNextSpeedChange =
|
||||||
(int)
|
(int)
|
||||||
Util.scaleLargeTimestamp(
|
Util.scaleLargeValue(
|
||||||
/* timestamp= */ nextSpeedChangeTimeUs - timeUs,
|
/* timestamp= */ nextSpeedChangeTimeUs - timeUs,
|
||||||
/* multiplier= */ (long) inputAudioFormat.sampleRate
|
/* multiplier= */ (long) inputAudioFormat.sampleRate
|
||||||
* inputAudioFormat.bytesPerFrame,
|
* inputAudioFormat.bytesPerFrame,
|
||||||
/* divisor= */ C.MICROS_PER_SECOND);
|
/* divisor= */ C.MICROS_PER_SECOND,
|
||||||
|
RoundingMode.CEILING);
|
||||||
int bytesToNextFrame =
|
int bytesToNextFrame =
|
||||||
inputAudioFormat.bytesPerFrame - bytesToNextSpeedChange % inputAudioFormat.bytesPerFrame;
|
inputAudioFormat.bytesPerFrame - bytesToNextSpeedChange % inputAudioFormat.bytesPerFrame;
|
||||||
if (bytesToNextFrame != inputAudioFormat.bytesPerFrame) {
|
if (bytesToNextFrame != inputAudioFormat.bytesPerFrame) {
|
||||||
|
@ -239,6 +239,25 @@ public class SpeedChangingAudioProcessorTest {
|
|||||||
assertThat(inputBuffer.limit()).isEqualTo(inputBufferLimit);
|
assertThat(inputBuffer.limit()).isEqualTo(inputBufferLimit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void queueInput_multipleSpeedsInBufferWithLimitVeryClose_readsDataUntilSpeedLimit()
|
||||||
|
throws Exception {
|
||||||
|
long speedChangeTimeUs = 1; // Change speed very close to current position at 1us.
|
||||||
|
SpeedProvider speedProvider =
|
||||||
|
TestSpeedProvider.createWithStartTimes(
|
||||||
|
/* startTimesUs= */ new long[] {0L, speedChangeTimeUs},
|
||||||
|
/* speeds= */ new float[] {1, 2});
|
||||||
|
SpeedChangingAudioProcessor speedChangingAudioProcessor =
|
||||||
|
getConfiguredSpeedChangingAudioProcessor(speedProvider);
|
||||||
|
ByteBuffer inputBuffer = getInputBuffer(/* frameCount= */ 5);
|
||||||
|
int inputBufferLimit = inputBuffer.limit();
|
||||||
|
|
||||||
|
speedChangingAudioProcessor.queueInput(inputBuffer);
|
||||||
|
|
||||||
|
assertThat(inputBuffer.position()).isEqualTo(AUDIO_FORMAT.bytesPerFrame);
|
||||||
|
assertThat(inputBuffer.limit()).isEqualTo(inputBufferLimit);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void queueEndOfStream_afterNoSpeedChangeAndWithOutputRetrieved_endsProcessor()
|
public void queueEndOfStream_afterNoSpeedChangeAndWithOutputRetrieved_endsProcessor()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user