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