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