AwesomePlayer.cpp revision acdd9d0f59c3d8bdc3de80664a609527ec3d21e2
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 mAudioSource->start(); 782 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_QCELP)) { 783 // For legacy reasons we're simply going to ignore the absence 784 // of an audio decoder for QCELP instead of aborting playback 785 // altogether. 786 return OK; 787 } 788 789 return mAudioSource != NULL ? OK : UNKNOWN_ERROR; 790} 791 792void AwesomePlayer::setVideoSource(sp<MediaSource> source) { 793 CHECK(source != NULL); 794 795 if (mPrefetcher != NULL) { 796 source = mPrefetcher->addSource(source); 797 } 798 799 mVideoTrack = source; 800} 801 802status_t AwesomePlayer::initVideoDecoder() { 803 mVideoSource = OMXCodec::Create( 804 mClient.interface(), mVideoTrack->getFormat(), 805 false, // createEncoder 806 mVideoTrack); 807 808 if (mVideoSource != NULL) { 809 int64_t durationUs; 810 if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) { 811 Mutex::Autolock autoLock(mMiscStateLock); 812 if (mDurationUs < 0 || durationUs > mDurationUs) { 813 mDurationUs = durationUs; 814 } 815 } 816 817 CHECK(mVideoTrack->getFormat()->findInt32(kKeyWidth, &mVideoWidth)); 818 CHECK(mVideoTrack->getFormat()->findInt32(kKeyHeight, &mVideoHeight)); 819 820 mVideoSource->start(); 821 } 822 823 return mVideoSource != NULL ? OK : UNKNOWN_ERROR; 824} 825 826void AwesomePlayer::onVideoEvent() { 827 Mutex::Autolock autoLock(mLock); 828 if (!mVideoEventPending) { 829 // The event has been cancelled in reset_l() but had already 830 // been scheduled for execution at that time. 831 return; 832 } 833 mVideoEventPending = false; 834 835 if (mSeeking) { 836 if (mLastVideoBuffer) { 837 mLastVideoBuffer->release(); 838 mLastVideoBuffer = NULL; 839 } 840 841 if (mVideoBuffer) { 842 mVideoBuffer->release(); 843 mVideoBuffer = NULL; 844 } 845 } 846 847 if (!mVideoBuffer) { 848 MediaSource::ReadOptions options; 849 if (mSeeking) { 850 LOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs, mSeekTimeUs / 1E6); 851 852 options.setSeekTo(mSeekTimeUs); 853 } 854 for (;;) { 855 status_t err = mVideoSource->read(&mVideoBuffer, &options); 856 options.clearSeekTo(); 857 858 if (err != OK) { 859 CHECK_EQ(mVideoBuffer, NULL); 860 861 if (err == INFO_FORMAT_CHANGED) { 862 LOGV("VideoSource signalled format change."); 863 864 if (mVideoRenderer != NULL) { 865 mVideoRendererIsPreview = false; 866 initRenderer_l(); 867 } 868 continue; 869 } 870 871 postStreamDoneEvent_l(err); 872 return; 873 } 874 875 if (mVideoBuffer->range_length() == 0) { 876 // Some decoders, notably the PV AVC software decoder 877 // return spurious empty buffers that we just want to ignore. 878 879 mVideoBuffer->release(); 880 mVideoBuffer = NULL; 881 continue; 882 } 883 884 break; 885 } 886 } 887 888 int64_t timeUs; 889 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs)); 890 891 { 892 Mutex::Autolock autoLock(mMiscStateLock); 893 mVideoTimeUs = timeUs; 894 } 895 896 if (mSeeking) { 897 if (mAudioPlayer != NULL) { 898 LOGV("seeking audio to %lld us (%.2f secs).", timeUs, timeUs / 1E6); 899 900 mAudioPlayer->seekTo(timeUs); 901 mWatchForAudioSeekComplete = true; 902 mWatchForAudioEOS = true; 903 } else if (!mSeekNotificationSent) { 904 // If we're playing video only, report seek complete now, 905 // otherwise audio player will notify us later. 906 notifyListener_l(MEDIA_SEEK_COMPLETE); 907 } 908 909 mFlags |= FIRST_FRAME; 910 mSeeking = false; 911 mSeekNotificationSent = false; 912 } 913 914 if (mFlags & FIRST_FRAME) { 915 mFlags &= ~FIRST_FRAME; 916 917 mTimeSourceDeltaUs = mTimeSource->getRealTimeUs() - timeUs; 918 } 919 920 int64_t realTimeUs, mediaTimeUs; 921 if (mAudioPlayer != NULL 922 && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) { 923 mTimeSourceDeltaUs = realTimeUs - mediaTimeUs; 924 } 925 926 int64_t nowUs = mTimeSource->getRealTimeUs() - mTimeSourceDeltaUs; 927 928 int64_t latenessUs = nowUs - timeUs; 929 930 if (latenessUs > 40000) { 931 // We're more than 40ms late. 932 LOGV("we're late by %lld us (%.2f secs)", latenessUs, latenessUs / 1E6); 933 934 mVideoBuffer->release(); 935 mVideoBuffer = NULL; 936 937 postVideoEvent_l(); 938 return; 939 } 940 941 if (latenessUs < -10000) { 942 // We're more than 10ms early. 943 944 postVideoEvent_l(10000); 945 return; 946 } 947 948 if (mVideoRendererIsPreview || mVideoRenderer == NULL) { 949 mVideoRendererIsPreview = false; 950 951 initRenderer_l(); 952 } 953 954 if (mVideoRenderer != NULL) { 955 mVideoRenderer->render(mVideoBuffer); 956 } 957 958 if (mLastVideoBuffer) { 959 mLastVideoBuffer->release(); 960 mLastVideoBuffer = NULL; 961 } 962 mLastVideoBuffer = mVideoBuffer; 963 mVideoBuffer = NULL; 964 965 postVideoEvent_l(); 966} 967 968void AwesomePlayer::postVideoEvent_l(int64_t delayUs) { 969 if (mVideoEventPending) { 970 return; 971 } 972 973 mVideoEventPending = true; 974 mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs); 975} 976 977void AwesomePlayer::postStreamDoneEvent_l(status_t status) { 978 if (mStreamDoneEventPending) { 979 return; 980 } 981 mStreamDoneEventPending = true; 982 983 mStreamDoneStatus = status; 984 mQueue.postEvent(mStreamDoneEvent); 985} 986 987void AwesomePlayer::postBufferingEvent_l() { 988 if (mPrefetcher == NULL) { 989 return; 990 } 991 992 if (mBufferingEventPending) { 993 return; 994 } 995 mBufferingEventPending = true; 996 mQueue.postEventWithDelay(mBufferingEvent, 1000000ll); 997} 998 999void AwesomePlayer::postCheckAudioStatusEvent_l() { 1000 if (mAudioStatusEventPending) { 1001 return; 1002 } 1003 mAudioStatusEventPending = true; 1004 mQueue.postEventWithDelay(mCheckAudioStatusEvent, 100000ll); 1005} 1006 1007void AwesomePlayer::onCheckAudioStatus() { 1008 Mutex::Autolock autoLock(mLock); 1009 if (!mAudioStatusEventPending) { 1010 // Event was dispatched and while we were blocking on the mutex, 1011 // has already been cancelled. 1012 return; 1013 } 1014 1015 mAudioStatusEventPending = false; 1016 1017 if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) { 1018 mWatchForAudioSeekComplete = false; 1019 1020 if (!mSeekNotificationSent) { 1021 notifyListener_l(MEDIA_SEEK_COMPLETE); 1022 mSeekNotificationSent = true; 1023 } 1024 1025 mSeeking = false; 1026 } 1027 1028 status_t finalStatus; 1029 if (mWatchForAudioEOS && mAudioPlayer->reachedEOS(&finalStatus)) { 1030 mWatchForAudioEOS = false; 1031 postStreamDoneEvent_l(finalStatus); 1032 } 1033 1034 postCheckAudioStatusEvent_l(); 1035} 1036 1037status_t AwesomePlayer::prepare() { 1038 Mutex::Autolock autoLock(mLock); 1039 return prepare_l(); 1040} 1041 1042status_t AwesomePlayer::prepare_l() { 1043 if (mFlags & PREPARED) { 1044 return OK; 1045 } 1046 1047 if (mFlags & PREPARING) { 1048 return UNKNOWN_ERROR; 1049 } 1050 1051 mIsAsyncPrepare = false; 1052 status_t err = prepareAsync_l(); 1053 1054 if (err != OK) { 1055 return err; 1056 } 1057 1058 while (mFlags & PREPARING) { 1059 mPreparedCondition.wait(mLock); 1060 } 1061 1062 return mPrepareResult; 1063} 1064 1065status_t AwesomePlayer::prepareAsync() { 1066 Mutex::Autolock autoLock(mLock); 1067 1068 if (mFlags & PREPARING) { 1069 return UNKNOWN_ERROR; // async prepare already pending 1070 } 1071 1072 mIsAsyncPrepare = true; 1073 return prepareAsync_l(); 1074} 1075 1076status_t AwesomePlayer::prepareAsync_l() { 1077 if (mFlags & PREPARING) { 1078 return UNKNOWN_ERROR; // async prepare already pending 1079 } 1080 1081 if (!mQueueStarted) { 1082 mQueue.start(); 1083 mQueueStarted = true; 1084 } 1085 1086 mFlags |= PREPARING; 1087 mAsyncPrepareEvent = new AwesomeEvent( 1088 this, &AwesomePlayer::onPrepareAsyncEvent); 1089 1090 mQueue.postEvent(mAsyncPrepareEvent); 1091 1092 return OK; 1093} 1094 1095status_t AwesomePlayer::finishSetDataSource_l() { 1096 sp<DataSource> dataSource; 1097 1098 if (!strncasecmp("http://", mUri.string(), 7)) { 1099 mConnectingDataSource = new HTTPDataSource(mUri, &mUriHeaders); 1100 1101 mLock.unlock(); 1102 status_t err = mConnectingDataSource->connect(); 1103 mLock.lock(); 1104 1105 if (err != OK) { 1106 mConnectingDataSource.clear(); 1107 1108 LOGI("mConnectingDataSource->connect() returned %d", err); 1109 return err; 1110 } 1111 1112 dataSource = new CachingDataSource( 1113 mConnectingDataSource, 64 * 1024, 10); 1114 1115 mConnectingDataSource.clear(); 1116 } else { 1117 dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders); 1118 } 1119 1120 if (dataSource == NULL) { 1121 return UNKNOWN_ERROR; 1122 } 1123 1124 sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource); 1125 1126 if (extractor == NULL) { 1127 return UNKNOWN_ERROR; 1128 } 1129 1130 if (dataSource->flags() & DataSource::kWantsPrefetching) { 1131 mPrefetcher = new Prefetcher; 1132 } 1133 1134 return setDataSource_l(extractor); 1135} 1136 1137void AwesomePlayer::abortPrepare(status_t err) { 1138 CHECK(err != OK); 1139 1140 if (mIsAsyncPrepare) { 1141 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err); 1142 } 1143 1144 mPrepareResult = err; 1145 mFlags &= ~(PREPARING|PREPARE_CANCELLED); 1146 mAsyncPrepareEvent = NULL; 1147 mPreparedCondition.broadcast(); 1148} 1149 1150// static 1151bool AwesomePlayer::ContinuePreparation(void *cookie) { 1152 AwesomePlayer *me = static_cast<AwesomePlayer *>(cookie); 1153 1154 return (me->mFlags & PREPARE_CANCELLED) == 0; 1155} 1156 1157void AwesomePlayer::onPrepareAsyncEvent() { 1158 sp<Prefetcher> prefetcher; 1159 1160 { 1161 Mutex::Autolock autoLock(mLock); 1162 1163 if (mFlags & PREPARE_CANCELLED) { 1164 LOGI("prepare was cancelled before doing anything"); 1165 abortPrepare(UNKNOWN_ERROR); 1166 return; 1167 } 1168 1169 if (mUri.size() > 0) { 1170 status_t err = finishSetDataSource_l(); 1171 1172 if (err != OK) { 1173 abortPrepare(err); 1174 return; 1175 } 1176 } 1177 1178 if (mVideoTrack != NULL && mVideoSource == NULL) { 1179 status_t err = initVideoDecoder(); 1180 1181 if (err != OK) { 1182 abortPrepare(err); 1183 return; 1184 } 1185 } 1186 1187 if (mAudioTrack != NULL && mAudioSource == NULL) { 1188 status_t err = initAudioDecoder(); 1189 1190 if (err != OK) { 1191 abortPrepare(err); 1192 return; 1193 } 1194 } 1195 1196 prefetcher = mPrefetcher; 1197 } 1198 1199 if (prefetcher != NULL) { 1200 { 1201 Mutex::Autolock autoLock(mLock); 1202 if (mFlags & PREPARE_CANCELLED) { 1203 LOGI("prepare was cancelled before preparing the prefetcher"); 1204 1205 prefetcher.clear(); 1206 abortPrepare(UNKNOWN_ERROR); 1207 return; 1208 } 1209 } 1210 1211 LOGI("calling prefetcher->prepare()"); 1212 status_t result = 1213 prefetcher->prepare(&AwesomePlayer::ContinuePreparation, this); 1214 1215 prefetcher.clear(); 1216 1217 if (result == OK) { 1218 LOGI("prefetcher is done preparing"); 1219 } else { 1220 Mutex::Autolock autoLock(mLock); 1221 1222 CHECK_EQ(result, -EINTR); 1223 1224 LOGI("prefetcher->prepare() was cancelled early."); 1225 abortPrepare(UNKNOWN_ERROR); 1226 return; 1227 } 1228 } 1229 1230 Mutex::Autolock autoLock(mLock); 1231 1232 if (mIsAsyncPrepare) { 1233 if (mVideoWidth < 0 || mVideoHeight < 0) { 1234 notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0); 1235 } else { 1236 notifyListener_l(MEDIA_SET_VIDEO_SIZE, mVideoWidth, mVideoHeight); 1237 } 1238 1239 notifyListener_l(MEDIA_PREPARED); 1240 } 1241 1242 mPrepareResult = OK; 1243 mFlags &= ~(PREPARING|PREPARE_CANCELLED); 1244 mFlags |= PREPARED; 1245 mAsyncPrepareEvent = NULL; 1246 mPreparedCondition.broadcast(); 1247 1248 postBufferingEvent_l(); 1249} 1250 1251status_t AwesomePlayer::suspend() { 1252 LOGV("suspend"); 1253 Mutex::Autolock autoLock(mLock); 1254 1255 if (mSuspensionState != NULL) { 1256 if (mLastVideoBuffer == NULL) { 1257 //go into here if video is suspended again 1258 //after resuming without being played between 1259 //them 1260 SuspensionState *state = mSuspensionState; 1261 mSuspensionState = NULL; 1262 reset_l(); 1263 mSuspensionState = state; 1264 return OK; 1265 } 1266 1267 delete mSuspensionState; 1268 mSuspensionState = NULL; 1269 } 1270 1271 if (mFlags & PREPARING) { 1272 mFlags |= PREPARE_CANCELLED; 1273 if (mConnectingDataSource != NULL) { 1274 LOGI("interrupting the connection process"); 1275 mConnectingDataSource->disconnect(); 1276 } 1277 } 1278 1279 while (mFlags & PREPARING) { 1280 mPreparedCondition.wait(mLock); 1281 } 1282 1283 SuspensionState *state = new SuspensionState; 1284 state->mUri = mUri; 1285 state->mUriHeaders = mUriHeaders; 1286 state->mFileSource = mFileSource; 1287 1288 state->mFlags = mFlags & (PLAYING | LOOPING | AT_EOS); 1289 getPosition(&state->mPositionUs); 1290 1291 if (mLastVideoBuffer) { 1292 size_t size = mLastVideoBuffer->range_length(); 1293 if (size) { 1294 state->mLastVideoFrameSize = size; 1295 state->mLastVideoFrame = malloc(size); 1296 memcpy(state->mLastVideoFrame, 1297 (const uint8_t *)mLastVideoBuffer->data() 1298 + mLastVideoBuffer->range_offset(), 1299 size); 1300 1301 state->mVideoWidth = mVideoWidth; 1302 state->mVideoHeight = mVideoHeight; 1303 1304 sp<MetaData> meta = mVideoSource->getFormat(); 1305 CHECK(meta->findInt32(kKeyColorFormat, &state->mColorFormat)); 1306 CHECK(meta->findInt32(kKeyWidth, &state->mDecodedWidth)); 1307 CHECK(meta->findInt32(kKeyHeight, &state->mDecodedHeight)); 1308 } 1309 } 1310 1311 reset_l(); 1312 1313 mSuspensionState = state; 1314 1315 return OK; 1316} 1317 1318status_t AwesomePlayer::resume() { 1319 LOGV("resume"); 1320 Mutex::Autolock autoLock(mLock); 1321 1322 if (mSuspensionState == NULL) { 1323 return INVALID_OPERATION; 1324 } 1325 1326 SuspensionState *state = mSuspensionState; 1327 mSuspensionState = NULL; 1328 1329 status_t err; 1330 if (state->mFileSource != NULL) { 1331 err = setDataSource_l(state->mFileSource); 1332 1333 if (err == OK) { 1334 mFileSource = state->mFileSource; 1335 } 1336 } else { 1337 err = setDataSource_l(state->mUri, &state->mUriHeaders); 1338 } 1339 1340 if (err != OK) { 1341 delete state; 1342 state = NULL; 1343 1344 return err; 1345 } 1346 1347 seekTo_l(state->mPositionUs); 1348 1349 mFlags = state->mFlags & (LOOPING | AT_EOS); 1350 1351 if (state->mLastVideoFrame && mISurface != NULL) { 1352 mVideoRenderer = 1353 new AwesomeLocalRenderer( 1354 true, // previewOnly 1355 "", 1356 (OMX_COLOR_FORMATTYPE)state->mColorFormat, 1357 mISurface, 1358 state->mVideoWidth, 1359 state->mVideoHeight, 1360 state->mDecodedWidth, 1361 state->mDecodedHeight); 1362 1363 mVideoRendererIsPreview = true; 1364 1365 ((AwesomeLocalRenderer *)mVideoRenderer.get())->render( 1366 state->mLastVideoFrame, state->mLastVideoFrameSize); 1367 } 1368 1369 if (state->mFlags & PLAYING) { 1370 play_l(); 1371 } 1372 1373 mSuspensionState = state; 1374 state = NULL; 1375 1376 return OK; 1377} 1378 1379uint32_t AwesomePlayer::flags() const { 1380 return mExtractorFlags; 1381} 1382 1383} // namespace android 1384 1385