MediaRecorderTest.java revision e996c419e6c9beff09b2bb8d6d5777313a0cf29f
1/* 2 * Copyright (C) 2008 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.functional.mediarecorder; 18 19import com.android.mediaframeworktest.MediaFrameworkTest; 20import com.android.mediaframeworktest.MediaNames; 21 22import java.io.*; 23 24import android.content.Context; 25import android.graphics.Canvas; 26import android.graphics.Color; 27import android.graphics.Paint; 28import android.graphics.Typeface; 29import android.hardware.Camera; 30import android.media.MediaPlayer; 31import android.media.MediaRecorder; 32import android.media.EncoderCapabilities; 33import android.media.EncoderCapabilities.VideoEncoderCap; 34import android.media.EncoderCapabilities.AudioEncoderCap; 35import android.test.ActivityInstrumentationTestCase2; 36import android.util.Log; 37import android.view.Surface; 38import android.view.SurfaceHolder; 39import android.view.SurfaceView; 40import com.android.mediaframeworktest.MediaProfileReader; 41import com.android.mediaframeworktest.MediaFrameworkTestRunner; 42 43import android.test.suitebuilder.annotation.LargeTest; 44import android.test.suitebuilder.annotation.Suppress; 45import java.util.List; 46 47 48/** 49 * Junit / Instrumentation test case for the media recorder api 50 */ 51public class MediaRecorderTest extends ActivityInstrumentationTestCase2<MediaFrameworkTest> { 52 private String TAG = "MediaRecorderTest"; 53 private int mOutputDuration =0; 54 private int mOutputVideoWidth = 0; 55 private int mOutputVideoHeight= 0 ; 56 57 private SurfaceHolder mSurfaceHolder = null; 58 private MediaRecorder mRecorder; 59 60 private int MIN_VIDEO_FPS = 5; 61 62 private static final int CAMERA_ID = 0; 63 64 Context mContext; 65 Camera mCamera; 66 67 public MediaRecorderTest() { 68 super(MediaFrameworkTest.class); 69 70 } 71 72 protected void setUp() throws Exception { 73 getActivity(); 74 mRecorder = new MediaRecorder(); 75 super.setUp(); 76 } 77 78 private void recordVideo(int frameRate, int width, int height, 79 int videoFormat, int outFormat, String outFile, boolean videoOnly) { 80 Log.v(TAG,"startPreviewAndPrepareRecording"); 81 try { 82 if (!videoOnly) { 83 Log.v(TAG, "setAudioSource"); 84 mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); 85 } 86 mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); 87 mRecorder.setOutputFormat(outFormat); 88 Log.v(TAG, "output format " + outFormat); 89 mRecorder.setOutputFile(outFile); 90 mRecorder.setVideoFrameRate(frameRate); 91 mRecorder.setVideoSize(width, height); 92 Log.v(TAG, "setEncoder"); 93 mRecorder.setVideoEncoder(videoFormat); 94 if (!videoOnly) { 95 mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); 96 } 97 mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder(); 98 Log.v(TAG, "setPreview"); 99 mRecorder.setPreviewDisplay(mSurfaceHolder.getSurface()); 100 Log.v(TAG, "prepare"); 101 mRecorder.prepare(); 102 Log.v(TAG, "start"); 103 mRecorder.start(); 104 Thread.sleep(MediaNames.RECORDED_TIME); 105 Log.v(TAG, "stop"); 106 mRecorder.stop(); 107 mRecorder.release(); 108 } catch (Exception e) { 109 Log.v("record video failed ", e.toString()); 110 mRecorder.release(); 111 } 112 } 113 114 private boolean validateGetSurface(boolean useSurface) { 115 Log.v(TAG,"validateGetSurface, useSurface=" + useSurface); 116 MediaRecorder recorder = new MediaRecorder(); 117 Surface surface; 118 boolean success = true; 119 try { 120 /* initialization */ 121 if (!useSurface) { 122 mCamera = Camera.open(CAMERA_ID); 123 Camera.Parameters parameters = mCamera.getParameters(); 124 parameters.setPreviewSize(352, 288); 125 parameters.set("orientation", "portrait"); 126 mCamera.setParameters(parameters); 127 mCamera.unlock(); 128 recorder.setCamera(mCamera); 129 mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder(); 130 recorder.setPreviewDisplay(mSurfaceHolder.getSurface()); 131 } 132 133 recorder.setAudioSource(MediaRecorder.AudioSource.MIC); 134 int videoSource = useSurface ? 135 MediaRecorder.VideoSource.SURFACE : 136 MediaRecorder.VideoSource.CAMERA; 137 recorder.setVideoSource(videoSource); 138 recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); 139 recorder.setOutputFile(MediaNames.RECORDED_SURFACE_3GP); 140 recorder.setVideoFrameRate(30); 141 recorder.setVideoSize(352, 288); 142 recorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); 143 recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); 144 145 /* Test: getSurface() before prepare() 146 * should throw IllegalStateException 147 */ 148 try { 149 surface = recorder.getSurface(); 150 throw new Exception("getSurface failed to throw IllegalStateException"); 151 } catch (IllegalStateException e) { 152 // OK 153 } 154 155 recorder.prepare(); 156 157 /* Test: getSurface() after prepare() 158 * should succeed for surface source 159 * should fail for camera source 160 */ 161 try { 162 surface = recorder.getSurface(); 163 if (!useSurface) { 164 throw new Exception("getSurface failed to throw IllegalStateException"); 165 } 166 } catch (IllegalStateException e) { 167 if (useSurface) { 168 throw new Exception("getSurface failed to throw IllegalStateException"); 169 } 170 } 171 172 recorder.start(); 173 174 /* Test: getSurface() after start() 175 * should succeed for surface source 176 * should fail for camera source 177 */ 178 try { 179 surface = recorder.getSurface(); 180 if (!useSurface) { 181 throw new Exception("getSurface failed to throw IllegalStateException"); 182 } 183 } catch (IllegalStateException e) { 184 if (useSurface) { 185 throw new Exception("getSurface failed to throw IllegalStateException"); 186 } 187 } 188 189 try { 190 recorder.stop(); 191 } catch (Exception e) { 192 // stop() could fail if the recording is empty, as we didn't render anything. 193 // ignore any failure in stop, we just want it stopped. 194 } 195 196 /* Test: getSurface() after stop() 197 * should throw IllegalStateException 198 */ 199 try { 200 surface = recorder.getSurface(); 201 throw new Exception("getSurface failed to throw IllegalStateException"); 202 } catch (IllegalStateException e) { 203 // OK 204 } 205 } catch (Exception e) { 206 // fail 207 success = false; 208 } 209 210 try { 211 if (mCamera != null) { 212 mCamera.lock(); 213 mCamera.release(); 214 mCamera = null; 215 } 216 recorder.release(); 217 } catch (Exception e) { 218 success = false; 219 } 220 221 return success; 222 } 223 224 private boolean recordVideoFromSurface(int frameRate, int width, int height, 225 int videoFormat, int outFormat, String outFile, boolean videoOnly) { 226 Log.v(TAG,"recordVideoFromSurface"); 227 MediaRecorder recorder = new MediaRecorder(); 228 try { 229 if (!videoOnly) { 230 recorder.setAudioSource(MediaRecorder.AudioSource.MIC); 231 } 232 recorder.setVideoSource(MediaRecorder.VideoSource.SURFACE); 233 recorder.setOutputFormat(outFormat); 234 recorder.setOutputFile(outFile); 235 recorder.setVideoFrameRate(frameRate); 236 recorder.setVideoSize(width, height); 237 recorder.setVideoEncoder(videoFormat); 238 if (!videoOnly) { 239 recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); 240 } 241 recorder.prepare(); 242 Surface surface = recorder.getSurface(); 243 244 Paint paint = new Paint(); 245 paint.setTextSize(16); 246 paint.setColor(Color.RED); 247 int i; 248 249 /* Test: draw 10 frames at 30fps before start 250 * these should be dropped and not causing malformed stream. 251 */ 252 for(i = 0; i < 10; i++) { 253 Canvas canvas = surface.lockCanvas(null); 254 int background = (i * 255 / 99); 255 canvas.drawARGB(255, background, background, background); 256 String text = "Frame #" + i; 257 canvas.drawText(text, 100, 100, paint); 258 surface.unlockCanvasAndPost(canvas); 259 Thread.sleep(33); 260 } 261 262 Log.v(TAG, "start"); 263 recorder.start(); 264 265 /* Test: draw another 90 frames at 30fps after start */ 266 for(i = 10; i < 100; i++) { 267 Canvas canvas = surface.lockCanvas(null); 268 int background = (i * 255 / 99); 269 canvas.drawARGB(255, background, background, background); 270 String text = "Frame #" + i; 271 canvas.drawText(text, 100, 100, paint); 272 surface.unlockCanvasAndPost(canvas); 273 Thread.sleep(33); 274 } 275 276 Log.v(TAG, "stop"); 277 recorder.stop(); 278 recorder.release(); 279 } catch (Exception e) { 280 Log.v("record video failed ", e.toString()); 281 recorder.release(); 282 return false; 283 } 284 return true; 285 } 286 287 private boolean recordVideoWithPara(VideoEncoderCap videoCap, AudioEncoderCap audioCap, boolean highQuality){ 288 boolean recordSuccess = false; 289 int videoEncoder = videoCap.mCodec; 290 int audioEncoder = audioCap.mCodec; 291 int videoWidth = highQuality? videoCap.mMaxFrameWidth: videoCap.mMinFrameWidth; 292 int videoHeight = highQuality? videoCap.mMaxFrameHeight: videoCap.mMinFrameHeight; 293 int videoFps = highQuality? videoCap.mMaxFrameRate: videoCap.mMinFrameRate; 294 int videoBitrate = highQuality? videoCap.mMaxBitRate: videoCap.mMinBitRate; 295 int audioBitrate = highQuality? audioCap.mMaxBitRate: audioCap.mMinBitRate; 296 int audioChannels = highQuality? audioCap.mMaxChannels: audioCap.mMinChannels ; 297 int audioSamplingRate = highQuality? audioCap.mMaxSampleRate: audioCap.mMinSampleRate; 298 299 //Overide the fps if the min_camera_fps is set 300 if (MediaFrameworkTestRunner.mMinCameraFps != 0 && 301 MediaFrameworkTestRunner.mMinCameraFps > videoFps){ 302 videoFps = MediaFrameworkTestRunner.mMinCameraFps; 303 } 304 305 if (videoFps < MIN_VIDEO_FPS) { 306 videoFps = MIN_VIDEO_FPS; 307 } 308 309 mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder(); 310 String filename = ("/sdcard/" + videoEncoder + "_" + audioEncoder + "_" + highQuality + ".3gp"); 311 try { 312 Log.v(TAG, "video encoder : " + videoEncoder); 313 Log.v(TAG, "audio encoder : " + audioEncoder); 314 Log.v(TAG, "quality : " + (highQuality?"high": "low")); 315 Log.v(TAG, "encoder : " + MediaProfileReader.getVideoCodecName(videoEncoder)); 316 Log.v(TAG, "audio : " + MediaProfileReader.getAudioCodecName(audioEncoder)); 317 Log.v(TAG, "videoWidth : " + videoWidth); 318 Log.v(TAG, "videoHeight : " + videoHeight); 319 Log.v(TAG, "videoFPS : " + videoFps); 320 Log.v(TAG, "videobitrate : " + videoBitrate); 321 Log.v(TAG, "audioBitrate : " + audioBitrate); 322 Log.v(TAG, "audioChannel : " + audioChannels); 323 Log.v(TAG, "AudioSampleRate : " + audioSamplingRate); 324 325 MediaRecorder mMediaRecorder = new MediaRecorder(); 326 mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); 327 mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); 328 mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); 329 mMediaRecorder.setOutputFile(filename); 330 mMediaRecorder.setVideoFrameRate(videoFps); 331 mMediaRecorder.setVideoSize(videoWidth, videoHeight); 332 mMediaRecorder.setVideoEncodingBitRate(videoBitrate); 333 mMediaRecorder.setAudioEncodingBitRate(audioBitrate); 334 mMediaRecorder.setAudioChannels(audioChannels); 335 mMediaRecorder.setAudioSamplingRate(audioSamplingRate); 336 mMediaRecorder.setVideoEncoder(videoEncoder); 337 mMediaRecorder.setAudioEncoder(audioEncoder); 338 mMediaRecorder.setPreviewDisplay(mSurfaceHolder.getSurface()); 339 mMediaRecorder.prepare(); 340 mMediaRecorder.start(); 341 Thread.sleep(MediaNames.RECORDED_TIME); 342 mMediaRecorder.stop(); 343 mMediaRecorder.release(); 344 recordSuccess = validateVideo(filename, videoWidth, videoHeight); 345 } catch (Exception e) { 346 Log.v(TAG, e.toString()); 347 return false; 348 } 349 return recordSuccess; 350 } 351 352 private boolean invalidRecordSetting(int frameRate, int width, int height, 353 int videoFormat, int outFormat, String outFile, boolean videoOnly) { 354 try { 355 if (!videoOnly) { 356 Log.v(TAG, "setAudioSource"); 357 mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); 358 } 359 mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); 360 mRecorder.setOutputFormat(outFormat); 361 Log.v(TAG, "output format " + outFormat); 362 mRecorder.setOutputFile(outFile); 363 mRecorder.setVideoFrameRate(frameRate); 364 mRecorder.setVideoSize(width, height); 365 Log.v(TAG, "setEncoder"); 366 mRecorder.setVideoEncoder(videoFormat); 367 if (!videoOnly) { 368 mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); 369 } 370 mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder(); 371 Log.v(TAG, "setPreview"); 372 mRecorder.setPreviewDisplay(mSurfaceHolder.getSurface()); 373 Log.v(TAG, "prepare"); 374 mRecorder.prepare(); 375 Log.v(TAG, "start"); 376 mRecorder.start(); 377 Thread.sleep(MediaNames.RECORDED_TIME); 378 Log.v(TAG, "stop"); 379 mRecorder.stop(); 380 mRecorder.release(); 381 } catch (Exception e) { 382 Log.v("record video failed ", e.toString()); 383 mRecorder.release(); 384 Log.v(TAG, "reset and release"); 385 return true; 386 } 387 return false; 388 } 389 390 private void getOutputVideoProperty(String outputFilePath) { 391 MediaPlayer mediaPlayer = new MediaPlayer(); 392 try { 393 mediaPlayer.setDataSource(outputFilePath); 394 Log.v(TAG, "file Path = " + outputFilePath); 395 mediaPlayer.setDisplay(MediaFrameworkTest.mSurfaceView.getHolder()); 396 Log.v(TAG, "before player prepare"); 397 mediaPlayer.prepare(); 398 Log.v(TAG, "before getduration"); 399 mOutputDuration = mediaPlayer.getDuration(); 400 Log.v(TAG, "get video dimension"); 401 Thread.sleep(1000); 402 mOutputVideoHeight = mediaPlayer.getVideoHeight(); 403 mOutputVideoWidth = mediaPlayer.getVideoWidth(); 404 mediaPlayer.release(); 405 } catch (Exception e) { 406 Log.v(TAG, e.toString()); 407 mediaPlayer.release(); 408 } 409 } 410 411 private boolean validateVideo(String filePath, int width, int height) { 412 boolean validVideo = false; 413 getOutputVideoProperty(filePath); 414 if (mOutputVideoWidth == width && mOutputVideoHeight == height && 415 mOutputDuration > MediaNames.VALID_VIDEO_DURATION ) { 416 validVideo = true; 417 } 418 Log.v(TAG, "width = " + mOutputVideoWidth + " height = " + mOutputVideoHeight + " Duration = " + mOutputDuration); 419 return validVideo; 420 } 421 422 @LargeTest 423 /* 424 * This test case set the camera in portrait mode. 425 * Verification: validate the video dimension and the duration. 426 */ 427 public void testPortraitH263() throws Exception { 428 boolean videoRecordedResult = false; 429 try { 430 mCamera = Camera.open(CAMERA_ID); 431 Camera.Parameters parameters = mCamera.getParameters(); 432 parameters.setPreviewSize(352, 288); 433 parameters.set("orientation", "portrait"); 434 mCamera.setParameters(parameters); 435 mCamera.unlock(); 436 mRecorder.setCamera(mCamera); 437 Thread.sleep(1000); 438 int codec = MediaRecorder.VideoEncoder.H263; 439 int frameRate = MediaProfileReader.getMaxFrameRateForCodec(codec); 440 recordVideo(frameRate, 352, 288, codec, 441 MediaRecorder.OutputFormat.THREE_GPP, 442 MediaNames.RECORDED_PORTRAIT_H263, true); 443 mCamera.lock(); 444 mCamera.release(); 445 videoRecordedResult = 446 validateVideo(MediaNames.RECORDED_PORTRAIT_H263, 352, 288); 447 } catch (Exception e) { 448 Log.v(TAG, e.toString()); 449 } 450 assertTrue("PortraitH263", videoRecordedResult); 451 } 452 453 @LargeTest 454 public void testInvalidVideoPath() throws Exception { 455 boolean isTestInvalidVideoPathSuccessful = false; 456 isTestInvalidVideoPathSuccessful = invalidRecordSetting(15, 176, 144, MediaRecorder.VideoEncoder.H263, 457 MediaRecorder.OutputFormat.THREE_GPP, MediaNames.INVALD_VIDEO_PATH, false); 458 assertTrue("Invalid outputFile Path", isTestInvalidVideoPathSuccessful); 459 } 460 461 @LargeTest 462 //test cases for the new codec 463 public void testDeviceSpecificCodec() throws Exception { 464 int noOfFailure = 0; 465 boolean recordSuccess = false; 466 String deviceType = MediaProfileReader.getDeviceType(); 467 Log.v(TAG, "deviceType = " + deviceType); 468 List<VideoEncoderCap> videoEncoders = MediaProfileReader.getVideoEncoders(); 469 List<AudioEncoderCap> audioEncoders = MediaProfileReader.getAudioEncoders(); 470 for (int k = 0; k < 2; k++) { 471 for (VideoEncoderCap videoEncoder: videoEncoders) { 472 for (AudioEncoderCap audioEncoder: audioEncoders) { 473 if (k == 0) { 474 recordSuccess = recordVideoWithPara(videoEncoder, audioEncoder, true); 475 } else { 476 recordSuccess = recordVideoWithPara(videoEncoder, audioEncoder, false); 477 } 478 if (!recordSuccess) { 479 Log.v(TAG, "testDeviceSpecificCodec failed"); 480 Log.v(TAG, "Encoder = " + videoEncoder.mCodec + "Audio Encoder = " + audioEncoder.mCodec); 481 noOfFailure++; 482 } 483 } 484 } 485 } 486 if (noOfFailure != 0) { 487 assertTrue("testDeviceSpecificCodec", false); 488 } 489 } 490 491 // Test MediaRecorder.getSurface() api with surface or camera source 492 public void testGetSurfaceApi() { 493 boolean success = false; 494 int noOfFailure = 0; 495 try { 496 for (int k = 0; k < 2; k++) { 497 success = validateGetSurface( 498 k == 0 ? true : false /* useSurface */); 499 if (!success) { 500 noOfFailure++; 501 } 502 } 503 } catch (Exception e) { 504 Log.v(TAG, e.toString()); 505 } 506 assertTrue("testGetSurfaceApi", noOfFailure == 0); 507 } 508 509 // Test recording from surface source with/without audio 510 public void testSurfaceRecording() { 511 boolean success = false; 512 int noOfFailure = 0; 513 try { 514 int codec = MediaRecorder.VideoEncoder.H264; 515 int frameRate = MediaProfileReader.getMaxFrameRateForCodec(codec); 516 for (int k = 0; k < 2; k++) { 517 String filename = "/sdcard/surface_" + 518 (k==0?"video_only":"with_audio") + ".3gp"; 519 520 success = recordVideoFromSurface(frameRate, 352, 288, codec, 521 MediaRecorder.OutputFormat.THREE_GPP, filename, 522 k == 0 ? true : false /* videoOnly */); 523 if (success) { 524 success = validateVideo(filename, 352, 288); 525 } 526 if (!success) { 527 noOfFailure++; 528 } 529 } 530 } catch (Exception e) { 531 Log.v(TAG, e.toString()); 532 } 533 assertTrue("testSurfaceRecording", noOfFailure == 0); 534 } 535} 536