Fix resetting TimestampAdjuster with DO_NOT_OFFSET

Prior to this change, an initalized TimestampAdjuster that's then
reset with DO_NOT_OFFSET would incorrectly continue to apply the
offset.

Also add a test case for this issue, and for some other simple use
cases.

#minor-release

PiperOrigin-RevId: 388182645
This commit is contained in:
olly 2021-08-02 11:31:04 +01:00 committed by Christos Tsilopoulos
parent a9fdade9df
commit ff71425dca
2 changed files with 93 additions and 9 deletions

View File

@ -53,8 +53,7 @@ public final class TimestampAdjuster {
* microseconds, or {@link #DO_NOT_OFFSET} if timestamps should not be offset.
*/
public TimestampAdjuster(long firstSampleTimestampUs) {
this.firstSampleTimestampUs = firstSampleTimestampUs;
lastSampleTimestampUs = C.TIME_UNSET;
reset(firstSampleTimestampUs);
}
/**
@ -80,18 +79,18 @@ public final class TimestampAdjuster {
* </ul>
*
* @param canInitialize Whether the caller is able to initialize the adjuster, if needed.
* @param startTimeUs The desired first sample timestamp of the caller, in microseconds. Only used
* if {@code canInitialize} is {@code true}.
* @param firstSampleTimestampUs The desired value of the first adjusted sample timestamp in
* microseconds. Only used if {@code canInitialize} is {@code true}.
* @throws InterruptedException If the thread is interrupted whilst blocked waiting for
* initialization to complete.
*/
public synchronized void sharedInitializeOrWait(boolean canInitialize, long startTimeUs)
throws InterruptedException {
public synchronized void sharedInitializeOrWait(
boolean canInitialize, long firstSampleTimestampUs) throws InterruptedException {
if (canInitialize && !sharedInitializationStarted) {
firstSampleTimestampUs = startTimeUs;
reset(firstSampleTimestampUs);
sharedInitializationStarted = true;
}
if (!canInitialize || startTimeUs != firstSampleTimestampUs) {
if (!canInitialize || this.firstSampleTimestampUs != firstSampleTimestampUs) {
while (lastSampleTimestampUs == C.TIME_UNSET) {
wait();
}
@ -134,7 +133,7 @@ public final class TimestampAdjuster {
}
/**
* Resets the instance to its initial state.
* Resets the instance.
*
* @param firstSampleTimestampUs The desired value of the first adjusted sample timestamp after
* this reset, in microseconds, or {@link #DO_NOT_OFFSET} if timestamps should not be offset.
@ -142,6 +141,7 @@ public final class TimestampAdjuster {
public synchronized void reset(long firstSampleTimestampUs) {
this.firstSampleTimestampUs = firstSampleTimestampUs;
lastSampleTimestampUs = C.TIME_UNSET;
timestampOffsetUs = 0;
sharedInitializationStarted = false;
}

View File

@ -0,0 +1,84 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.exoplayer2.util;
import static com.google.android.exoplayer2.util.TimestampAdjuster.DO_NOT_OFFSET;
import static com.google.common.truth.Truth.assertThat;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
/** Tests for {@link TimestampAdjuster}. */
@RunWith(AndroidJUnit4.class)
public class TimestampAdjusterTest {
@Test
public void adjustSampleTimestamp_fromZero() {
TimestampAdjuster adjuster = new TimestampAdjuster(/* firstSampleTimestampUs= */ 0);
long firstAdjustedTimestampUs = adjuster.adjustSampleTimestamp(/* timeUs= */ 2000);
long secondAdjustedTimestampUs = adjuster.adjustSampleTimestamp(/* timeUs= */ 6000);
assertThat(firstAdjustedTimestampUs).isEqualTo(0);
assertThat(secondAdjustedTimestampUs).isEqualTo(4000);
}
@Test
public void adjustSampleTimestamp_fromNonZero() {
TimestampAdjuster adjuster = new TimestampAdjuster(/* firstSampleTimestampUs= */ 1000);
long firstAdjustedTimestampUs = adjuster.adjustSampleTimestamp(/* timeUs= */ 2000);
long secondAdjustedTimestampUs = adjuster.adjustSampleTimestamp(/* timeUs= */ 6000);
assertThat(firstAdjustedTimestampUs).isEqualTo(1000);
assertThat(secondAdjustedTimestampUs).isEqualTo(5000);
}
@Test
public void adjustSampleTimestamp_doNotOffset() {
TimestampAdjuster adjuster = new TimestampAdjuster(/* firstSampleTimestampUs= */ DO_NOT_OFFSET);
long firstAdjustedTimestampUs = adjuster.adjustSampleTimestamp(/* timeUs= */ 2000);
long secondAdjustedTimestampUs = adjuster.adjustSampleTimestamp(/* timeUs= */ 6000);
assertThat(firstAdjustedTimestampUs).isEqualTo(2000);
assertThat(secondAdjustedTimestampUs).isEqualTo(6000);
}
@Test
public void adjustSampleTimestamp_afterResetToNotOffset() {
TimestampAdjuster adjuster = new TimestampAdjuster(/* firstSampleTimestampUs= */ 0);
// Let the adjuster establish an offset, to make sure that reset really clears it.
adjuster.adjustSampleTimestamp(/* timeUs= */ 1000);
adjuster.reset(/* firstSampleTimestampUs= */ DO_NOT_OFFSET);
long firstAdjustedTimestampUs = adjuster.adjustSampleTimestamp(/* timeUs= */ 2000);
long secondAdjustedTimestampUs = adjuster.adjustSampleTimestamp(/* timeUs= */ 6000);
assertThat(firstAdjustedTimestampUs).isEqualTo(2000);
assertThat(secondAdjustedTimestampUs).isEqualTo(6000);
}
@Test
public void adjustSampleTimestamp_afterResetToDifferentStartTime() {
TimestampAdjuster adjuster = new TimestampAdjuster(/* firstSampleTimestampUs= */ 0);
// Let the adjuster establish an offset, to make sure that reset really clears it.
adjuster.adjustSampleTimestamp(/* timeUs= */ 1000);
adjuster.reset(/* firstSampleTimestampUs= */ 5000);
long firstAdjustedTimestampUs = adjuster.adjustSampleTimestamp(/* timeUs= */ 2000);
long secondAdjustedTimestampUs = adjuster.adjustSampleTimestamp(/* timeUs= */ 6000);
assertThat(firstAdjustedTimestampUs).isEqualTo(5000);
assertThat(secondAdjustedTimestampUs).isEqualTo(9000);
}
}