1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of 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, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.mediastress.cts; 18 19 import android.content.res.AssetFileDescriptor; 20 import android.graphics.Bitmap; 21 import android.graphics.BitmapFactory; 22 import android.media.MediaMetadataRetriever; 23 import android.media.MediaPlayer; 24 import android.media.MediaRecorder; 25 import android.os.Looper; 26 import android.os.SystemClock; 27 import android.util.Log; 28 29 import java.io.IOException; 30 import java.io.InputStream; 31 import java.util.concurrent.CountDownLatch; 32 import java.util.concurrent.TimeUnit; 33 34 /** 35 * Junit / Instrumentation test case for the media player api 36 */ 37 public class CodecTest { 38 private static String TAG = "CodecTest"; 39 private static MediaPlayer mMediaPlayer; 40 private MediaPlayer.OnPreparedListener mOnPreparedListener; 41 42 private static int WAIT_FOR_COMMAND_TO_COMPLETE = 60000; //1 min max. 43 private static boolean mInitialized = false; 44 private static boolean mPrepareReset = false; 45 private static Looper mLooper = null; 46 private static final Object mLock = new Object(); 47 private static final Object mPrepareDone = new Object(); 48 private static final Object mVideoSizeChanged = new Object(); 49 private static boolean mOnPrepareSuccess = false; 50 private static final long PAUSE_WAIT_TIME = 3000; 51 private static final long WAIT_TIME = 2000; 52 private static final int SEEK_TIME = 10000; 53 private static final int PLAYBACK_SETTLE_TIME_MS = 5000; 54 private static final int SETUP_SETTLE_TIME_MS = 5000; 55 56 public static CountDownLatch mFirstFrameLatch; 57 public static CountDownLatch mCompletionLatch; 58 public static boolean mOnCompleteSuccess = false; 59 public static boolean mPlaybackError = false; 60 61 public static int mMediaInfoUnknownCount = 0; 62 public static int mMediaInfoVideoTrackLaggingCount = 0; 63 public static int mMediaInfoBadInterleavingCount = 0; 64 public static int mMediaInfoNotSeekableCount = 0; 65 public static int mMediaInfoMetdataUpdateCount = 0; 66 printCpuInfo()67 public static String printCpuInfo() { 68 String cm = "dumpsys cpuinfo"; 69 String cpuinfo = null; 70 int ch; 71 try { 72 Process p = Runtime.getRuntime().exec(cm); 73 InputStream in = p.getInputStream(); 74 StringBuffer sb = new StringBuffer(512); 75 while ( ( ch = in.read() ) != -1 ) { 76 sb.append((char) ch); 77 } 78 cpuinfo = sb.toString(); 79 } catch (IOException e) { 80 Log.v(TAG, e.toString()); 81 } 82 return cpuinfo; 83 } 84 85 getDuration(String filePath)86 public static int getDuration(String filePath) { 87 Log.v(TAG, "getDuration - " + filePath); 88 MediaPlayer mp = new MediaPlayer(); 89 try { 90 mp.setDataSource(filePath); 91 mp.prepare(); 92 } catch (Exception e) { 93 Log.v(TAG, e.toString()); 94 } 95 int duration = mp.getDuration(); 96 Log.v(TAG, "Duration " + duration); 97 mp.release(); 98 Log.v(TAG, "release"); 99 return duration; 100 } 101 getCurrentPosition(String filePath)102 public static boolean getCurrentPosition(String filePath) { 103 Log.v(TAG, "GetCurrentPosition - " + filePath); 104 int currentPosition = 0; 105 long t1=0; 106 long t2 =0; 107 MediaPlayer mp = new MediaPlayer(); 108 try { 109 mp.setDataSource(filePath); 110 Log.v(TAG, "start playback"); 111 mp.prepare(); 112 mp.start(); 113 t1=SystemClock.uptimeMillis(); 114 Thread.sleep(10000); 115 mp.pause(); 116 Thread.sleep(PAUSE_WAIT_TIME); 117 t2=SystemClock.uptimeMillis(); 118 } catch (Exception e) { 119 Log.v(TAG, e.toString()); 120 } 121 currentPosition = mp.getCurrentPosition(); 122 mp.stop(); 123 mp.release(); 124 Log.v(TAG, "mp currentPositon = " + currentPosition + " play duration = " + (t2-t1)); 125 126 if ((currentPosition < ((t2-t1) *1.2)) && (currentPosition > 0)) 127 return true; 128 else 129 return false; 130 } 131 seekTo(String filePath)132 public static boolean seekTo(String filePath) { 133 Log.v(TAG, "seekTo " + filePath); 134 int currentPosition = 0; 135 MediaPlayer mp = new MediaPlayer(); 136 try { 137 mp.setDataSource(filePath); 138 mp.prepare(); 139 mp.start(); 140 mp.seekTo(SEEK_TIME); 141 Thread.sleep(WAIT_TIME); 142 currentPosition = mp.getCurrentPosition(); 143 } catch (Exception e) { 144 Log.v(TAG, e.getMessage()); 145 } 146 mp.stop(); 147 mp.release(); 148 Log.v(TAG, "CurrentPosition = " + currentPosition); 149 //The currentposition should be at least greater than the 80% of seek time 150 if ((currentPosition > SEEK_TIME *0.8)) 151 return true; 152 else 153 return false; 154 } 155 setLooping(String filePath)156 public static boolean setLooping(String filePath) { 157 int currentPosition = 0; 158 int duration = 0; 159 long t1 =0; 160 long t2 =0; 161 Log.v (TAG, "SetLooping - " + filePath); 162 MediaPlayer mp = new MediaPlayer(); 163 try { 164 mp.setDataSource(filePath); 165 mp.prepare(); 166 duration = mp.getDuration(); 167 Log.v(TAG, "setLooping duration " + duration); 168 mp.setLooping(true); 169 mp.start(); 170 Thread.sleep(5000); 171 mp.seekTo(duration - 5000); 172 t1=SystemClock.uptimeMillis(); 173 Thread.sleep(20000); 174 t2=SystemClock.uptimeMillis(); 175 Log.v(TAG, "pause"); 176 //Bug# 1106852 - IllegalStateException will be thrown if pause is called 177 //in here 178 //mp.pause(); 179 currentPosition = mp.getCurrentPosition(); 180 Log.v(TAG, "looping position " + currentPosition + "duration = " + (t2-t1)); 181 } catch (Exception e) { 182 Log.v(TAG, "Exception : " + e.toString()); 183 } 184 mp.stop(); 185 mp.release(); 186 //The current position should be within 20% of the sleep time 187 //and should be greater than zero. 188 if ((currentPosition < ((t2-t1-5000)*1.2)) && currentPosition > 0) 189 return true; 190 else 191 return false; 192 } 193 pause(String filePath)194 public static boolean pause(String filePath) throws Exception { 195 Log.v(TAG, "pause - " + filePath); 196 boolean misPlaying = true; 197 boolean pauseResult = false; 198 long t1=0; 199 long t2=0; 200 MediaPlayer mp = new MediaPlayer(); 201 mp.setDataSource(filePath); 202 mp.prepare(); 203 int duration = mp.getDuration(); 204 mp.start(); 205 t1=SystemClock.uptimeMillis(); 206 Thread.sleep(5000); 207 mp.pause(); 208 Thread.sleep(PAUSE_WAIT_TIME); 209 t2=SystemClock.uptimeMillis(); 210 misPlaying = mp.isPlaying(); 211 int curPosition = mp.getCurrentPosition(); 212 Log.v(TAG, filePath + " pause currentPositon " + curPosition); 213 Log.v(TAG, "isPlaying "+ misPlaying + " wait time " + (t2 - t1) ); 214 String cpuinfo = printCpuInfo(); 215 Log.v(TAG, cpuinfo); 216 if ((curPosition>0) && (curPosition < ((t2-t1) * 1.3)) && (misPlaying == false)) 217 pauseResult = true; 218 mp.stop(); 219 mp.release(); 220 return pauseResult; 221 } 222 prepareStopRelease(String filePath)223 public static void prepareStopRelease(String filePath) throws Exception { 224 Log.v(TAG, "prepareStopRelease" + filePath); 225 MediaPlayer mp = new MediaPlayer(); 226 mp.setDataSource(filePath); 227 mp.prepare(); 228 mp.stop(); 229 mp.release(); 230 } 231 preparePauseRelease(String filePath)232 public static void preparePauseRelease(String filePath) throws Exception { 233 Log.v(TAG, "preparePauseRelease" + filePath); 234 MediaPlayer mp = new MediaPlayer(); 235 mp.setDataSource(filePath); 236 mp.prepare(); 237 mp.pause(); 238 mp.release(); 239 } 240 241 static MediaPlayer.OnVideoSizeChangedListener mOnVideoSizeChangedListener = 242 new MediaPlayer.OnVideoSizeChangedListener() { 243 public void onVideoSizeChanged(MediaPlayer mp, int width, int height) { 244 synchronized (mVideoSizeChanged) { 245 Log.v(TAG, "sizechanged notification received ..."); 246 mVideoSizeChanged.notify(); 247 } 248 } 249 }; 250 251 //Register the videoSizeChanged listener videoHeight(String filePath)252 public static int videoHeight(String filePath) throws Exception { 253 Log.v(TAG, "videoHeight - " + filePath); 254 int videoHeight = 0; 255 synchronized (mLock) { 256 initializeMessageLooper(); 257 try { 258 mLock.wait(WAIT_FOR_COMMAND_TO_COMPLETE); 259 } catch(Exception e) { 260 Log.v(TAG, "looper was interrupted."); 261 return 0; 262 } 263 } 264 try { 265 mMediaPlayer.setDataSource(filePath); 266 mMediaPlayer.setDisplay(MediaFrameworkTest.getSurfaceView().getHolder()); 267 mMediaPlayer.setOnVideoSizeChangedListener(mOnVideoSizeChangedListener); 268 synchronized (mVideoSizeChanged) { 269 try { 270 mMediaPlayer.prepare(); 271 mMediaPlayer.start(); 272 mVideoSizeChanged.wait(WAIT_FOR_COMMAND_TO_COMPLETE); 273 } catch (Exception e) { 274 Log.v(TAG, "wait was interrupted"); 275 } 276 } 277 videoHeight = mMediaPlayer.getVideoHeight(); 278 terminateMessageLooper(); 279 } catch (Exception e) { 280 Log.e(TAG, e.getMessage()); 281 } 282 283 return videoHeight; 284 } 285 286 //Register the videoSizeChanged listener videoWidth(String filePath)287 public static int videoWidth(String filePath) throws Exception { 288 Log.v(TAG, "videoWidth - " + filePath); 289 int videoWidth = 0; 290 291 synchronized (mLock) { 292 initializeMessageLooper(); 293 try { 294 mLock.wait(WAIT_FOR_COMMAND_TO_COMPLETE); 295 } catch(Exception e) { 296 Log.v(TAG, "looper was interrupted."); 297 return 0; 298 } 299 } 300 try { 301 mMediaPlayer.setDataSource(filePath); 302 mMediaPlayer.setDisplay(MediaFrameworkTest.getSurfaceView().getHolder()); 303 mMediaPlayer.setOnVideoSizeChangedListener(mOnVideoSizeChangedListener); 304 synchronized (mVideoSizeChanged) { 305 try { 306 mMediaPlayer.prepare(); 307 mMediaPlayer.start(); 308 mVideoSizeChanged.wait(WAIT_FOR_COMMAND_TO_COMPLETE); 309 } catch (Exception e) { 310 Log.v(TAG, "wait was interrupted"); 311 } 312 } 313 videoWidth = mMediaPlayer.getVideoWidth(); 314 terminateMessageLooper(); 315 } catch (Exception e) { 316 Log.e(TAG, e.getMessage()); 317 } 318 return videoWidth; 319 } 320 321 //This also test the streaming video which may take a long 322 //time to start the playback. videoSeekTo(String filePath)323 public static boolean videoSeekTo(String filePath) throws Exception { 324 Log.v(TAG, "videoSeekTo - " + filePath); 325 int currentPosition = 0; 326 int duration = 0; 327 boolean videoResult = false; 328 MediaPlayer mp = new MediaPlayer(); 329 mp.setDataSource(filePath); 330 mp.setDisplay(MediaFrameworkTest.getSurfaceView().getHolder()); 331 mp.prepare(); 332 mp.start(); 333 334 Thread.sleep(5000); 335 duration = mp.getDuration(); 336 Log.v(TAG, "video duration " + duration); 337 mp.pause(); 338 Thread.sleep(PAUSE_WAIT_TIME); 339 mp.seekTo(duration - 20000 ); 340 mp.start(); 341 Thread.sleep(1000); 342 mp.pause(); 343 Thread.sleep(PAUSE_WAIT_TIME); 344 mp.seekTo(duration/2); 345 mp.start(); 346 Thread.sleep(10000); 347 currentPosition = mp.getCurrentPosition(); 348 Log.v(TAG, "video currentPosition " + currentPosition); 349 mp.release(); 350 if (currentPosition > (duration /2 )*0.9) 351 return true; 352 else 353 return false; 354 355 } 356 seekToEnd(String filePath)357 public static boolean seekToEnd(String filePath) { 358 Log.v(TAG, "seekToEnd - " + filePath); 359 int duration = 0; 360 int currentPosition = 0; 361 boolean isPlaying = false; 362 MediaPlayer mp = new MediaPlayer(); 363 try { 364 mp.setDataSource(filePath); 365 Log.v(TAG, "start playback"); 366 mp.prepare(); 367 duration = mp.getDuration(); 368 mp.seekTo(duration - 3000); 369 mp.start(); 370 Thread.sleep(6000); 371 } catch (Exception e) {} 372 isPlaying = mp.isPlaying(); 373 currentPosition = mp.getCurrentPosition(); 374 Log.v(TAG, "seekToEnd currentPosition= " + currentPosition + " isPlaying = " + isPlaying); 375 mp.stop(); 376 mp.release(); 377 Log.v(TAG, "duration = " + duration); 378 if (currentPosition < 0.9 * duration || isPlaying) 379 return false; 380 else 381 return true; 382 } 383 shortMediaStop(String filePath)384 public static boolean shortMediaStop(String filePath) { 385 Log.v(TAG, "shortMediaStop - " + filePath); 386 //This test is only for the short media file 387 int duration = 0; 388 int currentPosition = 0; 389 boolean isPlaying = false; 390 MediaPlayer mp = new MediaPlayer(); 391 try { 392 mp.setDataSource(filePath); 393 Log.v(TAG, "start playback"); 394 mp.prepare(); 395 duration = mp.getDuration(); 396 mp.start(); 397 Thread.sleep(10000); 398 } catch (Exception e) {} 399 isPlaying = mp.isPlaying(); 400 currentPosition = mp.getCurrentPosition(); 401 Log.v(TAG, "seekToEnd currentPosition= " + currentPosition + " isPlaying = " + isPlaying); 402 mp.stop(); 403 mp.release(); 404 Log.v(TAG, "duration = " + duration); 405 if (currentPosition > duration || isPlaying) 406 return false; 407 else 408 return true; 409 } 410 playToEnd(String filePath)411 public static boolean playToEnd(String filePath) { 412 Log.v(TAG, "shortMediaStop - " + filePath); 413 //This test is only for the short media file 414 int duration = 200000; 415 int updateDuration = 0; 416 int currentPosition = 0; 417 boolean isPlaying = false; 418 MediaPlayer mp = new MediaPlayer(); 419 try { 420 Thread.sleep(5000); 421 mp.setDataSource(filePath); 422 Log.v(TAG, "start playback"); 423 mp.prepare(); 424 //duration = mp.getDuration(); 425 mp.start(); 426 Thread.sleep(50000); 427 } catch (Exception e){} 428 isPlaying = mp.isPlaying(); 429 currentPosition = mp.getCurrentPosition(); 430 //updateDuration = mp.getDuration(); 431 Log.v(TAG, "seekToEnd currentPosition= " + currentPosition + " isPlaying = " + isPlaying); 432 mp.stop(); 433 mp.release(); 434 //Log.v(TAG, "duration = " + duration); 435 //Log.v(TAG, "Update duration = " + updateDuration); 436 if (currentPosition > duration || isPlaying) 437 return false; 438 else 439 return true; 440 } 441 seektoBeforeStart(String filePath)442 public static boolean seektoBeforeStart(String filePath){ 443 Log.v(TAG, "seektoBeforeStart - " + filePath); 444 //This test is only for the short media file 445 int duration = 0; 446 int currentPosition = 0; 447 448 MediaPlayer mp = new MediaPlayer(); 449 try { 450 mp.setDataSource(filePath); 451 mp.prepare(); 452 duration = mp.getDuration(); 453 mp.seekTo(duration - 10000); 454 mp.start(); 455 currentPosition=mp.getCurrentPosition(); 456 mp.stop(); 457 mp.release(); 458 } catch (Exception e) {} 459 if (currentPosition < duration/2) 460 return false; 461 else 462 return true; 463 } 464 mediaRecorderRecord(String filePath)465 public static boolean mediaRecorderRecord(String filePath){ 466 Log.v(TAG, "SoundRecording - " + filePath); 467 //This test is only for the short media file 468 int duration = 0; 469 try { 470 MediaRecorder mRecorder = new MediaRecorder(); 471 mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); 472 mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); 473 mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); 474 mRecorder.setOutputFile(filePath); 475 mRecorder.prepare(); 476 mRecorder.start(); 477 Thread.sleep(500); 478 mRecorder.stop(); 479 Log.v(TAG, "sound recorded"); 480 mRecorder.release(); 481 } catch (Exception e) { 482 Log.v(TAG, e.toString()); 483 } 484 485 //Verify the recorded file 486 MediaPlayer mp = new MediaPlayer(); 487 try { 488 mp.setDataSource(filePath); 489 mp.prepare(); 490 duration = mp.getDuration(); 491 Log.v(TAG,"Duration " + duration); 492 mp.release(); 493 } catch (Exception e) {} 494 //Check the record media file length is greate than zero 495 if (duration > 0) 496 return true; 497 else 498 return false; 499 500 } 501 502 //Test for mediaMeta Data Thumbnail getThumbnail(String filePath, String goldenPath)503 public static boolean getThumbnail(String filePath, String goldenPath) { 504 Log.v(TAG, "getThumbnail - " + filePath); 505 506 int goldenHeight = 0; 507 int goldenWidth = 0; 508 int outputWidth = 0; 509 int outputHeight = 0; 510 511 //This test is only for the short media file 512 try { 513 BitmapFactory mBitmapFactory = new BitmapFactory(); 514 515 Bitmap outThumbnail; 516 try (MediaMetadataRetriever mediaMetadataRetriever = new MediaMetadataRetriever()) { 517 try { 518 mediaMetadataRetriever.setDataSource(filePath); 519 } catch (Exception e) { 520 e.printStackTrace(); 521 return false; 522 } 523 outThumbnail = mediaMetadataRetriever.getFrameAtTime(-1); 524 } 525 526 //Verify the thumbnail 527 Bitmap goldenBitmap = mBitmapFactory.decodeFile(goldenPath); 528 outputWidth = outThumbnail.getWidth(); 529 outputHeight = outThumbnail.getHeight(); 530 goldenHeight = goldenBitmap.getHeight(); 531 goldenWidth = goldenBitmap.getWidth(); 532 533 //check the image dimension 534 if ((outputWidth != goldenWidth) || (outputHeight != goldenHeight)) 535 return false; 536 537 // Check half line of pixel 538 int x = goldenHeight / 2; 539 for (int j = 1; j < goldenWidth / 2; j++) { 540 if (goldenBitmap.getPixel(x, j) != outThumbnail.getPixel(x, j)) { 541 Log.v(TAG, "pixel = " + goldenBitmap.getPixel(x, j)); 542 return false; 543 } 544 } 545 } catch (Exception e) { 546 Log.v(TAG, e.toString()); 547 return false; 548 } 549 return true; 550 } 551 552 //Load midi file from resources resourcesPlayback(AssetFileDescriptor afd, int expectedDuration)553 public static boolean resourcesPlayback(AssetFileDescriptor afd, int expectedDuration) { 554 int duration = 0; 555 try { 556 MediaPlayer mp = new MediaPlayer(); 557 mp.setDataSource(afd.getFileDescriptor(),afd.getStartOffset(), afd.getLength()); 558 mp.prepare(); 559 mp.start(); 560 duration = mp.getDuration(); 561 Thread.sleep(5000); 562 mp.release(); 563 } catch (Exception e) { 564 Log.v(TAG,e.getMessage()); 565 } 566 if (duration > expectedDuration) 567 return true; 568 else 569 return false; 570 } 571 prepareAsyncReset(String filePath)572 public static boolean prepareAsyncReset(String filePath) { 573 //preparesAsync 574 try { 575 MediaPlayer mp = new MediaPlayer(); 576 mp.setDataSource(filePath); 577 mp.prepareAsync(); 578 mp.reset(); 579 mp.release(); 580 } catch (Exception e) { 581 Log.v(TAG,e.getMessage()); 582 return false; 583 } 584 return true; 585 } 586 587 isLooping(String filePath)588 public static boolean isLooping(String filePath) { 589 MediaPlayer mp = null; 590 591 try { 592 mp = new MediaPlayer(); 593 if (mp.isLooping()) { 594 Log.v(TAG, "MediaPlayer.isLooping() returned true after ctor"); 595 return false; 596 } 597 mp.setDataSource(filePath); 598 mp.prepare(); 599 600 mp.setLooping(true); 601 if (!mp.isLooping()) { 602 Log.v(TAG, "MediaPlayer.isLooping() returned false after setLooping(true)"); 603 return false; 604 } 605 606 mp.setLooping(false); 607 if (mp.isLooping()) { 608 Log.v(TAG, "MediaPlayer.isLooping() returned true after setLooping(false)"); 609 return false; 610 } 611 } catch (Exception e) { 612 Log.v(TAG, "Exception : " + e.toString()); 613 return false; 614 } finally { 615 if (mp != null) 616 mp.release(); 617 } 618 619 return true; 620 } 621 isLoopingAfterReset(String filePath)622 public static boolean isLoopingAfterReset(String filePath) { 623 MediaPlayer mp = null; 624 try { 625 mp = new MediaPlayer(); 626 mp.setDataSource(filePath); 627 mp.prepare(); 628 629 mp.setLooping(true); 630 mp.reset(); 631 if (mp.isLooping()) { 632 Log.v(TAG, "MediaPlayer.isLooping() returned true after reset()"); 633 return false; 634 } 635 } catch (Exception e){ 636 Log.v(TAG, "Exception : " + e.toString()); 637 return false; 638 } finally { 639 if (mp != null) 640 mp.release(); 641 } 642 643 return true; 644 } 645 646 /* 647 * Initializes the message looper so that the mediaPlayer object can 648 * receive the callback messages. 649 */ initializeMessageLooper()650 private static void initializeMessageLooper() { 651 Log.v(TAG, "start looper"); 652 new Thread() { 653 @Override 654 public void run() { 655 // Set up a looper to be used by camera. 656 Looper.prepare(); 657 Log.v(TAG, "start loopRun"); 658 // Save the looper so that we can terminate this thread 659 // after we are done with it. 660 mLooper = Looper.myLooper(); 661 mMediaPlayer = new MediaPlayer(); 662 synchronized (mLock) { 663 mInitialized = true; 664 mLock.notify(); 665 } 666 Looper.loop(); // Blocks forever until Looper.quit() is called. 667 Log.v(TAG, "initializeMessageLooper: quit."); 668 } 669 }.start(); 670 } 671 672 /* 673 * Terminates the message looper thread. 674 */ terminateMessageLooper()675 private static void terminateMessageLooper() { 676 if (mLooper != null) { 677 mLooper.quit(); 678 } 679 if (mMediaPlayer != null) { 680 mMediaPlayer.release(); 681 } 682 } 683 684 static MediaPlayer.OnPreparedListener mPreparedListener = new MediaPlayer.OnPreparedListener() { 685 public void onPrepared(MediaPlayer mp) { 686 synchronized (mPrepareDone) { 687 if(mPrepareReset) { 688 Log.v(TAG, "call Reset"); 689 mMediaPlayer.reset(); 690 } 691 Log.v(TAG, "notify the prepare callback"); 692 mPrepareDone.notify(); 693 mOnPrepareSuccess = true; 694 } 695 } 696 }; 697 prepareAsyncCallback(String filePath, boolean reset)698 public static boolean prepareAsyncCallback(String filePath, boolean reset) throws Exception { 699 //Added the PrepareReset flag which allow us to switch to different 700 //test case. 701 if (reset) { 702 mPrepareReset = true; 703 } 704 705 synchronized (mLock) { 706 initializeMessageLooper(); 707 try { 708 mLock.wait(WAIT_FOR_COMMAND_TO_COMPLETE); 709 } catch(Exception e) { 710 Log.v(TAG, "looper was interrupted."); 711 return false; 712 } 713 } 714 try{ 715 mMediaPlayer.setOnPreparedListener(mPreparedListener); 716 mMediaPlayer.setDataSource(filePath); 717 mMediaPlayer.setDisplay(MediaFrameworkTest.getSurfaceView().getHolder()); 718 mMediaPlayer.prepareAsync(); 719 synchronized (mPrepareDone) { 720 try { 721 mPrepareDone.wait(WAIT_FOR_COMMAND_TO_COMPLETE); 722 } catch (Exception e) { 723 Log.v(TAG, "wait was interrupted."); 724 } 725 } 726 terminateMessageLooper(); 727 }catch (Exception e) { 728 Log.v(TAG,e.getMessage()); 729 } 730 return mOnPrepareSuccess; 731 } 732 733 static MediaPlayer.OnCompletionListener mCompletionListener = new MediaPlayer.OnCompletionListener() { 734 public void onCompletion(MediaPlayer mp) { 735 Log.v(TAG, "notify the completion callback"); 736 mOnCompleteSuccess = true; 737 mCompletionLatch.countDown(); 738 } 739 }; 740 741 static MediaPlayer.OnErrorListener mOnErrorListener = new MediaPlayer.OnErrorListener() { 742 public boolean onError(MediaPlayer mp, int framework_err, int impl_err) { 743 Log.v(TAG, "playback error"); 744 mPlaybackError = true; 745 mp.reset(); 746 mOnCompleteSuccess = false; 747 mCompletionLatch.countDown(); 748 return true; 749 } 750 }; 751 752 static MediaPlayer.OnInfoListener mInfoListener = new MediaPlayer.OnInfoListener() { 753 public boolean onInfo(MediaPlayer mp, int what, int extra) { 754 switch (what) { 755 case MediaPlayer.MEDIA_INFO_UNKNOWN: 756 mMediaInfoUnknownCount++; 757 break; 758 case MediaPlayer.MEDIA_INFO_VIDEO_TRACK_LAGGING: 759 mMediaInfoVideoTrackLaggingCount++; 760 break; 761 case MediaPlayer.MEDIA_INFO_BAD_INTERLEAVING: 762 mMediaInfoBadInterleavingCount++; 763 break; 764 case MediaPlayer.MEDIA_INFO_NOT_SEEKABLE: 765 mMediaInfoNotSeekableCount++; 766 break; 767 case MediaPlayer.MEDIA_INFO_METADATA_UPDATE: 768 mMediaInfoMetdataUpdateCount++; 769 break; 770 case MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START: 771 mFirstFrameLatch.countDown(); 772 break; 773 } 774 return true; 775 } 776 }; 777 setupPlaybackMarkers()778 private static void setupPlaybackMarkers() { 779 // we only ever worry about these firing 1 time 780 mFirstFrameLatch = new CountDownLatch(1); 781 mCompletionLatch = new CountDownLatch(1); 782 783 mOnCompleteSuccess = false; 784 mPlaybackError = false; 785 786 mMediaInfoUnknownCount = 0; 787 mMediaInfoVideoTrackLaggingCount = 0; 788 mMediaInfoBadInterleavingCount = 0; 789 mMediaInfoNotSeekableCount = 0; 790 mMediaInfoMetdataUpdateCount = 0; 791 } 792 793 // null == success, !null == reason why it failed playMediaSample(String fileName)794 public static String playMediaSample(String fileName) throws Exception { 795 int duration = 0; 796 int curPosition = 0; 797 int nextPosition = 0; 798 799 setupPlaybackMarkers(); 800 801 initializeMessageLooper(); 802 synchronized (mLock) { 803 try { 804 mLock.wait(WAIT_FOR_COMMAND_TO_COMPLETE); 805 } catch(Exception e) { 806 Log.v(TAG, "looper was interrupted."); 807 return "Looper was interrupted"; 808 } 809 } 810 try { 811 mMediaPlayer.setOnCompletionListener(mCompletionListener); 812 mMediaPlayer.setOnErrorListener(mOnErrorListener); 813 mMediaPlayer.setOnInfoListener(mInfoListener); 814 Log.v(TAG, "playMediaSample: sample file name " + fileName); 815 mMediaPlayer.setDataSource(fileName); 816 mMediaPlayer.setDisplay(MediaFrameworkTest.getSurfaceView().getHolder()); 817 mMediaPlayer.prepare(); 818 duration = mMediaPlayer.getDuration(); 819 Log.v(TAG, "duration of media " + duration); 820 821 // start to play 822 long time_started = SystemClock.uptimeMillis(); 823 long time_firstFrame = time_started - 1; 824 long time_completed = time_started - 1; 825 mMediaPlayer.start(); 826 827 boolean happyStart = mFirstFrameLatch.await(SETUP_SETTLE_TIME_MS, 828 TimeUnit.MILLISECONDS); 829 time_firstFrame = SystemClock.uptimeMillis(); 830 if (happyStart == false) { 831 String msg = "playMediaSamples playback did not start within " 832 + SETUP_SETTLE_TIME_MS + " ms"; 833 Log.i(TAG, msg); 834 return msg; 835 } 836 837 // now that we know playback has started, calculate when it should 838 // finish and wait that long that. Account for what has already 839 // played (should be very close to 0 as we get here shortly after playback 840 // starts) 841 int startingPosition = mMediaPlayer.getCurrentPosition(); 842 int remainingDuration = duration - startingPosition; 843 844 boolean happyFinish = mCompletionLatch.await(remainingDuration + PLAYBACK_SETTLE_TIME_MS, 845 TimeUnit.MILLISECONDS); 846 time_completed = SystemClock.uptimeMillis(); 847 848 // really helps diagnose the class of failures we've seen. 849 if (true) { 850 Log.i(TAG, "duration of video sample: " + duration + " ms"); 851 Log.i(TAG, "full start+playback+completionsignal: " 852 + (time_completed - time_started) + " ms"); 853 Log.i(TAG, "total overhead: " 854 + (time_completed - time_started - duration) + " ms"); 855 Log.i(TAG, "time until 1st frame rendered: " 856 + (time_firstFrame - time_started) + " ms"); 857 Log.i(TAG, "video position when started timer: " + startingPosition + " ms"); 858 long preOverhead = (time_firstFrame - time_started) - (startingPosition); 859 Log.i(TAG, "start() startup overhead: " + preOverhead + " ms"); 860 long postOverhead = (time_completed - time_started) - duration - preOverhead; 861 Log.i(TAG, "trailing costs overhead: " + postOverhead + " ms"); 862 } 863 864 // did we succeed? 865 if (happyFinish == false) { 866 // the test failed 867 868 // wait a little more, to help who is trying to figure out why it's bad. 869 boolean happyExtra = mCompletionLatch.await(10000, TimeUnit.MILLISECONDS); 870 long time_extension = SystemClock.uptimeMillis(); 871 872 String extraTime = ""; 873 if (happyExtra) { 874 extraTime = " BUT complete after an additional " 875 + (time_extension - time_completed) + " ms"; 876 } else { 877 extraTime = " AND still not complete after an additional " 878 + (time_extension - time_completed) + " ms"; 879 } 880 881 // it's still a failure, even if we did finish in extra time 882 Log.e(TAG, "wait timed-out without onCompletion notification" + extraTime); 883 return "wait timed-out without onCompletion notification" + extraTime; 884 } 885 } catch (Exception e) { 886 Log.v(TAG, "playMediaSample Exception:" + e.getMessage()); 887 } finally { 888 // we need to clean up, even if we tripped an early return above 889 terminateMessageLooper(); 890 } 891 return mOnCompleteSuccess ? null : "unknown failure reason"; 892 } 893 } 894