Reputation: 3
I have a texture view that displays video from the camera. The texture view is constrained by a fixed-width framelayout on the right, with buttons. Its constrained on the bottom by another framelayout that has a fixed height, and a width that should go from the left edge of the screen to the left edge of the main framelayout. So the texture view's aspect ratio should change depending on the screen aspect ratio of the device.
The video preview itself can also change aspect ratio, because the video size is user-selectable. For instance, on my phone, there are options for 4:3, 16:9, and 2:1 video sizes. The desired behavior is for the video preview to always fit within the textureview, without cropping, and without stretching. Thus in most cases, this will mean black bars on the sides, or on the top and bottom of the video. Unless, of course, the aspect ratio of the texture view and the video preview happen to be the same.
Here's my XML: (My app is landscape only)
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.android.camera2video.AutoFitTextureView
android:id="@+id/texture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@id/longTexture"
android:layout_alignLeft="@id/longTexture"
android:layout_alignRight="@id/longTexture"
android:layout_alignTop="@id/mainPanel"
/>
<FrameLayout
android:id="@+id/longTexture"
android:layout_width="match_parent"
android:layout_height="75dp"
android:layout_alignParentBottom="true"
android:layout_toLeftOf="@id/mainPanel"
android:background="#0088FF"
/>
<FrameLayout
android:id="@+id/mainPanel"
android:layout_width="250dp"
android:layout_height="match_parent"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
android:background="#222222"
android:orientation="horizontal">
(Button and spinners here)
</FrameLayout>
</RelativeLayout>
But currently, the video preview appears to be always zoomed to fit the whole texture; its not being stretched, which is good, but its cropped and doesn't reflect the actual aspect ratio of the video.
My app, by the way, is just a modification of this old sample code: https://github.com/googlearchive/android-Camera2Video . I've modified it to let the user select resolution, framerate and exposure settings of the video.
Upvotes: 0
Views: 111
Reputation: 3
Well, I solved my problem, and I'm not exactly sure why this works, but here's what I did:
There was already a configureTransform function in the code I started with :
private void configureTransform(int viewWidth, int viewHeight) {
Activity activity = getActivity();
if (null == mTextureView || null == mPreviewSize || null == activity) {
return;
}
int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
Matrix matrix = new Matrix();
RectF viewRect = new RectF(0, 0, viewWidth, viewHeight);
RectF bufferRect = new RectF(0, 0, mPreviewSize.getHeight(), mPreviewSize.getWidth());
float centerX = viewRect.centerX();
float centerY = viewRect.centerY();
if (Surface.ROTATION_90 == rotation || Surface.ROTATION_270 == rotation) {
bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY());
matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL);
float scale = Math.max(
(float) viewHeight / mPreviewSize.getHeight(),
(float) viewWidth / mPreviewSize.getWidth());
matrix.postScale(scale, scale, centerX, centerY);
matrix.postRotate(90 * (rotation - 2), centerX, centerY);
}
mTextureView.setTransform(matrix);
}
All I did was change the line
float scale = Math.max(
(float) viewHeight / mPreviewSize.getHeight(),
(float) viewWidth / mPreviewSize.getWidth());
to
float scale = Math.min(
(float) viewHeight / mPreviewSize.getHeight(),
(float) viewWidth / mPreviewSize.getWidth());
And in the spinner where the user chooses the resolution (and thus aspect ratio), I now have the lines
mPreviewSize = currentResolution;
configureTransform(mTextureView.getWidth(),mTextureView.getHeight());
startPreview();
I do now get the desired behavior of the video preview letterboxing itself within the texture view.
Upvotes: 0