Change onOutputFrameAvailable timestamp from nanos to micros.
Upstream timestamps from the decoder are also in microseconds, so using microseconds here is consistent with that. PiperOrigin-RevId: 468659099
This commit is contained in:
parent
30257c767b
commit
0b1c540ff9
@ -81,11 +81,11 @@ public interface FrameProcessor {
|
|||||||
void onOutputSizeChanged(int width, int height);
|
void onOutputSizeChanged(int width, int height);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when an output frame with the given {@code presentationTimeNs} becomes available.
|
* Called when an output frame with the given {@code presentationTimeUs} becomes available.
|
||||||
*
|
*
|
||||||
* @param presentationTimeNs The presentation time of the frame, in nanoseconds.
|
* @param presentationTimeUs The presentation time of the frame, in microseconds.
|
||||||
*/
|
*/
|
||||||
void onOutputFrameAvailable(long presentationTimeNs);
|
void onOutputFrameAvailable(long presentationTimeUs);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when an exception occurs during asynchronous frame processing.
|
* Called when an exception occurs during asynchronous frame processing.
|
||||||
|
@ -72,52 +72,57 @@ public final class GlEffectsFrameProcessorFrameReleaseTest {
|
|||||||
@Test
|
@Test
|
||||||
public void automaticFrameRelease_withOneFrame_reusesInputTimestamp() throws Exception {
|
public void automaticFrameRelease_withOneFrame_reusesInputTimestamp() throws Exception {
|
||||||
long originalPresentationTimeUs = 1234;
|
long originalPresentationTimeUs = 1234;
|
||||||
AtomicLong actualPresentationTimeNs = new AtomicLong();
|
AtomicLong actualPresentationTimeUs = new AtomicLong();
|
||||||
setupGlEffectsFrameProcessorWithBlankFrameProducer(
|
setupGlEffectsFrameProcessorWithBlankFrameProducer(
|
||||||
/* inputPresentationTimesUs= */ new long[] {originalPresentationTimeUs},
|
/* inputPresentationTimesUs= */ new long[] {originalPresentationTimeUs},
|
||||||
/* onFrameAvailableListener= */ actualPresentationTimeNs::set,
|
/* onFrameAvailableListener= */ actualPresentationTimeUs::set,
|
||||||
/* releaseFramesAutomatically= */ true);
|
/* releaseFramesAutomatically= */ true);
|
||||||
|
|
||||||
checkNotNull(produceBlankFramesTask).run();
|
checkNotNull(produceBlankFramesTask).run();
|
||||||
Thread.sleep(FRAME_PROCESSING_WAIT_MS);
|
Thread.sleep(FRAME_PROCESSING_WAIT_MS);
|
||||||
|
|
||||||
assertThat(frameProcessingException.get()).isNull();
|
assertThat(frameProcessingException.get()).isNull();
|
||||||
assertThat(actualPresentationTimeNs.get())
|
assertThat(actualPresentationTimeUs.get()).isEqualTo(originalPresentationTimeUs);
|
||||||
.isEqualTo(MICROS_TO_NANOS * originalPresentationTimeUs);
|
|
||||||
assertThat(outputReleaseTimesNs).containsExactly(MICROS_TO_NANOS * originalPresentationTimeUs);
|
assertThat(outputReleaseTimesNs).containsExactly(MICROS_TO_NANOS * originalPresentationTimeUs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void automaticFrameRelease_withThreeFrames_reusesInputTimestamps() throws Exception {
|
public void automaticFrameRelease_withThreeFrames_reusesInputTimestamps() throws Exception {
|
||||||
long[] originalPresentationTimesUs = new long[] {1234, 3456, 4567};
|
long[] originalPresentationTimesUs = new long[] {1234, 3456, 4567};
|
||||||
ArrayList<Long> actualPresentationTimesNs = new ArrayList<>();
|
ArrayList<Long> actualPresentationTimesUs = new ArrayList<>();
|
||||||
setupGlEffectsFrameProcessorWithBlankFrameProducer(
|
setupGlEffectsFrameProcessorWithBlankFrameProducer(
|
||||||
originalPresentationTimesUs,
|
originalPresentationTimesUs,
|
||||||
/* onFrameAvailableListener= */ actualPresentationTimesNs::add,
|
/* onFrameAvailableListener= */ actualPresentationTimesUs::add,
|
||||||
/* releaseFramesAutomatically= */ true);
|
/* releaseFramesAutomatically= */ true);
|
||||||
|
|
||||||
checkNotNull(produceBlankFramesTask).run();
|
checkNotNull(produceBlankFramesTask).run();
|
||||||
Thread.sleep(FRAME_PROCESSING_WAIT_MS);
|
Thread.sleep(FRAME_PROCESSING_WAIT_MS);
|
||||||
|
|
||||||
assertThat(frameProcessingException.get()).isNull();
|
assertThat(frameProcessingException.get()).isNull();
|
||||||
assertThat(actualPresentationTimesNs)
|
assertThat(actualPresentationTimesUs)
|
||||||
|
.containsExactly(
|
||||||
|
originalPresentationTimesUs[0],
|
||||||
|
originalPresentationTimesUs[1],
|
||||||
|
originalPresentationTimesUs[2])
|
||||||
|
.inOrder();
|
||||||
|
assertThat(outputReleaseTimesNs)
|
||||||
.containsExactly(
|
.containsExactly(
|
||||||
MICROS_TO_NANOS * originalPresentationTimesUs[0],
|
MICROS_TO_NANOS * originalPresentationTimesUs[0],
|
||||||
MICROS_TO_NANOS * originalPresentationTimesUs[1],
|
MICROS_TO_NANOS * originalPresentationTimesUs[1],
|
||||||
MICROS_TO_NANOS * originalPresentationTimesUs[2])
|
MICROS_TO_NANOS * originalPresentationTimesUs[2])
|
||||||
.inOrder();
|
.inOrder();
|
||||||
assertThat(outputReleaseTimesNs).containsExactlyElementsIn(actualPresentationTimesNs).inOrder();
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void controlledFrameRelease_withOneFrame_usesGivenTimestamp() throws Exception {
|
public void controlledFrameRelease_withOneFrame_usesGivenTimestamp() throws Exception {
|
||||||
long originalPresentationTimeUs = 1234;
|
long originalPresentationTimeUs = 1234;
|
||||||
long releaseTimesNs = System.nanoTime() + MILLIS_TO_NANOS * FRAME_PROCESSING_WAIT_MS + 345678;
|
long releaseTimesNs = System.nanoTime() + MILLIS_TO_NANOS * FRAME_PROCESSING_WAIT_MS + 345678;
|
||||||
AtomicLong actualPresentationTimeNs = new AtomicLong();
|
AtomicLong actualPresentationTimeUs = new AtomicLong();
|
||||||
setupGlEffectsFrameProcessorWithBlankFrameProducer(
|
setupGlEffectsFrameProcessorWithBlankFrameProducer(
|
||||||
/* inputPresentationTimesUs= */ new long[] {originalPresentationTimeUs},
|
/* inputPresentationTimesUs= */ new long[] {originalPresentationTimeUs},
|
||||||
/* onFrameAvailableListener= */ presentationTimeNs -> {
|
/* onFrameAvailableListener= */ presentationTimeUs -> {
|
||||||
actualPresentationTimeNs.set(presentationTimeNs);
|
actualPresentationTimeUs.set(presentationTimeUs);
|
||||||
checkNotNull(glEffectsFrameProcessor).releaseOutputFrame(releaseTimesNs);
|
checkNotNull(glEffectsFrameProcessor).releaseOutputFrame(releaseTimesNs);
|
||||||
},
|
},
|
||||||
/* releaseFramesAutomatically= */ false);
|
/* releaseFramesAutomatically= */ false);
|
||||||
@ -126,8 +131,7 @@ public final class GlEffectsFrameProcessorFrameReleaseTest {
|
|||||||
Thread.sleep(FRAME_PROCESSING_WAIT_MS);
|
Thread.sleep(FRAME_PROCESSING_WAIT_MS);
|
||||||
|
|
||||||
assertThat(frameProcessingException.get()).isNull();
|
assertThat(frameProcessingException.get()).isNull();
|
||||||
assertThat(actualPresentationTimeNs.get())
|
assertThat(actualPresentationTimeUs.get()).isEqualTo(originalPresentationTimeUs);
|
||||||
.isEqualTo(MICROS_TO_NANOS * originalPresentationTimeUs);
|
|
||||||
assertThat(outputReleaseTimesNs).containsExactly(releaseTimesNs);
|
assertThat(outputReleaseTimesNs).containsExactly(releaseTimesNs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,11 +139,11 @@ public final class GlEffectsFrameProcessorFrameReleaseTest {
|
|||||||
public void controlledFrameRelease_withLateFrame_dropsFrame() throws Exception {
|
public void controlledFrameRelease_withLateFrame_dropsFrame() throws Exception {
|
||||||
long originalPresentationTimeUs = 1234;
|
long originalPresentationTimeUs = 1234;
|
||||||
long releaseTimeBeforeCurrentTimeNs = System.nanoTime() - 345678;
|
long releaseTimeBeforeCurrentTimeNs = System.nanoTime() - 345678;
|
||||||
AtomicLong actualPresentationTimeNs = new AtomicLong();
|
AtomicLong actualPresentationTimeUs = new AtomicLong();
|
||||||
setupGlEffectsFrameProcessorWithBlankFrameProducer(
|
setupGlEffectsFrameProcessorWithBlankFrameProducer(
|
||||||
/* inputPresentationTimesUs= */ new long[] {originalPresentationTimeUs},
|
/* inputPresentationTimesUs= */ new long[] {originalPresentationTimeUs},
|
||||||
/* onFrameAvailableListener= */ presentationTimeNs -> {
|
/* onFrameAvailableListener= */ presentationTimeUs -> {
|
||||||
actualPresentationTimeNs.set(presentationTimeNs);
|
actualPresentationTimeUs.set(presentationTimeUs);
|
||||||
checkNotNull(glEffectsFrameProcessor).releaseOutputFrame(releaseTimeBeforeCurrentTimeNs);
|
checkNotNull(glEffectsFrameProcessor).releaseOutputFrame(releaseTimeBeforeCurrentTimeNs);
|
||||||
},
|
},
|
||||||
/* releaseFramesAutomatically= */ false);
|
/* releaseFramesAutomatically= */ false);
|
||||||
@ -148,19 +152,18 @@ public final class GlEffectsFrameProcessorFrameReleaseTest {
|
|||||||
Thread.sleep(FRAME_PROCESSING_WAIT_MS);
|
Thread.sleep(FRAME_PROCESSING_WAIT_MS);
|
||||||
|
|
||||||
assertThat(frameProcessingException.get()).isNull();
|
assertThat(frameProcessingException.get()).isNull();
|
||||||
assertThat(actualPresentationTimeNs.get())
|
assertThat(actualPresentationTimeUs.get()).isEqualTo(originalPresentationTimeUs);
|
||||||
.isEqualTo(MICROS_TO_NANOS * originalPresentationTimeUs);
|
|
||||||
assertThat(outputReleaseTimesNs).isEmpty();
|
assertThat(outputReleaseTimesNs).isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void controlledFrameRelease_withUnsetReleaseTime_dropsFrame() throws Exception {
|
public void controlledFrameRelease_withUnsetReleaseTime_dropsFrame() throws Exception {
|
||||||
long originalPresentationTimeUs = 1234;
|
long originalPresentationTimeUs = 1234;
|
||||||
AtomicLong actualPresentationTimeNs = new AtomicLong();
|
AtomicLong actualPresentationTimeUs = new AtomicLong();
|
||||||
setupGlEffectsFrameProcessorWithBlankFrameProducer(
|
setupGlEffectsFrameProcessorWithBlankFrameProducer(
|
||||||
/* inputPresentationTimesUs= */ new long[] {originalPresentationTimeUs},
|
/* inputPresentationTimesUs= */ new long[] {originalPresentationTimeUs},
|
||||||
/* onFrameAvailableListener= */ presentationTimeNs -> {
|
/* onFrameAvailableListener= */ presentationTimeNs -> {
|
||||||
actualPresentationTimeNs.set(presentationTimeNs);
|
actualPresentationTimeUs.set(presentationTimeNs);
|
||||||
checkNotNull(glEffectsFrameProcessor)
|
checkNotNull(glEffectsFrameProcessor)
|
||||||
.releaseOutputFrame(/* releaseTimeNs= */ C.TIME_UNSET);
|
.releaseOutputFrame(/* releaseTimeNs= */ C.TIME_UNSET);
|
||||||
},
|
},
|
||||||
@ -170,8 +173,7 @@ public final class GlEffectsFrameProcessorFrameReleaseTest {
|
|||||||
Thread.sleep(FRAME_PROCESSING_WAIT_MS);
|
Thread.sleep(FRAME_PROCESSING_WAIT_MS);
|
||||||
|
|
||||||
assertThat(frameProcessingException.get()).isNull();
|
assertThat(frameProcessingException.get()).isNull();
|
||||||
assertThat(actualPresentationTimeNs.get())
|
assertThat(actualPresentationTimeUs.get()).isEqualTo(originalPresentationTimeUs);
|
||||||
.isEqualTo(MICROS_TO_NANOS * originalPresentationTimeUs);
|
|
||||||
assertThat(outputReleaseTimesNs).isEmpty();
|
assertThat(outputReleaseTimesNs).isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -181,12 +183,12 @@ public final class GlEffectsFrameProcessorFrameReleaseTest {
|
|||||||
long[] originalPresentationTimesUs = new long[] {1234, 3456, 4567};
|
long[] originalPresentationTimesUs = new long[] {1234, 3456, 4567};
|
||||||
long offsetNs = System.nanoTime() + MILLIS_TO_NANOS * FRAME_PROCESSING_WAIT_MS;
|
long offsetNs = System.nanoTime() + MILLIS_TO_NANOS * FRAME_PROCESSING_WAIT_MS;
|
||||||
long[] releaseTimesNs = new long[] {offsetNs + 123456, offsetNs + 234567, offsetNs + 345678};
|
long[] releaseTimesNs = new long[] {offsetNs + 123456, offsetNs + 234567, offsetNs + 345678};
|
||||||
ArrayList<Long> actualPresentationTimesNs = new ArrayList<>();
|
ArrayList<Long> actualPresentationTimesUs = new ArrayList<>();
|
||||||
AtomicInteger frameIndex = new AtomicInteger();
|
AtomicInteger frameIndex = new AtomicInteger();
|
||||||
setupGlEffectsFrameProcessorWithBlankFrameProducer(
|
setupGlEffectsFrameProcessorWithBlankFrameProducer(
|
||||||
/* inputPresentationTimesUs= */ originalPresentationTimesUs,
|
/* inputPresentationTimesUs= */ originalPresentationTimesUs,
|
||||||
/* onFrameAvailableListener= */ presentationTimeNs -> {
|
/* onFrameAvailableListener= */ presentationTimeUs -> {
|
||||||
actualPresentationTimesNs.add(presentationTimeNs);
|
actualPresentationTimesUs.add(presentationTimeUs);
|
||||||
checkNotNull(glEffectsFrameProcessor)
|
checkNotNull(glEffectsFrameProcessor)
|
||||||
.releaseOutputFrame(releaseTimesNs[frameIndex.getAndIncrement()]);
|
.releaseOutputFrame(releaseTimesNs[frameIndex.getAndIncrement()]);
|
||||||
},
|
},
|
||||||
@ -196,11 +198,11 @@ public final class GlEffectsFrameProcessorFrameReleaseTest {
|
|||||||
Thread.sleep(FRAME_PROCESSING_WAIT_MS);
|
Thread.sleep(FRAME_PROCESSING_WAIT_MS);
|
||||||
|
|
||||||
assertThat(frameProcessingException.get()).isNull();
|
assertThat(frameProcessingException.get()).isNull();
|
||||||
assertThat(actualPresentationTimesNs)
|
assertThat(actualPresentationTimesUs)
|
||||||
.containsExactly(
|
.containsExactly(
|
||||||
MICROS_TO_NANOS * originalPresentationTimesUs[0],
|
originalPresentationTimesUs[0],
|
||||||
MICROS_TO_NANOS * originalPresentationTimesUs[1],
|
originalPresentationTimesUs[1],
|
||||||
MICROS_TO_NANOS * originalPresentationTimesUs[2])
|
originalPresentationTimesUs[2])
|
||||||
.inOrder();
|
.inOrder();
|
||||||
assertThat(frameIndex.get()).isEqualTo(originalPresentationTimesUs.length);
|
assertThat(frameIndex.get()).isEqualTo(originalPresentationTimesUs.length);
|
||||||
assertThat(outputReleaseTimesNs)
|
assertThat(outputReleaseTimesNs)
|
||||||
@ -213,10 +215,10 @@ public final class GlEffectsFrameProcessorFrameReleaseTest {
|
|||||||
long[] originalPresentationTimesUs = new long[] {1234, 3456, 4567};
|
long[] originalPresentationTimesUs = new long[] {1234, 3456, 4567};
|
||||||
long offsetNs = System.nanoTime() + MILLIS_TO_NANOS * 2 * FRAME_PROCESSING_WAIT_MS;
|
long offsetNs = System.nanoTime() + MILLIS_TO_NANOS * 2 * FRAME_PROCESSING_WAIT_MS;
|
||||||
long[] releaseTimesNs = new long[] {offsetNs + 123456, offsetNs + 234567, offsetNs + 345678};
|
long[] releaseTimesNs = new long[] {offsetNs + 123456, offsetNs + 234567, offsetNs + 345678};
|
||||||
ArrayList<Long> actualPresentationTimesNs = new ArrayList<>();
|
ArrayList<Long> actualPresentationTimesUs = new ArrayList<>();
|
||||||
setupGlEffectsFrameProcessorWithBlankFrameProducer(
|
setupGlEffectsFrameProcessorWithBlankFrameProducer(
|
||||||
/* inputPresentationTimesUs= */ originalPresentationTimesUs,
|
/* inputPresentationTimesUs= */ originalPresentationTimesUs,
|
||||||
/* onFrameAvailableListener= */ actualPresentationTimesNs::add,
|
/* onFrameAvailableListener= */ actualPresentationTimesUs::add,
|
||||||
/* releaseFramesAutomatically= */ false);
|
/* releaseFramesAutomatically= */ false);
|
||||||
|
|
||||||
checkNotNull(produceBlankFramesTask).run();
|
checkNotNull(produceBlankFramesTask).run();
|
||||||
@ -227,11 +229,11 @@ public final class GlEffectsFrameProcessorFrameReleaseTest {
|
|||||||
Thread.sleep(FRAME_PROCESSING_WAIT_MS);
|
Thread.sleep(FRAME_PROCESSING_WAIT_MS);
|
||||||
|
|
||||||
assertThat(frameProcessingException.get()).isNull();
|
assertThat(frameProcessingException.get()).isNull();
|
||||||
assertThat(actualPresentationTimesNs)
|
assertThat(actualPresentationTimesUs)
|
||||||
.containsExactly(
|
.containsExactly(
|
||||||
MICROS_TO_NANOS * originalPresentationTimesUs[0],
|
originalPresentationTimesUs[0],
|
||||||
MICROS_TO_NANOS * originalPresentationTimesUs[1],
|
originalPresentationTimesUs[1],
|
||||||
MICROS_TO_NANOS * originalPresentationTimesUs[2])
|
originalPresentationTimesUs[2])
|
||||||
.inOrder();
|
.inOrder();
|
||||||
assertThat(outputReleaseTimesNs)
|
assertThat(outputReleaseTimesNs)
|
||||||
.containsExactly(releaseTimesNs[0], releaseTimesNs[1], releaseTimesNs[2])
|
.containsExactly(releaseTimesNs[0], releaseTimesNs[1], releaseTimesNs[2])
|
||||||
@ -239,7 +241,7 @@ public final class GlEffectsFrameProcessorFrameReleaseTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private interface OnFrameAvailableListener {
|
private interface OnFrameAvailableListener {
|
||||||
void onFrameAvailable(long presentationTimeNs);
|
void onFrameAvailable(long presentationTimeUs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@EnsuresNonNull("glEffectsFrameProcessor")
|
@EnsuresNonNull("glEffectsFrameProcessor")
|
||||||
@ -275,8 +277,8 @@ public final class GlEffectsFrameProcessorFrameReleaseTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onOutputFrameAvailable(long presentationTimeNs) {
|
public void onOutputFrameAvailable(long presentationTimeUs) {
|
||||||
onFrameAvailableListener.onFrameAvailable(presentationTimeNs);
|
onFrameAvailableListener.onFrameAvailable(presentationTimeUs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -477,7 +477,7 @@ public final class GlEffectsFrameProcessorPixelTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onOutputFrameAvailable(long presentationTimeNs) {
|
public void onOutputFrameAvailable(long presentationTimeUs) {
|
||||||
// Do nothing as frames are released automatically.
|
// Do nothing as frames are released automatically.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,13 +144,13 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
public void queueInputFrame(TextureInfo inputTexture, long presentationTimeUs) {
|
public void queueInputFrame(TextureInfo inputTexture, long presentationTimeUs) {
|
||||||
long streamOffsetUs =
|
long streamOffsetUs =
|
||||||
checkStateNotNull(streamOffsetUsQueue.peek(), "No input stream specified.");
|
checkStateNotNull(streamOffsetUsQueue.peek(), "No input stream specified.");
|
||||||
long presentationTimeNs = (presentationTimeUs + streamOffsetUs) * 1000;
|
long offsetPresentationTimeUs = presentationTimeUs + streamOffsetUs;
|
||||||
frameProcessorListener.onOutputFrameAvailable(presentationTimeNs);
|
frameProcessorListener.onOutputFrameAvailable(offsetPresentationTimeUs);
|
||||||
if (releaseFramesAutomatically) {
|
if (releaseFramesAutomatically) {
|
||||||
renderFrameToSurfaces(
|
renderFrameToSurfaces(
|
||||||
inputTexture,
|
inputTexture,
|
||||||
presentationTimeUs,
|
presentationTimeUs,
|
||||||
/* releaseTimeNs= */ presentationTimeNs,
|
/* releaseTimeNs= */ offsetPresentationTimeUs * 1000,
|
||||||
/* dropLateFrame= */ false);
|
/* dropLateFrame= */ false);
|
||||||
} else {
|
} else {
|
||||||
availableFrames.add(Pair.create(inputTexture, presentationTimeUs));
|
availableFrames.add(Pair.create(inputTexture, presentationTimeUs));
|
||||||
|
@ -126,7 +126,7 @@ import org.checkerframework.dataflow.qual.Pure;
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onOutputFrameAvailable(long presentationTimeNs) {
|
public void onOutputFrameAvailable(long presentationTimeUs) {
|
||||||
// Do nothing as frames are released automatically.
|
// Do nothing as frames are released automatically.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user