From 3ef609fa3b7f41774ca7453b53276fea1f4dfe52 Mon Sep 17 00:00:00 2001 From: olly Date: Fri, 13 Nov 2020 18:28:55 +0000 Subject: [PATCH] Plumb playback speed and frame-rate via VideoFrameReleaseTimeHelper PiperOrigin-RevId: 342289646 --- .../video/MediaCodecVideoRenderer.java | 9 +++-- .../video/VideoFrameReleaseTimeHelper.java | 40 ++++++++++++++++--- 2 files changed, 40 insertions(+), 9 deletions(-) diff --git a/library/core/src/main/java/com/google/android/exoplayer2/video/MediaCodecVideoRenderer.java b/library/core/src/main/java/com/google/android/exoplayer2/video/MediaCodecVideoRenderer.java index c6197e591f..cebcece5ae 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/video/MediaCodecVideoRenderer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/video/MediaCodecVideoRenderer.java @@ -141,7 +141,6 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { private int currentHeight; private int currentUnappliedRotationDegrees; private float currentPixelWidthHeightRatio; - private float currentFrameRate; private int reportedWidth; private int reportedHeight; private int reportedUnappliedRotationDegrees; @@ -588,6 +587,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { @Override public void setPlaybackSpeed(float playbackSpeed) throws ExoPlaybackException { super.setPlaybackSpeed(playbackSpeed); + frameReleaseTimeHelper.setPlaybackSpeed(playbackSpeed); updateSurfaceFrameRate(/* isNewSurface= */ false); } @@ -690,7 +690,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { // On API level 20 and below the decoder does not apply the rotation. currentUnappliedRotationDegrees = format.rotationDegrees; } - currentFrameRate = format.frameRate; + frameReleaseTimeHelper.setFormatFrameRate(format.frameRate); updateSurfaceFrameRate(/* isNewSurface= */ false); } @@ -1079,8 +1079,9 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { if (Util.SDK_INT < 30 || surface == null || surface == dummySurface) { return; } - boolean shouldSetFrameRate = getState() == STATE_STARTED && currentFrameRate != Format.NO_VALUE; - float surfaceFrameRate = shouldSetFrameRate ? currentFrameRate * getPlaybackSpeed() : 0; + float playbackFrameRate = frameReleaseTimeHelper.getPlaybackFrameRate(); + float surfaceFrameRate = + getState() == STATE_STARTED && playbackFrameRate != C.RATE_UNSET ? playbackFrameRate : 0; // We always set the frame-rate if we have a new surface, since we have no way of knowing what // it might have been set to previously. if (this.surfaceFrameRate == surfaceFrameRate && !isNewSurface) { diff --git a/library/core/src/main/java/com/google/android/exoplayer2/video/VideoFrameReleaseTimeHelper.java b/library/core/src/main/java/com/google/android/exoplayer2/video/VideoFrameReleaseTimeHelper.java index 01b296e747..143f41a676 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/video/VideoFrameReleaseTimeHelper.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/video/VideoFrameReleaseTimeHelper.java @@ -28,6 +28,7 @@ import android.view.WindowManager; import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; import com.google.android.exoplayer2.C; +import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.util.Util; /** @@ -45,6 +46,9 @@ public final class VideoFrameReleaseTimeHelper { @Nullable private final VSyncSampler vsyncSampler; @Nullable private final DefaultDisplayListener displayListener; + private float formatFrameRate; + private float playbackSpeed; + private long vsyncDurationNs; private long vsyncOffsetNs; @@ -87,9 +91,11 @@ public final class VideoFrameReleaseTimeHelper { } vsyncDurationNs = C.TIME_UNSET; vsyncOffsetNs = C.TIME_UNSET; + formatFrameRate = Format.NO_VALUE; + playbackSpeed = 1f; } - /** Enables the helper. Must be called from the playback thread. */ + /** Enables the helper. */ @TargetApi(17) // displayListener is null if Util.SDK_INT < 17. public void enable() { haveSync = false; @@ -102,7 +108,7 @@ public final class VideoFrameReleaseTimeHelper { } } - /** Disables the helper. Must be called from the playback thread. */ + /** Disables the helper. */ @TargetApi(17) // displayListener is null if Util.SDK_INT < 17. public void disable() { if (windowManager != null) { @@ -113,12 +119,36 @@ public final class VideoFrameReleaseTimeHelper { } } + /** Returns the estimated playback frame rate, or {@link C#RATE_UNSET} if unknown. */ + public float getPlaybackFrameRate() { + return formatFrameRate == Format.NO_VALUE ? C.RATE_UNSET : (formatFrameRate * playbackSpeed); + } + /** - * Adjusts a frame release timestamp. Must be called from the playback thread. + * Sets the player's speed, where 1 is the default rate, 2 is twice the default rate, 0.5 is half + * the default rate and so on. + * + * @param playbackSpeed The player's speed. + */ + public void setPlaybackSpeed(float playbackSpeed) { + this.playbackSpeed = playbackSpeed; + } + + /** + * Sets the format's frame rate in frames per second, or {@link Format#NO_VALUE} if unknown. + * + * @param formatFrameRate The format's frame rate, or {@link Format#NO_VALUE}. + */ + public void setFormatFrameRate(float formatFrameRate) { + this.formatFrameRate = formatFrameRate; + } + + /** + * Adjusts a frame release timestamp. * * @param framePresentationTimeUs The frame's presentation time, in microseconds. - * @param unadjustedReleaseTimeNs The frame's unadjusted release time, in nanoseconds and in - * the same time base as {@link System#nanoTime()}. + * @param unadjustedReleaseTimeNs The frame's unadjusted release time, in nanoseconds and in the + * same time base as {@link System#nanoTime()}. * @return The adjusted frame release timestamp, in nanoseconds and in the same time base as * {@link System#nanoTime()}. */