mirror of
https://github.com/androidx/media.git
synced 2025-05-03 21:57:46 +08:00
Accumulate remainder in buffer duration calculations.
When dropping the remainder, the decoder and encoder timestamps start diverging after a few buffers when no speed changes are supposed to occur. Tracking the remainder keeps them in sync. PiperOrigin-RevId: 408341074
This commit is contained in:
parent
ba9ade1c8e
commit
9efa32e49b
@ -31,7 +31,9 @@ import com.google.android.exoplayer2.audio.AudioProcessor;
|
|||||||
import com.google.android.exoplayer2.audio.AudioProcessor.AudioFormat;
|
import com.google.android.exoplayer2.audio.AudioProcessor.AudioFormat;
|
||||||
import com.google.android.exoplayer2.audio.SonicAudioProcessor;
|
import com.google.android.exoplayer2.audio.SonicAudioProcessor;
|
||||||
import com.google.android.exoplayer2.decoder.DecoderInputBuffer;
|
import com.google.android.exoplayer2.decoder.DecoderInputBuffer;
|
||||||
|
import com.google.common.math.LongMath;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.math.RoundingMode;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf;
|
import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf;
|
||||||
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||||
@ -62,6 +64,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||||||
private @MonotonicNonNull AudioFormat encoderInputAudioFormat;
|
private @MonotonicNonNull AudioFormat encoderInputAudioFormat;
|
||||||
private @MonotonicNonNull MediaCodecAdapterWrapper encoder;
|
private @MonotonicNonNull MediaCodecAdapterWrapper encoder;
|
||||||
private long nextEncoderInputBufferTimeUs;
|
private long nextEncoderInputBufferTimeUs;
|
||||||
|
private long encoderBufferDurationRemainder;
|
||||||
|
|
||||||
private ByteBuffer sonicOutputBuffer;
|
private ByteBuffer sonicOutputBuffer;
|
||||||
private boolean drainingSonicForSpeedChange;
|
private boolean drainingSonicForSpeedChange;
|
||||||
@ -82,6 +85,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||||||
sonicAudioProcessor = new SonicAudioProcessor();
|
sonicAudioProcessor = new SonicAudioProcessor();
|
||||||
sonicOutputBuffer = AudioProcessor.EMPTY_BUFFER;
|
sonicOutputBuffer = AudioProcessor.EMPTY_BUFFER;
|
||||||
nextEncoderInputBufferTimeUs = 0;
|
nextEncoderInputBufferTimeUs = 0;
|
||||||
|
encoderBufferDurationRemainder = 0;
|
||||||
speedProvider = new SegmentSpeedProvider(decoderInputFormat);
|
speedProvider = new SegmentSpeedProvider(decoderInputFormat);
|
||||||
currentSpeed = speedProvider.getSpeed(0);
|
currentSpeed = speedProvider.getSpeed(0);
|
||||||
try {
|
try {
|
||||||
@ -269,7 +273,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||||||
encoderInputBufferData.put(inputBuffer);
|
encoderInputBufferData.put(inputBuffer);
|
||||||
encoderInputBuffer.timeUs = nextEncoderInputBufferTimeUs;
|
encoderInputBuffer.timeUs = nextEncoderInputBufferTimeUs;
|
||||||
nextEncoderInputBufferTimeUs +=
|
nextEncoderInputBufferTimeUs +=
|
||||||
getBufferDurationUs(
|
getEncoderBufferDurationUs(
|
||||||
/* bytesWritten= */ encoderInputBufferData.position(),
|
/* bytesWritten= */ encoderInputBufferData.position(),
|
||||||
encoderInputAudioFormat.bytesPerFrame,
|
encoderInputAudioFormat.bytesPerFrame,
|
||||||
encoderInputAudioFormat.sampleRate);
|
encoderInputAudioFormat.sampleRate);
|
||||||
@ -366,9 +370,17 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||||||
errorCode);
|
errorCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(internal b/204978301): Ensure encoder and decoder timestamps match when no speed change.
|
private long getEncoderBufferDurationUs(long bytesWritten, int bytesPerFrame, int sampleRate) {
|
||||||
private static long getBufferDurationUs(long bytesWritten, int bytesPerFrame, int sampleRate) {
|
// The calculation below accounts for remainders and rounding. Without that it corresponds to
|
||||||
long framesWritten = bytesWritten / bytesPerFrame;
|
// the following:
|
||||||
return framesWritten * C.MICROS_PER_SECOND / sampleRate;
|
// bufferDurationUs = numberOfFramesInBuffer * sampleDurationUs
|
||||||
|
// where numberOfFramesInBuffer = bytesWritten / bytesPerFrame
|
||||||
|
// and sampleDurationUs = C.MICROS_PER_SECOND / sampleRate
|
||||||
|
long framesWrittenMicrosPerSecond =
|
||||||
|
bytesWritten * C.MICROS_PER_SECOND / bytesPerFrame + encoderBufferDurationRemainder;
|
||||||
|
long bufferDurationUs =
|
||||||
|
LongMath.divide(framesWrittenMicrosPerSecond, sampleRate, RoundingMode.CEILING);
|
||||||
|
encoderBufferDurationRemainder = framesWrittenMicrosPerSecond - bufferDurationUs * sampleRate;
|
||||||
|
return bufferDurationUs;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -135,145 +135,145 @@ sample:
|
|||||||
dataHashCode = 1000136444
|
dataHashCode = 1000136444
|
||||||
size = 140
|
size = 140
|
||||||
isKeyFrame = true
|
isKeyFrame = true
|
||||||
presentationTimeUs = 416
|
presentationTimeUs = 417
|
||||||
sample:
|
sample:
|
||||||
trackIndex = 0
|
trackIndex = 0
|
||||||
dataHashCode = 217961709
|
dataHashCode = 217961709
|
||||||
size = 172
|
size = 172
|
||||||
isKeyFrame = true
|
isKeyFrame = true
|
||||||
presentationTimeUs = 3332
|
presentationTimeUs = 3334
|
||||||
sample:
|
sample:
|
||||||
trackIndex = 0
|
trackIndex = 0
|
||||||
dataHashCode = -879376936
|
dataHashCode = -879376936
|
||||||
size = 176
|
size = 176
|
||||||
isKeyFrame = true
|
isKeyFrame = true
|
||||||
presentationTimeUs = 6915
|
presentationTimeUs = 6917
|
||||||
sample:
|
sample:
|
||||||
trackIndex = 0
|
trackIndex = 0
|
||||||
dataHashCode = 1259979587
|
dataHashCode = 1259979587
|
||||||
size = 192
|
size = 192
|
||||||
isKeyFrame = true
|
isKeyFrame = true
|
||||||
presentationTimeUs = 10581
|
presentationTimeUs = 10584
|
||||||
sample:
|
sample:
|
||||||
trackIndex = 0
|
trackIndex = 0
|
||||||
dataHashCode = 907407225
|
dataHashCode = 907407225
|
||||||
size = 188
|
size = 188
|
||||||
isKeyFrame = true
|
isKeyFrame = true
|
||||||
presentationTimeUs = 14581
|
presentationTimeUs = 14584
|
||||||
sample:
|
sample:
|
||||||
trackIndex = 0
|
trackIndex = 0
|
||||||
dataHashCode = -904354707
|
dataHashCode = -904354707
|
||||||
size = 176
|
size = 176
|
||||||
isKeyFrame = true
|
isKeyFrame = true
|
||||||
presentationTimeUs = 18497
|
presentationTimeUs = 18500
|
||||||
sample:
|
sample:
|
||||||
trackIndex = 0
|
trackIndex = 0
|
||||||
dataHashCode = 1001385853
|
dataHashCode = 1001385853
|
||||||
size = 172
|
size = 172
|
||||||
isKeyFrame = true
|
isKeyFrame = true
|
||||||
presentationTimeUs = 22163
|
presentationTimeUs = 22167
|
||||||
sample:
|
sample:
|
||||||
trackIndex = 0
|
trackIndex = 0
|
||||||
dataHashCode = 1545716086
|
dataHashCode = 1545716086
|
||||||
size = 196
|
size = 196
|
||||||
isKeyFrame = true
|
isKeyFrame = true
|
||||||
presentationTimeUs = 25746
|
presentationTimeUs = 25750
|
||||||
sample:
|
sample:
|
||||||
trackIndex = 0
|
trackIndex = 0
|
||||||
dataHashCode = 358710839
|
dataHashCode = 358710839
|
||||||
size = 180
|
size = 180
|
||||||
isKeyFrame = true
|
isKeyFrame = true
|
||||||
presentationTimeUs = 29829
|
presentationTimeUs = 29834
|
||||||
sample:
|
sample:
|
||||||
trackIndex = 0
|
trackIndex = 0
|
||||||
dataHashCode = -671124798
|
dataHashCode = -671124798
|
||||||
size = 140
|
size = 140
|
||||||
isKeyFrame = true
|
isKeyFrame = true
|
||||||
presentationTimeUs = 33579
|
presentationTimeUs = 33584
|
||||||
sample:
|
sample:
|
||||||
trackIndex = 0
|
trackIndex = 0
|
||||||
dataHashCode = -945404910
|
dataHashCode = -945404910
|
||||||
size = 120
|
size = 120
|
||||||
isKeyFrame = true
|
isKeyFrame = true
|
||||||
presentationTimeUs = 36495
|
presentationTimeUs = 36500
|
||||||
sample:
|
sample:
|
||||||
trackIndex = 0
|
trackIndex = 0
|
||||||
dataHashCode = 1881048379
|
dataHashCode = 1881048379
|
||||||
size = 88
|
size = 88
|
||||||
isKeyFrame = true
|
isKeyFrame = true
|
||||||
presentationTimeUs = 38995
|
presentationTimeUs = 39000
|
||||||
sample:
|
sample:
|
||||||
trackIndex = 0
|
trackIndex = 0
|
||||||
dataHashCode = 1059579897
|
dataHashCode = 1059579897
|
||||||
size = 88
|
size = 88
|
||||||
isKeyFrame = true
|
isKeyFrame = true
|
||||||
presentationTimeUs = 40828
|
presentationTimeUs = 40834
|
||||||
sample:
|
sample:
|
||||||
trackIndex = 0
|
trackIndex = 0
|
||||||
dataHashCode = 1496098648
|
dataHashCode = 1496098648
|
||||||
size = 84
|
size = 84
|
||||||
isKeyFrame = true
|
isKeyFrame = true
|
||||||
presentationTimeUs = 42661
|
presentationTimeUs = 42667
|
||||||
sample:
|
sample:
|
||||||
trackIndex = 0
|
trackIndex = 0
|
||||||
dataHashCode = 250093960
|
dataHashCode = 250093960
|
||||||
size = 751
|
size = 751
|
||||||
isKeyFrame = true
|
isKeyFrame = true
|
||||||
presentationTimeUs = 44411
|
presentationTimeUs = 44417
|
||||||
sample:
|
sample:
|
||||||
trackIndex = 0
|
trackIndex = 0
|
||||||
dataHashCode = 1895536226
|
dataHashCode = 1895536226
|
||||||
size = 1045
|
size = 1045
|
||||||
isKeyFrame = true
|
isKeyFrame = true
|
||||||
presentationTimeUs = 59994
|
presentationTimeUs = 60063
|
||||||
sample:
|
sample:
|
||||||
trackIndex = 0
|
trackIndex = 0
|
||||||
dataHashCode = 1723596464
|
dataHashCode = 1723596464
|
||||||
size = 947
|
size = 947
|
||||||
isKeyFrame = true
|
isKeyFrame = true
|
||||||
presentationTimeUs = 81744
|
presentationTimeUs = 81834
|
||||||
sample:
|
sample:
|
||||||
trackIndex = 0
|
trackIndex = 0
|
||||||
dataHashCode = -978803114
|
dataHashCode = -978803114
|
||||||
size = 946
|
size = 946
|
||||||
isKeyFrame = true
|
isKeyFrame = true
|
||||||
presentationTimeUs = 101410
|
presentationTimeUs = 101563
|
||||||
sample:
|
sample:
|
||||||
trackIndex = 0
|
trackIndex = 0
|
||||||
dataHashCode = 387377078
|
dataHashCode = 387377078
|
||||||
size = 946
|
size = 946
|
||||||
isKeyFrame = true
|
isKeyFrame = true
|
||||||
presentationTimeUs = 121076
|
presentationTimeUs = 121271
|
||||||
sample:
|
sample:
|
||||||
trackIndex = 0
|
trackIndex = 0
|
||||||
dataHashCode = -132658698
|
dataHashCode = -132658698
|
||||||
size = 901
|
size = 901
|
||||||
isKeyFrame = true
|
isKeyFrame = true
|
||||||
presentationTimeUs = 140742
|
presentationTimeUs = 140980
|
||||||
sample:
|
sample:
|
||||||
trackIndex = 0
|
trackIndex = 0
|
||||||
dataHashCode = 1495036471
|
dataHashCode = 1495036471
|
||||||
size = 899
|
size = 899
|
||||||
isKeyFrame = true
|
isKeyFrame = true
|
||||||
presentationTimeUs = 159492
|
presentationTimeUs = 159750
|
||||||
sample:
|
sample:
|
||||||
trackIndex = 0
|
trackIndex = 0
|
||||||
dataHashCode = 304440590
|
dataHashCode = 304440590
|
||||||
size = 878
|
size = 878
|
||||||
isKeyFrame = true
|
isKeyFrame = true
|
||||||
presentationTimeUs = 178158
|
presentationTimeUs = 178480
|
||||||
sample:
|
sample:
|
||||||
trackIndex = 0
|
trackIndex = 0
|
||||||
dataHashCode = -1955900344
|
dataHashCode = -1955900344
|
||||||
size = 112
|
size = 112
|
||||||
isKeyFrame = true
|
isKeyFrame = true
|
||||||
presentationTimeUs = 196408
|
presentationTimeUs = 196771
|
||||||
sample:
|
sample:
|
||||||
trackIndex = 0
|
trackIndex = 0
|
||||||
dataHashCode = 88896626
|
dataHashCode = 88896626
|
||||||
size = 116
|
size = 116
|
||||||
isKeyFrame = true
|
isKeyFrame = true
|
||||||
presentationTimeUs = 198741
|
presentationTimeUs = 199105
|
||||||
sample:
|
sample:
|
||||||
trackIndex = 1
|
trackIndex = 1
|
||||||
dataHashCode = 2139021989
|
dataHashCode = 2139021989
|
||||||
|
Loading…
x
Reference in New Issue
Block a user