diff options
Diffstat (limited to 'java/com/android/incallui/videosurface/impl/VideoScale.java')
-rw-r--r-- | java/com/android/incallui/videosurface/impl/VideoScale.java | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/java/com/android/incallui/videosurface/impl/VideoScale.java b/java/com/android/incallui/videosurface/impl/VideoScale.java new file mode 100644 index 000000000..1444f5900 --- /dev/null +++ b/java/com/android/incallui/videosurface/impl/VideoScale.java @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2016 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.android.incallui.videosurface.impl; + +import android.graphics.Matrix; +import android.view.TextureView; +import com.android.dialer.common.LogUtil; + +/** Utilities to scale the preview and remote video. */ +public class VideoScale { + /** + * Scales the video in the given view such that the video takes up the entire view. To maintain + * aspect ratio the video will be scaled to be larger than the view. + */ + public static void scaleVideoAndFillView( + TextureView textureView, float videoWidth, float videoHeight, float rotationDegrees) { + float viewWidth = textureView.getWidth(); + float viewHeight = textureView.getHeight(); + float viewAspectRatio = viewWidth / viewHeight; + float videoAspectRatio = videoWidth / videoHeight; + float scaleWidth = 1.0f; + float scaleHeight = 1.0f; + + if (viewAspectRatio > videoAspectRatio) { + // Scale to exactly fit the width of the video. The top and bottom will be cropped. + float scaleFactor = viewWidth / videoWidth; + float desiredScaledHeight = videoHeight * scaleFactor; + scaleHeight = desiredScaledHeight / viewHeight; + } else { + // Scale to exactly fit the height of the video. The sides will be cropped. + float scaleFactor = viewHeight / videoHeight; + float desiredScaledWidth = videoWidth * scaleFactor; + scaleWidth = desiredScaledWidth / viewWidth; + } + + if (rotationDegrees == 90.0f || rotationDegrees == 270.0f) { + // We're in landscape mode but the camera feed is still drawing in portrait mode. Normally, + // scale of 1.0 means that the video feed stretches to fit the view. In this case the X axis + // is scaled to fit the height and the Y axis is scaled to fit the width. + float scaleX = scaleWidth; + float scaleY = scaleHeight; + scaleWidth = viewHeight / viewWidth * scaleY; + scaleHeight = viewWidth / viewHeight * scaleX; + + // This flips the view vertically. Without this the camera feed would be upside down. + scaleWidth = scaleWidth * -1.0f; + // This flips the view horizontally. Without this the camera feed would be mirrored (left + // side would appear on right). + scaleHeight = scaleHeight * -1.0f; + } + + LogUtil.i( + "VideoScale.scaleVideoAndFillView", + "view: %f x %f, video: %f x %f scale: %f x %f, rotation: %f", + viewWidth, + viewHeight, + videoWidth, + videoHeight, + scaleWidth, + scaleHeight, + rotationDegrees); + + Matrix transform = new Matrix(); + transform.setScale( + scaleWidth, + scaleHeight, + // This performs the scaling from the horizontal middle of the view. + viewWidth / 2.0f, + // This perform the scaling from vertical middle of the view. + viewHeight / 2.0f); + if (rotationDegrees != 0) { + transform.postRotate(rotationDegrees, viewWidth / 2.0f, viewHeight / 2.0f); + } + textureView.setTransform(transform); + } + + /** + * Scales the video in the given view such that all of the video is visible. This will result in + * black bars on the top and bottom or the sides of the video. + */ + public static void scaleVideoMaintainingAspectRatio( + TextureView textureView, int videoWidth, int videoHeight) { + int viewWidth = textureView.getWidth(); + int viewHeight = textureView.getHeight(); + float scaleWidth = 1.0f; + float scaleHeight = 1.0f; + + if (viewWidth > viewHeight) { + // Landscape layout. + if (viewHeight * videoWidth > viewWidth * videoHeight) { + // Current display height is too much. Correct it. + int desiredHeight = viewWidth * videoHeight / videoWidth; + scaleWidth = (float) desiredHeight / (float) viewHeight; + } else if (viewHeight * videoWidth < viewWidth * videoHeight) { + // Current display width is too much. Correct it. + int desiredWidth = viewHeight * videoWidth / videoHeight; + scaleWidth = (float) desiredWidth / (float) viewWidth; + } + } else { + // Portrait layout. + if (viewHeight * videoWidth > viewWidth * videoHeight) { + // Current display height is too much. Correct it. + int desiredHeight = viewWidth * videoHeight / videoWidth; + scaleHeight = (float) desiredHeight / (float) viewHeight; + } else if (viewHeight * videoWidth < viewWidth * videoHeight) { + // Current display width is too much. Correct it. + int desiredWidth = viewHeight * videoWidth / videoHeight; + scaleHeight = (float) desiredWidth / (float) viewWidth; + } + } + + LogUtil.i( + "VideoScale.scaleVideoMaintainingAspectRatio", + "view: %d x %d, video: %d x %d scale: %f x %f", + viewWidth, + viewHeight, + videoWidth, + videoHeight, + scaleWidth, + scaleHeight); + Matrix transform = new Matrix(); + transform.setScale( + scaleWidth, + scaleHeight, + // This performs the scaling from the horizontal middle of the view. + viewWidth / 2.0f, + // This perform the scaling from vertical middle of the view. + viewHeight / 2.0f); + textureView.setTransform(transform); + } + + private VideoScale() {} +} |