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