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