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