Skip to content

Commit 52a88e7

Browse files
committed
Fix camera preview aspect ratio
This fixes the aspect ratio of the SurfaceViews used to show the camera preview in the "Show + capture camera" and "Continuous capture" activities.
1 parent a5ae09c commit 52a88e7

File tree

7 files changed

+57
-35
lines changed

7 files changed

+57
-35
lines changed

AndroidManifest.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
1919
package="com.android.grafika"
20-
android:versionCode="29"
20+
android:versionCode="30"
2121
android:versionName="1.0" >
2222

2323
<uses-sdk

README.md

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -64,15 +64,14 @@ Current features
6464
- Name starts with an asterisk so it's at the top of the list of activities.
6565

6666
[Continuous capture](src/com/android/grafika/ContinuousCaptureActivity.java). Stores video in a circular buffer, saving it when you hit the "capture" button. (Formerly "Constant capture".)
67-
- The aspect ratio of the display window does not match the incoming frames, so the
68-
images will appear stretched on screen.
6967
- Currently hard-wired to try to capture 7 seconds of video from the camera at 6MB/sec,
7068
preferrably 15fps 720p. That requires a buffer size of about 5MB.
7169
- The time span of frames currently held in the buffer is displayed. The actual
7270
time span saved when you hit "capture" will be slightly less than what is shown because
7371
we have to start the output on a sync frame, which are configured to appear once per second.
7472
- Output is a video-only MP4 file ("constant-capture.mp4"). Video is always 1280x720, which
75-
usually matches what the camera provides.
73+
usually matches what the camera provides; if it doesn't, the recorded video will have the
74+
wrong aspect ratio.
7675

7776
[Double decode](src/com/android/grafika/DoubleDecodeActivity.java). Decodes two video streams side-by-side to a pair of `TextureViews`.
7877
- Plays the two auto-generated videos. Note they play at different rates.
@@ -136,9 +135,9 @@ Current features
136135
- Recording continues until stopped. If you back out and return, recording will start again,
137136
with a real-time gap. If you try to play the movie while it's recording, you will see
138137
an incomplete file (and probably cause the play movie activity to crash).
139-
- The preview frames are rendered to a `GLSurfaceView`. The aspect ratio will likely appear
140-
stretched -- the View's size isn't adjusted. Generally looks best in landscape. The
141-
recorded video is scaled to 640x480, so it will probably look squished.
138+
- The recorded video is scaled to 640x480, so it will probably look squished. A real app
139+
would either set the recording size equal to the camera input size, or correct the aspect
140+
ratio by letter- or pillar-boxing the frames as they are rendered to the encoder.
142141
- You can select a filter to apply to the preview. It does not get applied to the recording.
143142
The shader used for the filters is not optimized, but seems to perform well on most devices
144143
(the original Nexus 7 (2012) being a notable exception). Demo
@@ -194,8 +193,6 @@ In no particular order.
194193
- Capture audio from microphone, record + mux it.
195194
- Enable preview on front/back cameras simultaneously, display them side-by-side. (This
196195
appears to be impossible except on specific devices.)
197-
- Fix the various aspect ratio problems (camera in/out in "Show + capture" and "Continuous
198-
capture" activities).
199196
- Add a test that renders to two different TextureViews using different EGLContexts
200197
from a single renderer thread.
201198

res/layout/activity_camera_capture.xml

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,22 @@
2424
android:paddingTop="@dimen/activity_vertical_margin"
2525
tools:context=".CameraCaptureActivity" >
2626

27-
<android.opengl.GLSurfaceView
28-
android:id="@+id/cameraPreviewSurface"
29-
android:layout_width="wrap_content"
30-
android:layout_height="wrap_content"
27+
<com.android.grafika.AspectFrameLayout
28+
android:id="@+id/cameraPreview_afl"
29+
android:layout_width="match_parent"
30+
android:layout_height="match_parent"
3131
android:layout_alignLeft="@+id/toggleRecording_button"
3232
android:layout_alignParentBottom="true"
3333
android:layout_alignParentRight="true"
34-
android:layout_below="@+id/toggleRecording_button" />
34+
android:layout_below="@+id/toggleRecording_button"
35+
android:layout_centerInParent="true" >
36+
37+
<android.opengl.GLSurfaceView
38+
android:id="@+id/cameraPreview_surfaceView"
39+
android:layout_width="match_parent"
40+
android:layout_height="match_parent"
41+
android:layout_gravity="center" />
42+
</com.android.grafika.AspectFrameLayout>
3543

3644
<Button
3745
android:id="@+id/toggleRecording_button"
@@ -53,25 +61,25 @@
5361
android:id="@+id/cameraParams_text"
5462
android:layout_width="wrap_content"
5563
android:layout_height="wrap_content"
56-
android:layout_below="@+id/toggleRecording_button"
64+
android:layout_below="@id/toggleRecording_button"
5765
android:text="[?]"
5866
android:textAppearance="?android:attr/textAppearanceMedium" />
5967

6068
<TextView
6169
android:id="@+id/cameraOutputFileLabel"
6270
android:layout_width="wrap_content"
6371
android:layout_height="wrap_content"
64-
android:layout_alignLeft="@+id/cameraParams_text"
65-
android:layout_below="@+id/cameraParams_text"
72+
android:layout_alignLeft="@id/cameraParams_text"
73+
android:layout_below="@id/cameraParams_text"
6674
android:text="@string/cameraOutputFileLabel_text" />
6775

6876
<TextView
6977
android:id="@+id/cameraOutputFile_text"
7078
android:layout_width="wrap_content"
7179
android:layout_height="wrap_content"
72-
android:layout_alignBaseline="@+id/cameraOutputFileLabel"
73-
android:layout_alignBottom="@+id/cameraOutputFileLabel"
74-
android:layout_toRightOf="@+id/cameraOutputFileLabel"
80+
android:layout_alignBaseline="@id/cameraOutputFileLabel"
81+
android:layout_alignBottom="@id/cameraOutputFileLabel"
82+
android:layout_toRightOf="@id/cameraOutputFileLabel"
7583
android:paddingLeft="4dp"
7684
android:text="@string/cameraOutputFile_text" />
7785

res/layout/activity_continuous_capture.xml

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,26 +21,35 @@
2121
android:id="@+id/capturedVideoDesc_text"
2222
android:layout_width="wrap_content"
2323
android:layout_height="wrap_content"
24-
android:layout_alignBaseline="@+id/capture_button"
25-
android:layout_alignBottom="@+id/capture_button"
26-
android:layout_toRightOf="@+id/capture_button"
24+
android:layout_alignBaseline="@id/capture_button"
25+
android:layout_alignBottom="@id/capture_button"
26+
android:layout_toRightOf="@id/capture_button"
2727
android:text="@string/secondsOfVideo" />
2828

29-
<SurfaceView
30-
android:id="@+id/continuousCapture_surfaceView"
31-
android:layout_width="wrap_content"
32-
android:layout_height="wrap_content"
29+
<com.android.grafika.AspectFrameLayout
30+
android:id="@+id/continuousCapture_afl"
31+
android:layout_width="match_parent"
32+
android:layout_height="match_parent"
3333
android:layout_alignParentBottom="true"
3434
android:layout_alignParentLeft="true"
3535
android:layout_alignParentRight="true"
36-
android:layout_below="@+id/capture_button" />
36+
android:layout_below="@id/capture_button"
37+
android:layout_centerInParent="true" >
38+
39+
<SurfaceView
40+
android:id="@+id/continuousCapture_surfaceView"
41+
android:layout_width="match_parent"
42+
android:layout_height="match_parent"
43+
android:layout_gravity="center" />
44+
45+
</com.android.grafika.AspectFrameLayout>
3746

3847
<TextView
3948
android:id="@+id/recording_text"
4049
android:layout_width="wrap_content"
4150
android:layout_height="wrap_content"
42-
android:layout_alignLeft="@+id/continuousCapture_surfaceView"
43-
android:layout_alignTop="@+id/continuousCapture_surfaceView"
51+
android:layout_alignLeft="@id/continuousCapture_afl"
52+
android:layout_alignTop="@id/continuousCapture_afl"
4453
android:text="@string/nowRecording"
4554
android:textColor="#f00"
4655
android:textAppearance="?android:attr/textAppearanceLarge" />

res/layout/activity_play_movie_surface.xml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,14 @@
3737
android:id="@+id/playMovieFile_spinner"
3838
android:layout_width="wrap_content"
3939
android:layout_height="wrap_content"
40-
android:layout_alignTop="@+id/play_stop_button"
41-
android:layout_toRightOf="@+id/play_stop_button" />
40+
android:layout_alignTop="@id/play_stop_button"
41+
android:layout_toRightOf="@id/play_stop_button" />
4242

4343
<com.android.grafika.AspectFrameLayout
4444
android:id="@+id/playMovie_afl"
4545
android:layout_width="match_parent"
4646
android:layout_height="match_parent"
47-
android:layout_below="@+id/play_stop_button"
47+
android:layout_below="@id/play_stop_button"
4848
android:layout_centerInParent="true" >
4949

5050
<SurfaceView

src/com/android/grafika/CameraCaptureActivity.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ protected void onCreate(Bundle savedInstanceState) {
168168

169169
// Configure the GLSurfaceView. This will start the Renderer thread, with an
170170
// appropriate EGL context.
171-
mGLView = (GLSurfaceView) findViewById(R.id.cameraPreviewSurface);
171+
mGLView = (GLSurfaceView) findViewById(R.id.cameraPreview_surfaceView);
172172
mGLView.setEGLContextClientVersion(2); // select GLES 2.0
173173
mRenderer = new CameraSurfaceRenderer(mCameraHandler, sVideoEncoder, outputFile);
174174
mGLView.setRenderer(mRenderer);
@@ -182,8 +182,12 @@ protected void onResume() {
182182
Log.d(TAG, "onResume -- acquiring camera");
183183
super.onResume();
184184
updateControls();
185-
//openCamera(640, 480); // updates mCameraPreviewWidth/Height
186185
openCamera(1280, 720); // updates mCameraPreviewWidth/Height
186+
187+
// Set the preview aspect ratio.
188+
AspectFrameLayout layout = (AspectFrameLayout) findViewById(R.id.cameraPreview_afl);
189+
layout.setAspectRatio((double) mCameraPreviewWidth / mCameraPreviewHeight);
190+
187191
mGLView.onResume();
188192
mGLView.queueEvent(new Runnable() {
189193
@Override public void run() {

src/com/android/grafika/ContinuousCaptureActivity.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,10 @@ private void openCamera(int desiredWidth, int desiredHeight, int desiredFps) {
260260
String previewFacts = mCameraPreviewSize.width + "x" + mCameraPreviewSize.height +
261261
" @" + (mCameraPreviewThousandFps / 1000.0f) + "fps";
262262
Log.i(TAG, "Camera config: " + previewFacts);
263+
264+
// Set the preview aspect ratio.
265+
AspectFrameLayout layout = (AspectFrameLayout) findViewById(R.id.continuousCapture_afl);
266+
layout.setAspectRatio((double) mCameraPreviewSize.width / mCameraPreviewSize.height);
263267
}
264268

265269
/**

0 commit comments

Comments
 (0)