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