AwesomePlayer.cpp revision 88c030e0e0152791ff74f90249f55fce01371198
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 "include/AwesomePlayer.h" 22#include "include/Prefetcher.h" 23#include "include/SoftwareRenderer.h" 24 25#include <binder/IPCThreadState.h> 26#include <media/stagefright/AudioPlayer.h> 27#include <media/stagefright/DataSource.h> 28#include <media/stagefright/FileSource.h> 29#include <media/stagefright/MediaBuffer.h> 30#include <media/stagefright/MediaDefs.h> 31#include <media/stagefright/MediaExtractor.h> 32#include <media/stagefright/MediaDebug.h> 33#include <media/stagefright/MediaSource.h> 34#include <media/stagefright/MetaData.h> 35#include <media/stagefright/OMXCodec.h> 36 37namespace android { 38 39struct AwesomeEvent : public TimedEventQueue::Event { 40 AwesomeEvent(AwesomePlayer *player, int32_t code) 41 : mPlayer(player), 42 mCode(code) { 43 } 44 45protected: 46 virtual ~AwesomeEvent() {} 47 48 virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) { 49 mPlayer->onEvent(mCode); 50 } 51 52private: 53 AwesomePlayer *mPlayer; 54 int32_t mCode; 55 56 AwesomeEvent(const AwesomeEvent &); 57 AwesomeEvent &operator=(const AwesomeEvent &); 58}; 59 60struct AwesomeRemoteRenderer : public AwesomeRenderer { 61 AwesomeRemoteRenderer(const sp<IOMXRenderer> &target) 62 : mTarget(target) { 63 } 64 65 virtual void render(MediaBuffer *buffer) { 66 void *id; 67 if (buffer->meta_data()->findPointer(kKeyBufferID, &id)) { 68 mTarget->render((IOMX::buffer_id)id); 69 } 70 } 71 72private: 73 sp<IOMXRenderer> mTarget; 74 75 AwesomeRemoteRenderer(const AwesomeRemoteRenderer &); 76 AwesomeRemoteRenderer &operator=(const AwesomeRemoteRenderer &); 77}; 78 79struct AwesomeLocalRenderer : public AwesomeRenderer { 80 AwesomeLocalRenderer( 81 OMX_COLOR_FORMATTYPE colorFormat, 82 const sp<ISurface> &surface, 83 size_t displayWidth, size_t displayHeight, 84 size_t decodedWidth, size_t decodedHeight) 85 : mTarget(new SoftwareRenderer( 86 colorFormat, surface, displayWidth, displayHeight, 87 decodedWidth, decodedHeight)) { 88 } 89 90 virtual void render(MediaBuffer *buffer) { 91 mTarget->render( 92 (const uint8_t *)buffer->data() + buffer->range_offset(), 93 buffer->range_length(), NULL); 94 } 95 96protected: 97 virtual ~AwesomeLocalRenderer() { 98 delete mTarget; 99 mTarget = NULL; 100 } 101 102private: 103 SoftwareRenderer *mTarget; 104 105 AwesomeLocalRenderer(const AwesomeLocalRenderer &); 106 AwesomeLocalRenderer &operator=(const AwesomeLocalRenderer &);; 107}; 108 109AwesomePlayer::AwesomePlayer() 110 : mTimeSource(NULL), 111 mAudioPlayer(NULL), 112 mLastVideoBuffer(NULL), 113 mVideoBuffer(NULL) { 114 CHECK_EQ(mClient.connect(), OK); 115 116 DataSource::RegisterDefaultSniffers(); 117 118 mVideoEvent = new AwesomeEvent(this, 0); 119 mVideoEventPending = false; 120 mStreamDoneEvent = new AwesomeEvent(this, 1); 121 mStreamDoneEventPending = false; 122 mBufferingEvent = new AwesomeEvent(this, 2); 123 mBufferingEventPending = false; 124 125 mQueue.start(); 126 127 reset(); 128} 129 130AwesomePlayer::~AwesomePlayer() { 131 mQueue.stop(); 132 133 reset(); 134 135 mClient.disconnect(); 136} 137 138void AwesomePlayer::cancelPlayerEvents(bool keepBufferingGoing) { 139 mQueue.cancelEvent(mVideoEvent->eventID()); 140 mVideoEventPending = false; 141 mQueue.cancelEvent(mStreamDoneEvent->eventID()); 142 mStreamDoneEventPending = false; 143 144 if (!keepBufferingGoing) { 145 mQueue.cancelEvent(mBufferingEvent->eventID()); 146 mBufferingEventPending = false; 147 } 148} 149 150void AwesomePlayer::setListener(const wp<MediaPlayerBase> &listener) { 151 Mutex::Autolock autoLock(mLock); 152 mListener = listener; 153} 154 155status_t AwesomePlayer::setDataSource( 156 const char *uri, const KeyedVector<String8, String8> *headers) { 157 Mutex::Autolock autoLock(mLock); 158 159 reset_l(); 160 161 sp<DataSource> dataSource = DataSource::CreateFromURI(uri, headers); 162 163 if (dataSource == NULL) { 164 return UNKNOWN_ERROR; 165 } 166 167 sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource); 168 169 if (extractor == NULL) { 170 return UNKNOWN_ERROR; 171 } 172 173 if (dataSource->flags() & DataSource::kWantsPrefetching) { 174 mPrefetcher = new Prefetcher; 175 } 176 177 return setDataSource_l(extractor); 178} 179 180status_t AwesomePlayer::setDataSource( 181 int fd, int64_t offset, int64_t length) { 182 Mutex::Autolock autoLock(mLock); 183 184 reset_l(); 185 186 sp<DataSource> source = new FileSource(fd, offset, length); 187 188 status_t err = source->initCheck(); 189 190 if (err != OK) { 191 return err; 192 } 193 194 sp<MediaExtractor> extractor = MediaExtractor::Create(source); 195 196 if (extractor == NULL) { 197 return UNKNOWN_ERROR; 198 } 199 200 return setDataSource_l(extractor); 201} 202 203status_t AwesomePlayer::setDataSource_l(const sp<MediaExtractor> &extractor) { 204 bool haveAudio = false; 205 bool haveVideo = false; 206 for (size_t i = 0; i < extractor->countTracks(); ++i) { 207 sp<MetaData> meta = extractor->getTrackMetaData(i); 208 209 const char *mime; 210 CHECK(meta->findCString(kKeyMIMEType, &mime)); 211 212 if (!haveVideo && !strncasecmp(mime, "video/", 6)) { 213 if (setVideoSource(extractor->getTrack(i)) == OK) { 214 haveVideo = true; 215 } 216 } else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) { 217 if (setAudioSource(extractor->getTrack(i)) == OK) { 218 haveAudio = true; 219 } 220 } 221 222 if (haveAudio && haveVideo) { 223 break; 224 } 225 } 226 227 return !haveAudio && !haveVideo ? UNKNOWN_ERROR : OK; 228} 229 230void AwesomePlayer::reset() { 231 Mutex::Autolock autoLock(mLock); 232 reset_l(); 233} 234 235void AwesomePlayer::reset_l() { 236 cancelPlayerEvents(); 237 238 mVideoRenderer.clear(); 239 240 if (mLastVideoBuffer) { 241 mLastVideoBuffer->release(); 242 mLastVideoBuffer = NULL; 243 } 244 245 if (mVideoBuffer) { 246 mVideoBuffer->release(); 247 mVideoBuffer = NULL; 248 } 249 250 if (mVideoSource != NULL) { 251 mVideoSource->stop(); 252 253 // The following hack is necessary to ensure that the OMX 254 // component is completely released by the time we may try 255 // to instantiate it again. 256 wp<MediaSource> tmp = mVideoSource; 257 mVideoSource.clear(); 258 while (tmp.promote() != NULL) { 259 usleep(1000); 260 } 261 IPCThreadState::self()->flushCommands(); 262 } 263 264 mAudioSource.clear(); 265 266 if (mTimeSource != mAudioPlayer) { 267 delete mTimeSource; 268 } 269 mTimeSource = NULL; 270 271 delete mAudioPlayer; 272 mAudioPlayer = NULL; 273 274 mDurationUs = -1; 275 mFlags = 0; 276 mVideoWidth = mVideoHeight = -1; 277 mTimeSourceDeltaUs = 0; 278 mVideoTimeUs = 0; 279 280 mSeeking = false; 281 mSeekTimeUs = 0; 282 283 mPrefetcher.clear(); 284} 285 286// static 287void AwesomePlayer::AudioNotify(void *_me, int what) { 288 AwesomePlayer *me = (AwesomePlayer *)_me; 289 290 Mutex::Autolock autoLock(me->mLock); 291 292 switch (what) { 293 case AudioPlayer::REACHED_EOS: 294 me->postStreamDoneEvent_l(); 295 break; 296 297 case AudioPlayer::SEEK_COMPLETE: 298 { 299 me->notifyListener_l(MEDIA_SEEK_COMPLETE); 300 break; 301 } 302 303 default: 304 CHECK(!"should not be here."); 305 break; 306 } 307} 308 309void AwesomePlayer::notifyListener_l(int msg, int ext1) { 310 if (mListener != NULL) { 311 sp<MediaPlayerBase> listener = mListener.promote(); 312 313 if (listener != NULL) { 314 listener->sendEvent(msg, ext1); 315 } 316 } 317} 318 319void AwesomePlayer::onBufferingUpdate() { 320 Mutex::Autolock autoLock(mLock); 321 mBufferingEventPending = false; 322 323 if (mDurationUs >= 0) { 324 int64_t cachedDurationUs = mPrefetcher->getCachedDurationUs(); 325 int64_t positionUs = 0; 326 if (mVideoRenderer != NULL) { 327 positionUs = mVideoTimeUs; 328 } else if (mAudioPlayer != NULL) { 329 positionUs = mAudioPlayer->getMediaTimeUs(); 330 } 331 332 cachedDurationUs += positionUs; 333 334 double percentage = (double)cachedDurationUs / mDurationUs; 335 notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage * 100.0); 336 337 postBufferingEvent_l(); 338 } 339} 340 341void AwesomePlayer::onStreamDone() { 342 // Posted whenever any stream finishes playing. 343 344 Mutex::Autolock autoLock(mLock); 345 mStreamDoneEventPending = false; 346 347 if (mFlags & LOOPING) { 348 seekTo_l(0); 349 350 if (mVideoRenderer != NULL) { 351 postVideoEvent_l(); 352 } 353 } else { 354 notifyListener_l(MEDIA_PLAYBACK_COMPLETE); 355 356 pause_l(); 357 } 358} 359 360status_t AwesomePlayer::play() { 361 Mutex::Autolock autoLock(mLock); 362 363 if (mFlags & PLAYING) { 364 return OK; 365 } 366 367 mFlags |= PLAYING; 368 mFlags |= FIRST_FRAME; 369 370 bool deferredAudioSeek = false; 371 372 if (mAudioSource != NULL) { 373 if (mAudioPlayer == NULL) { 374 if (mAudioSink != NULL) { 375 mAudioPlayer = new AudioPlayer(mAudioSink); 376 377 mAudioPlayer->setListenerCallback( 378 &AwesomePlayer::AudioNotify, this); 379 380 mAudioPlayer->setSource(mAudioSource); 381 status_t err = mAudioPlayer->start(); 382 383 if (err != OK) { 384 delete mAudioPlayer; 385 mAudioPlayer = NULL; 386 387 mFlags &= ~(PLAYING | FIRST_FRAME); 388 389 return err; 390 } 391 392 delete mTimeSource; 393 mTimeSource = mAudioPlayer; 394 395 deferredAudioSeek = true; 396 } 397 } else { 398 mAudioPlayer->resume(); 399 } 400 } 401 402 if (mTimeSource == NULL && mAudioPlayer == NULL) { 403 mTimeSource = new SystemTimeSource; 404 } 405 406 if (mVideoSource != NULL) { 407 if (mVideoRenderer == NULL) { 408 initRenderer_l(); 409 } 410 411 if (mVideoRenderer != NULL) { 412 // Kick off video playback 413 postVideoEvent_l(); 414 } 415 } 416 417 if (deferredAudioSeek) { 418 // If there was a seek request while we were paused 419 // and we're just starting up again, honor the request now. 420 seekAudioIfNecessary_l(); 421 } 422 423 postBufferingEvent_l(); 424 425 return OK; 426} 427 428void AwesomePlayer::initRenderer_l() { 429 if (mISurface != NULL) { 430 sp<MetaData> meta = mVideoSource->getFormat(); 431 432 int32_t format; 433 const char *component; 434 int32_t decodedWidth, decodedHeight; 435 CHECK(meta->findInt32(kKeyColorFormat, &format)); 436 CHECK(meta->findCString(kKeyDecoderComponent, &component)); 437 CHECK(meta->findInt32(kKeyWidth, &decodedWidth)); 438 CHECK(meta->findInt32(kKeyHeight, &decodedHeight)); 439 440 mVideoRenderer.clear(); 441 442 // Must ensure that mVideoRenderer's destructor is actually executed 443 // before creating a new one. 444 IPCThreadState::self()->flushCommands(); 445 446 if (!strncmp("OMX.", component, 4)) { 447 // Our OMX codecs allocate buffers on the media_server side 448 // therefore they require a remote IOMXRenderer that knows how 449 // to display them. 450 mVideoRenderer = new AwesomeRemoteRenderer( 451 mClient.interface()->createRenderer( 452 mISurface, component, 453 (OMX_COLOR_FORMATTYPE)format, 454 decodedWidth, decodedHeight, 455 mVideoWidth, mVideoHeight)); 456 } else { 457 // Other decoders are instantiated locally and as a consequence 458 // allocate their buffers in local address space. 459 mVideoRenderer = new AwesomeLocalRenderer( 460 (OMX_COLOR_FORMATTYPE)format, 461 mISurface, 462 mVideoWidth, mVideoHeight, 463 decodedWidth, decodedHeight); 464 } 465 } 466} 467 468status_t AwesomePlayer::pause() { 469 Mutex::Autolock autoLock(mLock); 470 return pause_l(); 471} 472 473status_t AwesomePlayer::pause_l() { 474 if (!(mFlags & PLAYING)) { 475 return OK; 476 } 477 478 cancelPlayerEvents(true /* keepBufferingGoing */); 479 480 if (mAudioPlayer != NULL) { 481 mAudioPlayer->pause(); 482 } 483 484 mFlags &= ~PLAYING; 485 486 return OK; 487} 488 489bool AwesomePlayer::isPlaying() const { 490 Mutex::Autolock autoLock(mLock); 491 492 return mFlags & PLAYING; 493} 494 495void AwesomePlayer::setISurface(const sp<ISurface> &isurface) { 496 Mutex::Autolock autoLock(mLock); 497 498 mISurface = isurface; 499} 500 501void AwesomePlayer::setAudioSink( 502 const sp<MediaPlayerBase::AudioSink> &audioSink) { 503 Mutex::Autolock autoLock(mLock); 504 505 mAudioSink = audioSink; 506} 507 508status_t AwesomePlayer::setLooping(bool shouldLoop) { 509 Mutex::Autolock autoLock(mLock); 510 511 mFlags = mFlags & ~LOOPING; 512 513 if (shouldLoop) { 514 mFlags |= LOOPING; 515 } 516 517 return OK; 518} 519 520status_t AwesomePlayer::getDuration(int64_t *durationUs) { 521 Mutex::Autolock autoLock(mLock); 522 523 if (mDurationUs < 0) { 524 return UNKNOWN_ERROR; 525 } 526 527 *durationUs = mDurationUs; 528 529 return OK; 530} 531 532status_t AwesomePlayer::getPosition(int64_t *positionUs) { 533 Mutex::Autolock autoLock(mLock); 534 535 if (mVideoRenderer != NULL) { 536 *positionUs = mVideoTimeUs; 537 } else if (mAudioPlayer != NULL) { 538 *positionUs = mAudioPlayer->getMediaTimeUs(); 539 } else { 540 *positionUs = 0; 541 } 542 543 return OK; 544} 545 546status_t AwesomePlayer::seekTo(int64_t timeUs) { 547 Mutex::Autolock autoLock(mLock); 548 return seekTo_l(timeUs); 549} 550 551status_t AwesomePlayer::seekTo_l(int64_t timeUs) { 552 mSeeking = true; 553 mSeekTimeUs = timeUs; 554 555 seekAudioIfNecessary_l(); 556 557 return OK; 558} 559 560void AwesomePlayer::seekAudioIfNecessary_l() { 561 if (mSeeking && mVideoRenderer == NULL && mAudioPlayer != NULL) { 562 mAudioPlayer->seekTo(mSeekTimeUs); 563 564 mSeeking = false; 565 } 566} 567 568status_t AwesomePlayer::getVideoDimensions( 569 int32_t *width, int32_t *height) const { 570 Mutex::Autolock autoLock(mLock); 571 572 if (mVideoWidth < 0 || mVideoHeight < 0) { 573 return UNKNOWN_ERROR; 574 } 575 576 *width = mVideoWidth; 577 *height = mVideoHeight; 578 579 return OK; 580} 581 582status_t AwesomePlayer::setAudioSource(sp<MediaSource> source) { 583 if (source == NULL) { 584 return UNKNOWN_ERROR; 585 } 586 587 if (mPrefetcher != NULL) { 588 source = mPrefetcher->addSource(source); 589 } 590 591 sp<MetaData> meta = source->getFormat(); 592 593 const char *mime; 594 CHECK(meta->findCString(kKeyMIMEType, &mime)); 595 596 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) { 597 mAudioSource = source; 598 } else { 599 mAudioSource = OMXCodec::Create( 600 mClient.interface(), source->getFormat(), 601 false, // createEncoder 602 source); 603 } 604 605 if (mAudioSource != NULL) { 606 int64_t durationUs; 607 if (source->getFormat()->findInt64(kKeyDuration, &durationUs)) { 608 if (mDurationUs < 0 || durationUs > mDurationUs) { 609 mDurationUs = durationUs; 610 } 611 } 612 } 613 614 return mAudioSource != NULL ? OK : UNKNOWN_ERROR; 615} 616 617status_t AwesomePlayer::setVideoSource(sp<MediaSource> source) { 618 if (source == NULL) { 619 return UNKNOWN_ERROR; 620 } 621 622 if (mPrefetcher != NULL) { 623 source = mPrefetcher->addSource(source); 624 } 625 626 mVideoSource = OMXCodec::Create( 627 mClient.interface(), source->getFormat(), 628 false, // createEncoder 629 source); 630 631 if (mVideoSource != NULL) { 632 int64_t durationUs; 633 if (source->getFormat()->findInt64(kKeyDuration, &durationUs)) { 634 if (mDurationUs < 0 || durationUs > mDurationUs) { 635 mDurationUs = durationUs; 636 } 637 } 638 639 CHECK(source->getFormat()->findInt32(kKeyWidth, &mVideoWidth)); 640 CHECK(source->getFormat()->findInt32(kKeyHeight, &mVideoHeight)); 641 642 mVideoSource->start(); 643 } 644 645 return mVideoSource != NULL ? OK : UNKNOWN_ERROR; 646} 647 648void AwesomePlayer::onEvent(int32_t code) { 649 if (code == 1) { 650 onStreamDone(); 651 return; 652 } else if (code == 2) { 653 onBufferingUpdate(); 654 return; 655 } 656 657 Mutex::Autolock autoLock(mLock); 658 659 mVideoEventPending = false; 660 661 if (mSeeking) { 662 if (mLastVideoBuffer) { 663 mLastVideoBuffer->release(); 664 mLastVideoBuffer = NULL; 665 } 666 667 if (mVideoBuffer) { 668 mVideoBuffer->release(); 669 mVideoBuffer = NULL; 670 } 671 } 672 673 if (!mVideoBuffer) { 674 MediaSource::ReadOptions options; 675 if (mSeeking) { 676 LOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs, mSeekTimeUs / 1E6); 677 678 options.setSeekTo(mSeekTimeUs); 679 } 680 for (;;) { 681 status_t err = mVideoSource->read(&mVideoBuffer, &options); 682 options.clearSeekTo(); 683 684 if (err != OK) { 685 CHECK_EQ(mVideoBuffer, NULL); 686 687 if (err == INFO_FORMAT_CHANGED) { 688 LOGV("VideoSource signalled format change."); 689 690 initRenderer_l(); 691 continue; 692 } 693 694 postStreamDoneEvent_l(); 695 return; 696 } 697 698 if (mVideoBuffer->range_length() == 0) { 699 // Some decoders, notably the PV AVC software decoder 700 // return spurious empty buffers that we just want to ignore. 701 702 mVideoBuffer->release(); 703 mVideoBuffer = NULL; 704 continue; 705 } 706 707 break; 708 } 709 } 710 711 int64_t timeUs; 712 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs)); 713 714 mVideoTimeUs = timeUs; 715 716 if (mSeeking) { 717 if (mAudioPlayer != NULL) { 718 LOGV("seeking audio to %lld us (%.2f secs).", timeUs, timeUs / 1E6); 719 720 mAudioPlayer->seekTo(timeUs); 721 } else { 722 // If we're playing video only, report seek complete now, 723 // otherwise audio player will notify us later. 724 notifyListener_l(MEDIA_SEEK_COMPLETE); 725 } 726 727 mFlags |= FIRST_FRAME; 728 mSeeking = false; 729 } 730 731 if (mFlags & FIRST_FRAME) { 732 mFlags &= ~FIRST_FRAME; 733 734 mTimeSourceDeltaUs = mTimeSource->getRealTimeUs() - timeUs; 735 } 736 737 int64_t realTimeUs, mediaTimeUs; 738 if (mAudioPlayer != NULL 739 && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) { 740 mTimeSourceDeltaUs = realTimeUs - mediaTimeUs; 741 } 742 743 int64_t nowUs = mTimeSource->getRealTimeUs() - mTimeSourceDeltaUs; 744 745 int64_t latenessUs = nowUs - timeUs; 746 747 if (latenessUs > 40000) { 748 // We're more than 40ms late. 749 LOGI("we're late by %lld us (%.2f secs)", latenessUs, latenessUs / 1E6); 750 751 mVideoBuffer->release(); 752 mVideoBuffer = NULL; 753 754 postVideoEvent_l(); 755 return; 756 } 757 758 if (latenessUs < -10000) { 759 // We're more than 10ms early. 760 761 postVideoEvent_l(10000); 762 return; 763 } 764 765 mVideoRenderer->render(mVideoBuffer); 766 767 if (mLastVideoBuffer) { 768 mLastVideoBuffer->release(); 769 mLastVideoBuffer = NULL; 770 } 771 mLastVideoBuffer = mVideoBuffer; 772 mVideoBuffer = NULL; 773 774 postVideoEvent_l(); 775} 776 777void AwesomePlayer::postVideoEvent_l(int64_t delayUs) { 778 if (mVideoEventPending) { 779 return; 780 } 781 782 mVideoEventPending = true; 783 mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs); 784} 785 786void AwesomePlayer::postStreamDoneEvent_l() { 787 if (mStreamDoneEventPending) { 788 return; 789 } 790 mStreamDoneEventPending = true; 791 mQueue.postEvent(mStreamDoneEvent); 792} 793 794void AwesomePlayer::postBufferingEvent_l() { 795 if (mPrefetcher == NULL) { 796 return; 797 } 798 799 if (mBufferingEventPending) { 800 return; 801 } 802 mBufferingEventPending = true; 803 mQueue.postEventWithDelay(mBufferingEvent, 1000000ll); 804} 805 806} // namespace android 807 808