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