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