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