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