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 = 60000000ll; 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 & LOOPING) 882 || ((mFlags & AUTO_LOOPING) 883 && (mAudioSink == NULL || mAudioSink->realtime()))) { 884 // Don't AUTO_LOOP if we're being recorded, since that cannot be 885 // turned off and recording would go on indefinitely. 886 887 seekTo_l(0); 888 889 if (mVideoSource != NULL) { 890 postVideoEvent_l(); 891 } 892 } else { 893 ALOGV("MEDIA_PLAYBACK_COMPLETE"); 894 notifyListener_l(MEDIA_PLAYBACK_COMPLETE); 895 896 pause_l(true /* at eos */); 897 898 // If audio hasn't completed MEDIA_SEEK_COMPLETE yet, 899 // notify MEDIA_SEEK_COMPLETE to observer immediately for state persistence. 900 if (mWatchForAudioSeekComplete) { 901 notifyListener_l(MEDIA_SEEK_COMPLETE); 902 mWatchForAudioSeekComplete = false; 903 } 904 905 modifyFlags(AT_EOS, SET); 906 } 907 } 908 909 status_t AwesomePlayer::play() { 910 ATRACE_CALL(); 911 912 Mutex::Autolock autoLock(mLock); 913 914 modifyFlags(CACHE_UNDERRUN, CLEAR); 915 916 return play_l(); 917 } 918 919 status_t AwesomePlayer::play_l() { 920 modifyFlags(SEEK_PREVIEW, CLEAR); 921 922 if (mFlags & PLAYING) { 923 return OK; 924 } 925 926 mMediaRenderingStartGeneration = ++mStartGeneration; 927 928 if (!(mFlags & PREPARED)) { 929 status_t err = prepare_l(); 930 931 if (err != OK) { 932 return err; 933 } 934 } 935 936 modifyFlags(PLAYING, SET); 937 modifyFlags(FIRST_FRAME, SET); 938 939 if (mDecryptHandle != NULL) { 940 int64_t position; 941 getPosition(&position); 942 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, 943 Playback::START, position / 1000); 944 } 945 946 if (mAudioSource != NULL) { 947 if (mAudioPlayer == NULL) { 948 createAudioPlayer_l(); 949 } 950 951 CHECK(!(mFlags & AUDIO_RUNNING)); 952 953 if (mVideoSource == NULL) { 954 955 // We don't want to post an error notification at this point, 956 // the error returned from MediaPlayer::start() will suffice. 957 958 status_t err = startAudioPlayer_l( 959 false /* sendErrorNotification */); 960 961 if ((err != OK) && mOffloadAudio) { 962 ALOGI("play_l() cannot create offload output, fallback to sw decode"); 963 int64_t curTimeUs; 964 getPosition(&curTimeUs); 965 966 delete mAudioPlayer; 967 mAudioPlayer = NULL; 968 // if the player was started it will take care of stopping the source when destroyed 969 if (!(mFlags & AUDIOPLAYER_STARTED)) { 970 mAudioSource->stop(); 971 } 972 modifyFlags((AUDIO_RUNNING | AUDIOPLAYER_STARTED), CLEAR); 973 mOffloadAudio = false; 974 mAudioSource = mOmxSource; 975 if (mAudioSource != NULL) { 976 err = mAudioSource->start(); 977 978 if (err != OK) { 979 mAudioSource.clear(); 980 } else { 981 mSeekNotificationSent = true; 982 if (mExtractorFlags & MediaExtractor::CAN_SEEK) { 983 seekTo_l(curTimeUs); 984 } 985 createAudioPlayer_l(); 986 err = startAudioPlayer_l(false); 987 } 988 } 989 } 990 991 if (err != OK) { 992 delete mAudioPlayer; 993 mAudioPlayer = NULL; 994 995 modifyFlags((PLAYING | FIRST_FRAME), CLEAR); 996 997 if (mDecryptHandle != NULL) { 998 mDrmManagerClient->setPlaybackStatus( 999 mDecryptHandle, Playback::STOP, 0); 1000 } 1001 1002 return err; 1003 } 1004 } 1005 } 1006 1007 if (mTimeSource == NULL && mAudioPlayer == NULL) { 1008 mTimeSource = &mSystemTimeSource; 1009 } 1010 1011 if (mVideoSource != NULL) { 1012 // Kick off video playback 1013 postVideoEvent_l(); 1014 1015 if (mAudioSource != NULL && mVideoSource != NULL) { 1016 postVideoLagEvent_l(); 1017 } 1018 } 1019 1020 if (mFlags & AT_EOS) { 1021 // Legacy behaviour, if a stream finishes playing and then 1022 // is started again, we play from the start... 1023 seekTo_l(0); 1024 } 1025 1026 uint32_t params = IMediaPlayerService::kBatteryDataCodecStarted 1027 | IMediaPlayerService::kBatteryDataTrackDecoder; 1028 if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) { 1029 params |= IMediaPlayerService::kBatteryDataTrackAudio; 1030 } 1031 if (mVideoSource != NULL) { 1032 params |= IMediaPlayerService::kBatteryDataTrackVideo; 1033 } 1034 addBatteryData(params); 1035 1036 if (isStreamingHTTP()) { 1037 postBufferingEvent_l(); 1038 } 1039 1040 return OK; 1041 } 1042 1043 void AwesomePlayer::createAudioPlayer_l() 1044 { 1045 uint32_t flags = 0; 1046 int64_t cachedDurationUs; 1047 bool eos; 1048 1049 if (mOffloadAudio) { 1050 flags |= AudioPlayer::USE_OFFLOAD; 1051 } else if (mVideoSource == NULL 1052 && (mDurationUs > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US || 1053 (getCachedDuration_l(&cachedDurationUs, &eos) && 1054 cachedDurationUs > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US))) { 1055 flags |= AudioPlayer::ALLOW_DEEP_BUFFERING; 1056 } 1057 if (isStreamingHTTP()) { 1058 flags |= AudioPlayer::IS_STREAMING; 1059 } 1060 if (mVideoSource != NULL) { 1061 flags |= AudioPlayer::HAS_VIDEO; 1062 } 1063 1064 mAudioPlayer = new AudioPlayer(mAudioSink, flags, this); 1065 mAudioPlayer->setSource(mAudioSource); 1066 1067 mTimeSource = mAudioPlayer; 1068 1069 // If there was a seek request before we ever started, 1070 // honor the request now. 1071 // Make sure to do this before starting the audio player 1072 // to avoid a race condition. 1073 seekAudioIfNecessary_l(); 1074 } 1075 1076 void AwesomePlayer::notifyIfMediaStarted_l() { 1077 if (mMediaRenderingStartGeneration == mStartGeneration) { 1078 mMediaRenderingStartGeneration = -1; 1079 notifyListener_l(MEDIA_STARTED); 1080 } 1081 } 1082 1083 status_t AwesomePlayer::startAudioPlayer_l(bool sendErrorNotification) { 1084 CHECK(!(mFlags & AUDIO_RUNNING)); 1085 status_t err = OK; 1086 1087 if (mAudioSource == NULL || mAudioPlayer == NULL) { 1088 return OK; 1089 } 1090 1091 if (mOffloadAudio) { 1092 mQueue.cancelEvent(mAudioTearDownEvent->eventID()); 1093 mAudioTearDownEventPending = false; 1094 } 1095 1096 if (!(mFlags & AUDIOPLAYER_STARTED)) { 1097 bool wasSeeking = mAudioPlayer->isSeeking(); 1098 1099 // We've already started the MediaSource in order to enable 1100 // the prefetcher to read its data. 1101 err = mAudioPlayer->start( 1102 true /* sourceAlreadyStarted */); 1103 1104 if (err != OK) { 1105 if (sendErrorNotification) { 1106 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err); 1107 } 1108 1109 return err; 1110 } 1111 1112 modifyFlags(AUDIOPLAYER_STARTED, SET); 1113 1114 if (wasSeeking) { 1115 CHECK(!mAudioPlayer->isSeeking()); 1116 1117 // We will have finished the seek while starting the audio player. 1118 postAudioSeekComplete(); 1119 } else { 1120 notifyIfMediaStarted_l(); 1121 } 1122 } else { 1123 err = mAudioPlayer->resume(); 1124 } 1125 1126 if (err == OK) { 1127 modifyFlags(AUDIO_RUNNING, SET); 1128 1129 mWatchForAudioEOS = true; 1130 } 1131 1132 return err; 1133 } 1134 1135 void AwesomePlayer::notifyVideoSize_l() { 1136 ATRACE_CALL(); 1137 sp<MetaData> meta = mVideoSource->getFormat(); 1138 1139 int32_t cropLeft, cropTop, cropRight, cropBottom; 1140 if (!meta->findRect( 1141 kKeyCropRect, &cropLeft, &cropTop, &cropRight, &cropBottom)) { 1142 int32_t width, height; 1143 CHECK(meta->findInt32(kKeyWidth, &width)); 1144 CHECK(meta->findInt32(kKeyHeight, &height)); 1145 1146 cropLeft = cropTop = 0; 1147 cropRight = width - 1; 1148 cropBottom = height - 1; 1149 1150 ALOGV("got dimensions only %d x %d", width, height); 1151 } else { 1152 ALOGV("got crop rect %d, %d, %d, %d", 1153 cropLeft, cropTop, cropRight, cropBottom); 1154 } 1155 1156 int32_t displayWidth; 1157 if (meta->findInt32(kKeyDisplayWidth, &displayWidth)) { 1158 ALOGV("Display width changed (%d=>%d)", mDisplayWidth, displayWidth); 1159 mDisplayWidth = displayWidth; 1160 } 1161 int32_t displayHeight; 1162 if (meta->findInt32(kKeyDisplayHeight, &displayHeight)) { 1163 ALOGV("Display height changed (%d=>%d)", mDisplayHeight, displayHeight); 1164 mDisplayHeight = displayHeight; 1165 } 1166 1167 int32_t usableWidth = cropRight - cropLeft + 1; 1168 int32_t usableHeight = cropBottom - cropTop + 1; 1169 if (mDisplayWidth != 0) { 1170 usableWidth = mDisplayWidth; 1171 } 1172 if (mDisplayHeight != 0) { 1173 usableHeight = mDisplayHeight; 1174 } 1175 1176 { 1177 Mutex::Autolock autoLock(mStatsLock); 1178 mStats.mVideoWidth = usableWidth; 1179 mStats.mVideoHeight = usableHeight; 1180 } 1181 1182 int32_t rotationDegrees; 1183 if (!mVideoTrack->getFormat()->findInt32( 1184 kKeyRotation, &rotationDegrees)) { 1185 rotationDegrees = 0; 1186 } 1187 1188 if (rotationDegrees == 90 || rotationDegrees == 270) { 1189 notifyListener_l( 1190 MEDIA_SET_VIDEO_SIZE, usableHeight, usableWidth); 1191 } else { 1192 notifyListener_l( 1193 MEDIA_SET_VIDEO_SIZE, usableWidth, usableHeight); 1194 } 1195 } 1196 1197 void AwesomePlayer::initRenderer_l() { 1198 ATRACE_CALL(); 1199 1200 if (mNativeWindow == NULL) { 1201 return; 1202 } 1203 1204 sp<MetaData> meta = mVideoSource->getFormat(); 1205 1206 int32_t format; 1207 const char *component; 1208 int32_t decodedWidth, decodedHeight; 1209 CHECK(meta->findInt32(kKeyColorFormat, &format)); 1210 CHECK(meta->findCString(kKeyDecoderComponent, &component)); 1211 CHECK(meta->findInt32(kKeyWidth, &decodedWidth)); 1212 CHECK(meta->findInt32(kKeyHeight, &decodedHeight)); 1213 1214 int32_t rotationDegrees; 1215 if (!mVideoTrack->getFormat()->findInt32( 1216 kKeyRotation, &rotationDegrees)) { 1217 rotationDegrees = 0; 1218 } 1219 1220 mVideoRenderer.clear(); 1221 1222 // Must ensure that mVideoRenderer's destructor is actually executed 1223 // before creating a new one. 1224 IPCThreadState::self()->flushCommands(); 1225 1226 // Even if set scaling mode fails, we will continue anyway 1227 setVideoScalingMode_l(mVideoScalingMode); 1228 if (USE_SURFACE_ALLOC 1229 && !strncmp(component, "OMX.", 4) 1230 && strncmp(component, "OMX.google.", 11)) { 1231 // Hardware decoders avoid the CPU color conversion by decoding 1232 // directly to ANativeBuffers, so we must use a renderer that 1233 // just pushes those buffers to the ANativeWindow. 1234 mVideoRenderer = 1235 new AwesomeNativeWindowRenderer(mNativeWindow, rotationDegrees); 1236 } else { 1237 // Other decoders are instantiated locally and as a consequence 1238 // allocate their buffers in local address space. This renderer 1239 // then performs a color conversion and copy to get the data 1240 // into the ANativeBuffer. 1241 sp<AMessage> format; 1242 convertMetaDataToMessage(meta, &format); 1243 mVideoRenderer = new AwesomeLocalRenderer(mNativeWindow, format); 1244 } 1245 } 1246 1247 status_t AwesomePlayer::pause() { 1248 ATRACE_CALL(); 1249 1250 Mutex::Autolock autoLock(mLock); 1251 1252 modifyFlags(CACHE_UNDERRUN, CLEAR); 1253 1254 return pause_l(); 1255 } 1256 1257 status_t AwesomePlayer::pause_l(bool at_eos) { 1258 if (!(mFlags & PLAYING)) { 1259 if (mAudioTearDown && mAudioTearDownWasPlaying) { 1260 ALOGV("pause_l() during teardown and finishSetDataSource_l() mFlags %x" , mFlags); 1261 mAudioTearDownWasPlaying = false; 1262 notifyListener_l(MEDIA_PAUSED); 1263 mMediaRenderingStartGeneration = ++mStartGeneration; 1264 } 1265 return OK; 1266 } 1267 1268 notifyListener_l(MEDIA_PAUSED); 1269 mMediaRenderingStartGeneration = ++mStartGeneration; 1270 1271 cancelPlayerEvents(true /* keepNotifications */); 1272 1273 if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) { 1274 // If we played the audio stream to completion we 1275 // want to make sure that all samples remaining in the audio 1276 // track's queue are played out. 1277 mAudioPlayer->pause(at_eos /* playPendingSamples */); 1278 // send us a reminder to tear down the AudioPlayer if paused for too long. 1279 if (mOffloadAudio) { 1280 postAudioTearDownEvent(kOffloadPauseMaxUs); 1281 } 1282 modifyFlags(AUDIO_RUNNING, CLEAR); 1283 } 1284 1285 if (mFlags & TEXTPLAYER_INITIALIZED) { 1286 mTextDriver->pause(); 1287 modifyFlags(TEXT_RUNNING, CLEAR); 1288 } 1289 1290 modifyFlags(PLAYING, CLEAR); 1291 1292 if (mDecryptHandle != NULL) { 1293 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, 1294 Playback::PAUSE, 0); 1295 } 1296 1297 uint32_t params = IMediaPlayerService::kBatteryDataTrackDecoder; 1298 if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) { 1299 params |= IMediaPlayerService::kBatteryDataTrackAudio; 1300 } 1301 if (mVideoSource != NULL) { 1302 params |= IMediaPlayerService::kBatteryDataTrackVideo; 1303 } 1304 1305 addBatteryData(params); 1306 1307 return OK; 1308 } 1309 1310 bool AwesomePlayer::isPlaying() const { 1311 return (mFlags & PLAYING) || (mFlags & CACHE_UNDERRUN); 1312 } 1313 1314 status_t AwesomePlayer::setSurfaceTexture(const sp<IGraphicBufferProducer> &bufferProducer) { 1315 Mutex::Autolock autoLock(mLock); 1316 1317 status_t err; 1318 if (bufferProducer != NULL) { 1319 err = setNativeWindow_l(new Surface(bufferProducer)); 1320 } else { 1321 err = setNativeWindow_l(NULL); 1322 } 1323 1324 return err; 1325 } 1326 1327 void AwesomePlayer::shutdownVideoDecoder_l() { 1328 if (mVideoBuffer) { 1329 mVideoBuffer->release(); 1330 mVideoBuffer = NULL; 1331 } 1332 1333 mVideoSource->stop(); 1334 1335 // The following hack is necessary to ensure that the OMX 1336 // component is completely released by the time we may try 1337 // to instantiate it again. 1338 wp<MediaSource> tmp = mVideoSource; 1339 mVideoSource.clear(); 1340 while (tmp.promote() != NULL) { 1341 usleep(1000); 1342 } 1343 IPCThreadState::self()->flushCommands(); 1344 ALOGV("video decoder shutdown completed"); 1345 } 1346 1347 status_t AwesomePlayer::setNativeWindow_l(const sp<ANativeWindow> &native) { 1348 mNativeWindow = native; 1349 1350 if (mVideoSource == NULL) { 1351 return OK; 1352 } 1353 1354 ALOGV("attempting to reconfigure to use new surface"); 1355 1356 bool wasPlaying = (mFlags & PLAYING) != 0; 1357 1358 pause_l(); 1359 mVideoRenderer.clear(); 1360 1361 shutdownVideoDecoder_l(); 1362 1363 status_t err = initVideoDecoder(); 1364 1365 if (err != OK) { 1366 ALOGE("failed to reinstantiate video decoder after surface change."); 1367 return err; 1368 } 1369 1370 if (mLastVideoTimeUs >= 0) { 1371 mSeeking = SEEK; 1372 mSeekTimeUs = mLastVideoTimeUs; 1373 modifyFlags((AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS), CLEAR); 1374 } 1375 1376 if (wasPlaying) { 1377 play_l(); 1378 } 1379 1380 return OK; 1381 } 1382 1383 void AwesomePlayer::setAudioSink( 1384 const sp<MediaPlayerBase::AudioSink> &audioSink) { 1385 Mutex::Autolock autoLock(mLock); 1386 1387 mAudioSink = audioSink; 1388 } 1389 1390 status_t AwesomePlayer::setLooping(bool shouldLoop) { 1391 Mutex::Autolock autoLock(mLock); 1392 1393 modifyFlags(LOOPING, CLEAR); 1394 1395 if (shouldLoop) { 1396 modifyFlags(LOOPING, SET); 1397 } 1398 1399 return OK; 1400 } 1401 1402 status_t AwesomePlayer::getDuration(int64_t *durationUs) { 1403 Mutex::Autolock autoLock(mMiscStateLock); 1404 1405 if (mDurationUs < 0) { 1406 return UNKNOWN_ERROR; 1407 } 1408 1409 *durationUs = mDurationUs; 1410 1411 return OK; 1412 } 1413 1414 status_t AwesomePlayer::getPosition(int64_t *positionUs) { 1415 if (mSeeking != NO_SEEK) { 1416 *positionUs = mSeekTimeUs; 1417 } else if (mVideoSource != NULL 1418 && (mAudioPlayer == NULL || !(mFlags & VIDEO_AT_EOS))) { 1419 Mutex::Autolock autoLock(mMiscStateLock); 1420 *positionUs = mVideoTimeUs; 1421 } else if (mAudioPlayer != NULL) { 1422 *positionUs = mAudioPlayer->getMediaTimeUs(); 1423 } else { 1424 *positionUs = 0; 1425 } 1426 return OK; 1427 } 1428 1429 status_t AwesomePlayer::seekTo(int64_t timeUs) { 1430 ATRACE_CALL(); 1431 1432 if (mExtractorFlags & MediaExtractor::CAN_SEEK) { 1433 Mutex::Autolock autoLock(mLock); 1434 return seekTo_l(timeUs); 1435 } 1436 1437 return OK; 1438 } 1439 1440 status_t AwesomePlayer::seekTo_l(int64_t timeUs) { 1441 if (mFlags & CACHE_UNDERRUN) { 1442 modifyFlags(CACHE_UNDERRUN, CLEAR); 1443 play_l(); 1444 } 1445 1446 if ((mFlags & PLAYING) && mVideoSource != NULL && (mFlags & VIDEO_AT_EOS)) { 1447 // Video playback completed before, there's no pending 1448 // video event right now. In order for this new seek 1449 // to be honored, we need to post one. 1450 1451 postVideoEvent_l(); 1452 } 1453 1454 mSeeking = SEEK; 1455 mSeekNotificationSent = false; 1456 mSeekTimeUs = timeUs; 1457 modifyFlags((AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS), CLEAR); 1458 1459 if (mFlags & PLAYING) { 1460 notifyListener_l(MEDIA_PAUSED); 1461 mMediaRenderingStartGeneration = ++mStartGeneration; 1462 } 1463 1464 seekAudioIfNecessary_l(); 1465 1466 if (mFlags & TEXTPLAYER_INITIALIZED) { 1467 mTextDriver->seekToAsync(mSeekTimeUs); 1468 } 1469 1470 if (!(mFlags & PLAYING)) { 1471 ALOGV("seeking while paused, sending SEEK_COMPLETE notification" 1472 " immediately."); 1473 1474 notifyListener_l(MEDIA_SEEK_COMPLETE); 1475 mSeekNotificationSent = true; 1476 1477 if ((mFlags & PREPARED) && mVideoSource != NULL) { 1478 modifyFlags(SEEK_PREVIEW, SET); 1479 postVideoEvent_l(); 1480 } 1481 } 1482 1483 return OK; 1484 } 1485 1486 void AwesomePlayer::seekAudioIfNecessary_l() { 1487 if (mSeeking != NO_SEEK && mVideoSource == NULL && mAudioPlayer != NULL) { 1488 mAudioPlayer->seekTo(mSeekTimeUs); 1489 1490 mWatchForAudioSeekComplete = true; 1491 mWatchForAudioEOS = true; 1492 1493 if (mDecryptHandle != NULL) { 1494 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, 1495 Playback::PAUSE, 0); 1496 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, 1497 Playback::START, mSeekTimeUs / 1000); 1498 } 1499 } 1500 } 1501 1502 void AwesomePlayer::setAudioSource(sp<MediaSource> source) { 1503 CHECK(source != NULL); 1504 1505 mAudioTrack = source; 1506 } 1507 1508 void AwesomePlayer::addTextSource_l(size_t trackIndex, const sp<MediaSource>& source) { 1509 CHECK(source != NULL); 1510 1511 if (mTextDriver == NULL) { 1512 mTextDriver = new TimedTextDriver(mListener, mHTTPService); 1513 } 1514 1515 mTextDriver->addInBandTextSource(trackIndex, source); 1516 } 1517 1518 status_t AwesomePlayer::initAudioDecoder() { 1519 ATRACE_CALL(); 1520 1521 sp<MetaData> meta = mAudioTrack->getFormat(); 1522 1523 const char *mime; 1524 CHECK(meta->findCString(kKeyMIMEType, &mime)); 1525 // Check whether there is a hardware codec for this stream 1526 // This doesn't guarantee that the hardware has a free stream 1527 // but it avoids us attempting to open (and re-open) an offload 1528 // stream to hardware that doesn't have the necessary codec 1529 audio_stream_type_t streamType = AUDIO_STREAM_MUSIC; 1530 if (mAudioSink != NULL) { 1531 streamType = mAudioSink->getAudioStreamType(); 1532 } 1533 1534 mOffloadAudio = canOffloadStream(meta, (mVideoSource != NULL), 1535 isStreamingHTTP(), streamType); 1536 1537 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) { 1538 ALOGV("createAudioPlayer: bypass OMX (raw)"); 1539 mAudioSource = mAudioTrack; 1540 } else { 1541 // If offloading we still create a OMX decoder as a fall-back 1542 // but we don't start it 1543 mOmxSource = OMXCodec::Create( 1544 mClient.interface(), mAudioTrack->getFormat(), 1545 false, // createEncoder 1546 mAudioTrack); 1547 1548 if (mOffloadAudio) { 1549 ALOGV("createAudioPlayer: bypass OMX (offload)"); 1550 mAudioSource = mAudioTrack; 1551 } else { 1552 mAudioSource = mOmxSource; 1553 } 1554 } 1555 1556 if (mAudioSource != NULL) { 1557 int64_t durationUs; 1558 if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) { 1559 Mutex::Autolock autoLock(mMiscStateLock); 1560 if (mDurationUs < 0 || durationUs > mDurationUs) { 1561 mDurationUs = durationUs; 1562 } 1563 } 1564 1565 status_t err = mAudioSource->start(); 1566 1567 if (err != OK) { 1568 mAudioSource.clear(); 1569 mOmxSource.clear(); 1570 return err; 1571 } 1572 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_QCELP)) { 1573 // For legacy reasons we're simply going to ignore the absence 1574 // of an audio decoder for QCELP instead of aborting playback 1575 // altogether. 1576 return OK; 1577 } 1578 1579 if (mAudioSource != NULL) { 1580 Mutex::Autolock autoLock(mStatsLock); 1581 TrackStat *stat = &mStats.mTracks.editItemAt(mStats.mAudioTrackIndex); 1582 const char *component; 1583 if (!mAudioSource->getFormat() 1584 ->findCString(kKeyDecoderComponent, &component)) { 1585 component = "none"; 1586 } 1587 1588 stat->mDecoderName = component; 1589 } 1590 1591 return mAudioSource != NULL ? OK : UNKNOWN_ERROR; 1592 } 1593 1594 void AwesomePlayer::setVideoSource(sp<MediaSource> source) { 1595 CHECK(source != NULL); 1596 1597 mVideoTrack = source; 1598 } 1599 1600 status_t AwesomePlayer::initVideoDecoder(uint32_t flags) { 1601 ATRACE_CALL(); 1602 1603 // Either the application or the DRM system can independently say 1604 // that there must be a hardware-protected path to an external video sink. 1605 // For now we always require a hardware-protected path to external video sink 1606 // if content is DRMed, but eventually this could be optional per DRM agent. 1607 // When the application wants protection, then 1608 // (USE_SURFACE_ALLOC && (mSurface != 0) && 1609 // (mSurface->getFlags() & ISurfaceComposer::eProtectedByApp)) 1610 // will be true, but that part is already handled by SurfaceFlinger. 1611 1612 #ifdef DEBUG_HDCP 1613 // For debugging, we allow a system property to control the protected usage. 1614 // In case of uninitialized or unexpected property, we default to "DRM only". 1615 bool setProtectionBit = false; 1616 char value[PROPERTY_VALUE_MAX]; 1617 if (property_get("persist.sys.hdcp_checking", value, NULL)) { 1618 if (!strcmp(value, "never")) { 1619 // nop 1620 } else if (!strcmp(value, "always")) { 1621 setProtectionBit = true; 1622 } else if (!strcmp(value, "drm-only")) { 1623 if (mDecryptHandle != NULL) { 1624 setProtectionBit = true; 1625 } 1626 // property value is empty, or unexpected value 1627 } else { 1628 if (mDecryptHandle != NULL) { 1629 setProtectionBit = true; 1630 } 1631 } 1632 // can' read property value 1633 } else { 1634 if (mDecryptHandle != NULL) { 1635 setProtectionBit = true; 1636 } 1637 } 1638 // note that usage bit is already cleared, so no need to clear it in the "else" case 1639 if (setProtectionBit) { 1640 flags |= OMXCodec::kEnableGrallocUsageProtected; 1641 } 1642 #else 1643 if (mDecryptHandle != NULL) { 1644 flags |= OMXCodec::kEnableGrallocUsageProtected; 1645 } 1646 #endif 1647 ALOGV("initVideoDecoder flags=0x%x", flags); 1648 mVideoSource = OMXCodec::Create( 1649 mClient.interface(), mVideoTrack->getFormat(), 1650 false, // createEncoder 1651 mVideoTrack, 1652 NULL, flags, USE_SURFACE_ALLOC ? mNativeWindow : NULL); 1653 1654 if (mVideoSource != NULL) { 1655 int64_t durationUs; 1656 if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) { 1657 Mutex::Autolock autoLock(mMiscStateLock); 1658 if (mDurationUs < 0 || durationUs > mDurationUs) { 1659 mDurationUs = durationUs; 1660 } 1661 } 1662 1663 status_t err = mVideoSource->start(); 1664 1665 if (err != OK) { 1666 ALOGE("failed to start video source"); 1667 mVideoSource.clear(); 1668 return err; 1669 } 1670 } 1671 1672 if (mVideoSource != NULL) { 1673 const char *componentName; 1674 CHECK(mVideoSource->getFormat() 1675 ->findCString(kKeyDecoderComponent, &componentName)); 1676 1677 { 1678 Mutex::Autolock autoLock(mStatsLock); 1679 TrackStat *stat = &mStats.mTracks.editItemAt(mStats.mVideoTrackIndex); 1680 1681 stat->mDecoderName = componentName; 1682 } 1683 1684 static const char *kPrefix = "OMX.Nvidia."; 1685 static const char *kSuffix = ".decode"; 1686 static const size_t kSuffixLength = strlen(kSuffix); 1687 1688 size_t componentNameLength = strlen(componentName); 1689 1690 if (!strncmp(componentName, kPrefix, strlen(kPrefix)) 1691 && componentNameLength >= kSuffixLength 1692 && !strcmp(&componentName[ 1693 componentNameLength - kSuffixLength], kSuffix)) { 1694 modifyFlags(SLOW_DECODER_HACK, SET); 1695 } 1696 } 1697 1698 return mVideoSource != NULL ? OK : UNKNOWN_ERROR; 1699 } 1700 1701 void AwesomePlayer::finishSeekIfNecessary(int64_t videoTimeUs) { 1702 ATRACE_CALL(); 1703 1704 if (mSeeking == SEEK_VIDEO_ONLY) { 1705 mSeeking = NO_SEEK; 1706 return; 1707 } 1708 1709 if (mSeeking == NO_SEEK || (mFlags & SEEK_PREVIEW)) { 1710 return; 1711 } 1712 1713 // If we paused, then seeked, then resumed, it is possible that we have 1714 // signaled SEEK_COMPLETE at a copmletely different media time than where 1715 // we are now resuming. Signal new position to media time provider. 1716 // Cannot signal another SEEK_COMPLETE, as existing clients may not expect 1717 // multiple SEEK_COMPLETE responses to a single seek() request. 1718 if (mSeekNotificationSent && abs(mSeekTimeUs - videoTimeUs) > 10000) { 1719 // notify if we are resuming more than 10ms away from desired seek time 1720 notifyListener_l(MEDIA_SKIPPED); 1721 } 1722 1723 if (mAudioPlayer != NULL) { 1724 ALOGV("seeking audio to %" PRId64 " us (%.2f secs).", videoTimeUs, videoTimeUs / 1E6); 1725 1726 // If we don't have a video time, seek audio to the originally 1727 // requested seek time instead. 1728 1729 mAudioPlayer->seekTo(videoTimeUs < 0 ? mSeekTimeUs : videoTimeUs); 1730 mWatchForAudioSeekComplete = true; 1731 mWatchForAudioEOS = true; 1732 } else if (!mSeekNotificationSent) { 1733 // If we're playing video only, report seek complete now, 1734 // otherwise audio player will notify us later. 1735 notifyListener_l(MEDIA_SEEK_COMPLETE); 1736 mSeekNotificationSent = true; 1737 } 1738 1739 modifyFlags(FIRST_FRAME, SET); 1740 mSeeking = NO_SEEK; 1741 1742 if (mDecryptHandle != NULL) { 1743 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, 1744 Playback::PAUSE, 0); 1745 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, 1746 Playback::START, videoTimeUs / 1000); 1747 } 1748 } 1749 1750 void AwesomePlayer::onVideoEvent() { 1751 ATRACE_CALL(); 1752 Mutex::Autolock autoLock(mLock); 1753 if (!mVideoEventPending) { 1754 // The event has been cancelled in reset_l() but had already 1755 // been scheduled for execution at that time. 1756 return; 1757 } 1758 mVideoEventPending = false; 1759 1760 if (mSeeking != NO_SEEK) { 1761 if (mVideoBuffer) { 1762 mVideoBuffer->release(); 1763 mVideoBuffer = NULL; 1764 } 1765 1766 if (mSeeking == SEEK && isStreamingHTTP() && mAudioSource != NULL 1767 && !(mFlags & SEEK_PREVIEW)) { 1768 // We're going to seek the video source first, followed by 1769 // the audio source. 1770 // In order to avoid jumps in the DataSource offset caused by 1771 // the audio codec prefetching data from the old locations 1772 // while the video codec is already reading data from the new 1773 // locations, we'll "pause" the audio source, causing it to 1774 // stop reading input data until a subsequent seek. 1775 1776 if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) { 1777 mAudioPlayer->pause(); 1778 1779 modifyFlags(AUDIO_RUNNING, CLEAR); 1780 } 1781 mAudioSource->pause(); 1782 } 1783 } 1784 1785 if (!mVideoBuffer) { 1786 MediaSource::ReadOptions options; 1787 if (mSeeking != NO_SEEK) { 1788 ALOGV("seeking to %" PRId64 " us (%.2f secs)", mSeekTimeUs, mSeekTimeUs / 1E6); 1789 1790 options.setSeekTo( 1791 mSeekTimeUs, 1792 mSeeking == SEEK_VIDEO_ONLY 1793 ? MediaSource::ReadOptions::SEEK_NEXT_SYNC 1794 : MediaSource::ReadOptions::SEEK_CLOSEST_SYNC); 1795 } 1796 for (;;) { 1797 status_t err = mVideoSource->read(&mVideoBuffer, &options); 1798 options.clearSeekTo(); 1799 1800 if (err != OK) { 1801 CHECK(mVideoBuffer == NULL); 1802 1803 if (err == INFO_FORMAT_CHANGED) { 1804 ALOGV("VideoSource signalled format change."); 1805 1806 notifyVideoSize_l(); 1807 1808 if (mVideoRenderer != NULL) { 1809 mVideoRendererIsPreview = false; 1810 initRenderer_l(); 1811 } 1812 continue; 1813 } 1814 1815 // So video playback is complete, but we may still have 1816 // a seek request pending that needs to be applied 1817 // to the audio track. 1818 if (mSeeking != NO_SEEK) { 1819 ALOGV("video stream ended while seeking!"); 1820 } 1821 finishSeekIfNecessary(-1); 1822 1823 if (mAudioPlayer != NULL 1824 && !(mFlags & (AUDIO_RUNNING | SEEK_PREVIEW))) { 1825 startAudioPlayer_l(); 1826 } 1827 1828 modifyFlags(VIDEO_AT_EOS, SET); 1829 postStreamDoneEvent_l(err); 1830 return; 1831 } 1832 1833 if (mVideoBuffer->range_length() == 0) { 1834 // Some decoders, notably the PV AVC software decoder 1835 // return spurious empty buffers that we just want to ignore. 1836 1837 mVideoBuffer->release(); 1838 mVideoBuffer = NULL; 1839 continue; 1840 } 1841 1842 break; 1843 } 1844 1845 { 1846 Mutex::Autolock autoLock(mStatsLock); 1847 ++mStats.mNumVideoFramesDecoded; 1848 } 1849 } 1850 1851 int64_t timeUs; 1852 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs)); 1853 1854 mLastVideoTimeUs = timeUs; 1855 1856 if (mSeeking == SEEK_VIDEO_ONLY) { 1857 if (mSeekTimeUs > timeUs) { 1858 ALOGI("XXX mSeekTimeUs = %" PRId64 " us, timeUs = %" PRId64 " us", 1859 mSeekTimeUs, timeUs); 1860 } 1861 } 1862 1863 { 1864 Mutex::Autolock autoLock(mMiscStateLock); 1865 mVideoTimeUs = timeUs; 1866 } 1867 1868 SeekType wasSeeking = mSeeking; 1869 finishSeekIfNecessary(timeUs); 1870 1871 if (mAudioPlayer != NULL && !(mFlags & (AUDIO_RUNNING | SEEK_PREVIEW))) { 1872 status_t err = startAudioPlayer_l(); 1873 if (err != OK) { 1874 ALOGE("Starting the audio player failed w/ err %d", err); 1875 return; 1876 } 1877 } 1878 1879 if ((mFlags & TEXTPLAYER_INITIALIZED) 1880 && !(mFlags & (TEXT_RUNNING | SEEK_PREVIEW))) { 1881 mTextDriver->start(); 1882 modifyFlags(TEXT_RUNNING, SET); 1883 } 1884 1885 TimeSource *ts = 1886 ((mFlags & AUDIO_AT_EOS) || !(mFlags & AUDIOPLAYER_STARTED)) 1887 ? &mSystemTimeSource : mTimeSource; 1888 int64_t systemTimeUs = mSystemTimeSource.getRealTimeUs(); 1889 int64_t looperTimeUs = ALooper::GetNowUs(); 1890 1891 if (mFlags & FIRST_FRAME) { 1892 modifyFlags(FIRST_FRAME, CLEAR); 1893 mSinceLastDropped = 0; 1894 mClockEstimator->reset(); 1895 mTimeSourceDeltaUs = estimateRealTimeUs(ts, systemTimeUs) - timeUs; 1896 } 1897 1898 int64_t realTimeUs, mediaTimeUs; 1899 if (!(mFlags & AUDIO_AT_EOS) && mAudioPlayer != NULL 1900 && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) { 1901 ALOGV("updating TSdelta (%" PRId64 " => %" PRId64 " change %" PRId64 ")", 1902 mTimeSourceDeltaUs, realTimeUs - mediaTimeUs, 1903 mTimeSourceDeltaUs - (realTimeUs - mediaTimeUs)); 1904 ATRACE_INT("TS delta change (ms)", (mTimeSourceDeltaUs - (realTimeUs - mediaTimeUs)) / 1E3); 1905 mTimeSourceDeltaUs = realTimeUs - mediaTimeUs; 1906 } 1907 1908 if (wasSeeking == SEEK_VIDEO_ONLY) { 1909 int64_t nowUs = estimateRealTimeUs(ts, systemTimeUs) - mTimeSourceDeltaUs; 1910 1911 int64_t latenessUs = nowUs - timeUs; 1912 1913 ATRACE_INT("Video Lateness (ms)", latenessUs / 1E3); 1914 1915 if (latenessUs > 0) { 1916 ALOGI("after SEEK_VIDEO_ONLY we're late by %.2f secs", latenessUs / 1E6); 1917 } 1918 } 1919 1920 int64_t latenessUs = 0; 1921 if (wasSeeking == NO_SEEK) { 1922 // Let's display the first frame after seeking right away. 1923 1924 int64_t nowUs = estimateRealTimeUs(ts, systemTimeUs) - mTimeSourceDeltaUs; 1925 1926 latenessUs = nowUs - timeUs; 1927 1928 ATRACE_INT("Video Lateness (ms)", latenessUs / 1E3); 1929 1930 if (latenessUs > 500000ll 1931 && mAudioPlayer != NULL 1932 && mAudioPlayer->getMediaTimeMapping( 1933 &realTimeUs, &mediaTimeUs)) { 1934 if (mWVMExtractor == NULL) { 1935 ALOGI("we're much too late (%.2f secs), video skipping ahead", 1936 latenessUs / 1E6); 1937 1938 mVideoBuffer->release(); 1939 mVideoBuffer = NULL; 1940 1941 mSeeking = SEEK_VIDEO_ONLY; 1942 mSeekTimeUs = mediaTimeUs; 1943 1944 postVideoEvent_l(); 1945 return; 1946 } else { 1947 // The widevine extractor doesn't deal well with seeking 1948 // audio and video independently. We'll just have to wait 1949 // until the decoder catches up, which won't be long at all. 1950 ALOGI("we're very late (%.2f secs)", latenessUs / 1E6); 1951 } 1952 } 1953 1954 if (latenessUs > 40000) { 1955 // We're more than 40ms late. 1956 ALOGV("we're late by %" PRId64 " us (%.2f secs)", 1957 latenessUs, latenessUs / 1E6); 1958 1959 if (!(mFlags & SLOW_DECODER_HACK) 1960 || mSinceLastDropped > FRAME_DROP_FREQ) 1961 { 1962 ALOGV("we're late by %" PRId64 " us (%.2f secs) dropping " 1963 "one after %d frames", 1964 latenessUs, latenessUs / 1E6, mSinceLastDropped); 1965 1966 mSinceLastDropped = 0; 1967 mVideoBuffer->release(); 1968 mVideoBuffer = NULL; 1969 1970 { 1971 Mutex::Autolock autoLock(mStatsLock); 1972 ++mStats.mNumVideoFramesDropped; 1973 } 1974 1975 postVideoEvent_l(0); 1976 return; 1977 } 1978 } 1979 1980 if (latenessUs < -30000) { 1981 // We're more than 30ms early, schedule at most 20 ms before time due 1982 postVideoEvent_l(latenessUs < -60000 ? 30000 : -latenessUs - 20000); 1983 return; 1984 } 1985 } 1986 1987 if ((mNativeWindow != NULL) 1988 && (mVideoRendererIsPreview || mVideoRenderer == NULL)) { 1989 mVideoRendererIsPreview = false; 1990 1991 initRenderer_l(); 1992 } 1993 1994 if (mVideoRenderer != NULL) { 1995 mSinceLastDropped++; 1996 mVideoBuffer->meta_data()->setInt64(kKeyTime, looperTimeUs - latenessUs); 1997 1998 mVideoRenderer->render(mVideoBuffer); 1999 if (!mVideoRenderingStarted) { 2000 mVideoRenderingStarted = true; 2001 notifyListener_l(MEDIA_INFO, MEDIA_INFO_RENDERING_START); 2002 } 2003 2004 if (mFlags & PLAYING) { 2005 notifyIfMediaStarted_l(); 2006 } 2007 } 2008 2009 mVideoBuffer->release(); 2010 mVideoBuffer = NULL; 2011 2012 if (wasSeeking != NO_SEEK && (mFlags & SEEK_PREVIEW)) { 2013 modifyFlags(SEEK_PREVIEW, CLEAR); 2014 return; 2015 } 2016 2017 /* get next frame time */ 2018 if (wasSeeking == NO_SEEK) { 2019 MediaSource::ReadOptions options; 2020 for (;;) { 2021 status_t err = mVideoSource->read(&mVideoBuffer, &options); 2022 if (err != OK) { 2023 // deal with any errors next time 2024 CHECK(mVideoBuffer == NULL); 2025 postVideoEvent_l(0); 2026 return; 2027 } 2028 2029 if (mVideoBuffer->range_length() != 0) { 2030 break; 2031 } 2032 2033 // Some decoders, notably the PV AVC software decoder 2034 // return spurious empty buffers that we just want to ignore. 2035 2036 mVideoBuffer->release(); 2037 mVideoBuffer = NULL; 2038 } 2039 2040 { 2041 Mutex::Autolock autoLock(mStatsLock); 2042 ++mStats.mNumVideoFramesDecoded; 2043 } 2044 2045 int64_t nextTimeUs; 2046 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &nextTimeUs)); 2047 systemTimeUs = mSystemTimeSource.getRealTimeUs(); 2048 int64_t delayUs = nextTimeUs - estimateRealTimeUs(ts, systemTimeUs) + mTimeSourceDeltaUs; 2049 ATRACE_INT("Frame delta (ms)", (nextTimeUs - timeUs) / 1E3); 2050 ALOGV("next frame in %" PRId64, delayUs); 2051 // try to schedule 30ms before time due 2052 postVideoEvent_l(delayUs > 60000 ? 30000 : (delayUs < 30000 ? 0 : delayUs - 30000)); 2053 return; 2054 } 2055 2056 postVideoEvent_l(); 2057 } 2058 2059 int64_t AwesomePlayer::estimateRealTimeUs(TimeSource *ts, int64_t systemTimeUs) { 2060 if (ts == &mSystemTimeSource) { 2061 return systemTimeUs; 2062 } else { 2063 return (int64_t)mClockEstimator->estimate(systemTimeUs, ts->getRealTimeUs()); 2064 } 2065 } 2066 2067 void AwesomePlayer::postVideoEvent_l(int64_t delayUs) { 2068 ATRACE_CALL(); 2069 2070 if (mVideoEventPending) { 2071 return; 2072 } 2073 2074 mVideoEventPending = true; 2075 mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs); 2076 } 2077 2078 void AwesomePlayer::postStreamDoneEvent_l(status_t status) { 2079 if (mStreamDoneEventPending) { 2080 return; 2081 } 2082 mStreamDoneEventPending = true; 2083 2084 mStreamDoneStatus = status; 2085 mQueue.postEvent(mStreamDoneEvent); 2086 } 2087 2088 void AwesomePlayer::postBufferingEvent_l() { 2089 if (mBufferingEventPending) { 2090 return; 2091 } 2092 mBufferingEventPending = true; 2093 mQueue.postEventWithDelay(mBufferingEvent, 1000000ll); 2094 } 2095 2096 void AwesomePlayer::postVideoLagEvent_l() { 2097 if (mVideoLagEventPending) { 2098 return; 2099 } 2100 mVideoLagEventPending = true; 2101 mQueue.postEventWithDelay(mVideoLagEvent, 1000000ll); 2102 } 2103 2104 void AwesomePlayer::postCheckAudioStatusEvent(int64_t delayUs) { 2105 Mutex::Autolock autoLock(mAudioLock); 2106 if (mAudioStatusEventPending) { 2107 return; 2108 } 2109 mAudioStatusEventPending = true; 2110 // Do not honor delay when looping in order to limit audio gap 2111 if (mFlags & (LOOPING | AUTO_LOOPING)) { 2112 delayUs = 0; 2113 } 2114 mQueue.postEventWithDelay(mCheckAudioStatusEvent, delayUs); 2115 } 2116 2117 void AwesomePlayer::postAudioTearDownEvent(int64_t delayUs) { 2118 Mutex::Autolock autoLock(mAudioLock); 2119 if (mAudioTearDownEventPending) { 2120 return; 2121 } 2122 mAudioTearDownEventPending = true; 2123 mQueue.postEventWithDelay(mAudioTearDownEvent, delayUs); 2124 } 2125 2126 void AwesomePlayer::onCheckAudioStatus() { 2127 { 2128 Mutex::Autolock autoLock(mAudioLock); 2129 if (!mAudioStatusEventPending) { 2130 // Event was dispatched and while we were blocking on the mutex, 2131 // has already been cancelled. 2132 return; 2133 } 2134 2135 mAudioStatusEventPending = false; 2136 } 2137 2138 Mutex::Autolock autoLock(mLock); 2139 2140 if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) { 2141 mWatchForAudioSeekComplete = false; 2142 2143 if (!mSeekNotificationSent) { 2144 notifyListener_l(MEDIA_SEEK_COMPLETE); 2145 mSeekNotificationSent = true; 2146 } 2147 2148 if (mVideoSource == NULL) { 2149 // For video the mSeeking flag is always reset in finishSeekIfNecessary 2150 mSeeking = NO_SEEK; 2151 } 2152 2153 notifyIfMediaStarted_l(); 2154 } 2155 2156 status_t finalStatus; 2157 if (mWatchForAudioEOS && mAudioPlayer->reachedEOS(&finalStatus)) { 2158 mWatchForAudioEOS = false; 2159 modifyFlags(AUDIO_AT_EOS, SET); 2160 modifyFlags(FIRST_FRAME, SET); 2161 postStreamDoneEvent_l(finalStatus); 2162 } 2163 } 2164 2165 status_t AwesomePlayer::prepare() { 2166 ATRACE_CALL(); 2167 Mutex::Autolock autoLock(mLock); 2168 return prepare_l(); 2169 } 2170 2171 status_t AwesomePlayer::prepare_l() { 2172 if (mFlags & PREPARED) { 2173 return OK; 2174 } 2175 2176 if (mFlags & PREPARING) { 2177 return UNKNOWN_ERROR; 2178 } 2179 2180 mIsAsyncPrepare = false; 2181 status_t err = prepareAsync_l(); 2182 2183 if (err != OK) { 2184 return err; 2185 } 2186 2187 while (mFlags & PREPARING) { 2188 mPreparedCondition.wait(mLock); 2189 } 2190 2191 return mPrepareResult; 2192 } 2193 2194 status_t AwesomePlayer::prepareAsync() { 2195 ATRACE_CALL(); 2196 Mutex::Autolock autoLock(mLock); 2197 2198 if (mFlags & PREPARING) { 2199 return UNKNOWN_ERROR; // async prepare already pending 2200 } 2201 2202 mIsAsyncPrepare = true; 2203 return prepareAsync_l(); 2204 } 2205 2206 status_t AwesomePlayer::prepareAsync_l() { 2207 if (mFlags & PREPARING) { 2208 return UNKNOWN_ERROR; // async prepare already pending 2209 } 2210 2211 if (!mQueueStarted) { 2212 mQueue.start(); 2213 mQueueStarted = true; 2214 } 2215 2216 modifyFlags(PREPARING, SET); 2217 mAsyncPrepareEvent = new AwesomeEvent( 2218 this, &AwesomePlayer::onPrepareAsyncEvent); 2219 2220 mQueue.postEvent(mAsyncPrepareEvent); 2221 2222 return OK; 2223 } 2224 2225 status_t AwesomePlayer::finishSetDataSource_l() { 2226 ATRACE_CALL(); 2227 sp<DataSource> dataSource; 2228 2229 bool isWidevineStreaming = false; 2230 if (!strncasecmp("widevine://", mUri.string(), 11)) { 2231 isWidevineStreaming = true; 2232 2233 String8 newURI = String8("http://"); 2234 newURI.append(mUri.string() + 11); 2235 2236 mUri = newURI; 2237 } 2238 2239 AString sniffedMIME; 2240 2241 if (!strncasecmp("http://", mUri.string(), 7) 2242 || !strncasecmp("https://", mUri.string(), 8) 2243 || isWidevineStreaming) { 2244 if (mHTTPService == NULL) { 2245 ALOGE("Attempt to play media from http URI without HTTP service."); 2246 return UNKNOWN_ERROR; 2247 } 2248 2249 sp<IMediaHTTPConnection> conn = mHTTPService->makeHTTPConnection(); 2250 mConnectingDataSource = new MediaHTTP(conn); 2251 2252 String8 cacheConfig; 2253 bool disconnectAtHighwatermark; 2254 NuCachedSource2::RemoveCacheSpecificHeaders( 2255 &mUriHeaders, &cacheConfig, &disconnectAtHighwatermark); 2256 2257 mLock.unlock(); 2258 status_t err = mConnectingDataSource->connect(mUri, &mUriHeaders); 2259 // force connection at this point, to avoid a race condition between getMIMEType and the 2260 // caching datasource constructed below, which could result in multiple requests to the 2261 // server, and/or failed connections. 2262 String8 contentType = mConnectingDataSource->getMIMEType(); 2263 mLock.lock(); 2264 2265 if (err != OK) { 2266 mConnectingDataSource.clear(); 2267 2268 ALOGI("mConnectingDataSource->connect() returned %d", err); 2269 return err; 2270 } 2271 2272 if (!isWidevineStreaming) { 2273 // The widevine extractor does its own caching. 2274 2275 #if 0 2276 mCachedSource = new NuCachedSource2( 2277 new ThrottledSource( 2278 mConnectingDataSource, 50 * 1024 /* bytes/sec */)); 2279 #else 2280 mCachedSource = new NuCachedSource2( 2281 mConnectingDataSource, 2282 cacheConfig.isEmpty() ? NULL : cacheConfig.string(), 2283 disconnectAtHighwatermark); 2284 #endif 2285 2286 dataSource = mCachedSource; 2287 } else { 2288 dataSource = mConnectingDataSource; 2289 } 2290 2291 mConnectingDataSource.clear(); 2292 2293 if (strncasecmp(contentType.string(), "audio/", 6)) { 2294 // We're not doing this for streams that appear to be audio-only 2295 // streams to ensure that even low bandwidth streams start 2296 // playing back fairly instantly. 2297 2298 // We're going to prefill the cache before trying to instantiate 2299 // the extractor below, as the latter is an operation that otherwise 2300 // could block on the datasource for a significant amount of time. 2301 // During that time we'd be unable to abort the preparation phase 2302 // without this prefill. 2303 if (mCachedSource != NULL) { 2304 // We're going to prefill the cache before trying to instantiate 2305 // the extractor below, as the latter is an operation that otherwise 2306 // could block on the datasource for a significant amount of time. 2307 // During that time we'd be unable to abort the preparation phase 2308 // without this prefill. 2309 2310 mLock.unlock(); 2311 2312 // Initially make sure we have at least 192 KB for the sniff 2313 // to complete without blocking. 2314 static const size_t kMinBytesForSniffing = 192 * 1024; 2315 2316 off64_t metaDataSize = -1ll; 2317 for (;;) { 2318 status_t finalStatus; 2319 size_t cachedDataRemaining = 2320 mCachedSource->approxDataRemaining(&finalStatus); 2321 2322 if (finalStatus != OK 2323 || (metaDataSize >= 0 2324 && (off64_t)cachedDataRemaining >= metaDataSize) 2325 || (mFlags & PREPARE_CANCELLED)) { 2326 break; 2327 } 2328 2329 ALOGV("now cached %zu bytes of data", cachedDataRemaining); 2330 2331 if (metaDataSize < 0 2332 && cachedDataRemaining >= kMinBytesForSniffing) { 2333 String8 tmp; 2334 float confidence; 2335 sp<AMessage> meta; 2336 if (!dataSource->sniff(&tmp, &confidence, &meta)) { 2337 mLock.lock(); 2338 return UNKNOWN_ERROR; 2339 } 2340 2341 // We successfully identified the file's extractor to 2342 // be, remember this mime type so we don't have to 2343 // sniff it again when we call MediaExtractor::Create() 2344 // below. 2345 sniffedMIME = tmp.string(); 2346 2347 if (meta == NULL 2348 || !meta->findInt64("meta-data-size", 2349 reinterpret_cast<int64_t*>(&metaDataSize))) { 2350 metaDataSize = kHighWaterMarkBytes; 2351 } 2352 2353 CHECK_GE(metaDataSize, 0ll); 2354 ALOGV("metaDataSize = %lld bytes", metaDataSize); 2355 } 2356 2357 usleep(200000); 2358 } 2359 2360 mLock.lock(); 2361 } 2362 2363 if (mFlags & PREPARE_CANCELLED) { 2364 ALOGI("Prepare cancelled while waiting for initial cache fill."); 2365 return UNKNOWN_ERROR; 2366 } 2367 } 2368 } else { 2369 dataSource = DataSource::CreateFromURI( 2370 mHTTPService, mUri.string(), &mUriHeaders); 2371 } 2372 2373 if (dataSource == NULL) { 2374 return UNKNOWN_ERROR; 2375 } 2376 2377 sp<MediaExtractor> extractor; 2378 2379 if (isWidevineStreaming) { 2380 String8 mimeType; 2381 float confidence; 2382 sp<AMessage> dummy; 2383 bool success; 2384 2385 // SniffWVM is potentially blocking since it may require network access. 2386 // Do not call it with mLock held. 2387 mLock.unlock(); 2388 success = SniffWVM(dataSource, &mimeType, &confidence, &dummy); 2389 mLock.lock(); 2390 2391 if (!success 2392 || strcasecmp( 2393 mimeType.string(), MEDIA_MIMETYPE_CONTAINER_WVM)) { 2394 return ERROR_UNSUPPORTED; 2395 } 2396 2397 mWVMExtractor = new WVMExtractor(dataSource); 2398 mWVMExtractor->setAdaptiveStreamingMode(true); 2399 if (mUIDValid) 2400 mWVMExtractor->setUID(mUID); 2401 extractor = mWVMExtractor; 2402 } else { 2403 extractor = MediaExtractor::Create( 2404 dataSource, sniffedMIME.empty() ? NULL : sniffedMIME.c_str()); 2405 2406 if (extractor == NULL) { 2407 return UNKNOWN_ERROR; 2408 } 2409 } 2410 2411 if (extractor->getDrmFlag()) { 2412 checkDrmStatus(dataSource); 2413 } 2414 2415 status_t err = setDataSource_l(extractor); 2416 2417 if (err != OK) { 2418 mWVMExtractor.clear(); 2419 2420 return err; 2421 } 2422 2423 return OK; 2424 } 2425 2426 void AwesomePlayer::abortPrepare(status_t err) { 2427 CHECK(err != OK); 2428 2429 if (mIsAsyncPrepare) { 2430 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err); 2431 } 2432 2433 mPrepareResult = err; 2434 modifyFlags((PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED), CLEAR); 2435 mAsyncPrepareEvent = NULL; 2436 mPreparedCondition.broadcast(); 2437 mAudioTearDown = false; 2438 } 2439 2440 // static 2441 bool AwesomePlayer::ContinuePreparation(void *cookie) { 2442 AwesomePlayer *me = static_cast<AwesomePlayer *>(cookie); 2443 2444 return (me->mFlags & PREPARE_CANCELLED) == 0; 2445 } 2446 2447 void AwesomePlayer::onPrepareAsyncEvent() { 2448 Mutex::Autolock autoLock(mLock); 2449 beginPrepareAsync_l(); 2450 } 2451 2452 void AwesomePlayer::beginPrepareAsync_l() { 2453 if (mFlags & PREPARE_CANCELLED) { 2454 ALOGI("prepare was cancelled before doing anything"); 2455 abortPrepare(UNKNOWN_ERROR); 2456 return; 2457 } 2458 2459 if (mUri.size() > 0) { 2460 status_t err = finishSetDataSource_l(); 2461 2462 if (err != OK) { 2463 abortPrepare(err); 2464 return; 2465 } 2466 } 2467 2468 if (mVideoTrack != NULL && mVideoSource == NULL) { 2469 status_t err = initVideoDecoder(); 2470 2471 if (err != OK) { 2472 abortPrepare(err); 2473 return; 2474 } 2475 } 2476 2477 if (mAudioTrack != NULL && mAudioSource == NULL) { 2478 status_t err = initAudioDecoder(); 2479 2480 if (err != OK) { 2481 abortPrepare(err); 2482 return; 2483 } 2484 } 2485 2486 modifyFlags(PREPARING_CONNECTED, SET); 2487 2488 if (isStreamingHTTP()) { 2489 postBufferingEvent_l(); 2490 } else { 2491 finishAsyncPrepare_l(); 2492 } 2493 } 2494 2495 void AwesomePlayer::finishAsyncPrepare_l() { 2496 if (mIsAsyncPrepare) { 2497 if (mVideoSource == NULL) { 2498 notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0); 2499 } else { 2500 notifyVideoSize_l(); 2501 } 2502 2503 notifyListener_l(MEDIA_PREPARED); 2504 } 2505 2506 mPrepareResult = OK; 2507 modifyFlags((PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED), CLEAR); 2508 modifyFlags(PREPARED, SET); 2509 mAsyncPrepareEvent = NULL; 2510 mPreparedCondition.broadcast(); 2511 2512 if (mAudioTearDown) { 2513 if (mPrepareResult == OK) { 2514 if (mExtractorFlags & MediaExtractor::CAN_SEEK) { 2515 seekTo_l(mAudioTearDownPosition); 2516 } 2517 2518 if (mAudioTearDownWasPlaying) { 2519 modifyFlags(CACHE_UNDERRUN, CLEAR); 2520 play_l(); 2521 } 2522 } 2523 mAudioTearDown = false; 2524 } 2525 } 2526 2527 uint32_t AwesomePlayer::flags() const { 2528 return mExtractorFlags; 2529 } 2530 2531 void AwesomePlayer::postAudioEOS(int64_t delayUs) { 2532 postCheckAudioStatusEvent(delayUs); 2533 } 2534 2535 void AwesomePlayer::postAudioSeekComplete() { 2536 postCheckAudioStatusEvent(0); 2537 } 2538 2539 void AwesomePlayer::postAudioTearDown() { 2540 postAudioTearDownEvent(0); 2541 } 2542 2543 status_t AwesomePlayer::setParameter(int key, const Parcel &request) { 2544 switch (key) { 2545 case KEY_PARAMETER_CACHE_STAT_COLLECT_FREQ_MS: 2546 { 2547 return setCacheStatCollectFreq(request); 2548 } 2549 case KEY_PARAMETER_PLAYBACK_RATE_PERMILLE: 2550 { 2551 if (mAudioPlayer != NULL) { 2552 return mAudioPlayer->setPlaybackRatePermille(request.readInt32()); 2553 } else { 2554 return NO_INIT; 2555 } 2556 } 2557 default: 2558 { 2559 return ERROR_UNSUPPORTED; 2560 } 2561 } 2562 } 2563 2564 status_t AwesomePlayer::setCacheStatCollectFreq(const Parcel &request) { 2565 if (mCachedSource != NULL) { 2566 int32_t freqMs = request.readInt32(); 2567 ALOGD("Request to keep cache stats in the past %d ms", 2568 freqMs); 2569 return mCachedSource->setCacheStatCollectFreq(freqMs); 2570 } 2571 return ERROR_UNSUPPORTED; 2572 } 2573 2574 status_t AwesomePlayer::getParameter(int key, Parcel *reply) { 2575 switch (key) { 2576 case KEY_PARAMETER_AUDIO_CHANNEL_COUNT: 2577 { 2578 int32_t channelCount; 2579 if (mAudioTrack == 0 || 2580 !mAudioTrack->getFormat()->findInt32(kKeyChannelCount, &channelCount)) { 2581 channelCount = 0; 2582 } 2583 reply->writeInt32(channelCount); 2584 } 2585 return OK; 2586 default: 2587 { 2588 return ERROR_UNSUPPORTED; 2589 } 2590 } 2591 } 2592 2593 status_t AwesomePlayer::getTrackInfo(Parcel *reply) const { 2594 Mutex::Autolock autoLock(mLock); 2595 size_t trackCount = mExtractor->countTracks(); 2596 if (mTextDriver != NULL) { 2597 trackCount += mTextDriver->countExternalTracks(); 2598 } 2599 2600 reply->writeInt32(trackCount); 2601 for (size_t i = 0; i < mExtractor->countTracks(); ++i) { 2602 sp<MetaData> meta = mExtractor->getTrackMetaData(i); 2603 2604 const char *_mime; 2605 CHECK(meta->findCString(kKeyMIMEType, &_mime)); 2606 2607 String8 mime = String8(_mime); 2608 2609 reply->writeInt32(2); // 2 fields 2610 2611 if (!strncasecmp(mime.string(), "video/", 6)) { 2612 reply->writeInt32(MEDIA_TRACK_TYPE_VIDEO); 2613 } else if (!strncasecmp(mime.string(), "audio/", 6)) { 2614 reply->writeInt32(MEDIA_TRACK_TYPE_AUDIO); 2615 } else if (!strcasecmp(mime.string(), MEDIA_MIMETYPE_TEXT_3GPP)) { 2616 reply->writeInt32(MEDIA_TRACK_TYPE_TIMEDTEXT); 2617 } else { 2618 reply->writeInt32(MEDIA_TRACK_TYPE_UNKNOWN); 2619 } 2620 2621 const char *lang; 2622 if (!meta->findCString(kKeyMediaLanguage, &lang)) { 2623 lang = "und"; 2624 } 2625 reply->writeString16(String16(lang)); 2626 } 2627 2628 if (mTextDriver != NULL) { 2629 mTextDriver->getExternalTrackInfo(reply); 2630 } 2631 return OK; 2632 } 2633 2634 status_t AwesomePlayer::selectAudioTrack_l( 2635 const sp<MediaSource>& source, size_t trackIndex) { 2636 2637 ALOGI("selectAudioTrack_l: trackIndex=%zu, mFlags=0x%x", trackIndex, mFlags); 2638 2639 { 2640 Mutex::Autolock autoLock(mStatsLock); 2641 if ((ssize_t)trackIndex == mActiveAudioTrackIndex) { 2642 ALOGI("Track %zu is active. Does nothing.", trackIndex); 2643 return OK; 2644 } 2645 //mStats.mFlags = mFlags; 2646 } 2647 2648 if (mSeeking != NO_SEEK) { 2649 ALOGE("Selecting a track while seeking is not supported"); 2650 return ERROR_UNSUPPORTED; 2651 } 2652 2653 if ((mFlags & PREPARED) == 0) { 2654 ALOGE("Data source has not finished preparation"); 2655 return ERROR_UNSUPPORTED; 2656 } 2657 2658 CHECK(source != NULL); 2659 bool wasPlaying = (mFlags & PLAYING) != 0; 2660 2661 pause_l(); 2662 2663 int64_t curTimeUs; 2664 CHECK_EQ(getPosition(&curTimeUs), (status_t)OK); 2665 2666 if ((mAudioPlayer == NULL || !(mFlags & AUDIOPLAYER_STARTED)) 2667 && mAudioSource != NULL) { 2668 // If we had an audio player, it would have effectively 2669 // taken possession of the audio source and stopped it when 2670 // _it_ is stopped. Otherwise this is still our responsibility. 2671 mAudioSource->stop(); 2672 } 2673 mAudioSource.clear(); 2674 mOmxSource.clear(); 2675 2676 mTimeSource = NULL; 2677 2678 delete mAudioPlayer; 2679 mAudioPlayer = NULL; 2680 2681 modifyFlags(AUDIOPLAYER_STARTED, CLEAR); 2682 2683 setAudioSource(source); 2684 2685 modifyFlags(AUDIO_AT_EOS, CLEAR); 2686 modifyFlags(AT_EOS, CLEAR); 2687 2688 status_t err; 2689 if ((err = initAudioDecoder()) != OK) { 2690 ALOGE("Failed to init audio decoder: 0x%x", err); 2691 return err; 2692 } 2693 2694 mSeekNotificationSent = true; 2695 seekTo_l(curTimeUs); 2696 2697 if (wasPlaying) { 2698 play_l(); 2699 } 2700 2701 mActiveAudioTrackIndex = trackIndex; 2702 2703 return OK; 2704 } 2705 2706 status_t AwesomePlayer::selectTrack(size_t trackIndex, bool select) { 2707 ATRACE_CALL(); 2708 ALOGV("selectTrack: trackIndex = %zu and select=%d", trackIndex, select); 2709 Mutex::Autolock autoLock(mLock); 2710 size_t trackCount = mExtractor->countTracks(); 2711 if (mTextDriver != NULL) { 2712 trackCount += mTextDriver->countExternalTracks(); 2713 } 2714 if (trackIndex >= trackCount) { 2715 ALOGE("Track index (%zu) is out of range [0, %zu)", trackIndex, trackCount); 2716 return ERROR_OUT_OF_RANGE; 2717 } 2718 2719 bool isAudioTrack = false; 2720 if (trackIndex < mExtractor->countTracks()) { 2721 sp<MetaData> meta = mExtractor->getTrackMetaData(trackIndex); 2722 const char *mime; 2723 CHECK(meta->findCString(kKeyMIMEType, &mime)); 2724 isAudioTrack = !strncasecmp(mime, "audio/", 6); 2725 2726 if (!isAudioTrack && strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP) != 0) { 2727 ALOGE("Track %zu is not either audio or timed text", trackIndex); 2728 return ERROR_UNSUPPORTED; 2729 } 2730 } 2731 2732 if (isAudioTrack) { 2733 if (!select) { 2734 ALOGE("Deselect an audio track (%zu) is not supported", trackIndex); 2735 return ERROR_UNSUPPORTED; 2736 } 2737 return selectAudioTrack_l(mExtractor->getTrack(trackIndex), trackIndex); 2738 } 2739 2740 // Timed text track handling 2741 if (mTextDriver == NULL) { 2742 return INVALID_OPERATION; 2743 } 2744 2745 status_t err = OK; 2746 if (select) { 2747 err = mTextDriver->selectTrack(trackIndex); 2748 if (err == OK) { 2749 modifyFlags(TEXTPLAYER_INITIALIZED, SET); 2750 if (mFlags & PLAYING && !(mFlags & TEXT_RUNNING)) { 2751 mTextDriver->start(); 2752 modifyFlags(TEXT_RUNNING, SET); 2753 } 2754 } 2755 } else { 2756 err = mTextDriver->unselectTrack(trackIndex); 2757 if (err == OK) { 2758 modifyFlags(TEXTPLAYER_INITIALIZED, CLEAR); 2759 modifyFlags(TEXT_RUNNING, CLEAR); 2760 } 2761 } 2762 return err; 2763 } 2764 2765 size_t AwesomePlayer::countTracks() const { 2766 return mExtractor->countTracks() + mTextDriver->countExternalTracks(); 2767 } 2768 2769 status_t AwesomePlayer::setVideoScalingMode(int32_t mode) { 2770 Mutex::Autolock lock(mLock); 2771 return setVideoScalingMode_l(mode); 2772 } 2773 2774 status_t AwesomePlayer::setVideoScalingMode_l(int32_t mode) { 2775 mVideoScalingMode = mode; 2776 if (mNativeWindow != NULL) { 2777 status_t err = native_window_set_scaling_mode( 2778 mNativeWindow.get(), mVideoScalingMode); 2779 if (err != OK) { 2780 ALOGW("Failed to set scaling mode: %d", err); 2781 } 2782 return err; 2783 } 2784 return OK; 2785 } 2786 2787 status_t AwesomePlayer::invoke(const Parcel &request, Parcel *reply) { 2788 ATRACE_CALL(); 2789 if (NULL == reply) { 2790 return android::BAD_VALUE; 2791 } 2792 int32_t methodId; 2793 status_t ret = request.readInt32(&methodId); 2794 if (ret != android::OK) { 2795 return ret; 2796 } 2797 switch(methodId) { 2798 case INVOKE_ID_SET_VIDEO_SCALING_MODE: 2799 { 2800 int mode = request.readInt32(); 2801 return setVideoScalingMode(mode); 2802 } 2803 2804 case INVOKE_ID_GET_TRACK_INFO: 2805 { 2806 return getTrackInfo(reply); 2807 } 2808 case INVOKE_ID_ADD_EXTERNAL_SOURCE: 2809 { 2810 Mutex::Autolock autoLock(mLock); 2811 if (mTextDriver == NULL) { 2812 mTextDriver = new TimedTextDriver(mListener, mHTTPService); 2813 } 2814 // String values written in Parcel are UTF-16 values. 2815 String8 uri(request.readString16()); 2816 String8 mimeType(request.readString16()); 2817 size_t nTracks = countTracks(); 2818 return mTextDriver->addOutOfBandTextSource(nTracks, uri, mimeType); 2819 } 2820 case INVOKE_ID_ADD_EXTERNAL_SOURCE_FD: 2821 { 2822 Mutex::Autolock autoLock(mLock); 2823 if (mTextDriver == NULL) { 2824 mTextDriver = new TimedTextDriver(mListener, mHTTPService); 2825 } 2826 int fd = request.readFileDescriptor(); 2827 off64_t offset = request.readInt64(); 2828 off64_t length = request.readInt64(); 2829 String8 mimeType(request.readString16()); 2830 size_t nTracks = countTracks(); 2831 return mTextDriver->addOutOfBandTextSource( 2832 nTracks, fd, offset, length, mimeType); 2833 } 2834 case INVOKE_ID_SELECT_TRACK: 2835 { 2836 int trackIndex = request.readInt32(); 2837 return selectTrack(trackIndex, true /* select */); 2838 } 2839 case INVOKE_ID_UNSELECT_TRACK: 2840 { 2841 int trackIndex = request.readInt32(); 2842 return selectTrack(trackIndex, false /* select */); 2843 } 2844 default: 2845 { 2846 return ERROR_UNSUPPORTED; 2847 } 2848 } 2849 // It will not reach here. 2850 return OK; 2851 } 2852 2853 bool AwesomePlayer::isStreamingHTTP() const { 2854 return mCachedSource != NULL || mWVMExtractor != NULL; 2855 } 2856 2857 status_t AwesomePlayer::dump( 2858 int fd, const Vector<String16> & /* args */) const { 2859 Mutex::Autolock autoLock(mStatsLock); 2860 2861 FILE *out = fdopen(dup(fd), "w"); 2862 2863 fprintf(out, " AwesomePlayer\n"); 2864 if (mStats.mFd < 0) { 2865 fprintf(out, " URI(%s)", uriDebugString(mUri, mFlags & INCOGNITO).c_str()); 2866 } else { 2867 fprintf(out, " fd(%d)", mStats.mFd); 2868 } 2869 2870 fprintf(out, ", flags(0x%08x)", mStats.mFlags); 2871 2872 if (mStats.mBitrate >= 0) { 2873 fprintf(out, ", bitrate(%" PRId64 " bps)", mStats.mBitrate); 2874 } 2875 2876 fprintf(out, "\n"); 2877 2878 for (size_t i = 0; i < mStats.mTracks.size(); ++i) { 2879 const TrackStat &stat = mStats.mTracks.itemAt(i); 2880 2881 fprintf(out, " Track %zu\n", i + 1); 2882 fprintf(out, " MIME(%s)", stat.mMIME.string()); 2883 2884 if (!stat.mDecoderName.isEmpty()) { 2885 fprintf(out, ", decoder(%s)", stat.mDecoderName.string()); 2886 } 2887 2888 fprintf(out, "\n"); 2889 2890 if ((ssize_t)i == mStats.mVideoTrackIndex) { 2891 fprintf(out, 2892 " videoDimensions(%d x %d), " 2893 "numVideoFramesDecoded(%" PRId64 "), " 2894 "numVideoFramesDropped(%" PRId64 ")\n", 2895 mStats.mVideoWidth, 2896 mStats.mVideoHeight, 2897 mStats.mNumVideoFramesDecoded, 2898 mStats.mNumVideoFramesDropped); 2899 } 2900 } 2901 2902 fclose(out); 2903 out = NULL; 2904 2905 return OK; 2906 } 2907 2908 void AwesomePlayer::modifyFlags(unsigned value, FlagMode mode) { 2909 switch (mode) { 2910 case SET: 2911 mFlags |= value; 2912 break; 2913 case CLEAR: 2914 if ((value & CACHE_UNDERRUN) && (mFlags & CACHE_UNDERRUN)) { 2915 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END); 2916 } 2917 mFlags &= ~value; 2918 break; 2919 case ASSIGN: 2920 mFlags = value; 2921 break; 2922 default: 2923 TRESPASS(); 2924 } 2925 2926 { 2927 Mutex::Autolock autoLock(mStatsLock); 2928 mStats.mFlags = mFlags; 2929 } 2930 } 2931 2932 void AwesomePlayer::onAudioTearDownEvent() { 2933 2934 Mutex::Autolock autoLock(mLock); 2935 if (!mAudioTearDownEventPending) { 2936 return; 2937 } 2938 mAudioTearDownEventPending = false; 2939 2940 ALOGV("onAudioTearDownEvent"); 2941 2942 // stream info is cleared by reset_l() so copy what we need 2943 mAudioTearDownWasPlaying = (mFlags & PLAYING); 2944 KeyedVector<String8, String8> uriHeaders(mUriHeaders); 2945 sp<DataSource> fileSource(mFileSource); 2946 2947 mStatsLock.lock(); 2948 String8 uri(mStats.mURI); 2949 mStatsLock.unlock(); 2950 2951 // get current position so we can start recreated stream from here 2952 getPosition(&mAudioTearDownPosition); 2953 2954 sp<IMediaHTTPService> savedHTTPService = mHTTPService; 2955 2956 bool wasLooping = mFlags & LOOPING; 2957 // Reset and recreate 2958 reset_l(); 2959 2960 status_t err; 2961 2962 if (fileSource != NULL) { 2963 mFileSource = fileSource; 2964 err = setDataSource_l(fileSource); 2965 } else { 2966 err = setDataSource_l(savedHTTPService, uri, &uriHeaders); 2967 } 2968 2969 mFlags |= PREPARING; 2970 if ( err != OK ) { 2971 // This will force beingPrepareAsync_l() to notify 2972 // a MEDIA_ERROR to the client and abort the prepare 2973 mFlags |= PREPARE_CANCELLED; 2974 } 2975 if (wasLooping) { 2976 mFlags |= LOOPING; 2977 } 2978 2979 mAudioTearDown = true; 2980 mIsAsyncPrepare = true; 2981 2982 // Call prepare for the host decoding 2983 beginPrepareAsync_l(); 2984 } 2985 2986 } // namespace android 2987