AwesomePlayer.cpp revision dcd25efb46c41c8d24a0a9cf61fb57f84149709e
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/AwesomePlayer.h" 24#include "include/Prefetcher.h" 25#include "include/SoftwareRenderer.h" 26 27#include <binder/IPCThreadState.h> 28#include <media/stagefright/AudioPlayer.h> 29#include <media/stagefright/CachingDataSource.h> 30#include <media/stagefright/DataSource.h> 31#include <media/stagefright/FileSource.h> 32#include <media/stagefright/MediaBuffer.h> 33#include <media/stagefright/MediaDefs.h> 34#include <media/stagefright/MediaExtractor.h> 35#include <media/stagefright/MediaDebug.h> 36#include <media/stagefright/MediaSource.h> 37#include <media/stagefright/MetaData.h> 38#include <media/stagefright/OMXCodec.h> 39 40#include <surfaceflinger/ISurface.h> 41 42namespace android { 43 44struct AwesomeEvent : public TimedEventQueue::Event { 45 AwesomeEvent( 46 AwesomePlayer *player, 47 void (AwesomePlayer::*method)()) 48 : mPlayer(player), 49 mMethod(method) { 50 } 51 52protected: 53 virtual ~AwesomeEvent() {} 54 55 virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) { 56 (mPlayer->*mMethod)(); 57 } 58 59private: 60 AwesomePlayer *mPlayer; 61 void (AwesomePlayer::*mMethod)(); 62 63 AwesomeEvent(const AwesomeEvent &); 64 AwesomeEvent &operator=(const AwesomeEvent &); 65}; 66 67struct AwesomeRemoteRenderer : public AwesomeRenderer { 68 AwesomeRemoteRenderer(const sp<IOMXRenderer> &target) 69 : mTarget(target) { 70 } 71 72 virtual void render(MediaBuffer *buffer) { 73 void *id; 74 if (buffer->meta_data()->findPointer(kKeyBufferID, &id)) { 75 mTarget->render((IOMX::buffer_id)id); 76 } 77 } 78 79private: 80 sp<IOMXRenderer> mTarget; 81 82 AwesomeRemoteRenderer(const AwesomeRemoteRenderer &); 83 AwesomeRemoteRenderer &operator=(const AwesomeRemoteRenderer &); 84}; 85 86struct AwesomeLocalRenderer : public AwesomeRenderer { 87 AwesomeLocalRenderer( 88 bool previewOnly, 89 const char *componentName, 90 OMX_COLOR_FORMATTYPE colorFormat, 91 const sp<ISurface> &surface, 92 size_t displayWidth, size_t displayHeight, 93 size_t decodedWidth, size_t decodedHeight) 94 : mTarget(NULL), 95 mLibHandle(NULL) { 96 init(previewOnly, componentName, 97 colorFormat, surface, displayWidth, 98 displayHeight, decodedWidth, decodedHeight); 99 } 100 101 virtual void render(MediaBuffer *buffer) { 102 render((const uint8_t *)buffer->data() + buffer->range_offset(), 103 buffer->range_length()); 104 } 105 106 void render(const void *data, size_t size) { 107 mTarget->render(data, size, NULL); 108 } 109 110protected: 111 virtual ~AwesomeLocalRenderer() { 112 delete mTarget; 113 mTarget = NULL; 114 115 if (mLibHandle) { 116 dlclose(mLibHandle); 117 mLibHandle = NULL; 118 } 119 } 120 121private: 122 VideoRenderer *mTarget; 123 void *mLibHandle; 124 125 void init( 126 bool previewOnly, 127 const char *componentName, 128 OMX_COLOR_FORMATTYPE colorFormat, 129 const sp<ISurface> &surface, 130 size_t displayWidth, size_t displayHeight, 131 size_t decodedWidth, size_t decodedHeight); 132 133 AwesomeLocalRenderer(const AwesomeLocalRenderer &); 134 AwesomeLocalRenderer &operator=(const AwesomeLocalRenderer &);; 135}; 136 137void AwesomeLocalRenderer::init( 138 bool previewOnly, 139 const char *componentName, 140 OMX_COLOR_FORMATTYPE colorFormat, 141 const sp<ISurface> &surface, 142 size_t displayWidth, size_t displayHeight, 143 size_t decodedWidth, size_t decodedHeight) { 144 if (!previewOnly) { 145 // We will stick to the vanilla software-color-converting renderer 146 // for "previewOnly" mode, to avoid unneccessarily switching overlays 147 // more often than necessary. 148 149 mLibHandle = dlopen("libstagefrighthw.so", RTLD_NOW); 150 151 if (mLibHandle) { 152 typedef VideoRenderer *(*CreateRendererFunc)( 153 const sp<ISurface> &surface, 154 const char *componentName, 155 OMX_COLOR_FORMATTYPE colorFormat, 156 size_t displayWidth, size_t displayHeight, 157 size_t decodedWidth, size_t decodedHeight); 158 159 CreateRendererFunc func = 160 (CreateRendererFunc)dlsym( 161 mLibHandle, 162 "_Z14createRendererRKN7android2spINS_8ISurfaceEEEPKc20" 163 "OMX_COLOR_FORMATTYPEjjjj"); 164 165 if (func) { 166 mTarget = 167 (*func)(surface, componentName, colorFormat, 168 displayWidth, displayHeight, 169 decodedWidth, decodedHeight); 170 } 171 } 172 } 173 174 if (mTarget == NULL) { 175 mTarget = new SoftwareRenderer( 176 colorFormat, surface, displayWidth, displayHeight, 177 decodedWidth, decodedHeight); 178 } 179} 180 181AwesomePlayer::AwesomePlayer() 182 : mQueueStarted(false), 183 mTimeSource(NULL), 184 mVideoRendererIsPreview(false), 185 mAudioPlayer(NULL), 186 mFlags(0), 187 mExtractorFlags(0), 188 mLastVideoBuffer(NULL), 189 mVideoBuffer(NULL), 190 mSuspensionState(NULL), 191 mDecryptHandle(NULL) { 192 CHECK_EQ(mClient.connect(), OK); 193 194 DataSource::RegisterDefaultSniffers(); 195 196 mVideoEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoEvent); 197 mVideoEventPending = false; 198 mStreamDoneEvent = new AwesomeEvent(this, &AwesomePlayer::onStreamDone); 199 mStreamDoneEventPending = false; 200 mBufferingEvent = new AwesomeEvent(this, &AwesomePlayer::onBufferingUpdate); 201 mBufferingEventPending = false; 202 203 mCheckAudioStatusEvent = new AwesomeEvent( 204 this, &AwesomePlayer::onCheckAudioStatus); 205 206 mAudioStatusEventPending = false; 207 208 reset(); 209} 210 211AwesomePlayer::~AwesomePlayer() { 212 if (mQueueStarted) { 213 mQueue.stop(); 214 } 215 216 reset(); 217 218 mClient.disconnect(); 219} 220 221void AwesomePlayer::cancelPlayerEvents(bool keepBufferingGoing) { 222 mQueue.cancelEvent(mVideoEvent->eventID()); 223 mVideoEventPending = false; 224 mQueue.cancelEvent(mStreamDoneEvent->eventID()); 225 mStreamDoneEventPending = false; 226 mQueue.cancelEvent(mCheckAudioStatusEvent->eventID()); 227 mAudioStatusEventPending = false; 228 229 if (!keepBufferingGoing) { 230 mQueue.cancelEvent(mBufferingEvent->eventID()); 231 mBufferingEventPending = false; 232 } 233} 234 235void AwesomePlayer::setListener(const wp<MediaPlayerBase> &listener) { 236 Mutex::Autolock autoLock(mLock); 237 mListener = listener; 238} 239 240status_t AwesomePlayer::setDataSource( 241 const char *uri, const KeyedVector<String8, String8> *headers) { 242 Mutex::Autolock autoLock(mLock); 243 return setDataSource_l(uri, headers); 244} 245 246status_t AwesomePlayer::setDataSource_l( 247 const char *uri, const KeyedVector<String8, String8> *headers) { 248 reset_l(); 249 250 mUri = uri; 251 252 if (headers) { 253 mUriHeaders = *headers; 254 } 255 256 // The actual work will be done during preparation in the call to 257 // ::finishSetDataSource_l to avoid blocking the calling thread in 258 // setDataSource for any significant time. 259 260 return OK; 261} 262 263status_t AwesomePlayer::setDataSource( 264 int fd, int64_t offset, int64_t length) { 265 Mutex::Autolock autoLock(mLock); 266 267 reset_l(); 268 269 sp<DataSource> dataSource = new FileSource(fd, offset, length); 270 271 status_t err = dataSource->initCheck(); 272 273 if (err != OK) { 274 return err; 275 } 276 277 mFileSource = dataSource; 278 279 return setDataSource_l(dataSource); 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 if (RightsStatus::RIGHTS_VALID == mDecryptHandle->status) { 293 if (DecryptApiType::CONTAINER_BASED == mDecryptHandle->decryptApiType) { 294 mDrmManagerClient->consumeRights(mDecryptHandle, Action::PLAY, true); 295 } 296 } else { 297 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_NO_LICENSE); 298 } 299 } 300 301 return setDataSource_l(extractor); 302} 303 304status_t AwesomePlayer::setDataSource_l(const sp<MediaExtractor> &extractor) { 305 bool haveAudio = false; 306 bool haveVideo = false; 307 for (size_t i = 0; i < extractor->countTracks(); ++i) { 308 sp<MetaData> meta = extractor->getTrackMetaData(i); 309 310 const char *mime; 311 CHECK(meta->findCString(kKeyMIMEType, &mime)); 312 313 if (!haveVideo && !strncasecmp(mime, "video/", 6)) { 314 setVideoSource(extractor->getTrack(i)); 315 haveVideo = true; 316 } else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) { 317 setAudioSource(extractor->getTrack(i)); 318 haveAudio = true; 319 } 320 321 if (haveAudio && haveVideo) { 322 break; 323 } 324 } 325 326 if (!haveAudio && !haveVideo) { 327 return UNKNOWN_ERROR; 328 } 329 330 mExtractorFlags = extractor->flags(); 331 if (mDecryptHandle != NULL) { 332 if (DecryptApiType::ELEMENTARY_STREAM_BASED == mDecryptHandle->decryptApiType) { 333 mDrmManagerClient->consumeRights(mDecryptHandle, Action::PLAY, true); 334 } 335 } 336 337 return OK; 338} 339 340void AwesomePlayer::reset() { 341 Mutex::Autolock autoLock(mLock); 342 reset_l(); 343} 344 345void AwesomePlayer::reset_l() { 346 if (mDecryptHandle != NULL) { 347 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, 348 Playback::STOP, 0); 349 mDrmManagerClient->consumeRights(mDecryptHandle, 350 Action::PLAY, false); 351 mDecryptHandle = NULL; 352 mDrmManagerClient = NULL; 353 } 354 355 if (mFlags & PREPARING) { 356 mFlags |= PREPARE_CANCELLED; 357 if (mConnectingDataSource != NULL) { 358 LOGI("interrupting the connection process"); 359 mConnectingDataSource->disconnect(); 360 } 361 } 362 363 while (mFlags & PREPARING) { 364 mPreparedCondition.wait(mLock); 365 } 366 367 cancelPlayerEvents(); 368 369 if (mPrefetcher != NULL) { 370 CHECK_EQ(mPrefetcher->getStrongCount(), 1); 371 } 372 mPrefetcher.clear(); 373 374 mAudioTrack.clear(); 375 mVideoTrack.clear(); 376 377 // Shutdown audio first, so that the respone to the reset request 378 // appears to happen instantaneously as far as the user is concerned 379 // If we did this later, audio would continue playing while we 380 // shutdown the video-related resources and the player appear to 381 // not be as responsive to a reset request. 382 if (mAudioPlayer == NULL && mAudioSource != NULL) { 383 // If we had an audio player, it would have effectively 384 // taken possession of the audio source and stopped it when 385 // _it_ is stopped. Otherwise this is still our responsibility. 386 mAudioSource->stop(); 387 } 388 mAudioSource.clear(); 389 390 if (mTimeSource != mAudioPlayer) { 391 delete mTimeSource; 392 } 393 mTimeSource = NULL; 394 395 delete mAudioPlayer; 396 mAudioPlayer = NULL; 397 398 mVideoRenderer.clear(); 399 400 if (mLastVideoBuffer) { 401 mLastVideoBuffer->release(); 402 mLastVideoBuffer = NULL; 403 } 404 405 if (mVideoBuffer) { 406 mVideoBuffer->release(); 407 mVideoBuffer = NULL; 408 } 409 410 if (mVideoSource != NULL) { 411 mVideoSource->stop(); 412 413 // The following hack is necessary to ensure that the OMX 414 // component is completely released by the time we may try 415 // to instantiate it again. 416 wp<MediaSource> tmp = mVideoSource; 417 mVideoSource.clear(); 418 while (tmp.promote() != NULL) { 419 usleep(1000); 420 } 421 IPCThreadState::self()->flushCommands(); 422 } 423 424 mDurationUs = -1; 425 mFlags = 0; 426 mExtractorFlags = 0; 427 mVideoWidth = mVideoHeight = -1; 428 mTimeSourceDeltaUs = 0; 429 mVideoTimeUs = 0; 430 431 mSeeking = false; 432 mSeekNotificationSent = false; 433 mSeekTimeUs = 0; 434 435 mUri.setTo(""); 436 mUriHeaders.clear(); 437 438 mFileSource.clear(); 439 440 delete mSuspensionState; 441 mSuspensionState = NULL; 442} 443 444void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) { 445 if (mListener != NULL) { 446 sp<MediaPlayerBase> listener = mListener.promote(); 447 448 if (listener != NULL) { 449 listener->sendEvent(msg, ext1, ext2); 450 } 451 } 452} 453 454void AwesomePlayer::onBufferingUpdate() { 455 Mutex::Autolock autoLock(mLock); 456 if (!mBufferingEventPending) { 457 return; 458 } 459 mBufferingEventPending = false; 460 461 int64_t durationUs; 462 { 463 Mutex::Autolock autoLock(mMiscStateLock); 464 durationUs = mDurationUs; 465 } 466 467 if (durationUs >= 0) { 468 int64_t cachedDurationUs = mPrefetcher->getCachedDurationUs(); 469 470 LOGV("cache holds %.2f secs worth of data.", cachedDurationUs / 1E6); 471 472 int64_t positionUs; 473 getPosition(&positionUs); 474 475 cachedDurationUs += positionUs; 476 477 double percentage = (double)cachedDurationUs / durationUs; 478 notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage * 100.0); 479 480 postBufferingEvent_l(); 481 } else { 482 LOGE("Not sending buffering status because duration is unknown."); 483 } 484} 485 486void AwesomePlayer::onStreamDone() { 487 // Posted whenever any stream finishes playing. 488 489 Mutex::Autolock autoLock(mLock); 490 if (!mStreamDoneEventPending) { 491 return; 492 } 493 mStreamDoneEventPending = false; 494 495 if (mStreamDoneStatus == ERROR_END_OF_STREAM && (mFlags & LOOPING)) { 496 seekTo_l(0); 497 498 if (mVideoSource != NULL) { 499 postVideoEvent_l(); 500 } 501 } else { 502 if (mStreamDoneStatus == ERROR_END_OF_STREAM) { 503 LOGV("MEDIA_PLAYBACK_COMPLETE"); 504 notifyListener_l(MEDIA_PLAYBACK_COMPLETE); 505 } else { 506 LOGV("MEDIA_ERROR %d", mStreamDoneStatus); 507 508 notifyListener_l( 509 MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, mStreamDoneStatus); 510 } 511 512 pause_l(); 513 514 mFlags |= AT_EOS; 515 } 516} 517 518status_t AwesomePlayer::play() { 519 Mutex::Autolock autoLock(mLock); 520 return play_l(); 521} 522 523status_t AwesomePlayer::play_l() { 524 if (mFlags & PLAYING) { 525 return OK; 526 } 527 528 if (!(mFlags & PREPARED)) { 529 status_t err = prepare_l(); 530 531 if (err != OK) { 532 return err; 533 } 534 } 535 536 mFlags |= PLAYING; 537 mFlags |= FIRST_FRAME; 538 539 bool deferredAudioSeek = false; 540 541 if (mAudioSource != NULL) { 542 if (mAudioPlayer == NULL) { 543 if (mAudioSink != NULL) { 544 mAudioPlayer = new AudioPlayer(mAudioSink); 545 mAudioPlayer->setSource(mAudioSource); 546 547 // We've already started the MediaSource in order to enable 548 // the prefetcher to read its data. 549 status_t err = mAudioPlayer->start( 550 true /* sourceAlreadyStarted */); 551 552 if (err != OK) { 553 delete mAudioPlayer; 554 mAudioPlayer = NULL; 555 556 mFlags &= ~(PLAYING | FIRST_FRAME); 557 558 return err; 559 } 560 561 delete mTimeSource; 562 mTimeSource = mAudioPlayer; 563 564 deferredAudioSeek = true; 565 566 mWatchForAudioSeekComplete = false; 567 mWatchForAudioEOS = true; 568 } 569 } else { 570 mAudioPlayer->resume(); 571 } 572 573 postCheckAudioStatusEvent_l(); 574 } 575 576 if (mTimeSource == NULL && mAudioPlayer == NULL) { 577 mTimeSource = new SystemTimeSource; 578 } 579 580 if (mVideoSource != NULL) { 581 // Kick off video playback 582 postVideoEvent_l(); 583 } 584 585 if (deferredAudioSeek) { 586 // If there was a seek request while we were paused 587 // and we're just starting up again, honor the request now. 588 seekAudioIfNecessary_l(); 589 } 590 591 if (mFlags & AT_EOS) { 592 // Legacy behaviour, if a stream finishes playing and then 593 // is started again, we play from the start... 594 seekTo_l(0); 595 } 596 597 if (mDecryptHandle != NULL) { 598 int64_t position; 599 getPosition(&position); 600 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, 601 Playback::START, position / 1000); 602 } 603 604 return OK; 605} 606 607void AwesomePlayer::initRenderer_l() { 608 if (mISurface != NULL) { 609 sp<MetaData> meta = mVideoSource->getFormat(); 610 611 int32_t format; 612 const char *component; 613 int32_t decodedWidth, decodedHeight; 614 CHECK(meta->findInt32(kKeyColorFormat, &format)); 615 CHECK(meta->findCString(kKeyDecoderComponent, &component)); 616 CHECK(meta->findInt32(kKeyWidth, &decodedWidth)); 617 CHECK(meta->findInt32(kKeyHeight, &decodedHeight)); 618 619 mVideoRenderer.clear(); 620 621 // Must ensure that mVideoRenderer's destructor is actually executed 622 // before creating a new one. 623 IPCThreadState::self()->flushCommands(); 624 625 if (!strncmp("OMX.", component, 4)) { 626 // Our OMX codecs allocate buffers on the media_server side 627 // therefore they require a remote IOMXRenderer that knows how 628 // to display them. 629 mVideoRenderer = new AwesomeRemoteRenderer( 630 mClient.interface()->createRenderer( 631 mISurface, component, 632 (OMX_COLOR_FORMATTYPE)format, 633 decodedWidth, decodedHeight, 634 mVideoWidth, mVideoHeight)); 635 } else { 636 // Other decoders are instantiated locally and as a consequence 637 // allocate their buffers in local address space. 638 mVideoRenderer = new AwesomeLocalRenderer( 639 false, // previewOnly 640 component, 641 (OMX_COLOR_FORMATTYPE)format, 642 mISurface, 643 mVideoWidth, mVideoHeight, 644 decodedWidth, decodedHeight); 645 } 646 } 647} 648 649status_t AwesomePlayer::pause() { 650 Mutex::Autolock autoLock(mLock); 651 return pause_l(); 652} 653 654status_t AwesomePlayer::pause_l() { 655 if (!(mFlags & PLAYING)) { 656 return OK; 657 } 658 659 cancelPlayerEvents(true /* keepBufferingGoing */); 660 661 if (mAudioPlayer != NULL) { 662 mAudioPlayer->pause(); 663 } 664 665 mFlags &= ~PLAYING; 666 667 if (mDecryptHandle != NULL) { 668 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, 669 Playback::PAUSE, 0); 670 } 671 672 return OK; 673} 674 675bool AwesomePlayer::isPlaying() const { 676 return mFlags & PLAYING; 677} 678 679void AwesomePlayer::setISurface(const sp<ISurface> &isurface) { 680 Mutex::Autolock autoLock(mLock); 681 682 mISurface = isurface; 683} 684 685void AwesomePlayer::setAudioSink( 686 const sp<MediaPlayerBase::AudioSink> &audioSink) { 687 Mutex::Autolock autoLock(mLock); 688 689 mAudioSink = audioSink; 690} 691 692status_t AwesomePlayer::setLooping(bool shouldLoop) { 693 Mutex::Autolock autoLock(mLock); 694 695 mFlags = mFlags & ~LOOPING; 696 697 if (shouldLoop) { 698 mFlags |= LOOPING; 699 } 700 701 return OK; 702} 703 704status_t AwesomePlayer::getDuration(int64_t *durationUs) { 705 Mutex::Autolock autoLock(mMiscStateLock); 706 707 if (mDurationUs < 0) { 708 return UNKNOWN_ERROR; 709 } 710 711 *durationUs = mDurationUs; 712 713 return OK; 714} 715 716status_t AwesomePlayer::getPosition(int64_t *positionUs) { 717 if (mSeeking) { 718 *positionUs = mSeekTimeUs; 719 } else if (mVideoSource != NULL) { 720 Mutex::Autolock autoLock(mMiscStateLock); 721 *positionUs = mVideoTimeUs; 722 } else if (mAudioPlayer != NULL) { 723 *positionUs = mAudioPlayer->getMediaTimeUs(); 724 } else { 725 *positionUs = 0; 726 } 727 728 return OK; 729} 730 731status_t AwesomePlayer::seekTo(int64_t timeUs) { 732 if (mExtractorFlags 733 & (MediaExtractor::CAN_SEEK_FORWARD 734 | MediaExtractor::CAN_SEEK_BACKWARD)) { 735 Mutex::Autolock autoLock(mLock); 736 return seekTo_l(timeUs); 737 } 738 739 return OK; 740} 741 742status_t AwesomePlayer::seekTo_l(int64_t timeUs) { 743 mSeeking = true; 744 mSeekNotificationSent = false; 745 mSeekTimeUs = timeUs; 746 mFlags &= ~AT_EOS; 747 748 seekAudioIfNecessary_l(); 749 750 if (!(mFlags & PLAYING)) { 751 LOGV("seeking while paused, sending SEEK_COMPLETE notification" 752 " immediately."); 753 754 notifyListener_l(MEDIA_SEEK_COMPLETE); 755 mSeekNotificationSent = true; 756 } 757 758 return OK; 759} 760 761void AwesomePlayer::seekAudioIfNecessary_l() { 762 if (mSeeking && mVideoSource == NULL && mAudioPlayer != NULL) { 763 mAudioPlayer->seekTo(mSeekTimeUs); 764 765 mWatchForAudioSeekComplete = true; 766 mWatchForAudioEOS = true; 767 mSeekNotificationSent = false; 768 769 if (mDecryptHandle != NULL) { 770 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, 771 Playback::PAUSE, 0); 772 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, 773 Playback::START, mSeekTimeUs / 1000); 774 } 775 } 776} 777 778status_t AwesomePlayer::getVideoDimensions( 779 int32_t *width, int32_t *height) const { 780 Mutex::Autolock autoLock(mLock); 781 782 if (mVideoWidth < 0 || mVideoHeight < 0) { 783 return UNKNOWN_ERROR; 784 } 785 786 *width = mVideoWidth; 787 *height = mVideoHeight; 788 789 return OK; 790} 791 792void AwesomePlayer::setAudioSource(sp<MediaSource> source) { 793 CHECK(source != NULL); 794 795 if (mPrefetcher != NULL) { 796 source = mPrefetcher->addSource(source); 797 } 798 799 mAudioTrack = source; 800} 801 802status_t AwesomePlayer::initAudioDecoder() { 803 sp<MetaData> meta = mAudioTrack->getFormat(); 804 805 const char *mime; 806 CHECK(meta->findCString(kKeyMIMEType, &mime)); 807 808 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) { 809 mAudioSource = mAudioTrack; 810 } else { 811 mAudioSource = OMXCodec::Create( 812 mClient.interface(), mAudioTrack->getFormat(), 813 false, // createEncoder 814 mAudioTrack); 815 } 816 817 if (mAudioSource != NULL) { 818 int64_t durationUs; 819 if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) { 820 Mutex::Autolock autoLock(mMiscStateLock); 821 if (mDurationUs < 0 || durationUs > mDurationUs) { 822 mDurationUs = durationUs; 823 } 824 } 825 826 status_t err = mAudioSource->start(); 827 828 if (err != OK) { 829 mAudioSource.clear(); 830 return err; 831 } 832 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_QCELP)) { 833 // For legacy reasons we're simply going to ignore the absence 834 // of an audio decoder for QCELP instead of aborting playback 835 // altogether. 836 return OK; 837 } 838 839 return mAudioSource != NULL ? OK : UNKNOWN_ERROR; 840} 841 842void AwesomePlayer::setVideoSource(sp<MediaSource> source) { 843 CHECK(source != NULL); 844 845 if (mPrefetcher != NULL) { 846 source = mPrefetcher->addSource(source); 847 } 848 849 mVideoTrack = source; 850} 851 852status_t AwesomePlayer::initVideoDecoder() { 853 mVideoSource = OMXCodec::Create( 854 mClient.interface(), mVideoTrack->getFormat(), 855 false, // createEncoder 856 mVideoTrack); 857 858 if (mVideoSource != NULL) { 859 int64_t durationUs; 860 if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) { 861 Mutex::Autolock autoLock(mMiscStateLock); 862 if (mDurationUs < 0 || durationUs > mDurationUs) { 863 mDurationUs = durationUs; 864 } 865 } 866 867 CHECK(mVideoTrack->getFormat()->findInt32(kKeyWidth, &mVideoWidth)); 868 CHECK(mVideoTrack->getFormat()->findInt32(kKeyHeight, &mVideoHeight)); 869 870 status_t err = mVideoSource->start(); 871 872 if (err != OK) { 873 mVideoSource.clear(); 874 return err; 875 } 876 } 877 878 return mVideoSource != NULL ? OK : UNKNOWN_ERROR; 879} 880 881void AwesomePlayer::onVideoEvent() { 882 Mutex::Autolock autoLock(mLock); 883 if (!mVideoEventPending) { 884 // The event has been cancelled in reset_l() but had already 885 // been scheduled for execution at that time. 886 return; 887 } 888 mVideoEventPending = false; 889 890 if (mSeeking) { 891 if (mLastVideoBuffer) { 892 mLastVideoBuffer->release(); 893 mLastVideoBuffer = NULL; 894 } 895 896 if (mVideoBuffer) { 897 mVideoBuffer->release(); 898 mVideoBuffer = NULL; 899 } 900 } 901 902 if (!mVideoBuffer) { 903 MediaSource::ReadOptions options; 904 if (mSeeking) { 905 LOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs, mSeekTimeUs / 1E6); 906 907 options.setSeekTo(mSeekTimeUs); 908 } 909 for (;;) { 910 status_t err = mVideoSource->read(&mVideoBuffer, &options); 911 options.clearSeekTo(); 912 913 if (err != OK) { 914 CHECK_EQ(mVideoBuffer, NULL); 915 916 if (err == INFO_FORMAT_CHANGED) { 917 LOGV("VideoSource signalled format change."); 918 919 if (mVideoRenderer != NULL) { 920 mVideoRendererIsPreview = false; 921 initRenderer_l(); 922 } 923 continue; 924 } 925 926 postStreamDoneEvent_l(err); 927 return; 928 } 929 930 if (mVideoBuffer->range_length() == 0) { 931 // Some decoders, notably the PV AVC software decoder 932 // return spurious empty buffers that we just want to ignore. 933 934 mVideoBuffer->release(); 935 mVideoBuffer = NULL; 936 continue; 937 } 938 939 break; 940 } 941 } 942 943 int64_t timeUs; 944 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs)); 945 946 { 947 Mutex::Autolock autoLock(mMiscStateLock); 948 mVideoTimeUs = timeUs; 949 } 950 951 if (mSeeking) { 952 if (mAudioPlayer != NULL) { 953 LOGV("seeking audio to %lld us (%.2f secs).", timeUs, timeUs / 1E6); 954 955 mAudioPlayer->seekTo(timeUs); 956 mWatchForAudioSeekComplete = true; 957 mWatchForAudioEOS = true; 958 } else if (!mSeekNotificationSent) { 959 // If we're playing video only, report seek complete now, 960 // otherwise audio player will notify us later. 961 notifyListener_l(MEDIA_SEEK_COMPLETE); 962 } 963 964 mFlags |= FIRST_FRAME; 965 mSeeking = false; 966 mSeekNotificationSent = false; 967 968 if (mDecryptHandle != NULL) { 969 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, 970 Playback::PAUSE, 0); 971 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, 972 Playback::START, timeUs / 1000); 973 } 974 } 975 976 if (mFlags & FIRST_FRAME) { 977 mFlags &= ~FIRST_FRAME; 978 979 mTimeSourceDeltaUs = mTimeSource->getRealTimeUs() - timeUs; 980 } 981 982 int64_t realTimeUs, mediaTimeUs; 983 if (mAudioPlayer != NULL 984 && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) { 985 mTimeSourceDeltaUs = realTimeUs - mediaTimeUs; 986 } 987 988 int64_t nowUs = mTimeSource->getRealTimeUs() - mTimeSourceDeltaUs; 989 990 int64_t latenessUs = nowUs - timeUs; 991 992 if (latenessUs > 40000) { 993 // We're more than 40ms late. 994 LOGV("we're late by %lld us (%.2f secs)", latenessUs, latenessUs / 1E6); 995 996 mVideoBuffer->release(); 997 mVideoBuffer = NULL; 998 999 postVideoEvent_l(); 1000 return; 1001 } 1002 1003 if (latenessUs < -10000) { 1004 // We're more than 10ms early. 1005 1006 postVideoEvent_l(10000); 1007 return; 1008 } 1009 1010 if (mVideoRendererIsPreview || mVideoRenderer == NULL) { 1011 mVideoRendererIsPreview = false; 1012 1013 initRenderer_l(); 1014 } 1015 1016 if (mVideoRenderer != NULL) { 1017 mVideoRenderer->render(mVideoBuffer); 1018 } 1019 1020 if (mLastVideoBuffer) { 1021 mLastVideoBuffer->release(); 1022 mLastVideoBuffer = NULL; 1023 } 1024 mLastVideoBuffer = mVideoBuffer; 1025 mVideoBuffer = NULL; 1026 1027 postVideoEvent_l(); 1028} 1029 1030void AwesomePlayer::postVideoEvent_l(int64_t delayUs) { 1031 if (mVideoEventPending) { 1032 return; 1033 } 1034 1035 mVideoEventPending = true; 1036 mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs); 1037} 1038 1039void AwesomePlayer::postStreamDoneEvent_l(status_t status) { 1040 if (mStreamDoneEventPending) { 1041 return; 1042 } 1043 mStreamDoneEventPending = true; 1044 1045 mStreamDoneStatus = status; 1046 mQueue.postEvent(mStreamDoneEvent); 1047} 1048 1049void AwesomePlayer::postBufferingEvent_l() { 1050 if (mPrefetcher == NULL) { 1051 return; 1052 } 1053 1054 if (mBufferingEventPending) { 1055 return; 1056 } 1057 mBufferingEventPending = true; 1058 mQueue.postEventWithDelay(mBufferingEvent, 1000000ll); 1059} 1060 1061void AwesomePlayer::postCheckAudioStatusEvent_l() { 1062 if (mAudioStatusEventPending) { 1063 return; 1064 } 1065 mAudioStatusEventPending = true; 1066 mQueue.postEventWithDelay(mCheckAudioStatusEvent, 100000ll); 1067} 1068 1069void AwesomePlayer::onCheckAudioStatus() { 1070 Mutex::Autolock autoLock(mLock); 1071 if (!mAudioStatusEventPending) { 1072 // Event was dispatched and while we were blocking on the mutex, 1073 // has already been cancelled. 1074 return; 1075 } 1076 1077 mAudioStatusEventPending = false; 1078 1079 if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) { 1080 mWatchForAudioSeekComplete = false; 1081 1082 if (!mSeekNotificationSent) { 1083 notifyListener_l(MEDIA_SEEK_COMPLETE); 1084 mSeekNotificationSent = true; 1085 } 1086 1087 mSeeking = false; 1088 } 1089 1090 status_t finalStatus; 1091 if (mWatchForAudioEOS && mAudioPlayer->reachedEOS(&finalStatus)) { 1092 mWatchForAudioEOS = false; 1093 postStreamDoneEvent_l(finalStatus); 1094 } 1095 1096 postCheckAudioStatusEvent_l(); 1097} 1098 1099status_t AwesomePlayer::prepare() { 1100 Mutex::Autolock autoLock(mLock); 1101 return prepare_l(); 1102} 1103 1104status_t AwesomePlayer::prepare_l() { 1105 if (mFlags & PREPARED) { 1106 return OK; 1107 } 1108 1109 if (mFlags & PREPARING) { 1110 return UNKNOWN_ERROR; 1111 } 1112 1113 mIsAsyncPrepare = false; 1114 status_t err = prepareAsync_l(); 1115 1116 if (err != OK) { 1117 return err; 1118 } 1119 1120 while (mFlags & PREPARING) { 1121 mPreparedCondition.wait(mLock); 1122 } 1123 1124 return mPrepareResult; 1125} 1126 1127status_t AwesomePlayer::prepareAsync() { 1128 Mutex::Autolock autoLock(mLock); 1129 1130 if (mFlags & PREPARING) { 1131 return UNKNOWN_ERROR; // async prepare already pending 1132 } 1133 1134 mIsAsyncPrepare = true; 1135 return prepareAsync_l(); 1136} 1137 1138status_t AwesomePlayer::prepareAsync_l() { 1139 if (mFlags & PREPARING) { 1140 return UNKNOWN_ERROR; // async prepare already pending 1141 } 1142 1143 if (!mQueueStarted) { 1144 mQueue.start(); 1145 mQueueStarted = true; 1146 } 1147 1148 mFlags |= PREPARING; 1149 mAsyncPrepareEvent = new AwesomeEvent( 1150 this, &AwesomePlayer::onPrepareAsyncEvent); 1151 1152 mQueue.postEvent(mAsyncPrepareEvent); 1153 1154 return OK; 1155} 1156 1157status_t AwesomePlayer::finishSetDataSource_l() { 1158 sp<DataSource> dataSource; 1159 1160 if (!strncasecmp("http://", mUri.string(), 7)) { 1161 mConnectingDataSource = new HTTPDataSource(mUri, &mUriHeaders); 1162 1163 mLock.unlock(); 1164 status_t err = mConnectingDataSource->connect(); 1165 mLock.lock(); 1166 1167 if (err != OK) { 1168 mConnectingDataSource.clear(); 1169 1170 LOGI("mConnectingDataSource->connect() returned %d", err); 1171 return err; 1172 } 1173 1174 dataSource = new CachingDataSource( 1175 mConnectingDataSource, 64 * 1024, 10); 1176 1177 mConnectingDataSource.clear(); 1178 } else { 1179 dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders); 1180 } 1181 1182 if (dataSource == NULL) { 1183 return UNKNOWN_ERROR; 1184 } 1185 1186 sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource); 1187 1188 if (extractor == NULL) { 1189 return UNKNOWN_ERROR; 1190 } 1191 1192 dataSource->getDrmInfo(&mDecryptHandle, &mDrmManagerClient); 1193 if (mDecryptHandle != NULL) { 1194 if (RightsStatus::RIGHTS_VALID == mDecryptHandle->status) { 1195 if (DecryptApiType::CONTAINER_BASED == mDecryptHandle->decryptApiType) { 1196 mDrmManagerClient->consumeRights(mDecryptHandle, Action::PLAY, true); 1197 } 1198 } else { 1199 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_NO_LICENSE); 1200 } 1201 } 1202 1203 if (dataSource->flags() & DataSource::kWantsPrefetching) { 1204 mPrefetcher = new Prefetcher; 1205 } 1206 1207 return setDataSource_l(extractor); 1208} 1209 1210void AwesomePlayer::abortPrepare(status_t err) { 1211 CHECK(err != OK); 1212 1213 if (mIsAsyncPrepare) { 1214 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err); 1215 } 1216 1217 mPrepareResult = err; 1218 mFlags &= ~(PREPARING|PREPARE_CANCELLED); 1219 mAsyncPrepareEvent = NULL; 1220 mPreparedCondition.broadcast(); 1221} 1222 1223// static 1224bool AwesomePlayer::ContinuePreparation(void *cookie) { 1225 AwesomePlayer *me = static_cast<AwesomePlayer *>(cookie); 1226 1227 return (me->mFlags & PREPARE_CANCELLED) == 0; 1228} 1229 1230void AwesomePlayer::onPrepareAsyncEvent() { 1231 sp<Prefetcher> prefetcher; 1232 1233 { 1234 Mutex::Autolock autoLock(mLock); 1235 1236 if (mFlags & PREPARE_CANCELLED) { 1237 LOGI("prepare was cancelled before doing anything"); 1238 abortPrepare(UNKNOWN_ERROR); 1239 return; 1240 } 1241 1242 if (mUri.size() > 0) { 1243 status_t err = finishSetDataSource_l(); 1244 1245 if (err != OK) { 1246 abortPrepare(err); 1247 return; 1248 } 1249 } 1250 1251 if (mVideoTrack != NULL && mVideoSource == NULL) { 1252 status_t err = initVideoDecoder(); 1253 1254 if (err != OK) { 1255 abortPrepare(err); 1256 return; 1257 } 1258 } 1259 1260 if (mAudioTrack != NULL && mAudioSource == NULL) { 1261 status_t err = initAudioDecoder(); 1262 1263 if (err != OK) { 1264 abortPrepare(err); 1265 return; 1266 } 1267 } 1268 1269 prefetcher = mPrefetcher; 1270 } 1271 1272 if (prefetcher != NULL) { 1273 { 1274 Mutex::Autolock autoLock(mLock); 1275 if (mFlags & PREPARE_CANCELLED) { 1276 LOGI("prepare was cancelled before preparing the prefetcher"); 1277 1278 prefetcher.clear(); 1279 abortPrepare(UNKNOWN_ERROR); 1280 return; 1281 } 1282 } 1283 1284 LOGI("calling prefetcher->prepare()"); 1285 status_t result = 1286 prefetcher->prepare(&AwesomePlayer::ContinuePreparation, this); 1287 1288 prefetcher.clear(); 1289 1290 if (result == OK) { 1291 LOGI("prefetcher is done preparing"); 1292 } else { 1293 Mutex::Autolock autoLock(mLock); 1294 1295 CHECK_EQ(result, -EINTR); 1296 1297 LOGI("prefetcher->prepare() was cancelled early."); 1298 abortPrepare(UNKNOWN_ERROR); 1299 return; 1300 } 1301 } 1302 1303 Mutex::Autolock autoLock(mLock); 1304 1305 if (mIsAsyncPrepare) { 1306 if (mVideoWidth < 0 || mVideoHeight < 0) { 1307 notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0); 1308 } else { 1309 notifyListener_l(MEDIA_SET_VIDEO_SIZE, mVideoWidth, mVideoHeight); 1310 } 1311 1312 notifyListener_l(MEDIA_PREPARED); 1313 } 1314 1315 mPrepareResult = OK; 1316 mFlags &= ~(PREPARING|PREPARE_CANCELLED); 1317 mFlags |= PREPARED; 1318 mAsyncPrepareEvent = NULL; 1319 mPreparedCondition.broadcast(); 1320 1321 postBufferingEvent_l(); 1322} 1323 1324status_t AwesomePlayer::suspend() { 1325 LOGV("suspend"); 1326 Mutex::Autolock autoLock(mLock); 1327 1328 if (mSuspensionState != NULL) { 1329 if (mLastVideoBuffer == NULL) { 1330 //go into here if video is suspended again 1331 //after resuming without being played between 1332 //them 1333 SuspensionState *state = mSuspensionState; 1334 mSuspensionState = NULL; 1335 reset_l(); 1336 mSuspensionState = state; 1337 return OK; 1338 } 1339 1340 delete mSuspensionState; 1341 mSuspensionState = NULL; 1342 } 1343 1344 if (mFlags & PREPARING) { 1345 mFlags |= PREPARE_CANCELLED; 1346 if (mConnectingDataSource != NULL) { 1347 LOGI("interrupting the connection process"); 1348 mConnectingDataSource->disconnect(); 1349 } 1350 } 1351 1352 while (mFlags & PREPARING) { 1353 mPreparedCondition.wait(mLock); 1354 } 1355 1356 SuspensionState *state = new SuspensionState; 1357 state->mUri = mUri; 1358 state->mUriHeaders = mUriHeaders; 1359 state->mFileSource = mFileSource; 1360 1361 state->mFlags = mFlags & (PLAYING | LOOPING | AT_EOS); 1362 getPosition(&state->mPositionUs); 1363 1364 if (mLastVideoBuffer) { 1365 size_t size = mLastVideoBuffer->range_length(); 1366 if (size) { 1367 state->mLastVideoFrameSize = size; 1368 state->mLastVideoFrame = malloc(size); 1369 memcpy(state->mLastVideoFrame, 1370 (const uint8_t *)mLastVideoBuffer->data() 1371 + mLastVideoBuffer->range_offset(), 1372 size); 1373 1374 state->mVideoWidth = mVideoWidth; 1375 state->mVideoHeight = mVideoHeight; 1376 1377 sp<MetaData> meta = mVideoSource->getFormat(); 1378 CHECK(meta->findInt32(kKeyColorFormat, &state->mColorFormat)); 1379 CHECK(meta->findInt32(kKeyWidth, &state->mDecodedWidth)); 1380 CHECK(meta->findInt32(kKeyHeight, &state->mDecodedHeight)); 1381 } 1382 } 1383 1384 reset_l(); 1385 1386 mSuspensionState = state; 1387 1388 return OK; 1389} 1390 1391status_t AwesomePlayer::resume() { 1392 LOGV("resume"); 1393 Mutex::Autolock autoLock(mLock); 1394 1395 if (mSuspensionState == NULL) { 1396 return INVALID_OPERATION; 1397 } 1398 1399 SuspensionState *state = mSuspensionState; 1400 mSuspensionState = NULL; 1401 1402 status_t err; 1403 if (state->mFileSource != NULL) { 1404 err = setDataSource_l(state->mFileSource); 1405 1406 if (err == OK) { 1407 mFileSource = state->mFileSource; 1408 } 1409 } else { 1410 err = setDataSource_l(state->mUri, &state->mUriHeaders); 1411 } 1412 1413 if (err != OK) { 1414 delete state; 1415 state = NULL; 1416 1417 return err; 1418 } 1419 1420 seekTo_l(state->mPositionUs); 1421 1422 mFlags = state->mFlags & (LOOPING | AT_EOS); 1423 1424 if (state->mLastVideoFrame && mISurface != NULL) { 1425 mVideoRenderer = 1426 new AwesomeLocalRenderer( 1427 true, // previewOnly 1428 "", 1429 (OMX_COLOR_FORMATTYPE)state->mColorFormat, 1430 mISurface, 1431 state->mVideoWidth, 1432 state->mVideoHeight, 1433 state->mDecodedWidth, 1434 state->mDecodedHeight); 1435 1436 mVideoRendererIsPreview = true; 1437 1438 ((AwesomeLocalRenderer *)mVideoRenderer.get())->render( 1439 state->mLastVideoFrame, state->mLastVideoFrameSize); 1440 } 1441 1442 if (state->mFlags & PLAYING) { 1443 play_l(); 1444 } 1445 1446 mSuspensionState = state; 1447 state = NULL; 1448 1449 return OK; 1450} 1451 1452uint32_t AwesomePlayer::flags() const { 1453 return mExtractorFlags; 1454} 1455 1456} // namespace android 1457 1458