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