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