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