AwesomePlayer.cpp revision e7e3b785a0e7819db4c895a4f60e9a4dd755880c
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 setVideoSource(extractor->getTrack(i)); 301 haveVideo = true; 302 } else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) { 303 setAudioSource(extractor->getTrack(i)); 304 haveAudio = true; 305 } 306 307 if (haveAudio && haveVideo) { 308 break; 309 } 310 } 311 312 return !haveAudio && !haveVideo ? UNKNOWN_ERROR : OK; 313} 314 315void AwesomePlayer::reset() { 316 Mutex::Autolock autoLock(mLock); 317 reset_l(); 318} 319 320void AwesomePlayer::reset_l() { 321 while (mFlags & PREPARING) { 322 mPreparedCondition.wait(mLock); 323 } 324 325 cancelPlayerEvents(); 326 327 if (mPrefetcher != NULL) { 328 CHECK_EQ(mPrefetcher->getStrongCount(), 1); 329 } 330 mPrefetcher.clear(); 331 332 mAudioTrack.clear(); 333 mVideoTrack.clear(); 334 335 // Shutdown audio first, so that the respone to the reset request 336 // appears to happen instantaneously as far as the user is concerned 337 // If we did this later, audio would continue playing while we 338 // shutdown the video-related resources and the player appear to 339 // not be as responsive to a reset request. 340 mAudioSource.clear(); 341 342 if (mTimeSource != mAudioPlayer) { 343 delete mTimeSource; 344 } 345 mTimeSource = NULL; 346 347 delete mAudioPlayer; 348 mAudioPlayer = NULL; 349 350 mVideoRenderer.clear(); 351 352 if (mLastVideoBuffer) { 353 mLastVideoBuffer->release(); 354 mLastVideoBuffer = NULL; 355 } 356 357 if (mVideoBuffer) { 358 mVideoBuffer->release(); 359 mVideoBuffer = NULL; 360 } 361 362 if (mVideoSource != NULL) { 363 mVideoSource->stop(); 364 365 // The following hack is necessary to ensure that the OMX 366 // component is completely released by the time we may try 367 // to instantiate it again. 368 wp<MediaSource> tmp = mVideoSource; 369 mVideoSource.clear(); 370 while (tmp.promote() != NULL) { 371 usleep(1000); 372 } 373 IPCThreadState::self()->flushCommands(); 374 } 375 376 mDurationUs = -1; 377 mFlags = 0; 378 mVideoWidth = mVideoHeight = -1; 379 mTimeSourceDeltaUs = 0; 380 mVideoTimeUs = 0; 381 382 mSeeking = false; 383 mSeekTimeUs = 0; 384 385 mUri.setTo(""); 386 mUriHeaders.clear(); 387 388 mFileSource.clear(); 389 390 delete mSuspensionState; 391 mSuspensionState = NULL; 392} 393 394void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) { 395 if (mListener != NULL) { 396 sp<MediaPlayerBase> listener = mListener.promote(); 397 398 if (listener != NULL) { 399 listener->sendEvent(msg, ext1, ext2); 400 } 401 } 402} 403 404void AwesomePlayer::onBufferingUpdate() { 405 Mutex::Autolock autoLock(mLock); 406 if (!mBufferingEventPending) { 407 return; 408 } 409 mBufferingEventPending = false; 410 411 if (mDurationUs >= 0) { 412 int64_t cachedDurationUs = mPrefetcher->getCachedDurationUs(); 413 414 LOGV("cache holds %.2f secs worth of data.", cachedDurationUs / 1E6); 415 416 int64_t positionUs = 0; 417 if (mVideoSource != NULL) { 418 positionUs = mVideoTimeUs; 419 } else if (mAudioPlayer != NULL) { 420 positionUs = mAudioPlayer->getMediaTimeUs(); 421 } 422 423 cachedDurationUs += positionUs; 424 425 double percentage = (double)cachedDurationUs / mDurationUs; 426 notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage * 100.0); 427 428 postBufferingEvent_l(); 429 } 430} 431 432void AwesomePlayer::onStreamDone() { 433 // Posted whenever any stream finishes playing. 434 435 Mutex::Autolock autoLock(mLock); 436 if (!mStreamDoneEventPending) { 437 return; 438 } 439 mStreamDoneEventPending = false; 440 441 if (mStreamDoneStatus == ERROR_END_OF_STREAM && (mFlags & LOOPING)) { 442 seekTo_l(0); 443 444 if (mVideoSource != NULL) { 445 postVideoEvent_l(); 446 } 447 } else { 448 if (mStreamDoneStatus == ERROR_END_OF_STREAM) { 449 LOGV("MEDIA_PLAYBACK_COMPLETE"); 450 notifyListener_l(MEDIA_PLAYBACK_COMPLETE); 451 } else { 452 LOGV("MEDIA_ERROR %d", mStreamDoneStatus); 453 454 notifyListener_l( 455 MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, mStreamDoneStatus); 456 } 457 458 pause_l(); 459 460 mFlags |= AT_EOS; 461 } 462} 463 464status_t AwesomePlayer::play() { 465 Mutex::Autolock autoLock(mLock); 466 return play_l(); 467} 468 469status_t AwesomePlayer::play_l() { 470 if (mFlags & PLAYING) { 471 return OK; 472 } 473 474 if (!(mFlags & PREPARED)) { 475 status_t err = prepare_l(); 476 477 if (err != OK) { 478 return err; 479 } 480 } 481 482 mFlags |= PLAYING; 483 mFlags |= FIRST_FRAME; 484 485 bool deferredAudioSeek = false; 486 487 if (mAudioSource != NULL) { 488 if (mAudioPlayer == NULL) { 489 if (mAudioSink != NULL) { 490 mAudioPlayer = new AudioPlayer(mAudioSink); 491 mAudioPlayer->setSource(mAudioSource); 492 493 // We've already started the MediaSource in order to enable 494 // the prefetcher to read its data. 495 status_t err = mAudioPlayer->start( 496 true /* sourceAlreadyStarted */); 497 498 if (err != OK) { 499 delete mAudioPlayer; 500 mAudioPlayer = NULL; 501 502 mFlags &= ~(PLAYING | FIRST_FRAME); 503 504 return err; 505 } 506 507 delete mTimeSource; 508 mTimeSource = mAudioPlayer; 509 510 deferredAudioSeek = true; 511 512 mWatchForAudioSeekComplete = false; 513 mWatchForAudioEOS = true; 514 } 515 } else { 516 mAudioPlayer->resume(); 517 } 518 519 postCheckAudioStatusEvent_l(); 520 } 521 522 if (mTimeSource == NULL && mAudioPlayer == NULL) { 523 mTimeSource = new SystemTimeSource; 524 } 525 526 if (mVideoSource != NULL) { 527 // Kick off video playback 528 postVideoEvent_l(); 529 } 530 531 if (deferredAudioSeek) { 532 // If there was a seek request while we were paused 533 // and we're just starting up again, honor the request now. 534 seekAudioIfNecessary_l(); 535 } 536 537 postBufferingEvent_l(); 538 539 if (mFlags & AT_EOS) { 540 // Legacy behaviour, if a stream finishes playing and then 541 // is started again, we play from the start... 542 seekTo_l(0); 543 } 544 545 return OK; 546} 547 548void AwesomePlayer::initRenderer_l() { 549 if (mISurface != NULL) { 550 sp<MetaData> meta = mVideoSource->getFormat(); 551 552 int32_t format; 553 const char *component; 554 int32_t decodedWidth, decodedHeight; 555 CHECK(meta->findInt32(kKeyColorFormat, &format)); 556 CHECK(meta->findCString(kKeyDecoderComponent, &component)); 557 CHECK(meta->findInt32(kKeyWidth, &decodedWidth)); 558 CHECK(meta->findInt32(kKeyHeight, &decodedHeight)); 559 560 mVideoRenderer.clear(); 561 562 // Must ensure that mVideoRenderer's destructor is actually executed 563 // before creating a new one. 564 IPCThreadState::self()->flushCommands(); 565 566 if (!strncmp("OMX.", component, 4)) { 567 // Our OMX codecs allocate buffers on the media_server side 568 // therefore they require a remote IOMXRenderer that knows how 569 // to display them. 570 mVideoRenderer = new AwesomeRemoteRenderer( 571 mClient.interface()->createRenderer( 572 mISurface, component, 573 (OMX_COLOR_FORMATTYPE)format, 574 decodedWidth, decodedHeight, 575 mVideoWidth, mVideoHeight)); 576 } else { 577 // Other decoders are instantiated locally and as a consequence 578 // allocate their buffers in local address space. 579 mVideoRenderer = new AwesomeLocalRenderer( 580 false, // previewOnly 581 component, 582 (OMX_COLOR_FORMATTYPE)format, 583 mISurface, 584 mVideoWidth, mVideoHeight, 585 decodedWidth, decodedHeight); 586 } 587 } 588} 589 590status_t AwesomePlayer::pause() { 591 Mutex::Autolock autoLock(mLock); 592 return pause_l(); 593} 594 595status_t AwesomePlayer::pause_l() { 596 if (!(mFlags & PLAYING)) { 597 return OK; 598 } 599 600 cancelPlayerEvents(true /* keepBufferingGoing */); 601 602 if (mAudioPlayer != NULL) { 603 mAudioPlayer->pause(); 604 } 605 606 mFlags &= ~PLAYING; 607 608 return OK; 609} 610 611bool AwesomePlayer::isPlaying() const { 612 Mutex::Autolock autoLock(mLock); 613 614 return mFlags & PLAYING; 615} 616 617void AwesomePlayer::setISurface(const sp<ISurface> &isurface) { 618 Mutex::Autolock autoLock(mLock); 619 620 mISurface = isurface; 621} 622 623void AwesomePlayer::setAudioSink( 624 const sp<MediaPlayerBase::AudioSink> &audioSink) { 625 Mutex::Autolock autoLock(mLock); 626 627 mAudioSink = audioSink; 628} 629 630status_t AwesomePlayer::setLooping(bool shouldLoop) { 631 Mutex::Autolock autoLock(mLock); 632 633 mFlags = mFlags & ~LOOPING; 634 635 if (shouldLoop) { 636 mFlags |= LOOPING; 637 } 638 639 return OK; 640} 641 642status_t AwesomePlayer::getDuration(int64_t *durationUs) { 643 Mutex::Autolock autoLock(mLock); 644 645 if (mDurationUs < 0) { 646 return UNKNOWN_ERROR; 647 } 648 649 *durationUs = mDurationUs; 650 651 return OK; 652} 653 654status_t AwesomePlayer::getPosition(int64_t *positionUs) { 655 Mutex::Autolock autoLock(mLock); 656 return getPosition_l(positionUs); 657} 658 659status_t AwesomePlayer::getPosition_l(int64_t *positionUs) { 660 if (mVideoSource != NULL) { 661 *positionUs = mVideoTimeUs; 662 } else if (mAudioPlayer != NULL) { 663 *positionUs = mAudioPlayer->getMediaTimeUs(); 664 } else { 665 *positionUs = 0; 666 } 667 668 return OK; 669} 670 671status_t AwesomePlayer::seekTo(int64_t timeUs) { 672 Mutex::Autolock autoLock(mLock); 673 return seekTo_l(timeUs); 674} 675 676status_t AwesomePlayer::seekTo_l(int64_t timeUs) { 677 mSeeking = true; 678 mSeekTimeUs = timeUs; 679 mFlags &= ~AT_EOS; 680 681 seekAudioIfNecessary_l(); 682 683 return OK; 684} 685 686void AwesomePlayer::seekAudioIfNecessary_l() { 687 if (mSeeking && mVideoSource == NULL && mAudioPlayer != NULL) { 688 mAudioPlayer->seekTo(mSeekTimeUs); 689 690 mWatchForAudioSeekComplete = true; 691 mWatchForAudioEOS = true; 692 mSeeking = false; 693 } 694} 695 696status_t AwesomePlayer::getVideoDimensions( 697 int32_t *width, int32_t *height) const { 698 Mutex::Autolock autoLock(mLock); 699 700 if (mVideoWidth < 0 || mVideoHeight < 0) { 701 return UNKNOWN_ERROR; 702 } 703 704 *width = mVideoWidth; 705 *height = mVideoHeight; 706 707 return OK; 708} 709 710void AwesomePlayer::setAudioSource(sp<MediaSource> source) { 711 CHECK(source != NULL); 712 713 if (mPrefetcher != NULL) { 714 source = mPrefetcher->addSource(source); 715 } 716 717 mAudioTrack = source; 718} 719 720status_t AwesomePlayer::initAudioDecoder() { 721 sp<MetaData> meta = mAudioTrack->getFormat(); 722 723 const char *mime; 724 CHECK(meta->findCString(kKeyMIMEType, &mime)); 725 726 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) { 727 mAudioSource = mAudioTrack; 728 } else { 729 mAudioSource = OMXCodec::Create( 730 mClient.interface(), mAudioTrack->getFormat(), 731 false, // createEncoder 732 mAudioTrack); 733 } 734 735 if (mAudioSource != NULL) { 736 int64_t durationUs; 737 if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) { 738 if (mDurationUs < 0 || durationUs > mDurationUs) { 739 mDurationUs = durationUs; 740 } 741 } 742 } 743 744 mAudioSource->start(); 745 746 return mAudioSource != NULL ? OK : UNKNOWN_ERROR; 747} 748 749void AwesomePlayer::setVideoSource(sp<MediaSource> source) { 750 CHECK(source != NULL); 751 752 if (mPrefetcher != NULL) { 753 source = mPrefetcher->addSource(source); 754 } 755 756 mVideoTrack = source; 757} 758 759status_t AwesomePlayer::initVideoDecoder() { 760 mVideoSource = OMXCodec::Create( 761 mClient.interface(), mVideoTrack->getFormat(), 762 false, // createEncoder 763 mVideoTrack); 764 765 if (mVideoSource != NULL) { 766 int64_t durationUs; 767 if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) { 768 if (mDurationUs < 0 || durationUs > mDurationUs) { 769 mDurationUs = durationUs; 770 } 771 } 772 773 CHECK(mVideoTrack->getFormat()->findInt32(kKeyWidth, &mVideoWidth)); 774 CHECK(mVideoTrack->getFormat()->findInt32(kKeyHeight, &mVideoHeight)); 775 776 mVideoSource->start(); 777 } 778 779 return mVideoSource != NULL ? OK : UNKNOWN_ERROR; 780} 781 782void AwesomePlayer::onVideoEvent() { 783 Mutex::Autolock autoLock(mLock); 784 if (!mVideoEventPending) { 785 // The event has been cancelled in reset_l() but had already 786 // been scheduled for execution at that time. 787 return; 788 } 789 mVideoEventPending = false; 790 791 if (mSeeking) { 792 if (mLastVideoBuffer) { 793 mLastVideoBuffer->release(); 794 mLastVideoBuffer = NULL; 795 } 796 797 if (mVideoBuffer) { 798 mVideoBuffer->release(); 799 mVideoBuffer = NULL; 800 } 801 } 802 803 if (!mVideoBuffer) { 804 MediaSource::ReadOptions options; 805 if (mSeeking) { 806 LOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs, mSeekTimeUs / 1E6); 807 808 options.setSeekTo(mSeekTimeUs); 809 } 810 for (;;) { 811 status_t err = mVideoSource->read(&mVideoBuffer, &options); 812 options.clearSeekTo(); 813 814 if (err != OK) { 815 CHECK_EQ(mVideoBuffer, NULL); 816 817 if (err == INFO_FORMAT_CHANGED) { 818 LOGV("VideoSource signalled format change."); 819 820 if (mVideoRenderer != NULL) { 821 mVideoRendererIsPreview = false; 822 initRenderer_l(); 823 } 824 continue; 825 } 826 827 postStreamDoneEvent_l(err); 828 return; 829 } 830 831 if (mVideoBuffer->range_length() == 0) { 832 // Some decoders, notably the PV AVC software decoder 833 // return spurious empty buffers that we just want to ignore. 834 835 mVideoBuffer->release(); 836 mVideoBuffer = NULL; 837 continue; 838 } 839 840 break; 841 } 842 } 843 844 int64_t timeUs; 845 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs)); 846 847 mVideoTimeUs = timeUs; 848 849 if (mSeeking) { 850 if (mAudioPlayer != NULL) { 851 LOGV("seeking audio to %lld us (%.2f secs).", timeUs, timeUs / 1E6); 852 853 mAudioPlayer->seekTo(timeUs); 854 mWatchForAudioSeekComplete = true; 855 mWatchForAudioEOS = true; 856 } else { 857 // If we're playing video only, report seek complete now, 858 // otherwise audio player will notify us later. 859 notifyListener_l(MEDIA_SEEK_COMPLETE); 860 } 861 862 mFlags |= FIRST_FRAME; 863 mSeeking = false; 864 } 865 866 if (mFlags & FIRST_FRAME) { 867 mFlags &= ~FIRST_FRAME; 868 869 mTimeSourceDeltaUs = mTimeSource->getRealTimeUs() - timeUs; 870 } 871 872 int64_t realTimeUs, mediaTimeUs; 873 if (mAudioPlayer != NULL 874 && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) { 875 mTimeSourceDeltaUs = realTimeUs - mediaTimeUs; 876 } 877 878 int64_t nowUs = mTimeSource->getRealTimeUs() - mTimeSourceDeltaUs; 879 880 int64_t latenessUs = nowUs - timeUs; 881 882 if (latenessUs > 40000) { 883 // We're more than 40ms late. 884 LOGV("we're late by %lld us (%.2f secs)", latenessUs, latenessUs / 1E6); 885 886 mVideoBuffer->release(); 887 mVideoBuffer = NULL; 888 889 postVideoEvent_l(); 890 return; 891 } 892 893 if (latenessUs < -10000) { 894 // We're more than 10ms early. 895 896 postVideoEvent_l(10000); 897 return; 898 } 899 900 if (mVideoRendererIsPreview || mVideoRenderer == NULL) { 901 mVideoRendererIsPreview = false; 902 903 initRenderer_l(); 904 } 905 906 if (mVideoRenderer != NULL) { 907 mVideoRenderer->render(mVideoBuffer); 908 } 909 910 if (mLastVideoBuffer) { 911 mLastVideoBuffer->release(); 912 mLastVideoBuffer = NULL; 913 } 914 mLastVideoBuffer = mVideoBuffer; 915 mVideoBuffer = NULL; 916 917 postVideoEvent_l(); 918} 919 920void AwesomePlayer::postVideoEvent_l(int64_t delayUs) { 921 if (mVideoEventPending) { 922 return; 923 } 924 925 mVideoEventPending = true; 926 mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs); 927} 928 929void AwesomePlayer::postStreamDoneEvent_l(status_t status) { 930 if (mStreamDoneEventPending) { 931 return; 932 } 933 mStreamDoneEventPending = true; 934 935 mStreamDoneStatus = status; 936 mQueue.postEvent(mStreamDoneEvent); 937} 938 939void AwesomePlayer::postBufferingEvent_l() { 940 if (mPrefetcher == NULL) { 941 return; 942 } 943 944 if (mBufferingEventPending) { 945 return; 946 } 947 mBufferingEventPending = true; 948 mQueue.postEventWithDelay(mBufferingEvent, 1000000ll); 949} 950 951void AwesomePlayer::postCheckAudioStatusEvent_l() { 952 if (mAudioStatusEventPending) { 953 return; 954 } 955 mAudioStatusEventPending = true; 956 mQueue.postEventWithDelay(mCheckAudioStatusEvent, 100000ll); 957} 958 959void AwesomePlayer::onCheckAudioStatus() { 960 Mutex::Autolock autoLock(mLock); 961 if (!mAudioStatusEventPending) { 962 // Event was dispatched and while we were blocking on the mutex, 963 // has already been cancelled. 964 return; 965 } 966 967 mAudioStatusEventPending = false; 968 969 if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) { 970 mWatchForAudioSeekComplete = false; 971 notifyListener_l(MEDIA_SEEK_COMPLETE); 972 } 973 974 status_t finalStatus; 975 if (mWatchForAudioEOS && mAudioPlayer->reachedEOS(&finalStatus)) { 976 mWatchForAudioEOS = false; 977 postStreamDoneEvent_l(finalStatus); 978 } 979 980 postCheckAudioStatusEvent_l(); 981} 982 983status_t AwesomePlayer::prepare() { 984 Mutex::Autolock autoLock(mLock); 985 return prepare_l(); 986} 987 988status_t AwesomePlayer::prepare_l() { 989 if (mFlags & PREPARED) { 990 return OK; 991 } 992 993 if (mFlags & PREPARING) { 994 return UNKNOWN_ERROR; 995 } 996 997 mIsAsyncPrepare = false; 998 status_t err = prepareAsync_l(); 999 1000 if (err != OK) { 1001 return err; 1002 } 1003 1004 while (mFlags & PREPARING) { 1005 mPreparedCondition.wait(mLock); 1006 } 1007 1008 return mPrepareResult; 1009} 1010 1011status_t AwesomePlayer::prepareAsync() { 1012 Mutex::Autolock autoLock(mLock); 1013 1014 if (mFlags & PREPARING) { 1015 return UNKNOWN_ERROR; // async prepare already pending 1016 } 1017 1018 mIsAsyncPrepare = true; 1019 return prepareAsync_l(); 1020} 1021 1022status_t AwesomePlayer::prepareAsync_l() { 1023 if (mFlags & PREPARING) { 1024 return UNKNOWN_ERROR; // async prepare already pending 1025 } 1026 1027 if (!mQueueStarted) { 1028 mQueue.start(); 1029 mQueueStarted = true; 1030 } 1031 1032 mFlags |= PREPARING; 1033 mAsyncPrepareEvent = new AwesomeEvent( 1034 this, &AwesomePlayer::onPrepareAsyncEvent); 1035 1036 mQueue.postEvent(mAsyncPrepareEvent); 1037 1038 return OK; 1039} 1040 1041status_t AwesomePlayer::finishSetDataSource_l() { 1042 sp<DataSource> dataSource = 1043 DataSource::CreateFromURI(mUri.string(), &mUriHeaders); 1044 1045 if (dataSource == NULL) { 1046 return UNKNOWN_ERROR; 1047 } 1048 1049 sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource); 1050 1051 if (extractor == NULL) { 1052 return UNKNOWN_ERROR; 1053 } 1054 1055 if (dataSource->flags() & DataSource::kWantsPrefetching) { 1056 mPrefetcher = new Prefetcher; 1057 } 1058 1059 return setDataSource_l(extractor); 1060} 1061 1062void AwesomePlayer::abortPrepare(status_t err) { 1063 CHECK(err != OK); 1064 1065 if (mIsAsyncPrepare) { 1066 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err); 1067 } 1068 1069 mPrepareResult = err; 1070 mFlags &= ~PREPARING; 1071 mAsyncPrepareEvent = NULL; 1072 mPreparedCondition.broadcast(); 1073} 1074 1075void AwesomePlayer::onPrepareAsyncEvent() { 1076 sp<Prefetcher> prefetcher; 1077 1078 { 1079 Mutex::Autolock autoLock(mLock); 1080 1081 if (mUri.size() > 0) { 1082 status_t err = finishSetDataSource_l(); 1083 1084 if (err != OK) { 1085 abortPrepare(err); 1086 return; 1087 } 1088 } 1089 1090 if (mVideoTrack != NULL && mVideoSource == NULL) { 1091 status_t err = initVideoDecoder(); 1092 1093 if (err != OK) { 1094 abortPrepare(err); 1095 return; 1096 } 1097 } 1098 1099 if (mAudioTrack != NULL && mAudioSource == NULL) { 1100 status_t err = initAudioDecoder(); 1101 1102 if (err != OK) { 1103 abortPrepare(err); 1104 return; 1105 } 1106 } 1107 1108 prefetcher = mPrefetcher; 1109 } 1110 1111 if (prefetcher != NULL) { 1112 prefetcher->prepare(); 1113 prefetcher.clear(); 1114 } 1115 1116 Mutex::Autolock autoLock(mLock); 1117 1118 if (mIsAsyncPrepare) { 1119 if (mVideoWidth < 0 || mVideoHeight < 0) { 1120 notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0); 1121 } else { 1122 notifyListener_l(MEDIA_SET_VIDEO_SIZE, mVideoWidth, mVideoHeight); 1123 } 1124 1125 notifyListener_l(MEDIA_PREPARED); 1126 } 1127 1128 mPrepareResult = OK; 1129 mFlags &= ~PREPARING; 1130 mFlags |= PREPARED; 1131 mAsyncPrepareEvent = NULL; 1132 mPreparedCondition.broadcast(); 1133} 1134 1135status_t AwesomePlayer::suspend() { 1136 LOGI("suspend"); 1137 Mutex::Autolock autoLock(mLock); 1138 1139 if (mSuspensionState != NULL) { 1140 return INVALID_OPERATION; 1141 } 1142 1143 while (mFlags & PREPARING) { 1144 mPreparedCondition.wait(mLock); 1145 } 1146 1147 SuspensionState *state = new SuspensionState; 1148 state->mUri = mUri; 1149 state->mUriHeaders = mUriHeaders; 1150 state->mFileSource = mFileSource; 1151 1152 state->mFlags = mFlags & (PLAYING | LOOPING | AT_EOS); 1153 getPosition_l(&state->mPositionUs); 1154 1155 if (mLastVideoBuffer) { 1156 size_t size = mLastVideoBuffer->range_length(); 1157 if (size) { 1158 state->mLastVideoFrameSize = size; 1159 state->mLastVideoFrame = malloc(size); 1160 memcpy(state->mLastVideoFrame, 1161 (const uint8_t *)mLastVideoBuffer->data() 1162 + mLastVideoBuffer->range_offset(), 1163 size); 1164 1165 state->mVideoWidth = mVideoWidth; 1166 state->mVideoHeight = mVideoHeight; 1167 1168 sp<MetaData> meta = mVideoSource->getFormat(); 1169 CHECK(meta->findInt32(kKeyColorFormat, &state->mColorFormat)); 1170 CHECK(meta->findInt32(kKeyWidth, &state->mDecodedWidth)); 1171 CHECK(meta->findInt32(kKeyHeight, &state->mDecodedHeight)); 1172 } 1173 } 1174 1175 reset_l(); 1176 1177 mSuspensionState = state; 1178 1179 return OK; 1180} 1181 1182status_t AwesomePlayer::resume() { 1183 LOGI("resume"); 1184 Mutex::Autolock autoLock(mLock); 1185 1186 if (mSuspensionState == NULL) { 1187 return INVALID_OPERATION; 1188 } 1189 1190 SuspensionState *state = mSuspensionState; 1191 mSuspensionState = NULL; 1192 1193 status_t err; 1194 if (state->mFileSource != NULL) { 1195 err = setDataSource_l(state->mFileSource); 1196 1197 if (err == OK) { 1198 mFileSource = state->mFileSource; 1199 } 1200 } else { 1201 err = setDataSource_l(state->mUri, &state->mUriHeaders); 1202 } 1203 1204 if (err != OK) { 1205 delete state; 1206 state = NULL; 1207 1208 return err; 1209 } 1210 1211 seekTo_l(state->mPositionUs); 1212 1213 mFlags = state->mFlags & (LOOPING | AT_EOS); 1214 1215 if (state->mLastVideoFrame && mISurface != NULL) { 1216 mVideoRenderer = 1217 new AwesomeLocalRenderer( 1218 true, // previewOnly 1219 "", 1220 (OMX_COLOR_FORMATTYPE)state->mColorFormat, 1221 mISurface, 1222 state->mVideoWidth, 1223 state->mVideoHeight, 1224 state->mDecodedWidth, 1225 state->mDecodedHeight); 1226 1227 mVideoRendererIsPreview = true; 1228 1229 ((AwesomeLocalRenderer *)mVideoRenderer.get())->render( 1230 state->mLastVideoFrame, state->mLastVideoFrameSize); 1231 } 1232 1233 if (state->mFlags & PLAYING) { 1234 play_l(); 1235 } 1236 1237 delete state; 1238 state = NULL; 1239 1240 return OK; 1241} 1242 1243} // namespace android 1244 1245