MediaRecorderStressTest.java revision eb4f3256b77fe7fd783297a550a64ea441c41169
1/*
2 * Copyright (C) 2009 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.android.mediaframeworktest.stress;
18
19
20import com.android.mediaframeworktest.MediaFrameworkTest;
21
22import java.io.BufferedWriter;
23import java.io.File;
24import java.io.FileWriter;
25import java.io.IOException;
26import java.io.Writer;
27import java.util.concurrent.Semaphore;
28import java.util.concurrent.TimeUnit;
29
30import android.hardware.Camera;
31import android.media.CamcorderProfile;
32import android.media.MediaPlayer;
33import android.media.MediaRecorder;
34import android.os.Handler;
35import android.os.Looper;
36import android.test.ActivityInstrumentationTestCase2;
37import android.test.suitebuilder.annotation.LargeTest;
38import android.util.Log;
39import android.view.SurfaceHolder;
40import com.android.mediaframeworktest.MediaRecorderStressTestRunner;
41
42/**
43 * Junit / Instrumentation test case for the media player api
44 */
45public class MediaRecorderStressTest extends ActivityInstrumentationTestCase2<MediaFrameworkTest> {
46
47    private String TAG = "MediaRecorderStressTest";
48    private MediaRecorder mRecorder;
49    private Camera mCamera;
50
51    private static final int NUMBER_OF_CAMERA_STRESS_LOOPS = 100;
52    private static final int NUMBER_OF_RECORDER_STRESS_LOOPS = 100;
53    private static final int NUMBER_OF_RECORDERANDPLAY_STRESS_LOOPS = 50;
54    private static final int NUMBER_OF_SWTICHING_LOOPS_BW_CAMERA_AND_RECORDER = 200;
55    private static final int NUMBER_OF_TIME_LAPSE_LOOPS = 25;
56    private static final int TIME_LAPSE_PLAYBACK_WAIT_TIME = 5* 1000; // 5 seconds
57    private static final long WAIT_TIME_CAMERA_TEST = 3 * 1000; // 3 seconds
58    private static final long WAIT_TIME_RECORDER_TEST = 6 * 1000; // 6 seconds
59    private static final String OUTPUT_FILE = "/sdcard/temp";
60    private static final String OUTPUT_FILE_EXT = ".3gp";
61    private static final String MEDIA_STRESS_OUTPUT =
62        "/sdcard/mediaStressOutput.txt";
63    private final CameraErrorCallback mCameraErrorCallback = new CameraErrorCallback();
64    private final RecorderErrorCallback mRecorderErrorCallback = new RecorderErrorCallback();
65
66    private final static int WAIT_TIMEOUT = 10 * 1000; // 10 seconds
67    private Thread mLooperThread;
68    private Handler mHandler;
69
70    public MediaRecorderStressTest() {
71        super("com.android.mediaframeworktest", MediaFrameworkTest.class);
72    }
73
74    protected void setUp() throws Exception {
75        final Semaphore sem = new Semaphore(0);
76        mLooperThread = new Thread() {
77            @Override
78            public void run() {
79                Log.v(TAG, "starting looper");
80                Looper.prepare();
81                mHandler = new Handler();
82                sem.release();
83                Looper.loop();
84                Log.v(TAG, "quit looper");
85            }
86        };
87        mLooperThread.start();
88        if (! sem.tryAcquire(WAIT_TIMEOUT, TimeUnit.MILLISECONDS)) {
89            fail("Failed to start the looper.");
90        }
91
92        getActivity();
93        super.setUp();
94    }
95
96    @Override
97    protected void tearDown() throws Exception {
98        if (mHandler != null) {
99            mHandler.getLooper().quit();
100            mHandler = null;
101        }
102        if (mLooperThread != null) {
103            mLooperThread.join(WAIT_TIMEOUT);
104            if (mLooperThread.isAlive()) {
105                fail("Failed to stop the looper.");
106            }
107            mLooperThread = null;
108        }
109
110        super.tearDown();
111    }
112
113    private void runOnLooper(final Runnable command) throws InterruptedException {
114        final Semaphore sem = new Semaphore(0);
115        mHandler.post(new Runnable() {
116            @Override
117            public void run() {
118                try {
119                    command.run();
120                } finally {
121                    sem.release();
122                }
123            }
124        });
125        if (! sem.tryAcquire(WAIT_TIMEOUT, TimeUnit.MILLISECONDS)) {
126            fail("Failed to run the command on the looper.");
127        }
128    }
129
130    private final class CameraErrorCallback implements android.hardware.Camera.ErrorCallback {
131        public void onError(int error, android.hardware.Camera camera) {
132            if (error == android.hardware.Camera.CAMERA_ERROR_SERVER_DIED) {
133                assertTrue("Camera test mediaserver died", false);
134            }
135        }
136    }
137
138    private final class RecorderErrorCallback implements MediaRecorder.OnErrorListener {
139        public void onError(MediaRecorder mr, int what, int extra) {
140            // fail the test case no matter what error come up
141            assertTrue("mediaRecorder error", false);
142        }
143    }
144
145    //Test case for stressing the camera preview.
146    @LargeTest
147    public void testStressCamera() throws Exception {
148        SurfaceHolder mSurfaceHolder;
149        mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
150        File stressOutFile = new File(MEDIA_STRESS_OUTPUT);
151        Writer output = new BufferedWriter(new FileWriter(stressOutFile, true));
152        output.write("Camera start preview stress:\n");
153        output.write("Total number of loops:" +
154                NUMBER_OF_CAMERA_STRESS_LOOPS + "\n");
155        try {
156            Log.v(TAG, "Start preview");
157            output.write("No of loop: ");
158
159            for (int i = 0; i< NUMBER_OF_CAMERA_STRESS_LOOPS; i++) {
160                runOnLooper(new Runnable() {
161                    @Override
162                    public void run() {
163                        mCamera = Camera.open();
164                    }
165                });
166                mCamera.setErrorCallback(mCameraErrorCallback);
167                mCamera.setPreviewDisplay(mSurfaceHolder);
168                mCamera.startPreview();
169                Thread.sleep(WAIT_TIME_CAMERA_TEST);
170                mCamera.stopPreview();
171                mCamera.release();
172                output.write(" ," + i);
173            }
174        } catch (Exception e) {
175            assertTrue("CameraStressTest", false);
176            Log.v(TAG, e.toString());
177        }
178        output.write("\n\n");
179        output.close();
180    }
181
182    //Test case for stressing the camera preview.
183    @LargeTest
184    public void testStressRecorder() throws Exception {
185        String filename;
186        SurfaceHolder mSurfaceHolder;
187        mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
188        File stressOutFile = new File(MEDIA_STRESS_OUTPUT);
189        Writer output = new BufferedWriter(new FileWriter(stressOutFile, true));
190        output.write("H263 video record- reset after prepare Stress test\n");
191        output.write("Total number of loops:" +
192                NUMBER_OF_RECORDER_STRESS_LOOPS + "\n");
193        try {
194            output.write("No of loop: ");
195            Log.v(TAG, "Start preview");
196            for (int i = 0; i < NUMBER_OF_RECORDER_STRESS_LOOPS; i++) {
197                runOnLooper(new Runnable() {
198                    @Override
199                    public void run() {
200                        mRecorder = new MediaRecorder();
201                    }
202                });
203                Log.v(TAG, "counter = " + i);
204                filename = OUTPUT_FILE + i + OUTPUT_FILE_EXT;
205                Log.v(TAG, filename);
206                mRecorder.setOnErrorListener(mRecorderErrorCallback);
207                mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
208                mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
209                mRecorder.setOutputFile(filename);
210                mRecorder.setVideoFrameRate(MediaRecorderStressTestRunner.mFrameRate);
211                mRecorder.setVideoSize(176,144);
212                Log.v(TAG, "setEncoder");
213                mRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H263);
214                mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
215                Log.v(TAG, "setPreview");
216                mRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
217                Log.v(TAG, "prepare");
218                mRecorder.prepare();
219                Log.v(TAG, "before release");
220                Thread.sleep(WAIT_TIME_RECORDER_TEST);
221                mRecorder.reset();
222                mRecorder.release();
223                output.write(", " + i);
224            }
225        } catch (Exception e) {
226            assertTrue("Recorder Stress test", false);
227            Log.v(TAG, e.toString());
228        }
229        output.write("\n\n");
230        output.close();
231    }
232
233    //Stress test case for switching camera and video recorder preview.
234    @LargeTest
235    public void testStressCameraSwitchRecorder() throws Exception {
236        String filename;
237        SurfaceHolder mSurfaceHolder;
238        mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
239        File stressOutFile = new File(MEDIA_STRESS_OUTPUT);
240        Writer output = new BufferedWriter(new FileWriter(stressOutFile, true));
241        output.write("Camera and video recorder preview switching\n");
242        output.write("Total number of loops:"
243                + NUMBER_OF_SWTICHING_LOOPS_BW_CAMERA_AND_RECORDER + "\n");
244        try {
245            Log.v(TAG, "Start preview");
246            output.write("No of loop: ");
247            for (int i = 0; i < NUMBER_OF_SWTICHING_LOOPS_BW_CAMERA_AND_RECORDER; i++) {
248                runOnLooper(new Runnable() {
249                    @Override
250                    public void run() {
251                        mCamera = Camera.open();
252                    }
253                });
254                mCamera.setErrorCallback(mCameraErrorCallback);
255                mCamera.setPreviewDisplay(mSurfaceHolder);
256                mCamera.startPreview();
257                Thread.sleep(WAIT_TIME_CAMERA_TEST);
258                mCamera.stopPreview();
259                mCamera.release();
260                mCamera = null;
261                Log.v(TAG, "release camera");
262                filename = OUTPUT_FILE + i + OUTPUT_FILE_EXT;
263                Log.v(TAG, filename);
264                runOnLooper(new Runnable() {
265                    @Override
266                    public void run() {
267                        mRecorder = new MediaRecorder();
268                    }
269                });
270                mRecorder.setOnErrorListener(mRecorderErrorCallback);
271                mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
272                mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
273                mRecorder.setOutputFile(filename);
274                mRecorder.setVideoFrameRate(MediaRecorderStressTestRunner.mFrameRate);
275                mRecorder.setVideoSize(176,144);
276                Log.v(TAG, "Media recorder setEncoder");
277                mRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H263);
278                Log.v(TAG, "mediaRecorder setPreview");
279                mRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
280                Log.v(TAG, "prepare");
281                mRecorder.prepare();
282                Log.v(TAG, "before release");
283                Thread.sleep(WAIT_TIME_CAMERA_TEST);
284                mRecorder.release();
285                Log.v(TAG, "release video recorder");
286                output.write(", " + i);
287            }
288        } catch (Exception e) {
289            assertTrue("Camer and recorder switch mode", false);
290                Log.v(TAG, e.toString());
291        }
292        output.write("\n\n");
293        output.close();
294    }
295
296    public void validateRecordedVideo(String recorded_file) {
297        try {
298            MediaPlayer mp = new MediaPlayer();
299            mp.setDataSource(recorded_file);
300            mp.prepare();
301            int duration = mp.getDuration();
302            if (duration <= 0){
303                assertTrue("stressRecordAndPlayback", false);
304            }
305            mp.release();
306        } catch (Exception e) {
307            assertTrue("stressRecordAndPlayback", false);
308        }
309    }
310
311    public void removeRecordedVideo(String filename){
312        File video = new File(filename);
313        Log.v(TAG, "remove recorded video " + filename);
314        video.delete();
315    }
316
317    //Stress test case for record a video and play right away.
318    @LargeTest
319    public void testStressRecordVideoAndPlayback() throws Exception {
320        int iterations = MediaRecorderStressTestRunner.mIterations;
321        int video_encoder = MediaRecorderStressTestRunner.mVideoEncoder;
322        int audio_encoder = MediaRecorderStressTestRunner.mAudioEncdoer;
323        int frame_rate = MediaRecorderStressTestRunner.mFrameRate;
324        int video_width = MediaRecorderStressTestRunner.mVideoWidth;
325        int video_height = MediaRecorderStressTestRunner.mVideoHeight;
326        int bit_rate = MediaRecorderStressTestRunner.mBitRate;
327        boolean remove_video = MediaRecorderStressTestRunner.mRemoveVideo;
328        int record_duration = MediaRecorderStressTestRunner.mDuration;
329
330        String filename;
331        SurfaceHolder mSurfaceHolder;
332        mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
333        File stressOutFile = new File(MEDIA_STRESS_OUTPUT);
334        Writer output = new BufferedWriter(
335                new FileWriter(stressOutFile, true));
336        output.write("Video record and play back stress test:\n");
337        output.write("Total number of loops:"
338                + NUMBER_OF_RECORDERANDPLAY_STRESS_LOOPS + "\n");
339        try {
340            output.write("No of loop: ");
341            for (int i = 0; i < iterations; i++){
342                filename = OUTPUT_FILE + i + OUTPUT_FILE_EXT;
343                Log.v(TAG, filename);
344                runOnLooper(new Runnable() {
345                    @Override
346                    public void run() {
347                        mRecorder = new MediaRecorder();
348                    }
349                });
350                Log.v(TAG, "iterations : " + iterations);
351                Log.v(TAG, "video_encoder : " + video_encoder);
352                Log.v(TAG, "audio_encoder : " + audio_encoder);
353                Log.v(TAG, "frame_rate : " + frame_rate);
354                Log.v(TAG, "video_width : " + video_width);
355                Log.v(TAG, "video_height : " + video_height);
356                Log.v(TAG, "bit rate : " + bit_rate);
357                Log.v(TAG, "record_duration : " + record_duration);
358
359                mRecorder.setOnErrorListener(mRecorderErrorCallback);
360                mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
361                mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
362                mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
363                mRecorder.setOutputFile(filename);
364                mRecorder.setVideoFrameRate(frame_rate);
365                mRecorder.setVideoSize(video_width, video_height);
366                mRecorder.setVideoEncoder(video_encoder);
367                mRecorder.setAudioEncoder(audio_encoder);
368                mRecorder.setVideoEncodingBitRate(bit_rate);
369                Log.v(TAG, "mediaRecorder setPreview");
370                mRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
371                mRecorder.prepare();
372                mRecorder.start();
373                Thread.sleep(record_duration);
374                Log.v(TAG, "Before stop");
375                mRecorder.stop();
376                mRecorder.release();
377                //start the playback
378                MediaPlayer mp = new MediaPlayer();
379                mp.setDataSource(filename);
380                mp.setDisplay(MediaFrameworkTest.mSurfaceView.getHolder());
381                mp.prepare();
382                mp.start();
383                Thread.sleep(record_duration);
384                mp.release();
385                validateRecordedVideo(filename);
386                if (remove_video) {
387                    removeRecordedVideo(filename);
388                }
389                output.write(", " + i);
390            }
391        } catch (Exception e) {
392            Log.v(TAG, e.toString());
393            assertTrue("record and playback", false);
394        }
395        output.write("\n\n");
396        output.close();
397    }
398
399    // Test case for stressing time lapse
400    @LargeTest
401    public void testStressTimeLapse() throws Exception {
402        SurfaceHolder mSurfaceHolder;
403        mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
404        int record_duration = MediaRecorderStressTestRunner.mTimeLapseDuration;
405        boolean remove_video = MediaRecorderStressTestRunner.mRemoveVideo;
406        double captureRate = MediaRecorderStressTestRunner.mCaptureRate;
407        String filename;
408        File stressOutFile = new File(MEDIA_STRESS_OUTPUT);
409        Writer output = new BufferedWriter(new FileWriter(stressOutFile, true));
410        output.write("Start camera time lapse stress:\n");
411        output.write("Total number of loops: " + NUMBER_OF_TIME_LAPSE_LOOPS + "\n");
412
413        try {
414            output.write("No of loop: ");
415            for (int i = 0; i < NUMBER_OF_TIME_LAPSE_LOOPS; i++) {
416                filename = OUTPUT_FILE + i + OUTPUT_FILE_EXT;
417                Log.v(TAG, filename);
418                runOnLooper(new Runnable() {
419                    @Override
420                    public void run() {
421                        mRecorder = new MediaRecorder();
422                    }
423                });
424
425                // Set callback
426                mRecorder.setOnErrorListener(mRecorderErrorCallback);
427
428                // Set video source
429                mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
430
431                // Set camcorder profile for time lapse
432                CamcorderProfile profile =
433                        CamcorderProfile.get(CamcorderProfile.QUALITY_TIME_LAPSE_HIGH);
434                mRecorder.setProfile(profile);
435
436                // Set the timelapse setting; 0.1 = 10 sec timelapse, 0.5 = 2 sec timelapse, etc.
437                // http://developer.android.com/guide/topics/media/camera.html#time-lapse-video
438                mRecorder.setCaptureRate(captureRate);
439
440                // Set output file
441                mRecorder.setOutputFile(filename);
442
443                // Set the preview display
444                Log.v(TAG, "mediaRecorder setPreviewDisplay");
445                mRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
446
447                mRecorder.prepare();
448                mRecorder.start();
449                Thread.sleep(record_duration);
450                Log.v(TAG, "Before stop");
451                mRecorder.stop();
452                mRecorder.release();
453
454                // Start the playback
455                MediaPlayer mp = new MediaPlayer();
456                mp.setDataSource(filename);
457                mp.setDisplay(mSurfaceHolder);
458                mp.prepare();
459                mp.start();
460                Thread.sleep(TIME_LAPSE_PLAYBACK_WAIT_TIME);
461                mp.release();
462                validateRecordedVideo(filename);
463                if(remove_video) {
464                  removeRecordedVideo(filename);
465                }
466                output.write(", " + i);
467            }
468        }
469        catch (IllegalStateException e) {
470            assertTrue("Camera time lapse stress test IllegalStateException", false);
471            Log.v(TAG, e.toString());
472        }
473        catch (IOException e) {
474            assertTrue("Camera time lapse stress test IOException", false);
475            Log.v(TAG, e.toString());
476        }
477        catch (Exception e) {
478            assertTrue("Camera time lapse stress test Exception", false);
479            Log.v(TAG, e.toString());
480        }
481        output.write("\n\n");
482        output.close();
483    }
484}
485