/* * Copyright (C) 2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package com.android.mediaframeworktest.performance; import com.android.mediaframeworktest.MediaFrameworkTest; import com.android.mediaframeworktest.MediaNames; import android.database.sqlite.SQLiteDatabase; import android.media.MediaPlayer; import android.media.MediaRecorder; import android.os.SystemClock; import android.test.ActivityInstrumentationTestCase; import android.test.suitebuilder.annotation.LargeTest; import android.test.suitebuilder.annotation.Suppress; import android.util.Log; import android.view.SurfaceHolder; import java.io.FileDescriptor; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.Writer; import java.io.File; import java.io.FileWriter; import java.io.BufferedWriter; import android.media.MediaMetadataRetriever; /** * Junit / Instrumentation - performance measurement for media player and * recorder */ public class MediaPlayerPerformance extends ActivityInstrumentationTestCase<MediaFrameworkTest> { private String TAG = "MediaFrameworkPerformance"; private SQLiteDatabase mDB; private SurfaceHolder mSurfaceHolder = null; private static final int NUM_STRESS_LOOP = 10; private static final int NUM_PLAYBACk_IN_EACH_LOOP = 20; private static final long MEDIA_STRESS_WAIT_TIME = 5000; //5 seconds private static final String H263_VIDEO_PLAYBACK_MEMOUT = "/sdcard/h263VideoPlaybackMemOut.txt"; private static final String H264_VIDEO_PLAYBACK_MEMOUT = "/sdcard/h264VideoPlaybackMemOut.txt"; private static final String WMV_VIDEO_PLAYBACK_MEMOUT = "/sdcard/WmvVideoPlaybackMemOut.txt"; private static final String H263_VIDEO_ONLY_RECORD_MEMOUT = "/sdcard/recordH263VideoOnlyMemOut.txt"; private static final String MP4_VIDEO_ONLY_RECORD_MEMOUT = "/sdcard/recordMPEG4VideoOnlyMemOut.txt"; private static final String H263_VIDEO_AUDIO_RECORD_MEMOUT = "/sdcard/recordVideoH263AudioMemOut.txt"; private static final String AUDIO_ONLY_RECORD_MEMOUT = "/sdcard/recordAudioOnlyMemOut.txt"; public MediaPlayerPerformance() { super("com.android.mediaframeworktest", MediaFrameworkTest.class); } protected void setUp() throws Exception { super.setUp(); } public void createDB() { mDB = SQLiteDatabase.openOrCreateDatabase("/sdcard/perf.db", null); mDB.execSQL("CREATE TABLE perfdata (_id INTEGER PRIMARY KEY," + "file TEXT," + "setdatatime LONG," + "preparetime LONG," + "playtime LONG" + ");"); } public void audioPlaybackStartupTime(String[] testFile) { long t1 = 0; long t2 = 0; long t3 = 0; long t4 = 0; long setDataSourceDuration = 0; long prepareDuration = 0; long startDuration = 0; long totalSetDataTime = 0; long totalPrepareTime = 0; long totalStartDuration = 0; int numberOfFiles = testFile.length; Log.v(TAG, "File length " + numberOfFiles); for (int k = 0; k < numberOfFiles; k++) { MediaPlayer mp = new MediaPlayer(); try { t1 = SystemClock.uptimeMillis(); FileInputStream fis = new FileInputStream(testFile[k]); FileDescriptor fd = fis.getFD(); mp.setDataSource(fd); fis.close(); t2 = SystemClock.uptimeMillis(); mp.prepare(); t3 = SystemClock.uptimeMillis(); mp.start(); t4 = SystemClock.uptimeMillis(); } catch (Exception e) { Log.v(TAG, e.toString()); } setDataSourceDuration = t2 - t1; prepareDuration = t3 - t2; startDuration = t4 - t3; totalSetDataTime = totalSetDataTime + setDataSourceDuration; totalPrepareTime = totalPrepareTime + prepareDuration; totalStartDuration = totalStartDuration + startDuration; mDB.execSQL("INSERT INTO perfdata (file, setdatatime, preparetime," + " playtime) VALUES (" + '"' + testFile[k] + '"' + ',' + setDataSourceDuration + ',' + prepareDuration + ',' + startDuration + ");"); Log.v(TAG, "File name " + testFile[k]); mp.stop(); mp.release(); } Log.v(TAG, "setDataSource average " + totalSetDataTime / numberOfFiles); Log.v(TAG, "prepare average " + totalPrepareTime / numberOfFiles); Log.v(TAG, "start average " + totalStartDuration / numberOfFiles); } @Suppress public void testStartUpTime() throws Exception { createDB(); audioPlaybackStartupTime(MediaNames.MP3FILES); audioPlaybackStartupTime(MediaNames.AACFILES); } public void wmametadatautility(String[] testFile) { long t1 = 0; long t2 = 0; long sum = 0; long duration = 0; MediaMetadataRetriever retriever = new MediaMetadataRetriever(); String value; for (int i = 0, n = testFile.length; i < n; ++i) { try { t1 = SystemClock.uptimeMillis(); retriever.setDataSource(testFile[i]); value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUM); value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST); value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_COMPOSER); value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_GENRE); value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE); value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_YEAR); value = retriever .extractMetadata(MediaMetadataRetriever.METADATA_KEY_CD_TRACK_NUMBER); t2 = SystemClock.uptimeMillis(); duration = t2 - t1; Log.v(TAG, "Time taken = " + duration); sum = sum + duration; } catch (Exception e) { Log.v(TAG, e.getMessage()); } } Log.v(TAG, "Average duration = " + sum / testFile.length); } // Note: This test is to assume the mediaserver's pid is 34 public void mediaStressPlayback(String testFilePath) { for (int i = 0; i < NUM_PLAYBACk_IN_EACH_LOOP; i++) { MediaPlayer mp = new MediaPlayer(); try { mp.setDataSource(testFilePath); mp.setDisplay(MediaFrameworkTest.mSurfaceView.getHolder()); mp.prepare(); mp.start(); Thread.sleep(MEDIA_STRESS_WAIT_TIME); mp.release(); } catch (Exception e) { mp.release(); Log.v(TAG, e.toString()); } } } // Note: This test is to assume the mediaserver's pid is 34 private void stressVideoRecord(int frameRate, int width, int height, int videoFormat, int outFormat, String outFile, boolean videoOnly) { // Video recording for (int i = 0; i < NUM_PLAYBACk_IN_EACH_LOOP; i++) { MediaRecorder mRecorder = new MediaRecorder(); try { if (!videoOnly) { Log.v(TAG, "setAudioSource"); mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); } mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); mRecorder.setOutputFormat(outFormat); Log.v(TAG, "output format " + outFormat); mRecorder.setOutputFile(outFile); mRecorder.setVideoFrameRate(frameRate); mRecorder.setVideoSize(width, height); Log.v(TAG, "setEncoder"); mRecorder.setVideoEncoder(videoFormat); if (!videoOnly) { mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); } mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder(); mRecorder.setPreviewDisplay(mSurfaceHolder.getSurface()); mRecorder.prepare(); mRecorder.start(); Thread.sleep(MEDIA_STRESS_WAIT_TIME); mRecorder.stop(); mRecorder.release(); } catch (Exception e) { Log.v("record video failed ", e.toString()); mRecorder.release(); } } } public void stressAudioRecord(String filePath) { // This test is only for the short media file for (int i = 0; i < NUM_PLAYBACk_IN_EACH_LOOP; i++) { MediaRecorder mRecorder = new MediaRecorder(); try { mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); mRecorder.setOutputFile(filePath); mRecorder.prepare(); mRecorder.start(); Thread.sleep(MEDIA_STRESS_WAIT_TIME); mRecorder.stop(); mRecorder.release(); } catch (Exception e) { Log.v(TAG, e.toString()); mRecorder.release(); } } } //Write the ps output to the file public void getMemoryWriteToLog(Writer output) { String cm = "ps mediaserver"; String memoryUsage = null; int ch; try { Process p = Runtime.getRuntime().exec(cm); InputStream in = p.getInputStream(); StringBuffer sb = new StringBuffer(512); while ((ch = in.read()) != -1) { sb.append((char) ch); } memoryUsage = sb.toString(); } catch (IOException e) { Log.v(TAG, e.toString()); } String[] poList = memoryUsage.split("\r|\n|\r\n"); String memusage = poList[1].concat("\n"); Log.v(TAG, memusage); try { //Write to file output output.write(memusage); } catch (Exception e) { e.toString(); } } @Suppress public void testWmaParseTime() throws Exception { // createDB(); wmametadatautility(MediaNames.WMASUPPORTED); } // Test case 1: Capture the memory usage after every 20 h263 playback @LargeTest public void testH263VideoPlaybackMemoryUsage() throws Exception { File h263MemoryOut = new File(H263_VIDEO_PLAYBACK_MEMOUT); Writer output = new BufferedWriter(new FileWriter(h263MemoryOut)); for (int i = 0; i < NUM_STRESS_LOOP; i++) { mediaStressPlayback(MediaNames.VIDEO_HIGHRES_H263); getMemoryWriteToLog(output); } output.close(); } // Test case 2: Capture the memory usage after every 20 h264 playback @LargeTest public void testH264VideoPlaybackMemoryUsage() throws Exception { File h264MemoryOut = new File(H264_VIDEO_PLAYBACK_MEMOUT); Writer output = new BufferedWriter(new FileWriter(h264MemoryOut)); for (int i = 0; i < NUM_STRESS_LOOP; i++) { mediaStressPlayback(MediaNames.VIDEO_H264_AMR); getMemoryWriteToLog(output); } output.close(); } // Test case 3: Capture the memory usage after each 20 WMV playback @LargeTest public void testWMVVideoPlaybackMemoryUsage() throws Exception { File wmvMemoryOut = new File(WMV_VIDEO_PLAYBACK_MEMOUT); Writer output = new BufferedWriter(new FileWriter(wmvMemoryOut)); for (int i = 0; i < NUM_STRESS_LOOP; i++) { mediaStressPlayback(MediaNames.VIDEO_WMV); getMemoryWriteToLog(output); } output.close(); } // Test case 4: Capture the memory usage after every 20 video only recorded @LargeTest public void testH263RecordVideoOnlyMemoryUsage() throws Exception { File videoH263RecordOnlyMemoryOut = new File(H263_VIDEO_ONLY_RECORD_MEMOUT); Writer output = new BufferedWriter(new FileWriter(videoH263RecordOnlyMemoryOut)); for (int i = 0; i < NUM_STRESS_LOOP; i++) { stressVideoRecord(20, 352, 288, MediaRecorder.VideoEncoder.H263, MediaRecorder.OutputFormat.MPEG_4, MediaNames.RECORDED_VIDEO_3GP, true); getMemoryWriteToLog(output); } output.close(); } // Test case 5: Capture the memory usage after every 20 video only recorded @LargeTest public void testMpeg4RecordVideoOnlyMemoryUsage() throws Exception { File videoMp4RecordOnlyMemoryOut = new File(MP4_VIDEO_ONLY_RECORD_MEMOUT); Writer output = new BufferedWriter(new FileWriter(videoMp4RecordOnlyMemoryOut)); for (int i = 0; i < NUM_STRESS_LOOP; i++) { stressVideoRecord(20, 352, 288, MediaRecorder.VideoEncoder.MPEG_4_SP, MediaRecorder.OutputFormat.MPEG_4, MediaNames.RECORDED_VIDEO_3GP, true); getMemoryWriteToLog(output); } output.close(); } // Test case 6: Capture the memory usage after every 20 video and audio recorded @LargeTest public void testRecordVidedAudioMemoryUsage() throws Exception { File videoRecordAudioMemoryOut = new File(H263_VIDEO_AUDIO_RECORD_MEMOUT); Writer output = new BufferedWriter(new FileWriter(videoRecordAudioMemoryOut)); for (int i = 0; i < NUM_STRESS_LOOP; i++) { stressVideoRecord(20, 352, 288, MediaRecorder.VideoEncoder.H263, MediaRecorder.OutputFormat.MPEG_4, MediaNames.RECORDED_VIDEO_3GP, false); getMemoryWriteToLog(output); } output.close(); } // Test case 7: Capture the memory usage after every 20 audio only recorded @LargeTest public void testRecordAudioOnlyMemoryUsage() throws Exception { File audioOnlyMemoryOut = new File(AUDIO_ONLY_RECORD_MEMOUT); Writer output = new BufferedWriter(new FileWriter(audioOnlyMemoryOut)); for (int i = 0; i < NUM_STRESS_LOOP; i++) { stressAudioRecord(MediaNames.RECORDER_OUTPUT); getMemoryWriteToLog(output); } output.close(); } }