19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2009 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage com.android.mediaframeworktest.stress;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1920a6b955fe4ea5ba4025f16ba2da013df176c035Yu Shan Emily Lau
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.mediaframeworktest.MediaFrameworkTest;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
22f16da13585ac22bb8d8fe7538509c2726bb06f29Yu Shan Emily Lauimport java.io.BufferedWriter;
23f16da13585ac22bb8d8fe7538509c2726bb06f29Yu Shan Emily Lauimport java.io.File;
24f16da13585ac22bb8d8fe7538509c2726bb06f29Yu Shan Emily Lauimport java.io.FileWriter;
2527c8d9ba169aa85127fac65d6df25e4335ee2fcaJason Noguchiimport java.io.IOException;
26f16da13585ac22bb8d8fe7538509c2726bb06f29Yu Shan Emily Lauimport java.io.Writer;
2779a3981e3885b9144bb3d458682141eed7365939Jeff Brownimport java.util.concurrent.Semaphore;
2879a3981e3885b9144bb3d458682141eed7365939Jeff Brownimport java.util.concurrent.TimeUnit;
29f16da13585ac22bb8d8fe7538509c2726bb06f29Yu Shan Emily Lau
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.hardware.Camera;
3127c8d9ba169aa85127fac65d6df25e4335ee2fcaJason Noguchiimport android.media.CamcorderProfile;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.media.MediaPlayer;
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.media.MediaRecorder;
34ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchiimport android.os.Environment;
3579a3981e3885b9144bb3d458682141eed7365939Jeff Brownimport android.os.Handler;
3620a6b955fe4ea5ba4025f16ba2da013df176c035Yu Shan Emily Lauimport android.os.Looper;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.test.ActivityInstrumentationTestCase2;
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.test.suitebuilder.annotation.LargeTest;
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.SurfaceHolder;
4148584d7b8f5e56b73bb13180bf6546b2647c1b28Yu Shan Emily Lauimport com.android.mediaframeworktest.MediaRecorderStressTestRunner;
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Junit / Instrumentation test case for the media player api
4527c8d9ba169aa85127fac65d6df25e4335ee2fcaJason Noguchi */
4627c8d9ba169aa85127fac65d6df25e4335ee2fcaJason Noguchipublic class MediaRecorderStressTest extends ActivityInstrumentationTestCase2<MediaFrameworkTest> {
4727c8d9ba169aa85127fac65d6df25e4335ee2fcaJason Noguchi
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private String TAG = "MediaRecorderStressTest";
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private MediaRecorder mRecorder;
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Camera mCamera;
5127c8d9ba169aa85127fac65d6df25e4335ee2fcaJason Noguchi
52ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi    private static final int CAMERA_ID = 0;
53984505d8168713469fb36bb50da50a2638751122Yu Shan Emily Lau    private static final int NUMBER_OF_TIME_LAPSE_LOOPS = 1;
54984505d8168713469fb36bb50da50a2638751122Yu Shan Emily Lau    private static final int TIME_LAPSE_PLAYBACK_WAIT_TIME = 30 * 1000; // 30 seconds
55ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi    private static final int USE_TEST_RUNNER_PROFILE = -1;
56ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi    private static final long WAIT_TIMEOUT = 10 * 1000; // 10 seconds
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String OUTPUT_FILE_EXT = ".3gp";
58ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi    private static final String MEDIA_STRESS_OUTPUT = "mediaStressOutput.txt";
59e35b3e052dab756113304cb394980e9f271b1613Yu Shan Emily Lau
6020a6b955fe4ea5ba4025f16ba2da013df176c035Yu Shan Emily Lau    private final CameraErrorCallback mCameraErrorCallback = new CameraErrorCallback();
6120a6b955fe4ea5ba4025f16ba2da013df176c035Yu Shan Emily Lau    private final RecorderErrorCallback mRecorderErrorCallback = new RecorderErrorCallback();
6220a6b955fe4ea5ba4025f16ba2da013df176c035Yu Shan Emily Lau
6379a3981e3885b9144bb3d458682141eed7365939Jeff Brown    private Handler mHandler;
64ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi    private Thread mLooperThread;
65ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi    private Writer mOutput;
6679a3981e3885b9144bb3d458682141eed7365939Jeff Brown
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public MediaRecorderStressTest() {
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super("com.android.mediaframeworktest", MediaFrameworkTest.class);
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void setUp() throws Exception {
7279a3981e3885b9144bb3d458682141eed7365939Jeff Brown        final Semaphore sem = new Semaphore(0);
7379a3981e3885b9144bb3d458682141eed7365939Jeff Brown        mLooperThread = new Thread() {
7479a3981e3885b9144bb3d458682141eed7365939Jeff Brown            @Override
7579a3981e3885b9144bb3d458682141eed7365939Jeff Brown            public void run() {
7679a3981e3885b9144bb3d458682141eed7365939Jeff Brown                Log.v(TAG, "starting looper");
7779a3981e3885b9144bb3d458682141eed7365939Jeff Brown                Looper.prepare();
7879a3981e3885b9144bb3d458682141eed7365939Jeff Brown                mHandler = new Handler();
7979a3981e3885b9144bb3d458682141eed7365939Jeff Brown                sem.release();
8079a3981e3885b9144bb3d458682141eed7365939Jeff Brown                Looper.loop();
8179a3981e3885b9144bb3d458682141eed7365939Jeff Brown                Log.v(TAG, "quit looper");
8279a3981e3885b9144bb3d458682141eed7365939Jeff Brown            }
8379a3981e3885b9144bb3d458682141eed7365939Jeff Brown        };
8479a3981e3885b9144bb3d458682141eed7365939Jeff Brown        mLooperThread.start();
8579a3981e3885b9144bb3d458682141eed7365939Jeff Brown        if (! sem.tryAcquire(WAIT_TIMEOUT, TimeUnit.MILLISECONDS)) {
8679a3981e3885b9144bb3d458682141eed7365939Jeff Brown            fail("Failed to start the looper.");
8779a3981e3885b9144bb3d458682141eed7365939Jeff Brown        }
88003a7569745640d700c318a463385ca5feb08728Yu Shan Emily Lau        //Insert a 2 second before launching the test activity. This is
89003a7569745640d700c318a463385ca5feb08728Yu Shan Emily Lau        //the workaround for the race condition of requesting the updated surface.
90003a7569745640d700c318a463385ca5feb08728Yu Shan Emily Lau        Thread.sleep(2000);
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        getActivity();
9279a3981e3885b9144bb3d458682141eed7365939Jeff Brown        super.setUp();
93ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi
94ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi        File stressOutFile = new File(String.format("%s/%s",
95ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi                Environment.getExternalStorageDirectory(), MEDIA_STRESS_OUTPUT));
96ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi        mOutput = new BufferedWriter(new FileWriter(stressOutFile, true));
97ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi        mOutput.write(this.getName() + "\n");
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9920a6b955fe4ea5ba4025f16ba2da013df176c035Yu Shan Emily Lau
10079a3981e3885b9144bb3d458682141eed7365939Jeff Brown    @Override
10179a3981e3885b9144bb3d458682141eed7365939Jeff Brown    protected void tearDown() throws Exception {
10279a3981e3885b9144bb3d458682141eed7365939Jeff Brown        if (mHandler != null) {
10379a3981e3885b9144bb3d458682141eed7365939Jeff Brown            mHandler.getLooper().quit();
10479a3981e3885b9144bb3d458682141eed7365939Jeff Brown            mHandler = null;
10579a3981e3885b9144bb3d458682141eed7365939Jeff Brown        }
10679a3981e3885b9144bb3d458682141eed7365939Jeff Brown        if (mLooperThread != null) {
10779a3981e3885b9144bb3d458682141eed7365939Jeff Brown            mLooperThread.join(WAIT_TIMEOUT);
10879a3981e3885b9144bb3d458682141eed7365939Jeff Brown            if (mLooperThread.isAlive()) {
10979a3981e3885b9144bb3d458682141eed7365939Jeff Brown                fail("Failed to stop the looper.");
11020a6b955fe4ea5ba4025f16ba2da013df176c035Yu Shan Emily Lau            }
11179a3981e3885b9144bb3d458682141eed7365939Jeff Brown            mLooperThread = null;
11220a6b955fe4ea5ba4025f16ba2da013df176c035Yu Shan Emily Lau        }
113ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi        mOutput.write("\n\n");
114ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi        mOutput.close();
11579a3981e3885b9144bb3d458682141eed7365939Jeff Brown        super.tearDown();
11620a6b955fe4ea5ba4025f16ba2da013df176c035Yu Shan Emily Lau    }
11720a6b955fe4ea5ba4025f16ba2da013df176c035Yu Shan Emily Lau
11879a3981e3885b9144bb3d458682141eed7365939Jeff Brown    private void runOnLooper(final Runnable command) throws InterruptedException {
11979a3981e3885b9144bb3d458682141eed7365939Jeff Brown        final Semaphore sem = new Semaphore(0);
12079a3981e3885b9144bb3d458682141eed7365939Jeff Brown        mHandler.post(new Runnable() {
12120a6b955fe4ea5ba4025f16ba2da013df176c035Yu Shan Emily Lau            @Override
12220a6b955fe4ea5ba4025f16ba2da013df176c035Yu Shan Emily Lau            public void run() {
12379a3981e3885b9144bb3d458682141eed7365939Jeff Brown                try {
12479a3981e3885b9144bb3d458682141eed7365939Jeff Brown                    command.run();
12579a3981e3885b9144bb3d458682141eed7365939Jeff Brown                } finally {
12679a3981e3885b9144bb3d458682141eed7365939Jeff Brown                    sem.release();
12720a6b955fe4ea5ba4025f16ba2da013df176c035Yu Shan Emily Lau                }
12820a6b955fe4ea5ba4025f16ba2da013df176c035Yu Shan Emily Lau            }
12979a3981e3885b9144bb3d458682141eed7365939Jeff Brown        });
13079a3981e3885b9144bb3d458682141eed7365939Jeff Brown        if (! sem.tryAcquire(WAIT_TIMEOUT, TimeUnit.MILLISECONDS)) {
13179a3981e3885b9144bb3d458682141eed7365939Jeff Brown            fail("Failed to run the command on the looper.");
13279a3981e3885b9144bb3d458682141eed7365939Jeff Brown        }
13320a6b955fe4ea5ba4025f16ba2da013df176c035Yu Shan Emily Lau    }
13420a6b955fe4ea5ba4025f16ba2da013df176c035Yu Shan Emily Lau
13579a3981e3885b9144bb3d458682141eed7365939Jeff Brown    private final class CameraErrorCallback implements android.hardware.Camera.ErrorCallback {
13679a3981e3885b9144bb3d458682141eed7365939Jeff Brown        public void onError(int error, android.hardware.Camera camera) {
137ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi            fail(String.format("Camera error, code: %d", error));
13820a6b955fe4ea5ba4025f16ba2da013df176c035Yu Shan Emily Lau        }
13920a6b955fe4ea5ba4025f16ba2da013df176c035Yu Shan Emily Lau    }
14020a6b955fe4ea5ba4025f16ba2da013df176c035Yu Shan Emily Lau
14179a3981e3885b9144bb3d458682141eed7365939Jeff Brown    private final class RecorderErrorCallback implements MediaRecorder.OnErrorListener {
14279a3981e3885b9144bb3d458682141eed7365939Jeff Brown        public void onError(MediaRecorder mr, int what, int extra) {
143ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi            fail(String.format("Media recorder error, code: %d\textra: %d", what, extra));
14420a6b955fe4ea5ba4025f16ba2da013df176c035Yu Shan Emily Lau        }
14520a6b955fe4ea5ba4025f16ba2da013df176c035Yu Shan Emily Lau    }
14620a6b955fe4ea5ba4025f16ba2da013df176c035Yu Shan Emily Lau
147ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi    public void validateRecordedVideo(String recordedFile) {
14848584d7b8f5e56b73bb13180bf6546b2647c1b28Yu Shan Emily Lau        try {
14948584d7b8f5e56b73bb13180bf6546b2647c1b28Yu Shan Emily Lau            MediaPlayer mp = new MediaPlayer();
150ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi            mp.setDataSource(recordedFile);
15148584d7b8f5e56b73bb13180bf6546b2647c1b28Yu Shan Emily Lau            mp.prepare();
15248584d7b8f5e56b73bb13180bf6546b2647c1b28Yu Shan Emily Lau            int duration = mp.getDuration();
15348584d7b8f5e56b73bb13180bf6546b2647c1b28Yu Shan Emily Lau            if (duration <= 0){
154ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi                fail("stressRecordAndPlayback");
15548584d7b8f5e56b73bb13180bf6546b2647c1b28Yu Shan Emily Lau            }
15693aa00c664ae59c2224853f14d30a6671c467ef0Yu Shan Emily Lau            mp.release();
15748584d7b8f5e56b73bb13180bf6546b2647c1b28Yu Shan Emily Lau        } catch (Exception e) {
158ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi            fail("stressRecordAndPlayback");
15948584d7b8f5e56b73bb13180bf6546b2647c1b28Yu Shan Emily Lau        }
16048584d7b8f5e56b73bb13180bf6546b2647c1b28Yu Shan Emily Lau    }
16148584d7b8f5e56b73bb13180bf6546b2647c1b28Yu Shan Emily Lau
162ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi    public void removeRecordedVideo(String fileName){
163ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi        File video = new File(fileName);
164ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi        Log.v(TAG, "remove recorded video " + fileName);
16548584d7b8f5e56b73bb13180bf6546b2647c1b28Yu Shan Emily Lau        video.delete();
16648584d7b8f5e56b73bb13180bf6546b2647c1b28Yu Shan Emily Lau    }
16748584d7b8f5e56b73bb13180bf6546b2647c1b28Yu Shan Emily Lau
168ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi    // Helper method for record & playback testing with different camcorder profiles
169ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi    private void recordVideoAndPlayback(int profile) throws Exception {
170ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi        int iterations;
171ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi        int recordDuration;
172ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi        boolean removeVideo;
173ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi
174ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi        int videoEncoder;
175ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi        int audioEncoder;
176ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi        int frameRate;
177ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi        int videoWidth;
178ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi        int videoHeight;
179ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi        int bitRate;
180ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi
181ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi        if (profile != USE_TEST_RUNNER_PROFILE) {
182ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi            assertTrue(String.format("Camera doesn't support profile %d", profile),
183ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi                    CamcorderProfile.hasProfile(CAMERA_ID, profile));
184ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi            CamcorderProfile camcorderProfile = CamcorderProfile.get(CAMERA_ID, profile);
185ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi            videoEncoder = camcorderProfile.videoCodec;
186ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi            audioEncoder = camcorderProfile.audioCodec;
187ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi            frameRate = camcorderProfile.videoFrameRate;
188ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi            videoWidth = camcorderProfile.videoFrameWidth;
189ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi            videoHeight = camcorderProfile.videoFrameHeight;
190ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi            bitRate = camcorderProfile.videoBitRate;
191ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi        } else {
192ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi            videoEncoder = MediaRecorderStressTestRunner.mVideoEncoder;
193ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi            audioEncoder = MediaRecorderStressTestRunner.mAudioEncoder;
194ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi            frameRate = MediaRecorderStressTestRunner.mFrameRate;
195ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi            videoWidth = MediaRecorderStressTestRunner.mVideoWidth;
196ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi            videoHeight = MediaRecorderStressTestRunner.mVideoHeight;
197ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi            bitRate = MediaRecorderStressTestRunner.mBitRate;
198ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi        }
199ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi        iterations = MediaRecorderStressTestRunner.mIterations;
200ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi        recordDuration = MediaRecorderStressTestRunner.mDuration;
201ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi        removeVideo = MediaRecorderStressTestRunner.mRemoveVideo;
202ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi
203ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi        SurfaceHolder surfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
204ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi        mOutput.write("Total number of loops: " + iterations + "\n");
205ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi
206f16da13585ac22bb8d8fe7538509c2726bb06f29Yu Shan Emily Lau        try {
207ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi            mOutput.write("No of loop: ");
208ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi            for (int i = 0; i < iterations; i++) {
209ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi                String fileName = String.format("%s/temp%d%s",
210ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi                        Environment.getExternalStorageDirectory(), i, OUTPUT_FILE_EXT);
211ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi                Log.v(TAG, fileName);
212ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi
21379a3981e3885b9144bb3d458682141eed7365939Jeff Brown                runOnLooper(new Runnable() {
21479a3981e3885b9144bb3d458682141eed7365939Jeff Brown                    @Override
21579a3981e3885b9144bb3d458682141eed7365939Jeff Brown                    public void run() {
21679a3981e3885b9144bb3d458682141eed7365939Jeff Brown                        mRecorder = new MediaRecorder();
21720a6b955fe4ea5ba4025f16ba2da013df176c035Yu Shan Emily Lau                    }
21879a3981e3885b9144bb3d458682141eed7365939Jeff Brown                });
219ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi
22048584d7b8f5e56b73bb13180bf6546b2647c1b28Yu Shan Emily Lau                Log.v(TAG, "iterations : " + iterations);
221ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi                Log.v(TAG, "video encoder : " + videoEncoder);
222ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi                Log.v(TAG, "audio encoder : " + audioEncoder);
223ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi                Log.v(TAG, "frame rate : " + frameRate);
224ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi                Log.v(TAG, "video width : " + videoWidth);
225ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi                Log.v(TAG, "video height : " + videoHeight);
226ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi                Log.v(TAG, "bit rate : " + bitRate);
227ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi                Log.v(TAG, "record duration : " + recordDuration);
22848584d7b8f5e56b73bb13180bf6546b2647c1b28Yu Shan Emily Lau
22920a6b955fe4ea5ba4025f16ba2da013df176c035Yu Shan Emily Lau                mRecorder.setOnErrorListener(mRecorderErrorCallback);
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
23220a6b955fe4ea5ba4025f16ba2da013df176c035Yu Shan Emily Lau                mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
233ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi                mRecorder.setOutputFile(fileName);
234ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi                mRecorder.setVideoFrameRate(frameRate);
235ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi                mRecorder.setVideoSize(videoWidth, videoHeight);
236ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi                mRecorder.setVideoEncoder(videoEncoder);
237ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi                mRecorder.setAudioEncoder(audioEncoder);
238ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi                mRecorder.setVideoEncodingBitRate(bitRate);
239ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Log.v(TAG, "mediaRecorder setPreview");
241ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi                mRecorder.setPreviewDisplay(surfaceHolder.getSurface());
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mRecorder.prepare();
24320a6b955fe4ea5ba4025f16ba2da013df176c035Yu Shan Emily Lau                mRecorder.start();
244ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi                Thread.sleep(recordDuration);
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Log.v(TAG, "Before stop");
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mRecorder.stop();
24779a3981e3885b9144bb3d458682141eed7365939Jeff Brown                mRecorder.release();
248ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                //start the playback
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                MediaPlayer mp = new MediaPlayer();
251ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi                mp.setDataSource(fileName);
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mp.setDisplay(MediaFrameworkTest.mSurfaceView.getHolder());
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mp.prepare();
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mp.start();
255ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi                Thread.sleep(recordDuration);
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mp.release();
257ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi                validateRecordedVideo(fileName);
258ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi                if (removeVideo) {
259ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi                    removeRecordedVideo(fileName);
260ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi                }
261ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi                if (i == 0) {
262ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi                    mOutput.write(i + 1);
263ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi                } else {
264ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi                    mOutput.write(String.format(", %d", (i + 1)));
26548584d7b8f5e56b73bb13180bf6546b2647c1b28Yu Shan Emily Lau                }
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
268ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi            Log.e(TAG, e.toString());
269ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi            fail("Record and playback");
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
271ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi    }
272ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi
273ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi    // Record and playback stress test @ 1080P quality
274ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi    @LargeTest
275ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi    public void testStressRecordVideoAndPlayback1080P() throws Exception {
276ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi        recordVideoAndPlayback(CamcorderProfile.QUALITY_1080P);
277ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi    }
278ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi
279ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi    // Record and playback stress test @ 720P quality
280ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi    @LargeTest
281ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi    public void testStressRecordVideoAndPlayback720P() throws Exception {
282ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi        recordVideoAndPlayback(CamcorderProfile.QUALITY_720P);
283ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi    }
284ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi
285ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi    // Record and playback stress test @ 480P quality
286ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi    @LargeTest
287ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi    public void testStressRecordVideoAndPlayback480P() throws Exception {
288ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi        recordVideoAndPlayback(CamcorderProfile.QUALITY_480P);
289ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi    }
290ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi
291ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi    // This test method uses the codec info from the test runner. Use this
292ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi    // for more granular control of video encoding.
293ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi    @LargeTest
294ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi    public void defaultStressRecordVideoAndPlayback() throws Exception {
295ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi        recordVideoAndPlayback(USE_TEST_RUNNER_PROFILE);
29620a6b955fe4ea5ba4025f16ba2da013df176c035Yu Shan Emily Lau    }
29727c8d9ba169aa85127fac65d6df25e4335ee2fcaJason Noguchi
29827c8d9ba169aa85127fac65d6df25e4335ee2fcaJason Noguchi    // Test case for stressing time lapse
29927c8d9ba169aa85127fac65d6df25e4335ee2fcaJason Noguchi    @LargeTest
30027c8d9ba169aa85127fac65d6df25e4335ee2fcaJason Noguchi    public void testStressTimeLapse() throws Exception {
30127c8d9ba169aa85127fac65d6df25e4335ee2fcaJason Noguchi        SurfaceHolder mSurfaceHolder;
30227c8d9ba169aa85127fac65d6df25e4335ee2fcaJason Noguchi        mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
303ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi        int recordDuration = MediaRecorderStressTestRunner.mTimeLapseDuration;
304ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi        boolean removeVideo = MediaRecorderStressTestRunner.mRemoveVideo;
30527c8d9ba169aa85127fac65d6df25e4335ee2fcaJason Noguchi        double captureRate = MediaRecorderStressTestRunner.mCaptureRate;
306ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi        Log.v(TAG, "Start camera time lapse stress:");
307ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi        mOutput.write("Total number of loops: " + NUMBER_OF_TIME_LAPSE_LOOPS + "\n");
30827c8d9ba169aa85127fac65d6df25e4335ee2fcaJason Noguchi
30927c8d9ba169aa85127fac65d6df25e4335ee2fcaJason Noguchi        try {
310ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi            for (int i = 0, n = Camera.getNumberOfCameras(); i < n; i++) {
311ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi                mOutput.write("No of loop: camera " + i);
312ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi                for (int j = 0; j < NUMBER_OF_TIME_LAPSE_LOOPS; j++) {
313ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi                    String fileName = String.format("%s/temp%d_%d%s",
314ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi                            Environment.getExternalStorageDirectory(), i, j, OUTPUT_FILE_EXT);
315ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi                    Log.v(TAG, fileName);
3167b996d19afcc7030400b515a665d28523a44bb18James Dong                    runOnLooper(new Runnable() {
3177b996d19afcc7030400b515a665d28523a44bb18James Dong                        @Override
3187b996d19afcc7030400b515a665d28523a44bb18James Dong                        public void run() {
3197b996d19afcc7030400b515a665d28523a44bb18James Dong                            mRecorder = new MediaRecorder();
3207b996d19afcc7030400b515a665d28523a44bb18James Dong                        }
3217b996d19afcc7030400b515a665d28523a44bb18James Dong                    });
3227b996d19afcc7030400b515a665d28523a44bb18James Dong
3237b996d19afcc7030400b515a665d28523a44bb18James Dong                    // Set callback
3247b996d19afcc7030400b515a665d28523a44bb18James Dong                    mRecorder.setOnErrorListener(mRecorderErrorCallback);
3257b996d19afcc7030400b515a665d28523a44bb18James Dong
3267b996d19afcc7030400b515a665d28523a44bb18James Dong                    // Set video source
3277b996d19afcc7030400b515a665d28523a44bb18James Dong                    mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
3287b996d19afcc7030400b515a665d28523a44bb18James Dong
3297b996d19afcc7030400b515a665d28523a44bb18James Dong                    // Set camcorder profile for time lapse
3307b996d19afcc7030400b515a665d28523a44bb18James Dong                    CamcorderProfile profile =
3317b996d19afcc7030400b515a665d28523a44bb18James Dong                        CamcorderProfile.get(j, CamcorderProfile.QUALITY_TIME_LAPSE_HIGH);
3327b996d19afcc7030400b515a665d28523a44bb18James Dong                    mRecorder.setProfile(profile);
3337b996d19afcc7030400b515a665d28523a44bb18James Dong
334ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi                    // Set the timelapse setting; 0.1 = 10 sec timelapse, 0.5 = 2 sec timelapse, etc
3357b996d19afcc7030400b515a665d28523a44bb18James Dong                    // http://developer.android.com/guide/topics/media/camera.html#time-lapse-video
3367b996d19afcc7030400b515a665d28523a44bb18James Dong                    mRecorder.setCaptureRate(captureRate);
3377b996d19afcc7030400b515a665d28523a44bb18James Dong
3387b996d19afcc7030400b515a665d28523a44bb18James Dong                    // Set output file
339ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi                    mRecorder.setOutputFile(fileName);
3407b996d19afcc7030400b515a665d28523a44bb18James Dong
3417b996d19afcc7030400b515a665d28523a44bb18James Dong                    // Set the preview display
3427b996d19afcc7030400b515a665d28523a44bb18James Dong                    Log.v(TAG, "mediaRecorder setPreviewDisplay");
3437b996d19afcc7030400b515a665d28523a44bb18James Dong                    mRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
3447b996d19afcc7030400b515a665d28523a44bb18James Dong
3457b996d19afcc7030400b515a665d28523a44bb18James Dong                    mRecorder.prepare();
3467b996d19afcc7030400b515a665d28523a44bb18James Dong                    mRecorder.start();
347ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi                    Thread.sleep(recordDuration);
3487b996d19afcc7030400b515a665d28523a44bb18James Dong                    Log.v(TAG, "Before stop");
3497b996d19afcc7030400b515a665d28523a44bb18James Dong                    mRecorder.stop();
3507b996d19afcc7030400b515a665d28523a44bb18James Dong                    mRecorder.release();
3517b996d19afcc7030400b515a665d28523a44bb18James Dong
3527b996d19afcc7030400b515a665d28523a44bb18James Dong                    // Start the playback
3537b996d19afcc7030400b515a665d28523a44bb18James Dong                    MediaPlayer mp = new MediaPlayer();
354ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi                    mp.setDataSource(fileName);
3557b996d19afcc7030400b515a665d28523a44bb18James Dong                    mp.setDisplay(mSurfaceHolder);
3567b996d19afcc7030400b515a665d28523a44bb18James Dong                    mp.prepare();
3577b996d19afcc7030400b515a665d28523a44bb18James Dong                    mp.start();
3587b996d19afcc7030400b515a665d28523a44bb18James Dong                    Thread.sleep(TIME_LAPSE_PLAYBACK_WAIT_TIME);
3597b996d19afcc7030400b515a665d28523a44bb18James Dong                    mp.release();
360ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi                    validateRecordedVideo(fileName);
361ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi                    if (removeVideo) {
362ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi                        removeRecordedVideo(fileName);
363ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi                    }
364ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi
365ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi                    if (j == 0) {
366ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi                        mOutput.write(j + 1);
367ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi                    } else {
368ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi                        mOutput.write(String.format(", %d", (j + 1)));
36927c8d9ba169aa85127fac65d6df25e4335ee2fcaJason Noguchi                    }
37027c8d9ba169aa85127fac65d6df25e4335ee2fcaJason Noguchi                }
37127c8d9ba169aa85127fac65d6df25e4335ee2fcaJason Noguchi            }
372ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi        } catch (IllegalStateException e) {
373ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi            Log.e(TAG, e.toString());
374ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi            fail("Camera time lapse stress test IllegalStateException");
375ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi        } catch (IOException e) {
376ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi            Log.e(TAG, e.toString());
377ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi            fail("Camera time lapse stress test IOException");
378ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi        } catch (Exception e) {
379ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi            Log.e(TAG, e.toString());
380ca6a5eee8f72742298d28d8a4b8e1bd32020a237Jason Noguchi            fail("Camera time lapse stress test Exception");
38127c8d9ba169aa85127fac65d6df25e4335ee2fcaJason Noguchi        }
38227c8d9ba169aa85127fac65d6df25e4335ee2fcaJason Noguchi    }
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
384