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