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