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 #undef DEBUG_HDCP 18 19 //#define LOG_NDEBUG 0 20 #define LOG_TAG "AwesomePlayer" 21 #define ATRACE_TAG ATRACE_TAG_VIDEO 22 23 #include <inttypes.h> 24 25 #include <utils/Log.h> 26 #include <utils/Trace.h> 27 28 #include <dlfcn.h> 29 30 #include "include/AwesomePlayer.h" 31 #include "include/DRMExtractor.h" 32 #include "include/SoftwareRenderer.h" 33 #include "include/NuCachedSource2.h" 34 #include "include/ThrottledSource.h" 35 #include "include/MPEG2TSExtractor.h" 36 #include "include/WVMExtractor.h" 37 38 #include <binder/IPCThreadState.h> 39 #include <binder/IServiceManager.h> 40 #include <media/IMediaHTTPConnection.h> 41 #include <media/IMediaHTTPService.h> 42 #include <media/IMediaPlayerService.h> 43 #include <media/stagefright/foundation/hexdump.h> 44 #include <media/stagefright/foundation/ADebug.h> 45 #include <media/stagefright/timedtext/TimedTextDriver.h> 46 #include <media/stagefright/AudioPlayer.h> 47 #include <media/stagefright/ClockEstimator.h> 48 #include <media/stagefright/DataSource.h> 49 #include <media/stagefright/FileSource.h> 50 #include <media/stagefright/MediaBuffer.h> 51 #include <media/stagefright/MediaDefs.h> 52 #include <media/stagefright/MediaExtractor.h> 53 #include <media/stagefright/MediaHTTP.h> 54 #include <media/stagefright/MediaSource.h> 55 #include <media/stagefright/MetaData.h> 56 #include <media/stagefright/OMXCodec.h> 57 #include <media/stagefright/Utils.h> 58 59 #include <gui/IGraphicBufferProducer.h> 60 #include <gui/Surface.h> 61 62 #include <media/stagefright/foundation/AMessage.h> 63 64 #include <cutils/properties.h> 65 66 #define USE_SURFACE_ALLOC 1 67 #define FRAME_DROP_FREQ 0 68 69 namespace android { 70 71 static int64_t kLowWaterMarkUs = 2000000ll; // 2secs 72 static int64_t kHighWaterMarkUs = 5000000ll; // 5secs 73 static const size_t kLowWaterMarkBytes = 40000; 74 static const size_t kHighWaterMarkBytes = 200000; 75 76 // maximum time in paused state when offloading audio decompression. When elapsed, the AudioPlayer 77 // is destroyed to allow the audio DSP to power down. 78 static int64_t kOffloadPauseMaxUs = 10000000ll; 79 80 81 struct AwesomeEvent : public TimedEventQueue::Event { 82 AwesomeEvent( 83 AwesomePlayer *player, 84 void (AwesomePlayer::*method)()) 85 : mPlayer(player), 86 mMethod(method) { 87 } 88 89 protected: 90 virtual ~AwesomeEvent() {} 91 92 virtual void fire(TimedEventQueue * /* queue */, int64_t /* now_us */) { 93 (mPlayer->*mMethod)(); 94 } 95 96 private: 97 AwesomePlayer *mPlayer; 98 void (AwesomePlayer::*mMethod)(); 99 100 AwesomeEvent(const AwesomeEvent &); 101 AwesomeEvent &operator=(const AwesomeEvent &); 102 }; 103 104 struct AwesomeLocalRenderer : public AwesomeRenderer { 105 AwesomeLocalRenderer( 106 const sp<ANativeWindow> &nativeWindow, const sp<AMessage> &format) 107 : mFormat(format), 108 mTarget(new SoftwareRenderer(nativeWindow)) { 109 } 110 111 virtual void render(MediaBuffer *buffer) { 112 int64_t timeUs; 113 CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs)); 114 115 render((const uint8_t *)buffer->data() + buffer->range_offset(), 116 buffer->range_length(), timeUs * 1000); 117 } 118 119 void render(const void *data, size_t size, int64_t timestampNs) { 120 mTarget->render(data, size, timestampNs, NULL, mFormat); 121 } 122 123 protected: 124 virtual ~AwesomeLocalRenderer() { 125 delete mTarget; 126 mTarget = NULL; 127 } 128 129 private: 130 sp<AMessage> mFormat; 131 SoftwareRenderer *mTarget; 132 133 AwesomeLocalRenderer(const AwesomeLocalRenderer &); 134 AwesomeLocalRenderer &operator=(const AwesomeLocalRenderer &);; 135 }; 136 137 struct AwesomeNativeWindowRenderer : public AwesomeRenderer { 138 AwesomeNativeWindowRenderer( 139 const sp<ANativeWindow> &nativeWindow, 140 int32_t rotationDegrees) 141 : mNativeWindow(nativeWindow) { 142 applyRotation(rotationDegrees); 143 } 144 145 virtual void render(MediaBuffer *buffer) { 146 ATRACE_CALL(); 147 int64_t timeUs; 148 CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs)); 149 native_window_set_buffers_timestamp(mNativeWindow.get(), timeUs * 1000); 150 status_t err = mNativeWindow->queueBuffer( 151 mNativeWindow.get(), buffer->graphicBuffer().get(), -1); 152 if (err != 0) { 153 ALOGE("queueBuffer failed with error %s (%d)", strerror(-err), 154 -err); 155 return; 156 } 157 158 sp<MetaData> metaData = buffer->meta_data(); 159 metaData->setInt32(kKeyRendered, 1); 160 } 161 162 protected: 163 virtual ~AwesomeNativeWindowRenderer() {} 164 165 private: 166 sp<ANativeWindow> mNativeWindow; 167 168 void applyRotation(int32_t rotationDegrees) { 169 uint32_t transform; 170 switch (rotationDegrees) { 171 case 0: transform = 0; break; 172 case 90: transform = HAL_TRANSFORM_ROT_90; break; 173 case 180: transform = HAL_TRANSFORM_ROT_180; break; 174 case 270: transform = HAL_TRANSFORM_ROT_270; break; 175 default: transform = 0; break; 176 } 177 178 if (transform) { 179 CHECK_EQ(0, native_window_set_buffers_transform( 180 mNativeWindow.get(), transform)); 181 } 182 } 183 184 AwesomeNativeWindowRenderer(const AwesomeNativeWindowRenderer &); 185 AwesomeNativeWindowRenderer &operator=( 186 const AwesomeNativeWindowRenderer &); 187 }; 188 189 // To collect the decoder usage 190 void addBatteryData(uint32_t params) { 191 sp<IBinder> binder = 192 defaultServiceManager()->getService(String16("media.player")); 193 sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder); 194 CHECK(service.get() != NULL); 195 196 service->addBatteryData(params); 197 } 198 199 //////////////////////////////////////////////////////////////////////////////// 200 AwesomePlayer::AwesomePlayer() 201 : mQueueStarted(false), 202 mUIDValid(false), 203 mTimeSource(NULL), 204 mVideoRenderingStarted(false), 205 mVideoRendererIsPreview(false), 206 mMediaRenderingStartGeneration(0), 207 mStartGeneration(0), 208 mAudioPlayer(NULL), 209 mDisplayWidth(0), 210 mDisplayHeight(0), 211 mVideoScalingMode(NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW), 212 mFlags(0), 213 mExtractorFlags(0), 214 mVideoBuffer(NULL), 215 mDecryptHandle(NULL), 216 mLastVideoTimeUs(-1), 217 mTextDriver(NULL), 218 mOffloadAudio(false), 219 mAudioTearDown(false) { 220 CHECK_EQ(mClient.connect(), (status_t)OK); 221 222 DataSource::RegisterDefaultSniffers(); 223 224 mVideoEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoEvent); 225 mVideoEventPending = false; 226 mStreamDoneEvent = new AwesomeEvent(this, &AwesomePlayer::onStreamDone); 227 mStreamDoneEventPending = false; 228 mBufferingEvent = new AwesomeEvent(this, &AwesomePlayer::onBufferingUpdate); 229 mBufferingEventPending = false; 230 mVideoLagEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoLagUpdate); 231 mVideoLagEventPending = false; 232 233 mCheckAudioStatusEvent = new AwesomeEvent( 234 this, &AwesomePlayer::onCheckAudioStatus); 235 236 mAudioStatusEventPending = false; 237 238 mAudioTearDownEvent = new AwesomeEvent(this, 239 &AwesomePlayer::onAudioTearDownEvent); 240 mAudioTearDownEventPending = false; 241 242 mClockEstimator = new WindowedLinearFitEstimator(); 243 244 reset(); 245 } 246 247 AwesomePlayer::~AwesomePlayer() { 248 if (mQueueStarted) { 249 mQueue.stop(); 250 } 251 252 reset(); 253 254 mClient.disconnect(); 255 } 256 257 void AwesomePlayer::cancelPlayerEvents(bool keepNotifications) { 258 mQueue.cancelEvent(mVideoEvent->eventID()); 259 mVideoEventPending = false; 260 mQueue.cancelEvent(mVideoLagEvent->eventID()); 261 mVideoLagEventPending = false; 262 263 if (mOffloadAudio) { 264 mQueue.cancelEvent(mAudioTearDownEvent->eventID()); 265 mAudioTearDownEventPending = false; 266 } 267 268 if (!keepNotifications) { 269 mQueue.cancelEvent(mStreamDoneEvent->eventID()); 270 mStreamDoneEventPending = false; 271 mQueue.cancelEvent(mCheckAudioStatusEvent->eventID()); 272 mAudioStatusEventPending = false; 273 274 mQueue.cancelEvent(mBufferingEvent->eventID()); 275 mBufferingEventPending = false; 276 mAudioTearDown = false; 277 } 278 } 279 280 void AwesomePlayer::setListener(const wp<MediaPlayerBase> &listener) { 281 Mutex::Autolock autoLock(mLock); 282 mListener = listener; 283 } 284 285 void AwesomePlayer::setUID(uid_t uid) { 286 ALOGV("AwesomePlayer running on behalf of uid %d", uid); 287 288 mUID = uid; 289 mUIDValid = true; 290 } 291 292 status_t AwesomePlayer::setDataSource( 293 const sp<IMediaHTTPService> &httpService, 294 const char *uri, 295 const KeyedVector<String8, String8> *headers) { 296 Mutex::Autolock autoLock(mLock); 297 return setDataSource_l(httpService, uri, headers); 298 } 299 300 status_t AwesomePlayer::setDataSource_l( 301 const sp<IMediaHTTPService> &httpService, 302 const char *uri, 303 const KeyedVector<String8, String8> *headers) { 304 reset_l(); 305 306 mHTTPService = httpService; 307 mUri = uri; 308 309 if (headers) { 310 mUriHeaders = *headers; 311 312 ssize_t index = mUriHeaders.indexOfKey(String8("x-hide-urls-from-log")); 313 if (index >= 0) { 314 // Browser is in "incognito" mode, suppress logging URLs. 315 316 // This isn't something that should be passed to the server. 317 mUriHeaders.removeItemsAt(index); 318 319 modifyFlags(INCOGNITO, SET); 320 } 321 } 322 323 ALOGI("setDataSource_l(%s)", uriDebugString(mUri, mFlags & INCOGNITO).c_str()); 324 325 // The actual work will be done during preparation in the call to 326 // ::finishSetDataSource_l to avoid blocking the calling thread in 327 // setDataSource for any significant time. 328 329 { 330 Mutex::Autolock autoLock(mStatsLock); 331 mStats.mFd = -1; 332 mStats.mURI = mUri; 333 } 334 335 return OK; 336 } 337 338 status_t AwesomePlayer::setDataSource( 339 int fd, int64_t offset, int64_t length) { 340 Mutex::Autolock autoLock(mLock); 341 342 reset_l(); 343 344 sp<DataSource> dataSource = new FileSource(fd, offset, length); 345 346 status_t err = dataSource->initCheck(); 347 348 if (err != OK) { 349 return err; 350 } 351 352 mFileSource = dataSource; 353 354 { 355 Mutex::Autolock autoLock(mStatsLock); 356 mStats.mFd = fd; 357 mStats.mURI = String8(); 358 } 359 360 return setDataSource_l(dataSource); 361 } 362 363 status_t AwesomePlayer::setDataSource(const sp<IStreamSource> &source) { 364 return INVALID_OPERATION; 365 } 366 367 status_t AwesomePlayer::setDataSource_l( 368 const sp<DataSource> &dataSource) { 369 sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource); 370 371 if (extractor == NULL) { 372 return UNKNOWN_ERROR; 373 } 374 375 if (extractor->getDrmFlag()) { 376 checkDrmStatus(dataSource); 377 } 378 379 return setDataSource_l(extractor); 380 } 381 382 void AwesomePlayer::checkDrmStatus(const sp<DataSource>& dataSource) { 383 dataSource->getDrmInfo(mDecryptHandle, &mDrmManagerClient); 384 if (mDecryptHandle != NULL) { 385 CHECK(mDrmManagerClient); 386 if (RightsStatus::RIGHTS_VALID != mDecryptHandle->status) { 387 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_DRM_NO_LICENSE); 388 } 389 } 390 } 391 392 status_t AwesomePlayer::setDataSource_l(const sp<MediaExtractor> &extractor) { 393 // Attempt to approximate overall stream bitrate by summing all 394 // tracks' individual bitrates, if not all of them advertise bitrate, 395 // we have to fail. 396 397 int64_t totalBitRate = 0; 398 399 mExtractor = extractor; 400 for (size_t i = 0; i < extractor->countTracks(); ++i) { 401 sp<MetaData> meta = extractor->getTrackMetaData(i); 402 403 int32_t bitrate; 404 if (!meta->findInt32(kKeyBitRate, &bitrate)) { 405 const char *mime; 406 CHECK(meta->findCString(kKeyMIMEType, &mime)); 407 ALOGV("track of type '%s' does not publish bitrate", mime); 408 409 totalBitRate = -1; 410 break; 411 } 412 413 totalBitRate += bitrate; 414 } 415 sp<MetaData> fileMeta = mExtractor->getMetaData(); 416 if (fileMeta != NULL) { 417 int64_t duration; 418 if (fileMeta->findInt64(kKeyDuration, &duration)) { 419 mDurationUs = duration; 420 } 421 } 422 423 mBitrate = totalBitRate; 424 425 ALOGV("mBitrate = %lld bits/sec", mBitrate); 426 427 { 428 Mutex::Autolock autoLock(mStatsLock); 429 mStats.mBitrate = mBitrate; 430 mStats.mTracks.clear(); 431 mStats.mAudioTrackIndex = -1; 432 mStats.mVideoTrackIndex = -1; 433 } 434 435 bool haveAudio = false; 436 bool haveVideo = false; 437 for (size_t i = 0; i < extractor->countTracks(); ++i) { 438 sp<MetaData> meta = extractor->getTrackMetaData(i); 439 440 const char *_mime; 441 CHECK(meta->findCString(kKeyMIMEType, &_mime)); 442 443 String8 mime = String8(_mime); 444 445 if (!haveVideo && !strncasecmp(mime.string(), "video/", 6)) { 446 setVideoSource(extractor->getTrack(i)); 447 haveVideo = true; 448 449 // Set the presentation/display size 450 int32_t displayWidth, displayHeight; 451 bool success = meta->findInt32(kKeyDisplayWidth, &displayWidth); 452 if (success) { 453 success = meta->findInt32(kKeyDisplayHeight, &displayHeight); 454 } 455 if (success) { 456 mDisplayWidth = displayWidth; 457 mDisplayHeight = displayHeight; 458 } 459 460 { 461 Mutex::Autolock autoLock(mStatsLock); 462 mStats.mVideoTrackIndex = mStats.mTracks.size(); 463 mStats.mTracks.push(); 464 TrackStat *stat = 465 &mStats.mTracks.editItemAt(mStats.mVideoTrackIndex); 466 stat->mMIME = mime.string(); 467 } 468 } else if (!haveAudio && !strncasecmp(mime.string(), "audio/", 6)) { 469 setAudioSource(extractor->getTrack(i)); 470 haveAudio = true; 471 mActiveAudioTrackIndex = i; 472 473 { 474 Mutex::Autolock autoLock(mStatsLock); 475 mStats.mAudioTrackIndex = mStats.mTracks.size(); 476 mStats.mTracks.push(); 477 TrackStat *stat = 478 &mStats.mTracks.editItemAt(mStats.mAudioTrackIndex); 479 stat->mMIME = mime.string(); 480 } 481 482 if (!strcasecmp(mime.string(), MEDIA_MIMETYPE_AUDIO_VORBIS)) { 483 // Only do this for vorbis audio, none of the other audio 484 // formats even support this ringtone specific hack and 485 // retrieving the metadata on some extractors may turn out 486 // to be very expensive. 487 sp<MetaData> fileMeta = extractor->getMetaData(); 488 int32_t loop; 489 if (fileMeta != NULL 490 && fileMeta->findInt32(kKeyAutoLoop, &loop) && loop != 0) { 491 modifyFlags(AUTO_LOOPING, SET); 492 } 493 } 494 } else if (!strcasecmp(mime.string(), MEDIA_MIMETYPE_TEXT_3GPP)) { 495 addTextSource_l(i, extractor->getTrack(i)); 496 } 497 } 498 499 if (!haveAudio && !haveVideo) { 500 if (mWVMExtractor != NULL) { 501 return mWVMExtractor->getError(); 502 } else { 503 return UNKNOWN_ERROR; 504 } 505 } 506 507 mExtractorFlags = extractor->flags(); 508 509 return OK; 510 } 511 512 void AwesomePlayer::reset() { 513 Mutex::Autolock autoLock(mLock); 514 reset_l(); 515 } 516 517 void AwesomePlayer::reset_l() { 518 mVideoRenderingStarted = false; 519 mActiveAudioTrackIndex = -1; 520 mDisplayWidth = 0; 521 mDisplayHeight = 0; 522 523 notifyListener_l(MEDIA_STOPPED); 524 525 if (mDecryptHandle != NULL) { 526 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, 527 Playback::STOP, 0); 528 mDecryptHandle = NULL; 529 mDrmManagerClient = NULL; 530 } 531 532 if (mFlags & PLAYING) { 533 uint32_t params = IMediaPlayerService::kBatteryDataTrackDecoder; 534 if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) { 535 params |= IMediaPlayerService::kBatteryDataTrackAudio; 536 } 537 if (mVideoSource != NULL) { 538 params |= IMediaPlayerService::kBatteryDataTrackVideo; 539 } 540 addBatteryData(params); 541 } 542 543 if (mFlags & PREPARING) { 544 modifyFlags(PREPARE_CANCELLED, SET); 545 if (mConnectingDataSource != NULL) { 546 ALOGI("interrupting the connection process"); 547 mConnectingDataSource->disconnect(); 548 } 549 550 if (mFlags & PREPARING_CONNECTED) { 551 // We are basically done preparing, we're just buffering 552 // enough data to start playback, we can safely interrupt that. 553 finishAsyncPrepare_l(); 554 } 555 } 556 557 while (mFlags & PREPARING) { 558 mPreparedCondition.wait(mLock); 559 } 560 561 cancelPlayerEvents(); 562 563 mWVMExtractor.clear(); 564 mCachedSource.clear(); 565 mAudioTrack.clear(); 566 mVideoTrack.clear(); 567 mExtractor.clear(); 568 569 // Shutdown audio first, so that the response to the reset request 570 // appears to happen instantaneously as far as the user is concerned 571 // If we did this later, audio would continue playing while we 572 // shutdown the video-related resources and the player appear to 573 // not be as responsive to a reset request. 574 if ((mAudioPlayer == NULL || !(mFlags & AUDIOPLAYER_STARTED)) 575 && mAudioSource != NULL) { 576 // If we had an audio player, it would have effectively 577 // taken possession of the audio source and stopped it when 578 // _it_ is stopped. Otherwise this is still our responsibility. 579 mAudioSource->stop(); 580 } 581 mAudioSource.clear(); 582 mOmxSource.clear(); 583 584 mTimeSource = NULL; 585 586 delete mAudioPlayer; 587 mAudioPlayer = NULL; 588 589 if (mTextDriver != NULL) { 590 delete mTextDriver; 591 mTextDriver = NULL; 592 } 593 594 mVideoRenderer.clear(); 595 596 if (mVideoSource != NULL) { 597 shutdownVideoDecoder_l(); 598 } 599 600 mDurationUs = -1; 601 modifyFlags(0, ASSIGN); 602 mExtractorFlags = 0; 603 mTimeSourceDeltaUs = 0; 604 mVideoTimeUs = 0; 605 606 mSeeking = NO_SEEK; 607 mSeekNotificationSent = true; 608 mSeekTimeUs = 0; 609 610 mHTTPService.clear(); 611 mUri.setTo(""); 612 mUriHeaders.clear(); 613 614 mFileSource.clear(); 615 616 mBitrate = -1; 617 mLastVideoTimeUs = -1; 618 619 { 620 Mutex::Autolock autoLock(mStatsLock); 621 mStats.mFd = -1; 622 mStats.mURI = String8(); 623 mStats.mBitrate = -1; 624 mStats.mAudioTrackIndex = -1; 625 mStats.mVideoTrackIndex = -1; 626 mStats.mNumVideoFramesDecoded = 0; 627 mStats.mNumVideoFramesDropped = 0; 628 mStats.mVideoWidth = -1; 629 mStats.mVideoHeight = -1; 630 mStats.mFlags = 0; 631 mStats.mTracks.clear(); 632 } 633 634 mWatchForAudioSeekComplete = false; 635 mWatchForAudioEOS = false; 636 637 mMediaRenderingStartGeneration = 0; 638 mStartGeneration = 0; 639 } 640 641 void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) { 642 if ((mListener != NULL) && !mAudioTearDown) { 643 sp<MediaPlayerBase> listener = mListener.promote(); 644 645 if (listener != NULL) { 646 listener->sendEvent(msg, ext1, ext2); 647 } 648 } 649 } 650 651 bool AwesomePlayer::getBitrate(int64_t *bitrate) { 652 off64_t size; 653 if (mDurationUs > 0 && mCachedSource != NULL 654 && mCachedSource->getSize(&size) == OK) { 655 *bitrate = size * 8000000ll / mDurationUs; // in bits/sec 656 return true; 657 } 658 659 if (mBitrate >= 0) { 660 *bitrate = mBitrate; 661 return true; 662 } 663 664 *bitrate = 0; 665 666 return false; 667 } 668 669 // Returns true iff cached duration is available/applicable. 670 bool AwesomePlayer::getCachedDuration_l(int64_t *durationUs, bool *eos) { 671 int64_t bitrate; 672 673 if (mCachedSource != NULL && getBitrate(&bitrate) && (bitrate > 0)) { 674 status_t finalStatus; 675 size_t cachedDataRemaining = mCachedSource->approxDataRemaining(&finalStatus); 676 *durationUs = cachedDataRemaining * 8000000ll / bitrate; 677 *eos = (finalStatus != OK); 678 return true; 679 } else if (mWVMExtractor != NULL) { 680 status_t finalStatus; 681 *durationUs = mWVMExtractor->getCachedDurationUs(&finalStatus); 682 *eos = (finalStatus != OK); 683 return true; 684 } 685 686 return false; 687 } 688 689 void AwesomePlayer::ensureCacheIsFetching_l() { 690 if (mCachedSource != NULL) { 691 mCachedSource->resumeFetchingIfNecessary(); 692 } 693 } 694 695 void AwesomePlayer::onVideoLagUpdate() { 696 Mutex::Autolock autoLock(mLock); 697 if (!mVideoLagEventPending) { 698 return; 699 } 700 mVideoLagEventPending = false; 701 702 int64_t audioTimeUs = mAudioPlayer->getMediaTimeUs(); 703 int64_t videoLateByUs = audioTimeUs - mVideoTimeUs; 704 705 if (!(mFlags & VIDEO_AT_EOS) && videoLateByUs > 300000ll) { 706 ALOGV("video late by %lld ms.", videoLateByUs / 1000ll); 707 708 notifyListener_l( 709 MEDIA_INFO, 710 MEDIA_INFO_VIDEO_TRACK_LAGGING, 711 videoLateByUs / 1000ll); 712 } 713 714 postVideoLagEvent_l(); 715 } 716 717 void AwesomePlayer::onBufferingUpdate() { 718 Mutex::Autolock autoLock(mLock); 719 if (!mBufferingEventPending) { 720 return; 721 } 722 mBufferingEventPending = false; 723 724 if (mCachedSource != NULL) { 725 status_t finalStatus; 726 size_t cachedDataRemaining = mCachedSource->approxDataRemaining(&finalStatus); 727 bool eos = (finalStatus != OK); 728 729 if (eos) { 730 if (finalStatus == ERROR_END_OF_STREAM) { 731 notifyListener_l(MEDIA_BUFFERING_UPDATE, 100); 732 } 733 if (mFlags & PREPARING) { 734 ALOGV("cache has reached EOS, prepare is done."); 735 finishAsyncPrepare_l(); 736 } 737 } else { 738 bool eos2; 739 int64_t cachedDurationUs; 740 if (getCachedDuration_l(&cachedDurationUs, &eos2) && mDurationUs > 0) { 741 int percentage = 100.0 * (double)cachedDurationUs / mDurationUs; 742 if (percentage > 100) { 743 percentage = 100; 744 } 745 746 notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage); 747 } else { 748 // We don't know the bitrate/duration of the stream, use absolute size 749 // limits to maintain the cache. 750 751 if ((mFlags & PLAYING) && !eos 752 && (cachedDataRemaining < kLowWaterMarkBytes)) { 753 ALOGI("cache is running low (< %zu) , pausing.", 754 kLowWaterMarkBytes); 755 modifyFlags(CACHE_UNDERRUN, SET); 756 pause_l(); 757 ensureCacheIsFetching_l(); 758 sendCacheStats(); 759 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START); 760 } else if (eos || cachedDataRemaining > kHighWaterMarkBytes) { 761 if (mFlags & CACHE_UNDERRUN) { 762 ALOGI("cache has filled up (> %zu), resuming.", 763 kHighWaterMarkBytes); 764 modifyFlags(CACHE_UNDERRUN, CLEAR); 765 play_l(); 766 } else if (mFlags & PREPARING) { 767 ALOGV("cache has filled up (> %zu), prepare is done", 768 kHighWaterMarkBytes); 769 finishAsyncPrepare_l(); 770 } 771 } 772 } 773 } 774 } else if (mWVMExtractor != NULL) { 775 status_t finalStatus; 776 777 int64_t cachedDurationUs 778 = mWVMExtractor->getCachedDurationUs(&finalStatus); 779 780 bool eos = (finalStatus != OK); 781 782 if (eos) { 783 if (finalStatus == ERROR_END_OF_STREAM) { 784 notifyListener_l(MEDIA_BUFFERING_UPDATE, 100); 785 } 786 if (mFlags & PREPARING) { 787 ALOGV("cache has reached EOS, prepare is done."); 788 finishAsyncPrepare_l(); 789 } 790 } else { 791 int percentage = 100.0 * (double)cachedDurationUs / mDurationUs; 792 if (percentage > 100) { 793 percentage = 100; 794 } 795 796 notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage); 797 } 798 } 799 800 int64_t cachedDurationUs; 801 bool eos; 802 if (getCachedDuration_l(&cachedDurationUs, &eos)) { 803 ALOGV("cachedDurationUs = %.2f secs, eos=%d", 804 cachedDurationUs / 1E6, eos); 805 806 if ((mFlags & PLAYING) && !eos 807 && (cachedDurationUs < kLowWaterMarkUs)) { 808 modifyFlags(CACHE_UNDERRUN, SET); 809 ALOGI("cache is running low (%.2f secs) , pausing.", 810 cachedDurationUs / 1E6); 811 pause_l(); 812 ensureCacheIsFetching_l(); 813 sendCacheStats(); 814 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START); 815 } else if (eos || cachedDurationUs > kHighWaterMarkUs) { 816 if (mFlags & CACHE_UNDERRUN) { 817 modifyFlags(CACHE_UNDERRUN, CLEAR); 818 ALOGI("cache has filled up (%.2f secs), resuming.", 819 cachedDurationUs / 1E6); 820 play_l(); 821 } else if (mFlags & PREPARING) { 822 ALOGV("cache has filled up (%.2f secs), prepare is done", 823 cachedDurationUs / 1E6); 824 finishAsyncPrepare_l(); 825 } 826 } 827 } 828 829 if (mFlags & (PLAYING | PREPARING | CACHE_UNDERRUN)) { 830 postBufferingEvent_l(); 831 } 832 } 833 834 void AwesomePlayer::sendCacheStats() { 835 sp<MediaPlayerBase> listener = mListener.promote(); 836 if (listener != NULL) { 837 int32_t kbps = 0; 838 status_t err = UNKNOWN_ERROR; 839 if (mCachedSource != NULL) { 840 err = mCachedSource->getEstimatedBandwidthKbps(&kbps); 841 } else if (mWVMExtractor != NULL) { 842 err = mWVMExtractor->getEstimatedBandwidthKbps(&kbps); 843 } 844 if (err == OK) { 845 listener->sendEvent( 846 MEDIA_INFO, MEDIA_INFO_NETWORK_BANDWIDTH, kbps); 847 } 848 } 849 } 850 851 void AwesomePlayer::onStreamDone() { 852 // Posted whenever any stream finishes playing. 853 ATRACE_CALL(); 854 855 Mutex::Autolock autoLock(mLock); 856 if (!mStreamDoneEventPending) { 857 return; 858 } 859 mStreamDoneEventPending = false; 860 861 if (mStreamDoneStatus != ERROR_END_OF_STREAM) { 862 ALOGV("MEDIA_ERROR %d", mStreamDoneStatus); 863 864 notifyListener_l( 865 MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, mStreamDoneStatus); 866 867 pause_l(true /* at eos */); 868 869 modifyFlags(AT_EOS, SET); 870 return; 871 } 872 873 const bool allDone = 874 (mVideoSource == NULL || (mFlags & VIDEO_AT_EOS)) 875 && (mAudioSource == NULL || (mFlags & AUDIO_AT_EOS)); 876 877 if (!allDone) { 878 return; 879 } 880 881 if (mFlags & AUTO_LOOPING) { 882 audio_stream_type_t streamType = AUDIO_STREAM_MUSIC; 883 if (mAudioSink != NULL) { 884 streamType = mAudioSink->getAudioStreamType(); 885 } 886 if (streamType == AUDIO_STREAM_NOTIFICATION) { 887 ALOGW("disabling auto-loop for notification"); 888 modifyFlags(AUTO_LOOPING, CLEAR); 889 } 890 } 891 if ((mFlags & LOOPING) 892 || ((mFlags & AUTO_LOOPING) 893 && (mAudioSink == NULL || mAudioSink->realtime()))) { 894 // Don't AUTO_LOOP if we're being recorded, since that cannot be 895 // turned off and recording would go on indefinitely. 896 897 seekTo_l(0); 898 899 if (mVideoSource != NULL) { 900 postVideoEvent_l(); 901 } 902 } else { 903 ALOGV("MEDIA_PLAYBACK_COMPLETE"); 904 notifyListener_l(MEDIA_PLAYBACK_COMPLETE); 905 906 pause_l(true /* at eos */); 907 908 // If audio hasn't completed MEDIA_SEEK_COMPLETE yet, 909 // notify MEDIA_SEEK_COMPLETE to observer immediately for state persistence. 910 if (mWatchForAudioSeekComplete) { 911 notifyListener_l(MEDIA_SEEK_COMPLETE); 912 mWatchForAudioSeekComplete = false; 913 } 914 915 modifyFlags(AT_EOS, SET); 916 } 917 } 918 919 status_t AwesomePlayer::play() { 920 ATRACE_CALL(); 921 922 Mutex::Autolock autoLock(mLock); 923 924 modifyFlags(CACHE_UNDERRUN, CLEAR); 925 926 return play_l(); 927 } 928 929 status_t AwesomePlayer::play_l() { 930 modifyFlags(SEEK_PREVIEW, CLEAR); 931 932 if (mFlags & PLAYING) { 933 return OK; 934 } 935 936 mMediaRenderingStartGeneration = ++mStartGeneration; 937 938 if (!(mFlags & PREPARED)) { 939 status_t err = prepare_l(); 940 941 if (err != OK) { 942 return err; 943 } 944 } 945 946 modifyFlags(PLAYING, SET); 947 modifyFlags(FIRST_FRAME, SET); 948 949 if (mDecryptHandle != NULL) { 950 int64_t position; 951 getPosition(&position); 952 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, 953 Playback::START, position / 1000); 954 } 955 956 if (mAudioSource != NULL) { 957 if (mAudioPlayer == NULL) { 958 createAudioPlayer_l(); 959 } 960 961 CHECK(!(mFlags & AUDIO_RUNNING)); 962 963 if (mVideoSource == NULL) { 964 965 // We don't want to post an error notification at this point, 966 // the error returned from MediaPlayer::start() will suffice. 967 968 status_t err = startAudioPlayer_l( 969 false /* sendErrorNotification */); 970 971 if ((err != OK) && mOffloadAudio) { 972 ALOGI("play_l() cannot create offload output, fallback to sw decode"); 973 int64_t curTimeUs; 974 getPosition(&curTimeUs); 975 976 delete mAudioPlayer; 977 mAudioPlayer = NULL; 978 // if the player was started it will take care of stopping the source when destroyed 979 if (!(mFlags & AUDIOPLAYER_STARTED)) { 980 mAudioSource->stop(); 981 } 982 modifyFlags((AUDIO_RUNNING | AUDIOPLAYER_STARTED), CLEAR); 983 mOffloadAudio = false; 984 mAudioSource = mOmxSource; 985 if (mAudioSource != NULL) { 986 err = mAudioSource->start(); 987 988 if (err != OK) { 989 mAudioSource.clear(); 990 } else { 991 mSeekNotificationSent = true; 992 if (mExtractorFlags & MediaExtractor::CAN_SEEK) { 993 seekTo_l(curTimeUs); 994 } 995 createAudioPlayer_l(); 996 err = startAudioPlayer_l(false); 997 } 998 } 999 } 1000 1001 if (err != OK) { 1002 delete mAudioPlayer; 1003 mAudioPlayer = NULL; 1004 1005 modifyFlags((PLAYING | FIRST_FRAME), CLEAR); 1006 1007 if (mDecryptHandle != NULL) { 1008 mDrmManagerClient->setPlaybackStatus( 1009 mDecryptHandle, Playback::STOP, 0); 1010 } 1011 1012 return err; 1013 } 1014 } 1015 } 1016 1017 if (mTimeSource == NULL && mAudioPlayer == NULL) { 1018 mTimeSource = &mSystemTimeSource; 1019 } 1020 1021 if (mVideoSource != NULL) { 1022 // Kick off video playback 1023 postVideoEvent_l(); 1024 1025 if (mAudioSource != NULL && mVideoSource != NULL) { 1026 postVideoLagEvent_l(); 1027 } 1028 } 1029 1030 if (mFlags & AT_EOS) { 1031 // Legacy behaviour, if a stream finishes playing and then 1032 // is started again, we play from the start... 1033 seekTo_l(0); 1034 } 1035 1036 uint32_t params = IMediaPlayerService::kBatteryDataCodecStarted 1037 | IMediaPlayerService::kBatteryDataTrackDecoder; 1038 if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) { 1039 params |= IMediaPlayerService::kBatteryDataTrackAudio; 1040 } 1041 if (mVideoSource != NULL) { 1042 params |= IMediaPlayerService::kBatteryDataTrackVideo; 1043 } 1044 addBatteryData(params); 1045 1046 if (isStreamingHTTP()) { 1047 postBufferingEvent_l(); 1048 } 1049 1050 return OK; 1051 } 1052 1053 void AwesomePlayer::createAudioPlayer_l() 1054 { 1055 uint32_t flags = 0; 1056 int64_t cachedDurationUs; 1057 bool eos; 1058 1059 if (mOffloadAudio) { 1060 flags |= AudioPlayer::USE_OFFLOAD; 1061 } else if (mVideoSource == NULL 1062 && (mDurationUs > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US || 1063 (getCachedDuration_l(&cachedDurationUs, &eos) && 1064 cachedDurationUs > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US))) { 1065 flags |= AudioPlayer::ALLOW_DEEP_BUFFERING; 1066 } 1067 if (isStreamingHTTP()) { 1068 flags |= AudioPlayer::IS_STREAMING; 1069 } 1070 if (mVideoSource != NULL) { 1071 flags |= AudioPlayer::HAS_VIDEO; 1072 } 1073 1074 mAudioPlayer = new AudioPlayer(mAudioSink, flags, this); 1075 mAudioPlayer->setSource(mAudioSource); 1076 1077 mTimeSource = mAudioPlayer; 1078 1079 // If there was a seek request before we ever started, 1080 // honor the request now. 1081 // Make sure to do this before starting the audio player 1082 // to avoid a race condition. 1083 seekAudioIfNecessary_l(); 1084 } 1085 1086 void AwesomePlayer::notifyIfMediaStarted_l() { 1087 if (mMediaRenderingStartGeneration == mStartGeneration) { 1088 mMediaRenderingStartGeneration = -1; 1089 notifyListener_l(MEDIA_STARTED); 1090 } 1091 } 1092 1093 status_t AwesomePlayer::startAudioPlayer_l(bool sendErrorNotification) { 1094 CHECK(!(mFlags & AUDIO_RUNNING)); 1095 status_t err = OK; 1096 1097 if (mAudioSource == NULL || mAudioPlayer == NULL) { 1098 return OK; 1099 } 1100 1101 if (mOffloadAudio) { 1102 mQueue.cancelEvent(mAudioTearDownEvent->eventID()); 1103 mAudioTearDownEventPending = false; 1104 } 1105 1106 if (!(mFlags & AUDIOPLAYER_STARTED)) { 1107 bool wasSeeking = mAudioPlayer->isSeeking(); 1108 1109 // We've already started the MediaSource in order to enable 1110 // the prefetcher to read its data. 1111 err = mAudioPlayer->start( 1112 true /* sourceAlreadyStarted */); 1113 1114 if (err != OK) { 1115 if (sendErrorNotification) { 1116 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err); 1117 } 1118 1119 return err; 1120 } 1121 1122 modifyFlags(AUDIOPLAYER_STARTED, SET); 1123 1124 if (wasSeeking) { 1125 CHECK(!mAudioPlayer->isSeeking()); 1126 1127 // We will have finished the seek while starting the audio player. 1128 postAudioSeekComplete(); 1129 } else { 1130 notifyIfMediaStarted_l(); 1131 } 1132 } else { 1133 err = mAudioPlayer->resume(); 1134 } 1135 1136 if (err == OK) { 1137 modifyFlags(AUDIO_RUNNING, SET); 1138 1139 mWatchForAudioEOS = true; 1140 } 1141 1142 return err; 1143 } 1144 1145 void AwesomePlayer::notifyVideoSize_l() { 1146 ATRACE_CALL(); 1147 sp<MetaData> meta = mVideoSource->getFormat(); 1148 1149 int32_t cropLeft, cropTop, cropRight, cropBottom; 1150 if (!meta->findRect( 1151 kKeyCropRect, &cropLeft, &cropTop, &cropRight, &cropBottom)) { 1152 int32_t width, height; 1153 CHECK(meta->findInt32(kKeyWidth, &width)); 1154 CHECK(meta->findInt32(kKeyHeight, &height)); 1155 1156 cropLeft = cropTop = 0; 1157 cropRight = width - 1; 1158 cropBottom = height - 1; 1159 1160 ALOGV("got dimensions only %d x %d", width, height); 1161 } else { 1162 ALOGV("got crop rect %d, %d, %d, %d", 1163 cropLeft, cropTop, cropRight, cropBottom); 1164 } 1165 1166 int32_t displayWidth; 1167 if (meta->findInt32(kKeyDisplayWidth, &displayWidth)) { 1168 ALOGV("Display width changed (%d=>%d)", mDisplayWidth, displayWidth); 1169 mDisplayWidth = displayWidth; 1170 } 1171 int32_t displayHeight; 1172 if (meta->findInt32(kKeyDisplayHeight, &displayHeight)) { 1173 ALOGV("Display height changed (%d=>%d)", mDisplayHeight, displayHeight); 1174 mDisplayHeight = displayHeight; 1175 } 1176 1177 int32_t usableWidth = cropRight - cropLeft + 1; 1178 int32_t usableHeight = cropBottom - cropTop + 1; 1179 if (mDisplayWidth != 0) { 1180 usableWidth = mDisplayWidth; 1181 } 1182 if (mDisplayHeight != 0) { 1183 usableHeight = mDisplayHeight; 1184 } 1185 1186 { 1187 Mutex::Autolock autoLock(mStatsLock); 1188 mStats.mVideoWidth = usableWidth; 1189 mStats.mVideoHeight = usableHeight; 1190 } 1191 1192 int32_t rotationDegrees; 1193 if (!mVideoTrack->getFormat()->findInt32( 1194 kKeyRotation, &rotationDegrees)) { 1195 rotationDegrees = 0; 1196 } 1197 1198 if (rotationDegrees == 90 || rotationDegrees == 270) { 1199 notifyListener_l( 1200 MEDIA_SET_VIDEO_SIZE, usableHeight, usableWidth); 1201 } else { 1202 notifyListener_l( 1203 MEDIA_SET_VIDEO_SIZE, usableWidth, usableHeight); 1204 } 1205 } 1206 1207 void AwesomePlayer::initRenderer_l() { 1208 ATRACE_CALL(); 1209 1210 if (mNativeWindow == NULL) { 1211 return; 1212 } 1213 1214 sp<MetaData> meta = mVideoSource->getFormat(); 1215 1216 int32_t format; 1217 const char *component; 1218 int32_t decodedWidth, decodedHeight; 1219 CHECK(meta->findInt32(kKeyColorFormat, &format)); 1220 CHECK(meta->findCString(kKeyDecoderComponent, &component)); 1221 CHECK(meta->findInt32(kKeyWidth, &decodedWidth)); 1222 CHECK(meta->findInt32(kKeyHeight, &decodedHeight)); 1223 1224 int32_t rotationDegrees; 1225 if (!mVideoTrack->getFormat()->findInt32( 1226 kKeyRotation, &rotationDegrees)) { 1227 rotationDegrees = 0; 1228 } 1229 1230 mVideoRenderer.clear(); 1231 1232 // Must ensure that mVideoRenderer's destructor is actually executed 1233 // before creating a new one. 1234 IPCThreadState::self()->flushCommands(); 1235 1236 // Even if set scaling mode fails, we will continue anyway 1237 setVideoScalingMode_l(mVideoScalingMode); 1238 if (USE_SURFACE_ALLOC 1239 && !strncmp(component, "OMX.", 4) 1240 && strncmp(component, "OMX.google.", 11)) { 1241 // Hardware decoders avoid the CPU color conversion by decoding 1242 // directly to ANativeBuffers, so we must use a renderer that 1243 // just pushes those buffers to the ANativeWindow. 1244 mVideoRenderer = 1245 new AwesomeNativeWindowRenderer(mNativeWindow, rotationDegrees); 1246 } else { 1247 // Other decoders are instantiated locally and as a consequence 1248 // allocate their buffers in local address space. This renderer 1249 // then performs a color conversion and copy to get the data 1250 // into the ANativeBuffer. 1251 sp<AMessage> format; 1252 convertMetaDataToMessage(meta, &format); 1253 mVideoRenderer = new AwesomeLocalRenderer(mNativeWindow, format); 1254 } 1255 } 1256 1257 status_t AwesomePlayer::pause() { 1258 ATRACE_CALL(); 1259 1260 Mutex::Autolock autoLock(mLock); 1261 1262 modifyFlags(CACHE_UNDERRUN, CLEAR); 1263 1264 return pause_l(); 1265 } 1266 1267 status_t AwesomePlayer::pause_l(bool at_eos) { 1268 if (!(mFlags & PLAYING)) { 1269 if (mAudioTearDown && mAudioTearDownWasPlaying) { 1270 ALOGV("pause_l() during teardown and finishSetDataSource_l() mFlags %x" , mFlags); 1271 mAudioTearDownWasPlaying = false; 1272 notifyListener_l(MEDIA_PAUSED); 1273 mMediaRenderingStartGeneration = ++mStartGeneration; 1274 } 1275 return OK; 1276 } 1277 1278 notifyListener_l(MEDIA_PAUSED); 1279 mMediaRenderingStartGeneration = ++mStartGeneration; 1280 1281 cancelPlayerEvents(true /* keepNotifications */); 1282 1283 if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) { 1284 // If we played the audio stream to completion we 1285 // want to make sure that all samples remaining in the audio 1286 // track's queue are played out. 1287 mAudioPlayer->pause(at_eos /* playPendingSamples */); 1288 // send us a reminder to tear down the AudioPlayer if paused for too long. 1289 if (mOffloadAudio) { 1290 postAudioTearDownEvent(kOffloadPauseMaxUs); 1291 } 1292 modifyFlags(AUDIO_RUNNING, CLEAR); 1293 } 1294 1295 if (mFlags & TEXTPLAYER_INITIALIZED) { 1296 mTextDriver->pause(); 1297 modifyFlags(TEXT_RUNNING, CLEAR); 1298 } 1299 1300 modifyFlags(PLAYING, CLEAR); 1301 1302 if (mDecryptHandle != NULL) { 1303 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, 1304 Playback::PAUSE, 0); 1305 } 1306 1307 uint32_t params = IMediaPlayerService::kBatteryDataTrackDecoder; 1308 if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) { 1309 params |= IMediaPlayerService::kBatteryDataTrackAudio; 1310 } 1311 if (mVideoSource != NULL) { 1312 params |= IMediaPlayerService::kBatteryDataTrackVideo; 1313 } 1314 1315 addBatteryData(params); 1316 1317 return OK; 1318 } 1319 1320 bool AwesomePlayer::isPlaying() const { 1321 return (mFlags & PLAYING) || (mFlags & CACHE_UNDERRUN); 1322 } 1323 1324 status_t AwesomePlayer::setSurfaceTexture(const sp<IGraphicBufferProducer> &bufferProducer) { 1325 Mutex::Autolock autoLock(mLock); 1326 1327 status_t err; 1328 if (bufferProducer != NULL) { 1329 err = setNativeWindow_l(new Surface(bufferProducer)); 1330 } else { 1331 err = setNativeWindow_l(NULL); 1332 } 1333 1334 return err; 1335 } 1336 1337 void AwesomePlayer::shutdownVideoDecoder_l() { 1338 if (mVideoBuffer) { 1339 mVideoBuffer->release(); 1340 mVideoBuffer = NULL; 1341 } 1342 1343 mVideoSource->stop(); 1344 1345 // The following hack is necessary to ensure that the OMX 1346 // component is completely released by the time we may try 1347 // to instantiate it again. 1348 wp<MediaSource> tmp = mVideoSource; 1349 mVideoSource.clear(); 1350 while (tmp.promote() != NULL) { 1351 usleep(1000); 1352 } 1353 IPCThreadState::self()->flushCommands(); 1354 ALOGV("video decoder shutdown completed"); 1355 } 1356 1357 status_t AwesomePlayer::setNativeWindow_l(const sp<ANativeWindow> &native) { 1358 mNativeWindow = native; 1359 1360 if (mVideoSource == NULL) { 1361 return OK; 1362 } 1363 1364 ALOGV("attempting to reconfigure to use new surface"); 1365 1366 bool wasPlaying = (mFlags & PLAYING) != 0; 1367 1368 pause_l(); 1369 mVideoRenderer.clear(); 1370 1371 shutdownVideoDecoder_l(); 1372 1373 status_t err = initVideoDecoder(); 1374 1375 if (err != OK) { 1376 ALOGE("failed to reinstantiate video decoder after surface change."); 1377 return err; 1378 } 1379 1380 if (mLastVideoTimeUs >= 0) { 1381 mSeeking = SEEK; 1382 mSeekTimeUs = mLastVideoTimeUs; 1383 modifyFlags((AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS), CLEAR); 1384 } 1385 1386 if (wasPlaying) { 1387 play_l(); 1388 } 1389 1390 return OK; 1391 } 1392 1393 void AwesomePlayer::setAudioSink( 1394 const sp<MediaPlayerBase::AudioSink> &audioSink) { 1395 Mutex::Autolock autoLock(mLock); 1396 1397 mAudioSink = audioSink; 1398 } 1399 1400 status_t AwesomePlayer::setLooping(bool shouldLoop) { 1401 Mutex::Autolock autoLock(mLock); 1402 1403 modifyFlags(LOOPING, CLEAR); 1404 1405 if (shouldLoop) { 1406 modifyFlags(LOOPING, SET); 1407 } 1408 1409 return OK; 1410 } 1411 1412 status_t AwesomePlayer::getDuration(int64_t *durationUs) { 1413 Mutex::Autolock autoLock(mMiscStateLock); 1414 1415 if (mDurationUs < 0) { 1416 return UNKNOWN_ERROR; 1417 } 1418 1419 *durationUs = mDurationUs; 1420 1421 return OK; 1422 } 1423 1424 status_t AwesomePlayer::getPosition(int64_t *positionUs) { 1425 if (mSeeking != NO_SEEK) { 1426 *positionUs = mSeekTimeUs; 1427 } else if (mVideoSource != NULL 1428 && (mAudioPlayer == NULL || !(mFlags & VIDEO_AT_EOS))) { 1429 Mutex::Autolock autoLock(mMiscStateLock); 1430 *positionUs = mVideoTimeUs; 1431 } else if (mAudioPlayer != NULL) { 1432 *positionUs = mAudioPlayer->getMediaTimeUs(); 1433 } else { 1434 *positionUs = 0; 1435 } 1436 return OK; 1437 } 1438 1439 status_t AwesomePlayer::seekTo(int64_t timeUs) { 1440 ATRACE_CALL(); 1441 1442 if (mExtractorFlags & MediaExtractor::CAN_SEEK) { 1443 Mutex::Autolock autoLock(mLock); 1444 return seekTo_l(timeUs); 1445 } 1446 1447 return OK; 1448 } 1449 1450 status_t AwesomePlayer::seekTo_l(int64_t timeUs) { 1451 if (mFlags & CACHE_UNDERRUN) { 1452 modifyFlags(CACHE_UNDERRUN, CLEAR); 1453 play_l(); 1454 } 1455 1456 if ((mFlags & PLAYING) && mVideoSource != NULL && (mFlags & VIDEO_AT_EOS)) { 1457 // Video playback completed before, there's no pending 1458 // video event right now. In order for this new seek 1459 // to be honored, we need to post one. 1460 1461 postVideoEvent_l(); 1462 } 1463 1464 mSeeking = SEEK; 1465 mSeekNotificationSent = false; 1466 mSeekTimeUs = timeUs; 1467 modifyFlags((AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS), CLEAR); 1468 1469 if (mFlags & PLAYING) { 1470 notifyListener_l(MEDIA_PAUSED); 1471 mMediaRenderingStartGeneration = ++mStartGeneration; 1472 } 1473 1474 seekAudioIfNecessary_l(); 1475 1476 if (mFlags & TEXTPLAYER_INITIALIZED) { 1477 mTextDriver->seekToAsync(mSeekTimeUs); 1478 } 1479 1480 if (!(mFlags & PLAYING)) { 1481 ALOGV("seeking while paused, sending SEEK_COMPLETE notification" 1482 " immediately."); 1483 1484 notifyListener_l(MEDIA_SEEK_COMPLETE); 1485 mSeekNotificationSent = true; 1486 1487 if ((mFlags & PREPARED) && mVideoSource != NULL) { 1488 modifyFlags(SEEK_PREVIEW, SET); 1489 postVideoEvent_l(); 1490 } 1491 } 1492 1493 return OK; 1494 } 1495 1496 void AwesomePlayer::seekAudioIfNecessary_l() { 1497 if (mSeeking != NO_SEEK && mVideoSource == NULL && mAudioPlayer != NULL) { 1498 mAudioPlayer->seekTo(mSeekTimeUs); 1499 1500 mWatchForAudioSeekComplete = true; 1501 mWatchForAudioEOS = true; 1502 1503 if (mDecryptHandle != NULL) { 1504 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, 1505 Playback::PAUSE, 0); 1506 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, 1507 Playback::START, mSeekTimeUs / 1000); 1508 } 1509 } 1510 } 1511 1512 void AwesomePlayer::setAudioSource(sp<MediaSource> source) { 1513 CHECK(source != NULL); 1514 1515 mAudioTrack = source; 1516 } 1517 1518 void AwesomePlayer::addTextSource_l(size_t trackIndex, const sp<MediaSource>& source) { 1519 CHECK(source != NULL); 1520 1521 if (mTextDriver == NULL) { 1522 mTextDriver = new TimedTextDriver(mListener, mHTTPService); 1523 } 1524 1525 mTextDriver->addInBandTextSource(trackIndex, source); 1526 } 1527 1528 status_t AwesomePlayer::initAudioDecoder() { 1529 ATRACE_CALL(); 1530 1531 sp<MetaData> meta = mAudioTrack->getFormat(); 1532 1533 const char *mime; 1534 CHECK(meta->findCString(kKeyMIMEType, &mime)); 1535 // Check whether there is a hardware codec for this stream 1536 // This doesn't guarantee that the hardware has a free stream 1537 // but it avoids us attempting to open (and re-open) an offload 1538 // stream to hardware that doesn't have the necessary codec 1539 audio_stream_type_t streamType = AUDIO_STREAM_MUSIC; 1540 if (mAudioSink != NULL) { 1541 streamType = mAudioSink->getAudioStreamType(); 1542 } 1543 1544 mOffloadAudio = canOffloadStream(meta, (mVideoSource != NULL), 1545 isStreamingHTTP(), streamType); 1546 1547 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) { 1548 ALOGV("createAudioPlayer: bypass OMX (raw)"); 1549 mAudioSource = mAudioTrack; 1550 } else { 1551 // If offloading we still create a OMX decoder as a fall-back 1552 // but we don't start it 1553 mOmxSource = OMXCodec::Create( 1554 mClient.interface(), mAudioTrack->getFormat(), 1555 false, // createEncoder 1556 mAudioTrack); 1557 1558 if (mOffloadAudio) { 1559 ALOGV("createAudioPlayer: bypass OMX (offload)"); 1560 mAudioSource = mAudioTrack; 1561 } else { 1562 mAudioSource = mOmxSource; 1563 } 1564 } 1565 1566 if (mAudioSource != NULL) { 1567 int64_t durationUs; 1568 if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) { 1569 Mutex::Autolock autoLock(mMiscStateLock); 1570 if (mDurationUs < 0 || durationUs > mDurationUs) { 1571 mDurationUs = durationUs; 1572 } 1573 } 1574 1575 status_t err = mAudioSource->start(); 1576 1577 if (err != OK) { 1578 mAudioSource.clear(); 1579 mOmxSource.clear(); 1580 return err; 1581 } 1582 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_QCELP)) { 1583 // For legacy reasons we're simply going to ignore the absence 1584 // of an audio decoder for QCELP instead of aborting playback 1585 // altogether. 1586 return OK; 1587 } 1588 1589 if (mAudioSource != NULL) { 1590 Mutex::Autolock autoLock(mStatsLock); 1591 TrackStat *stat = &mStats.mTracks.editItemAt(mStats.mAudioTrackIndex); 1592 const char *component; 1593 if (!mAudioSource->getFormat() 1594 ->findCString(kKeyDecoderComponent, &component)) { 1595 component = "none"; 1596 } 1597 1598 stat->mDecoderName = component; 1599 } 1600 1601 return mAudioSource != NULL ? OK : UNKNOWN_ERROR; 1602 } 1603 1604 void AwesomePlayer::setVideoSource(sp<MediaSource> source) { 1605 CHECK(source != NULL); 1606 1607 mVideoTrack = source; 1608 } 1609 1610 status_t AwesomePlayer::initVideoDecoder(uint32_t flags) { 1611 ATRACE_CALL(); 1612 1613 // Either the application or the DRM system can independently say 1614 // that there must be a hardware-protected path to an external video sink. 1615 // For now we always require a hardware-protected path to external video sink 1616 // if content is DRMed, but eventually this could be optional per DRM agent. 1617 // When the application wants protection, then 1618 // (USE_SURFACE_ALLOC && (mSurface != 0) && 1619 // (mSurface->getFlags() & ISurfaceComposer::eProtectedByApp)) 1620 // will be true, but that part is already handled by SurfaceFlinger. 1621 1622 #ifdef DEBUG_HDCP 1623 // For debugging, we allow a system property to control the protected usage. 1624 // In case of uninitialized or unexpected property, we default to "DRM only". 1625 bool setProtectionBit = false; 1626 char value[PROPERTY_VALUE_MAX]; 1627 if (property_get("persist.sys.hdcp_checking", value, NULL)) { 1628 if (!strcmp(value, "never")) { 1629 // nop 1630 } else if (!strcmp(value, "always")) { 1631 setProtectionBit = true; 1632 } else if (!strcmp(value, "drm-only")) { 1633 if (mDecryptHandle != NULL) { 1634 setProtectionBit = true; 1635 } 1636 // property value is empty, or unexpected value 1637 } else { 1638 if (mDecryptHandle != NULL) { 1639 setProtectionBit = true; 1640 } 1641 } 1642 // can' read property value 1643 } else { 1644 if (mDecryptHandle != NULL) { 1645 setProtectionBit = true; 1646 } 1647 } 1648 // note that usage bit is already cleared, so no need to clear it in the "else" case 1649 if (setProtectionBit) { 1650 flags |= OMXCodec::kEnableGrallocUsageProtected; 1651 } 1652 #else 1653 if (mDecryptHandle != NULL) { 1654 flags |= OMXCodec::kEnableGrallocUsageProtected; 1655 } 1656 #endif 1657 ALOGV("initVideoDecoder flags=0x%x", flags); 1658 mVideoSource = OMXCodec::Create( 1659 mClient.interface(), mVideoTrack->getFormat(), 1660 false, // createEncoder 1661 mVideoTrack, 1662 NULL, flags, USE_SURFACE_ALLOC ? mNativeWindow : NULL); 1663 1664 if (mVideoSource != NULL) { 1665 int64_t durationUs; 1666 if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) { 1667 Mutex::Autolock autoLock(mMiscStateLock); 1668 if (mDurationUs < 0 || durationUs > mDurationUs) { 1669 mDurationUs = durationUs; 1670 } 1671 } 1672 1673 status_t err = mVideoSource->start(); 1674 1675 if (err != OK) { 1676 ALOGE("failed to start video source"); 1677 mVideoSource.clear(); 1678 return err; 1679 } 1680 } 1681 1682 if (mVideoSource != NULL) { 1683 const char *componentName; 1684 CHECK(mVideoSource->getFormat() 1685 ->findCString(kKeyDecoderComponent, &componentName)); 1686 1687 { 1688 Mutex::Autolock autoLock(mStatsLock); 1689 TrackStat *stat = &mStats.mTracks.editItemAt(mStats.mVideoTrackIndex); 1690 1691 stat->mDecoderName = componentName; 1692 } 1693 1694 static const char *kPrefix = "OMX.Nvidia."; 1695 static const char *kSuffix = ".decode"; 1696 static const size_t kSuffixLength = strlen(kSuffix); 1697 1698 size_t componentNameLength = strlen(componentName); 1699 1700 if (!strncmp(componentName, kPrefix, strlen(kPrefix)) 1701 && componentNameLength >= kSuffixLength 1702 && !strcmp(&componentName[ 1703 componentNameLength - kSuffixLength], kSuffix)) { 1704 modifyFlags(SLOW_DECODER_HACK, SET); 1705 } 1706 } 1707 1708 return mVideoSource != NULL ? OK : UNKNOWN_ERROR; 1709 } 1710 1711 void AwesomePlayer::finishSeekIfNecessary(int64_t videoTimeUs) { 1712 ATRACE_CALL(); 1713 1714 if (mSeeking == SEEK_VIDEO_ONLY) { 1715 mSeeking = NO_SEEK; 1716 return; 1717 } 1718 1719 if (mSeeking == NO_SEEK || (mFlags & SEEK_PREVIEW)) { 1720 return; 1721 } 1722 1723 // If we paused, then seeked, then resumed, it is possible that we have 1724 // signaled SEEK_COMPLETE at a copmletely different media time than where 1725 // we are now resuming. Signal new position to media time provider. 1726 // Cannot signal another SEEK_COMPLETE, as existing clients may not expect 1727 // multiple SEEK_COMPLETE responses to a single seek() request. 1728 if (mSeekNotificationSent && abs(mSeekTimeUs - videoTimeUs) > 10000) { 1729 // notify if we are resuming more than 10ms away from desired seek time 1730 notifyListener_l(MEDIA_SKIPPED); 1731 } 1732 1733 if (mAudioPlayer != NULL) { 1734 ALOGV("seeking audio to %" PRId64 " us (%.2f secs).", videoTimeUs, videoTimeUs / 1E6); 1735 1736 // If we don't have a video time, seek audio to the originally 1737 // requested seek time instead. 1738 1739 mAudioPlayer->seekTo(videoTimeUs < 0 ? mSeekTimeUs : videoTimeUs); 1740 mWatchForAudioSeekComplete = true; 1741 mWatchForAudioEOS = true; 1742 } else if (!mSeekNotificationSent) { 1743 // If we're playing video only, report seek complete now, 1744 // otherwise audio player will notify us later. 1745 notifyListener_l(MEDIA_SEEK_COMPLETE); 1746 mSeekNotificationSent = true; 1747 } 1748 1749 modifyFlags(FIRST_FRAME, SET); 1750 mSeeking = NO_SEEK; 1751 1752 if (mDecryptHandle != NULL) { 1753 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, 1754 Playback::PAUSE, 0); 1755 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, 1756 Playback::START, videoTimeUs / 1000); 1757 } 1758 } 1759 1760 void AwesomePlayer::onVideoEvent() { 1761 ATRACE_CALL(); 1762 Mutex::Autolock autoLock(mLock); 1763 if (!mVideoEventPending) { 1764 // The event has been cancelled in reset_l() but had already 1765 // been scheduled for execution at that time. 1766 return; 1767 } 1768 mVideoEventPending = false; 1769 1770 if (mSeeking != NO_SEEK) { 1771 if (mVideoBuffer) { 1772 mVideoBuffer->release(); 1773 mVideoBuffer = NULL; 1774 } 1775 1776 if (mSeeking == SEEK && isStreamingHTTP() && mAudioSource != NULL 1777 && !(mFlags & SEEK_PREVIEW)) { 1778 // We're going to seek the video source first, followed by 1779 // the audio source. 1780 // In order to avoid jumps in the DataSource offset caused by 1781 // the audio codec prefetching data from the old locations 1782 // while the video codec is already reading data from the new 1783 // locations, we'll "pause" the audio source, causing it to 1784 // stop reading input data until a subsequent seek. 1785 1786 if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) { 1787 mAudioPlayer->pause(); 1788 1789 modifyFlags(AUDIO_RUNNING, CLEAR); 1790 } 1791 mAudioSource->pause(); 1792 } 1793 } 1794 1795 if (!mVideoBuffer) { 1796 MediaSource::ReadOptions options; 1797 if (mSeeking != NO_SEEK) { 1798 ALOGV("seeking to %" PRId64 " us (%.2f secs)", mSeekTimeUs, mSeekTimeUs / 1E6); 1799 1800 options.setSeekTo( 1801 mSeekTimeUs, 1802 mSeeking == SEEK_VIDEO_ONLY 1803 ? MediaSource::ReadOptions::SEEK_NEXT_SYNC 1804 : MediaSource::ReadOptions::SEEK_CLOSEST_SYNC); 1805 } 1806 for (;;) { 1807 status_t err = mVideoSource->read(&mVideoBuffer, &options); 1808 options.clearSeekTo(); 1809 1810 if (err != OK) { 1811 CHECK(mVideoBuffer == NULL); 1812 1813 if (err == INFO_FORMAT_CHANGED) { 1814 ALOGV("VideoSource signalled format change."); 1815 1816 notifyVideoSize_l(); 1817 1818 if (mVideoRenderer != NULL) { 1819 mVideoRendererIsPreview = false; 1820 initRenderer_l(); 1821 } 1822 continue; 1823 } 1824 1825 // So video playback is complete, but we may still have 1826 // a seek request pending that needs to be applied 1827 // to the audio track. 1828 if (mSeeking != NO_SEEK) { 1829 ALOGV("video stream ended while seeking!"); 1830 } 1831 finishSeekIfNecessary(-1); 1832 1833 if (mAudioPlayer != NULL 1834 && !(mFlags & (AUDIO_RUNNING | SEEK_PREVIEW))) { 1835 startAudioPlayer_l(); 1836 } 1837 1838 modifyFlags(VIDEO_AT_EOS, SET); 1839 postStreamDoneEvent_l(err); 1840 return; 1841 } 1842 1843 if (mVideoBuffer->range_length() == 0) { 1844 // Some decoders, notably the PV AVC software decoder 1845 // return spurious empty buffers that we just want to ignore. 1846 1847 mVideoBuffer->release(); 1848 mVideoBuffer = NULL; 1849 continue; 1850 } 1851 1852 break; 1853 } 1854 1855 { 1856 Mutex::Autolock autoLock(mStatsLock); 1857 ++mStats.mNumVideoFramesDecoded; 1858 } 1859 } 1860 1861 int64_t timeUs; 1862 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs)); 1863 1864 mLastVideoTimeUs = timeUs; 1865 1866 if (mSeeking == SEEK_VIDEO_ONLY) { 1867 if (mSeekTimeUs > timeUs) { 1868 ALOGI("XXX mSeekTimeUs = %" PRId64 " us, timeUs = %" PRId64 " us", 1869 mSeekTimeUs, timeUs); 1870 } 1871 } 1872 1873 { 1874 Mutex::Autolock autoLock(mMiscStateLock); 1875 mVideoTimeUs = timeUs; 1876 } 1877 1878 SeekType wasSeeking = mSeeking; 1879 finishSeekIfNecessary(timeUs); 1880 1881 if (mAudioPlayer != NULL && !(mFlags & (AUDIO_RUNNING | SEEK_PREVIEW))) { 1882 status_t err = startAudioPlayer_l(); 1883 if (err != OK) { 1884 ALOGE("Starting the audio player failed w/ err %d", err); 1885 return; 1886 } 1887 } 1888 1889 if ((mFlags & TEXTPLAYER_INITIALIZED) 1890 && !(mFlags & (TEXT_RUNNING | SEEK_PREVIEW))) { 1891 mTextDriver->start(); 1892 modifyFlags(TEXT_RUNNING, SET); 1893 } 1894 1895 TimeSource *ts = 1896 ((mFlags & AUDIO_AT_EOS) || !(mFlags & AUDIOPLAYER_STARTED)) 1897 ? &mSystemTimeSource : mTimeSource; 1898 int64_t systemTimeUs = mSystemTimeSource.getRealTimeUs(); 1899 int64_t looperTimeUs = ALooper::GetNowUs(); 1900 1901 if (mFlags & FIRST_FRAME) { 1902 modifyFlags(FIRST_FRAME, CLEAR); 1903 mSinceLastDropped = 0; 1904 mClockEstimator->reset(); 1905 mTimeSourceDeltaUs = estimateRealTimeUs(ts, systemTimeUs) - timeUs; 1906 } 1907 1908 int64_t realTimeUs, mediaTimeUs; 1909 if (!(mFlags & AUDIO_AT_EOS) && mAudioPlayer != NULL 1910 && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) { 1911 ALOGV("updating TSdelta (%" PRId64 " => %" PRId64 " change %" PRId64 ")", 1912 mTimeSourceDeltaUs, realTimeUs - mediaTimeUs, 1913 mTimeSourceDeltaUs - (realTimeUs - mediaTimeUs)); 1914 ATRACE_INT("TS delta change (ms)", (mTimeSourceDeltaUs - (realTimeUs - mediaTimeUs)) / 1E3); 1915 mTimeSourceDeltaUs = realTimeUs - mediaTimeUs; 1916 } 1917 1918 if (wasSeeking == SEEK_VIDEO_ONLY) { 1919 int64_t nowUs = estimateRealTimeUs(ts, systemTimeUs) - mTimeSourceDeltaUs; 1920 1921 int64_t latenessUs = nowUs - timeUs; 1922 1923 ATRACE_INT("Video Lateness (ms)", latenessUs / 1E3); 1924 1925 if (latenessUs > 0) { 1926 ALOGI("after SEEK_VIDEO_ONLY we're late by %.2f secs", latenessUs / 1E6); 1927 } 1928 } 1929 1930 int64_t latenessUs = 0; 1931 if (wasSeeking == NO_SEEK) { 1932 // Let's display the first frame after seeking right away. 1933 1934 int64_t nowUs = estimateRealTimeUs(ts, systemTimeUs) - mTimeSourceDeltaUs; 1935 1936 latenessUs = nowUs - timeUs; 1937 1938 ATRACE_INT("Video Lateness (ms)", latenessUs / 1E3); 1939 1940 if (latenessUs > 500000ll 1941 && mAudioPlayer != NULL 1942 && mAudioPlayer->getMediaTimeMapping( 1943 &realTimeUs, &mediaTimeUs)) { 1944 if (mWVMExtractor == NULL) { 1945 ALOGI("we're much too late (%.2f secs), video skipping ahead", 1946 latenessUs / 1E6); 1947 1948 mVideoBuffer->release(); 1949 mVideoBuffer = NULL; 1950 1951 mSeeking = SEEK_VIDEO_ONLY; 1952 mSeekTimeUs = mediaTimeUs; 1953 1954 postVideoEvent_l(); 1955 return; 1956 } else { 1957 // The widevine extractor doesn't deal well with seeking 1958 // audio and video independently. We'll just have to wait 1959 // until the decoder catches up, which won't be long at all. 1960 ALOGI("we're very late (%.2f secs)", latenessUs / 1E6); 1961 } 1962 } 1963 1964 if (latenessUs > 40000) { 1965 // We're more than 40ms late. 1966 ALOGV("we're late by %" PRId64 " us (%.2f secs)", 1967 latenessUs, latenessUs / 1E6); 1968 1969 if (!(mFlags & SLOW_DECODER_HACK) 1970 || mSinceLastDropped > FRAME_DROP_FREQ) 1971 { 1972 ALOGV("we're late by %" PRId64 " us (%.2f secs) dropping " 1973 "one after %d frames", 1974 latenessUs, latenessUs / 1E6, mSinceLastDropped); 1975 1976 mSinceLastDropped = 0; 1977 mVideoBuffer->release(); 1978 mVideoBuffer = NULL; 1979 1980 { 1981 Mutex::Autolock autoLock(mStatsLock); 1982 ++mStats.mNumVideoFramesDropped; 1983 } 1984 1985 postVideoEvent_l(0); 1986 return; 1987 } 1988 } 1989 1990 if (latenessUs < -30000) { 1991 // We're more than 30ms early, schedule at most 20 ms before time due 1992 postVideoEvent_l(latenessUs < -60000 ? 30000 : -latenessUs - 20000); 1993 return; 1994 } 1995 } 1996 1997 if ((mNativeWindow != NULL) 1998 && (mVideoRendererIsPreview || mVideoRenderer == NULL)) { 1999 mVideoRendererIsPreview = false; 2000 2001 initRenderer_l(); 2002 } 2003 2004 if (mVideoRenderer != NULL) { 2005 mSinceLastDropped++; 2006 mVideoBuffer->meta_data()->setInt64(kKeyTime, looperTimeUs - latenessUs); 2007 2008 mVideoRenderer->render(mVideoBuffer); 2009 if (!mVideoRenderingStarted) { 2010 mVideoRenderingStarted = true; 2011 notifyListener_l(MEDIA_INFO, MEDIA_INFO_RENDERING_START); 2012 } 2013 2014 if (mFlags & PLAYING) { 2015 notifyIfMediaStarted_l(); 2016 } 2017 } 2018 2019 mVideoBuffer->release(); 2020 mVideoBuffer = NULL; 2021 2022 if (wasSeeking != NO_SEEK && (mFlags & SEEK_PREVIEW)) { 2023 modifyFlags(SEEK_PREVIEW, CLEAR); 2024 return; 2025 } 2026 2027 /* get next frame time */ 2028 if (wasSeeking == NO_SEEK) { 2029 MediaSource::ReadOptions options; 2030 for (;;) { 2031 status_t err = mVideoSource->read(&mVideoBuffer, &options); 2032 if (err != OK) { 2033 // deal with any errors next time 2034 CHECK(mVideoBuffer == NULL); 2035 postVideoEvent_l(0); 2036 return; 2037 } 2038 2039 if (mVideoBuffer->range_length() != 0) { 2040 break; 2041 } 2042 2043 // Some decoders, notably the PV AVC software decoder 2044 // return spurious empty buffers that we just want to ignore. 2045 2046 mVideoBuffer->release(); 2047 mVideoBuffer = NULL; 2048 } 2049 2050 { 2051 Mutex::Autolock autoLock(mStatsLock); 2052 ++mStats.mNumVideoFramesDecoded; 2053 } 2054 2055 int64_t nextTimeUs; 2056 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &nextTimeUs)); 2057 systemTimeUs = mSystemTimeSource.getRealTimeUs(); 2058 int64_t delayUs = nextTimeUs - estimateRealTimeUs(ts, systemTimeUs) + mTimeSourceDeltaUs; 2059 ATRACE_INT("Frame delta (ms)", (nextTimeUs - timeUs) / 1E3); 2060 ALOGV("next frame in %" PRId64, delayUs); 2061 // try to schedule 30ms before time due 2062 postVideoEvent_l(delayUs > 60000 ? 30000 : (delayUs < 30000 ? 0 : delayUs - 30000)); 2063 return; 2064 } 2065 2066 postVideoEvent_l(); 2067 } 2068 2069 int64_t AwesomePlayer::estimateRealTimeUs(TimeSource *ts, int64_t systemTimeUs) { 2070 if (ts == &mSystemTimeSource) { 2071 return systemTimeUs; 2072 } else { 2073 return (int64_t)mClockEstimator->estimate(systemTimeUs, ts->getRealTimeUs()); 2074 } 2075 } 2076 2077 void AwesomePlayer::postVideoEvent_l(int64_t delayUs) { 2078 ATRACE_CALL(); 2079 2080 if (mVideoEventPending) { 2081 return; 2082 } 2083 2084 mVideoEventPending = true; 2085 mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs); 2086 } 2087 2088 void AwesomePlayer::postStreamDoneEvent_l(status_t status) { 2089 if (mStreamDoneEventPending) { 2090 return; 2091 } 2092 mStreamDoneEventPending = true; 2093 2094 mStreamDoneStatus = status; 2095 mQueue.postEvent(mStreamDoneEvent); 2096 } 2097 2098 void AwesomePlayer::postBufferingEvent_l() { 2099 if (mBufferingEventPending) { 2100 return; 2101 } 2102 mBufferingEventPending = true; 2103 mQueue.postEventWithDelay(mBufferingEvent, 1000000ll); 2104 } 2105 2106 void AwesomePlayer::postVideoLagEvent_l() { 2107 if (mVideoLagEventPending) { 2108 return; 2109 } 2110 mVideoLagEventPending = true; 2111 mQueue.postEventWithDelay(mVideoLagEvent, 1000000ll); 2112 } 2113 2114 void AwesomePlayer::postCheckAudioStatusEvent(int64_t delayUs) { 2115 Mutex::Autolock autoLock(mAudioLock); 2116 if (mAudioStatusEventPending) { 2117 return; 2118 } 2119 mAudioStatusEventPending = true; 2120 // Do not honor delay when looping in order to limit audio gap 2121 if (mFlags & (LOOPING | AUTO_LOOPING)) { 2122 delayUs = 0; 2123 } 2124 mQueue.postEventWithDelay(mCheckAudioStatusEvent, delayUs); 2125 } 2126 2127 void AwesomePlayer::postAudioTearDownEvent(int64_t delayUs) { 2128 Mutex::Autolock autoLock(mAudioLock); 2129 if (mAudioTearDownEventPending) { 2130 return; 2131 } 2132 mAudioTearDownEventPending = true; 2133 mQueue.postEventWithDelay(mAudioTearDownEvent, delayUs); 2134 } 2135 2136 void AwesomePlayer::onCheckAudioStatus() { 2137 { 2138 Mutex::Autolock autoLock(mAudioLock); 2139 if (!mAudioStatusEventPending) { 2140 // Event was dispatched and while we were blocking on the mutex, 2141 // has already been cancelled. 2142 return; 2143 } 2144 2145 mAudioStatusEventPending = false; 2146 } 2147 2148 Mutex::Autolock autoLock(mLock); 2149 2150 if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) { 2151 mWatchForAudioSeekComplete = false; 2152 2153 if (!mSeekNotificationSent) { 2154 notifyListener_l(MEDIA_SEEK_COMPLETE); 2155 mSeekNotificationSent = true; 2156 } 2157 2158 if (mVideoSource == NULL) { 2159 // For video the mSeeking flag is always reset in finishSeekIfNecessary 2160 mSeeking = NO_SEEK; 2161 } 2162 2163 notifyIfMediaStarted_l(); 2164 } 2165 2166 status_t finalStatus; 2167 if (mWatchForAudioEOS && mAudioPlayer->reachedEOS(&finalStatus)) { 2168 mWatchForAudioEOS = false; 2169 modifyFlags(AUDIO_AT_EOS, SET); 2170 modifyFlags(FIRST_FRAME, SET); 2171 postStreamDoneEvent_l(finalStatus); 2172 } 2173 } 2174 2175 status_t AwesomePlayer::prepare() { 2176 ATRACE_CALL(); 2177 Mutex::Autolock autoLock(mLock); 2178 return prepare_l(); 2179 } 2180 2181 status_t AwesomePlayer::prepare_l() { 2182 if (mFlags & PREPARED) { 2183 return OK; 2184 } 2185 2186 if (mFlags & PREPARING) { 2187 return UNKNOWN_ERROR; 2188 } 2189 2190 mIsAsyncPrepare = false; 2191 status_t err = prepareAsync_l(); 2192 2193 if (err != OK) { 2194 return err; 2195 } 2196 2197 while (mFlags & PREPARING) { 2198 mPreparedCondition.wait(mLock); 2199 } 2200 2201 return mPrepareResult; 2202 } 2203 2204 status_t AwesomePlayer::prepareAsync() { 2205 ATRACE_CALL(); 2206 Mutex::Autolock autoLock(mLock); 2207 2208 if (mFlags & PREPARING) { 2209 return UNKNOWN_ERROR; // async prepare already pending 2210 } 2211 2212 mIsAsyncPrepare = true; 2213 return prepareAsync_l(); 2214 } 2215 2216 status_t AwesomePlayer::prepareAsync_l() { 2217 if (mFlags & PREPARING) { 2218 return UNKNOWN_ERROR; // async prepare already pending 2219 } 2220 2221 if (!mQueueStarted) { 2222 mQueue.start(); 2223 mQueueStarted = true; 2224 } 2225 2226 modifyFlags(PREPARING, SET); 2227 mAsyncPrepareEvent = new AwesomeEvent( 2228 this, &AwesomePlayer::onPrepareAsyncEvent); 2229 2230 mQueue.postEvent(mAsyncPrepareEvent); 2231 2232 return OK; 2233 } 2234 2235 status_t AwesomePlayer::finishSetDataSource_l() { 2236 ATRACE_CALL(); 2237 sp<DataSource> dataSource; 2238 2239 bool isWidevineStreaming = false; 2240 if (!strncasecmp("widevine://", mUri.string(), 11)) { 2241 isWidevineStreaming = true; 2242 2243 String8 newURI = String8("http://"); 2244 newURI.append(mUri.string() + 11); 2245 2246 mUri = newURI; 2247 } 2248 2249 AString sniffedMIME; 2250 2251 if (!strncasecmp("http://", mUri.string(), 7) 2252 || !strncasecmp("https://", mUri.string(), 8) 2253 || isWidevineStreaming) { 2254 if (mHTTPService == NULL) { 2255 ALOGE("Attempt to play media from http URI without HTTP service."); 2256 return UNKNOWN_ERROR; 2257 } 2258 2259 sp<IMediaHTTPConnection> conn = mHTTPService->makeHTTPConnection(); 2260 mConnectingDataSource = new MediaHTTP(conn); 2261 2262 String8 cacheConfig; 2263 bool disconnectAtHighwatermark; 2264 NuCachedSource2::RemoveCacheSpecificHeaders( 2265 &mUriHeaders, &cacheConfig, &disconnectAtHighwatermark); 2266 2267 mLock.unlock(); 2268 status_t err = mConnectingDataSource->connect(mUri, &mUriHeaders); 2269 // force connection at this point, to avoid a race condition between getMIMEType and the 2270 // caching datasource constructed below, which could result in multiple requests to the 2271 // server, and/or failed connections. 2272 String8 contentType = mConnectingDataSource->getMIMEType(); 2273 mLock.lock(); 2274 2275 if (err != OK) { 2276 mConnectingDataSource.clear(); 2277 2278 ALOGI("mConnectingDataSource->connect() returned %d", err); 2279 return err; 2280 } 2281 2282 if (!isWidevineStreaming) { 2283 // The widevine extractor does its own caching. 2284 2285 #if 0 2286 mCachedSource = new NuCachedSource2( 2287 new ThrottledSource( 2288 mConnectingDataSource, 50 * 1024 /* bytes/sec */)); 2289 #else 2290 mCachedSource = new NuCachedSource2( 2291 mConnectingDataSource, 2292 cacheConfig.isEmpty() ? NULL : cacheConfig.string(), 2293 disconnectAtHighwatermark); 2294 #endif 2295 2296 dataSource = mCachedSource; 2297 } else { 2298 dataSource = mConnectingDataSource; 2299 } 2300 2301 mConnectingDataSource.clear(); 2302 2303 if (strncasecmp(contentType.string(), "audio/", 6)) { 2304 // We're not doing this for streams that appear to be audio-only 2305 // streams to ensure that even low bandwidth streams start 2306 // playing back fairly instantly. 2307 2308 // We're going to prefill the cache before trying to instantiate 2309 // the extractor below, as the latter is an operation that otherwise 2310 // could block on the datasource for a significant amount of time. 2311 // During that time we'd be unable to abort the preparation phase 2312 // without this prefill. 2313 if (mCachedSource != NULL) { 2314 // We're going to prefill the cache before trying to instantiate 2315 // the extractor below, as the latter is an operation that otherwise 2316 // could block on the datasource for a significant amount of time. 2317 // During that time we'd be unable to abort the preparation phase 2318 // without this prefill. 2319 2320 mLock.unlock(); 2321 2322 // Initially make sure we have at least 192 KB for the sniff 2323 // to complete without blocking. 2324 static const size_t kMinBytesForSniffing = 192 * 1024; 2325 2326 off64_t metaDataSize = -1ll; 2327 for (;;) { 2328 status_t finalStatus; 2329 size_t cachedDataRemaining = 2330 mCachedSource->approxDataRemaining(&finalStatus); 2331 2332 if (finalStatus != OK 2333 || (metaDataSize >= 0 2334 && (off64_t)cachedDataRemaining >= metaDataSize) 2335 || (mFlags & PREPARE_CANCELLED)) { 2336 break; 2337 } 2338 2339 ALOGV("now cached %zu bytes of data", cachedDataRemaining); 2340 2341 if (metaDataSize < 0 2342 && cachedDataRemaining >= kMinBytesForSniffing) { 2343 String8 tmp; 2344 float confidence; 2345 sp<AMessage> meta; 2346 if (!dataSource->sniff(&tmp, &confidence, &meta)) { 2347 mLock.lock(); 2348 return UNKNOWN_ERROR; 2349 } 2350 2351 // We successfully identified the file's extractor to 2352 // be, remember this mime type so we don't have to 2353 // sniff it again when we call MediaExtractor::Create() 2354 // below. 2355 sniffedMIME = tmp.string(); 2356 2357 if (meta == NULL 2358 || !meta->findInt64("meta-data-size", 2359 reinterpret_cast<int64_t*>(&metaDataSize))) { 2360 metaDataSize = kHighWaterMarkBytes; 2361 } 2362 2363 CHECK_GE(metaDataSize, 0ll); 2364 ALOGV("metaDataSize = %lld bytes", metaDataSize); 2365 } 2366 2367 usleep(200000); 2368 } 2369 2370 mLock.lock(); 2371 } 2372 2373 if (mFlags & PREPARE_CANCELLED) { 2374 ALOGI("Prepare cancelled while waiting for initial cache fill."); 2375 return UNKNOWN_ERROR; 2376 } 2377 } 2378 } else { 2379 dataSource = DataSource::CreateFromURI( 2380 mHTTPService, mUri.string(), &mUriHeaders); 2381 } 2382 2383 if (dataSource == NULL) { 2384 return UNKNOWN_ERROR; 2385 } 2386 2387 sp<MediaExtractor> extractor; 2388 2389 if (isWidevineStreaming) { 2390 String8 mimeType; 2391 float confidence; 2392 sp<AMessage> dummy; 2393 bool success; 2394 2395 // SniffWVM is potentially blocking since it may require network access. 2396 // Do not call it with mLock held. 2397 mLock.unlock(); 2398 success = SniffWVM(dataSource, &mimeType, &confidence, &dummy); 2399 mLock.lock(); 2400 2401 if (!success 2402 || strcasecmp( 2403 mimeType.string(), MEDIA_MIMETYPE_CONTAINER_WVM)) { 2404 return ERROR_UNSUPPORTED; 2405 } 2406 2407 mWVMExtractor = new WVMExtractor(dataSource); 2408 mWVMExtractor->setAdaptiveStreamingMode(true); 2409 if (mUIDValid) 2410 mWVMExtractor->setUID(mUID); 2411 extractor = mWVMExtractor; 2412 } else { 2413 extractor = MediaExtractor::Create( 2414 dataSource, sniffedMIME.empty() ? NULL : sniffedMIME.c_str()); 2415 2416 if (extractor == NULL) { 2417 return UNKNOWN_ERROR; 2418 } 2419 } 2420 2421 if (extractor->getDrmFlag()) { 2422 checkDrmStatus(dataSource); 2423 } 2424 2425 status_t err = setDataSource_l(extractor); 2426 2427 if (err != OK) { 2428 mWVMExtractor.clear(); 2429 2430 return err; 2431 } 2432 2433 return OK; 2434 } 2435 2436 void AwesomePlayer::abortPrepare(status_t err) { 2437 CHECK(err != OK); 2438 2439 if (mIsAsyncPrepare) { 2440 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err); 2441 } 2442 2443 mPrepareResult = err; 2444 modifyFlags((PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED), CLEAR); 2445 mAsyncPrepareEvent = NULL; 2446 mPreparedCondition.broadcast(); 2447 mAudioTearDown = false; 2448 } 2449 2450 // static 2451 bool AwesomePlayer::ContinuePreparation(void *cookie) { 2452 AwesomePlayer *me = static_cast<AwesomePlayer *>(cookie); 2453 2454 return (me->mFlags & PREPARE_CANCELLED) == 0; 2455 } 2456 2457 void AwesomePlayer::onPrepareAsyncEvent() { 2458 Mutex::Autolock autoLock(mLock); 2459 beginPrepareAsync_l(); 2460 } 2461 2462 void AwesomePlayer::beginPrepareAsync_l() { 2463 if (mFlags & PREPARE_CANCELLED) { 2464 ALOGI("prepare was cancelled before doing anything"); 2465 abortPrepare(UNKNOWN_ERROR); 2466 return; 2467 } 2468 2469 if (mUri.size() > 0) { 2470 status_t err = finishSetDataSource_l(); 2471 2472 if (err != OK) { 2473 abortPrepare(err); 2474 return; 2475 } 2476 } 2477 2478 if (mVideoTrack != NULL && mVideoSource == NULL) { 2479 status_t err = initVideoDecoder(); 2480 2481 if (err != OK) { 2482 abortPrepare(err); 2483 return; 2484 } 2485 } 2486 2487 if (mAudioTrack != NULL && mAudioSource == NULL) { 2488 status_t err = initAudioDecoder(); 2489 2490 if (err != OK) { 2491 abortPrepare(err); 2492 return; 2493 } 2494 } 2495 2496 modifyFlags(PREPARING_CONNECTED, SET); 2497 2498 if (isStreamingHTTP()) { 2499 postBufferingEvent_l(); 2500 } else { 2501 finishAsyncPrepare_l(); 2502 } 2503 } 2504 2505 void AwesomePlayer::finishAsyncPrepare_l() { 2506 if (mIsAsyncPrepare) { 2507 if (mVideoSource == NULL) { 2508 notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0); 2509 } else { 2510 notifyVideoSize_l(); 2511 } 2512 2513 notifyListener_l(MEDIA_PREPARED); 2514 } 2515 2516 mPrepareResult = OK; 2517 modifyFlags((PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED), CLEAR); 2518 modifyFlags(PREPARED, SET); 2519 mAsyncPrepareEvent = NULL; 2520 mPreparedCondition.broadcast(); 2521 2522 if (mAudioTearDown) { 2523 if (mPrepareResult == OK) { 2524 if (mExtractorFlags & MediaExtractor::CAN_SEEK) { 2525 seekTo_l(mAudioTearDownPosition); 2526 } 2527 2528 if (mAudioTearDownWasPlaying) { 2529 modifyFlags(CACHE_UNDERRUN, CLEAR); 2530 play_l(); 2531 } 2532 } 2533 mAudioTearDown = false; 2534 } 2535 } 2536 2537 uint32_t AwesomePlayer::flags() const { 2538 return mExtractorFlags; 2539 } 2540 2541 void AwesomePlayer::postAudioEOS(int64_t delayUs) { 2542 postCheckAudioStatusEvent(delayUs); 2543 } 2544 2545 void AwesomePlayer::postAudioSeekComplete() { 2546 postCheckAudioStatusEvent(0); 2547 } 2548 2549 void AwesomePlayer::postAudioTearDown() { 2550 postAudioTearDownEvent(0); 2551 } 2552 2553 status_t AwesomePlayer::setParameter(int key, const Parcel &request) { 2554 switch (key) { 2555 case KEY_PARAMETER_CACHE_STAT_COLLECT_FREQ_MS: 2556 { 2557 return setCacheStatCollectFreq(request); 2558 } 2559 case KEY_PARAMETER_PLAYBACK_RATE_PERMILLE: 2560 { 2561 if (mAudioPlayer != NULL) { 2562 return mAudioPlayer->setPlaybackRatePermille(request.readInt32()); 2563 } else { 2564 return NO_INIT; 2565 } 2566 } 2567 default: 2568 { 2569 return ERROR_UNSUPPORTED; 2570 } 2571 } 2572 } 2573 2574 status_t AwesomePlayer::setCacheStatCollectFreq(const Parcel &request) { 2575 if (mCachedSource != NULL) { 2576 int32_t freqMs = request.readInt32(); 2577 ALOGD("Request to keep cache stats in the past %d ms", 2578 freqMs); 2579 return mCachedSource->setCacheStatCollectFreq(freqMs); 2580 } 2581 return ERROR_UNSUPPORTED; 2582 } 2583 2584 status_t AwesomePlayer::getParameter(int key, Parcel *reply) { 2585 switch (key) { 2586 case KEY_PARAMETER_AUDIO_CHANNEL_COUNT: 2587 { 2588 int32_t channelCount; 2589 if (mAudioTrack == 0 || 2590 !mAudioTrack->getFormat()->findInt32(kKeyChannelCount, &channelCount)) { 2591 channelCount = 0; 2592 } 2593 reply->writeInt32(channelCount); 2594 } 2595 return OK; 2596 default: 2597 { 2598 return ERROR_UNSUPPORTED; 2599 } 2600 } 2601 } 2602 2603 status_t AwesomePlayer::getTrackInfo(Parcel *reply) const { 2604 Mutex::Autolock autoLock(mLock); 2605 size_t trackCount = mExtractor->countTracks(); 2606 if (mTextDriver != NULL) { 2607 trackCount += mTextDriver->countExternalTracks(); 2608 } 2609 2610 reply->writeInt32(trackCount); 2611 for (size_t i = 0; i < mExtractor->countTracks(); ++i) { 2612 sp<MetaData> meta = mExtractor->getTrackMetaData(i); 2613 2614 const char *_mime; 2615 CHECK(meta->findCString(kKeyMIMEType, &_mime)); 2616 2617 String8 mime = String8(_mime); 2618 2619 reply->writeInt32(2); // 2 fields 2620 2621 if (!strncasecmp(mime.string(), "video/", 6)) { 2622 reply->writeInt32(MEDIA_TRACK_TYPE_VIDEO); 2623 } else if (!strncasecmp(mime.string(), "audio/", 6)) { 2624 reply->writeInt32(MEDIA_TRACK_TYPE_AUDIO); 2625 } else if (!strcasecmp(mime.string(), MEDIA_MIMETYPE_TEXT_3GPP)) { 2626 reply->writeInt32(MEDIA_TRACK_TYPE_TIMEDTEXT); 2627 } else { 2628 reply->writeInt32(MEDIA_TRACK_TYPE_UNKNOWN); 2629 } 2630 2631 const char *lang; 2632 if (!meta->findCString(kKeyMediaLanguage, &lang)) { 2633 lang = "und"; 2634 } 2635 reply->writeString16(String16(lang)); 2636 } 2637 2638 if (mTextDriver != NULL) { 2639 mTextDriver->getExternalTrackInfo(reply); 2640 } 2641 return OK; 2642 } 2643 2644 status_t AwesomePlayer::selectAudioTrack_l( 2645 const sp<MediaSource>& source, size_t trackIndex) { 2646 2647 ALOGI("selectAudioTrack_l: trackIndex=%zu, mFlags=0x%x", trackIndex, mFlags); 2648 2649 { 2650 Mutex::Autolock autoLock(mStatsLock); 2651 if ((ssize_t)trackIndex == mActiveAudioTrackIndex) { 2652 ALOGI("Track %zu is active. Does nothing.", trackIndex); 2653 return OK; 2654 } 2655 //mStats.mFlags = mFlags; 2656 } 2657 2658 if (mSeeking != NO_SEEK) { 2659 ALOGE("Selecting a track while seeking is not supported"); 2660 return ERROR_UNSUPPORTED; 2661 } 2662 2663 if ((mFlags & PREPARED) == 0) { 2664 ALOGE("Data source has not finished preparation"); 2665 return ERROR_UNSUPPORTED; 2666 } 2667 2668 CHECK(source != NULL); 2669 bool wasPlaying = (mFlags & PLAYING) != 0; 2670 2671 pause_l(); 2672 2673 int64_t curTimeUs; 2674 CHECK_EQ(getPosition(&curTimeUs), (status_t)OK); 2675 2676 if ((mAudioPlayer == NULL || !(mFlags & AUDIOPLAYER_STARTED)) 2677 && mAudioSource != NULL) { 2678 // If we had an audio player, it would have effectively 2679 // taken possession of the audio source and stopped it when 2680 // _it_ is stopped. Otherwise this is still our responsibility. 2681 mAudioSource->stop(); 2682 } 2683 mAudioSource.clear(); 2684 mOmxSource.clear(); 2685 2686 mTimeSource = NULL; 2687 2688 delete mAudioPlayer; 2689 mAudioPlayer = NULL; 2690 2691 modifyFlags(AUDIOPLAYER_STARTED, CLEAR); 2692 2693 setAudioSource(source); 2694 2695 modifyFlags(AUDIO_AT_EOS, CLEAR); 2696 modifyFlags(AT_EOS, CLEAR); 2697 2698 status_t err; 2699 if ((err = initAudioDecoder()) != OK) { 2700 ALOGE("Failed to init audio decoder: 0x%x", err); 2701 return err; 2702 } 2703 2704 mSeekNotificationSent = true; 2705 seekTo_l(curTimeUs); 2706 2707 if (wasPlaying) { 2708 play_l(); 2709 } 2710 2711 mActiveAudioTrackIndex = trackIndex; 2712 2713 return OK; 2714 } 2715 2716 status_t AwesomePlayer::selectTrack(size_t trackIndex, bool select) { 2717 ATRACE_CALL(); 2718 ALOGV("selectTrack: trackIndex = %zu and select=%d", trackIndex, select); 2719 Mutex::Autolock autoLock(mLock); 2720 size_t trackCount = mExtractor->countTracks(); 2721 if (mTextDriver != NULL) { 2722 trackCount += mTextDriver->countExternalTracks(); 2723 } 2724 if (trackIndex >= trackCount) { 2725 ALOGE("Track index (%zu) is out of range [0, %zu)", trackIndex, trackCount); 2726 return ERROR_OUT_OF_RANGE; 2727 } 2728 2729 bool isAudioTrack = false; 2730 if (trackIndex < mExtractor->countTracks()) { 2731 sp<MetaData> meta = mExtractor->getTrackMetaData(trackIndex); 2732 const char *mime; 2733 CHECK(meta->findCString(kKeyMIMEType, &mime)); 2734 isAudioTrack = !strncasecmp(mime, "audio/", 6); 2735 2736 if (!isAudioTrack && strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP) != 0) { 2737 ALOGE("Track %zu is not either audio or timed text", trackIndex); 2738 return ERROR_UNSUPPORTED; 2739 } 2740 } 2741 2742 if (isAudioTrack) { 2743 if (!select) { 2744 ALOGE("Deselect an audio track (%zu) is not supported", trackIndex); 2745 return ERROR_UNSUPPORTED; 2746 } 2747 return selectAudioTrack_l(mExtractor->getTrack(trackIndex), trackIndex); 2748 } 2749 2750 // Timed text track handling 2751 if (mTextDriver == NULL) { 2752 return INVALID_OPERATION; 2753 } 2754 2755 status_t err = OK; 2756 if (select) { 2757 err = mTextDriver->selectTrack(trackIndex); 2758 if (err == OK) { 2759 modifyFlags(TEXTPLAYER_INITIALIZED, SET); 2760 if (mFlags & PLAYING && !(mFlags & TEXT_RUNNING)) { 2761 mTextDriver->start(); 2762 modifyFlags(TEXT_RUNNING, SET); 2763 } 2764 } 2765 } else { 2766 err = mTextDriver->unselectTrack(trackIndex); 2767 if (err == OK) { 2768 modifyFlags(TEXTPLAYER_INITIALIZED, CLEAR); 2769 modifyFlags(TEXT_RUNNING, CLEAR); 2770 } 2771 } 2772 return err; 2773 } 2774 2775 size_t AwesomePlayer::countTracks() const { 2776 return mExtractor->countTracks() + mTextDriver->countExternalTracks(); 2777 } 2778 2779 status_t AwesomePlayer::setVideoScalingMode(int32_t mode) { 2780 Mutex::Autolock lock(mLock); 2781 return setVideoScalingMode_l(mode); 2782 } 2783 2784 status_t AwesomePlayer::setVideoScalingMode_l(int32_t mode) { 2785 mVideoScalingMode = mode; 2786 if (mNativeWindow != NULL) { 2787 status_t err = native_window_set_scaling_mode( 2788 mNativeWindow.get(), mVideoScalingMode); 2789 if (err != OK) { 2790 ALOGW("Failed to set scaling mode: %d", err); 2791 } 2792 return err; 2793 } 2794 return OK; 2795 } 2796 2797 status_t AwesomePlayer::invoke(const Parcel &request, Parcel *reply) { 2798 ATRACE_CALL(); 2799 if (NULL == reply) { 2800 return android::BAD_VALUE; 2801 } 2802 int32_t methodId; 2803 status_t ret = request.readInt32(&methodId); 2804 if (ret != android::OK) { 2805 return ret; 2806 } 2807 switch(methodId) { 2808 case INVOKE_ID_SET_VIDEO_SCALING_MODE: 2809 { 2810 int mode = request.readInt32(); 2811 return setVideoScalingMode(mode); 2812 } 2813 2814 case INVOKE_ID_GET_TRACK_INFO: 2815 { 2816 return getTrackInfo(reply); 2817 } 2818 case INVOKE_ID_ADD_EXTERNAL_SOURCE: 2819 { 2820 Mutex::Autolock autoLock(mLock); 2821 if (mTextDriver == NULL) { 2822 mTextDriver = new TimedTextDriver(mListener, mHTTPService); 2823 } 2824 // String values written in Parcel are UTF-16 values. 2825 String8 uri(request.readString16()); 2826 String8 mimeType(request.readString16()); 2827 size_t nTracks = countTracks(); 2828 return mTextDriver->addOutOfBandTextSource(nTracks, uri, mimeType); 2829 } 2830 case INVOKE_ID_ADD_EXTERNAL_SOURCE_FD: 2831 { 2832 Mutex::Autolock autoLock(mLock); 2833 if (mTextDriver == NULL) { 2834 mTextDriver = new TimedTextDriver(mListener, mHTTPService); 2835 } 2836 int fd = request.readFileDescriptor(); 2837 off64_t offset = request.readInt64(); 2838 off64_t length = request.readInt64(); 2839 String8 mimeType(request.readString16()); 2840 size_t nTracks = countTracks(); 2841 return mTextDriver->addOutOfBandTextSource( 2842 nTracks, fd, offset, length, mimeType); 2843 } 2844 case INVOKE_ID_SELECT_TRACK: 2845 { 2846 int trackIndex = request.readInt32(); 2847 return selectTrack(trackIndex, true /* select */); 2848 } 2849 case INVOKE_ID_UNSELECT_TRACK: 2850 { 2851 int trackIndex = request.readInt32(); 2852 return selectTrack(trackIndex, false /* select */); 2853 } 2854 default: 2855 { 2856 return ERROR_UNSUPPORTED; 2857 } 2858 } 2859 // It will not reach here. 2860 return OK; 2861 } 2862 2863 bool AwesomePlayer::isStreamingHTTP() const { 2864 return mCachedSource != NULL || mWVMExtractor != NULL; 2865 } 2866 2867 status_t AwesomePlayer::dump( 2868 int fd, const Vector<String16> & /* args */) const { 2869 Mutex::Autolock autoLock(mStatsLock); 2870 2871 FILE *out = fdopen(dup(fd), "w"); 2872 2873 fprintf(out, " AwesomePlayer\n"); 2874 if (mStats.mFd < 0) { 2875 fprintf(out, " URI(%s)", uriDebugString(mUri, mFlags & INCOGNITO).c_str()); 2876 } else { 2877 fprintf(out, " fd(%d)", mStats.mFd); 2878 } 2879 2880 fprintf(out, ", flags(0x%08x)", mStats.mFlags); 2881 2882 if (mStats.mBitrate >= 0) { 2883 fprintf(out, ", bitrate(%" PRId64 " bps)", mStats.mBitrate); 2884 } 2885 2886 fprintf(out, "\n"); 2887 2888 for (size_t i = 0; i < mStats.mTracks.size(); ++i) { 2889 const TrackStat &stat = mStats.mTracks.itemAt(i); 2890 2891 fprintf(out, " Track %zu\n", i + 1); 2892 fprintf(out, " MIME(%s)", stat.mMIME.string()); 2893 2894 if (!stat.mDecoderName.isEmpty()) { 2895 fprintf(out, ", decoder(%s)", stat.mDecoderName.string()); 2896 } 2897 2898 fprintf(out, "\n"); 2899 2900 if ((ssize_t)i == mStats.mVideoTrackIndex) { 2901 fprintf(out, 2902 " videoDimensions(%d x %d), " 2903 "numVideoFramesDecoded(%" PRId64 "), " 2904 "numVideoFramesDropped(%" PRId64 ")\n", 2905 mStats.mVideoWidth, 2906 mStats.mVideoHeight, 2907 mStats.mNumVideoFramesDecoded, 2908 mStats.mNumVideoFramesDropped); 2909 } 2910 } 2911 2912 fclose(out); 2913 out = NULL; 2914 2915 return OK; 2916 } 2917 2918 void AwesomePlayer::modifyFlags(unsigned value, FlagMode mode) { 2919 switch (mode) { 2920 case SET: 2921 mFlags |= value; 2922 break; 2923 case CLEAR: 2924 if ((value & CACHE_UNDERRUN) && (mFlags & CACHE_UNDERRUN)) { 2925 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END); 2926 } 2927 mFlags &= ~value; 2928 break; 2929 case ASSIGN: 2930 mFlags = value; 2931 break; 2932 default: 2933 TRESPASS(); 2934 } 2935 2936 { 2937 Mutex::Autolock autoLock(mStatsLock); 2938 mStats.mFlags = mFlags; 2939 } 2940 } 2941 2942 void AwesomePlayer::onAudioTearDownEvent() { 2943 2944 Mutex::Autolock autoLock(mLock); 2945 if (!mAudioTearDownEventPending) { 2946 return; 2947 } 2948 mAudioTearDownEventPending = false; 2949 2950 ALOGV("onAudioTearDownEvent"); 2951 2952 // stream info is cleared by reset_l() so copy what we need 2953 mAudioTearDownWasPlaying = (mFlags & PLAYING); 2954 KeyedVector<String8, String8> uriHeaders(mUriHeaders); 2955 sp<DataSource> fileSource(mFileSource); 2956 2957 mStatsLock.lock(); 2958 String8 uri(mStats.mURI); 2959 mStatsLock.unlock(); 2960 2961 // get current position so we can start recreated stream from here 2962 getPosition(&mAudioTearDownPosition); 2963 2964 sp<IMediaHTTPService> savedHTTPService = mHTTPService; 2965 2966 bool wasLooping = mFlags & LOOPING; 2967 // Reset and recreate 2968 reset_l(); 2969 2970 status_t err; 2971 2972 if (fileSource != NULL) { 2973 mFileSource = fileSource; 2974 err = setDataSource_l(fileSource); 2975 } else { 2976 err = setDataSource_l(savedHTTPService, uri, &uriHeaders); 2977 } 2978 2979 mFlags |= PREPARING; 2980 if ( err != OK ) { 2981 // This will force beingPrepareAsync_l() to notify 2982 // a MEDIA_ERROR to the client and abort the prepare 2983 mFlags |= PREPARE_CANCELLED; 2984 } 2985 if (wasLooping) { 2986 mFlags |= LOOPING; 2987 } 2988 2989 mAudioTearDown = true; 2990 mIsAsyncPrepare = true; 2991 2992 // Call prepare for the host decoding 2993 beginPrepareAsync_l(); 2994 } 2995 2996 } // namespace android 2997