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