AwesomePlayer.cpp revision 1173118eace0e9e347cb007f0da817cee87579ed
1/* 2 * Copyright (C) 2009 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//#define LOG_NDEBUG 0 18#define LOG_TAG "AwesomePlayer" 19#include <utils/Log.h> 20 21#include <dlfcn.h> 22 23#include "include/ARTSPController.h" 24#include "include/AwesomePlayer.h" 25#include "include/SoftwareRenderer.h" 26#include "include/NuCachedSource2.h" 27#include "include/ThrottledSource.h" 28#include "include/MPEG2TSExtractor.h" 29 30#include <binder/IPCThreadState.h> 31#include <binder/IServiceManager.h> 32#include <media/IMediaPlayerService.h> 33#include <media/stagefright/foundation/hexdump.h> 34#include <media/stagefright/foundation/ADebug.h> 35#include <media/stagefright/AudioPlayer.h> 36#include <media/stagefright/DataSource.h> 37#include <media/stagefright/FileSource.h> 38#include <media/stagefright/MediaBuffer.h> 39#include <media/stagefright/MediaDefs.h> 40#include <media/stagefright/MediaExtractor.h> 41#include <media/stagefright/MediaSource.h> 42#include <media/stagefright/MetaData.h> 43#include <media/stagefright/OMXCodec.h> 44 45#include <surfaceflinger/Surface.h> 46#include <gui/ISurfaceTexture.h> 47#include <gui/SurfaceTextureClient.h> 48 49#include <media/stagefright/foundation/ALooper.h> 50#include <media/stagefright/foundation/AMessage.h> 51 52#define USE_SURFACE_ALLOC 1 53#define FRAME_DROP_FREQ 7 54 55namespace android { 56 57static int64_t kLowWaterMarkUs = 2000000ll; // 2secs 58static int64_t kHighWaterMarkUs = 10000000ll; // 10secs 59static int64_t kHighWaterMarkRTSPUs = 4000000ll; // 4secs 60static const size_t kLowWaterMarkBytes = 40000; 61static const size_t kHighWaterMarkBytes = 200000; 62 63struct AwesomeEvent : public TimedEventQueue::Event { 64 AwesomeEvent( 65 AwesomePlayer *player, 66 void (AwesomePlayer::*method)()) 67 : mPlayer(player), 68 mMethod(method) { 69 } 70 71protected: 72 virtual ~AwesomeEvent() {} 73 74 virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) { 75 (mPlayer->*mMethod)(); 76 } 77 78private: 79 AwesomePlayer *mPlayer; 80 void (AwesomePlayer::*mMethod)(); 81 82 AwesomeEvent(const AwesomeEvent &); 83 AwesomeEvent &operator=(const AwesomeEvent &); 84}; 85 86struct AwesomeLocalRenderer : public AwesomeRenderer { 87 AwesomeLocalRenderer( 88 const sp<ANativeWindow> &nativeWindow, const sp<MetaData> &meta) 89 : mTarget(new SoftwareRenderer(nativeWindow, meta)) { 90 } 91 92 virtual void render(MediaBuffer *buffer) { 93 render((const uint8_t *)buffer->data() + buffer->range_offset(), 94 buffer->range_length()); 95 } 96 97 void render(const void *data, size_t size) { 98 mTarget->render(data, size, NULL); 99 } 100 101protected: 102 virtual ~AwesomeLocalRenderer() { 103 delete mTarget; 104 mTarget = NULL; 105 } 106 107private: 108 SoftwareRenderer *mTarget; 109 110 AwesomeLocalRenderer(const AwesomeLocalRenderer &); 111 AwesomeLocalRenderer &operator=(const AwesomeLocalRenderer &);; 112}; 113 114struct AwesomeNativeWindowRenderer : public AwesomeRenderer { 115 AwesomeNativeWindowRenderer( 116 const sp<ANativeWindow> &nativeWindow, 117 int32_t rotationDegrees) 118 : mNativeWindow(nativeWindow) { 119 applyRotation(rotationDegrees); 120 } 121 122 virtual void render(MediaBuffer *buffer) { 123 status_t err = mNativeWindow->queueBuffer( 124 mNativeWindow.get(), buffer->graphicBuffer().get()); 125 if (err != 0) { 126 LOGE("queueBuffer failed with error %s (%d)", strerror(-err), 127 -err); 128 return; 129 } 130 131 sp<MetaData> metaData = buffer->meta_data(); 132 metaData->setInt32(kKeyRendered, 1); 133 } 134 135protected: 136 virtual ~AwesomeNativeWindowRenderer() {} 137 138private: 139 sp<ANativeWindow> mNativeWindow; 140 141 void applyRotation(int32_t rotationDegrees) { 142 uint32_t transform; 143 switch (rotationDegrees) { 144 case 0: transform = 0; break; 145 case 90: transform = HAL_TRANSFORM_ROT_90; break; 146 case 180: transform = HAL_TRANSFORM_ROT_180; break; 147 case 270: transform = HAL_TRANSFORM_ROT_270; break; 148 default: transform = 0; break; 149 } 150 151 if (transform) { 152 CHECK_EQ(0, native_window_set_buffers_transform( 153 mNativeWindow.get(), transform)); 154 } 155 } 156 157 AwesomeNativeWindowRenderer(const AwesomeNativeWindowRenderer &); 158 AwesomeNativeWindowRenderer &operator=( 159 const AwesomeNativeWindowRenderer &); 160}; 161 162// To collect the decoder usage 163void addBatteryData(uint32_t params) { 164 sp<IBinder> binder = 165 defaultServiceManager()->getService(String16("media.player")); 166 sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder); 167 CHECK(service.get() != NULL); 168 169 service->addBatteryData(params); 170} 171 172//////////////////////////////////////////////////////////////////////////////// 173AwesomePlayer::AwesomePlayer() 174 : mQueueStarted(false), 175 mTimeSource(NULL), 176 mVideoRendererIsPreview(false), 177 mAudioPlayer(NULL), 178 mDisplayWidth(0), 179 mDisplayHeight(0), 180 mFlags(0), 181 mExtractorFlags(0), 182 mVideoBuffer(NULL), 183 mDecryptHandle(NULL) { 184 CHECK_EQ(mClient.connect(), (status_t)OK); 185 186 DataSource::RegisterDefaultSniffers(); 187 188 mVideoEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoEvent); 189 mVideoEventPending = false; 190 mStreamDoneEvent = new AwesomeEvent(this, &AwesomePlayer::onStreamDone); 191 mStreamDoneEventPending = false; 192 mBufferingEvent = new AwesomeEvent(this, &AwesomePlayer::onBufferingUpdate); 193 mBufferingEventPending = false; 194 mVideoLagEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoLagUpdate); 195 mVideoEventPending = false; 196 197 mCheckAudioStatusEvent = new AwesomeEvent( 198 this, &AwesomePlayer::onCheckAudioStatus); 199 200 mAudioStatusEventPending = false; 201 202 reset(); 203} 204 205AwesomePlayer::~AwesomePlayer() { 206 if (mQueueStarted) { 207 mQueue.stop(); 208 } 209 210 reset(); 211 212 mClient.disconnect(); 213} 214 215void AwesomePlayer::cancelPlayerEvents(bool keepBufferingGoing) { 216 mQueue.cancelEvent(mVideoEvent->eventID()); 217 mVideoEventPending = false; 218 mQueue.cancelEvent(mStreamDoneEvent->eventID()); 219 mStreamDoneEventPending = false; 220 mQueue.cancelEvent(mCheckAudioStatusEvent->eventID()); 221 mAudioStatusEventPending = false; 222 mQueue.cancelEvent(mVideoLagEvent->eventID()); 223 mVideoLagEventPending = false; 224 225 if (!keepBufferingGoing) { 226 mQueue.cancelEvent(mBufferingEvent->eventID()); 227 mBufferingEventPending = false; 228 } 229} 230 231void AwesomePlayer::setListener(const wp<MediaPlayerBase> &listener) { 232 Mutex::Autolock autoLock(mLock); 233 mListener = listener; 234} 235 236status_t AwesomePlayer::setDataSource( 237 const char *uri, const KeyedVector<String8, String8> *headers) { 238 Mutex::Autolock autoLock(mLock); 239 return setDataSource_l(uri, headers); 240} 241 242status_t AwesomePlayer::setDataSource_l( 243 const char *uri, const KeyedVector<String8, String8> *headers) { 244 reset_l(); 245 246 mUri = uri; 247 248 if (headers) { 249 mUriHeaders = *headers; 250 } 251 252 // The actual work will be done during preparation in the call to 253 // ::finishSetDataSource_l to avoid blocking the calling thread in 254 // setDataSource for any significant time. 255 256 return OK; 257} 258 259status_t AwesomePlayer::setDataSource( 260 int fd, int64_t offset, int64_t length) { 261 Mutex::Autolock autoLock(mLock); 262 263 reset_l(); 264 265 sp<DataSource> dataSource = new FileSource(fd, offset, length); 266 267 status_t err = dataSource->initCheck(); 268 269 if (err != OK) { 270 return err; 271 } 272 273 mFileSource = dataSource; 274 275 return setDataSource_l(dataSource); 276} 277 278status_t AwesomePlayer::setDataSource(const sp<IStreamSource> &source) { 279 return INVALID_OPERATION; 280} 281 282status_t AwesomePlayer::setDataSource_l( 283 const sp<DataSource> &dataSource) { 284 sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource); 285 286 if (extractor == NULL) { 287 return UNKNOWN_ERROR; 288 } 289 290 dataSource->getDrmInfo(&mDecryptHandle, &mDrmManagerClient); 291 if (mDecryptHandle != NULL) { 292 CHECK(mDrmManagerClient); 293 if (RightsStatus::RIGHTS_VALID != mDecryptHandle->status) { 294 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_NO_LICENSE); 295 } 296 } 297 298 return setDataSource_l(extractor); 299} 300 301status_t AwesomePlayer::setDataSource_l(const sp<MediaExtractor> &extractor) { 302 // Attempt to approximate overall stream bitrate by summing all 303 // tracks' individual bitrates, if not all of them advertise bitrate, 304 // we have to fail. 305 306 int64_t totalBitRate = 0; 307 308 for (size_t i = 0; i < extractor->countTracks(); ++i) { 309 sp<MetaData> meta = extractor->getTrackMetaData(i); 310 311 int32_t bitrate; 312 if (!meta->findInt32(kKeyBitRate, &bitrate)) { 313 totalBitRate = -1; 314 break; 315 } 316 317 totalBitRate += bitrate; 318 } 319 320 mBitrate = totalBitRate; 321 322 LOGV("mBitrate = %lld bits/sec", mBitrate); 323 324 bool haveAudio = false; 325 bool haveVideo = false; 326 for (size_t i = 0; i < extractor->countTracks(); ++i) { 327 sp<MetaData> meta = extractor->getTrackMetaData(i); 328 329 const char *mime; 330 CHECK(meta->findCString(kKeyMIMEType, &mime)); 331 332 if (!haveVideo && !strncasecmp(mime, "video/", 6)) { 333 setVideoSource(extractor->getTrack(i)); 334 haveVideo = true; 335 336 // Set the presentation/display size 337 int32_t displayWidth, displayHeight; 338 bool success = meta->findInt32(kKeyDisplayWidth, &displayWidth); 339 if (success) { 340 success = meta->findInt32(kKeyDisplayHeight, &displayHeight); 341 } 342 if (success) { 343 mDisplayWidth = displayWidth; 344 mDisplayHeight = displayHeight; 345 } 346 347 } else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) { 348 setAudioSource(extractor->getTrack(i)); 349 haveAudio = true; 350 351 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) { 352 // Only do this for vorbis audio, none of the other audio 353 // formats even support this ringtone specific hack and 354 // retrieving the metadata on some extractors may turn out 355 // to be very expensive. 356 sp<MetaData> fileMeta = extractor->getMetaData(); 357 int32_t loop; 358 if (fileMeta != NULL 359 && fileMeta->findInt32(kKeyAutoLoop, &loop) && loop != 0) { 360 mFlags |= AUTO_LOOPING; 361 } 362 } 363 } 364 365 if (haveAudio && haveVideo) { 366 break; 367 } 368 } 369 370 if (!haveAudio && !haveVideo) { 371 return UNKNOWN_ERROR; 372 } 373 374 mExtractorFlags = extractor->flags(); 375 376 return OK; 377} 378 379void AwesomePlayer::reset() { 380 Mutex::Autolock autoLock(mLock); 381 reset_l(); 382} 383 384void AwesomePlayer::reset_l() { 385 mDisplayWidth = 0; 386 mDisplayHeight = 0; 387 388 if (mDecryptHandle != NULL) { 389 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, 390 Playback::STOP, 0); 391 mDecryptHandle = NULL; 392 mDrmManagerClient = NULL; 393 } 394 395 if (mFlags & PLAYING) { 396 uint32_t params = IMediaPlayerService::kBatteryDataTrackDecoder; 397 if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) { 398 params |= IMediaPlayerService::kBatteryDataTrackAudio; 399 } 400 if (mVideoSource != NULL) { 401 params |= IMediaPlayerService::kBatteryDataTrackVideo; 402 } 403 addBatteryData(params); 404 } 405 406 if (mFlags & PREPARING) { 407 mFlags |= PREPARE_CANCELLED; 408 if (mConnectingDataSource != NULL) { 409 LOGI("interrupting the connection process"); 410 mConnectingDataSource->disconnect(); 411 } else if (mConnectingRTSPController != NULL) { 412 LOGI("interrupting the connection process"); 413 mConnectingRTSPController->disconnect(); 414 } 415 416 if (mFlags & PREPARING_CONNECTED) { 417 // We are basically done preparing, we're just buffering 418 // enough data to start playback, we can safely interrupt that. 419 finishAsyncPrepare_l(); 420 } 421 } 422 423 while (mFlags & PREPARING) { 424 mPreparedCondition.wait(mLock); 425 } 426 427 cancelPlayerEvents(); 428 429 mCachedSource.clear(); 430 mAudioTrack.clear(); 431 mVideoTrack.clear(); 432 433 // Shutdown audio first, so that the respone to the reset request 434 // appears to happen instantaneously as far as the user is concerned 435 // If we did this later, audio would continue playing while we 436 // shutdown the video-related resources and the player appear to 437 // not be as responsive to a reset request. 438 if (mAudioPlayer == NULL && mAudioSource != NULL) { 439 // If we had an audio player, it would have effectively 440 // taken possession of the audio source and stopped it when 441 // _it_ is stopped. Otherwise this is still our responsibility. 442 mAudioSource->stop(); 443 } 444 mAudioSource.clear(); 445 446 mTimeSource = NULL; 447 448 delete mAudioPlayer; 449 mAudioPlayer = NULL; 450 451 mVideoRenderer.clear(); 452 453 if (mVideoBuffer) { 454 mVideoBuffer->release(); 455 mVideoBuffer = NULL; 456 } 457 458 if (mRTSPController != NULL) { 459 mRTSPController->disconnect(); 460 mRTSPController.clear(); 461 } 462 463 if (mVideoSource != NULL) { 464 mVideoSource->stop(); 465 466 // The following hack is necessary to ensure that the OMX 467 // component is completely released by the time we may try 468 // to instantiate it again. 469 wp<MediaSource> tmp = mVideoSource; 470 mVideoSource.clear(); 471 while (tmp.promote() != NULL) { 472 usleep(1000); 473 } 474 IPCThreadState::self()->flushCommands(); 475 } 476 477 mDurationUs = -1; 478 mFlags = 0; 479 mExtractorFlags = 0; 480 mTimeSourceDeltaUs = 0; 481 mVideoTimeUs = 0; 482 483 mSeeking = false; 484 mSeekNotificationSent = false; 485 mSeekTimeUs = 0; 486 487 mUri.setTo(""); 488 mUriHeaders.clear(); 489 490 mFileSource.clear(); 491 492 mBitrate = -1; 493} 494 495void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) { 496 if (mListener != NULL) { 497 sp<MediaPlayerBase> listener = mListener.promote(); 498 499 if (listener != NULL) { 500 listener->sendEvent(msg, ext1, ext2); 501 } 502 } 503} 504 505bool AwesomePlayer::getBitrate(int64_t *bitrate) { 506 off64_t size; 507 if (mDurationUs >= 0 && mCachedSource != NULL 508 && mCachedSource->getSize(&size) == OK) { 509 *bitrate = size * 8000000ll / mDurationUs; // in bits/sec 510 return true; 511 } 512 513 if (mBitrate >= 0) { 514 *bitrate = mBitrate; 515 return true; 516 } 517 518 *bitrate = 0; 519 520 return false; 521} 522 523// Returns true iff cached duration is available/applicable. 524bool AwesomePlayer::getCachedDuration_l(int64_t *durationUs, bool *eos) { 525 int64_t bitrate; 526 527 if (mRTSPController != NULL) { 528 *durationUs = mRTSPController->getQueueDurationUs(eos); 529 return true; 530 } else if (mCachedSource != NULL && getBitrate(&bitrate)) { 531 status_t finalStatus; 532 size_t cachedDataRemaining = mCachedSource->approxDataRemaining(&finalStatus); 533 *durationUs = cachedDataRemaining * 8000000ll / bitrate; 534 *eos = (finalStatus != OK); 535 return true; 536 } 537 538 return false; 539} 540 541void AwesomePlayer::ensureCacheIsFetching_l() { 542 if (mCachedSource != NULL) { 543 mCachedSource->resumeFetchingIfNecessary(); 544 } 545} 546 547void AwesomePlayer::onVideoLagUpdate() { 548 Mutex::Autolock autoLock(mLock); 549 if (!mVideoLagEventPending) { 550 return; 551 } 552 mVideoLagEventPending = false; 553 554 int64_t audioTimeUs = mAudioPlayer->getMediaTimeUs(); 555 int64_t videoLateByUs = audioTimeUs - mVideoTimeUs; 556 557 if (videoLateByUs > 300000ll) { 558 LOGV("video late by %lld ms.", videoLateByUs / 1000ll); 559 560 notifyListener_l( 561 MEDIA_INFO, 562 MEDIA_INFO_VIDEO_TRACK_LAGGING, 563 videoLateByUs / 1000ll); 564 } 565 566 postVideoLagEvent_l(); 567} 568 569void AwesomePlayer::onBufferingUpdate() { 570 Mutex::Autolock autoLock(mLock); 571 if (!mBufferingEventPending) { 572 return; 573 } 574 mBufferingEventPending = false; 575 576 if (mCachedSource != NULL) { 577 status_t finalStatus; 578 size_t cachedDataRemaining = mCachedSource->approxDataRemaining(&finalStatus); 579 bool eos = (finalStatus != OK); 580 581 if (eos) { 582 if (finalStatus == ERROR_END_OF_STREAM) { 583 notifyListener_l(MEDIA_BUFFERING_UPDATE, 100); 584 } 585 if (mFlags & PREPARING) { 586 LOGV("cache has reached EOS, prepare is done."); 587 finishAsyncPrepare_l(); 588 } 589 } else { 590 int64_t bitrate; 591 if (getBitrate(&bitrate)) { 592 size_t cachedSize = mCachedSource->cachedSize(); 593 int64_t cachedDurationUs = cachedSize * 8000000ll / bitrate; 594 595 int percentage = 100.0 * (double)cachedDurationUs / mDurationUs; 596 if (percentage > 100) { 597 percentage = 100; 598 } 599 600 notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage); 601 } else { 602 // We don't know the bitrate of the stream, use absolute size 603 // limits to maintain the cache. 604 605 if ((mFlags & PLAYING) && !eos 606 && (cachedDataRemaining < kLowWaterMarkBytes)) { 607 LOGI("cache is running low (< %d) , pausing.", 608 kLowWaterMarkBytes); 609 mFlags |= CACHE_UNDERRUN; 610 pause_l(); 611 ensureCacheIsFetching_l(); 612 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START); 613 } else if (eos || cachedDataRemaining > kHighWaterMarkBytes) { 614 if (mFlags & CACHE_UNDERRUN) { 615 LOGI("cache has filled up (> %d), resuming.", 616 kHighWaterMarkBytes); 617 mFlags &= ~CACHE_UNDERRUN; 618 play_l(); 619 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END); 620 } else if (mFlags & PREPARING) { 621 LOGV("cache has filled up (> %d), prepare is done", 622 kHighWaterMarkBytes); 623 finishAsyncPrepare_l(); 624 } 625 } 626 } 627 } 628 } 629 630 int64_t cachedDurationUs; 631 bool eos; 632 if (getCachedDuration_l(&cachedDurationUs, &eos)) { 633 LOGV("cachedDurationUs = %.2f secs, eos=%d", 634 cachedDurationUs / 1E6, eos); 635 636 int64_t highWaterMarkUs = 637 (mRTSPController != NULL) ? kHighWaterMarkRTSPUs : kHighWaterMarkUs; 638 639 if ((mFlags & PLAYING) && !eos 640 && (cachedDurationUs < kLowWaterMarkUs)) { 641 LOGI("cache is running low (%.2f secs) , pausing.", 642 cachedDurationUs / 1E6); 643 mFlags |= CACHE_UNDERRUN; 644 pause_l(); 645 ensureCacheIsFetching_l(); 646 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START); 647 } else if (eos || cachedDurationUs > highWaterMarkUs) { 648 if (mFlags & CACHE_UNDERRUN) { 649 LOGI("cache has filled up (%.2f secs), resuming.", 650 cachedDurationUs / 1E6); 651 mFlags &= ~CACHE_UNDERRUN; 652 play_l(); 653 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END); 654 } else if (mFlags & PREPARING) { 655 LOGV("cache has filled up (%.2f secs), prepare is done", 656 cachedDurationUs / 1E6); 657 finishAsyncPrepare_l(); 658 } 659 } 660 } 661 662 postBufferingEvent_l(); 663} 664 665void AwesomePlayer::onStreamDone() { 666 // Posted whenever any stream finishes playing. 667 668 Mutex::Autolock autoLock(mLock); 669 if (!mStreamDoneEventPending) { 670 return; 671 } 672 mStreamDoneEventPending = false; 673 674 if (mStreamDoneStatus != ERROR_END_OF_STREAM) { 675 LOGV("MEDIA_ERROR %d", mStreamDoneStatus); 676 677 notifyListener_l( 678 MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, mStreamDoneStatus); 679 680 pause_l(true /* at eos */); 681 682 mFlags |= AT_EOS; 683 return; 684 } 685 686 const bool allDone = 687 (mVideoSource == NULL || (mFlags & VIDEO_AT_EOS)) 688 && (mAudioSource == NULL || (mFlags & AUDIO_AT_EOS)); 689 690 if (!allDone) { 691 return; 692 } 693 694 if (mFlags & (LOOPING | AUTO_LOOPING)) { 695 seekTo_l(0); 696 697 if (mVideoSource != NULL) { 698 postVideoEvent_l(); 699 } 700 } else { 701 LOGV("MEDIA_PLAYBACK_COMPLETE"); 702 notifyListener_l(MEDIA_PLAYBACK_COMPLETE); 703 704 pause_l(true /* at eos */); 705 706 mFlags |= AT_EOS; 707 } 708} 709 710status_t AwesomePlayer::play() { 711 Mutex::Autolock autoLock(mLock); 712 713 mFlags &= ~CACHE_UNDERRUN; 714 715 return play_l(); 716} 717 718status_t AwesomePlayer::play_l() { 719 mFlags &= ~SEEK_PREVIEW; 720 721 if (mFlags & PLAYING) { 722 return OK; 723 } 724 725 if (!(mFlags & PREPARED)) { 726 status_t err = prepare_l(); 727 728 if (err != OK) { 729 return err; 730 } 731 } 732 733 mFlags |= PLAYING; 734 mFlags |= FIRST_FRAME; 735 736 bool deferredAudioSeek = false; 737 738 if (mDecryptHandle != NULL) { 739 int64_t position; 740 getPosition(&position); 741 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, 742 Playback::START, position / 1000); 743 } 744 745 if (mAudioSource != NULL) { 746 if (mAudioPlayer == NULL) { 747 if (mAudioSink != NULL) { 748 mAudioPlayer = new AudioPlayer(mAudioSink, this); 749 mAudioPlayer->setSource(mAudioSource); 750 751 mTimeSource = mAudioPlayer; 752 753 deferredAudioSeek = true; 754 755 mWatchForAudioSeekComplete = false; 756 mWatchForAudioEOS = true; 757 } 758 } 759 760 CHECK(!(mFlags & AUDIO_RUNNING)); 761 762 if (mVideoSource == NULL) { 763 status_t err = startAudioPlayer_l(); 764 765 if (err != OK) { 766 delete mAudioPlayer; 767 mAudioPlayer = NULL; 768 769 mFlags &= ~(PLAYING | FIRST_FRAME); 770 771 if (mDecryptHandle != NULL) { 772 mDrmManagerClient->setPlaybackStatus( 773 mDecryptHandle, Playback::STOP, 0); 774 } 775 776 return err; 777 } 778 } 779 } 780 781 if (mTimeSource == NULL && mAudioPlayer == NULL) { 782 mTimeSource = &mSystemTimeSource; 783 } 784 785 if (mVideoSource != NULL) { 786 // Kick off video playback 787 postVideoEvent_l(); 788 789 if (mAudioSource != NULL && mVideoSource != NULL) { 790 postVideoLagEvent_l(); 791 } 792 } 793 794 if (deferredAudioSeek) { 795 // If there was a seek request while we were paused 796 // and we're just starting up again, honor the request now. 797 seekAudioIfNecessary_l(); 798 } 799 800 if (mFlags & AT_EOS) { 801 // Legacy behaviour, if a stream finishes playing and then 802 // is started again, we play from the start... 803 seekTo_l(0); 804 } 805 806 uint32_t params = IMediaPlayerService::kBatteryDataCodecStarted 807 | IMediaPlayerService::kBatteryDataTrackDecoder; 808 if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) { 809 params |= IMediaPlayerService::kBatteryDataTrackAudio; 810 } 811 if (mVideoSource != NULL) { 812 params |= IMediaPlayerService::kBatteryDataTrackVideo; 813 } 814 addBatteryData(params); 815 816 return OK; 817} 818 819status_t AwesomePlayer::startAudioPlayer_l() { 820 CHECK(!(mFlags & AUDIO_RUNNING)); 821 822 if (mAudioSource == NULL || mAudioPlayer == NULL) { 823 return OK; 824 } 825 826 if (!(mFlags & AUDIOPLAYER_STARTED)) { 827 mFlags |= AUDIOPLAYER_STARTED; 828 829 // We've already started the MediaSource in order to enable 830 // the prefetcher to read its data. 831 status_t err = mAudioPlayer->start( 832 true /* sourceAlreadyStarted */); 833 834 if (err != OK) { 835 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err); 836 return err; 837 } 838 } else { 839 mAudioPlayer->resume(); 840 } 841 842 mFlags |= AUDIO_RUNNING; 843 844 mWatchForAudioEOS = true; 845 846 return OK; 847} 848 849void AwesomePlayer::notifyVideoSize_l() { 850 sp<MetaData> meta = mVideoSource->getFormat(); 851 852 int32_t cropLeft, cropTop, cropRight, cropBottom; 853 if (!meta->findRect( 854 kKeyCropRect, &cropLeft, &cropTop, &cropRight, &cropBottom)) { 855 int32_t width, height; 856 CHECK(meta->findInt32(kKeyWidth, &width)); 857 CHECK(meta->findInt32(kKeyHeight, &height)); 858 859 cropLeft = cropTop = 0; 860 cropRight = width - 1; 861 cropBottom = height - 1; 862 863 LOGV("got dimensions only %d x %d", width, height); 864 } else { 865 LOGV("got crop rect %d, %d, %d, %d", 866 cropLeft, cropTop, cropRight, cropBottom); 867 } 868 869 int32_t usableWidth = cropRight - cropLeft + 1; 870 int32_t usableHeight = cropBottom - cropTop + 1; 871 if (mDisplayWidth != 0) { 872 usableWidth = mDisplayWidth; 873 } 874 if (mDisplayHeight != 0) { 875 usableHeight = mDisplayHeight; 876 } 877 878 int32_t rotationDegrees; 879 if (!mVideoTrack->getFormat()->findInt32( 880 kKeyRotation, &rotationDegrees)) { 881 rotationDegrees = 0; 882 } 883 884 if (rotationDegrees == 90 || rotationDegrees == 270) { 885 notifyListener_l( 886 MEDIA_SET_VIDEO_SIZE, usableHeight, usableWidth); 887 } else { 888 notifyListener_l( 889 MEDIA_SET_VIDEO_SIZE, usableWidth, usableHeight); 890 } 891} 892 893void AwesomePlayer::initRenderer_l() { 894 if (mNativeWindow == NULL) { 895 return; 896 } 897 898 sp<MetaData> meta = mVideoSource->getFormat(); 899 900 int32_t format; 901 const char *component; 902 int32_t decodedWidth, decodedHeight; 903 CHECK(meta->findInt32(kKeyColorFormat, &format)); 904 CHECK(meta->findCString(kKeyDecoderComponent, &component)); 905 CHECK(meta->findInt32(kKeyWidth, &decodedWidth)); 906 CHECK(meta->findInt32(kKeyHeight, &decodedHeight)); 907 908 int32_t rotationDegrees; 909 if (!mVideoTrack->getFormat()->findInt32( 910 kKeyRotation, &rotationDegrees)) { 911 rotationDegrees = 0; 912 } 913 914 mVideoRenderer.clear(); 915 916 // Must ensure that mVideoRenderer's destructor is actually executed 917 // before creating a new one. 918 IPCThreadState::self()->flushCommands(); 919 920 if (USE_SURFACE_ALLOC && strncmp(component, "OMX.", 4) == 0) { 921 // Hardware decoders avoid the CPU color conversion by decoding 922 // directly to ANativeBuffers, so we must use a renderer that 923 // just pushes those buffers to the ANativeWindow. 924 mVideoRenderer = 925 new AwesomeNativeWindowRenderer(mNativeWindow, rotationDegrees); 926 } else { 927 // Other decoders are instantiated locally and as a consequence 928 // allocate their buffers in local address space. This renderer 929 // then performs a color conversion and copy to get the data 930 // into the ANativeBuffer. 931 mVideoRenderer = new AwesomeLocalRenderer(mNativeWindow, meta); 932 } 933} 934 935status_t AwesomePlayer::pause() { 936 Mutex::Autolock autoLock(mLock); 937 938 mFlags &= ~CACHE_UNDERRUN; 939 940 return pause_l(); 941} 942 943status_t AwesomePlayer::pause_l(bool at_eos) { 944 if (!(mFlags & PLAYING)) { 945 return OK; 946 } 947 948 cancelPlayerEvents(true /* keepBufferingGoing */); 949 950 if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) { 951 if (at_eos) { 952 // If we played the audio stream to completion we 953 // want to make sure that all samples remaining in the audio 954 // track's queue are played out. 955 mAudioPlayer->pause(true /* playPendingSamples */); 956 } else { 957 mAudioPlayer->pause(); 958 } 959 960 mFlags &= ~AUDIO_RUNNING; 961 } 962 963 mFlags &= ~PLAYING; 964 965 if (mDecryptHandle != NULL) { 966 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, 967 Playback::PAUSE, 0); 968 } 969 970 uint32_t params = IMediaPlayerService::kBatteryDataTrackDecoder; 971 if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) { 972 params |= IMediaPlayerService::kBatteryDataTrackAudio; 973 } 974 if (mVideoSource != NULL) { 975 params |= IMediaPlayerService::kBatteryDataTrackVideo; 976 } 977 978 addBatteryData(params); 979 980 return OK; 981} 982 983bool AwesomePlayer::isPlaying() const { 984 return (mFlags & PLAYING) || (mFlags & CACHE_UNDERRUN); 985} 986 987void AwesomePlayer::setSurface(const sp<Surface> &surface) { 988 Mutex::Autolock autoLock(mLock); 989 990 mSurface = surface; 991 mNativeWindow = surface; 992} 993 994void AwesomePlayer::setSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture) { 995 Mutex::Autolock autoLock(mLock); 996 997 mSurface.clear(); 998 if (surfaceTexture != NULL) { 999 mNativeWindow = new SurfaceTextureClient(surfaceTexture); 1000 } 1001 1002} 1003 1004void AwesomePlayer::setAudioSink( 1005 const sp<MediaPlayerBase::AudioSink> &audioSink) { 1006 Mutex::Autolock autoLock(mLock); 1007 1008 mAudioSink = audioSink; 1009} 1010 1011status_t AwesomePlayer::setLooping(bool shouldLoop) { 1012 Mutex::Autolock autoLock(mLock); 1013 1014 mFlags = mFlags & ~LOOPING; 1015 1016 if (shouldLoop) { 1017 mFlags |= LOOPING; 1018 } 1019 1020 return OK; 1021} 1022 1023status_t AwesomePlayer::getDuration(int64_t *durationUs) { 1024 Mutex::Autolock autoLock(mMiscStateLock); 1025 1026 if (mDurationUs < 0) { 1027 return UNKNOWN_ERROR; 1028 } 1029 1030 *durationUs = mDurationUs; 1031 1032 return OK; 1033} 1034 1035status_t AwesomePlayer::getPosition(int64_t *positionUs) { 1036 if (mRTSPController != NULL) { 1037 *positionUs = mRTSPController->getNormalPlayTimeUs(); 1038 } 1039 else if (mSeeking) { 1040 *positionUs = mSeekTimeUs; 1041 } else if (mVideoSource != NULL) { 1042 Mutex::Autolock autoLock(mMiscStateLock); 1043 *positionUs = mVideoTimeUs; 1044 } else if (mAudioPlayer != NULL) { 1045 *positionUs = mAudioPlayer->getMediaTimeUs(); 1046 } else { 1047 *positionUs = 0; 1048 } 1049 1050 return OK; 1051} 1052 1053status_t AwesomePlayer::seekTo(int64_t timeUs) { 1054 if (mExtractorFlags & MediaExtractor::CAN_SEEK) { 1055 Mutex::Autolock autoLock(mLock); 1056 return seekTo_l(timeUs); 1057 } 1058 1059 return OK; 1060} 1061 1062// static 1063void AwesomePlayer::OnRTSPSeekDoneWrapper(void *cookie) { 1064 static_cast<AwesomePlayer *>(cookie)->onRTSPSeekDone(); 1065} 1066 1067void AwesomePlayer::onRTSPSeekDone() { 1068 notifyListener_l(MEDIA_SEEK_COMPLETE); 1069 mSeekNotificationSent = true; 1070} 1071 1072status_t AwesomePlayer::seekTo_l(int64_t timeUs) { 1073 if (mRTSPController != NULL) { 1074 mRTSPController->seekAsync(timeUs, OnRTSPSeekDoneWrapper, this); 1075 return OK; 1076 } 1077 1078 if (mFlags & CACHE_UNDERRUN) { 1079 mFlags &= ~CACHE_UNDERRUN; 1080 play_l(); 1081 } 1082 1083 mSeeking = true; 1084 mSeekNotificationSent = false; 1085 mSeekTimeUs = timeUs; 1086 mFlags &= ~(AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS); 1087 1088 seekAudioIfNecessary_l(); 1089 1090 if (!(mFlags & PLAYING)) { 1091 LOGV("seeking while paused, sending SEEK_COMPLETE notification" 1092 " immediately."); 1093 1094 notifyListener_l(MEDIA_SEEK_COMPLETE); 1095 mSeekNotificationSent = true; 1096 1097 if ((mFlags & PREPARED) && mVideoSource != NULL) { 1098 mFlags |= SEEK_PREVIEW; 1099 postVideoEvent_l(); 1100 } 1101 } 1102 1103 return OK; 1104} 1105 1106void AwesomePlayer::seekAudioIfNecessary_l() { 1107 if (mSeeking && mVideoSource == NULL && mAudioPlayer != NULL) { 1108 mAudioPlayer->seekTo(mSeekTimeUs); 1109 1110 mWatchForAudioSeekComplete = true; 1111 mWatchForAudioEOS = true; 1112 mSeekNotificationSent = false; 1113 1114 if (mDecryptHandle != NULL) { 1115 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, 1116 Playback::PAUSE, 0); 1117 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, 1118 Playback::START, mSeekTimeUs / 1000); 1119 } 1120 } 1121} 1122 1123void AwesomePlayer::setAudioSource(sp<MediaSource> source) { 1124 CHECK(source != NULL); 1125 1126 mAudioTrack = source; 1127} 1128 1129status_t AwesomePlayer::initAudioDecoder() { 1130 sp<MetaData> meta = mAudioTrack->getFormat(); 1131 1132 const char *mime; 1133 CHECK(meta->findCString(kKeyMIMEType, &mime)); 1134 1135 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) { 1136 mAudioSource = mAudioTrack; 1137 } else { 1138 mAudioSource = OMXCodec::Create( 1139 mClient.interface(), mAudioTrack->getFormat(), 1140 false, // createEncoder 1141 mAudioTrack); 1142 } 1143 1144 if (mAudioSource != NULL) { 1145 int64_t durationUs; 1146 if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) { 1147 Mutex::Autolock autoLock(mMiscStateLock); 1148 if (mDurationUs < 0 || durationUs > mDurationUs) { 1149 mDurationUs = durationUs; 1150 } 1151 } 1152 1153 status_t err = mAudioSource->start(); 1154 1155 if (err != OK) { 1156 mAudioSource.clear(); 1157 return err; 1158 } 1159 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_QCELP)) { 1160 // For legacy reasons we're simply going to ignore the absence 1161 // of an audio decoder for QCELP instead of aborting playback 1162 // altogether. 1163 return OK; 1164 } 1165 1166 return mAudioSource != NULL ? OK : UNKNOWN_ERROR; 1167} 1168 1169void AwesomePlayer::setVideoSource(sp<MediaSource> source) { 1170 CHECK(source != NULL); 1171 1172 mVideoTrack = source; 1173} 1174 1175status_t AwesomePlayer::initVideoDecoder(uint32_t flags) { 1176 mVideoSource = OMXCodec::Create( 1177 mClient.interface(), mVideoTrack->getFormat(), 1178 false, // createEncoder 1179 mVideoTrack, 1180 NULL, flags, USE_SURFACE_ALLOC ? mNativeWindow : NULL); 1181 1182 if (mVideoSource != NULL) { 1183 int64_t durationUs; 1184 if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) { 1185 Mutex::Autolock autoLock(mMiscStateLock); 1186 if (mDurationUs < 0 || durationUs > mDurationUs) { 1187 mDurationUs = durationUs; 1188 } 1189 } 1190 1191 status_t err = mVideoSource->start(); 1192 1193 if (err != OK) { 1194 mVideoSource.clear(); 1195 return err; 1196 } 1197 } 1198 1199 return mVideoSource != NULL ? OK : UNKNOWN_ERROR; 1200} 1201 1202void AwesomePlayer::finishSeekIfNecessary(int64_t videoTimeUs) { 1203 if (!mSeeking || (mFlags & SEEK_PREVIEW)) { 1204 return; 1205 } 1206 1207 if (mAudioPlayer != NULL) { 1208 LOGV("seeking audio to %lld us (%.2f secs).", videoTimeUs, videoTimeUs / 1E6); 1209 1210 // If we don't have a video time, seek audio to the originally 1211 // requested seek time instead. 1212 1213 mAudioPlayer->seekTo(videoTimeUs < 0 ? mSeekTimeUs : videoTimeUs); 1214 mWatchForAudioSeekComplete = true; 1215 } else if (!mSeekNotificationSent) { 1216 // If we're playing video only, report seek complete now, 1217 // otherwise audio player will notify us later. 1218 notifyListener_l(MEDIA_SEEK_COMPLETE); 1219 } 1220 1221 mFlags |= FIRST_FRAME; 1222 mSeeking = false; 1223 mSeekNotificationSent = false; 1224 1225 if (mDecryptHandle != NULL) { 1226 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, 1227 Playback::PAUSE, 0); 1228 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, 1229 Playback::START, videoTimeUs / 1000); 1230 } 1231} 1232 1233void AwesomePlayer::onVideoEvent() { 1234 Mutex::Autolock autoLock(mLock); 1235 if (!mVideoEventPending) { 1236 // The event has been cancelled in reset_l() but had already 1237 // been scheduled for execution at that time. 1238 return; 1239 } 1240 mVideoEventPending = false; 1241 1242 if (mSeeking) { 1243 if (mVideoBuffer) { 1244 mVideoBuffer->release(); 1245 mVideoBuffer = NULL; 1246 } 1247 1248 if (mCachedSource != NULL && mAudioSource != NULL 1249 && !(mFlags & SEEK_PREVIEW)) { 1250 // We're going to seek the video source first, followed by 1251 // the audio source. 1252 // In order to avoid jumps in the DataSource offset caused by 1253 // the audio codec prefetching data from the old locations 1254 // while the video codec is already reading data from the new 1255 // locations, we'll "pause" the audio source, causing it to 1256 // stop reading input data until a subsequent seek. 1257 1258 if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) { 1259 mAudioPlayer->pause(); 1260 1261 mFlags &= ~AUDIO_RUNNING; 1262 } 1263 mAudioSource->pause(); 1264 } 1265 } 1266 1267 if (!mVideoBuffer) { 1268 MediaSource::ReadOptions options; 1269 if (mSeeking) { 1270 LOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs, mSeekTimeUs / 1E6); 1271 1272 options.setSeekTo( 1273 mSeekTimeUs, MediaSource::ReadOptions::SEEK_CLOSEST_SYNC); 1274 } 1275 for (;;) { 1276 status_t err = mVideoSource->read(&mVideoBuffer, &options); 1277 options.clearSeekTo(); 1278 1279 if (err != OK) { 1280 CHECK(mVideoBuffer == NULL); 1281 1282 if (err == INFO_FORMAT_CHANGED) { 1283 LOGV("VideoSource signalled format change."); 1284 1285 notifyVideoSize_l(); 1286 1287 if (mVideoRenderer != NULL) { 1288 mVideoRendererIsPreview = false; 1289 initRenderer_l(); 1290 } 1291 continue; 1292 } 1293 1294 // So video playback is complete, but we may still have 1295 // a seek request pending that needs to be applied 1296 // to the audio track. 1297 if (mSeeking) { 1298 LOGV("video stream ended while seeking!"); 1299 } 1300 finishSeekIfNecessary(-1); 1301 1302 mFlags |= VIDEO_AT_EOS; 1303 postStreamDoneEvent_l(err); 1304 return; 1305 } 1306 1307 if (mVideoBuffer->range_length() == 0) { 1308 // Some decoders, notably the PV AVC software decoder 1309 // return spurious empty buffers that we just want to ignore. 1310 1311 mVideoBuffer->release(); 1312 mVideoBuffer = NULL; 1313 continue; 1314 } 1315 1316 break; 1317 } 1318 } 1319 1320 int64_t timeUs; 1321 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs)); 1322 1323 { 1324 Mutex::Autolock autoLock(mMiscStateLock); 1325 mVideoTimeUs = timeUs; 1326 } 1327 1328 bool wasSeeking = mSeeking; 1329 finishSeekIfNecessary(timeUs); 1330 1331 if (mAudioPlayer != NULL && !(mFlags & (AUDIO_RUNNING | SEEK_PREVIEW))) { 1332 status_t err = startAudioPlayer_l(); 1333 if (err != OK) { 1334 LOGE("Startung the audio player failed w/ err %d", err); 1335 return; 1336 } 1337 } 1338 1339 TimeSource *ts = (mFlags & AUDIO_AT_EOS) ? &mSystemTimeSource : mTimeSource; 1340 1341 if (mFlags & FIRST_FRAME) { 1342 mFlags &= ~FIRST_FRAME; 1343 mSinceLastDropped = 0; 1344 mTimeSourceDeltaUs = ts->getRealTimeUs() - timeUs; 1345 } 1346 1347 int64_t realTimeUs, mediaTimeUs; 1348 if (!(mFlags & AUDIO_AT_EOS) && mAudioPlayer != NULL 1349 && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) { 1350 mTimeSourceDeltaUs = realTimeUs - mediaTimeUs; 1351 } 1352 1353 if (!wasSeeking) { 1354 // Let's display the first frame after seeking right away. 1355 1356 int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs; 1357 1358 int64_t latenessUs = nowUs - timeUs; 1359 1360 if (latenessUs > 40000) { 1361 // We're more than 40ms late. 1362 LOGV("we're late by %lld us (%.2f secs)", latenessUs, latenessUs / 1E6); 1363 if ( mSinceLastDropped > FRAME_DROP_FREQ) 1364 { 1365 LOGV("we're late by %lld us (%.2f secs) dropping one after %d frames", latenessUs, latenessUs / 1E6, mSinceLastDropped); 1366 mSinceLastDropped = 0; 1367 mVideoBuffer->release(); 1368 mVideoBuffer = NULL; 1369 1370 postVideoEvent_l(); 1371 return; 1372 } 1373 } 1374 1375 if (latenessUs < -10000) { 1376 // We're more than 10ms early. 1377 1378 postVideoEvent_l(10000); 1379 return; 1380 } 1381 } 1382 1383 if (mVideoRendererIsPreview || mVideoRenderer == NULL) { 1384 mVideoRendererIsPreview = false; 1385 1386 initRenderer_l(); 1387 } 1388 1389 if (mVideoRenderer != NULL) { 1390 mSinceLastDropped++; 1391 mVideoRenderer->render(mVideoBuffer); 1392 } 1393 1394 mVideoBuffer->release(); 1395 mVideoBuffer = NULL; 1396 1397 if (wasSeeking && (mFlags & SEEK_PREVIEW)) { 1398 mFlags &= ~SEEK_PREVIEW; 1399 return; 1400 } 1401 1402 postVideoEvent_l(); 1403} 1404 1405void AwesomePlayer::postVideoEvent_l(int64_t delayUs) { 1406 if (mVideoEventPending) { 1407 return; 1408 } 1409 1410 mVideoEventPending = true; 1411 mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs); 1412} 1413 1414void AwesomePlayer::postStreamDoneEvent_l(status_t status) { 1415 if (mStreamDoneEventPending) { 1416 return; 1417 } 1418 mStreamDoneEventPending = true; 1419 1420 mStreamDoneStatus = status; 1421 mQueue.postEvent(mStreamDoneEvent); 1422} 1423 1424void AwesomePlayer::postBufferingEvent_l() { 1425 if (mBufferingEventPending) { 1426 return; 1427 } 1428 mBufferingEventPending = true; 1429 mQueue.postEventWithDelay(mBufferingEvent, 1000000ll); 1430} 1431 1432void AwesomePlayer::postVideoLagEvent_l() { 1433 if (mVideoLagEventPending) { 1434 return; 1435 } 1436 mVideoLagEventPending = true; 1437 mQueue.postEventWithDelay(mVideoLagEvent, 1000000ll); 1438} 1439 1440void AwesomePlayer::postCheckAudioStatusEvent_l() { 1441 if (mAudioStatusEventPending) { 1442 return; 1443 } 1444 mAudioStatusEventPending = true; 1445 mQueue.postEvent(mCheckAudioStatusEvent); 1446} 1447 1448void AwesomePlayer::onCheckAudioStatus() { 1449 Mutex::Autolock autoLock(mLock); 1450 if (!mAudioStatusEventPending) { 1451 // Event was dispatched and while we were blocking on the mutex, 1452 // has already been cancelled. 1453 return; 1454 } 1455 1456 mAudioStatusEventPending = false; 1457 1458 if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) { 1459 mWatchForAudioSeekComplete = false; 1460 1461 if (!mSeekNotificationSent) { 1462 notifyListener_l(MEDIA_SEEK_COMPLETE); 1463 mSeekNotificationSent = true; 1464 } 1465 1466 mSeeking = false; 1467 } 1468 1469 status_t finalStatus; 1470 if (mWatchForAudioEOS && mAudioPlayer->reachedEOS(&finalStatus)) { 1471 mWatchForAudioEOS = false; 1472 mFlags |= AUDIO_AT_EOS; 1473 mFlags |= FIRST_FRAME; 1474 postStreamDoneEvent_l(finalStatus); 1475 } 1476} 1477 1478status_t AwesomePlayer::prepare() { 1479 Mutex::Autolock autoLock(mLock); 1480 return prepare_l(); 1481} 1482 1483status_t AwesomePlayer::prepare_l() { 1484 if (mFlags & PREPARED) { 1485 return OK; 1486 } 1487 1488 if (mFlags & PREPARING) { 1489 return UNKNOWN_ERROR; 1490 } 1491 1492 mIsAsyncPrepare = false; 1493 status_t err = prepareAsync_l(); 1494 1495 if (err != OK) { 1496 return err; 1497 } 1498 1499 while (mFlags & PREPARING) { 1500 mPreparedCondition.wait(mLock); 1501 } 1502 1503 return mPrepareResult; 1504} 1505 1506status_t AwesomePlayer::prepareAsync() { 1507 Mutex::Autolock autoLock(mLock); 1508 1509 if (mFlags & PREPARING) { 1510 return UNKNOWN_ERROR; // async prepare already pending 1511 } 1512 1513 mIsAsyncPrepare = true; 1514 return prepareAsync_l(); 1515} 1516 1517status_t AwesomePlayer::prepareAsync_l() { 1518 if (mFlags & PREPARING) { 1519 return UNKNOWN_ERROR; // async prepare already pending 1520 } 1521 1522 if (!mQueueStarted) { 1523 mQueue.start(); 1524 mQueueStarted = true; 1525 } 1526 1527 mFlags |= PREPARING; 1528 mAsyncPrepareEvent = new AwesomeEvent( 1529 this, &AwesomePlayer::onPrepareAsyncEvent); 1530 1531 mQueue.postEvent(mAsyncPrepareEvent); 1532 1533 return OK; 1534} 1535 1536status_t AwesomePlayer::finishSetDataSource_l() { 1537 sp<DataSource> dataSource; 1538 1539 if (!strncasecmp("http://", mUri.string(), 7) 1540 || !strncasecmp("https://", mUri.string(), 8)) { 1541 mConnectingDataSource = new NuHTTPDataSource; 1542 1543 mLock.unlock(); 1544 status_t err = mConnectingDataSource->connect(mUri, &mUriHeaders); 1545 mLock.lock(); 1546 1547 if (err != OK) { 1548 mConnectingDataSource.clear(); 1549 1550 LOGI("mConnectingDataSource->connect() returned %d", err); 1551 return err; 1552 } 1553 1554#if 0 1555 mCachedSource = new NuCachedSource2( 1556 new ThrottledSource( 1557 mConnectingDataSource, 50 * 1024 /* bytes/sec */)); 1558#else 1559 mCachedSource = new NuCachedSource2(mConnectingDataSource); 1560#endif 1561 mConnectingDataSource.clear(); 1562 1563 dataSource = mCachedSource; 1564 1565 // We're going to prefill the cache before trying to instantiate 1566 // the extractor below, as the latter is an operation that otherwise 1567 // could block on the datasource for a significant amount of time. 1568 // During that time we'd be unable to abort the preparation phase 1569 // without this prefill. 1570 1571 mLock.unlock(); 1572 1573 for (;;) { 1574 status_t finalStatus; 1575 size_t cachedDataRemaining = 1576 mCachedSource->approxDataRemaining(&finalStatus); 1577 1578 if (finalStatus != OK || cachedDataRemaining >= kHighWaterMarkBytes 1579 || (mFlags & PREPARE_CANCELLED)) { 1580 break; 1581 } 1582 1583 usleep(200000); 1584 } 1585 1586 mLock.lock(); 1587 1588 if (mFlags & PREPARE_CANCELLED) { 1589 LOGI("Prepare cancelled while waiting for initial cache fill."); 1590 return UNKNOWN_ERROR; 1591 } 1592 } else if (!strncasecmp("rtsp://", mUri.string(), 7)) { 1593 if (mLooper == NULL) { 1594 mLooper = new ALooper; 1595 mLooper->setName("rtsp"); 1596 mLooper->start(); 1597 } 1598 mRTSPController = new ARTSPController(mLooper); 1599 mConnectingRTSPController = mRTSPController; 1600 1601 mLock.unlock(); 1602 status_t err = mRTSPController->connect(mUri.string()); 1603 mLock.lock(); 1604 1605 mConnectingRTSPController.clear(); 1606 1607 LOGI("ARTSPController::connect returned %d", err); 1608 1609 if (err != OK) { 1610 mRTSPController.clear(); 1611 return err; 1612 } 1613 1614 sp<MediaExtractor> extractor = mRTSPController.get(); 1615 return setDataSource_l(extractor); 1616 } else { 1617 dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders); 1618 } 1619 1620 if (dataSource == NULL) { 1621 return UNKNOWN_ERROR; 1622 } 1623 1624 sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource); 1625 1626 if (extractor == NULL) { 1627 return UNKNOWN_ERROR; 1628 } 1629 1630 dataSource->getDrmInfo(&mDecryptHandle, &mDrmManagerClient); 1631 if (mDecryptHandle != NULL) { 1632 CHECK(mDrmManagerClient); 1633 if (RightsStatus::RIGHTS_VALID == mDecryptHandle->status) { 1634 if (DecryptApiType::WV_BASED == mDecryptHandle->decryptApiType) { 1635 LOGD("Setting mCachedSource to NULL for WVM\n"); 1636 mCachedSource.clear(); 1637 } 1638 } else { 1639 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_NO_LICENSE); 1640 } 1641 } 1642 1643 return setDataSource_l(extractor); 1644} 1645 1646void AwesomePlayer::abortPrepare(status_t err) { 1647 CHECK(err != OK); 1648 1649 if (mIsAsyncPrepare) { 1650 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err); 1651 } 1652 1653 mPrepareResult = err; 1654 mFlags &= ~(PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED); 1655 mAsyncPrepareEvent = NULL; 1656 mPreparedCondition.broadcast(); 1657} 1658 1659// static 1660bool AwesomePlayer::ContinuePreparation(void *cookie) { 1661 AwesomePlayer *me = static_cast<AwesomePlayer *>(cookie); 1662 1663 return (me->mFlags & PREPARE_CANCELLED) == 0; 1664} 1665 1666void AwesomePlayer::onPrepareAsyncEvent() { 1667 Mutex::Autolock autoLock(mLock); 1668 1669 if (mFlags & PREPARE_CANCELLED) { 1670 LOGI("prepare was cancelled before doing anything"); 1671 abortPrepare(UNKNOWN_ERROR); 1672 return; 1673 } 1674 1675 if (mUri.size() > 0) { 1676 status_t err = finishSetDataSource_l(); 1677 1678 if (err != OK) { 1679 abortPrepare(err); 1680 return; 1681 } 1682 } 1683 1684 if (mVideoTrack != NULL && mVideoSource == NULL) { 1685 status_t err = initVideoDecoder(); 1686 1687 if (err != OK) { 1688 abortPrepare(err); 1689 return; 1690 } 1691 } 1692 1693 if (mAudioTrack != NULL && mAudioSource == NULL) { 1694 status_t err = initAudioDecoder(); 1695 1696 if (err != OK) { 1697 abortPrepare(err); 1698 return; 1699 } 1700 } 1701 1702 mFlags |= PREPARING_CONNECTED; 1703 1704 if (mCachedSource != NULL || mRTSPController != NULL) { 1705 postBufferingEvent_l(); 1706 } else { 1707 finishAsyncPrepare_l(); 1708 } 1709} 1710 1711void AwesomePlayer::finishAsyncPrepare_l() { 1712 if (mIsAsyncPrepare) { 1713 if (mVideoSource == NULL) { 1714 notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0); 1715 } else { 1716 notifyVideoSize_l(); 1717 } 1718 1719 notifyListener_l(MEDIA_PREPARED); 1720 } 1721 1722 mPrepareResult = OK; 1723 mFlags &= ~(PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED); 1724 mFlags |= PREPARED; 1725 mAsyncPrepareEvent = NULL; 1726 mPreparedCondition.broadcast(); 1727} 1728 1729uint32_t AwesomePlayer::flags() const { 1730 return mExtractorFlags; 1731} 1732 1733void AwesomePlayer::postAudioEOS() { 1734 postCheckAudioStatusEvent_l(); 1735} 1736 1737void AwesomePlayer::postAudioSeekComplete() { 1738 postCheckAudioStatusEvent_l(); 1739} 1740 1741} // namespace android 1742