Home | History | Annotate | Download | only in cts
      1 /*
      2  * Copyright (C) 2012 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 
     17 package android.mediastress.cts;
     18 
     19 import android.content.pm.PackageManager;
     20 import android.hardware.Camera;
     21 import android.media.CamcorderProfile;
     22 import android.media.MediaPlayer;
     23 import android.media.MediaRecorder;
     24 import android.os.Handler;
     25 import android.os.Looper;
     26 import android.test.ActivityInstrumentationTestCase2;
     27 import android.test.suitebuilder.annotation.LargeTest;
     28 import android.util.Log;
     29 import android.view.SurfaceHolder;
     30 
     31 import java.io.BufferedWriter;
     32 import java.io.File;
     33 import java.io.FileWriter;
     34 import java.io.Writer;
     35 import java.util.List;
     36 import java.util.concurrent.Semaphore;
     37 import java.util.concurrent.TimeUnit;
     38 
     39 public class MediaRecorderStressTest extends ActivityInstrumentationTestCase2<MediaFrameworkTest> {
     40 
     41     private static final String TAG = "MediaRecorderStressTest";
     42     private static final int NUMBER_OF_CAMERA_STRESS_LOOPS = 50;
     43     private static final int NUMBER_OF_RECORDER_STRESS_LOOPS = 50;
     44     private static final int NUMBER_OF_RECORDERANDPLAY_STRESS_LOOPS = 25;
     45     private static final int NUMBER_OF_SWTICHING_LOOPS_BW_CAMERA_AND_RECORDER = 50;
     46     private static final long WAIT_TIME_CAMERA_TEST = 3000;  // in ms
     47     private static final long WAIT_TIME_RECORDER_TEST = 5000;  // in ms
     48     private final String OUTPUT_FILE = WorkDir.getTopDirString() + "temp";
     49     private static final String OUTPUT_FILE_EXT = ".3gp";
     50     private static final String MEDIA_STRESS_OUTPUT ="mediaStressOutput.txt";
     51     private final CameraErrorCallback mCameraErrorCallback = new CameraErrorCallback();
     52     private final RecorderErrorCallback mRecorderErrorCallback = new RecorderErrorCallback();
     53     private final static int WAIT_TIMEOUT = 10000;
     54     private static final int VIDEO_WIDTH = 176;
     55     private static final int VIDEO_HEIGHT = 144;
     56 
     57     private MediaRecorder mRecorder;
     58     private Camera mCamera;
     59     private Thread mLooperThread;
     60     private Handler mHandler;
     61 
     62     private static int mCameraId;
     63     private static int mProfileQuality = CamcorderProfile.QUALITY_HIGH;
     64     private static CamcorderProfile profile =
     65                         CamcorderProfile.get(mCameraId, mProfileQuality);
     66 
     67     private int mVideoEncoder;
     68     private int mAudioEncoder;
     69     private int mFrameRate;
     70     private int mVideoWidth;
     71     private int mVideoHeight;
     72     private int mBitRate;
     73     private boolean mRemoveVideo = true;
     74     private int mRecordDuration = 5000;
     75 
     76     private boolean mHasRearCamera = false;
     77     private boolean mHasFrontCamera = false;
     78 
     79     public MediaRecorderStressTest() {
     80         super(MediaFrameworkTest.class);
     81     }
     82 
     83     protected void setUp() throws Exception {
     84         PackageManager packageManager =
     85                 getInstrumentation().getTargetContext().getPackageManager();
     86         mHasRearCamera = packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA);
     87         mHasFrontCamera = packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT);
     88         int cameraId = 0;
     89         CamcorderProfile profile = CamcorderProfile.get(cameraId, CamcorderProfile.QUALITY_HIGH);
     90         mVideoEncoder = profile.videoCodec;
     91         mAudioEncoder = profile.audioCodec;
     92         mFrameRate = profile.videoFrameRate;
     93         mVideoWidth = profile.videoFrameWidth;
     94         mVideoHeight = profile.videoFrameHeight;
     95         mBitRate = profile.videoBitRate;
     96 
     97         final Semaphore sem = new Semaphore(0);
     98         mLooperThread = new Thread() {
     99             @Override
    100             public void run() {
    101                 Log.v(TAG, "starting looper");
    102                 Looper.prepare();
    103                 mHandler = new Handler();
    104                 sem.release();
    105                 Looper.loop();
    106                 Log.v(TAG, "quit looper");
    107             }
    108         };
    109         mLooperThread.start();
    110         if (!sem.tryAcquire(WAIT_TIMEOUT, TimeUnit.MILLISECONDS)) {
    111             fail("Failed to start the looper.");
    112         }
    113 
    114         getActivity();
    115         super.setUp();
    116     }
    117 
    118     @Override
    119     protected void tearDown() throws Exception {
    120         if (mHandler != null) {
    121             mHandler.getLooper().quit();
    122             mHandler = null;
    123         }
    124         if (mLooperThread != null) {
    125             mLooperThread.join(WAIT_TIMEOUT);
    126             if (mLooperThread.isAlive()) {
    127                 fail("Failed to stop the looper.");
    128             }
    129             mLooperThread = null;
    130         }
    131 
    132         super.tearDown();
    133     }
    134 
    135     private void runOnLooper(final Runnable command) throws InterruptedException {
    136         final Semaphore sem = new Semaphore(0);
    137         mHandler.post(new Runnable() {
    138             @Override
    139             public void run() {
    140                 try {
    141                     command.run();
    142                 } finally {
    143                     sem.release();
    144                 }
    145             }
    146         });
    147         if (! sem.tryAcquire(WAIT_TIMEOUT, TimeUnit.MILLISECONDS)) {
    148             fail("Failed to run the command on the looper.");
    149         }
    150     }
    151 
    152     private final class CameraErrorCallback implements android.hardware.Camera.ErrorCallback {
    153         public void onError(int error, android.hardware.Camera camera) {
    154             assertTrue("Camera test mediaserver died", error !=
    155                     android.hardware.Camera.CAMERA_ERROR_SERVER_DIED);
    156         }
    157     }
    158 
    159     private final class RecorderErrorCallback implements MediaRecorder.OnErrorListener {
    160         public void onError(MediaRecorder mr, int what, int extra) {
    161             // fail the test case no matter what error come up
    162             fail("mediaRecorder error");
    163         }
    164     }
    165 
    166     //Test case for stressing the camera preview.
    167     @LargeTest
    168     public void testStressCamera() throws Exception {
    169         if (Camera.getNumberOfCameras() < 1) {
    170             return;
    171         }
    172 
    173         SurfaceHolder mSurfaceHolder;
    174         mSurfaceHolder = MediaFrameworkTest.getSurfaceView().getHolder();
    175         File stressOutFile = new File(WorkDir.getTopDir(), MEDIA_STRESS_OUTPUT);
    176         Writer output = new BufferedWriter(new FileWriter(stressOutFile, true));
    177         output.write("Camera start preview stress:\n");
    178         output.write("Total number of loops:" +
    179                 NUMBER_OF_CAMERA_STRESS_LOOPS + "\n");
    180 
    181         Log.v(TAG, "Start preview");
    182         output.write("No of loop: ");
    183 
    184         for (int i = 0; i< NUMBER_OF_CAMERA_STRESS_LOOPS; i++) {
    185             runOnLooper(new Runnable() {
    186                 @Override
    187                 public void run() {
    188                     if (mHasRearCamera) {
    189                         mCamera = Camera.open();
    190                     } else if (mHasFrontCamera) {
    191                         mCamera = Camera.open(0);
    192                     } else {
    193                         mCamera = null;
    194                     }
    195                 }
    196             });
    197             if (mCamera == null) {
    198                 break;
    199             }
    200             mCamera.setErrorCallback(mCameraErrorCallback);
    201             mCamera.setPreviewDisplay(mSurfaceHolder);
    202             mCamera.startPreview();
    203             Thread.sleep(WAIT_TIME_CAMERA_TEST);
    204             mCamera.stopPreview();
    205             mCamera.release();
    206             output.write(" ," + i);
    207         }
    208 
    209         output.write("\n\n");
    210         output.close();
    211     }
    212 
    213     //Test case for stressing the camera preview.
    214     @LargeTest
    215     public void testStressRecorder() throws Exception {
    216         String filename;
    217         SurfaceHolder mSurfaceHolder;
    218         mSurfaceHolder = MediaFrameworkTest.getSurfaceView().getHolder();
    219         File stressOutFile = new File(WorkDir.getTopDir(), MEDIA_STRESS_OUTPUT);
    220         Writer output = new BufferedWriter(new FileWriter(stressOutFile, true));
    221         int width;
    222         int height;
    223         Camera camera = null;
    224 
    225         if (!mHasRearCamera && !mHasFrontCamera) {
    226                 output.write("No camera found. Skipping recorder stress test\n");
    227                 return;
    228         }
    229         // Try to get camera smallest supported resolution.
    230         // If we fail for any reason, set the video size to default value.
    231         try {
    232             camera = Camera.open(0);
    233             List<Camera.Size> previewSizes = camera.getParameters().getSupportedPreviewSizes();
    234             width = previewSizes.get(0).width;
    235             height = previewSizes.get(0).height;
    236             for (Camera.Size size : previewSizes) {
    237                 if (size.width < width || size.height < height) {
    238                     width = size.width;
    239                     height = size.height;
    240                 }
    241             }
    242         } catch (Exception e) {
    243             width = VIDEO_WIDTH;
    244             height = VIDEO_HEIGHT;
    245         }
    246         if (camera != null) {
    247             camera.release();
    248         }
    249         Log.v(TAG, String.format("Camera video size used for test %dx%d", width, height));
    250         output.write("H263 video record- reset after prepare Stress test\n");
    251         output.write("Total number of loops:" +
    252                 NUMBER_OF_RECORDER_STRESS_LOOPS + "\n");
    253 
    254         output.write("No of loop: ");
    255         Log.v(TAG, "Start preview");
    256         for (int i = 0; i < NUMBER_OF_RECORDER_STRESS_LOOPS; i++) {
    257             runOnLooper(new Runnable() {
    258                 @Override
    259                 public void run() {
    260                     mRecorder = new MediaRecorder();
    261                 }
    262             });
    263             Log.v(TAG, "counter = " + i);
    264             filename = OUTPUT_FILE + i + OUTPUT_FILE_EXT;
    265             Log.v(TAG, filename);
    266             mRecorder.setOnErrorListener(mRecorderErrorCallback);
    267             mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
    268             mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
    269             mRecorder.setOutputFile(filename);
    270             mRecorder.setVideoFrameRate(mFrameRate);
    271             mRecorder.setVideoSize(width, height);
    272             Log.v(TAG, "setEncoder");
    273             mRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H263);
    274             mSurfaceHolder = MediaFrameworkTest.getSurfaceView().getHolder();
    275             Log.v(TAG, "setPreview");
    276             mRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
    277             Log.v(TAG, "prepare");
    278             mRecorder.prepare();
    279             Log.v(TAG, "before release");
    280             Thread.sleep(WAIT_TIME_RECORDER_TEST);
    281             mRecorder.reset();
    282             mRecorder.release();
    283             output.write(", " + i);
    284         }
    285 
    286         output.write("\n\n");
    287         output.close();
    288     }
    289 
    290     //Stress test case for switching camera and video recorder preview.
    291     @LargeTest
    292     public void testStressCameraSwitchRecorder() throws Exception {
    293         if (Camera.getNumberOfCameras() < 1) {
    294             return;
    295         }
    296 
    297         String filename;
    298         int width;
    299         int height;
    300         SurfaceHolder mSurfaceHolder;
    301         mSurfaceHolder = MediaFrameworkTest.getSurfaceView().getHolder();
    302         File stressOutFile = new File(WorkDir.getTopDir(), MEDIA_STRESS_OUTPUT);
    303         Writer output = new BufferedWriter(new FileWriter(stressOutFile, true));
    304         output.write("Camera and video recorder preview switching\n");
    305         output.write("Total number of loops:"
    306                 + NUMBER_OF_SWTICHING_LOOPS_BW_CAMERA_AND_RECORDER + "\n");
    307 
    308         Log.v(TAG, "Start preview");
    309         output.write("No of loop: ");
    310         for (int i = 0; i < NUMBER_OF_SWTICHING_LOOPS_BW_CAMERA_AND_RECORDER; i++) {
    311             runOnLooper(new Runnable() {
    312                 @Override
    313                 public void run() {
    314                     if (mHasRearCamera) {
    315                         mCamera = Camera.open();
    316                     } else if (mHasFrontCamera) {
    317                         mCamera = Camera.open(0);
    318                     } else {
    319                         mCamera = null;
    320                     }
    321                 }
    322             });
    323             if (mCamera == null) {
    324                 break;
    325             }
    326             // Try to get camera smallest supported resolution.
    327             // If we fail for any reason, set the video size to default value.
    328             List<Camera.Size> previewSizes = mCamera.getParameters().getSupportedPreviewSizes();
    329             width = previewSizes.get(0).width;
    330             height = previewSizes.get(0).height;
    331             for (Camera.Size size : previewSizes) {
    332                 if (size.width < width || size.height < height) {
    333                     width = size.width;
    334                     height = size.height;
    335                 }
    336             }
    337             Log.v(TAG, String.format("Camera video size used for test %dx%d", width, height));
    338 
    339             mCamera.setErrorCallback(mCameraErrorCallback);
    340             mCamera.setPreviewDisplay(mSurfaceHolder);
    341             mCamera.startPreview();
    342             Thread.sleep(WAIT_TIME_CAMERA_TEST);
    343             mCamera.stopPreview();
    344             mCamera.release();
    345             mCamera = null;
    346             Log.v(TAG, "release camera");
    347             filename = OUTPUT_FILE + i + OUTPUT_FILE_EXT;
    348             Log.v(TAG, filename);
    349             runOnLooper(new Runnable() {
    350                 @Override
    351                 public void run() {
    352                     mRecorder = new MediaRecorder();
    353                 }
    354             });
    355             mRecorder.setOnErrorListener(mRecorderErrorCallback);
    356             mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
    357             mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
    358             mRecorder.setOutputFile(filename);
    359             mRecorder.setVideoFrameRate(mFrameRate);
    360             mRecorder.setVideoSize(width, height);
    361             Log.v(TAG, "Media recorder setEncoder");
    362             mRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H263);
    363             Log.v(TAG, "mediaRecorder setPreview");
    364             mRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
    365             Log.v(TAG, "prepare");
    366             mRecorder.prepare();
    367             Log.v(TAG, "before release");
    368             Thread.sleep(WAIT_TIME_CAMERA_TEST);
    369             mRecorder.reset();
    370             mRecorder.release();
    371             Log.v(TAG, "release video recorder");
    372             output.write(", " + i);
    373         }
    374 
    375         output.write("\n\n");
    376         output.close();
    377     }
    378 
    379     public void validateRecordedVideo(String recordedFile) throws Exception {
    380         MediaPlayer mp = new MediaPlayer();
    381         mp.setDataSource(recordedFile);
    382         mp.prepare();
    383         int duration = mp.getDuration();
    384         if (duration <= 0){
    385             assertTrue("stressRecordAndPlayback", false);
    386         }
    387         mp.release();
    388     }
    389 
    390     public void removeRecodedVideo(String filename){
    391         File video = new File(filename);
    392         Log.v(TAG, "remove recorded video " + filename);
    393         video.delete();
    394     }
    395 
    396     //Stress test case for record a video and play right away.
    397     @LargeTest
    398     public void testStressRecordVideoAndPlayback() throws Exception {
    399         if (Camera.getNumberOfCameras() < 1) {
    400             return;
    401         }
    402 
    403         String filename;
    404         SurfaceHolder mSurfaceHolder;
    405         mSurfaceHolder = MediaFrameworkTest.getSurfaceView().getHolder();
    406         File stressOutFile = new File(WorkDir.getTopDir(), MEDIA_STRESS_OUTPUT);
    407         Writer output = new BufferedWriter(
    408                 new FileWriter(stressOutFile, true));
    409 
    410         output.write("Video record and play back stress test:\n");
    411         output.write("Total number of loops:"
    412                 + NUMBER_OF_RECORDERANDPLAY_STRESS_LOOPS + "\n");
    413 
    414         output.write("No of loop: ");
    415         for (int i = 0; i < NUMBER_OF_RECORDERANDPLAY_STRESS_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             Log.v(TAG, "iterations : " + i);
    425             Log.v(TAG, "videoEncoder : " + mVideoEncoder);
    426             Log.v(TAG, "audioEncoder : " + mAudioEncoder);
    427             Log.v(TAG, "frameRate : " + mFrameRate);
    428             Log.v(TAG, "videoWidth : " + mVideoWidth);
    429             Log.v(TAG, "videoHeight : " + mVideoHeight);
    430             Log.v(TAG, "bitRate : " + mBitRate);
    431             Log.v(TAG, "recordDuration : " + mRecordDuration);
    432 
    433             mRecorder.setOnErrorListener(mRecorderErrorCallback);
    434             mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
    435             mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
    436             mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
    437             mRecorder.setOutputFile(filename);
    438             mRecorder.setVideoFrameRate(mFrameRate);
    439             mRecorder.setVideoSize(mVideoWidth, mVideoHeight);
    440             mRecorder.setVideoEncoder(mVideoEncoder);
    441             mRecorder.setAudioEncoder(mAudioEncoder);
    442             Log.v(TAG, "mediaRecorder setPreview");
    443             mRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
    444             mRecorder.prepare();
    445             mRecorder.start();
    446             Thread.sleep(mRecordDuration);
    447             Log.v(TAG, "Before stop");
    448             mRecorder.stop();
    449             mRecorder.release();
    450             //start the playback
    451             MediaPlayer mp = new MediaPlayer();
    452             mp.setDataSource(filename);
    453             mp.setDisplay(MediaFrameworkTest.getSurfaceView().getHolder());
    454             mp.prepare();
    455             mp.start();
    456             Thread.sleep(mRecordDuration);
    457             mp.release();
    458             validateRecordedVideo(filename);
    459             if (mRemoveVideo) {
    460                 removeRecodedVideo(filename);
    461             }
    462             output.write(", " + i);
    463         }
    464 
    465         output.write("\n\n");
    466         output.close();
    467     }
    468 }
    469