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