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