1 /* 2 * Copyright 2018 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 package android.media.cts; 17 18 import android.media.cts.R; 19 20 import android.content.Context; 21 import android.content.pm.PackageManager; 22 import android.content.res.AssetFileDescriptor; 23 import android.graphics.Rect; 24 import android.hardware.Camera; 25 import android.media.AudioAttributes; 26 import android.media.AudioManager; 27 import android.media.DataSourceDesc; 28 import android.media.MediaCodec; 29 import android.media.Media2DataSource; 30 import android.media.MediaExtractor; 31 import android.media.MediaFormat; 32 import android.media.MediaMetadataRetriever; 33 import android.media.MediaPlayer2; 34 import android.media.MediaRecorder; 35 import android.media.MediaTimestamp; 36 import android.media.PlaybackParams; 37 import android.media.SubtitleData; 38 import android.media.SyncParams; 39 import android.media.TimedText; 40 import android.media.audiofx.AudioEffect; 41 import android.media.audiofx.Visualizer; 42 import android.media.cts.TestUtils.Monitor; 43 import android.net.Uri; 44 import android.os.Bundle; 45 import android.os.Environment; 46 import android.os.IBinder; 47 import android.os.PowerManager; 48 import android.os.ServiceManager; 49 import android.os.SystemClock; 50 import android.platform.test.annotations.AppModeFull; 51 import android.support.test.InstrumentationRegistry; 52 import android.support.test.filters.SmallTest; 53 import android.platform.test.annotations.RequiresDevice; 54 import android.util.Log; 55 56 import com.android.compatibility.common.util.MediaUtils; 57 58 import java.io.BufferedReader; 59 import java.io.File; 60 import java.io.InputStream; 61 import java.io.InputStreamReader; 62 import java.util.ArrayList; 63 import java.util.List; 64 import java.util.StringTokenizer; 65 import java.util.UUID; 66 import java.util.Vector; 67 import java.util.concurrent.Callable; 68 import java.util.concurrent.CountDownLatch; 69 import java.util.concurrent.ExecutorService; 70 import java.util.concurrent.Executors; 71 import java.util.concurrent.atomic.AtomicInteger; 72 import java.util.stream.Collectors; 73 import java.util.stream.Stream; 74 import junit.framework.AssertionFailedError; 75 76 /** 77 * Tests for the MediaPlayer2 API and local video/audio playback. 78 * 79 * The files in res/raw used by testLocalVideo* are (c) copyright 2008, 80 * Blender Foundation / www.bigbuckbunny.org, and are licensed under the Creative Commons 81 * Attribution 3.0 License at http://creativecommons.org/licenses/by/3.0/us/. 82 */ 83 @SmallTest 84 @RequiresDevice 85 @AppModeFull(reason = "TODO: evaluate and port to instant") 86 public class MediaPlayer2Test extends MediaPlayer2TestBase { 87 // TODO: remove this flag to enable tests. 88 private static final boolean IGNORE_TESTS = true; 89 90 private String RECORDED_FILE; 91 private static final String LOG_TAG = "MediaPlayer2Test"; 92 93 private static final int RECORDED_VIDEO_WIDTH = 176; 94 private static final int RECORDED_VIDEO_HEIGHT = 144; 95 private static final long RECORDED_DURATION_MS = 3000; 96 private static final float FLOAT_TOLERANCE = .0001f; 97 98 private final Vector<Integer> mTimedTextTrackIndex = new Vector<>(); 99 private final Monitor mOnTimedTextCalled = new Monitor(); 100 private int mSelectedTimedTextIndex; 101 102 private final Vector<Integer> mSubtitleTrackIndex = new Vector<>(); 103 private final Monitor mOnSubtitleDataCalled = new Monitor(); 104 private int mSelectedSubtitleIndex; 105 106 private File mOutFile; 107 108 private int mBoundsCount; 109 110 @Override 111 protected void setUp() throws Exception { 112 super.setUp(); 113 RECORDED_FILE = new File(Environment.getExternalStorageDirectory(), 114 "mediaplayer_record.out").getAbsolutePath(); 115 mOutFile = new File(RECORDED_FILE); 116 } 117 118 @Override 119 protected void tearDown() throws Exception { 120 super.tearDown(); 121 if (mOutFile != null && mOutFile.exists()) { 122 mOutFile.delete(); 123 } 124 } 125 126 // Bug 13652927 127 public void testVorbisCrash() throws Exception { 128 if (IGNORE_TESTS) { 129 return; 130 } 131 MediaPlayer2 mp = mPlayer; 132 MediaPlayer2 mp2 = mPlayer2; 133 AssetFileDescriptor afd2 = mResources.openRawResourceFd(R.raw.testmp3_2); 134 mp2.setDataSource(new DataSourceDesc.Builder() 135 .setDataSource(afd2.getFileDescriptor(), afd2.getStartOffset(), afd2.getLength()) 136 .build()); 137 Monitor onPrepareCalled = new Monitor(); 138 Monitor onErrorCalled = new Monitor(); 139 MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() { 140 @Override 141 public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) { 142 if (what == MediaPlayer2.MEDIA_INFO_PREPARED) { 143 onPrepareCalled.signal(); 144 } 145 } 146 147 @Override 148 public void onError(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) { 149 onErrorCalled.signal(); 150 } 151 }; 152 mp2.setMediaPlayer2EventCallback(mExecutor, ecb); 153 mp2.prepare(); 154 onPrepareCalled.waitForSignal(); 155 afd2.close(); 156 mp2.clearMediaPlayer2EventCallback(); 157 158 mp2.loopCurrent(true); 159 mp2.play(); 160 161 for (int i = 0; i < 20; i++) { 162 try { 163 AssetFileDescriptor afd = mResources.openRawResourceFd(R.raw.bug13652927); 164 mp.setDataSource(new DataSourceDesc.Builder() 165 .setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), 166 afd.getLength()) 167 .build()); 168 mp.setMediaPlayer2EventCallback(mExecutor, ecb); 169 onPrepareCalled.reset(); 170 mp.prepare(); 171 onErrorCalled.waitForSignal(); 172 afd.close(); 173 } catch (Exception e) { 174 // expected to fail 175 Log.i("@@@", "failed: " + e); 176 } 177 Thread.sleep(500); 178 assertTrue("media player died", mp2.isPlaying()); 179 mp.reset(); 180 } 181 } 182 183 public void testPlayNullSourcePath() throws Exception { 184 if (IGNORE_TESTS) { 185 return; 186 } 187 Monitor onSetDataSourceCalled = new Monitor(); 188 MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() { 189 @Override 190 public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd, int what, int status) { 191 if (what == MediaPlayer2.CALL_COMPLETED_SET_DATA_SOURCE) { 192 assertTrue(status != MediaPlayer2.CALL_STATUS_NO_ERROR); 193 onSetDataSourceCalled.signal(); 194 } 195 } 196 }; 197 synchronized (mEventCbLock) { 198 mEventCallbacks.add(ecb); 199 } 200 201 onSetDataSourceCalled.reset(); 202 mPlayer.setDataSource((DataSourceDesc)null); 203 onSetDataSourceCalled.waitForSignal(); 204 } 205 206 public void testPlayAudioFromDataURI() throws Exception { 207 if (IGNORE_TESTS) { 208 return; 209 } 210 final int mp3Duration = 34909; 211 final int tolerance = 70; 212 final int seekDuration = 100; 213 214 // This is "R.raw.testmp3_2", base64-encoded. 215 final int resid = R.raw.testmp3_3; 216 217 InputStream is = mContext.getResources().openRawResource(resid); 218 BufferedReader reader = new BufferedReader(new InputStreamReader(is)); 219 220 StringBuilder builder = new StringBuilder(); 221 builder.append("data:;base64,"); 222 builder.append(reader.readLine()); 223 Uri uri = Uri.parse(builder.toString()); 224 225 MediaPlayer2 mp = createMediaPlayer2(mContext, uri); 226 227 Monitor onPrepareCalled = new Monitor(); 228 Monitor onPlayCalled = new Monitor(); 229 Monitor onSeekToCalled = new Monitor(); 230 Monitor onLoopCurrentCalled = new Monitor(); 231 MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() { 232 @Override 233 public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) { 234 if (what == MediaPlayer2.MEDIA_INFO_PREPARED) { 235 onPrepareCalled.signal(); 236 } 237 } 238 239 @Override 240 public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd, int what, int status) { 241 if (what == MediaPlayer2.CALL_COMPLETED_PLAY) { 242 onPlayCalled.signal(); 243 } else if (what == MediaPlayer2.CALL_COMPLETED_LOOP_CURRENT) { 244 onLoopCurrentCalled.signal(); 245 } else if (what == MediaPlayer2.CALL_COMPLETED_SEEK_TO) { 246 onSeekToCalled.signal(); 247 } 248 } 249 }; 250 mp.setMediaPlayer2EventCallback(mExecutor, ecb); 251 252 try { 253 AudioAttributes attributes = new AudioAttributes.Builder() 254 .setInternalLegacyStreamType(AudioManager.STREAM_MUSIC) 255 .build(); 256 mp.setAudioAttributes(attributes); 257 mp.setWakeMode(mContext, PowerManager.PARTIAL_WAKE_LOCK); 258 259 assertFalse(mp.isPlaying()); 260 onPlayCalled.reset(); 261 mp.play(); 262 onPlayCalled.waitForSignal(); 263 assertTrue(mp.isPlaying()); 264 265 assertFalse(mp.isLooping()); 266 onLoopCurrentCalled.reset(); 267 mp.loopCurrent(true); 268 onLoopCurrentCalled.waitForSignal(); 269 assertTrue(mp.isLooping()); 270 271 assertEquals(mp3Duration, mp.getDuration(), tolerance); 272 long pos = mp.getCurrentPosition(); 273 assertTrue(pos >= 0); 274 assertTrue(pos < mp3Duration - seekDuration); 275 276 onSeekToCalled.reset(); 277 mp.seekTo(pos + seekDuration, MediaPlayer2.SEEK_PREVIOUS_SYNC); 278 onSeekToCalled.waitForSignal(); 279 assertEquals(pos + seekDuration, mp.getCurrentPosition(), tolerance); 280 281 // test pause and restart 282 mp.pause(); 283 Thread.sleep(SLEEP_TIME); 284 assertFalse(mp.isPlaying()); 285 onPlayCalled.reset(); 286 mp.play(); 287 onPlayCalled.waitForSignal(); 288 assertTrue(mp.isPlaying()); 289 290 // test stop and restart 291 mp.reset(); 292 mp.setMediaPlayer2EventCallback(mExecutor, ecb); 293 mp.setDataSource(new DataSourceDesc.Builder() 294 .setDataSource(mContext, uri) 295 .build()); 296 onPrepareCalled.reset(); 297 mp.prepare(); 298 onPrepareCalled.waitForSignal(); 299 300 assertFalse(mp.isPlaying()); 301 onPlayCalled.reset(); 302 mp.play(); 303 onPlayCalled.waitForSignal(); 304 assertTrue(mp.isPlaying()); 305 306 // waiting to complete 307 while(mp.isPlaying()) { 308 Thread.sleep(SLEEP_TIME); 309 } 310 } finally { 311 mp.close(); 312 } 313 } 314 315 public void testPlayAudio() throws Exception { 316 if (IGNORE_TESTS) { 317 return; 318 } 319 final int resid = R.raw.testmp3_2; 320 final int mp3Duration = 34909; 321 final int tolerance = 70; 322 final int seekDuration = 100; 323 324 MediaPlayer2 mp = createMediaPlayer2(mContext, resid); 325 326 Monitor onPrepareCalled = new Monitor(); 327 Monitor onPlayCalled = new Monitor(); 328 Monitor onSeekToCalled = new Monitor(); 329 Monitor onLoopCurrentCalled = new Monitor(); 330 MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() { 331 @Override 332 public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) { 333 if (what == MediaPlayer2.MEDIA_INFO_PREPARED) { 334 onPrepareCalled.signal(); 335 } 336 } 337 338 @Override 339 public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd, int what, int status) { 340 if (what == MediaPlayer2.CALL_COMPLETED_PLAY) { 341 onPlayCalled.signal(); 342 } else if (what == MediaPlayer2.CALL_COMPLETED_LOOP_CURRENT) { 343 onLoopCurrentCalled.signal(); 344 } else if (what == MediaPlayer2.CALL_COMPLETED_SEEK_TO) { 345 onSeekToCalled.signal(); 346 } 347 } 348 }; 349 mp.setMediaPlayer2EventCallback(mExecutor, ecb); 350 351 try { 352 AudioAttributes attributes = new AudioAttributes.Builder() 353 .setInternalLegacyStreamType(AudioManager.STREAM_MUSIC) 354 .build(); 355 mp.setAudioAttributes(attributes); 356 mp.setWakeMode(mContext, PowerManager.PARTIAL_WAKE_LOCK); 357 358 assertFalse(mp.isPlaying()); 359 onPlayCalled.reset(); 360 mp.play(); 361 onPlayCalled.waitForSignal(); 362 assertTrue(mp.isPlaying()); 363 364 assertFalse(mp.isLooping()); 365 onLoopCurrentCalled.reset(); 366 mp.loopCurrent(true); 367 onLoopCurrentCalled.waitForSignal(); 368 assertTrue(mp.isLooping()); 369 370 assertEquals(mp3Duration, mp.getDuration(), tolerance); 371 long pos = mp.getCurrentPosition(); 372 assertTrue(pos >= 0); 373 assertTrue(pos < mp3Duration - seekDuration); 374 375 onSeekToCalled.reset(); 376 mp.seekTo(pos + seekDuration, MediaPlayer2.SEEK_PREVIOUS_SYNC); 377 onSeekToCalled.waitForSignal(); 378 assertEquals(pos + seekDuration, mp.getCurrentPosition(), tolerance); 379 380 // test pause and restart 381 mp.pause(); 382 Thread.sleep(SLEEP_TIME); 383 assertFalse(mp.isPlaying()); 384 onPlayCalled.reset(); 385 mp.play(); 386 onPlayCalled.waitForSignal(); 387 assertTrue(mp.isPlaying()); 388 389 // test stop and restart 390 mp.reset(); 391 AssetFileDescriptor afd = mResources.openRawResourceFd(resid); 392 mp.setDataSource(new DataSourceDesc.Builder() 393 .setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength()) 394 .build()); 395 396 mp.setMediaPlayer2EventCallback(mExecutor, ecb); 397 onPrepareCalled.reset(); 398 mp.prepare(); 399 onPrepareCalled.waitForSignal(); 400 afd.close(); 401 402 assertFalse(mp.isPlaying()); 403 onPlayCalled.reset(); 404 mp.play(); 405 onPlayCalled.waitForSignal(); 406 assertTrue(mp.isPlaying()); 407 408 // waiting to complete 409 while(mp.isPlaying()) { 410 Thread.sleep(SLEEP_TIME); 411 } 412 } finally { 413 mp.close(); 414 } 415 } 416 417 public void testConcurentPlayAudio() throws Exception { 418 if (IGNORE_TESTS) { 419 return; 420 } 421 final int resid = R.raw.test1m1s; // MP3 longer than 1m are usualy offloaded 422 final int tolerance = 70; 423 424 List<MediaPlayer2> mps = Stream.generate(() -> createMediaPlayer2(mContext, resid)) 425 .limit(5).collect(Collectors.toList()); 426 427 try { 428 for (MediaPlayer2 mp : mps) { 429 Monitor onPlayCalled = new Monitor(); 430 Monitor onLoopCurrentCalled = new Monitor(); 431 MediaPlayer2.MediaPlayer2EventCallback ecb = 432 new MediaPlayer2.MediaPlayer2EventCallback() { 433 @Override 434 public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd, 435 int what, int status) { 436 if (what == MediaPlayer2.CALL_COMPLETED_PLAY) { 437 onPlayCalled.signal(); 438 } else if (what == MediaPlayer2.CALL_COMPLETED_LOOP_CURRENT) { 439 onLoopCurrentCalled.signal(); 440 } 441 } 442 }; 443 mp.setMediaPlayer2EventCallback(mExecutor, ecb); 444 445 AudioAttributes attributes = new AudioAttributes.Builder() 446 .setInternalLegacyStreamType(AudioManager.STREAM_MUSIC) 447 .build(); 448 mp.setAudioAttributes(attributes); 449 mp.setWakeMode(mContext, PowerManager.PARTIAL_WAKE_LOCK); 450 451 assertFalse(mp.isPlaying()); 452 onPlayCalled.reset(); 453 mp.play(); 454 onPlayCalled.waitForSignal(); 455 assertTrue(mp.isPlaying()); 456 457 assertFalse(mp.isLooping()); 458 onLoopCurrentCalled.reset(); 459 mp.loopCurrent(true); 460 onLoopCurrentCalled.waitForSignal(); 461 assertTrue(mp.isLooping()); 462 463 long pos = mp.getCurrentPosition(); 464 assertTrue(pos >= 0); 465 466 Thread.sleep(SLEEP_TIME); // Delay each track to be able to ear them 467 } 468 // Check that all mp3 are playing concurrently here 469 for (MediaPlayer2 mp : mps) { 470 long pos = mp.getCurrentPosition(); 471 Thread.sleep(SLEEP_TIME); 472 assertEquals(pos + SLEEP_TIME, mp.getCurrentPosition(), tolerance); 473 } 474 } finally { 475 mps.forEach(MediaPlayer2::close); 476 } 477 } 478 479 public void testPlayAudioLooping() throws Exception { 480 if (IGNORE_TESTS) { 481 return; 482 } 483 final int resid = R.raw.testmp3; 484 485 MediaPlayer2 mp = createMediaPlayer2(mContext, resid); 486 try { 487 AudioAttributes attributes = new AudioAttributes.Builder() 488 .setInternalLegacyStreamType(AudioManager.STREAM_MUSIC) 489 .build(); 490 mp.setAudioAttributes(attributes); 491 mp.setWakeMode(mContext, PowerManager.PARTIAL_WAKE_LOCK); 492 mp.loopCurrent(true); 493 Monitor onCompletionCalled = new Monitor(); 494 Monitor onPlayCalled = new Monitor(); 495 MediaPlayer2.MediaPlayer2EventCallback ecb = 496 new MediaPlayer2.MediaPlayer2EventCallback() { 497 @Override 498 public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, 499 int what, int extra) { 500 Log.i("@@@", "got oncompletion"); 501 onCompletionCalled.signal(); 502 } 503 504 @Override 505 public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd, 506 int what, int status) { 507 if (what == MediaPlayer2.CALL_COMPLETED_PLAY) { 508 onPlayCalled.signal(); 509 } 510 } 511 }; 512 mp.setMediaPlayer2EventCallback(mExecutor, ecb); 513 514 assertFalse(mp.isPlaying()); 515 onPlayCalled.reset(); 516 mp.play(); 517 onPlayCalled.waitForSignal(); 518 assertTrue(mp.isPlaying()); 519 520 long duration = mp.getDuration(); 521 Thread.sleep(duration * 4); // allow for several loops 522 assertTrue(mp.isPlaying()); 523 assertEquals("wrong number of completion signals", 0, 524 onCompletionCalled.getNumSignal()); 525 mp.loopCurrent(false); 526 527 // wait for playback to finish 528 while(mp.isPlaying()) { 529 Thread.sleep(SLEEP_TIME); 530 } 531 assertEquals("wrong number of completion signals", 1, 532 onCompletionCalled.getNumSignal()); 533 } finally { 534 mp.close(); 535 } 536 } 537 538 public void testPlayMidi() throws Exception { 539 if (IGNORE_TESTS) { 540 return; 541 } 542 final int resid = R.raw.midi8sec; 543 final int midiDuration = 8000; 544 final int tolerance = 70; 545 final int seekDuration = 1000; 546 547 MediaPlayer2 mp = createMediaPlayer2(mContext, resid); 548 549 Monitor onPrepareCalled = new Monitor(); 550 Monitor onSeekToCalled = new Monitor(); 551 Monitor onLoopCurrentCalled = new Monitor(); 552 MediaPlayer2.MediaPlayer2EventCallback ecb = 553 new MediaPlayer2.MediaPlayer2EventCallback() { 554 @Override 555 public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) { 556 if (what == MediaPlayer2.MEDIA_INFO_PREPARED) { 557 onPrepareCalled.signal(); 558 } 559 } 560 561 @Override 562 public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd, 563 int what, int status) { 564 if (what == MediaPlayer2.CALL_COMPLETED_LOOP_CURRENT) { 565 onLoopCurrentCalled.signal(); 566 } else if (what == MediaPlayer2.CALL_COMPLETED_SEEK_TO) { 567 onSeekToCalled.signal(); 568 } 569 } 570 }; 571 mp.setMediaPlayer2EventCallback(mExecutor, ecb); 572 573 try { 574 AudioAttributes attributes = new AudioAttributes.Builder() 575 .setInternalLegacyStreamType(AudioManager.STREAM_MUSIC) 576 .build(); 577 mp.setAudioAttributes(attributes); 578 mp.setWakeMode(mContext, PowerManager.PARTIAL_WAKE_LOCK); 579 580 mp.play(); 581 582 assertFalse(mp.isLooping()); 583 onLoopCurrentCalled.reset(); 584 mp.loopCurrent(true); 585 onLoopCurrentCalled.waitForSignal(); 586 assertTrue(mp.isLooping()); 587 588 assertEquals(midiDuration, mp.getDuration(), tolerance); 589 long pos = mp.getCurrentPosition(); 590 assertTrue(pos >= 0); 591 assertTrue(pos < midiDuration - seekDuration); 592 593 onSeekToCalled.reset(); 594 mp.seekTo(pos + seekDuration, MediaPlayer2.SEEK_PREVIOUS_SYNC); 595 onSeekToCalled.waitForSignal(); 596 assertEquals(pos + seekDuration, mp.getCurrentPosition(), tolerance); 597 598 // test stop and restart 599 mp.reset(); 600 AssetFileDescriptor afd = mResources.openRawResourceFd(resid); 601 mp.setDataSource(new DataSourceDesc.Builder() 602 .setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength()) 603 .build()); 604 605 mp.setMediaPlayer2EventCallback(mExecutor, ecb); 606 onPrepareCalled.reset(); 607 mp.prepare(); 608 onPrepareCalled.waitForSignal(); 609 afd.close(); 610 611 mp.play(); 612 613 Thread.sleep(SLEEP_TIME); 614 } finally { 615 mp.close(); 616 } 617 } 618 619 static class OutputListener { 620 int mSession; 621 AudioEffect mVc; 622 Visualizer mVis; 623 byte [] mVisData; 624 boolean mSoundDetected; 625 OutputListener(int session) { 626 mSession = session; 627 // creating a volume controller on output mix ensures that ro.audio.silent mutes 628 // audio after the effects and not before 629 mVc = new AudioEffect( 630 AudioEffect.EFFECT_TYPE_NULL, 631 UUID.fromString("119341a0-8469-11df-81f9-0002a5d5c51b"), 632 0, 633 session); 634 mVc.setEnabled(true); 635 mVis = new Visualizer(session); 636 int size = 256; 637 int[] range = Visualizer.getCaptureSizeRange(); 638 if (size < range[0]) { 639 size = range[0]; 640 } 641 if (size > range[1]) { 642 size = range[1]; 643 } 644 assertTrue(mVis.setCaptureSize(size) == Visualizer.SUCCESS); 645 646 mVis.setDataCaptureListener(new Visualizer.OnDataCaptureListener() { 647 @Override 648 public void onWaveFormDataCapture(Visualizer visualizer, 649 byte[] waveform, int samplingRate) { 650 if (!mSoundDetected) { 651 for (int i = 0; i < waveform.length; i++) { 652 // 8 bit unsigned PCM, zero level is at 128, which is -128 when 653 // seen as a signed byte 654 if (waveform[i] != -128) { 655 mSoundDetected = true; 656 break; 657 } 658 } 659 } 660 } 661 662 @Override 663 public void onFftDataCapture(Visualizer visualizer, byte[] fft, int samplingRate) { 664 } 665 }, 10000 /* milliHertz */, true /* PCM */, false /* FFT */); 666 assertTrue(mVis.setEnabled(true) == Visualizer.SUCCESS); 667 } 668 669 void reset() { 670 mSoundDetected = false; 671 } 672 673 boolean heardSound() { 674 return mSoundDetected; 675 } 676 677 void release() { 678 mVis.release(); 679 mVc.release(); 680 } 681 } 682 683 public void testPlayAudioTwice() throws Exception { 684 if (IGNORE_TESTS) { 685 return; 686 } 687 final int resid = R.raw.camera_click; 688 689 MediaPlayer2 mp = createMediaPlayer2(mContext, resid); 690 try { 691 AudioAttributes attributes = new AudioAttributes.Builder() 692 .setInternalLegacyStreamType(AudioManager.STREAM_MUSIC) 693 .build(); 694 mp.setAudioAttributes(attributes); 695 mp.setWakeMode(mContext, PowerManager.PARTIAL_WAKE_LOCK); 696 697 OutputListener listener = new OutputListener(mp.getAudioSessionId()); 698 699 Thread.sleep(SLEEP_TIME); 700 assertFalse("noise heard before test started", listener.heardSound()); 701 702 mp.play(); 703 Thread.sleep(SLEEP_TIME); 704 assertFalse("player was still playing after " + SLEEP_TIME + " ms", mp.isPlaying()); 705 assertTrue("nothing heard while test ran", listener.heardSound()); 706 listener.reset(); 707 mp.seekTo(0, MediaPlayer2.SEEK_PREVIOUS_SYNC); 708 mp.play(); 709 Thread.sleep(SLEEP_TIME); 710 assertTrue("nothing heard when sound was replayed", listener.heardSound()); 711 listener.release(); 712 } finally { 713 mp.close(); 714 } 715 } 716 717 public void testPlayVideo() throws Exception { 718 if (IGNORE_TESTS) { 719 return; 720 } 721 playVideoTest(R.raw.testvideo, 352, 288); 722 } 723 724 /** 725 * Test for reseting a surface during video playback 726 * After reseting, the video should continue playing 727 * from the time setDisplay() was called 728 */ 729 public void testVideoSurfaceResetting() throws Exception { 730 if (IGNORE_TESTS) { 731 return; 732 } 733 final int tolerance = 150; 734 final int audioLatencyTolerance = 1000; /* covers audio path latency variability */ 735 final int seekPos = 4760; // This is the I-frame position 736 737 final CountDownLatch seekDone = new CountDownLatch(1); 738 739 MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() { 740 @Override 741 public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd, int what, int status) { 742 if (what == MediaPlayer2.CALL_COMPLETED_SEEK_TO) { 743 seekDone.countDown(); 744 } 745 } 746 }; 747 synchronized (mEventCbLock) { 748 mEventCallbacks.add(ecb); 749 } 750 751 if (!checkLoadResource(R.raw.testvideo)) { 752 return; // skip; 753 } 754 playLoadedVideo(352, 288, -1); 755 756 Thread.sleep(SLEEP_TIME); 757 758 long posBefore = mPlayer.getCurrentPosition(); 759 mPlayer.setDisplay(getActivity().getSurfaceHolder2()); 760 long posAfter = mPlayer.getCurrentPosition(); 761 762 /* temporarily disable timestamp checking because MediaPlayer2 now seeks to I-frame 763 * position, instead of requested position. setDisplay invovles a seek operation 764 * internally. 765 */ 766 // TODO: uncomment out line below when MediaPlayer2 can seek to requested position. 767 // assertEquals(posAfter, posBefore, tolerance); 768 assertTrue(mPlayer.isPlaying()); 769 770 Thread.sleep(SLEEP_TIME); 771 772 mPlayer.seekTo(seekPos, MediaPlayer2.SEEK_PREVIOUS_SYNC); 773 seekDone.await(); 774 posAfter = mPlayer.getCurrentPosition(); 775 assertEquals(seekPos, posAfter, tolerance + audioLatencyTolerance); 776 777 Thread.sleep(SLEEP_TIME / 2); 778 posBefore = mPlayer.getCurrentPosition(); 779 mPlayer.setDisplay(null); 780 posAfter = mPlayer.getCurrentPosition(); 781 // TODO: uncomment out line below when MediaPlayer2 can seek to requested position. 782 // assertEquals(posAfter, posBefore, tolerance); 783 assertTrue(mPlayer.isPlaying()); 784 785 Thread.sleep(SLEEP_TIME); 786 787 posBefore = mPlayer.getCurrentPosition(); 788 mPlayer.setDisplay(getActivity().getSurfaceHolder()); 789 posAfter = mPlayer.getCurrentPosition(); 790 791 // TODO: uncomment out line below when MediaPlayer2 can seek to requested position. 792 // assertEquals(posAfter, posBefore, tolerance); 793 assertTrue(mPlayer.isPlaying()); 794 795 Thread.sleep(SLEEP_TIME); 796 } 797 798 public void testRecordedVideoPlayback0() throws Exception { 799 if (IGNORE_TESTS) { 800 return; 801 } 802 testRecordedVideoPlaybackWithAngle(0); 803 } 804 805 public void testRecordedVideoPlayback90() throws Exception { 806 if (IGNORE_TESTS) { 807 return; 808 } 809 testRecordedVideoPlaybackWithAngle(90); 810 } 811 812 public void testRecordedVideoPlayback180() throws Exception { 813 if (IGNORE_TESTS) { 814 return; 815 } 816 testRecordedVideoPlaybackWithAngle(180); 817 } 818 819 public void testRecordedVideoPlayback270() throws Exception { 820 if (IGNORE_TESTS) { 821 return; 822 } 823 testRecordedVideoPlaybackWithAngle(270); 824 } 825 826 private boolean hasCamera() { 827 return getActivity().getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA); 828 } 829 830 private Camera mCamera; 831 private void testRecordedVideoPlaybackWithAngle(int angle) throws Exception { 832 int width = RECORDED_VIDEO_WIDTH; 833 int height = RECORDED_VIDEO_HEIGHT; 834 final String file = RECORDED_FILE; 835 final long durationMs = RECORDED_DURATION_MS; 836 837 if (!hasCamera()) { 838 return; 839 } 840 841 boolean isSupported = false; 842 mCamera = Camera.open(0); 843 Camera.Parameters parameters = mCamera.getParameters(); 844 List<Camera.Size> videoSizes = parameters.getSupportedVideoSizes(); 845 // getSupportedVideoSizes returns null when separate video/preview size 846 // is not supported. 847 if (videoSizes == null) { 848 videoSizes = parameters.getSupportedPreviewSizes(); 849 } 850 for (Camera.Size size : videoSizes) 851 { 852 if (size.width == width && size.height == height) { 853 isSupported = true; 854 break; 855 } 856 } 857 mCamera.release(); 858 mCamera = null; 859 if (!isSupported) { 860 width = videoSizes.get(0).width; 861 height = videoSizes.get(0).height; 862 } 863 checkOrientation(angle); 864 recordVideo(width, height, angle, file, durationMs); 865 checkDisplayedVideoSize(width, height, angle, file); 866 checkVideoRotationAngle(angle, file); 867 } 868 869 private void checkOrientation(int angle) throws Exception { 870 assertTrue(angle >= 0); 871 assertTrue(angle < 360); 872 assertTrue((angle % 90) == 0); 873 } 874 875 private void recordVideo( 876 int w, int h, int angle, String file, long durationMs) throws Exception { 877 878 MediaRecorder recorder = new MediaRecorder(); 879 recorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); 880 recorder.setAudioSource(MediaRecorder.AudioSource.MIC); 881 recorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT); 882 recorder.setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT); 883 recorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT); 884 recorder.setOutputFile(file); 885 recorder.setOrientationHint(angle); 886 recorder.setVideoSize(w, h); 887 recorder.setPreviewDisplay(getActivity().getSurfaceHolder2().getSurface()); 888 recorder.prepare(); 889 recorder.start(); 890 Thread.sleep(durationMs); 891 recorder.stop(); 892 recorder.release(); 893 recorder = null; 894 } 895 896 private void checkDisplayedVideoSize( 897 int w, int h, int angle, String file) throws Exception { 898 899 int displayWidth = w; 900 int displayHeight = h; 901 if ((angle % 180) != 0) { 902 displayWidth = h; 903 displayHeight = w; 904 } 905 playVideoTest(file, displayWidth, displayHeight); 906 } 907 908 private void checkVideoRotationAngle(int angle, String file) { 909 MediaMetadataRetriever retriever = new MediaMetadataRetriever(); 910 retriever.setDataSource(file); 911 String rotation = retriever.extractMetadata( 912 MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION); 913 retriever.release(); 914 retriever = null; 915 assertNotNull(rotation); 916 assertEquals(Integer.parseInt(rotation), angle); 917 } 918 919 public void testPlaylist() throws Exception { 920 if (IGNORE_TESTS) { 921 return; 922 } 923 if (!checkLoadResource( 924 R.raw.video_480x360_mp4_h264_1000kbps_30fps_aac_stereo_128kbps_44100hz)) { 925 return; // skip 926 } 927 DataSourceDesc dsd1 = createDataSourceDesc( 928 R.raw.video_480x360_mp4_h264_1000kbps_30fps_aac_stereo_128kbps_44100hz); 929 DataSourceDesc dsd2 = createDataSourceDesc( 930 R.raw.testvideo); 931 ArrayList<DataSourceDesc> nextDSDs = new ArrayList<DataSourceDesc>(2); 932 nextDSDs.add(dsd2); 933 nextDSDs.add(dsd1); 934 935 mPlayer.setNextDataSources(nextDSDs); 936 937 Monitor onCompletion1Called = new Monitor(); 938 Monitor onCompletion2Called = new Monitor(); 939 MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() { 940 @Override 941 public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) { 942 if (what == MediaPlayer2.MEDIA_INFO_PREPARED) { 943 Log.i(LOG_TAG, "testPlaylist: prepared dsd MediaId=" + dsd.getMediaId()); 944 mOnPrepareCalled.signal(); 945 } else if (what == MediaPlayer2.MEDIA_INFO_PLAYBACK_COMPLETE) { 946 if (dsd == dsd1) { 947 onCompletion1Called.signal(); 948 } else if (dsd == dsd2) { 949 onCompletion2Called.signal(); 950 } else { 951 mOnCompletionCalled.signal(); 952 } 953 } 954 } 955 }; 956 synchronized (mEventCbLock) { 957 mEventCallbacks.add(ecb); 958 } 959 960 mOnCompletionCalled.reset(); 961 onCompletion1Called.reset(); 962 onCompletion2Called.reset(); 963 964 mPlayer.setDisplay(mActivity.getSurfaceHolder()); 965 966 mPlayer.prepare(); 967 968 mPlayer.play(); 969 970 mOnCompletionCalled.waitForSignal(); 971 onCompletion2Called.waitForSignal(); 972 onCompletion1Called.waitForSignal(); 973 974 mPlayer.reset(); 975 } 976 977 // setPlaybackParams() with non-zero speed should NOT start playback. 978 // TODO: enable this test when MediaPlayer2.setPlaybackParams() is fixed 979 /* 980 public void testSetPlaybackParamsPositiveSpeed() throws Exception { 981 if (IGNORE_TESTS) { 982 return; 983 } 984 if (!checkLoadResource( 985 R.raw.video_480x360_mp4_h264_1000kbps_30fps_aac_stereo_128kbps_44100hz)) { 986 return; // skip 987 } 988 989 MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() { 990 @Override 991 public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) { 992 if (what == MediaPlayer2.MEDIA_INFO_PREPARED) { 993 mOnPrepareCalled.signal(); 994 } else if (what == MediaPlayer2.MEDIA_INFO_PLAYBACK_COMPLETE) { 995 mOnCompletionCalled.signal(); 996 } 997 } 998 999 @Override 1000 public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd, int what, int status) { 1001 if (what == MediaPlayer2.CALL_COMPLETED_SEEK_TO) { 1002 mOnSeekCompleteCalled.signal(); 1003 } 1004 } 1005 }; 1006 synchronized (mEventCbLock) { 1007 mEventCallbacks.add(ecb); 1008 } 1009 1010 mOnCompletionCalled.reset(); 1011 mPlayer.setDisplay(mActivity.getSurfaceHolder()); 1012 1013 mOnPrepareCalled.reset(); 1014 mPlayer.prepare(); 1015 mOnPrepareCalled.waitForSignal(); 1016 1017 mOnSeekCompleteCalled.reset(); 1018 mPlayer.seekTo(0, MediaPlayer2.SEEK_PREVIOUS_SYNC); 1019 mOnSeekCompleteCalled.waitForSignal(); 1020 1021 final float playbackRate = 1.0f; 1022 1023 int playTime = 2000; // The testing clip is about 10 second long. 1024 mPlayer.setPlaybackParams(new PlaybackParams().setSpeed(playbackRate)); 1025 assertTrue("MediaPlayer2 should be playing", mPlayer.isPlaying()); 1026 Thread.sleep(playTime); 1027 assertTrue("MediaPlayer2 should still be playing", 1028 mPlayer.getCurrentPosition() > 0); 1029 1030 long duration = mPlayer.getDuration(); 1031 mOnSeekCompleteCalled.reset(); 1032 mPlayer.seekTo(duration - 1000, MediaPlayer2.SEEK_PREVIOUS_SYNC); 1033 mOnSeekCompleteCalled.waitForSignal(); 1034 1035 mOnCompletionCalled.waitForSignal(); 1036 assertFalse("MediaPlayer2 should not be playing", mPlayer.isPlaying()); 1037 long eosPosition = mPlayer.getCurrentPosition(); 1038 1039 mPlayer.setPlaybackParams(new PlaybackParams().setSpeed(playbackRate)); 1040 assertTrue("MediaPlayer2 should be playing after EOS", mPlayer.isPlaying()); 1041 Thread.sleep(playTime); 1042 long position = mPlayer.getCurrentPosition(); 1043 assertTrue("MediaPlayer2 should still be playing after EOS", 1044 position > 0 && position < eosPosition); 1045 1046 mPlayer.reset(); 1047 } 1048 */ 1049 1050 public void testPlaybackRate() throws Exception { 1051 if (IGNORE_TESTS) { 1052 return; 1053 } 1054 final int toleranceMs = 1000; 1055 if (!checkLoadResource( 1056 R.raw.video_480x360_mp4_h264_1000kbps_30fps_aac_stereo_128kbps_44100hz)) { 1057 return; // skip 1058 } 1059 1060 MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() { 1061 @Override 1062 public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) { 1063 if (what == MediaPlayer2.MEDIA_INFO_PREPARED) { 1064 mOnPrepareCalled.signal(); 1065 } 1066 } 1067 }; 1068 synchronized (mEventCbLock) { 1069 mEventCallbacks.add(ecb); 1070 } 1071 mPlayer.setDisplay(mActivity.getSurfaceHolder()); 1072 1073 mOnPrepareCalled.reset(); 1074 mPlayer.prepare(); 1075 mOnPrepareCalled.waitForSignal(); 1076 1077 SyncParams sync = new SyncParams().allowDefaults(); 1078 mPlayer.setSyncParams(sync); 1079 sync = mPlayer.getSyncParams(); 1080 1081 float[] rates = { 0.25f, 0.5f, 1.0f, 2.0f }; 1082 for (float playbackRate : rates) { 1083 mPlayer.seekTo(0, MediaPlayer2.SEEK_PREVIOUS_SYNC); 1084 Thread.sleep(1000); 1085 int playTime = 4000; // The testing clip is about 10 second long. 1086 mPlayer.setPlaybackParams(new PlaybackParams().setSpeed(playbackRate)); 1087 mPlayer.play(); 1088 Thread.sleep(playTime); 1089 PlaybackParams pbp = mPlayer.getPlaybackParams(); 1090 assertEquals( 1091 playbackRate, pbp.getSpeed(), 1092 FLOAT_TOLERANCE + playbackRate * sync.getTolerance()); 1093 assertTrue("MediaPlayer2 should still be playing", mPlayer.isPlaying()); 1094 1095 long playedMediaDurationMs = mPlayer.getCurrentPosition(); 1096 int diff = Math.abs((int)(playedMediaDurationMs / playbackRate) - playTime); 1097 if (diff > toleranceMs) { 1098 fail("Media player had error in playback rate " + playbackRate 1099 + ", play time is " + playTime + " vs expected " + playedMediaDurationMs); 1100 } 1101 mPlayer.pause(); 1102 pbp = mPlayer.getPlaybackParams(); 1103 // TODO: pause() should NOT change PlaybackParams. 1104 // assertEquals(0.f, pbp.getSpeed(), FLOAT_TOLERANCE); 1105 } 1106 mPlayer.reset(); 1107 } 1108 1109 public void testSeekModes() throws Exception { 1110 if (IGNORE_TESTS) { 1111 return; 1112 } 1113 // This clip has 2 I frames at 66687us and 4299687us. 1114 if (!checkLoadResource( 1115 R.raw.bbb_s1_320x240_mp4_h264_mp2_800kbps_30fps_aac_lc_5ch_240kbps_44100hz)) { 1116 return; // skip 1117 } 1118 1119 MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() { 1120 @Override 1121 public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) { 1122 if (what == MediaPlayer2.MEDIA_INFO_PREPARED) { 1123 mOnPrepareCalled.signal(); 1124 } 1125 } 1126 1127 @Override 1128 public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd, int what, int status) { 1129 if (what == MediaPlayer2.CALL_COMPLETED_SEEK_TO) { 1130 mOnSeekCompleteCalled.signal(); 1131 } 1132 } 1133 }; 1134 synchronized (mEventCbLock) { 1135 mEventCallbacks.add(ecb); 1136 } 1137 1138 mPlayer.setDisplay(mActivity.getSurfaceHolder()); 1139 1140 mOnPrepareCalled.reset(); 1141 mPlayer.prepare(); 1142 mOnPrepareCalled.waitForSignal(); 1143 1144 mOnSeekCompleteCalled.reset(); 1145 mPlayer.play(); 1146 1147 final long seekPosMs = 3000; 1148 final long timeToleranceMs = 100; 1149 final long syncTime1Ms = 67; 1150 final long syncTime2Ms = 4300; 1151 1152 // TODO: tighten checking range. For now, ensure mediaplayer doesn't 1153 // seek to previous sync or next sync. 1154 long cp = runSeekMode(MediaPlayer2.SEEK_CLOSEST, seekPosMs); 1155 assertTrue("MediaPlayer2 did not seek to closest position", 1156 cp > seekPosMs && cp < syncTime2Ms); 1157 1158 // TODO: tighten checking range. For now, ensure mediaplayer doesn't 1159 // seek to closest position or next sync. 1160 cp = runSeekMode(MediaPlayer2.SEEK_PREVIOUS_SYNC, seekPosMs); 1161 assertTrue("MediaPlayer2 did not seek to preivous sync position", 1162 cp < seekPosMs - timeToleranceMs); 1163 1164 // TODO: tighten checking range. For now, ensure mediaplayer doesn't 1165 // seek to closest position or previous sync. 1166 cp = runSeekMode(MediaPlayer2.SEEK_NEXT_SYNC, seekPosMs); 1167 assertTrue("MediaPlayer2 did not seek to next sync position", 1168 cp > syncTime2Ms - timeToleranceMs); 1169 1170 // TODO: tighten checking range. For now, ensure mediaplayer doesn't 1171 // seek to closest position or previous sync. 1172 cp = runSeekMode(MediaPlayer2.SEEK_CLOSEST_SYNC, seekPosMs); 1173 assertTrue("MediaPlayer2 did not seek to closest sync position", 1174 cp > syncTime2Ms - timeToleranceMs); 1175 1176 mPlayer.reset(); 1177 } 1178 1179 private long runSeekMode(int seekMode, long seekPosMs) throws Exception { 1180 final int sleepIntervalMs = 100; 1181 int timeRemainedMs = 10000; // total time for testing 1182 final int timeToleranceMs = 100; 1183 1184 mPlayer.seekTo(seekPosMs, seekMode); 1185 mOnSeekCompleteCalled.waitForSignal(); 1186 mOnSeekCompleteCalled.reset(); 1187 long cp = -seekPosMs; 1188 while (timeRemainedMs > 0) { 1189 cp = mPlayer.getCurrentPosition(); 1190 // Wait till MediaPlayer2 starts rendering since MediaPlayer2 caches 1191 // seek position as current position. 1192 if (cp < seekPosMs - timeToleranceMs || cp > seekPosMs + timeToleranceMs) { 1193 break; 1194 } 1195 timeRemainedMs -= sleepIntervalMs; 1196 Thread.sleep(sleepIntervalMs); 1197 } 1198 assertTrue("MediaPlayer2 did not finish seeking in time for mode " + seekMode, 1199 timeRemainedMs > 0); 1200 return cp; 1201 } 1202 1203 public void testGetTimestamp() throws Exception { 1204 if (IGNORE_TESTS) { 1205 return; 1206 } 1207 final int toleranceUs = 100000; 1208 final float playbackRate = 1.0f; 1209 if (!checkLoadResource( 1210 R.raw.video_480x360_mp4_h264_1000kbps_30fps_aac_stereo_128kbps_44100hz)) { 1211 return; // skip 1212 } 1213 1214 Monitor onPauseCalled = new Monitor(); 1215 MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() { 1216 @Override 1217 public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) { 1218 if (what == MediaPlayer2.MEDIA_INFO_PREPARED) { 1219 mOnPrepareCalled.signal(); 1220 } 1221 } 1222 1223 @Override 1224 public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd, int what, int status) { 1225 if (what == MediaPlayer2.CALL_COMPLETED_PAUSE) { 1226 onPauseCalled.signal(); 1227 } 1228 } 1229 }; 1230 synchronized (mEventCbLock) { 1231 mEventCallbacks.add(ecb); 1232 } 1233 1234 mPlayer.setDisplay(mActivity.getSurfaceHolder()); 1235 1236 mOnPrepareCalled.reset(); 1237 mPlayer.prepare(); 1238 mOnPrepareCalled.waitForSignal(); 1239 1240 mPlayer.play(); 1241 mPlayer.setPlaybackParams(new PlaybackParams().setSpeed(playbackRate)); 1242 Thread.sleep(SLEEP_TIME); // let player get into stable state. 1243 long nt1 = System.nanoTime(); 1244 MediaTimestamp ts1 = mPlayer.getTimestamp(); 1245 long nt2 = System.nanoTime(); 1246 assertTrue("Media player should return a valid time stamp", ts1 != null); 1247 assertEquals("MediaPlayer2 had error in clockRate " + ts1.getMediaClockRate(), 1248 playbackRate, ts1.getMediaClockRate(), 0.001f); 1249 assertTrue("The nanoTime of Media timestamp should be taken when getTimestamp is called.", 1250 nt1 <= ts1.getAnchorSytemNanoTime() && ts1.getAnchorSytemNanoTime() <= nt2); 1251 1252 onPauseCalled.reset(); 1253 mPlayer.pause(); 1254 onPauseCalled.waitForSignal(); 1255 ts1 = mPlayer.getTimestamp(); 1256 assertTrue("Media player should return a valid time stamp", ts1 != null); 1257 assertTrue("Media player should have play rate of 0.0f when paused", 1258 ts1.getMediaClockRate() == 0.0f); 1259 1260 mPlayer.seekTo(0, MediaPlayer2.SEEK_PREVIOUS_SYNC); 1261 mPlayer.play(); 1262 Thread.sleep(SLEEP_TIME); // let player get into stable state. 1263 int playTime = 4000; // The testing clip is about 10 second long. 1264 ts1 = mPlayer.getTimestamp(); 1265 assertTrue("Media player should return a valid time stamp", ts1 != null); 1266 Thread.sleep(playTime); 1267 MediaTimestamp ts2 = mPlayer.getTimestamp(); 1268 assertTrue("Media player should return a valid time stamp", ts2 != null); 1269 assertTrue("The clockRate should not be changed.", 1270 ts1.getMediaClockRate() == ts2.getMediaClockRate()); 1271 assertEquals("MediaPlayer2 had error in timestamp.", 1272 ts1.getAnchorMediaTimeUs() + (long)(playTime * ts1.getMediaClockRate() * 1000), 1273 ts2.getAnchorMediaTimeUs(), toleranceUs); 1274 1275 mPlayer.reset(); 1276 } 1277 1278 public void testLocalVideo_MKV_H265_1280x720_500kbps_25fps_AAC_Stereo_128kbps_44100Hz() 1279 throws Exception { 1280 if (IGNORE_TESTS) { 1281 return; 1282 } 1283 playVideoTest( 1284 R.raw.video_1280x720_mkv_h265_500kbps_25fps_aac_stereo_128kbps_44100hz, 1280, 720); 1285 } 1286 public void testLocalVideo_MP4_H264_480x360_500kbps_25fps_AAC_Stereo_128kbps_44110Hz() 1287 throws Exception { 1288 if (IGNORE_TESTS) { 1289 return; 1290 } 1291 playVideoTest( 1292 R.raw.video_480x360_mp4_h264_500kbps_25fps_aac_stereo_128kbps_44100hz, 480, 360); 1293 } 1294 1295 public void testLocalVideo_MP4_H264_480x360_500kbps_30fps_AAC_Stereo_128kbps_44110Hz() 1296 throws Exception { 1297 if (IGNORE_TESTS) { 1298 return; 1299 } 1300 playVideoTest( 1301 R.raw.video_480x360_mp4_h264_500kbps_30fps_aac_stereo_128kbps_44100hz, 480, 360); 1302 } 1303 1304 public void testLocalVideo_MP4_H264_480x360_1000kbps_25fps_AAC_Stereo_128kbps_44110Hz() 1305 throws Exception { 1306 if (IGNORE_TESTS) { 1307 return; 1308 } 1309 playVideoTest( 1310 R.raw.video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz, 480, 360); 1311 } 1312 1313 public void testLocalVideo_MP4_H264_480x360_1000kbps_30fps_AAC_Stereo_128kbps_44110Hz() 1314 throws Exception { 1315 if (IGNORE_TESTS) { 1316 return; 1317 } 1318 playVideoTest( 1319 R.raw.video_480x360_mp4_h264_1000kbps_30fps_aac_stereo_128kbps_44100hz, 480, 360); 1320 } 1321 1322 public void testLocalVideo_MP4_H264_480x360_1350kbps_25fps_AAC_Stereo_128kbps_44110Hz() 1323 throws Exception { 1324 if (IGNORE_TESTS) { 1325 return; 1326 } 1327 playVideoTest( 1328 R.raw.video_480x360_mp4_h264_1350kbps_25fps_aac_stereo_128kbps_44100hz, 480, 360); 1329 } 1330 1331 public void testLocalVideo_MP4_H264_480x360_1350kbps_30fps_AAC_Stereo_128kbps_44110Hz() 1332 throws Exception { 1333 if (IGNORE_TESTS) { 1334 return; 1335 } 1336 playVideoTest( 1337 R.raw.video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_128kbps_44100hz, 480, 360); 1338 } 1339 1340 public void testLocalVideo_MP4_H264_480x360_1350kbps_30fps_AAC_Stereo_128kbps_44110Hz_frag() 1341 throws Exception { 1342 if (IGNORE_TESTS) { 1343 return; 1344 } 1345 playVideoTest( 1346 R.raw.video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_128kbps_44100hz_fragmented, 1347 480, 360); 1348 } 1349 1350 1351 public void testLocalVideo_MP4_H264_480x360_1350kbps_30fps_AAC_Stereo_192kbps_44110Hz() 1352 throws Exception { 1353 if (IGNORE_TESTS) { 1354 return; 1355 } 1356 playVideoTest( 1357 R.raw.video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_192kbps_44100hz, 480, 360); 1358 } 1359 1360 public void testLocalVideo_3gp_H263_176x144_56kbps_12fps_AAC_Mono_24kbps_11025Hz() 1361 throws Exception { 1362 if (IGNORE_TESTS) { 1363 return; 1364 } 1365 playVideoTest( 1366 R.raw.video_176x144_3gp_h263_56kbps_12fps_aac_mono_24kbps_11025hz, 176, 144); 1367 } 1368 1369 public void testLocalVideo_3gp_H263_176x144_56kbps_12fps_AAC_Mono_24kbps_22050Hz() 1370 throws Exception { 1371 if (IGNORE_TESTS) { 1372 return; 1373 } 1374 playVideoTest( 1375 R.raw.video_176x144_3gp_h263_56kbps_12fps_aac_mono_24kbps_22050hz, 176, 144); 1376 } 1377 1378 public void testLocalVideo_3gp_H263_176x144_56kbps_12fps_AAC_Stereo_24kbps_11025Hz() 1379 throws Exception { 1380 if (IGNORE_TESTS) { 1381 return; 1382 } 1383 playVideoTest( 1384 R.raw.video_176x144_3gp_h263_56kbps_12fps_aac_stereo_24kbps_11025hz, 176, 144); 1385 } 1386 1387 public void testLocalVideo_3gp_H263_176x144_56kbps_12fps_AAC_Stereo_24kbps_22050Hz() 1388 throws Exception { 1389 if (IGNORE_TESTS) { 1390 return; 1391 } 1392 playVideoTest( 1393 R.raw.video_176x144_3gp_h263_56kbps_12fps_aac_stereo_24kbps_11025hz, 176, 144); 1394 } 1395 1396 public void testLocalVideo_3gp_H263_176x144_56kbps_12fps_AAC_Stereo_128kbps_11025Hz() 1397 throws Exception { 1398 if (IGNORE_TESTS) { 1399 return; 1400 } 1401 playVideoTest( 1402 R.raw.video_176x144_3gp_h263_56kbps_12fps_aac_stereo_128kbps_11025hz, 176, 144); 1403 } 1404 1405 public void testLocalVideo_3gp_H263_176x144_56kbps_12fps_AAC_Stereo_128kbps_22050Hz() 1406 throws Exception { 1407 if (IGNORE_TESTS) { 1408 return; 1409 } 1410 playVideoTest( 1411 R.raw.video_176x144_3gp_h263_56kbps_12fps_aac_stereo_128kbps_11025hz, 176, 144); 1412 } 1413 1414 public void testLocalVideo_3gp_H263_176x144_56kbps_25fps_AAC_Mono_24kbps_11025Hz() 1415 throws Exception { 1416 if (IGNORE_TESTS) { 1417 return; 1418 } 1419 playVideoTest( 1420 R.raw.video_176x144_3gp_h263_56kbps_25fps_aac_mono_24kbps_11025hz, 176, 144); 1421 } 1422 1423 public void testLocalVideo_3gp_H263_176x144_56kbps_25fps_AAC_Mono_24kbps_22050Hz() 1424 throws Exception { 1425 if (IGNORE_TESTS) { 1426 return; 1427 } 1428 playVideoTest( 1429 R.raw.video_176x144_3gp_h263_56kbps_25fps_aac_mono_24kbps_22050hz, 176, 144); 1430 } 1431 1432 public void testLocalVideo_3gp_H263_176x144_56kbps_25fps_AAC_Stereo_24kbps_11025Hz() 1433 throws Exception { 1434 if (IGNORE_TESTS) { 1435 return; 1436 } 1437 playVideoTest( 1438 R.raw.video_176x144_3gp_h263_56kbps_25fps_aac_stereo_24kbps_11025hz, 176, 144); 1439 } 1440 1441 public void testLocalVideo_3gp_H263_176x144_56kbps_25fps_AAC_Stereo_24kbps_22050Hz() 1442 throws Exception { 1443 if (IGNORE_TESTS) { 1444 return; 1445 } 1446 playVideoTest( 1447 R.raw.video_176x144_3gp_h263_56kbps_25fps_aac_stereo_24kbps_11025hz, 176, 144); 1448 } 1449 1450 public void testLocalVideo_3gp_H263_176x144_56kbps_25fps_AAC_Stereo_128kbps_11025Hz() 1451 throws Exception { 1452 if (IGNORE_TESTS) { 1453 return; 1454 } 1455 playVideoTest( 1456 R.raw.video_176x144_3gp_h263_56kbps_25fps_aac_stereo_128kbps_11025hz, 176, 144); 1457 } 1458 1459 public void testLocalVideo_3gp_H263_176x144_56kbps_25fps_AAC_Stereo_128kbps_22050Hz() 1460 throws Exception { 1461 if (IGNORE_TESTS) { 1462 return; 1463 } 1464 playVideoTest( 1465 R.raw.video_176x144_3gp_h263_56kbps_25fps_aac_stereo_128kbps_11025hz, 176, 144); 1466 } 1467 1468 public void testLocalVideo_3gp_H263_176x144_300kbps_12fps_AAC_Mono_24kbps_11025Hz() 1469 throws Exception { 1470 if (IGNORE_TESTS) { 1471 return; 1472 } 1473 playVideoTest( 1474 R.raw.video_176x144_3gp_h263_300kbps_12fps_aac_mono_24kbps_11025hz, 176, 144); 1475 } 1476 1477 public void testLocalVideo_3gp_H263_176x144_300kbps_12fps_AAC_Mono_24kbps_22050Hz() 1478 throws Exception { 1479 if (IGNORE_TESTS) { 1480 return; 1481 } 1482 playVideoTest( 1483 R.raw.video_176x144_3gp_h263_300kbps_12fps_aac_mono_24kbps_22050hz, 176, 144); 1484 } 1485 1486 public void testLocalVideo_3gp_H263_176x144_300kbps_12fps_AAC_Stereo_24kbps_11025Hz() 1487 throws Exception { 1488 if (IGNORE_TESTS) { 1489 return; 1490 } 1491 playVideoTest( 1492 R.raw.video_176x144_3gp_h263_300kbps_12fps_aac_stereo_24kbps_11025hz, 176, 144); 1493 } 1494 1495 public void testLocalVideo_3gp_H263_176x144_300kbps_12fps_AAC_Stereo_24kbps_22050Hz() 1496 throws Exception { 1497 if (IGNORE_TESTS) { 1498 return; 1499 } 1500 playVideoTest( 1501 R.raw.video_176x144_3gp_h263_300kbps_12fps_aac_stereo_24kbps_11025hz, 176, 144); 1502 } 1503 1504 public void testLocalVideo_3gp_H263_176x144_300kbps_12fps_AAC_Stereo_128kbps_11025Hz() 1505 throws Exception { 1506 if (IGNORE_TESTS) { 1507 return; 1508 } 1509 playVideoTest( 1510 R.raw.video_176x144_3gp_h263_300kbps_12fps_aac_stereo_128kbps_11025hz, 176, 144); 1511 } 1512 1513 public void testLocalVideo_3gp_H263_176x144_300kbps_12fps_AAC_Stereo_128kbps_22050Hz() 1514 throws Exception { 1515 if (IGNORE_TESTS) { 1516 return; 1517 } 1518 playVideoTest( 1519 R.raw.video_176x144_3gp_h263_300kbps_12fps_aac_stereo_128kbps_11025hz, 176, 144); 1520 } 1521 1522 public void testLocalVideo_3gp_H263_176x144_300kbps_25fps_AAC_Mono_24kbps_11025Hz() 1523 throws Exception { 1524 if (IGNORE_TESTS) { 1525 return; 1526 } 1527 playVideoTest( 1528 R.raw.video_176x144_3gp_h263_300kbps_25fps_aac_mono_24kbps_11025hz, 176, 144); 1529 } 1530 1531 public void testLocalVideo_3gp_H263_176x144_300kbps_25fps_AAC_Mono_24kbps_22050Hz() 1532 throws Exception { 1533 if (IGNORE_TESTS) { 1534 return; 1535 } 1536 playVideoTest( 1537 R.raw.video_176x144_3gp_h263_300kbps_25fps_aac_mono_24kbps_22050hz, 176, 144); 1538 } 1539 1540 public void testLocalVideo_3gp_H263_176x144_300kbps_25fps_AAC_Stereo_24kbps_11025Hz() 1541 throws Exception { 1542 if (IGNORE_TESTS) { 1543 return; 1544 } 1545 playVideoTest( 1546 R.raw.video_176x144_3gp_h263_300kbps_25fps_aac_stereo_24kbps_11025hz, 176, 144); 1547 } 1548 1549 public void testLocalVideo_3gp_H263_176x144_300kbps_25fps_AAC_Stereo_24kbps_22050Hz() 1550 throws Exception { 1551 if (IGNORE_TESTS) { 1552 return; 1553 } 1554 playVideoTest( 1555 R.raw.video_176x144_3gp_h263_300kbps_25fps_aac_stereo_24kbps_11025hz, 176, 144); 1556 } 1557 1558 public void testLocalVideo_3gp_H263_176x144_300kbps_25fps_AAC_Stereo_128kbps_11025Hz() 1559 throws Exception { 1560 if (IGNORE_TESTS) { 1561 return; 1562 } 1563 playVideoTest( 1564 R.raw.video_176x144_3gp_h263_300kbps_25fps_aac_stereo_128kbps_11025hz, 176, 144); 1565 } 1566 1567 public void testLocalVideo_3gp_H263_176x144_300kbps_25fps_AAC_Stereo_128kbps_22050Hz() 1568 throws Exception { 1569 if (IGNORE_TESTS) { 1570 return; 1571 } 1572 playVideoTest( 1573 R.raw.video_176x144_3gp_h263_300kbps_25fps_aac_stereo_128kbps_22050hz, 176, 144); 1574 } 1575 1576 private void readSubtitleTracks() throws Exception { 1577 mSubtitleTrackIndex.clear(); 1578 List<MediaPlayer2.TrackInfo> trackInfos = mPlayer.getTrackInfo(); 1579 if (trackInfos == null || trackInfos.size() == 0) { 1580 return; 1581 } 1582 1583 Vector<Integer> subtitleTrackIndex = new Vector<>(); 1584 for (int i = 0; i < trackInfos.size(); ++i) { 1585 assertTrue(trackInfos.get(i) != null); 1586 if (trackInfos.get(i).getTrackType() == 1587 MediaPlayer2.TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE) { 1588 subtitleTrackIndex.add(i); 1589 } 1590 } 1591 1592 mSubtitleTrackIndex.addAll(subtitleTrackIndex); 1593 } 1594 1595 private void selectSubtitleTrack(int index) throws Exception { 1596 int trackIndex = mSubtitleTrackIndex.get(index); 1597 mPlayer.selectTrack(trackIndex); 1598 mSelectedSubtitleIndex = index; 1599 } 1600 1601 private void deselectSubtitleTrack(int index) throws Exception { 1602 int trackIndex = mSubtitleTrackIndex.get(index); 1603 mOnDeselectTrackCalled.reset(); 1604 mPlayer.deselectTrack(trackIndex); 1605 mOnDeselectTrackCalled.waitForSignal(); 1606 if (mSelectedSubtitleIndex == index) { 1607 mSelectedSubtitleIndex = -1; 1608 } 1609 } 1610 1611 public void testDeselectTrackForSubtitleTracks() throws Throwable { 1612 if (IGNORE_TESTS) { 1613 return; 1614 } 1615 if (!checkLoadResource(R.raw.testvideo_with_2_subtitle_tracks)) { 1616 return; // skip; 1617 } 1618 1619 getInstrumentation().waitForIdleSync(); 1620 1621 MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() { 1622 @Override 1623 public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) { 1624 if (what == MediaPlayer2.MEDIA_INFO_PREPARED) { 1625 mOnPrepareCalled.signal(); 1626 } else if (what == MediaPlayer2.MEDIA_INFO_METADATA_UPDATE) { 1627 mOnInfoCalled.signal(); 1628 } 1629 } 1630 1631 @Override 1632 public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd, int what, int status) { 1633 if (what == MediaPlayer2.CALL_COMPLETED_SEEK_TO) { 1634 mOnSeekCompleteCalled.signal(); 1635 } else if (what == MediaPlayer2.CALL_COMPLETED_PLAY) { 1636 mOnPlayCalled.signal(); 1637 } else if (what == MediaPlayer2.CALL_COMPLETED_DESELECT_TRACK) { 1638 mCallStatus = status; 1639 mOnDeselectTrackCalled.signal(); 1640 } 1641 } 1642 }; 1643 synchronized (mEventCbLock) { 1644 mEventCallbacks.add(ecb); 1645 } 1646 1647 mPlayer.setOnSubtitleDataListener(new MediaPlayer2.OnSubtitleDataListener() { 1648 @Override 1649 public void onSubtitleData(MediaPlayer2 mp, SubtitleData data) { 1650 if (data != null && data.getData() != null) { 1651 mOnSubtitleDataCalled.signal(); 1652 } 1653 } 1654 }); 1655 1656 mPlayer.setDisplay(getActivity().getSurfaceHolder()); 1657 mPlayer.setScreenOnWhilePlaying(true); 1658 mPlayer.setWakeMode(mContext, PowerManager.PARTIAL_WAKE_LOCK); 1659 1660 mOnPrepareCalled.reset(); 1661 mPlayer.prepare(); 1662 mOnPrepareCalled.waitForSignal(); 1663 1664 mOnPlayCalled.reset(); 1665 mPlayer.play(); 1666 mOnPlayCalled.waitForSignal(); 1667 assertTrue(mPlayer.isPlaying()); 1668 1669 // Closed caption tracks are in-band. 1670 // So, those tracks will be found after processing a number of frames. 1671 mOnInfoCalled.waitForSignal(1500); 1672 1673 mOnInfoCalled.reset(); 1674 mOnInfoCalled.waitForSignal(1500); 1675 1676 readSubtitleTracks(); 1677 1678 // Run twice to check if repeated selection-deselection on the same track works well. 1679 for (int i = 0; i < 2; i++) { 1680 // Waits until at least one subtitle is fired. Timeout is 2.5 seconds. 1681 selectSubtitleTrack(i); 1682 mOnSubtitleDataCalled.reset(); 1683 assertTrue(mOnSubtitleDataCalled.waitForSignal(2500)); 1684 1685 // Try deselecting track. 1686 deselectSubtitleTrack(i); 1687 mOnSubtitleDataCalled.reset(); 1688 assertFalse(mOnSubtitleDataCalled.waitForSignal(1500)); 1689 } 1690 1691 // Deselecting unselected track: expected error status 1692 mCallStatus = MediaPlayer2.CALL_STATUS_NO_ERROR; 1693 deselectSubtitleTrack(0); 1694 assertTrue(mCallStatus != MediaPlayer2.CALL_STATUS_NO_ERROR); 1695 1696 mPlayer.reset(); 1697 } 1698 1699 public void testChangeSubtitleTrack() throws Throwable { 1700 if (IGNORE_TESTS) { 1701 return; 1702 } 1703 if (!checkLoadResource(R.raw.testvideo_with_2_subtitle_tracks)) { 1704 return; // skip; 1705 } 1706 1707 mPlayer.setOnSubtitleDataListener(new MediaPlayer2.OnSubtitleDataListener() { 1708 @Override 1709 public void onSubtitleData(MediaPlayer2 mp, SubtitleData data) { 1710 if (data != null && data.getData() != null) { 1711 mOnSubtitleDataCalled.signal(); 1712 } 1713 } 1714 }); 1715 1716 MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() { 1717 @Override 1718 public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) { 1719 if (what == MediaPlayer2.MEDIA_INFO_PREPARED) { 1720 mOnPrepareCalled.signal(); 1721 } else if (what == MediaPlayer2.MEDIA_INFO_METADATA_UPDATE) { 1722 mOnInfoCalled.signal(); 1723 } 1724 } 1725 1726 @Override 1727 public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd, int what, int status) { 1728 if (what == MediaPlayer2.CALL_COMPLETED_PLAY) { 1729 mOnPlayCalled.signal(); 1730 } 1731 } 1732 }; 1733 synchronized (mEventCbLock) { 1734 mEventCallbacks.add(ecb); 1735 } 1736 1737 mPlayer.setDisplay(getActivity().getSurfaceHolder()); 1738 mPlayer.setScreenOnWhilePlaying(true); 1739 mPlayer.setWakeMode(mContext, PowerManager.PARTIAL_WAKE_LOCK); 1740 1741 mOnPrepareCalled.reset(); 1742 mPlayer.prepare(); 1743 mOnPrepareCalled.waitForSignal(); 1744 1745 mOnPlayCalled.reset(); 1746 mPlayer.play(); 1747 mOnPlayCalled.waitForSignal(); 1748 assertTrue(mPlayer.isPlaying()); 1749 1750 // Closed caption tracks are in-band. 1751 // So, those tracks will be found after processing a number of frames. 1752 mOnInfoCalled.waitForSignal(1500); 1753 1754 mOnInfoCalled.reset(); 1755 mOnInfoCalled.waitForSignal(1500); 1756 1757 readSubtitleTracks(); 1758 1759 // Waits until at least two captions are fired. Timeout is 2.5 sec. 1760 selectSubtitleTrack(0); 1761 assertTrue(mOnSubtitleDataCalled.waitForCountedSignals(2, 2500) >= 2); 1762 1763 mOnSubtitleDataCalled.reset(); 1764 selectSubtitleTrack(1); 1765 assertTrue(mOnSubtitleDataCalled.waitForCountedSignals(2, 2500) >= 2); 1766 1767 mPlayer.reset(); 1768 } 1769 1770 public void testGetTrackInfoForVideoWithSubtitleTracks() throws Throwable { 1771 if (IGNORE_TESTS) { 1772 return; 1773 } 1774 if (!checkLoadResource(R.raw.testvideo_with_2_subtitle_tracks)) { 1775 return; // skip; 1776 } 1777 1778 getInstrumentation().waitForIdleSync(); 1779 1780 MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() { 1781 @Override 1782 public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) { 1783 if (what == MediaPlayer2.MEDIA_INFO_PREPARED) { 1784 mOnPrepareCalled.signal(); 1785 } else if (what == MediaPlayer2.MEDIA_INFO_METADATA_UPDATE) { 1786 mOnInfoCalled.signal(); 1787 } 1788 } 1789 1790 @Override 1791 public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd, int what, int status) { 1792 if (what == MediaPlayer2.CALL_COMPLETED_PLAY) { 1793 mOnPlayCalled.signal(); 1794 } 1795 } 1796 }; 1797 synchronized (mEventCbLock) { 1798 mEventCallbacks.add(ecb); 1799 } 1800 1801 mPlayer.setDisplay(getActivity().getSurfaceHolder()); 1802 mPlayer.setScreenOnWhilePlaying(true); 1803 mPlayer.setWakeMode(mContext, PowerManager.PARTIAL_WAKE_LOCK); 1804 1805 mOnPrepareCalled.reset(); 1806 mPlayer.prepare(); 1807 mOnPrepareCalled.waitForSignal(); 1808 1809 mOnPlayCalled.reset(); 1810 mPlayer.play(); 1811 mOnPlayCalled.waitForSignal(); 1812 assertTrue(mPlayer.isPlaying()); 1813 1814 // The media metadata will be changed while playing since closed caption tracks are in-band 1815 // and those tracks will be found after processing a number of frames. These tracks will be 1816 // found within one second. 1817 mOnInfoCalled.waitForSignal(1500); 1818 1819 mOnInfoCalled.reset(); 1820 mOnInfoCalled.waitForSignal(1500); 1821 1822 readSubtitleTracks(); 1823 assertEquals(2, mSubtitleTrackIndex.size()); 1824 1825 mPlayer.reset(); 1826 } 1827 1828 /* 1829 * This test assumes the resources being tested are between 8 and 14 seconds long 1830 * The ones being used here are 10 seconds long. 1831 */ 1832 public void testResumeAtEnd() throws Throwable { 1833 if (IGNORE_TESTS) { 1834 return; 1835 } 1836 int testsRun = 1837 testResumeAtEnd(R.raw.loudsoftmp3) + 1838 testResumeAtEnd(R.raw.loudsoftwav) + 1839 testResumeAtEnd(R.raw.loudsoftogg) + 1840 testResumeAtEnd(R.raw.loudsoftitunes) + 1841 testResumeAtEnd(R.raw.loudsoftfaac) + 1842 testResumeAtEnd(R.raw.loudsoftaac); 1843 if (testsRun == 0) { 1844 MediaUtils.skipTest("no decoder found"); 1845 } 1846 } 1847 1848 // returns 1 if test was run, 0 otherwise 1849 private int testResumeAtEnd(int res) throws Throwable { 1850 if (!loadResource(res)) { 1851 Log.i(LOG_TAG, "testResumeAtEnd: No decoder found for " + 1852 mContext.getResources().getResourceEntryName(res) + 1853 " --- skipping."); 1854 return 0; // skip 1855 } 1856 mOnCompletionCalled.reset(); 1857 MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() { 1858 @Override 1859 public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) { 1860 if (what == MediaPlayer2.MEDIA_INFO_PREPARED) { 1861 mOnPrepareCalled.signal(); 1862 } else if (what == MediaPlayer2.MEDIA_INFO_PLAYBACK_COMPLETE) { 1863 mOnCompletionCalled.signal(); 1864 mPlayer.play(); 1865 } 1866 } 1867 }; 1868 mPlayer.setMediaPlayer2EventCallback(mExecutor, ecb); 1869 1870 mOnPrepareCalled.reset(); 1871 mPlayer.prepare(); 1872 mOnPrepareCalled.waitForSignal(); 1873 1874 // skip the first part of the file so we reach EOF sooner 1875 mPlayer.seekTo(5000, MediaPlayer2.SEEK_PREVIOUS_SYNC); 1876 mPlayer.play(); 1877 // sleep long enough that we restart playback at least once, but no more 1878 Thread.sleep(10000); 1879 assertTrue("MediaPlayer2 should still be playing", mPlayer.isPlaying()); 1880 mPlayer.reset(); 1881 assertEquals("wrong number of repetitions", 1, mOnCompletionCalled.getNumSignal()); 1882 return 1; 1883 } 1884 1885 public void testPositionAtEnd() throws Throwable { 1886 if (IGNORE_TESTS) { 1887 return; 1888 } 1889 int testsRun = 1890 testPositionAtEnd(R.raw.test1m1shighstereo) + 1891 testPositionAtEnd(R.raw.loudsoftmp3) + 1892 testPositionAtEnd(R.raw.loudsoftwav) + 1893 testPositionAtEnd(R.raw.loudsoftogg) + 1894 testPositionAtEnd(R.raw.loudsoftitunes) + 1895 testPositionAtEnd(R.raw.loudsoftfaac) + 1896 testPositionAtEnd(R.raw.loudsoftaac); 1897 if (testsRun == 0) { 1898 MediaUtils.skipTest(LOG_TAG, "no decoder found"); 1899 } 1900 } 1901 1902 private int testPositionAtEnd(int res) throws Throwable { 1903 if (!loadResource(res)) { 1904 Log.i(LOG_TAG, "testPositionAtEnd: No decoder found for " + 1905 mContext.getResources().getResourceEntryName(res) + 1906 " --- skipping."); 1907 return 0; // skip 1908 } 1909 AudioAttributes attributes = new AudioAttributes.Builder() 1910 .setInternalLegacyStreamType(AudioManager.STREAM_MUSIC) 1911 .build(); 1912 mPlayer.setAudioAttributes(attributes); 1913 1914 mOnCompletionCalled.reset(); 1915 MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() { 1916 @Override 1917 public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) { 1918 if (what == MediaPlayer2.MEDIA_INFO_PREPARED) { 1919 mOnPrepareCalled.signal(); 1920 } else if (what == MediaPlayer2.MEDIA_INFO_PLAYBACK_COMPLETE) { 1921 mOnCompletionCalled.signal(); 1922 } 1923 } 1924 1925 @Override 1926 public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd, int what, int status) { 1927 if (what == MediaPlayer2.CALL_COMPLETED_PLAY) { 1928 mOnPlayCalled.signal(); 1929 } 1930 } 1931 }; 1932 mPlayer.setMediaPlayer2EventCallback(mExecutor, ecb); 1933 1934 mOnPrepareCalled.reset(); 1935 mPlayer.prepare(); 1936 mOnPrepareCalled.waitForSignal(); 1937 1938 long duration = mPlayer.getDuration(); 1939 assertTrue("resource too short", duration > 6000); 1940 mPlayer.seekTo(duration - 5000, MediaPlayer2.SEEK_PREVIOUS_SYNC); 1941 mOnPlayCalled.reset(); 1942 mPlayer.play(); 1943 mOnPlayCalled.waitForSignal(); 1944 while (mPlayer.isPlaying()) { 1945 Log.i("@@@@", "position: " + mPlayer.getCurrentPosition()); 1946 Thread.sleep(500); 1947 } 1948 Log.i("@@@@", "final position: " + mPlayer.getCurrentPosition()); 1949 assertTrue(mPlayer.getCurrentPosition() > duration - 1000); 1950 mPlayer.reset(); 1951 return 1; 1952 } 1953 1954 public void testCallback() throws Throwable { 1955 if (IGNORE_TESTS) { 1956 return; 1957 } 1958 final int mp4Duration = 8484; 1959 1960 if (!checkLoadResource(R.raw.testvideo)) { 1961 return; // skip; 1962 } 1963 1964 mPlayer.setDisplay(getActivity().getSurfaceHolder()); 1965 mPlayer.setScreenOnWhilePlaying(true); 1966 1967 mOnCompletionCalled.reset(); 1968 MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() { 1969 @Override 1970 public void onVideoSizeChanged(MediaPlayer2 mp, DataSourceDesc dsd, 1971 int width, int height) { 1972 mOnVideoSizeChangedCalled.signal(); 1973 } 1974 1975 @Override 1976 public void onError(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) { 1977 mOnErrorCalled.signal(); 1978 } 1979 1980 @Override 1981 public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) { 1982 mOnInfoCalled.signal(); 1983 1984 if (what == MediaPlayer2.MEDIA_INFO_PREPARED) { 1985 mOnPrepareCalled.signal(); 1986 } else if (what == MediaPlayer2.MEDIA_INFO_PLAYBACK_COMPLETE) { 1987 mOnCompletionCalled.signal(); 1988 } 1989 } 1990 1991 @Override 1992 public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd, int what, int status) { 1993 if (what == MediaPlayer2.CALL_COMPLETED_SEEK_TO) { 1994 mOnSeekCompleteCalled.signal(); 1995 } else if (what == MediaPlayer2.CALL_COMPLETED_PLAY) { 1996 mOnPlayCalled.signal(); 1997 } 1998 } 1999 }; 2000 synchronized (mEventCbLock) { 2001 mEventCallbacks.add(ecb); 2002 } 2003 2004 assertFalse(mOnPrepareCalled.isSignalled()); 2005 assertFalse(mOnVideoSizeChangedCalled.isSignalled()); 2006 mPlayer.prepare(); 2007 mOnPrepareCalled.waitForSignal(); 2008 mOnVideoSizeChangedCalled.waitForSignal(); 2009 2010 mOnSeekCompleteCalled.reset(); 2011 mPlayer.seekTo(mp4Duration >> 1, MediaPlayer2.SEEK_PREVIOUS_SYNC); 2012 mOnSeekCompleteCalled.waitForSignal(); 2013 2014 assertFalse(mOnCompletionCalled.isSignalled()); 2015 mPlayer.play(); 2016 mOnPlayCalled.waitForSignal(); 2017 while(mPlayer.isPlaying()) { 2018 Thread.sleep(SLEEP_TIME); 2019 } 2020 assertFalse(mPlayer.isPlaying()); 2021 mOnCompletionCalled.waitForSignal(); 2022 assertFalse(mOnErrorCalled.isSignalled()); 2023 mPlayer.reset(); 2024 } 2025 2026 public void testRecordAndPlay() throws Exception { 2027 if (IGNORE_TESTS) { 2028 return; 2029 } 2030 if (!hasMicrophone()) { 2031 MediaUtils.skipTest(LOG_TAG, "no microphone"); 2032 return; 2033 } 2034 if (!MediaUtils.checkDecoder(MediaFormat.MIMETYPE_AUDIO_AMR_NB) 2035 || !MediaUtils.checkEncoder(MediaFormat.MIMETYPE_AUDIO_AMR_NB)) { 2036 return; // skip 2037 } 2038 File outputFile = new File(Environment.getExternalStorageDirectory(), 2039 "record_and_play.3gp"); 2040 String outputFileLocation = outputFile.getAbsolutePath(); 2041 try { 2042 recordMedia(outputFileLocation); 2043 2044 Uri uri = Uri.parse(outputFileLocation); 2045 MediaPlayer2 mp = MediaPlayer2.create(); 2046 try { 2047 mp.setDataSource(new DataSourceDesc.Builder() 2048 .setDataSource(mContext, uri) 2049 .build()); 2050 mp.prepare(); 2051 Thread.sleep(SLEEP_TIME); 2052 playAndStop(mp); 2053 } finally { 2054 mp.close(); 2055 } 2056 2057 try { 2058 mp = createMediaPlayer2(mContext, uri); 2059 playAndStop(mp); 2060 } finally { 2061 if (mp != null) { 2062 mp.close(); 2063 } 2064 } 2065 2066 try { 2067 mp = createMediaPlayer2(mContext, uri, getActivity().getSurfaceHolder()); 2068 playAndStop(mp); 2069 } finally { 2070 if (mp != null) { 2071 mp.close(); 2072 } 2073 } 2074 } finally { 2075 outputFile.delete(); 2076 } 2077 } 2078 2079 private void playAndStop(MediaPlayer2 mp) throws Exception { 2080 mp.play(); 2081 Thread.sleep(SLEEP_TIME); 2082 mp.reset(); 2083 } 2084 2085 private void recordMedia(String outputFile) throws Exception { 2086 MediaRecorder mr = new MediaRecorder(); 2087 try { 2088 mr.setAudioSource(MediaRecorder.AudioSource.MIC); 2089 mr.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); 2090 mr.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); 2091 mr.setOutputFile(outputFile); 2092 2093 mr.prepare(); 2094 mr.start(); 2095 Thread.sleep(SLEEP_TIME); 2096 mr.stop(); 2097 } finally { 2098 mr.release(); 2099 } 2100 } 2101 2102 private boolean hasMicrophone() { 2103 return getActivity().getPackageManager().hasSystemFeature( 2104 PackageManager.FEATURE_MICROPHONE); 2105 } 2106 2107 // Smoke test playback from a Media2DataSource. 2108 public void testPlaybackFromAMedia2DataSource() throws Exception { 2109 if (IGNORE_TESTS) { 2110 return; 2111 } 2112 final int resid = R.raw.video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_192kbps_44100hz; 2113 final int duration = 10000; 2114 2115 if (!MediaUtils.hasCodecsForResource(mContext, resid)) { 2116 return; 2117 } 2118 2119 TestMedia2DataSource dataSource = 2120 TestMedia2DataSource.fromAssetFd(mResources.openRawResourceFd(resid)); 2121 // Test returning -1 from getSize() to indicate unknown size. 2122 dataSource.returnFromGetSize(-1); 2123 mPlayer.setDataSource(new DataSourceDesc.Builder() 2124 .setDataSource(dataSource) 2125 .build()); 2126 playLoadedVideo(null, null, -1); 2127 assertTrue(mPlayer.isPlaying()); 2128 2129 // Test pause and restart. 2130 mPlayer.pause(); 2131 Thread.sleep(SLEEP_TIME); 2132 assertFalse(mPlayer.isPlaying()); 2133 2134 MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() { 2135 @Override 2136 public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) { 2137 if (what == MediaPlayer2.MEDIA_INFO_PREPARED) { 2138 mOnPrepareCalled.signal(); 2139 } 2140 } 2141 2142 @Override 2143 public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd, int what, int status) { 2144 if (what == MediaPlayer2.CALL_COMPLETED_PLAY) { 2145 mOnPlayCalled.signal(); 2146 } 2147 } 2148 }; 2149 mPlayer.setMediaPlayer2EventCallback(mExecutor, ecb); 2150 2151 mOnPlayCalled.reset(); 2152 mPlayer.play(); 2153 mOnPlayCalled.waitForSignal(); 2154 assertTrue(mPlayer.isPlaying()); 2155 2156 // Test reset. 2157 mPlayer.reset(); 2158 mPlayer.setDataSource(new DataSourceDesc.Builder() 2159 .setDataSource(dataSource) 2160 .build()); 2161 2162 mPlayer.setMediaPlayer2EventCallback(mExecutor, ecb); 2163 2164 mOnPrepareCalled.reset(); 2165 mPlayer.prepare(); 2166 mOnPrepareCalled.waitForSignal(); 2167 2168 mOnPlayCalled.reset(); 2169 mPlayer.play(); 2170 mOnPlayCalled.waitForSignal(); 2171 assertTrue(mPlayer.isPlaying()); 2172 2173 // Test seek. Note: the seek position is cached and returned as the 2174 // current position so there's no point in comparing them. 2175 mPlayer.seekTo(duration - SLEEP_TIME, MediaPlayer2.SEEK_PREVIOUS_SYNC); 2176 while (mPlayer.isPlaying()) { 2177 Thread.sleep(SLEEP_TIME); 2178 } 2179 } 2180 2181 public void testNullMedia2DataSourceIsRejected() throws Exception { 2182 if (IGNORE_TESTS) { 2183 return; 2184 } 2185 MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() { 2186 @Override 2187 public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd, int what, int status) { 2188 if (what == MediaPlayer2.CALL_COMPLETED_SET_DATA_SOURCE) { 2189 mCallStatus = status; 2190 mOnPlayCalled.signal(); 2191 } 2192 } 2193 }; 2194 mPlayer.setMediaPlayer2EventCallback(mExecutor, ecb); 2195 2196 mCallStatus = MediaPlayer2.CALL_STATUS_NO_ERROR; 2197 mPlayer.setDataSource((DataSourceDesc)null); 2198 mOnPlayCalled.waitForSignal(); 2199 assertTrue(mCallStatus != MediaPlayer2.CALL_STATUS_NO_ERROR); 2200 } 2201 2202 public void testMedia2DataSourceIsClosedOnReset() throws Exception { 2203 if (IGNORE_TESTS) { 2204 return; 2205 } 2206 MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() { 2207 @Override 2208 public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd, int what, int status) { 2209 if (what == MediaPlayer2.CALL_COMPLETED_SET_DATA_SOURCE) { 2210 mCallStatus = status; 2211 mOnPlayCalled.signal(); 2212 } 2213 } 2214 }; 2215 mPlayer.setMediaPlayer2EventCallback(mExecutor, ecb); 2216 2217 TestMedia2DataSource dataSource = new TestMedia2DataSource(new byte[0]); 2218 mPlayer.setDataSource(new DataSourceDesc.Builder() 2219 .setDataSource(dataSource) 2220 .build()); 2221 mOnPlayCalled.waitForSignal(); 2222 mPlayer.reset(); 2223 assertTrue(dataSource.isClosed()); 2224 } 2225 2226 public void testPlaybackFailsIfMedia2DataSourceThrows() throws Exception { 2227 if (IGNORE_TESTS) { 2228 return; 2229 } 2230 final int resid = R.raw.video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_192kbps_44100hz; 2231 if (!MediaUtils.hasCodecsForResource(mContext, resid)) { 2232 return; 2233 } 2234 2235 setOnErrorListener(); 2236 TestMedia2DataSource dataSource = 2237 TestMedia2DataSource.fromAssetFd(mResources.openRawResourceFd(resid)); 2238 mPlayer.setDataSource(new DataSourceDesc.Builder() 2239 .setDataSource(dataSource) 2240 .build()); 2241 2242 MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() { 2243 @Override 2244 public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) { 2245 if (what == MediaPlayer2.MEDIA_INFO_PREPARED) { 2246 mOnPrepareCalled.signal(); 2247 } 2248 } 2249 }; 2250 synchronized (mEventCbLock) { 2251 mEventCallbacks.add(ecb); 2252 } 2253 2254 mOnPrepareCalled.reset(); 2255 mPlayer.prepare(); 2256 mOnPrepareCalled.waitForSignal(); 2257 2258 dataSource.throwFromReadAt(); 2259 mPlayer.play(); 2260 assertTrue(mOnErrorCalled.waitForSignal()); 2261 } 2262 2263 public void testPlaybackFailsIfMedia2DataSourceReturnsAnError() throws Exception { 2264 if (IGNORE_TESTS) { 2265 return; 2266 } 2267 final int resid = R.raw.video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_192kbps_44100hz; 2268 if (!MediaUtils.hasCodecsForResource(mContext, resid)) { 2269 return; 2270 } 2271 2272 TestMedia2DataSource dataSource = 2273 TestMedia2DataSource.fromAssetFd(mResources.openRawResourceFd(resid)); 2274 mPlayer.setDataSource(new DataSourceDesc.Builder() 2275 .setDataSource(dataSource) 2276 .build()); 2277 2278 setOnErrorListener(); 2279 MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() { 2280 @Override 2281 public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) { 2282 if (what == MediaPlayer2.MEDIA_INFO_PREPARED) { 2283 mOnPrepareCalled.signal(); 2284 } 2285 } 2286 }; 2287 synchronized (mEventCbLock) { 2288 mEventCallbacks.add(ecb); 2289 } 2290 2291 mOnPrepareCalled.reset(); 2292 mPlayer.prepare(); 2293 mOnPrepareCalled.waitForSignal(); 2294 2295 dataSource.returnFromReadAt(-2); 2296 mPlayer.play(); 2297 assertTrue(mOnErrorCalled.waitForSignal()); 2298 } 2299 } 2300