Android SurfaceView resize to fit screen 16:9 - android

Hello! Is there a good way of having a 16:9 SurfaceView, and then resize it bigger until it touches a screen edge? (so the SurfaceView is at its biggest size and still 16:9 and not outside the screen)
I have heard it is called letterbox, but havn't found any tutorial about it.
Thanks

There are two relevant sizes, the size of the Surface and the size of the View.
The size of the Surface is determined by the size of the video being rendered to it. You can't change this. A 720p video will set the size to 1280x720.
The size of the View is determined by the layout code. This can be set from within your app.
The system compositor (SurfaceFlinger) will scale the contents of the Surface so they fit in the View. To avoid distortion, you want to maintain the same aspect ratio. You do this with a custom FrameLayout.
For an example, see how AspectFrameLayout is used in Grafika's video players, e.g. this chunk of code.

Related

How to overlap a SurfaceView beyond the display area in Kotlin?

I have this school project where I have to adjust a video content
depending on the aspect ratio of the display area based on the set Screen Format.
I'm already done with the following Screen Formats:
Stretch-to-Fit
Letterbox/Pillarbox
But I just can't seem to nail the Crop format.
BACKGROUND:
Cropping happens when the display area aspect ratio is smaller than that of the video content
For example:
The display area is in (4:3) aspect ratio and video content is at (16:9) aspect ratio,
What is expected is:
Crop Format
The height of the video content will match that of the display area but doing so will also
increase the width of the video content. But the Crop format will just crop both sides of the
video content to match the display area.
NOTE:
I don't have access to the MediaPlayer class since I just pass the SurfaceView to another
component so the video content will be drawn.
It's been a few weeks now and I'm at my wits end that's why I decided to post here
for help.
Thank you
WHAT I ALREADY TRIED:
I already tried Scaling the SurfaceView using the setScaleX(2.0f) method.
But it doesn't seem to go beyond the display area.
I also tried setting the LayoutParams width to twice the value.
But it doesn't go beyond the display area too.

ExoPlayer2 Scaling

I have an Activity that contains a FrameLayout where ExoPlayer takes place.
This activity support both orientations and video aspect ratio should be preserved.
According to ExoPlayer docs, for the setResizeMode we can have one of the following:
RESIZE_MODE_FIT,
RESIZE_MODE_FIXED_WIDTH,
RESIZE_MODE_FIXED_HEIGHT,
RESIZE_MODE_FILL,
RESIZE_MODE_ZOOM
In my case, since I don't know the video size nor the device orientation, I can have two scenarios:
Video is larger than my Viewport, so I would like to have RESIZE_MODE_FIT to scale it down
Video is smaller than my Viewport, so I would like to have RESIZE_MODE_ZOOM to scale it up.
But in the end I could not find a way to achieve this behavior.
If I set RESIZE_MODE_FIT, small videos does not fill my Viewport.
If I set RESIZE_MODE_ZOOM, large videos overflow the Viewport.
Thanks.

How does PreviewView fill-scaling handle images which are higher resolution than the view?

When dealing with the PreviewView "FILL" scaling types (e.g. PreviewView.ScaleType.FILL_CENTER), the docs seem to imply that the image will not be scaled if it is higher resolution than the view.
Scale the preview, maintaining the source aspect ratio, so it fills the entire PreviewView, and center it in the view
In cases where the image is lower resolution than the view, I can understand why the image is scaled, as otherwise there would have to be black borders (i.e. would not fill the entire view), which FILL is guaranteeing will not be displayed. In cases where the image is higher resolution than the view, the preview image already fills the entire view (i.e. doesn't need to show black borders) so my assumption would be that the preview does not need to be scaled.
For example, your image is 1920x1080 and your view is 800x800, I would expect PreviewView to not scale the image and just crop an 800x800 square out of the centre of the existing image (using FILL_CENTER).
However when looking into the code I could not find any condition which actually stops scaling from happening when the resolution is higher.
For example:
preview.setScaleX(surfaceRectInPreviewView.width() / mResolution.getWidth());
preview.setScaleY(surfaceRectInPreviewView.height() / mResolution.getHeight());
preview.setTranslationX(surfaceRectInPreviewView.left - preview.getLeft());
preview.setTranslationY(surfaceRectInPreviewView.top - preview.getTop());
This code is after all the matrix transformations are done (which I don't fully understand), so I may be misinterpreting it. So I just wanted to validate my assumption about whether images are scaled if they are higher resolution than the view.
PreviewView is designed to display the largest possible FOV. If you wish to display a smaller FOV, you can take a look at the zooming APIs: https://developer.android.com/reference/androidx/camera/core/CameraControl#setZoomRatio(float)
The scaling in PreviewView is for getting rid of the black bars in case the aspect ratio of the preview does not match the aspect ratio of the view. It doesn't matter what resolutions they have.
In your example, the output image is 1920x1080 and the view is 800x800. For the FILL_* types, the output image will be scaled to fill the view, in which case it will be scaled to 1422x800, then the extras will be cropped out. For the FIT_* types, the output image will be scaled to fit the view, in which case it will be scaled to 800x450, and placed inside of the view.
Hope this helps. Please let me know if you have more questions.

How to get fullscreen textureview using camera2?

I am trying to get a full screen preview of the camera. I read through the documentation of camera2 which says Each Surface has to be pre-configured with an appropriate size and format (if applicable) to match the sizes and formats available from the camera device. Here is what I understand so far. Please correct me if any of my understanding is wrong:
The texture view and the preview buffer need to be the same aspect ratio. They can be different resolutions, but the aspect ratio must be the same if you don't want the preview to look distorted.
You should set the buffer size of the texture view to the optimally chosen preview size. camera2basic demo seems to confirm this with the line texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight().
The question I have is, once you match the aspect ratio and size of the texture view and the preview to be the same, how do you scale the texture view so that it fits fullscreen?
The camera2basic demo's configureTransform method seems to transform the TextureView to the preview size, but not make it full screen. How do I calculate the correct scale factor to make TextureView fullscreen?
You can just make your TextureView fill the screen in your Activity's layout. You'll then need to adjust the configureTransform() method to account for the aspect ratio difference between the full-screen TextureView and the closest-aspect preview size; basically you need to implement the usual letter- or pillar-boxing effect.
Of course, if there does happen to be a matching aspect ratio, you can use it directly, but this isn't too likely.

How to scale video on a SurfaceView larger than the window on Android?

Android 2.2 (on a media player boxtop) with a display of 1280x720.
My video is 480px high, 720px wide; standard definition.
I know that if change the layouts of a SurfaceView, the video is scaled to fit whichever is smallest to maintain aspect ratio.
This is great, except I can only scale up to the height of the screen. This is a problem as there is are black bars being broadcast on the top/bottom of the video.
See here:
http://i.imgur.com/dsiLw.jpg
I would need to make my SurfaceView (and the window) larger than the screen.
I know about FLAG_LAYOUT_NO_LIMITS, on WindowManager:
http://developer.android.com/reference/android/view/WindowManager.LayoutParams.html#FLAG_LAYOUT_NO_LIMITS
It is supposed to allow my window to expand out past the screen... but I can't seem to get this working. It always seems to resize it to 1280x720px no matter what I do.
If you could help me get this so I can expand my surfaceview video so it looks full screen (clipping the tops video), I will be extremely grateful.
:)

Categories

Resources