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