AwesomePlayer.cpp revision 7b3396acc702451be9bafb19d7fe26d55d43a316
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/DataSource.h> 30#include <media/stagefright/FileSource.h> 31#include <media/stagefright/MediaBuffer.h> 32#include <media/stagefright/MediaDefs.h> 33#include <media/stagefright/MediaExtractor.h> 34#include <media/stagefright/MediaDebug.h> 35#include <media/stagefright/MediaSource.h> 36#include <media/stagefright/MetaData.h> 37#include <media/stagefright/OMXCodec.h> 38 39#include <surfaceflinger/ISurface.h> 40 41namespace android { 42 43struct AwesomeEvent : public TimedEventQueue::Event { 44 AwesomeEvent( 45 AwesomePlayer *player, 46 void (AwesomePlayer::*method)()) 47 : mPlayer(player), 48 mMethod(method) { 49 } 50 51protected: 52 virtual ~AwesomeEvent() {} 53 54 virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) { 55 (mPlayer->*mMethod)(); 56 } 57 58private: 59 AwesomePlayer *mPlayer; 60 void (AwesomePlayer::*mMethod)(); 61 62 AwesomeEvent(const AwesomeEvent &); 63 AwesomeEvent &operator=(const AwesomeEvent &); 64}; 65 66struct AwesomeRemoteRenderer : public AwesomeRenderer { 67 AwesomeRemoteRenderer(const sp<IOMXRenderer> &target) 68 : mTarget(target) { 69 } 70 71 virtual void render(MediaBuffer *buffer) { 72 void *id; 73 if (buffer->meta_data()->findPointer(kKeyBufferID, &id)) { 74 mTarget->render((IOMX::buffer_id)id); 75 } 76 } 77 78private: 79 sp<IOMXRenderer> mTarget; 80 81 AwesomeRemoteRenderer(const AwesomeRemoteRenderer &); 82 AwesomeRemoteRenderer &operator=(const AwesomeRemoteRenderer &); 83}; 84 85struct AwesomeLocalRenderer : public AwesomeRenderer { 86 AwesomeLocalRenderer( 87 const char *componentName, 88 OMX_COLOR_FORMATTYPE colorFormat, 89 const sp<ISurface> &surface, 90 size_t displayWidth, size_t displayHeight, 91 size_t decodedWidth, size_t decodedHeight) 92 : mTarget(NULL), 93 mLibHandle(NULL) { 94 init(componentName, 95 colorFormat, surface, displayWidth, 96 displayHeight, decodedWidth, decodedHeight); 97 } 98 99 virtual void render(MediaBuffer *buffer) { 100 mTarget->render( 101 (const uint8_t *)buffer->data() + buffer->range_offset(), 102 buffer->range_length(), NULL); 103 } 104 105protected: 106 virtual ~AwesomeLocalRenderer() { 107 delete mTarget; 108 mTarget = NULL; 109 110 if (mLibHandle) { 111 dlclose(mLibHandle); 112 mLibHandle = NULL; 113 } 114 } 115 116private: 117 VideoRenderer *mTarget; 118 void *mLibHandle; 119 120 void init( 121 const char *componentName, 122 OMX_COLOR_FORMATTYPE colorFormat, 123 const sp<ISurface> &surface, 124 size_t displayWidth, size_t displayHeight, 125 size_t decodedWidth, size_t decodedHeight); 126 127 AwesomeLocalRenderer(const AwesomeLocalRenderer &); 128 AwesomeLocalRenderer &operator=(const AwesomeLocalRenderer &);; 129}; 130 131void AwesomeLocalRenderer::init( 132 const char *componentName, 133 OMX_COLOR_FORMATTYPE colorFormat, 134 const sp<ISurface> &surface, 135 size_t displayWidth, size_t displayHeight, 136 size_t decodedWidth, size_t decodedHeight) { 137 mLibHandle = dlopen("libstagefrighthw.so", RTLD_NOW); 138 139 if (mLibHandle) { 140 typedef VideoRenderer *(*CreateRendererFunc)( 141 const sp<ISurface> &surface, 142 const char *componentName, 143 OMX_COLOR_FORMATTYPE colorFormat, 144 size_t displayWidth, size_t displayHeight, 145 size_t decodedWidth, size_t decodedHeight); 146 147 CreateRendererFunc func = 148 (CreateRendererFunc)dlsym( 149 mLibHandle, 150 "_Z14createRendererRKN7android2spINS_8ISurfaceEEEPKc20" 151 "OMX_COLOR_FORMATTYPEjjjj"); 152 153 if (func) { 154 mTarget = 155 (*func)(surface, componentName, colorFormat, 156 displayWidth, displayHeight, decodedWidth, decodedHeight); 157 } 158 } 159 160 if (mTarget == NULL) { 161 mTarget = new SoftwareRenderer( 162 colorFormat, surface, displayWidth, displayHeight, 163 decodedWidth, decodedHeight); 164 } 165} 166 167AwesomePlayer::AwesomePlayer() 168 : mTimeSource(NULL), 169 mAudioPlayer(NULL), 170 mFlags(0), 171 mLastVideoBuffer(NULL), 172 mVideoBuffer(NULL), 173 mSuspensionState(NULL) { 174 CHECK_EQ(mClient.connect(), OK); 175 176 DataSource::RegisterDefaultSniffers(); 177 178 mVideoEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoEvent); 179 mVideoEventPending = false; 180 mStreamDoneEvent = new AwesomeEvent(this, &AwesomePlayer::onStreamDone); 181 mStreamDoneEventPending = false; 182 mBufferingEvent = new AwesomeEvent(this, &AwesomePlayer::onBufferingUpdate); 183 mBufferingEventPending = false; 184 185 mCheckAudioStatusEvent = new AwesomeEvent( 186 this, &AwesomePlayer::onCheckAudioStatus); 187 188 mAudioStatusEventPending = false; 189 190 mQueue.start(); 191 192 reset(); 193} 194 195AwesomePlayer::~AwesomePlayer() { 196 mQueue.stop(); 197 198 reset(); 199 200 mClient.disconnect(); 201} 202 203void AwesomePlayer::cancelPlayerEvents(bool keepBufferingGoing) { 204 mQueue.cancelEvent(mVideoEvent->eventID()); 205 mVideoEventPending = false; 206 mQueue.cancelEvent(mStreamDoneEvent->eventID()); 207 mStreamDoneEventPending = false; 208 mQueue.cancelEvent(mCheckAudioStatusEvent->eventID()); 209 mAudioStatusEventPending = false; 210 211 if (!keepBufferingGoing) { 212 mQueue.cancelEvent(mBufferingEvent->eventID()); 213 mBufferingEventPending = false; 214 } 215} 216 217void AwesomePlayer::setListener(const wp<MediaPlayerBase> &listener) { 218 Mutex::Autolock autoLock(mLock); 219 mListener = listener; 220} 221 222status_t AwesomePlayer::setDataSource( 223 const char *uri, const KeyedVector<String8, String8> *headers) { 224 Mutex::Autolock autoLock(mLock); 225 return setDataSource_l(uri, headers); 226} 227 228status_t AwesomePlayer::setDataSource_l( 229 const char *uri, const KeyedVector<String8, String8> *headers) { 230 reset_l(); 231 232 mUri = uri; 233 234 if (headers) { 235 mUriHeaders = *headers; 236 } 237 238 // The actual work will be done during preparation in the call to 239 // ::finishSetDataSource_l to avoid blocking the calling thread in 240 // setDataSource for any significant time. 241 242 return OK; 243} 244 245status_t AwesomePlayer::setDataSource( 246 int fd, int64_t offset, int64_t length) { 247 Mutex::Autolock autoLock(mLock); 248 249 reset_l(); 250 251 sp<DataSource> dataSource = new FileSource(fd, offset, length); 252 253 status_t err = dataSource->initCheck(); 254 255 if (err != OK) { 256 return err; 257 } 258 259 mFileSource = dataSource; 260 261 return setDataSource_l(dataSource); 262} 263 264status_t AwesomePlayer::setDataSource_l( 265 const sp<DataSource> &dataSource) { 266 sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource); 267 268 if (extractor == NULL) { 269 return UNKNOWN_ERROR; 270 } 271 272 return setDataSource_l(extractor); 273} 274 275status_t AwesomePlayer::setDataSource_l(const sp<MediaExtractor> &extractor) { 276 bool haveAudio = false; 277 bool haveVideo = false; 278 for (size_t i = 0; i < extractor->countTracks(); ++i) { 279 sp<MetaData> meta = extractor->getTrackMetaData(i); 280 281 const char *mime; 282 CHECK(meta->findCString(kKeyMIMEType, &mime)); 283 284 if (!haveVideo && !strncasecmp(mime, "video/", 6)) { 285 if (setVideoSource(extractor->getTrack(i)) == OK) { 286 haveVideo = true; 287 } 288 } else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) { 289 if (setAudioSource(extractor->getTrack(i)) == OK) { 290 haveAudio = true; 291 } 292 } 293 294 if (haveAudio && haveVideo) { 295 break; 296 } 297 } 298 299 return !haveAudio && !haveVideo ? UNKNOWN_ERROR : OK; 300} 301 302void AwesomePlayer::reset() { 303 Mutex::Autolock autoLock(mLock); 304 reset_l(); 305} 306 307void AwesomePlayer::reset_l() { 308 while (mFlags & PREPARING) { 309 mPreparedCondition.wait(mLock); 310 } 311 312 cancelPlayerEvents(); 313 314 if (mPrefetcher != NULL) { 315 CHECK_EQ(mPrefetcher->getStrongCount(), 1); 316 } 317 mPrefetcher.clear(); 318 319 // Shutdown audio first, so that the respone to the reset request 320 // appears to happen instantaneously as far as the user is concerned 321 // If we did this later, audio would continue playing while we 322 // shutdown the video-related resources and the player appear to 323 // not be as responsive to a reset request. 324 mAudioSource.clear(); 325 326 if (mTimeSource != mAudioPlayer) { 327 delete mTimeSource; 328 } 329 mTimeSource = NULL; 330 331 delete mAudioPlayer; 332 mAudioPlayer = NULL; 333 334 mVideoRenderer.clear(); 335 336 if (mLastVideoBuffer) { 337 mLastVideoBuffer->release(); 338 mLastVideoBuffer = NULL; 339 } 340 341 if (mVideoBuffer) { 342 mVideoBuffer->release(); 343 mVideoBuffer = NULL; 344 } 345 346 if (mVideoSource != NULL) { 347 mVideoSource->stop(); 348 349 // The following hack is necessary to ensure that the OMX 350 // component is completely released by the time we may try 351 // to instantiate it again. 352 wp<MediaSource> tmp = mVideoSource; 353 mVideoSource.clear(); 354 while (tmp.promote() != NULL) { 355 usleep(1000); 356 } 357 IPCThreadState::self()->flushCommands(); 358 } 359 360 mDurationUs = -1; 361 mFlags = 0; 362 mVideoWidth = mVideoHeight = -1; 363 mTimeSourceDeltaUs = 0; 364 mVideoTimeUs = 0; 365 366 mSeeking = false; 367 mSeekTimeUs = 0; 368 369 mUri.setTo(""); 370 mUriHeaders.clear(); 371 372 mFileSource.clear(); 373 374 delete mSuspensionState; 375 mSuspensionState = NULL; 376} 377 378void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) { 379 if (mListener != NULL) { 380 sp<MediaPlayerBase> listener = mListener.promote(); 381 382 if (listener != NULL) { 383 listener->sendEvent(msg, ext1, ext2); 384 } 385 } 386} 387 388void AwesomePlayer::onBufferingUpdate() { 389 Mutex::Autolock autoLock(mLock); 390 mBufferingEventPending = false; 391 392 if (mDurationUs >= 0) { 393 int64_t cachedDurationUs = mPrefetcher->getCachedDurationUs(); 394 int64_t positionUs = 0; 395 if (mVideoSource != NULL) { 396 positionUs = mVideoTimeUs; 397 } else if (mAudioPlayer != NULL) { 398 positionUs = mAudioPlayer->getMediaTimeUs(); 399 } 400 401 cachedDurationUs += positionUs; 402 403 double percentage = (double)cachedDurationUs / mDurationUs; 404 notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage * 100.0); 405 406 postBufferingEvent_l(); 407 } 408} 409 410void AwesomePlayer::onStreamDone() { 411 // Posted whenever any stream finishes playing. 412 413 Mutex::Autolock autoLock(mLock); 414 mStreamDoneEventPending = false; 415 416 if (mFlags & LOOPING) { 417 seekTo_l(0); 418 419 if (mVideoSource != NULL) { 420 postVideoEvent_l(); 421 } 422 } else { 423 notifyListener_l(MEDIA_PLAYBACK_COMPLETE); 424 425 pause_l(); 426 } 427} 428 429status_t AwesomePlayer::play() { 430 Mutex::Autolock autoLock(mLock); 431 return play_l(); 432} 433 434status_t AwesomePlayer::play_l() { 435 if (mFlags & PLAYING) { 436 return OK; 437 } 438 439 if (!(mFlags & PREPARED)) { 440 status_t err = prepare_l(); 441 442 if (err != OK) { 443 return err; 444 } 445 } 446 447 mFlags |= PLAYING; 448 mFlags |= FIRST_FRAME; 449 450 bool deferredAudioSeek = false; 451 452 if (mAudioSource != NULL) { 453 if (mAudioPlayer == NULL) { 454 if (mAudioSink != NULL) { 455 mAudioPlayer = new AudioPlayer(mAudioSink); 456 mAudioPlayer->setSource(mAudioSource); 457 status_t err = mAudioPlayer->start(); 458 459 if (err != OK) { 460 delete mAudioPlayer; 461 mAudioPlayer = NULL; 462 463 mFlags &= ~(PLAYING | FIRST_FRAME); 464 465 return err; 466 } 467 468 delete mTimeSource; 469 mTimeSource = mAudioPlayer; 470 471 deferredAudioSeek = true; 472 473 mWatchForAudioSeekComplete = false; 474 mWatchForAudioEOS = true; 475 } 476 } else { 477 mAudioPlayer->resume(); 478 } 479 480 postCheckAudioStatusEvent_l(); 481 } 482 483 if (mTimeSource == NULL && mAudioPlayer == NULL) { 484 mTimeSource = new SystemTimeSource; 485 } 486 487 if (mVideoSource != NULL) { 488 // Kick off video playback 489 postVideoEvent_l(); 490 } 491 492 if (deferredAudioSeek) { 493 // If there was a seek request while we were paused 494 // and we're just starting up again, honor the request now. 495 seekAudioIfNecessary_l(); 496 } 497 498 postBufferingEvent_l(); 499 500 return OK; 501} 502 503void AwesomePlayer::initRenderer_l() { 504 if (mISurface != NULL) { 505 sp<MetaData> meta = mVideoSource->getFormat(); 506 507 int32_t format; 508 const char *component; 509 int32_t decodedWidth, decodedHeight; 510 CHECK(meta->findInt32(kKeyColorFormat, &format)); 511 CHECK(meta->findCString(kKeyDecoderComponent, &component)); 512 CHECK(meta->findInt32(kKeyWidth, &decodedWidth)); 513 CHECK(meta->findInt32(kKeyHeight, &decodedHeight)); 514 515 mVideoRenderer.clear(); 516 517 // Must ensure that mVideoRenderer's destructor is actually executed 518 // before creating a new one. 519 IPCThreadState::self()->flushCommands(); 520 521 if (!strncmp("OMX.", component, 4)) { 522 // Our OMX codecs allocate buffers on the media_server side 523 // therefore they require a remote IOMXRenderer that knows how 524 // to display them. 525 mVideoRenderer = new AwesomeRemoteRenderer( 526 mClient.interface()->createRenderer( 527 mISurface, component, 528 (OMX_COLOR_FORMATTYPE)format, 529 decodedWidth, decodedHeight, 530 mVideoWidth, mVideoHeight)); 531 } else { 532 // Other decoders are instantiated locally and as a consequence 533 // allocate their buffers in local address space. 534 mVideoRenderer = new AwesomeLocalRenderer( 535 component, 536 (OMX_COLOR_FORMATTYPE)format, 537 mISurface, 538 mVideoWidth, mVideoHeight, 539 decodedWidth, decodedHeight); 540 } 541 } 542} 543 544status_t AwesomePlayer::pause() { 545 Mutex::Autolock autoLock(mLock); 546 return pause_l(); 547} 548 549status_t AwesomePlayer::pause_l() { 550 if (!(mFlags & PLAYING)) { 551 return OK; 552 } 553 554 cancelPlayerEvents(true /* keepBufferingGoing */); 555 556 if (mAudioPlayer != NULL) { 557 mAudioPlayer->pause(); 558 } 559 560 mFlags &= ~PLAYING; 561 562 return OK; 563} 564 565bool AwesomePlayer::isPlaying() const { 566 Mutex::Autolock autoLock(mLock); 567 568 return mFlags & PLAYING; 569} 570 571void AwesomePlayer::setISurface(const sp<ISurface> &isurface) { 572 Mutex::Autolock autoLock(mLock); 573 574 mISurface = isurface; 575} 576 577void AwesomePlayer::setAudioSink( 578 const sp<MediaPlayerBase::AudioSink> &audioSink) { 579 Mutex::Autolock autoLock(mLock); 580 581 mAudioSink = audioSink; 582} 583 584status_t AwesomePlayer::setLooping(bool shouldLoop) { 585 Mutex::Autolock autoLock(mLock); 586 587 mFlags = mFlags & ~LOOPING; 588 589 if (shouldLoop) { 590 mFlags |= LOOPING; 591 } 592 593 return OK; 594} 595 596status_t AwesomePlayer::getDuration(int64_t *durationUs) { 597 Mutex::Autolock autoLock(mLock); 598 599 if (mDurationUs < 0) { 600 return UNKNOWN_ERROR; 601 } 602 603 *durationUs = mDurationUs; 604 605 return OK; 606} 607 608status_t AwesomePlayer::getPosition(int64_t *positionUs) { 609 Mutex::Autolock autoLock(mLock); 610 return getPosition_l(positionUs); 611} 612 613status_t AwesomePlayer::getPosition_l(int64_t *positionUs) { 614 if (mVideoSource != NULL) { 615 *positionUs = mVideoTimeUs; 616 } else if (mAudioPlayer != NULL) { 617 *positionUs = mAudioPlayer->getMediaTimeUs(); 618 } else { 619 *positionUs = 0; 620 } 621 622 return OK; 623} 624 625status_t AwesomePlayer::seekTo(int64_t timeUs) { 626 Mutex::Autolock autoLock(mLock); 627 return seekTo_l(timeUs); 628} 629 630status_t AwesomePlayer::seekTo_l(int64_t timeUs) { 631 mSeeking = true; 632 mSeekTimeUs = timeUs; 633 634 seekAudioIfNecessary_l(); 635 636 return OK; 637} 638 639void AwesomePlayer::seekAudioIfNecessary_l() { 640 if (mSeeking && mVideoSource == NULL && mAudioPlayer != NULL) { 641 mAudioPlayer->seekTo(mSeekTimeUs); 642 643 mWatchForAudioSeekComplete = true; 644 mWatchForAudioEOS = true; 645 mSeeking = false; 646 } 647} 648 649status_t AwesomePlayer::getVideoDimensions( 650 int32_t *width, int32_t *height) const { 651 Mutex::Autolock autoLock(mLock); 652 653 if (mVideoWidth < 0 || mVideoHeight < 0) { 654 return UNKNOWN_ERROR; 655 } 656 657 *width = mVideoWidth; 658 *height = mVideoHeight; 659 660 return OK; 661} 662 663status_t AwesomePlayer::setAudioSource(sp<MediaSource> source) { 664 if (source == NULL) { 665 return UNKNOWN_ERROR; 666 } 667 668 if (mPrefetcher != NULL) { 669 source = mPrefetcher->addSource(source); 670 } 671 672 sp<MetaData> meta = source->getFormat(); 673 674 const char *mime; 675 CHECK(meta->findCString(kKeyMIMEType, &mime)); 676 677 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) { 678 mAudioSource = source; 679 } else { 680 mAudioSource = OMXCodec::Create( 681 mClient.interface(), source->getFormat(), 682 false, // createEncoder 683 source); 684 } 685 686 if (mAudioSource != NULL) { 687 int64_t durationUs; 688 if (source->getFormat()->findInt64(kKeyDuration, &durationUs)) { 689 if (mDurationUs < 0 || durationUs > mDurationUs) { 690 mDurationUs = durationUs; 691 } 692 } 693 } 694 695 return mAudioSource != NULL ? OK : UNKNOWN_ERROR; 696} 697 698status_t AwesomePlayer::setVideoSource(sp<MediaSource> source) { 699 if (source == NULL) { 700 return UNKNOWN_ERROR; 701 } 702 703 if (mPrefetcher != NULL) { 704 source = mPrefetcher->addSource(source); 705 } 706 707 mVideoSource = OMXCodec::Create( 708 mClient.interface(), source->getFormat(), 709 false, // createEncoder 710 source); 711 712 if (mVideoSource != NULL) { 713 int64_t durationUs; 714 if (source->getFormat()->findInt64(kKeyDuration, &durationUs)) { 715 if (mDurationUs < 0 || durationUs > mDurationUs) { 716 mDurationUs = durationUs; 717 } 718 } 719 720 CHECK(source->getFormat()->findInt32(kKeyWidth, &mVideoWidth)); 721 CHECK(source->getFormat()->findInt32(kKeyHeight, &mVideoHeight)); 722 723 mVideoSource->start(); 724 } 725 726 return mVideoSource != NULL ? OK : UNKNOWN_ERROR; 727} 728 729void AwesomePlayer::onVideoEvent() { 730 Mutex::Autolock autoLock(mLock); 731 if (!mVideoEventPending) { 732 // The event has been cancelled in reset_l() but had already 733 // been scheduled for execution at that time. 734 return; 735 } 736 mVideoEventPending = false; 737 738 if (mSeeking) { 739 if (mLastVideoBuffer) { 740 mLastVideoBuffer->release(); 741 mLastVideoBuffer = NULL; 742 } 743 744 if (mVideoBuffer) { 745 mVideoBuffer->release(); 746 mVideoBuffer = NULL; 747 } 748 } 749 750 if (!mVideoBuffer) { 751 MediaSource::ReadOptions options; 752 if (mSeeking) { 753 LOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs, mSeekTimeUs / 1E6); 754 755 options.setSeekTo(mSeekTimeUs); 756 } 757 for (;;) { 758 status_t err = mVideoSource->read(&mVideoBuffer, &options); 759 options.clearSeekTo(); 760 761 if (err != OK) { 762 CHECK_EQ(mVideoBuffer, NULL); 763 764 if (err == INFO_FORMAT_CHANGED) { 765 LOGV("VideoSource signalled format change."); 766 767 if (mVideoRenderer != NULL) { 768 initRenderer_l(); 769 } 770 continue; 771 } 772 773 postStreamDoneEvent_l(); 774 return; 775 } 776 777 if (mVideoBuffer->range_length() == 0) { 778 // Some decoders, notably the PV AVC software decoder 779 // return spurious empty buffers that we just want to ignore. 780 781 mVideoBuffer->release(); 782 mVideoBuffer = NULL; 783 continue; 784 } 785 786 break; 787 } 788 } 789 790 int64_t timeUs; 791 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs)); 792 793 mVideoTimeUs = timeUs; 794 795 if (mSeeking) { 796 if (mAudioPlayer != NULL) { 797 LOGV("seeking audio to %lld us (%.2f secs).", timeUs, timeUs / 1E6); 798 799 mAudioPlayer->seekTo(timeUs); 800 mWatchForAudioSeekComplete = true; 801 mWatchForAudioEOS = true; 802 } else { 803 // If we're playing video only, report seek complete now, 804 // otherwise audio player will notify us later. 805 notifyListener_l(MEDIA_SEEK_COMPLETE); 806 } 807 808 mFlags |= FIRST_FRAME; 809 mSeeking = false; 810 } 811 812 if (mFlags & FIRST_FRAME) { 813 mFlags &= ~FIRST_FRAME; 814 815 mTimeSourceDeltaUs = mTimeSource->getRealTimeUs() - timeUs; 816 } 817 818 int64_t realTimeUs, mediaTimeUs; 819 if (mAudioPlayer != NULL 820 && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) { 821 mTimeSourceDeltaUs = realTimeUs - mediaTimeUs; 822 } 823 824 int64_t nowUs = mTimeSource->getRealTimeUs() - mTimeSourceDeltaUs; 825 826 int64_t latenessUs = nowUs - timeUs; 827 828 if (latenessUs > 40000) { 829 // We're more than 40ms late. 830 LOGV("we're late by %lld us (%.2f secs)", latenessUs, latenessUs / 1E6); 831 832 mVideoBuffer->release(); 833 mVideoBuffer = NULL; 834 835 postVideoEvent_l(); 836 return; 837 } 838 839 if (latenessUs < -10000) { 840 // We're more than 10ms early. 841 842 postVideoEvent_l(10000); 843 return; 844 } 845 846 if (mVideoRenderer == NULL) { 847 initRenderer_l(); 848 } 849 850 if (mVideoRenderer != NULL) { 851 mVideoRenderer->render(mVideoBuffer); 852 } 853 854 if (mLastVideoBuffer) { 855 mLastVideoBuffer->release(); 856 mLastVideoBuffer = NULL; 857 } 858 mLastVideoBuffer = mVideoBuffer; 859 mVideoBuffer = NULL; 860 861 postVideoEvent_l(); 862} 863 864void AwesomePlayer::postVideoEvent_l(int64_t delayUs) { 865 if (mVideoEventPending) { 866 return; 867 } 868 869 mVideoEventPending = true; 870 mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs); 871} 872 873void AwesomePlayer::postStreamDoneEvent_l() { 874 if (mStreamDoneEventPending) { 875 return; 876 } 877 mStreamDoneEventPending = true; 878 mQueue.postEvent(mStreamDoneEvent); 879} 880 881void AwesomePlayer::postBufferingEvent_l() { 882 if (mPrefetcher == NULL) { 883 return; 884 } 885 886 if (mBufferingEventPending) { 887 return; 888 } 889 mBufferingEventPending = true; 890 mQueue.postEventWithDelay(mBufferingEvent, 1000000ll); 891} 892 893void AwesomePlayer::postCheckAudioStatusEvent_l() { 894 if (mAudioStatusEventPending) { 895 return; 896 } 897 mAudioStatusEventPending = true; 898 mQueue.postEventWithDelay(mCheckAudioStatusEvent, 100000ll); 899} 900 901void AwesomePlayer::onCheckAudioStatus() { 902 Mutex::Autolock autoLock(mLock); 903 mAudioStatusEventPending = false; 904 905 if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) { 906 mWatchForAudioSeekComplete = false; 907 notifyListener_l(MEDIA_SEEK_COMPLETE); 908 } 909 910 if (mWatchForAudioEOS && mAudioPlayer->reachedEOS()) { 911 mWatchForAudioEOS = false; 912 postStreamDoneEvent_l(); 913 } 914 915 postCheckAudioStatusEvent_l(); 916} 917 918status_t AwesomePlayer::prepare() { 919 Mutex::Autolock autoLock(mLock); 920 return prepare_l(); 921} 922 923status_t AwesomePlayer::prepare_l() { 924 if (mFlags & PREPARED) { 925 return OK; 926 } 927 928 if (mFlags & PREPARING) { 929 return UNKNOWN_ERROR; 930 } 931 932 mIsAsyncPrepare = false; 933 status_t err = prepareAsync_l(); 934 935 if (err != OK) { 936 return err; 937 } 938 939 while (mFlags & PREPARING) { 940 mPreparedCondition.wait(mLock); 941 } 942 943 return mPrepareResult; 944} 945 946status_t AwesomePlayer::prepareAsync() { 947 Mutex::Autolock autoLock(mLock); 948 949 if (mFlags & PREPARING) { 950 return UNKNOWN_ERROR; // async prepare already pending 951 } 952 953 mIsAsyncPrepare = true; 954 return prepareAsync_l(); 955} 956 957status_t AwesomePlayer::prepareAsync_l() { 958 if (mFlags & PREPARING) { 959 return UNKNOWN_ERROR; // async prepare already pending 960 } 961 962 mFlags |= PREPARING; 963 mAsyncPrepareEvent = new AwesomeEvent( 964 this, &AwesomePlayer::onPrepareAsyncEvent); 965 966 mQueue.postEvent(mAsyncPrepareEvent); 967 968 return OK; 969} 970 971status_t AwesomePlayer::finishSetDataSource_l() { 972 sp<DataSource> dataSource = 973 DataSource::CreateFromURI(mUri.string(), &mUriHeaders); 974 975 if (dataSource == NULL) { 976 return UNKNOWN_ERROR; 977 } 978 979 sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource); 980 981 if (extractor == NULL) { 982 return UNKNOWN_ERROR; 983 } 984 985 if (dataSource->flags() & DataSource::kWantsPrefetching) { 986 mPrefetcher = new Prefetcher; 987 } 988 989 return setDataSource_l(extractor); 990} 991 992void AwesomePlayer::onPrepareAsyncEvent() { 993 { 994 Mutex::Autolock autoLock(mLock); 995 996 if (mUri.size() > 0) { 997 status_t err = finishSetDataSource_l(); 998 999 if (err != OK) { 1000 if (mIsAsyncPrepare) { 1001 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err); 1002 } 1003 1004 mPrepareResult = err; 1005 mFlags &= ~PREPARING; 1006 mAsyncPrepareEvent = NULL; 1007 mPreparedCondition.broadcast(); 1008 1009 return; 1010 } 1011 } 1012 } 1013 1014 sp<Prefetcher> prefetcher; 1015 1016 { 1017 Mutex::Autolock autoLock(mLock); 1018 prefetcher = mPrefetcher; 1019 } 1020 1021 if (prefetcher != NULL) { 1022 prefetcher->prepare(); 1023 prefetcher.clear(); 1024 } 1025 1026 Mutex::Autolock autoLock(mLock); 1027 1028 if (mIsAsyncPrepare) { 1029 if (mVideoWidth < 0 || mVideoHeight < 0) { 1030 notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0); 1031 } else { 1032 notifyListener_l(MEDIA_SET_VIDEO_SIZE, mVideoWidth, mVideoHeight); 1033 } 1034 1035 notifyListener_l(MEDIA_PREPARED); 1036 } 1037 1038 mPrepareResult = OK; 1039 mFlags &= ~PREPARING; 1040 mFlags |= PREPARED; 1041 mAsyncPrepareEvent = NULL; 1042 mPreparedCondition.broadcast(); 1043} 1044 1045status_t AwesomePlayer::suspend() { 1046 LOGI("suspend"); 1047 Mutex::Autolock autoLock(mLock); 1048 1049 if (mSuspensionState != NULL) { 1050 return INVALID_OPERATION; 1051 } 1052 1053 while (mFlags & PREPARING) { 1054 mPreparedCondition.wait(mLock); 1055 } 1056 1057 SuspensionState *state = new SuspensionState; 1058 state->mUri = mUri; 1059 state->mUriHeaders = mUriHeaders; 1060 state->mFileSource = mFileSource; 1061 1062 state->mFlags = mFlags & (PLAYING | LOOPING); 1063 getPosition_l(&state->mPositionUs); 1064 1065 reset_l(); 1066 1067 mSuspensionState = state; 1068 1069 return OK; 1070} 1071 1072status_t AwesomePlayer::resume() { 1073 LOGI("resume"); 1074 Mutex::Autolock autoLock(mLock); 1075 1076 if (mSuspensionState == NULL) { 1077 return INVALID_OPERATION; 1078 } 1079 1080 SuspensionState *state = mSuspensionState; 1081 mSuspensionState = NULL; 1082 1083 status_t err; 1084 if (state->mFileSource != NULL) { 1085 err = setDataSource_l(state->mFileSource); 1086 1087 if (err == OK) { 1088 mFileSource = state->mFileSource; 1089 } 1090 } else { 1091 err = setDataSource_l(state->mUri, &state->mUriHeaders); 1092 } 1093 1094 if (err != OK) { 1095 delete state; 1096 state = NULL; 1097 1098 return err; 1099 } 1100 1101 seekTo_l(state->mPositionUs); 1102 1103 mFlags = state->mFlags & LOOPING; 1104 1105 if (state->mFlags & PLAYING) { 1106 play_l(); 1107 } 1108 1109 delete state; 1110 state = NULL; 1111 1112 return OK; 1113} 1114 1115} // namespace android 1116 1117