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