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