diff --git a/libraries/common/src/main/java/androidx/media3/common/FrameProcessor.java b/libraries/common/src/main/java/androidx/media3/common/FrameProcessor.java index 9ce300eabd..23776a216c 100644 --- a/libraries/common/src/main/java/androidx/media3/common/FrameProcessor.java +++ b/libraries/common/src/main/java/androidx/media3/common/FrameProcessor.java @@ -81,11 +81,11 @@ public interface FrameProcessor { 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. diff --git a/libraries/effect/src/androidTest/java/androidx/media3/effect/GlEffectsFrameProcessorFrameReleaseTest.java b/libraries/effect/src/androidTest/java/androidx/media3/effect/GlEffectsFrameProcessorFrameReleaseTest.java index 8d4eab2f2a..c94f6c97eb 100644 --- a/libraries/effect/src/androidTest/java/androidx/media3/effect/GlEffectsFrameProcessorFrameReleaseTest.java +++ b/libraries/effect/src/androidTest/java/androidx/media3/effect/GlEffectsFrameProcessorFrameReleaseTest.java @@ -72,52 +72,57 @@ public final class GlEffectsFrameProcessorFrameReleaseTest { @Test public void automaticFrameRelease_withOneFrame_reusesInputTimestamp() throws Exception { long originalPresentationTimeUs = 1234; - AtomicLong actualPresentationTimeNs = new AtomicLong(); + AtomicLong actualPresentationTimeUs = new AtomicLong(); setupGlEffectsFrameProcessorWithBlankFrameProducer( /* inputPresentationTimesUs= */ new long[] {originalPresentationTimeUs}, - /* onFrameAvailableListener= */ actualPresentationTimeNs::set, + /* onFrameAvailableListener= */ actualPresentationTimeUs::set, /* releaseFramesAutomatically= */ true); checkNotNull(produceBlankFramesTask).run(); Thread.sleep(FRAME_PROCESSING_WAIT_MS); assertThat(frameProcessingException.get()).isNull(); - assertThat(actualPresentationTimeNs.get()) - .isEqualTo(MICROS_TO_NANOS * originalPresentationTimeUs); + assertThat(actualPresentationTimeUs.get()).isEqualTo(originalPresentationTimeUs); assertThat(outputReleaseTimesNs).containsExactly(MICROS_TO_NANOS * originalPresentationTimeUs); } @Test public void automaticFrameRelease_withThreeFrames_reusesInputTimestamps() throws Exception { long[] originalPresentationTimesUs = new long[] {1234, 3456, 4567}; - ArrayList actualPresentationTimesNs = new ArrayList<>(); + ArrayList actualPresentationTimesUs = new ArrayList<>(); setupGlEffectsFrameProcessorWithBlankFrameProducer( originalPresentationTimesUs, - /* onFrameAvailableListener= */ actualPresentationTimesNs::add, + /* onFrameAvailableListener= */ actualPresentationTimesUs::add, /* releaseFramesAutomatically= */ true); checkNotNull(produceBlankFramesTask).run(); Thread.sleep(FRAME_PROCESSING_WAIT_MS); assertThat(frameProcessingException.get()).isNull(); - assertThat(actualPresentationTimesNs) + assertThat(actualPresentationTimesUs) + .containsExactly( + originalPresentationTimesUs[0], + originalPresentationTimesUs[1], + originalPresentationTimesUs[2]) + .inOrder(); + assertThat(outputReleaseTimesNs) .containsExactly( MICROS_TO_NANOS * originalPresentationTimesUs[0], MICROS_TO_NANOS * originalPresentationTimesUs[1], MICROS_TO_NANOS * originalPresentationTimesUs[2]) .inOrder(); - assertThat(outputReleaseTimesNs).containsExactlyElementsIn(actualPresentationTimesNs).inOrder(); + ; } @Test public void controlledFrameRelease_withOneFrame_usesGivenTimestamp() throws Exception { long originalPresentationTimeUs = 1234; long releaseTimesNs = System.nanoTime() + MILLIS_TO_NANOS * FRAME_PROCESSING_WAIT_MS + 345678; - AtomicLong actualPresentationTimeNs = new AtomicLong(); + AtomicLong actualPresentationTimeUs = new AtomicLong(); setupGlEffectsFrameProcessorWithBlankFrameProducer( /* inputPresentationTimesUs= */ new long[] {originalPresentationTimeUs}, - /* onFrameAvailableListener= */ presentationTimeNs -> { - actualPresentationTimeNs.set(presentationTimeNs); + /* onFrameAvailableListener= */ presentationTimeUs -> { + actualPresentationTimeUs.set(presentationTimeUs); checkNotNull(glEffectsFrameProcessor).releaseOutputFrame(releaseTimesNs); }, /* releaseFramesAutomatically= */ false); @@ -126,8 +131,7 @@ public final class GlEffectsFrameProcessorFrameReleaseTest { Thread.sleep(FRAME_PROCESSING_WAIT_MS); assertThat(frameProcessingException.get()).isNull(); - assertThat(actualPresentationTimeNs.get()) - .isEqualTo(MICROS_TO_NANOS * originalPresentationTimeUs); + assertThat(actualPresentationTimeUs.get()).isEqualTo(originalPresentationTimeUs); assertThat(outputReleaseTimesNs).containsExactly(releaseTimesNs); } @@ -135,11 +139,11 @@ public final class GlEffectsFrameProcessorFrameReleaseTest { public void controlledFrameRelease_withLateFrame_dropsFrame() throws Exception { long originalPresentationTimeUs = 1234; long releaseTimeBeforeCurrentTimeNs = System.nanoTime() - 345678; - AtomicLong actualPresentationTimeNs = new AtomicLong(); + AtomicLong actualPresentationTimeUs = new AtomicLong(); setupGlEffectsFrameProcessorWithBlankFrameProducer( /* inputPresentationTimesUs= */ new long[] {originalPresentationTimeUs}, - /* onFrameAvailableListener= */ presentationTimeNs -> { - actualPresentationTimeNs.set(presentationTimeNs); + /* onFrameAvailableListener= */ presentationTimeUs -> { + actualPresentationTimeUs.set(presentationTimeUs); checkNotNull(glEffectsFrameProcessor).releaseOutputFrame(releaseTimeBeforeCurrentTimeNs); }, /* releaseFramesAutomatically= */ false); @@ -148,19 +152,18 @@ public final class GlEffectsFrameProcessorFrameReleaseTest { Thread.sleep(FRAME_PROCESSING_WAIT_MS); assertThat(frameProcessingException.get()).isNull(); - assertThat(actualPresentationTimeNs.get()) - .isEqualTo(MICROS_TO_NANOS * originalPresentationTimeUs); + assertThat(actualPresentationTimeUs.get()).isEqualTo(originalPresentationTimeUs); assertThat(outputReleaseTimesNs).isEmpty(); } @Test public void controlledFrameRelease_withUnsetReleaseTime_dropsFrame() throws Exception { long originalPresentationTimeUs = 1234; - AtomicLong actualPresentationTimeNs = new AtomicLong(); + AtomicLong actualPresentationTimeUs = new AtomicLong(); setupGlEffectsFrameProcessorWithBlankFrameProducer( /* inputPresentationTimesUs= */ new long[] {originalPresentationTimeUs}, /* onFrameAvailableListener= */ presentationTimeNs -> { - actualPresentationTimeNs.set(presentationTimeNs); + actualPresentationTimeUs.set(presentationTimeNs); checkNotNull(glEffectsFrameProcessor) .releaseOutputFrame(/* releaseTimeNs= */ C.TIME_UNSET); }, @@ -170,8 +173,7 @@ public final class GlEffectsFrameProcessorFrameReleaseTest { Thread.sleep(FRAME_PROCESSING_WAIT_MS); assertThat(frameProcessingException.get()).isNull(); - assertThat(actualPresentationTimeNs.get()) - .isEqualTo(MICROS_TO_NANOS * originalPresentationTimeUs); + assertThat(actualPresentationTimeUs.get()).isEqualTo(originalPresentationTimeUs); assertThat(outputReleaseTimesNs).isEmpty(); } @@ -181,12 +183,12 @@ public final class GlEffectsFrameProcessorFrameReleaseTest { long[] originalPresentationTimesUs = new long[] {1234, 3456, 4567}; long offsetNs = System.nanoTime() + MILLIS_TO_NANOS * FRAME_PROCESSING_WAIT_MS; long[] releaseTimesNs = new long[] {offsetNs + 123456, offsetNs + 234567, offsetNs + 345678}; - ArrayList actualPresentationTimesNs = new ArrayList<>(); + ArrayList actualPresentationTimesUs = new ArrayList<>(); AtomicInteger frameIndex = new AtomicInteger(); setupGlEffectsFrameProcessorWithBlankFrameProducer( /* inputPresentationTimesUs= */ originalPresentationTimesUs, - /* onFrameAvailableListener= */ presentationTimeNs -> { - actualPresentationTimesNs.add(presentationTimeNs); + /* onFrameAvailableListener= */ presentationTimeUs -> { + actualPresentationTimesUs.add(presentationTimeUs); checkNotNull(glEffectsFrameProcessor) .releaseOutputFrame(releaseTimesNs[frameIndex.getAndIncrement()]); }, @@ -196,11 +198,11 @@ public final class GlEffectsFrameProcessorFrameReleaseTest { Thread.sleep(FRAME_PROCESSING_WAIT_MS); assertThat(frameProcessingException.get()).isNull(); - assertThat(actualPresentationTimesNs) + assertThat(actualPresentationTimesUs) .containsExactly( - MICROS_TO_NANOS * originalPresentationTimesUs[0], - MICROS_TO_NANOS * originalPresentationTimesUs[1], - MICROS_TO_NANOS * originalPresentationTimesUs[2]) + originalPresentationTimesUs[0], + originalPresentationTimesUs[1], + originalPresentationTimesUs[2]) .inOrder(); assertThat(frameIndex.get()).isEqualTo(originalPresentationTimesUs.length); assertThat(outputReleaseTimesNs) @@ -213,10 +215,10 @@ public final class GlEffectsFrameProcessorFrameReleaseTest { long[] originalPresentationTimesUs = new long[] {1234, 3456, 4567}; long offsetNs = System.nanoTime() + MILLIS_TO_NANOS * 2 * FRAME_PROCESSING_WAIT_MS; long[] releaseTimesNs = new long[] {offsetNs + 123456, offsetNs + 234567, offsetNs + 345678}; - ArrayList actualPresentationTimesNs = new ArrayList<>(); + ArrayList actualPresentationTimesUs = new ArrayList<>(); setupGlEffectsFrameProcessorWithBlankFrameProducer( /* inputPresentationTimesUs= */ originalPresentationTimesUs, - /* onFrameAvailableListener= */ actualPresentationTimesNs::add, + /* onFrameAvailableListener= */ actualPresentationTimesUs::add, /* releaseFramesAutomatically= */ false); checkNotNull(produceBlankFramesTask).run(); @@ -227,11 +229,11 @@ public final class GlEffectsFrameProcessorFrameReleaseTest { Thread.sleep(FRAME_PROCESSING_WAIT_MS); assertThat(frameProcessingException.get()).isNull(); - assertThat(actualPresentationTimesNs) + assertThat(actualPresentationTimesUs) .containsExactly( - MICROS_TO_NANOS * originalPresentationTimesUs[0], - MICROS_TO_NANOS * originalPresentationTimesUs[1], - MICROS_TO_NANOS * originalPresentationTimesUs[2]) + originalPresentationTimesUs[0], + originalPresentationTimesUs[1], + originalPresentationTimesUs[2]) .inOrder(); assertThat(outputReleaseTimesNs) .containsExactly(releaseTimesNs[0], releaseTimesNs[1], releaseTimesNs[2]) @@ -239,7 +241,7 @@ public final class GlEffectsFrameProcessorFrameReleaseTest { } private interface OnFrameAvailableListener { - void onFrameAvailable(long presentationTimeNs); + void onFrameAvailable(long presentationTimeUs); } @EnsuresNonNull("glEffectsFrameProcessor") @@ -275,8 +277,8 @@ public final class GlEffectsFrameProcessorFrameReleaseTest { } @Override - public void onOutputFrameAvailable(long presentationTimeNs) { - onFrameAvailableListener.onFrameAvailable(presentationTimeNs); + public void onOutputFrameAvailable(long presentationTimeUs) { + onFrameAvailableListener.onFrameAvailable(presentationTimeUs); } @Override diff --git a/libraries/effect/src/androidTest/java/androidx/media3/effect/GlEffectsFrameProcessorPixelTest.java b/libraries/effect/src/androidTest/java/androidx/media3/effect/GlEffectsFrameProcessorPixelTest.java index 06d3139ef2..92de9b1828 100644 --- a/libraries/effect/src/androidTest/java/androidx/media3/effect/GlEffectsFrameProcessorPixelTest.java +++ b/libraries/effect/src/androidTest/java/androidx/media3/effect/GlEffectsFrameProcessorPixelTest.java @@ -477,7 +477,7 @@ public final class GlEffectsFrameProcessorPixelTest { } @Override - public void onOutputFrameAvailable(long presentationTimeNs) { + public void onOutputFrameAvailable(long presentationTimeUs) { // Do nothing as frames are released automatically. } diff --git a/libraries/effect/src/main/java/androidx/media3/effect/FinalMatrixTransformationProcessorWrapper.java b/libraries/effect/src/main/java/androidx/media3/effect/FinalMatrixTransformationProcessorWrapper.java index 747e9f04bc..eff8b8d18b 100644 --- a/libraries/effect/src/main/java/androidx/media3/effect/FinalMatrixTransformationProcessorWrapper.java +++ b/libraries/effect/src/main/java/androidx/media3/effect/FinalMatrixTransformationProcessorWrapper.java @@ -144,13 +144,13 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; public void queueInputFrame(TextureInfo inputTexture, long presentationTimeUs) { long streamOffsetUs = checkStateNotNull(streamOffsetUsQueue.peek(), "No input stream specified."); - long presentationTimeNs = (presentationTimeUs + streamOffsetUs) * 1000; - frameProcessorListener.onOutputFrameAvailable(presentationTimeNs); + long offsetPresentationTimeUs = presentationTimeUs + streamOffsetUs; + frameProcessorListener.onOutputFrameAvailable(offsetPresentationTimeUs); if (releaseFramesAutomatically) { renderFrameToSurfaces( inputTexture, presentationTimeUs, - /* releaseTimeNs= */ presentationTimeNs, + /* releaseTimeNs= */ offsetPresentationTimeUs * 1000, /* dropLateFrame= */ false); } else { availableFrames.add(Pair.create(inputTexture, presentationTimeUs)); diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/VideoTranscodingSamplePipeline.java b/libraries/transformer/src/main/java/androidx/media3/transformer/VideoTranscodingSamplePipeline.java index 991784ffa7..09d6306883 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/VideoTranscodingSamplePipeline.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/VideoTranscodingSamplePipeline.java @@ -126,7 +126,7 @@ import org.checkerframework.dataflow.qual.Pure; } @Override - public void onOutputFrameAvailable(long presentationTimeNs) { + public void onOutputFrameAvailable(long presentationTimeUs) { // Do nothing as frames are released automatically. }