From 0ead7bb221916f9862cd20e5c78e0da6971f916d Mon Sep 17 00:00:00 2001 From: Colin Kho Date: Thu, 25 Jul 2024 22:12:15 -0700 Subject: [PATCH 1/2] Refactor getMaxVideoSizeInViewport into TrackSelectionUtil so it can be reused in external code --- .../trackselection/DefaultTrackSelector.java | 28 +------------------ .../trackselection/TrackSelectionUtil.java | 28 +++++++++++++++++++ 2 files changed, 29 insertions(+), 27 deletions(-) diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/trackselection/DefaultTrackSelector.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/trackselection/DefaultTrackSelector.java index 801f34b365..b34939927d 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/trackselection/DefaultTrackSelector.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/trackselection/DefaultTrackSelector.java @@ -3361,7 +3361,7 @@ public class DefaultTrackSelector extends MappingTrackSelector // smallest to exceed the maximum size at which it can be displayed within the viewport. if (format.width > 0 && format.height > 0) { Point maxVideoSizeInViewport = - getMaxVideoSizeInViewport( + TrackSelectionUtil.getMaxVideoSizeInViewport( orientationMayChange, viewportWidth, viewportHeight, format.width, format.height); int videoPixels = format.width * format.height; if (format.width >= (int) (maxVideoSizeInViewport.x * FRACTION_TO_CONSIDER_FULLSCREEN) @@ -3374,32 +3374,6 @@ public class DefaultTrackSelector extends MappingTrackSelector return maxVideoPixelsToRetain; } - /** - * Given viewport dimensions and video dimensions, computes the maximum size of the video as it - * will be rendered to fit inside of the viewport. - */ - private static Point getMaxVideoSizeInViewport( - boolean orientationMayChange, - int viewportWidth, - int viewportHeight, - int videoWidth, - int videoHeight) { - if (orientationMayChange && (videoWidth > videoHeight) != (viewportWidth > viewportHeight)) { - // Rotation is allowed, and the video will be larger in the rotated viewport. - int tempViewportWidth = viewportWidth; - viewportWidth = viewportHeight; - viewportHeight = tempViewportWidth; - } - - if (videoWidth * viewportHeight >= videoHeight * viewportWidth) { - // Horizontal letter-boxing along top and bottom. - return new Point(viewportWidth, Util.ceilDivide(viewportWidth * videoHeight, videoWidth)); - } else { - // Vertical letter-boxing along edges. - return new Point(Util.ceilDivide(viewportHeight * videoWidth, videoHeight), viewportHeight); - } - } - private static int getRoleFlagMatchScore(int trackRoleFlags, int preferredRoleFlags) { if (trackRoleFlags != 0 && trackRoleFlags == preferredRoleFlags) { // Prefer perfect match over partial matches. diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/trackselection/TrackSelectionUtil.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/trackselection/TrackSelectionUtil.java index 6dd1a62e90..2509294c43 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/trackselection/TrackSelectionUtil.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/trackselection/TrackSelectionUtil.java @@ -15,6 +15,7 @@ */ package androidx.media3.exoplayer.trackselection; +import android.graphics.Point; import android.os.SystemClock; import androidx.annotation.Nullable; import androidx.media3.common.C; @@ -22,6 +23,7 @@ import androidx.media3.common.TrackGroup; import androidx.media3.common.Tracks; import androidx.media3.common.util.NullableType; import androidx.media3.common.util.UnstableApi; +import androidx.media3.common.util.Util; import androidx.media3.exoplayer.RendererCapabilities; import androidx.media3.exoplayer.source.TrackGroupArray; import androidx.media3.exoplayer.trackselection.DefaultTrackSelector.SelectionOverride; @@ -203,4 +205,30 @@ public final class TrackSelectionUtil { } return new Tracks(trackGroups.build()); } + + /** + * Given viewport dimensions and video dimensions, computes the maximum size of the video as it + * will be rendered to fit inside of the viewport. + */ + public static Point getMaxVideoSizeInViewport( + boolean orientationMayChange, + int viewportWidth, + int viewportHeight, + int videoWidth, + int videoHeight) { + if (orientationMayChange && (videoWidth > videoHeight) != (viewportWidth > viewportHeight)) { + // Rotation is allowed, and the video will be larger in the rotated viewport. + int tempViewportWidth = viewportWidth; + viewportWidth = viewportHeight; + viewportHeight = tempViewportWidth; + } + + if (videoWidth * viewportHeight >= videoHeight * viewportWidth) { + // Horizontal letter-boxing along top and bottom. + return new Point(viewportWidth, Util.ceilDivide(viewportWidth * videoHeight, videoWidth)); + } else { + // Vertical letter-boxing along edges. + return new Point(Util.ceilDivide(viewportHeight * videoWidth, videoHeight), viewportHeight); + } + } } From 335d5e7a1d9200688b083a3f6c980dd335ad5696 Mon Sep 17 00:00:00 2001 From: Ian Baker Date: Mon, 29 Jul 2024 15:11:38 +0100 Subject: [PATCH 2/2] Add some tests to TrackSelectionUtilTest --- .../TrackSelectionUtilTest.java | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/trackselection/TrackSelectionUtilTest.java b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/trackselection/TrackSelectionUtilTest.java index d8befc1eae..bd4ee18621 100644 --- a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/trackselection/TrackSelectionUtilTest.java +++ b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/trackselection/TrackSelectionUtilTest.java @@ -30,6 +30,7 @@ import static androidx.media3.exoplayer.RendererCapabilities.ADAPTIVE_NOT_SUPPOR import static androidx.media3.exoplayer.RendererCapabilities.ADAPTIVE_SEAMLESS; import static com.google.common.truth.Truth.assertThat; +import android.graphics.Point; import androidx.media3.common.Format; import androidx.media3.common.TrackGroup; import androidx.media3.common.Tracks; @@ -148,4 +149,86 @@ public class TrackSelectionUtilTest { assertThat(trackGroups.get(0).getType()).isEqualTo(TRACK_TYPE_AUDIO); assertThat(trackGroups.get(1).getType()).isEqualTo(TRACK_TYPE_AUDIO); } + + @Test + public void getMaxVideoSizeInViewport_aspectRatioMatches() { + Point maxVideoSize = + TrackSelectionUtil.getMaxVideoSizeInViewport( + /* orientationMayChange= */ true, + /* viewportWidth= */ 1920, + /* viewportHeight= */ 1080, + /* videoWidth= */ 3840, + /* videoHeight= */ 2160); + + assertThat(maxVideoSize).isEqualTo(new Point(1920, 1080)); + } + + @Test + public void getMaxVideoSizeInViewport_rotatedAspectRatioMatches_rotationAllowed() { + Point maxVideoSize = + TrackSelectionUtil.getMaxVideoSizeInViewport( + /* orientationMayChange= */ true, + /* viewportWidth= */ 1080, + /* viewportHeight= */ 1920, + /* videoWidth= */ 3840, + /* videoHeight= */ 2160); + + assertThat(maxVideoSize).isEqualTo(new Point(1920, 1080)); + } + + @Test + public void getMaxVideoSizeInViewport_letterboxing() { + // 16:9 content on 16:10 screen + Point maxVideoSize = + TrackSelectionUtil.getMaxVideoSizeInViewport( + /* orientationMayChange= */ false, + /* viewportWidth= */ 1920, + /* viewportHeight= */ 1200, + /* videoWidth= */ 1280, + /* videoHeight= */ 720); + + assertThat(maxVideoSize).isEqualTo(new Point(1920, 1080)); + } + + @Test + public void getMaxVideoSizeInViewport_letterboxingWhenRotated() { + // 16:9 content on 10:16 screen + Point maxVideoSize = + TrackSelectionUtil.getMaxVideoSizeInViewport( + /* orientationMayChange= */ true, + /* viewportWidth= */ 1200, + /* viewportHeight= */ 1920, + /* videoWidth= */ 1280, + /* videoHeight= */ 720); + + assertThat(maxVideoSize).isEqualTo(new Point(1920, 1080)); + } + + @Test + public void getMaxVideoSizeInViewport_pillarboxing() { + // 4:3 content on 16:10 screen + Point maxVideoSize = + TrackSelectionUtil.getMaxVideoSizeInViewport( + /* orientationMayChange= */ false, + /* viewportWidth= */ 1920, + /* viewportHeight= */ 1200, + /* videoWidth= */ 960, + /* videoHeight= */ 720); + + assertThat(maxVideoSize).isEqualTo(new Point(1600, 1200)); + } + + @Test + public void getMaxVideoSizeInViewport_pillarboxingWhenRotated() { + // 4:3 content on 10:16 screen + Point maxVideoSize = + TrackSelectionUtil.getMaxVideoSizeInViewport( + /* orientationMayChange= */ true, + /* viewportWidth= */ 1200, + /* viewportHeight= */ 1920, + /* videoWidth= */ 960, + /* videoHeight= */ 720); + + assertThat(maxVideoSize).isEqualTo(new Point(1600, 1200)); + } }