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