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