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