VideoChatTestActivity.java revision 148fb32e83b51415b3e27b1963da01368e2c742f
1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.example.android.videochatcameratest;
18
19import android.app.Activity;
20import android.graphics.ImageFormat;
21import android.hardware.Camera;
22import android.hardware.Camera.Size;
23import android.os.AsyncTask;
24import android.os.Bundle;
25import android.util.Log;
26import android.view.View;
27import android.view.View.OnClickListener;
28import android.widget.Button;
29import android.widget.CheckBox;
30import android.widget.TextView;
31
32import java.io.IOException;
33import java.util.ArrayList;
34import java.util.List;
35
36/**
37 * This class provides a basic demonstration of how to write an Android
38 * activity. Inside of its window, it places a single view: an EditText that
39 * displays and edits some internal text.
40 */
41public class VideoChatTestActivity extends Activity {
42
43    static final private int NUM_CAMERA_PREVIEW_BUFFERS = 2;
44
45    static final private String TAG = "VideoChatTest";
46
47    public VideoChatTestActivity() {
48    }
49
50    /** Called with the activity is first created. */
51    @Override
52    public void onCreate(Bundle savedInstanceState) {
53        super.onCreate(savedInstanceState);
54
55        // Inflate our UI from its XML layout description.
56        setContentView(R.layout.videochatcameratest_activity);
57
58        ((Button) findViewById(R.id.gobutton)).setOnClickListener(mGoListener);
59
60        ((TextView)findViewById(R.id.statushistory)).setVerticalScrollBarEnabled(true);
61
62//        // Find the text editor view inside the layout, because we
63//        // want to do various programmatic things with it.
64//        mEditor = (EditText) findViewById(R.id.editor);
65//
66//        // Hook up button presses to the appropriate event handler.
67//        ((Button) findViewById(R.id.back)).setOnClickListener(mBackListener);
68//        ((Button) findViewById(R.id.clear)).setOnClickListener(mClearListener);
69//
70//        mEditor.setText(getText(R.string.main_label));
71    }
72
73    /**
74     * Called when the activity is about to start interacting with the user.
75     */
76    @Override
77    protected void onResume() {
78        super.onResume();
79    }
80
81    /**
82     * A call-back for when the user presses the back button.
83     */
84    OnClickListener mGoListener = new OnClickListener() {
85
86        public void onClick(View v) {
87            new CameraTestRunner().execute();
88        }
89    };
90
91    private class CameraTestRunner extends AsyncTask<Void, String, Void> {
92
93        TextView mTextStatus;
94        TextView mTextStatusHistory;
95
96        @Override
97        protected Void doInBackground(Void... params) {
98            mTextStatus = (TextView) findViewById(R.id.status);
99            mTextStatusHistory = (TextView) findViewById(R.id.statushistory);
100            boolean testFrontCamera =
101                    ((CheckBox) findViewById(R.id.frontcameracheckbox)).isChecked();
102            boolean testBackCamera = ((CheckBox) findViewById(R.id.backcameracheckbox)).isChecked();
103            boolean testQVGA = ((CheckBox) findViewById(R.id.qvgacheckbox)).isChecked();
104            boolean testVGA = ((CheckBox) findViewById(R.id.vgacheckbox)).isChecked();
105            boolean test15fps = ((CheckBox) findViewById(R.id.fps15checkbox)).isChecked();
106            boolean test30fps = ((CheckBox) findViewById(R.id.fps30checkbox)).isChecked();
107            boolean testRotate0 = ((CheckBox) findViewById(R.id.rotate0checkbox)).isChecked();
108            boolean testRotate90 = ((CheckBox) findViewById(R.id.rotate90checkbox)).isChecked();
109            boolean testRotate180 = ((CheckBox) findViewById(R.id.rotate180checkbox)).isChecked();
110            boolean testRotate270 = ((CheckBox) findViewById(R.id.rotate270checkbox)).isChecked();
111
112            ArrayList<Integer> setDisplayOrentationAngles = new ArrayList<Integer>();
113
114            if (testRotate0) {
115                setDisplayOrentationAngles.add(0);
116            }
117            if (testRotate90) {
118                setDisplayOrentationAngles.add(90);
119            }
120            if (testRotate180) {
121                setDisplayOrentationAngles.add(180);
122            }
123            if (testRotate270) {
124                setDisplayOrentationAngles.add(270);
125            }
126
127            final int widths[] = new int[] {320, 640};
128            final int heights[] = new int[] {240, 480};
129
130            final int framerates[] = new int[] {15, 30};
131
132            do {
133                for (int whichCamera = 0; whichCamera < 2; whichCamera++) {
134                    if (whichCamera == 0 && !testBackCamera) {
135                        continue;
136                    }
137
138
139                    if (whichCamera == 1 && !testFrontCamera) {
140                        continue;
141                    }
142
143                    for (int whichResolution = 0; whichResolution < 2; whichResolution++) {
144                        if (whichResolution == 0 && !testQVGA) {
145                            continue;
146                        }
147                        if (whichResolution == 1 && !testVGA) {
148                            continue;
149                        }
150
151                        for (int whichFramerate = 0; whichFramerate < 2; whichFramerate++) {
152                            if (whichFramerate == 0 && !test15fps) {
153                                continue;
154                            }
155                            if (whichFramerate == 1 && !test30fps) {
156                                continue;
157                            }
158
159                            TestCamera(whichCamera, widths[whichResolution],
160                                    heights[whichResolution], framerates[whichFramerate],
161                                    setDisplayOrentationAngles);
162                        }
163                    }
164                }
165            } while (((CheckBox) findViewById(R.id.repeatcheckbox)).isChecked());
166            // start tests
167
168            return null;
169        }
170
171        @Override
172        protected void onPostExecute(Void result) {
173            final String allDoneString = "Test complete";
174            Log.v(TAG, allDoneString);
175            mTextStatus.setText(allDoneString);
176            mTextStatusHistory.append(allDoneString + "\r\n");
177        }
178
179
180        private class FrameCatcher implements Camera.PreviewCallback {
181            public int mFrames = 0;
182
183            public FrameCatcher(int width, int height) {
184            }
185
186            @Override
187            public void onPreviewFrame(byte[] data, Camera camera) {
188                mFrames++;
189                camera.addCallbackBuffer(data);
190            }
191
192        }
193
194        private void setupCallback(Camera camera, FrameCatcher catcher, int bufferSize) {
195            camera.setPreviewCallbackWithBuffer(null);
196            camera.setPreviewCallbackWithBuffer(catcher);
197            for (int i = 0; i < NUM_CAMERA_PREVIEW_BUFFERS; i++) {
198                byte [] cameraBuffer = new byte[bufferSize];
199                camera.addCallbackBuffer(cameraBuffer);
200            }
201        }
202        protected void TestCamera(int whichCamera,
203                int width, int height,
204                int frameRate,
205                List<Integer> setDisplayOrentationAngles) {
206            String baseStatus = "Camera id " + whichCamera + " " +
207                width + "x" + height + " " +
208                frameRate + "fps";
209            publishProgress("Initializing " + baseStatus);
210            String status = "";
211            boolean succeeded = true;
212            Log.v(TAG, "Start test -- id " + whichCamera + " " + width + "x" + height +
213                    " " + frameRate + "fps");
214            Camera camera;
215            CameraPreviewView previewView = (CameraPreviewView)findViewById(R.id.previewrender);
216
217            camera = Camera.open(whichCamera);
218            publishProgress("Opened " + baseStatus);
219            try {
220                try {
221                    camera.setPreviewDisplay(previewView.mHolder);
222                } catch (IOException exception) {
223                    succeeded = false;
224                    status = exception.toString();
225                    return;
226                }
227                camera.startPreview();
228
229                camera.setPreviewCallbackWithBuffer(null);
230                Camera.Parameters parameters = camera.getParameters();
231
232                publishProgress("Changing preview parameters " + baseStatus);
233
234                parameters.setPreviewSize(width, height);
235                parameters.setPreviewFormat(ImageFormat.NV21);
236
237                parameters.setPreviewFrameRate(frameRate);
238                camera.stopPreview();
239                camera.setParameters(parameters);
240                camera.startPreview();
241
242                publishProgress("Validating preview parameters " + baseStatus);
243
244                parameters = camera.getParameters();
245                Size setSize = parameters.getPreviewSize();
246                if (setSize.width != width || setSize.height != height) {
247                    status += "Bad reported size, wanted " + width + "x" + height + ", got " +
248                    setSize.width + "x" + setSize.height;
249                    succeeded = false;
250                }
251
252                if (parameters.getPreviewFrameRate() != frameRate) {
253                    status += "Bad reported frame rate, wanted " + frameRate
254                    + ", got " + parameters.getPreviewFrameRate();
255                    succeeded = false;
256                }
257
258                publishProgress("Initializing callback buffers " + baseStatus);
259                int imageFormat = parameters.getPreviewFormat();
260                int bufferSize;
261                bufferSize = setSize.width * setSize.height
262                                * ImageFormat.getBitsPerPixel(imageFormat) / 8;
263
264                camera.stopPreview();
265
266                FrameCatcher catcher = new FrameCatcher(setSize.width, setSize.height);
267
268                if (succeeded) {
269                    publishProgress("Starting " + baseStatus);
270                } else {
271                    publishProgress("Starting " + baseStatus + " -- but " + status);
272                }
273
274                int numPasses;
275                boolean doSetDisplayOrientation;
276                if (setDisplayOrentationAngles == null || setDisplayOrentationAngles.size() == 0) {
277                    numPasses = 1;
278                    doSetDisplayOrientation = false;
279                } else {
280                    numPasses = setDisplayOrentationAngles.size();
281                    doSetDisplayOrientation = true;
282                }
283
284                for (int i = 0; i < numPasses; i++) {
285                    if (doSetDisplayOrientation) {
286                        int rotation = setDisplayOrentationAngles.get(i);
287                        publishProgress("setDisplayOrientation to " + rotation);
288                        try {
289                            camera.setDisplayOrientation(rotation);
290                        } catch (RuntimeException exception) {
291                            succeeded = false;
292                            status = exception.toString();
293                            return;
294                        }
295                    }
296                    setupCallback(camera, catcher, bufferSize);
297                    camera.startPreview();
298                    try {
299                        Thread.sleep(5000);
300                    } catch (InterruptedException exception) {
301                        succeeded = false;
302                        status = exception.toString();
303                        return;
304                    }
305                    camera.setPreviewCallbackWithBuffer(null);
306                    camera.stopPreview();
307                }
308
309                if (catcher.mFrames == 0) {
310                    succeeded = false;
311                    publishProgress("Preview callback received no frames from " + baseStatus);
312                } else {
313                    publishProgress("Preview callback got " + catcher.mFrames + " frames (~" +
314                            Math.round(((double)catcher.mFrames)/(5.0 * numPasses)) + "fps) " +
315                            baseStatus);
316                }
317                try {
318                    camera.setPreviewDisplay(null);
319                } catch (IOException exception) {
320                    succeeded = false;
321                    status = exception.toString();
322                    return;
323                }
324            } finally {
325                Log.v(TAG, "Releasing camera");
326
327                if (succeeded) {
328                    publishProgress("Success " + baseStatus);
329                } else {
330                    publishProgress("Finished " + baseStatus + " -- but " + status);
331                }
332
333                camera.release();
334            }
335        }
336
337        @Override
338        protected void onProgressUpdate(String... message) {
339            Log.v(TAG, message[0]);
340            mTextStatus.setText(message[0]);
341            mTextStatusHistory.append(message[0] + "\r\n");
342        }
343    }
344}
345