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