MediaPlayerPerformance.java revision a74603052b525e7c8709ffc3b618af0a8b140f0b
1/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 * use this file except in compliance with the License. You may obtain a copy of
6 * 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, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations under
14 * the License.
15 */
16
17package com.android.mediaframeworktest.performance;
18
19import com.android.mediaframeworktest.MediaFrameworkTest;
20import com.android.mediaframeworktest.MediaNames;
21
22import android.database.sqlite.SQLiteDatabase;
23import android.media.MediaPlayer;
24import android.media.MediaRecorder;
25import android.os.SystemClock;
26import android.test.ActivityInstrumentationTestCase;
27import android.test.suitebuilder.annotation.LargeTest;
28import android.test.suitebuilder.annotation.Suppress;
29import android.util.Log;
30import android.view.SurfaceHolder;
31
32import java.io.FileDescriptor;
33import java.io.FileInputStream;
34import java.io.FileOutputStream;
35import java.io.IOException;
36import java.io.InputStream;
37import java.io.Writer;
38import java.io.File;
39import java.io.FileWriter;
40import java.io.BufferedWriter;
41
42import android.media.MediaMetadataRetriever;
43
44/**
45 * Junit / Instrumentation - performance measurement for media player and
46 * recorder
47 */
48public class MediaPlayerPerformance extends ActivityInstrumentationTestCase<MediaFrameworkTest> {
49
50    private String TAG = "MediaFrameworkPerformance";
51
52    private SQLiteDatabase mDB;
53    private SurfaceHolder mSurfaceHolder = null;
54    private static final int NUM_STRESS_LOOP = 1;
55    private static final int NUM_PLAYBACk_IN_EACH_LOOP = 2;
56    private static final long MEDIA_STRESS_WAIT_TIME = 5000; //5 seconds
57    private static final String MEDIA_MEMORY_OUTPUT =
58        "/sdcard/mediaMemOutput.txt";
59
60    //the tolerant memory leak
61    private static final int MAX_ACCEPTED_MEMORY_LEAK_KB = 150;
62
63    private static int mStartMemory = 0;
64    private static int mEndMemory = 0;
65    private static int mStartPid = 0;
66    private static int mEndPid = 0;
67
68
69    public MediaPlayerPerformance() {
70        super("com.android.mediaframeworktest", MediaFrameworkTest.class);
71    }
72
73    protected void setUp() throws Exception {
74        super.setUp();
75    }
76
77    public void createDB() {
78        mDB = SQLiteDatabase.openOrCreateDatabase("/sdcard/perf.db", null);
79        mDB.execSQL("CREATE TABLE perfdata (_id INTEGER PRIMARY KEY," +
80                "file TEXT," + "setdatatime LONG," + "preparetime LONG," +
81                "playtime LONG" + ");");
82    }
83
84    public void audioPlaybackStartupTime(String[] testFile) {
85        long t1 = 0;
86        long t2 = 0;
87        long t3 = 0;
88        long t4 = 0;
89        long setDataSourceDuration = 0;
90        long prepareDuration = 0;
91        long startDuration = 0;
92        long totalSetDataTime = 0;
93        long totalPrepareTime = 0;
94        long totalStartDuration = 0;
95
96        int numberOfFiles = testFile.length;
97        Log.v(TAG, "File length " + numberOfFiles);
98        for (int k = 0; k < numberOfFiles; k++) {
99            MediaPlayer mp = new MediaPlayer();
100            try {
101                t1 = SystemClock.uptimeMillis();
102                FileInputStream fis = new FileInputStream(testFile[k]);
103                FileDescriptor fd = fis.getFD();
104                mp.setDataSource(fd);
105                fis.close();
106                t2 = SystemClock.uptimeMillis();
107                mp.prepare();
108                t3 = SystemClock.uptimeMillis();
109                mp.start();
110                t4 = SystemClock.uptimeMillis();
111            } catch (Exception e) {
112                Log.v(TAG, e.toString());
113            }
114            setDataSourceDuration = t2 - t1;
115            prepareDuration = t3 - t2;
116            startDuration = t4 - t3;
117            totalSetDataTime = totalSetDataTime + setDataSourceDuration;
118            totalPrepareTime = totalPrepareTime + prepareDuration;
119            totalStartDuration = totalStartDuration + startDuration;
120            mDB.execSQL("INSERT INTO perfdata (file, setdatatime, preparetime," +
121                    " playtime) VALUES (" + '"' + testFile[k] + '"' + ',' +
122                    setDataSourceDuration + ',' + prepareDuration +
123            		',' + startDuration + ");");
124            Log.v(TAG, "File name " + testFile[k]);
125            mp.stop();
126            mp.release();
127        }
128        Log.v(TAG, "setDataSource average " + totalSetDataTime / numberOfFiles);
129        Log.v(TAG, "prepare average " + totalPrepareTime / numberOfFiles);
130        Log.v(TAG, "start average " + totalStartDuration / numberOfFiles);
131
132    }
133
134    @Suppress
135    public void testStartUpTime() throws Exception {
136        createDB();
137        audioPlaybackStartupTime(MediaNames.MP3FILES);
138        audioPlaybackStartupTime(MediaNames.AACFILES);
139
140    }
141
142    public void wmametadatautility(String[] testFile) {
143        long t1 = 0;
144        long t2 = 0;
145        long sum = 0;
146        long duration = 0;
147        MediaMetadataRetriever retriever = new MediaMetadataRetriever();
148        String value;
149        for (int i = 0, n = testFile.length; i < n; ++i) {
150            try {
151                t1 = SystemClock.uptimeMillis();
152                retriever.setDataSource(testFile[i]);
153                value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUM);
154                value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST);
155                value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_COMPOSER);
156                value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_GENRE);
157                value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE);
158                value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_YEAR);
159                value =
160                    retriever
161                    .extractMetadata(MediaMetadataRetriever.METADATA_KEY_CD_TRACK_NUMBER);
162                t2 = SystemClock.uptimeMillis();
163                duration = t2 - t1;
164                Log.v(TAG, "Time taken = " + duration);
165                sum = sum + duration;
166            } catch (Exception e) {
167                Log.v(TAG, e.getMessage());
168            }
169
170        }
171        Log.v(TAG, "Average duration = " + sum / testFile.length);
172    }
173
174
175    // Note: This test is to assume the mediaserver's pid is 34
176    public void mediaStressPlayback(String testFilePath) {
177        for (int i = 0; i < NUM_PLAYBACk_IN_EACH_LOOP; i++) {
178            MediaPlayer mp = new MediaPlayer();
179            try {
180                mp.setDataSource(testFilePath);
181                mp.setDisplay(MediaFrameworkTest.mSurfaceView.getHolder());
182                mp.prepare();
183                mp.start();
184                Thread.sleep(MEDIA_STRESS_WAIT_TIME);
185                mp.release();
186            } catch (Exception e) {
187                mp.release();
188                Log.v(TAG, e.toString());
189            }
190        }
191    }
192
193    // Note: This test is to assume the mediaserver's pid is 34
194    private void stressVideoRecord(int frameRate, int width, int height, int videoFormat,
195            int outFormat, String outFile, boolean videoOnly) {
196        // Video recording
197        for (int i = 0; i < NUM_PLAYBACk_IN_EACH_LOOP; i++) {
198            MediaRecorder mRecorder = new MediaRecorder();
199            try {
200                if (!videoOnly) {
201                    Log.v(TAG, "setAudioSource");
202                    mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
203                }
204                mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
205                mRecorder.setOutputFormat(outFormat);
206                Log.v(TAG, "output format " + outFormat);
207                mRecorder.setOutputFile(outFile);
208                mRecorder.setVideoFrameRate(frameRate);
209                mRecorder.setVideoSize(width, height);
210                Log.v(TAG, "setEncoder");
211                mRecorder.setVideoEncoder(videoFormat);
212                if (!videoOnly) {
213                    mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
214                }
215                mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
216                mRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
217                mRecorder.prepare();
218                mRecorder.start();
219                Thread.sleep(MEDIA_STRESS_WAIT_TIME);
220                mRecorder.stop();
221                mRecorder.release();
222            } catch (Exception e) {
223                Log.v("record video failed ", e.toString());
224                mRecorder.release();
225            }
226        }
227    }
228
229    public void stressAudioRecord(String filePath) {
230        // This test is only for the short media file
231        for (int i = 0; i < NUM_PLAYBACk_IN_EACH_LOOP; i++) {
232            MediaRecorder mRecorder = new MediaRecorder();
233            try {
234                mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
235                mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
236                mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
237                mRecorder.setOutputFile(filePath);
238                mRecorder.prepare();
239                mRecorder.start();
240                Thread.sleep(MEDIA_STRESS_WAIT_TIME);
241                mRecorder.stop();
242                mRecorder.release();
243            } catch (Exception e) {
244                Log.v(TAG, e.toString());
245                mRecorder.release();
246            }
247        }
248    }
249
250    //Write the ps output to the file
251    public void getMemoryWriteToLog(Writer output) {
252        String memusage = null;
253        memusage = captureMediaserverInfo();
254        Log.v(TAG, memusage);
255        try {
256            //Write to file output
257            output.write(memusage);
258        } catch (Exception e) {
259            e.toString();
260        }
261    }
262
263    public String captureMediaserverInfo() {
264        String cm = "ps mediaserver";
265        String memoryUsage = null;
266
267        int ch;
268        try {
269            Process p = Runtime.getRuntime().exec(cm);
270            InputStream in = p.getInputStream();
271            StringBuffer sb = new StringBuffer(512);
272            while ((ch = in.read()) != -1) {
273                sb.append((char) ch);
274            }
275            memoryUsage = sb.toString();
276        } catch (IOException e) {
277            Log.v(TAG, e.toString());
278        }
279        String[] poList = memoryUsage.split("\r|\n|\r\n");
280        String memusage = poList[1].concat("\n");
281        return memusage;
282    }
283
284    public int getMediaserverPid(){
285        String memoryUsage = null;
286        int pidvalue = 0;
287        memoryUsage = captureMediaserverInfo();
288        String[] poList2 = memoryUsage.split("\t|\\s+");
289        String pid = poList2[1];
290        pidvalue = Integer.parseInt(pid);
291        Log.v(TAG, "PID = " + pidvalue);
292        return pidvalue;
293    }
294
295    public int getMediaserverVsize(){
296        String memoryUsage = captureMediaserverInfo();
297        String[] poList2 = memoryUsage.split("\t|\\s+");
298        String vsize = poList2[3];
299        int vsizevalue = Integer.parseInt(vsize);
300        Log.v(TAG, "VSIZE = " + vsizevalue);
301        return vsizevalue;
302    }
303
304    public boolean validateMemoryResult (int startPid, int startMemory, Writer output) throws Exception {
305        mEndPid = getMediaserverPid();
306        mEndMemory = getMediaserverVsize();
307
308        //Write the total memory different into the output file
309        output.write("The total diff = " + (mEndMemory - startMemory));
310        output.write("\n\n");
311        //mediaserver crash
312        if (startPid != mEndPid){
313            output.write("mediaserver died. Test failed\n");
314            return false;
315        }
316        //memory leak greter than the tolerant
317        if ((mEndMemory - startMemory) > MAX_ACCEPTED_MEMORY_LEAK_KB )
318            return false;
319        return true;
320    }
321
322    @Suppress
323    public void testWmaParseTime() throws Exception {
324        // createDB();
325        wmametadatautility(MediaNames.WMASUPPORTED);
326    }
327
328
329    // Test case 1: Capture the memory usage after every 20 h263 playback
330    @LargeTest
331    public void testH263VideoPlaybackMemoryUsage() throws Exception {
332        boolean memoryResult = false;
333        mStartPid = getMediaserverPid();
334        mStartMemory = getMediaserverVsize();
335
336        File h263MemoryOut = new File(MEDIA_MEMORY_OUTPUT);
337        Writer output = new BufferedWriter(new FileWriter(h263MemoryOut, true));
338        output.write("H263 Video Playback Only\n");
339        getMemoryWriteToLog(output);
340        for (int i = 0; i < NUM_STRESS_LOOP; i++) {
341            mediaStressPlayback(MediaNames.VIDEO_HIGHRES_H263);
342            getMemoryWriteToLog(output);
343        }
344        output.write("\n");
345        memoryResult = validateMemoryResult(mStartPid, mStartMemory, output);
346        output.close();
347        assertTrue("H263 playback memory test", memoryResult);
348    }
349
350    // Test case 2: Capture the memory usage after every 20 h264 playback
351    @LargeTest
352    public void testH264VideoPlaybackMemoryUsage() throws Exception {
353        boolean memoryResult = false;
354        mStartPid = getMediaserverPid();
355        mStartMemory = getMediaserverVsize();
356
357        File h264MemoryOut = new File(MEDIA_MEMORY_OUTPUT);
358        Writer output = new BufferedWriter(new FileWriter(h264MemoryOut, true));
359        output.write("H264 Video Playback only\n");
360        getMemoryWriteToLog(output);
361        for (int i = 0; i < NUM_STRESS_LOOP; i++) {
362            mediaStressPlayback(MediaNames.VIDEO_H264_AMR);
363            getMemoryWriteToLog(output);
364        }
365        output.write("\n");
366        memoryResult = validateMemoryResult(mStartPid, mStartMemory, output);
367        output.close();
368        assertTrue("H264 playback memory test", memoryResult);
369    }
370
371    // Test case 3: Capture the memory usage after each 20 WMV playback
372    @LargeTest
373    public void testWMVVideoPlaybackMemoryUsage() throws Exception {
374        boolean memoryResult = false;
375        mStartPid = getMediaserverPid();
376        mStartMemory = getMediaserverVsize();
377
378        File wmvMemoryOut = new File(MEDIA_MEMORY_OUTPUT);
379        Writer output = new BufferedWriter(new FileWriter(wmvMemoryOut, true));
380        output.write("WMV video playback only\n");
381        getMemoryWriteToLog(output);
382        for (int i = 0; i < NUM_STRESS_LOOP; i++) {
383            mediaStressPlayback(MediaNames.VIDEO_WMV);
384            getMemoryWriteToLog(output);
385        }
386        output.write("\n");
387        memoryResult = validateMemoryResult(mStartPid, mStartMemory, output);
388        output.close();
389        assertTrue("wmv playback memory test", memoryResult);
390    }
391
392    // Test case 4: Capture the memory usage after every 20 video only recorded
393    @LargeTest
394    public void testH263RecordVideoOnlyMemoryUsage() throws Exception {
395        boolean memoryResult = false;
396        mStartPid = getMediaserverPid();
397        mStartMemory = getMediaserverVsize();
398
399        File videoH263RecordOnlyMemoryOut = new File(MEDIA_MEMORY_OUTPUT);
400        Writer output = new BufferedWriter(new FileWriter(videoH263RecordOnlyMemoryOut, true));
401        output.write("H263 video record only\n");
402        getMemoryWriteToLog(output);
403        for (int i = 0; i < NUM_STRESS_LOOP; i++) {
404            stressVideoRecord(20, 352, 288, MediaRecorder.VideoEncoder.H263,
405                    MediaRecorder.OutputFormat.MPEG_4, MediaNames.RECORDED_VIDEO_3GP, true);
406            getMemoryWriteToLog(output);
407        }
408        output.write("\n");
409        memoryResult = validateMemoryResult(mStartPid, mStartMemory, output);
410        output.close();
411        assertTrue("H263 record only memory test", memoryResult);
412    }
413
414    // Test case 5: Capture the memory usage after every 20 video only recorded
415    @LargeTest
416    public void testMpeg4RecordVideoOnlyMemoryUsage() throws Exception {
417        boolean memoryResult = false;
418        mStartPid = getMediaserverPid();
419        mStartMemory = getMediaserverVsize();
420
421        File videoMp4RecordOnlyMemoryOut = new File(MEDIA_MEMORY_OUTPUT);
422        Writer output = new BufferedWriter(new FileWriter(videoMp4RecordOnlyMemoryOut, true));
423        output.write("MPEG4 video record only\n");
424        getMemoryWriteToLog(output);
425        for (int i = 0; i < NUM_STRESS_LOOP; i++) {
426            stressVideoRecord(20, 352, 288, MediaRecorder.VideoEncoder.MPEG_4_SP,
427                    MediaRecorder.OutputFormat.MPEG_4, MediaNames.RECORDED_VIDEO_3GP, true);
428            getMemoryWriteToLog(output);
429        }
430        output.write("\n");
431        memoryResult = validateMemoryResult(mStartPid, mStartMemory, output);
432        output.close();
433        assertTrue("mpeg4 record only memory test", memoryResult);
434    }
435
436    // Test case 6: Capture the memory usage after every 20 video and audio
437    // recorded
438    @LargeTest
439    public void testRecordVidedAudioMemoryUsage() throws Exception {
440        boolean memoryResult = false;
441        mStartPid = getMediaserverPid();
442        mStartMemory = getMediaserverVsize();
443
444        File videoRecordAudioMemoryOut = new File(MEDIA_MEMORY_OUTPUT);
445        Writer output = new BufferedWriter(new FileWriter(videoRecordAudioMemoryOut, true));
446        output.write("Audio and h263 video record\n");
447        getMemoryWriteToLog(output);
448        for (int i = 0; i < NUM_STRESS_LOOP; i++) {
449            stressVideoRecord(20, 352, 288, MediaRecorder.VideoEncoder.H263,
450                    MediaRecorder.OutputFormat.MPEG_4, MediaNames.RECORDED_VIDEO_3GP, false);
451            getMemoryWriteToLog(output);
452        }
453        output.write("\n");
454        memoryResult = validateMemoryResult(mStartPid, mStartMemory, output);
455        output.close();
456        assertTrue("H263 audio video record memory test", memoryResult);
457    }
458
459    // Test case 7: Capture the memory usage after every 20 audio only recorded
460    @LargeTest
461    public void testRecordAudioOnlyMemoryUsage() throws Exception {
462        boolean memoryResult = false;
463        mStartPid = getMediaserverPid();
464        mStartMemory = getMediaserverVsize();
465
466        File audioOnlyMemoryOut = new File(MEDIA_MEMORY_OUTPUT);
467        Writer output = new BufferedWriter(new FileWriter(audioOnlyMemoryOut, true));
468        output.write("Audio record only\n");
469        getMemoryWriteToLog(output);
470        for (int i = 0; i < NUM_STRESS_LOOP; i++) {
471            stressAudioRecord(MediaNames.RECORDER_OUTPUT);
472            getMemoryWriteToLog(output);
473        }
474        output.write("\n");
475        memoryResult = validateMemoryResult(mStartPid, mStartMemory, output);
476        output.close();
477        assertTrue("audio record only memory test", memoryResult);
478    }
479}
480