AwesomePlayer.cpp revision b371426ce4cf2fa6d8c3d1903b61322feb165d35
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/ARTSPController.h" 24#include "include/AwesomePlayer.h" 25#include "include/LiveSource.h" 26#include "include/SoftwareRenderer.h" 27#include "include/NuCachedSource2.h" 28#include "include/ThrottledSource.h" 29#include "include/MPEG2TSExtractor.h" 30 31#include "ARTPSession.h" 32#include "APacketSource.h" 33#include "ASessionDescription.h" 34#include "UDPPusher.h" 35 36#include <binder/IPCThreadState.h> 37#include <media/stagefright/AudioPlayer.h> 38#include <media/stagefright/DataSource.h> 39#include <media/stagefright/FileSource.h> 40#include <media/stagefright/MediaBuffer.h> 41#include <media/stagefright/MediaDefs.h> 42#include <media/stagefright/MediaExtractor.h> 43#include <media/stagefright/MediaDebug.h> 44#include <media/stagefright/MediaSource.h> 45#include <media/stagefright/MetaData.h> 46#include <media/stagefright/OMXCodec.h> 47 48#include <surfaceflinger/Surface.h> 49 50#include <media/stagefright/foundation/ALooper.h> 51 52namespace android { 53 54static int64_t kLowWaterMarkUs = 2000000ll; // 2secs 55static int64_t kHighWaterMarkUs = 10000000ll; // 10secs 56 57struct AwesomeEvent : public TimedEventQueue::Event { 58 AwesomeEvent( 59 AwesomePlayer *player, 60 void (AwesomePlayer::*method)()) 61 : mPlayer(player), 62 mMethod(method) { 63 } 64 65protected: 66 virtual ~AwesomeEvent() {} 67 68 virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) { 69 (mPlayer->*mMethod)(); 70 } 71 72private: 73 AwesomePlayer *mPlayer; 74 void (AwesomePlayer::*mMethod)(); 75 76 AwesomeEvent(const AwesomeEvent &); 77 AwesomeEvent &operator=(const AwesomeEvent &); 78}; 79 80struct AwesomeRemoteRenderer : public AwesomeRenderer { 81 AwesomeRemoteRenderer(const sp<IOMXRenderer> &target) 82 : mTarget(target) { 83 } 84 85 virtual void render(MediaBuffer *buffer) { 86 void *id; 87 if (buffer->meta_data()->findPointer(kKeyBufferID, &id)) { 88 mTarget->render((IOMX::buffer_id)id); 89 } 90 } 91 92private: 93 sp<IOMXRenderer> mTarget; 94 95 AwesomeRemoteRenderer(const AwesomeRemoteRenderer &); 96 AwesomeRemoteRenderer &operator=(const AwesomeRemoteRenderer &); 97}; 98 99struct AwesomeLocalRenderer : public AwesomeRenderer { 100 AwesomeLocalRenderer( 101 bool previewOnly, 102 const char *componentName, 103 OMX_COLOR_FORMATTYPE colorFormat, 104 const sp<ISurface> &isurface, 105 const sp<Surface> &surface, 106 size_t displayWidth, size_t displayHeight, 107 size_t decodedWidth, size_t decodedHeight) 108 : mTarget(NULL), 109 mLibHandle(NULL) { 110 init(previewOnly, componentName, 111 colorFormat, isurface, surface, displayWidth, 112 displayHeight, decodedWidth, decodedHeight); 113 } 114 115 virtual void render(MediaBuffer *buffer) { 116 render((const uint8_t *)buffer->data() + buffer->range_offset(), 117 buffer->range_length()); 118 } 119 120 void render(const void *data, size_t size) { 121 mTarget->render(data, size, NULL); 122 } 123 124protected: 125 virtual ~AwesomeLocalRenderer() { 126 delete mTarget; 127 mTarget = NULL; 128 129 if (mLibHandle) { 130 dlclose(mLibHandle); 131 mLibHandle = NULL; 132 } 133 } 134 135private: 136 VideoRenderer *mTarget; 137 void *mLibHandle; 138 139 void init( 140 bool previewOnly, 141 const char *componentName, 142 OMX_COLOR_FORMATTYPE colorFormat, 143 const sp<ISurface> &isurface, 144 const sp<Surface> &surface, 145 size_t displayWidth, size_t displayHeight, 146 size_t decodedWidth, size_t decodedHeight); 147 148 AwesomeLocalRenderer(const AwesomeLocalRenderer &); 149 AwesomeLocalRenderer &operator=(const AwesomeLocalRenderer &);; 150}; 151 152void AwesomeLocalRenderer::init( 153 bool previewOnly, 154 const char *componentName, 155 OMX_COLOR_FORMATTYPE colorFormat, 156 const sp<ISurface> &isurface, 157 const sp<Surface> &surface, 158 size_t displayWidth, size_t displayHeight, 159 size_t decodedWidth, size_t decodedHeight) { 160 if (!previewOnly) { 161 // We will stick to the vanilla software-color-converting renderer 162 // for "previewOnly" mode, to avoid unneccessarily switching overlays 163 // more often than necessary. 164 165 mLibHandle = dlopen("libstagefrighthw.so", RTLD_NOW); 166 167 if (mLibHandle) { 168 typedef VideoRenderer *(*CreateRendererFunc)( 169 const sp<ISurface> &surface, 170 const char *componentName, 171 OMX_COLOR_FORMATTYPE colorFormat, 172 size_t displayWidth, size_t displayHeight, 173 size_t decodedWidth, size_t decodedHeight); 174 175 CreateRendererFunc func = 176 (CreateRendererFunc)dlsym( 177 mLibHandle, 178 "_Z14createRendererRKN7android2spINS_8ISurfaceEEEPKc20" 179 "OMX_COLOR_FORMATTYPEjjjj"); 180 181 if (func) { 182 mTarget = 183 (*func)(isurface, componentName, colorFormat, 184 displayWidth, displayHeight, 185 decodedWidth, decodedHeight); 186 } 187 } 188 } 189 190 if (mTarget == NULL) { 191 mTarget = new SoftwareRenderer( 192 colorFormat, surface, displayWidth, displayHeight, 193 decodedWidth, decodedHeight); 194 } 195} 196 197struct AwesomeNativeWindowRenderer : public AwesomeRenderer { 198 AwesomeNativeWindowRenderer(const sp<ANativeWindow> &nativeWindow) 199 : mNativeWindow(nativeWindow) { 200 } 201 202 virtual void render(MediaBuffer *buffer) { 203 status_t err = mNativeWindow->queueBuffer( 204 mNativeWindow.get(), buffer->graphicBuffer().get()); 205 if (err != 0) { 206 LOGE("queueBuffer failed with error %s (%d)", strerror(-err), 207 -err); 208 return; 209 } 210 211 sp<MetaData> metaData = buffer->meta_data(); 212 metaData->setInt32(kKeyRendered, 1); 213 } 214 215protected: 216 virtual ~AwesomeNativeWindowRenderer() {} 217 218private: 219 sp<ANativeWindow> mNativeWindow; 220 221 AwesomeNativeWindowRenderer(const AwesomeNativeWindowRenderer &); 222 AwesomeNativeWindowRenderer &operator=( 223 const AwesomeNativeWindowRenderer &); 224}; 225 226AwesomePlayer::AwesomePlayer() 227 : mQueueStarted(false), 228 mTimeSource(NULL), 229 mVideoRendererIsPreview(false), 230 mAudioPlayer(NULL), 231 mFlags(0), 232 mExtractorFlags(0), 233 mLastVideoBuffer(NULL), 234 mVideoBuffer(NULL), 235 mSuspensionState(NULL), 236 mDecryptHandle(NULL) { 237 CHECK_EQ(mClient.connect(), OK); 238 239 DataSource::RegisterDefaultSniffers(); 240 241 mVideoEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoEvent); 242 mVideoEventPending = false; 243 mStreamDoneEvent = new AwesomeEvent(this, &AwesomePlayer::onStreamDone); 244 mStreamDoneEventPending = false; 245 mBufferingEvent = new AwesomeEvent(this, &AwesomePlayer::onBufferingUpdate); 246 mBufferingEventPending = false; 247 248 mCheckAudioStatusEvent = new AwesomeEvent( 249 this, &AwesomePlayer::onCheckAudioStatus); 250 251 mAudioStatusEventPending = false; 252 253 reset(); 254} 255 256AwesomePlayer::~AwesomePlayer() { 257 if (mQueueStarted) { 258 mQueue.stop(); 259 } 260 261 reset(); 262 263 mClient.disconnect(); 264} 265 266void AwesomePlayer::cancelPlayerEvents(bool keepBufferingGoing) { 267 mQueue.cancelEvent(mVideoEvent->eventID()); 268 mVideoEventPending = false; 269 mQueue.cancelEvent(mStreamDoneEvent->eventID()); 270 mStreamDoneEventPending = false; 271 mQueue.cancelEvent(mCheckAudioStatusEvent->eventID()); 272 mAudioStatusEventPending = false; 273 274 if (!keepBufferingGoing) { 275 mQueue.cancelEvent(mBufferingEvent->eventID()); 276 mBufferingEventPending = false; 277 } 278} 279 280void AwesomePlayer::setListener(const wp<MediaPlayerBase> &listener) { 281 Mutex::Autolock autoLock(mLock); 282 mListener = listener; 283} 284 285status_t AwesomePlayer::setDataSource( 286 const char *uri, const KeyedVector<String8, String8> *headers) { 287 Mutex::Autolock autoLock(mLock); 288 return setDataSource_l(uri, headers); 289} 290 291status_t AwesomePlayer::setDataSource_l( 292 const char *uri, const KeyedVector<String8, String8> *headers) { 293 reset_l(); 294 295 mUri = uri; 296 297 if (headers) { 298 mUriHeaders = *headers; 299 } 300 301 // The actual work will be done during preparation in the call to 302 // ::finishSetDataSource_l to avoid blocking the calling thread in 303 // setDataSource for any significant time. 304 305 return OK; 306} 307 308status_t AwesomePlayer::setDataSource( 309 int fd, int64_t offset, int64_t length) { 310 Mutex::Autolock autoLock(mLock); 311 312 reset_l(); 313 314 sp<DataSource> dataSource = new FileSource(fd, offset, length); 315 316 status_t err = dataSource->initCheck(); 317 318 if (err != OK) { 319 return err; 320 } 321 322 mFileSource = dataSource; 323 324 return setDataSource_l(dataSource); 325} 326 327status_t AwesomePlayer::setDataSource_l( 328 const sp<DataSource> &dataSource) { 329 sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource); 330 331 if (extractor == NULL) { 332 return UNKNOWN_ERROR; 333 } 334 335 dataSource->getDrmInfo(&mDecryptHandle, &mDrmManagerClient); 336 if (mDecryptHandle != NULL 337 && RightsStatus::RIGHTS_VALID != mDecryptHandle->status) { 338 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_NO_LICENSE); 339 } 340 341 return setDataSource_l(extractor); 342} 343 344status_t AwesomePlayer::setDataSource_l(const sp<MediaExtractor> &extractor) { 345 // Attempt to approximate overall stream bitrate by summing all 346 // tracks' individual bitrates, if not all of them advertise bitrate, 347 // we have to fail. 348 349 int64_t totalBitRate = 0; 350 351 for (size_t i = 0; i < extractor->countTracks(); ++i) { 352 sp<MetaData> meta = extractor->getTrackMetaData(i); 353 354 int32_t bitrate; 355 if (!meta->findInt32(kKeyBitRate, &bitrate)) { 356 totalBitRate = -1; 357 break; 358 } 359 360 totalBitRate += bitrate; 361 } 362 363 mBitrate = totalBitRate; 364 365 LOGV("mBitrate = %lld bits/sec", mBitrate); 366 367 bool haveAudio = false; 368 bool haveVideo = false; 369 for (size_t i = 0; i < extractor->countTracks(); ++i) { 370 sp<MetaData> meta = extractor->getTrackMetaData(i); 371 372 const char *mime; 373 CHECK(meta->findCString(kKeyMIMEType, &mime)); 374 375 if (!haveVideo && !strncasecmp(mime, "video/", 6)) { 376 setVideoSource(extractor->getTrack(i)); 377 haveVideo = true; 378 } else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) { 379 setAudioSource(extractor->getTrack(i)); 380 haveAudio = true; 381 382 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) { 383 // Only do this for vorbis audio, none of the other audio 384 // formats even support this ringtone specific hack and 385 // retrieving the metadata on some extractors may turn out 386 // to be very expensive. 387 sp<MetaData> fileMeta = extractor->getMetaData(); 388 int32_t loop; 389 if (fileMeta != NULL 390 && fileMeta->findInt32(kKeyAutoLoop, &loop) && loop != 0) { 391 mFlags |= AUTO_LOOPING; 392 } 393 } 394 } 395 396 if (haveAudio && haveVideo) { 397 break; 398 } 399 } 400 401 if (!haveAudio && !haveVideo) { 402 return UNKNOWN_ERROR; 403 } 404 405 mExtractorFlags = extractor->flags(); 406 407 return OK; 408} 409 410void AwesomePlayer::reset() { 411 Mutex::Autolock autoLock(mLock); 412 reset_l(); 413} 414 415void AwesomePlayer::reset_l() { 416 if (mDecryptHandle != NULL) { 417 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, 418 Playback::STOP, 0); 419 mDrmManagerClient->closeDecryptSession(mDecryptHandle); 420 mDecryptHandle = NULL; 421 mDrmManagerClient = NULL; 422 } 423 424 if (mFlags & PREPARING) { 425 mFlags |= PREPARE_CANCELLED; 426 if (mConnectingDataSource != NULL) { 427 LOGI("interrupting the connection process"); 428 mConnectingDataSource->disconnect(); 429 } 430 431 if (mFlags & PREPARING_CONNECTED) { 432 // We are basically done preparing, we're just buffering 433 // enough data to start playback, we can safely interrupt that. 434 finishAsyncPrepare_l(); 435 } 436 } 437 438 while (mFlags & PREPARING) { 439 mPreparedCondition.wait(mLock); 440 } 441 442 cancelPlayerEvents(); 443 444 mCachedSource.clear(); 445 mAudioTrack.clear(); 446 mVideoTrack.clear(); 447 448 // Shutdown audio first, so that the respone to the reset request 449 // appears to happen instantaneously as far as the user is concerned 450 // If we did this later, audio would continue playing while we 451 // shutdown the video-related resources and the player appear to 452 // not be as responsive to a reset request. 453 if (mAudioPlayer == NULL && mAudioSource != NULL) { 454 // If we had an audio player, it would have effectively 455 // taken possession of the audio source and stopped it when 456 // _it_ is stopped. Otherwise this is still our responsibility. 457 mAudioSource->stop(); 458 } 459 mAudioSource.clear(); 460 461 mTimeSource = NULL; 462 463 delete mAudioPlayer; 464 mAudioPlayer = NULL; 465 466 mVideoRenderer.clear(); 467 468 if (mLastVideoBuffer) { 469 mLastVideoBuffer->release(); 470 mLastVideoBuffer = NULL; 471 } 472 473 if (mVideoBuffer) { 474 mVideoBuffer->release(); 475 mVideoBuffer = NULL; 476 } 477 478 if (mRTSPController != NULL) { 479 mRTSPController->disconnect(); 480 mRTSPController.clear(); 481 } 482 483 mRTPPusher.clear(); 484 mRTCPPusher.clear(); 485 mRTPSession.clear(); 486 487 if (mVideoSource != NULL) { 488 mVideoSource->stop(); 489 490 // The following hack is necessary to ensure that the OMX 491 // component is completely released by the time we may try 492 // to instantiate it again. 493 wp<MediaSource> tmp = mVideoSource; 494 mVideoSource.clear(); 495 while (tmp.promote() != NULL) { 496 usleep(1000); 497 } 498 IPCThreadState::self()->flushCommands(); 499 } 500 501 mDurationUs = -1; 502 mFlags = 0; 503 mExtractorFlags = 0; 504 mVideoWidth = mVideoHeight = -1; 505 mTimeSourceDeltaUs = 0; 506 mVideoTimeUs = 0; 507 508 mSeeking = false; 509 mSeekNotificationSent = false; 510 mSeekTimeUs = 0; 511 512 mUri.setTo(""); 513 mUriHeaders.clear(); 514 515 mFileSource.clear(); 516 517 delete mSuspensionState; 518 mSuspensionState = NULL; 519 520 mBitrate = -1; 521} 522 523void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) { 524 if (mListener != NULL) { 525 sp<MediaPlayerBase> listener = mListener.promote(); 526 527 if (listener != NULL) { 528 listener->sendEvent(msg, ext1, ext2); 529 } 530 } 531} 532 533bool AwesomePlayer::getBitrate(int64_t *bitrate) { 534 off_t size; 535 if (mDurationUs >= 0 && mCachedSource != NULL 536 && mCachedSource->getSize(&size) == OK) { 537 *bitrate = size * 8000000ll / mDurationUs; // in bits/sec 538 return true; 539 } 540 541 if (mBitrate >= 0) { 542 *bitrate = mBitrate; 543 return true; 544 } 545 546 *bitrate = 0; 547 548 return false; 549} 550 551// Returns true iff cached duration is available/applicable. 552bool AwesomePlayer::getCachedDuration_l(int64_t *durationUs, bool *eos) { 553 int64_t bitrate; 554 555 if (mRTSPController != NULL) { 556 *durationUs = mRTSPController->getQueueDurationUs(eos); 557 return true; 558 } else if (mCachedSource != NULL && getBitrate(&bitrate)) { 559 size_t cachedDataRemaining = mCachedSource->approxDataRemaining(eos); 560 *durationUs = cachedDataRemaining * 8000000ll / bitrate; 561 return true; 562 } 563 564 return false; 565} 566 567void AwesomePlayer::onBufferingUpdate() { 568 Mutex::Autolock autoLock(mLock); 569 if (!mBufferingEventPending) { 570 return; 571 } 572 mBufferingEventPending = false; 573 574 if (mCachedSource != NULL) { 575 bool eos; 576 size_t cachedDataRemaining = mCachedSource->approxDataRemaining(&eos); 577 578 if (eos) { 579 notifyListener_l(MEDIA_BUFFERING_UPDATE, 100); 580 if (mFlags & PREPARING) { 581 LOGV("cache has reached EOS, prepare is done."); 582 finishAsyncPrepare_l(); 583 } 584 } else { 585 int64_t bitrate; 586 if (getBitrate(&bitrate)) { 587 size_t cachedSize = mCachedSource->cachedSize(); 588 int64_t cachedDurationUs = cachedSize * 8000000ll / bitrate; 589 590 int percentage = 100.0 * (double)cachedDurationUs / mDurationUs; 591 if (percentage > 100) { 592 percentage = 100; 593 } 594 595 notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage); 596 } else { 597 // We don't know the bitrate of the stream, use absolute size 598 // limits to maintain the cache. 599 600 const size_t kLowWaterMarkBytes = 40000; 601 const size_t kHighWaterMarkBytes = 200000; 602 603 if ((mFlags & PLAYING) && !eos 604 && (cachedDataRemaining < kLowWaterMarkBytes)) { 605 LOGI("cache is running low (< %d) , pausing.", 606 kLowWaterMarkBytes); 607 mFlags |= CACHE_UNDERRUN; 608 pause_l(); 609 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START); 610 } else if (eos || cachedDataRemaining > kHighWaterMarkBytes) { 611 if (mFlags & CACHE_UNDERRUN) { 612 LOGI("cache has filled up (> %d), resuming.", 613 kHighWaterMarkBytes); 614 mFlags &= ~CACHE_UNDERRUN; 615 play_l(); 616 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END); 617 } else if (mFlags & PREPARING) { 618 LOGV("cache has filled up (> %d), prepare is done", 619 kHighWaterMarkBytes); 620 finishAsyncPrepare_l(); 621 } 622 } 623 } 624 } 625 } 626 627 int64_t cachedDurationUs; 628 bool eos; 629 if (getCachedDuration_l(&cachedDurationUs, &eos)) { 630 if ((mFlags & PLAYING) && !eos 631 && (cachedDurationUs < kLowWaterMarkUs)) { 632 LOGI("cache is running low (%.2f secs) , pausing.", 633 cachedDurationUs / 1E6); 634 mFlags |= CACHE_UNDERRUN; 635 pause_l(); 636 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START); 637 } else if (eos || cachedDurationUs > kHighWaterMarkUs) { 638 if (mFlags & CACHE_UNDERRUN) { 639 LOGI("cache has filled up (%.2f secs), resuming.", 640 cachedDurationUs / 1E6); 641 mFlags &= ~CACHE_UNDERRUN; 642 play_l(); 643 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END); 644 } else if (mFlags & PREPARING) { 645 LOGV("cache has filled up (%.2f secs), prepare is done", 646 cachedDurationUs / 1E6); 647 finishAsyncPrepare_l(); 648 } 649 } 650 } 651 652 postBufferingEvent_l(); 653} 654 655void AwesomePlayer::partial_reset_l() { 656 // Only reset the video renderer and shut down the video decoder. 657 // Then instantiate a new video decoder and resume video playback. 658 659 mVideoRenderer.clear(); 660 661 if (mLastVideoBuffer) { 662 mLastVideoBuffer->release(); 663 mLastVideoBuffer = NULL; 664 } 665 666 if (mVideoBuffer) { 667 mVideoBuffer->release(); 668 mVideoBuffer = NULL; 669 } 670 671 { 672 mVideoSource->stop(); 673 674 // The following hack is necessary to ensure that the OMX 675 // component is completely released by the time we may try 676 // to instantiate it again. 677 wp<MediaSource> tmp = mVideoSource; 678 mVideoSource.clear(); 679 while (tmp.promote() != NULL) { 680 usleep(1000); 681 } 682 IPCThreadState::self()->flushCommands(); 683 } 684 685 CHECK_EQ(OK, initVideoDecoder(OMXCodec::kIgnoreCodecSpecificData)); 686} 687 688void AwesomePlayer::onStreamDone() { 689 // Posted whenever any stream finishes playing. 690 691 Mutex::Autolock autoLock(mLock); 692 if (!mStreamDoneEventPending) { 693 return; 694 } 695 mStreamDoneEventPending = false; 696 697 if (mStreamDoneStatus == INFO_DISCONTINUITY) { 698 // This special status is returned because an http live stream's 699 // video stream switched to a different bandwidth at this point 700 // and future data may have been encoded using different parameters. 701 // This requires us to shutdown the video decoder and reinstantiate 702 // a fresh one. 703 704 LOGV("INFO_DISCONTINUITY"); 705 706 CHECK(mVideoSource != NULL); 707 708 partial_reset_l(); 709 postVideoEvent_l(); 710 return; 711 } else if (mStreamDoneStatus != ERROR_END_OF_STREAM) { 712 LOGV("MEDIA_ERROR %d", mStreamDoneStatus); 713 714 notifyListener_l( 715 MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, mStreamDoneStatus); 716 717 pause_l(true /* at eos */); 718 719 mFlags |= AT_EOS; 720 return; 721 } 722 723 const bool allDone = 724 (mVideoSource == NULL || (mFlags & VIDEO_AT_EOS)) 725 && (mAudioSource == NULL || (mFlags & AUDIO_AT_EOS)); 726 727 if (!allDone) { 728 return; 729 } 730 731 if (mFlags & (LOOPING | AUTO_LOOPING)) { 732 seekTo_l(0); 733 734 if (mVideoSource != NULL) { 735 postVideoEvent_l(); 736 } 737 } else { 738 LOGV("MEDIA_PLAYBACK_COMPLETE"); 739 notifyListener_l(MEDIA_PLAYBACK_COMPLETE); 740 741 pause_l(true /* at eos */); 742 743 mFlags |= AT_EOS; 744 } 745} 746 747status_t AwesomePlayer::play() { 748 Mutex::Autolock autoLock(mLock); 749 750 mFlags &= ~CACHE_UNDERRUN; 751 752 return play_l(); 753} 754 755status_t AwesomePlayer::play_l() { 756 if (mFlags & PLAYING) { 757 return OK; 758 } 759 760 if (!(mFlags & PREPARED)) { 761 status_t err = prepare_l(); 762 763 if (err != OK) { 764 return err; 765 } 766 } 767 768 mFlags |= PLAYING; 769 mFlags |= FIRST_FRAME; 770 771 bool deferredAudioSeek = false; 772 773 if (mAudioSource != NULL) { 774 if (mAudioPlayer == NULL) { 775 if (mAudioSink != NULL) { 776 mAudioPlayer = new AudioPlayer(mAudioSink, this); 777 mAudioPlayer->setSource(mAudioSource); 778 779 // We've already started the MediaSource in order to enable 780 // the prefetcher to read its data. 781 status_t err = mAudioPlayer->start( 782 true /* sourceAlreadyStarted */); 783 784 if (err != OK) { 785 delete mAudioPlayer; 786 mAudioPlayer = NULL; 787 788 mFlags &= ~(PLAYING | FIRST_FRAME); 789 790 return err; 791 } 792 793 mTimeSource = mAudioPlayer; 794 795 deferredAudioSeek = true; 796 797 mWatchForAudioSeekComplete = false; 798 mWatchForAudioEOS = true; 799 } 800 } else { 801 mAudioPlayer->resume(); 802 } 803 } 804 805 if (mTimeSource == NULL && mAudioPlayer == NULL) { 806 mTimeSource = &mSystemTimeSource; 807 } 808 809 if (mVideoSource != NULL) { 810 // Kick off video playback 811 postVideoEvent_l(); 812 } 813 814 if (deferredAudioSeek) { 815 // If there was a seek request while we were paused 816 // and we're just starting up again, honor the request now. 817 seekAudioIfNecessary_l(); 818 } 819 820 if (mFlags & AT_EOS) { 821 // Legacy behaviour, if a stream finishes playing and then 822 // is started again, we play from the start... 823 seekTo_l(0); 824 } 825 826 if (mDecryptHandle != NULL) { 827 int64_t position; 828 getPosition(&position); 829 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, 830 Playback::START, position / 1000); 831 } 832 833 return OK; 834} 835 836void AwesomePlayer::notifyVideoSize_l() { 837 sp<MetaData> meta = mVideoSource->getFormat(); 838 839 int32_t decodedWidth, decodedHeight; 840 CHECK(meta->findInt32(kKeyWidth, &decodedWidth)); 841 CHECK(meta->findInt32(kKeyHeight, &decodedHeight)); 842 843 notifyListener_l(MEDIA_SET_VIDEO_SIZE, decodedWidth, decodedHeight); 844} 845 846void AwesomePlayer::initRenderer_l() { 847 if (mSurface != NULL || mISurface != NULL) { 848 sp<MetaData> meta = mVideoSource->getFormat(); 849 850 int32_t format; 851 const char *component; 852 int32_t decodedWidth, decodedHeight; 853 CHECK(meta->findInt32(kKeyColorFormat, &format)); 854 CHECK(meta->findCString(kKeyDecoderComponent, &component)); 855 CHECK(meta->findInt32(kKeyWidth, &decodedWidth)); 856 CHECK(meta->findInt32(kKeyHeight, &decodedHeight)); 857 858 mVideoRenderer.clear(); 859 860 // Must ensure that mVideoRenderer's destructor is actually executed 861 // before creating a new one. 862 IPCThreadState::self()->flushCommands(); 863 864 if (mSurface != NULL) { 865 if (strncmp(component, "OMX.", 4) == 0) { 866 // Hardware decoders avoid the CPU color conversion by decoding 867 // directly to ANativeBuffers, so we must use a renderer that 868 // just pushes those buffers to the ANativeWindow. 869 mVideoRenderer = new AwesomeNativeWindowRenderer(mSurface); 870 } else { 871 // Other decoders are instantiated locally and as a consequence 872 // allocate their buffers in local address space. This renderer 873 // then performs a color conversion and copy to get the data 874 // into the ANativeBuffer. 875 mVideoRenderer = new AwesomeLocalRenderer( 876 false, // previewOnly 877 component, 878 (OMX_COLOR_FORMATTYPE)format, 879 mISurface, 880 mSurface, 881 mVideoWidth, mVideoHeight, 882 decodedWidth, decodedHeight); 883 } 884 } else { 885 // Our OMX codecs allocate buffers on the media_server side 886 // therefore they require a remote IOMXRenderer that knows how 887 // to display them. 888 mVideoRenderer = new AwesomeRemoteRenderer( 889 mClient.interface()->createRenderer( 890 mISurface, component, 891 (OMX_COLOR_FORMATTYPE)format, 892 decodedWidth, decodedHeight, 893 mVideoWidth, mVideoHeight)); 894 } 895 } 896} 897 898status_t AwesomePlayer::pause() { 899 Mutex::Autolock autoLock(mLock); 900 901 mFlags &= ~CACHE_UNDERRUN; 902 903 return pause_l(); 904} 905 906status_t AwesomePlayer::pause_l(bool at_eos) { 907 if (!(mFlags & PLAYING)) { 908 return OK; 909 } 910 911 cancelPlayerEvents(true /* keepBufferingGoing */); 912 913 if (mAudioPlayer != NULL) { 914 if (at_eos) { 915 // If we played the audio stream to completion we 916 // want to make sure that all samples remaining in the audio 917 // track's queue are played out. 918 mAudioPlayer->pause(true /* playPendingSamples */); 919 } else { 920 mAudioPlayer->pause(); 921 } 922 } 923 924 mFlags &= ~PLAYING; 925 926 if (mDecryptHandle != NULL) { 927 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, 928 Playback::PAUSE, 0); 929 } 930 931 return OK; 932} 933 934bool AwesomePlayer::isPlaying() const { 935 return (mFlags & PLAYING) || (mFlags & CACHE_UNDERRUN); 936} 937 938void AwesomePlayer::setISurface(const sp<ISurface> &isurface) { 939 Mutex::Autolock autoLock(mLock); 940 941 mISurface = isurface; 942} 943 944void AwesomePlayer::setSurface(const sp<Surface> &surface) { 945 Mutex::Autolock autoLock(mLock); 946 947 mSurface = surface; 948} 949 950void AwesomePlayer::setAudioSink( 951 const sp<MediaPlayerBase::AudioSink> &audioSink) { 952 Mutex::Autolock autoLock(mLock); 953 954 mAudioSink = audioSink; 955} 956 957status_t AwesomePlayer::setLooping(bool shouldLoop) { 958 Mutex::Autolock autoLock(mLock); 959 960 mFlags = mFlags & ~LOOPING; 961 962 if (shouldLoop) { 963 mFlags |= LOOPING; 964 } 965 966 return OK; 967} 968 969status_t AwesomePlayer::getDuration(int64_t *durationUs) { 970 Mutex::Autolock autoLock(mMiscStateLock); 971 972 if (mDurationUs < 0) { 973 return UNKNOWN_ERROR; 974 } 975 976 *durationUs = mDurationUs; 977 978 return OK; 979} 980 981status_t AwesomePlayer::getPosition(int64_t *positionUs) { 982 if (mRTSPController != NULL) { 983 *positionUs = mRTSPController->getNormalPlayTimeUs(); 984 } 985 else if (mSeeking) { 986 *positionUs = mSeekTimeUs; 987 } else if (mVideoSource != NULL) { 988 Mutex::Autolock autoLock(mMiscStateLock); 989 *positionUs = mVideoTimeUs; 990 } else if (mAudioPlayer != NULL) { 991 *positionUs = mAudioPlayer->getMediaTimeUs(); 992 } else { 993 *positionUs = 0; 994 } 995 996 return OK; 997} 998 999status_t AwesomePlayer::seekTo(int64_t timeUs) { 1000 if (mExtractorFlags & MediaExtractor::CAN_SEEK) { 1001 Mutex::Autolock autoLock(mLock); 1002 return seekTo_l(timeUs); 1003 } 1004 1005 return OK; 1006} 1007 1008// static 1009void AwesomePlayer::OnRTSPSeekDoneWrapper(void *cookie) { 1010 static_cast<AwesomePlayer *>(cookie)->onRTSPSeekDone(); 1011} 1012 1013void AwesomePlayer::onRTSPSeekDone() { 1014 notifyListener_l(MEDIA_SEEK_COMPLETE); 1015 mSeekNotificationSent = true; 1016} 1017 1018status_t AwesomePlayer::seekTo_l(int64_t timeUs) { 1019 if (mRTSPController != NULL) { 1020 mRTSPController->seekAsync(timeUs, OnRTSPSeekDoneWrapper, this); 1021 return OK; 1022 } 1023 1024 if (mFlags & CACHE_UNDERRUN) { 1025 mFlags &= ~CACHE_UNDERRUN; 1026 play_l(); 1027 } 1028 1029 mSeeking = true; 1030 mSeekNotificationSent = false; 1031 mSeekTimeUs = timeUs; 1032 mFlags &= ~(AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS); 1033 1034 seekAudioIfNecessary_l(); 1035 1036 if (!(mFlags & PLAYING)) { 1037 LOGV("seeking while paused, sending SEEK_COMPLETE notification" 1038 " immediately."); 1039 1040 notifyListener_l(MEDIA_SEEK_COMPLETE); 1041 mSeekNotificationSent = true; 1042 } 1043 1044 return OK; 1045} 1046 1047void AwesomePlayer::seekAudioIfNecessary_l() { 1048 if (mSeeking && mVideoSource == NULL && mAudioPlayer != NULL) { 1049 mAudioPlayer->seekTo(mSeekTimeUs); 1050 1051 mWatchForAudioSeekComplete = true; 1052 mWatchForAudioEOS = true; 1053 mSeekNotificationSent = false; 1054 1055 if (mDecryptHandle != NULL) { 1056 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, 1057 Playback::PAUSE, 0); 1058 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, 1059 Playback::START, mSeekTimeUs / 1000); 1060 } 1061 } 1062} 1063 1064status_t AwesomePlayer::getVideoDimensions( 1065 int32_t *width, int32_t *height) const { 1066 Mutex::Autolock autoLock(mLock); 1067 1068 if (mVideoWidth < 0 || mVideoHeight < 0) { 1069 return UNKNOWN_ERROR; 1070 } 1071 1072 *width = mVideoWidth; 1073 *height = mVideoHeight; 1074 1075 return OK; 1076} 1077 1078void AwesomePlayer::setAudioSource(sp<MediaSource> source) { 1079 CHECK(source != NULL); 1080 1081 mAudioTrack = source; 1082} 1083 1084status_t AwesomePlayer::initAudioDecoder() { 1085 sp<MetaData> meta = mAudioTrack->getFormat(); 1086 1087 const char *mime; 1088 CHECK(meta->findCString(kKeyMIMEType, &mime)); 1089 1090 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) { 1091 mAudioSource = mAudioTrack; 1092 } else { 1093 mAudioSource = OMXCodec::Create( 1094 mClient.interface(), mAudioTrack->getFormat(), 1095 false, // createEncoder 1096 mAudioTrack); 1097 } 1098 1099 if (mAudioSource != NULL) { 1100 int64_t durationUs; 1101 if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) { 1102 Mutex::Autolock autoLock(mMiscStateLock); 1103 if (mDurationUs < 0 || durationUs > mDurationUs) { 1104 mDurationUs = durationUs; 1105 } 1106 } 1107 1108 status_t err = mAudioSource->start(); 1109 1110 if (err != OK) { 1111 mAudioSource.clear(); 1112 return err; 1113 } 1114 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_QCELP)) { 1115 // For legacy reasons we're simply going to ignore the absence 1116 // of an audio decoder for QCELP instead of aborting playback 1117 // altogether. 1118 return OK; 1119 } 1120 1121 return mAudioSource != NULL ? OK : UNKNOWN_ERROR; 1122} 1123 1124void AwesomePlayer::setVideoSource(sp<MediaSource> source) { 1125 CHECK(source != NULL); 1126 1127 mVideoTrack = source; 1128} 1129 1130status_t AwesomePlayer::initVideoDecoder(uint32_t flags) { 1131 mVideoSource = OMXCodec::Create( 1132 mClient.interface(), mVideoTrack->getFormat(), 1133 false, // createEncoder 1134 mVideoTrack, 1135 NULL, flags, mSurface); 1136 1137 if (mVideoSource != NULL) { 1138 int64_t durationUs; 1139 if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) { 1140 Mutex::Autolock autoLock(mMiscStateLock); 1141 if (mDurationUs < 0 || durationUs > mDurationUs) { 1142 mDurationUs = durationUs; 1143 } 1144 } 1145 1146 CHECK(mVideoTrack->getFormat()->findInt32(kKeyWidth, &mVideoWidth)); 1147 CHECK(mVideoTrack->getFormat()->findInt32(kKeyHeight, &mVideoHeight)); 1148 1149 status_t err = mVideoSource->start(); 1150 1151 if (err != OK) { 1152 mVideoSource.clear(); 1153 return err; 1154 } 1155 } 1156 1157 return mVideoSource != NULL ? OK : UNKNOWN_ERROR; 1158} 1159 1160void AwesomePlayer::finishSeekIfNecessary(int64_t videoTimeUs) { 1161 if (!mSeeking) { 1162 return; 1163 } 1164 1165 if (mAudioPlayer != NULL) { 1166 LOGV("seeking audio to %lld us (%.2f secs).", videoTimeUs, videoTimeUs / 1E6); 1167 1168 // If we don't have a video time, seek audio to the originally 1169 // requested seek time instead. 1170 1171 mAudioPlayer->seekTo(videoTimeUs < 0 ? mSeekTimeUs : videoTimeUs); 1172 mAudioPlayer->resume(); 1173 mWatchForAudioSeekComplete = true; 1174 mWatchForAudioEOS = true; 1175 } else if (!mSeekNotificationSent) { 1176 // If we're playing video only, report seek complete now, 1177 // otherwise audio player will notify us later. 1178 notifyListener_l(MEDIA_SEEK_COMPLETE); 1179 } 1180 1181 mFlags |= FIRST_FRAME; 1182 mSeeking = false; 1183 mSeekNotificationSent = false; 1184 1185 if (mDecryptHandle != NULL) { 1186 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, 1187 Playback::PAUSE, 0); 1188 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, 1189 Playback::START, videoTimeUs / 1000); 1190 } 1191} 1192 1193void AwesomePlayer::onVideoEvent() { 1194 Mutex::Autolock autoLock(mLock); 1195 if (!mVideoEventPending) { 1196 // The event has been cancelled in reset_l() but had already 1197 // been scheduled for execution at that time. 1198 return; 1199 } 1200 mVideoEventPending = false; 1201 1202 if (mSeeking) { 1203 if (mLastVideoBuffer) { 1204 mLastVideoBuffer->release(); 1205 mLastVideoBuffer = NULL; 1206 } 1207 1208 if (mVideoBuffer) { 1209 mVideoBuffer->release(); 1210 mVideoBuffer = NULL; 1211 } 1212 1213 if (mCachedSource != NULL && mAudioSource != NULL) { 1214 // We're going to seek the video source first, followed by 1215 // the audio source. 1216 // In order to avoid jumps in the DataSource offset caused by 1217 // the audio codec prefetching data from the old locations 1218 // while the video codec is already reading data from the new 1219 // locations, we'll "pause" the audio source, causing it to 1220 // stop reading input data until a subsequent seek. 1221 1222 if (mAudioPlayer != NULL) { 1223 mAudioPlayer->pause(); 1224 } 1225 mAudioSource->pause(); 1226 } 1227 } 1228 1229 if (!mVideoBuffer) { 1230 MediaSource::ReadOptions options; 1231 if (mSeeking) { 1232 LOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs, mSeekTimeUs / 1E6); 1233 1234 options.setSeekTo( 1235 mSeekTimeUs, MediaSource::ReadOptions::SEEK_CLOSEST_SYNC); 1236 } 1237 for (;;) { 1238 status_t err = mVideoSource->read(&mVideoBuffer, &options); 1239 options.clearSeekTo(); 1240 1241 if (err != OK) { 1242 CHECK_EQ(mVideoBuffer, NULL); 1243 1244 if (err == INFO_FORMAT_CHANGED) { 1245 LOGV("VideoSource signalled format change."); 1246 1247 notifyVideoSize_l(); 1248 1249 if (mVideoRenderer != NULL) { 1250 mVideoRendererIsPreview = false; 1251 initRenderer_l(); 1252 } 1253 continue; 1254 } 1255 1256 // So video playback is complete, but we may still have 1257 // a seek request pending that needs to be applied 1258 // to the audio track. 1259 if (mSeeking) { 1260 LOGV("video stream ended while seeking!"); 1261 } 1262 finishSeekIfNecessary(-1); 1263 1264 mFlags |= VIDEO_AT_EOS; 1265 postStreamDoneEvent_l(err); 1266 return; 1267 } 1268 1269 if (mVideoBuffer->range_length() == 0) { 1270 // Some decoders, notably the PV AVC software decoder 1271 // return spurious empty buffers that we just want to ignore. 1272 1273 mVideoBuffer->release(); 1274 mVideoBuffer = NULL; 1275 continue; 1276 } 1277 1278 break; 1279 } 1280 } 1281 1282 int64_t timeUs; 1283 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs)); 1284 1285 { 1286 Mutex::Autolock autoLock(mMiscStateLock); 1287 mVideoTimeUs = timeUs; 1288 } 1289 1290 bool wasSeeking = mSeeking; 1291 finishSeekIfNecessary(timeUs); 1292 1293 TimeSource *ts = (mFlags & AUDIO_AT_EOS) ? &mSystemTimeSource : mTimeSource; 1294 1295 if (mFlags & FIRST_FRAME) { 1296 mFlags &= ~FIRST_FRAME; 1297 1298 mTimeSourceDeltaUs = ts->getRealTimeUs() - timeUs; 1299 } 1300 1301 int64_t realTimeUs, mediaTimeUs; 1302 if (!(mFlags & AUDIO_AT_EOS) && mAudioPlayer != NULL 1303 && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) { 1304 mTimeSourceDeltaUs = realTimeUs - mediaTimeUs; 1305 } 1306 1307 int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs; 1308 1309 int64_t latenessUs = nowUs - timeUs; 1310 1311 if (wasSeeking) { 1312 // Let's display the first frame after seeking right away. 1313 latenessUs = 0; 1314 } 1315 1316 if (mRTPSession != NULL) { 1317 // We'll completely ignore timestamps for gtalk videochat 1318 // and we'll play incoming video as fast as we get it. 1319 latenessUs = 0; 1320 } 1321 1322 if (latenessUs > 40000) { 1323 // We're more than 40ms late. 1324 LOGV("we're late by %lld us (%.2f secs)", latenessUs, latenessUs / 1E6); 1325 1326 mVideoBuffer->release(); 1327 mVideoBuffer = NULL; 1328 1329 postVideoEvent_l(); 1330 return; 1331 } 1332 1333 if (latenessUs < -10000) { 1334 // We're more than 10ms early. 1335 1336 postVideoEvent_l(10000); 1337 return; 1338 } 1339 1340 if (mVideoRendererIsPreview || mVideoRenderer == NULL) { 1341 mVideoRendererIsPreview = false; 1342 1343 initRenderer_l(); 1344 } 1345 1346 if (mVideoRenderer != NULL) { 1347 mVideoRenderer->render(mVideoBuffer); 1348 } 1349 1350 if (mLastVideoBuffer) { 1351 mLastVideoBuffer->release(); 1352 mLastVideoBuffer = NULL; 1353 } 1354 mLastVideoBuffer = mVideoBuffer; 1355 mVideoBuffer = NULL; 1356 1357 postVideoEvent_l(); 1358} 1359 1360void AwesomePlayer::postVideoEvent_l(int64_t delayUs) { 1361 if (mVideoEventPending) { 1362 return; 1363 } 1364 1365 mVideoEventPending = true; 1366 mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs); 1367} 1368 1369void AwesomePlayer::postStreamDoneEvent_l(status_t status) { 1370 if (mStreamDoneEventPending) { 1371 return; 1372 } 1373 mStreamDoneEventPending = true; 1374 1375 mStreamDoneStatus = status; 1376 mQueue.postEvent(mStreamDoneEvent); 1377} 1378 1379void AwesomePlayer::postBufferingEvent_l() { 1380 if (mBufferingEventPending) { 1381 return; 1382 } 1383 mBufferingEventPending = true; 1384 mQueue.postEventWithDelay(mBufferingEvent, 1000000ll); 1385} 1386 1387void AwesomePlayer::postCheckAudioStatusEvent_l() { 1388 if (mAudioStatusEventPending) { 1389 return; 1390 } 1391 mAudioStatusEventPending = true; 1392 mQueue.postEvent(mCheckAudioStatusEvent); 1393} 1394 1395void AwesomePlayer::onCheckAudioStatus() { 1396 Mutex::Autolock autoLock(mLock); 1397 if (!mAudioStatusEventPending) { 1398 // Event was dispatched and while we were blocking on the mutex, 1399 // has already been cancelled. 1400 return; 1401 } 1402 1403 mAudioStatusEventPending = false; 1404 1405 if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) { 1406 mWatchForAudioSeekComplete = false; 1407 1408 if (!mSeekNotificationSent) { 1409 notifyListener_l(MEDIA_SEEK_COMPLETE); 1410 mSeekNotificationSent = true; 1411 } 1412 1413 mSeeking = false; 1414 } 1415 1416 status_t finalStatus; 1417 if (mWatchForAudioEOS && mAudioPlayer->reachedEOS(&finalStatus)) { 1418 mWatchForAudioEOS = false; 1419 mFlags |= AUDIO_AT_EOS; 1420 mFlags |= FIRST_FRAME; 1421 postStreamDoneEvent_l(finalStatus); 1422 } 1423} 1424 1425status_t AwesomePlayer::prepare() { 1426 Mutex::Autolock autoLock(mLock); 1427 return prepare_l(); 1428} 1429 1430status_t AwesomePlayer::prepare_l() { 1431 if (mFlags & PREPARED) { 1432 return OK; 1433 } 1434 1435 if (mFlags & PREPARING) { 1436 return UNKNOWN_ERROR; 1437 } 1438 1439 mIsAsyncPrepare = false; 1440 status_t err = prepareAsync_l(); 1441 1442 if (err != OK) { 1443 return err; 1444 } 1445 1446 while (mFlags & PREPARING) { 1447 mPreparedCondition.wait(mLock); 1448 } 1449 1450 return mPrepareResult; 1451} 1452 1453status_t AwesomePlayer::prepareAsync() { 1454 Mutex::Autolock autoLock(mLock); 1455 1456 if (mFlags & PREPARING) { 1457 return UNKNOWN_ERROR; // async prepare already pending 1458 } 1459 1460 mIsAsyncPrepare = true; 1461 return prepareAsync_l(); 1462} 1463 1464status_t AwesomePlayer::prepareAsync_l() { 1465 if (mFlags & PREPARING) { 1466 return UNKNOWN_ERROR; // async prepare already pending 1467 } 1468 1469 if (!mQueueStarted) { 1470 mQueue.start(); 1471 mQueueStarted = true; 1472 } 1473 1474 mFlags |= PREPARING; 1475 mAsyncPrepareEvent = new AwesomeEvent( 1476 this, &AwesomePlayer::onPrepareAsyncEvent); 1477 1478 mQueue.postEvent(mAsyncPrepareEvent); 1479 1480 return OK; 1481} 1482 1483status_t AwesomePlayer::finishSetDataSource_l() { 1484 sp<DataSource> dataSource; 1485 1486 if (!strncasecmp("http://", mUri.string(), 7)) { 1487 mConnectingDataSource = new NuHTTPDataSource; 1488 1489 mLock.unlock(); 1490 status_t err = mConnectingDataSource->connect(mUri, &mUriHeaders); 1491 mLock.lock(); 1492 1493 if (err != OK) { 1494 mConnectingDataSource.clear(); 1495 1496 LOGI("mConnectingDataSource->connect() returned %d", err); 1497 return err; 1498 } 1499 1500#if 0 1501 mCachedSource = new NuCachedSource2( 1502 new ThrottledSource( 1503 mConnectingDataSource, 50 * 1024 /* bytes/sec */)); 1504#else 1505 mCachedSource = new NuCachedSource2(mConnectingDataSource); 1506#endif 1507 mConnectingDataSource.clear(); 1508 1509 dataSource = mCachedSource; 1510 } else if (!strncasecmp(mUri.string(), "httplive://", 11)) { 1511 String8 uri("http://"); 1512 uri.append(mUri.string() + 11); 1513 1514 sp<LiveSource> liveSource = new LiveSource(uri.string()); 1515 1516 mCachedSource = new NuCachedSource2(liveSource); 1517 dataSource = mCachedSource; 1518 1519 sp<MediaExtractor> extractor = 1520 MediaExtractor::Create(dataSource, MEDIA_MIMETYPE_CONTAINER_MPEG2TS); 1521 1522 static_cast<MPEG2TSExtractor *>(extractor.get()) 1523 ->setLiveSource(liveSource); 1524 1525 return setDataSource_l(extractor); 1526 } else if (!strncmp("rtsp://gtalk/", mUri.string(), 13)) { 1527 if (mLooper == NULL) { 1528 mLooper = new ALooper; 1529 mLooper->setName("gtalk rtp"); 1530 mLooper->start( 1531 false /* runOnCallingThread */, 1532 false /* canCallJava */, 1533 PRIORITY_HIGHEST); 1534 } 1535 1536 const char *startOfCodecString = &mUri.string()[13]; 1537 const char *startOfSlash1 = strchr(startOfCodecString, '/'); 1538 if (startOfSlash1 == NULL) { 1539 return BAD_VALUE; 1540 } 1541 const char *startOfWidthString = &startOfSlash1[1]; 1542 const char *startOfSlash2 = strchr(startOfWidthString, '/'); 1543 if (startOfSlash2 == NULL) { 1544 return BAD_VALUE; 1545 } 1546 const char *startOfHeightString = &startOfSlash2[1]; 1547 1548 String8 codecString(startOfCodecString, startOfSlash1 - startOfCodecString); 1549 String8 widthString(startOfWidthString, startOfSlash2 - startOfWidthString); 1550 String8 heightString(startOfHeightString); 1551 1552#if 0 1553 mRTPPusher = new UDPPusher("/data/misc/rtpout.bin", 5434); 1554 mLooper->registerHandler(mRTPPusher); 1555 1556 mRTCPPusher = new UDPPusher("/data/misc/rtcpout.bin", 5435); 1557 mLooper->registerHandler(mRTCPPusher); 1558#endif 1559 1560 mRTPSession = new ARTPSession; 1561 mLooper->registerHandler(mRTPSession); 1562 1563#if 0 1564 // My AMR SDP 1565 static const char *raw = 1566 "v=0\r\n" 1567 "o=- 64 233572944 IN IP4 127.0.0.0\r\n" 1568 "s=QuickTime\r\n" 1569 "t=0 0\r\n" 1570 "a=range:npt=0-315\r\n" 1571 "a=isma-compliance:2,2.0,2\r\n" 1572 "m=audio 5434 RTP/AVP 97\r\n" 1573 "c=IN IP4 127.0.0.1\r\n" 1574 "b=AS:30\r\n" 1575 "a=rtpmap:97 AMR/8000/1\r\n" 1576 "a=fmtp:97 octet-align\r\n"; 1577#elif 1 1578 String8 sdp; 1579 sdp.appendFormat( 1580 "v=0\r\n" 1581 "o=- 64 233572944 IN IP4 127.0.0.0\r\n" 1582 "s=QuickTime\r\n" 1583 "t=0 0\r\n" 1584 "a=range:npt=0-315\r\n" 1585 "a=isma-compliance:2,2.0,2\r\n" 1586 "m=video 5434 RTP/AVP 97\r\n" 1587 "c=IN IP4 127.0.0.1\r\n" 1588 "b=AS:30\r\n" 1589 "a=rtpmap:97 %s/90000\r\n" 1590 "a=cliprect:0,0,%s,%s\r\n" 1591 "a=framesize:97 %s-%s\r\n", 1592 1593 codecString.string(), 1594 heightString.string(), widthString.string(), 1595 widthString.string(), heightString.string() 1596 ); 1597 const char *raw = sdp.string(); 1598 1599#endif 1600 1601 sp<ASessionDescription> desc = new ASessionDescription; 1602 CHECK(desc->setTo(raw, strlen(raw))); 1603 1604 CHECK_EQ(mRTPSession->setup(desc), (status_t)OK); 1605 1606 if (mRTPPusher != NULL) { 1607 mRTPPusher->start(); 1608 } 1609 1610 if (mRTCPPusher != NULL) { 1611 mRTCPPusher->start(); 1612 } 1613 1614 CHECK_EQ(mRTPSession->countTracks(), 1u); 1615 sp<MediaSource> source = mRTPSession->trackAt(0); 1616 1617#if 0 1618 bool eos; 1619 while (((APacketSource *)source.get()) 1620 ->getQueuedDuration(&eos) < 5000000ll && !eos) { 1621 usleep(100000ll); 1622 } 1623#endif 1624 1625 const char *mime; 1626 CHECK(source->getFormat()->findCString(kKeyMIMEType, &mime)); 1627 1628 if (!strncasecmp("video/", mime, 6)) { 1629 setVideoSource(source); 1630 } else { 1631 CHECK(!strncasecmp("audio/", mime, 6)); 1632 setAudioSource(source); 1633 } 1634 1635 mExtractorFlags = MediaExtractor::CAN_PAUSE; 1636 1637 return OK; 1638 } else if (!strncasecmp("rtsp://", mUri.string(), 7)) { 1639 if (mLooper == NULL) { 1640 mLooper = new ALooper; 1641 mLooper->setName("rtsp"); 1642 mLooper->start(); 1643 } 1644 mRTSPController = new ARTSPController(mLooper); 1645 status_t err = mRTSPController->connect(mUri.string()); 1646 1647 LOGI("ARTSPController::connect returned %d", err); 1648 1649 if (err != OK) { 1650 mRTSPController.clear(); 1651 return err; 1652 } 1653 1654 sp<MediaExtractor> extractor = mRTSPController.get(); 1655 return setDataSource_l(extractor); 1656 } else { 1657 dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders); 1658 } 1659 1660 if (dataSource == NULL) { 1661 return UNKNOWN_ERROR; 1662 } 1663 1664 sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource); 1665 1666 if (extractor == NULL) { 1667 return UNKNOWN_ERROR; 1668 } 1669 1670 dataSource->getDrmInfo(&mDecryptHandle, &mDrmManagerClient); 1671 if (mDecryptHandle != NULL) { 1672 if (RightsStatus::RIGHTS_VALID == mDecryptHandle->status) { 1673 if (DecryptApiType::WV_BASED == mDecryptHandle->decryptApiType) { 1674 LOGD("Setting mCachedSource to NULL for WVM\n"); 1675 mCachedSource.clear(); 1676 } 1677 } else { 1678 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_NO_LICENSE); 1679 } 1680 } 1681 1682 return setDataSource_l(extractor); 1683} 1684 1685void AwesomePlayer::abortPrepare(status_t err) { 1686 CHECK(err != OK); 1687 1688 if (mIsAsyncPrepare) { 1689 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err); 1690 } 1691 1692 mPrepareResult = err; 1693 mFlags &= ~(PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED); 1694 mAsyncPrepareEvent = NULL; 1695 mPreparedCondition.broadcast(); 1696} 1697 1698// static 1699bool AwesomePlayer::ContinuePreparation(void *cookie) { 1700 AwesomePlayer *me = static_cast<AwesomePlayer *>(cookie); 1701 1702 return (me->mFlags & PREPARE_CANCELLED) == 0; 1703} 1704 1705void AwesomePlayer::onPrepareAsyncEvent() { 1706 Mutex::Autolock autoLock(mLock); 1707 1708 if (mFlags & PREPARE_CANCELLED) { 1709 LOGI("prepare was cancelled before doing anything"); 1710 abortPrepare(UNKNOWN_ERROR); 1711 return; 1712 } 1713 1714 if (mUri.size() > 0) { 1715 status_t err = finishSetDataSource_l(); 1716 1717 if (err != OK) { 1718 abortPrepare(err); 1719 return; 1720 } 1721 } 1722 1723 if (mVideoTrack != NULL && mVideoSource == NULL) { 1724 status_t err = initVideoDecoder(); 1725 1726 if (err != OK) { 1727 abortPrepare(err); 1728 return; 1729 } 1730 } 1731 1732 if (mAudioTrack != NULL && mAudioSource == NULL) { 1733 status_t err = initAudioDecoder(); 1734 1735 if (err != OK) { 1736 abortPrepare(err); 1737 return; 1738 } 1739 } 1740 1741 mFlags |= PREPARING_CONNECTED; 1742 1743 if (mCachedSource != NULL || mRTSPController != NULL) { 1744 postBufferingEvent_l(); 1745 } else { 1746 finishAsyncPrepare_l(); 1747 } 1748} 1749 1750void AwesomePlayer::finishAsyncPrepare_l() { 1751 if (mIsAsyncPrepare) { 1752 if (mVideoSource == NULL) { 1753 notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0); 1754 } else { 1755 notifyVideoSize_l(); 1756 } 1757 1758 notifyListener_l(MEDIA_PREPARED); 1759 } 1760 1761 mPrepareResult = OK; 1762 mFlags &= ~(PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED); 1763 mFlags |= PREPARED; 1764 mAsyncPrepareEvent = NULL; 1765 mPreparedCondition.broadcast(); 1766} 1767 1768status_t AwesomePlayer::suspend() { 1769 LOGV("suspend"); 1770 Mutex::Autolock autoLock(mLock); 1771 1772 if (mSuspensionState != NULL) { 1773 if (mLastVideoBuffer == NULL) { 1774 //go into here if video is suspended again 1775 //after resuming without being played between 1776 //them 1777 SuspensionState *state = mSuspensionState; 1778 mSuspensionState = NULL; 1779 reset_l(); 1780 mSuspensionState = state; 1781 return OK; 1782 } 1783 1784 delete mSuspensionState; 1785 mSuspensionState = NULL; 1786 } 1787 1788 if (mFlags & PREPARING) { 1789 mFlags |= PREPARE_CANCELLED; 1790 if (mConnectingDataSource != NULL) { 1791 LOGI("interrupting the connection process"); 1792 mConnectingDataSource->disconnect(); 1793 } 1794 } 1795 1796 while (mFlags & PREPARING) { 1797 mPreparedCondition.wait(mLock); 1798 } 1799 1800 SuspensionState *state = new SuspensionState; 1801 state->mUri = mUri; 1802 state->mUriHeaders = mUriHeaders; 1803 state->mFileSource = mFileSource; 1804 1805 state->mFlags = mFlags & (PLAYING | AUTO_LOOPING | LOOPING | AT_EOS); 1806 getPosition(&state->mPositionUs); 1807 1808 if (mLastVideoBuffer) { 1809 size_t size = mLastVideoBuffer->range_length(); 1810 1811 if (size) { 1812 int32_t unreadable; 1813 if (!mLastVideoBuffer->meta_data()->findInt32( 1814 kKeyIsUnreadable, &unreadable) 1815 || unreadable == 0) { 1816 state->mLastVideoFrameSize = size; 1817 state->mLastVideoFrame = malloc(size); 1818 memcpy(state->mLastVideoFrame, 1819 (const uint8_t *)mLastVideoBuffer->data() 1820 + mLastVideoBuffer->range_offset(), 1821 size); 1822 1823 state->mVideoWidth = mVideoWidth; 1824 state->mVideoHeight = mVideoHeight; 1825 1826 sp<MetaData> meta = mVideoSource->getFormat(); 1827 CHECK(meta->findInt32(kKeyColorFormat, &state->mColorFormat)); 1828 CHECK(meta->findInt32(kKeyWidth, &state->mDecodedWidth)); 1829 CHECK(meta->findInt32(kKeyHeight, &state->mDecodedHeight)); 1830 } else { 1831 LOGV("Unable to save last video frame, we have no access to " 1832 "the decoded video data."); 1833 } 1834 } 1835 } 1836 1837 reset_l(); 1838 1839 mSuspensionState = state; 1840 1841 return OK; 1842} 1843 1844status_t AwesomePlayer::resume() { 1845 LOGV("resume"); 1846 Mutex::Autolock autoLock(mLock); 1847 1848 if (mSuspensionState == NULL) { 1849 return INVALID_OPERATION; 1850 } 1851 1852 SuspensionState *state = mSuspensionState; 1853 mSuspensionState = NULL; 1854 1855 status_t err; 1856 if (state->mFileSource != NULL) { 1857 err = setDataSource_l(state->mFileSource); 1858 1859 if (err == OK) { 1860 mFileSource = state->mFileSource; 1861 } 1862 } else { 1863 err = setDataSource_l(state->mUri, &state->mUriHeaders); 1864 } 1865 1866 if (err != OK) { 1867 delete state; 1868 state = NULL; 1869 1870 return err; 1871 } 1872 1873 seekTo_l(state->mPositionUs); 1874 1875 mFlags = state->mFlags & (AUTO_LOOPING | LOOPING | AT_EOS); 1876 1877 if (state->mLastVideoFrame && (mSurface != NULL || mISurface != NULL)) { 1878 mVideoRenderer = 1879 new AwesomeLocalRenderer( 1880 true, // previewOnly 1881 "", 1882 (OMX_COLOR_FORMATTYPE)state->mColorFormat, 1883 mISurface, 1884 mSurface, 1885 state->mVideoWidth, 1886 state->mVideoHeight, 1887 state->mDecodedWidth, 1888 state->mDecodedHeight); 1889 1890 mVideoRendererIsPreview = true; 1891 1892 ((AwesomeLocalRenderer *)mVideoRenderer.get())->render( 1893 state->mLastVideoFrame, state->mLastVideoFrameSize); 1894 } 1895 1896 if (state->mFlags & PLAYING) { 1897 play_l(); 1898 } 1899 1900 mSuspensionState = state; 1901 state = NULL; 1902 1903 return OK; 1904} 1905 1906uint32_t AwesomePlayer::flags() const { 1907 return mExtractorFlags; 1908} 1909 1910void AwesomePlayer::postAudioEOS() { 1911 postCheckAudioStatusEvent_l(); 1912} 1913 1914void AwesomePlayer::postAudioSeekComplete() { 1915 postCheckAudioStatusEvent_l(); 1916} 1917 1918} // namespace android 1919