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