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