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