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