AwesomePlayer.cpp revision 99590d29c9d3081cadfccd036842f5ce9a7debef
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#include <utils/Log.h> 22 23#include <dlfcn.h> 24 25#include "include/ARTSPController.h" 26#include "include/AwesomePlayer.h" 27#include "include/DRMExtractor.h" 28#include "include/SoftwareRenderer.h" 29#include "include/NuCachedSource2.h" 30#include "include/ThrottledSource.h" 31#include "include/MPEG2TSExtractor.h" 32#include "include/WVMExtractor.h" 33 34#include "timedtext/TimedTextPlayer.h" 35 36#include <binder/IPCThreadState.h> 37#include <binder/IServiceManager.h> 38#include <media/IMediaPlayerService.h> 39#include <media/stagefright/foundation/hexdump.h> 40#include <media/stagefright/foundation/ADebug.h> 41#include <media/stagefright/AudioPlayer.h> 42#include <media/stagefright/DataSource.h> 43#include <media/stagefright/FileSource.h> 44#include <media/stagefright/MediaBuffer.h> 45#include <media/stagefright/MediaDefs.h> 46#include <media/stagefright/MediaExtractor.h> 47#include <media/stagefright/MediaSource.h> 48#include <media/stagefright/MetaData.h> 49#include <media/stagefright/OMXCodec.h> 50 51#include <surfaceflinger/Surface.h> 52#include <gui/ISurfaceTexture.h> 53#include <gui/SurfaceTextureClient.h> 54#include <surfaceflinger/ISurfaceComposer.h> 55 56#include <media/stagefright/foundation/ALooper.h> 57#include <media/stagefright/foundation/AMessage.h> 58 59#include <cutils/properties.h> 60 61#define USE_SURFACE_ALLOC 1 62 63namespace android { 64 65static int64_t kLowWaterMarkUs = 2000000ll; // 2secs 66static int64_t kHighWaterMarkUs = 5000000ll; // 5secs 67static int64_t kHighWaterMarkRTSPUs = 4000000ll; // 4secs 68static const size_t kLowWaterMarkBytes = 40000; 69static const size_t kHighWaterMarkBytes = 200000; 70 71struct AwesomeEvent : public TimedEventQueue::Event { 72 AwesomeEvent( 73 AwesomePlayer *player, 74 void (AwesomePlayer::*method)()) 75 : mPlayer(player), 76 mMethod(method) { 77 } 78 79protected: 80 virtual ~AwesomeEvent() {} 81 82 virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) { 83 (mPlayer->*mMethod)(); 84 } 85 86private: 87 AwesomePlayer *mPlayer; 88 void (AwesomePlayer::*mMethod)(); 89 90 AwesomeEvent(const AwesomeEvent &); 91 AwesomeEvent &operator=(const AwesomeEvent &); 92}; 93 94struct AwesomeLocalRenderer : public AwesomeRenderer { 95 AwesomeLocalRenderer( 96 const sp<ANativeWindow> &nativeWindow, const sp<MetaData> &meta) 97 : mTarget(new SoftwareRenderer(nativeWindow, meta)) { 98 } 99 100 virtual void render(MediaBuffer *buffer) { 101 render((const uint8_t *)buffer->data() + buffer->range_offset(), 102 buffer->range_length()); 103 } 104 105 void render(const void *data, size_t size) { 106 mTarget->render(data, size, NULL); 107 } 108 109protected: 110 virtual ~AwesomeLocalRenderer() { 111 delete mTarget; 112 mTarget = NULL; 113 } 114 115private: 116 SoftwareRenderer *mTarget; 117 118 AwesomeLocalRenderer(const AwesomeLocalRenderer &); 119 AwesomeLocalRenderer &operator=(const AwesomeLocalRenderer &);; 120}; 121 122struct AwesomeNativeWindowRenderer : public AwesomeRenderer { 123 AwesomeNativeWindowRenderer( 124 const sp<ANativeWindow> &nativeWindow, 125 int32_t rotationDegrees) 126 : mNativeWindow(nativeWindow) { 127 applyRotation(rotationDegrees); 128 } 129 130 virtual void render(MediaBuffer *buffer) { 131 int64_t timeUs; 132 CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs)); 133 native_window_set_buffers_timestamp(mNativeWindow.get(), timeUs * 1000); 134 status_t err = mNativeWindow->queueBuffer( 135 mNativeWindow.get(), buffer->graphicBuffer().get()); 136 if (err != 0) { 137 LOGE("queueBuffer failed with error %s (%d)", strerror(-err), 138 -err); 139 return; 140 } 141 142 sp<MetaData> metaData = buffer->meta_data(); 143 metaData->setInt32(kKeyRendered, 1); 144 } 145 146protected: 147 virtual ~AwesomeNativeWindowRenderer() {} 148 149private: 150 sp<ANativeWindow> mNativeWindow; 151 152 void applyRotation(int32_t rotationDegrees) { 153 uint32_t transform; 154 switch (rotationDegrees) { 155 case 0: transform = 0; break; 156 case 90: transform = HAL_TRANSFORM_ROT_90; break; 157 case 180: transform = HAL_TRANSFORM_ROT_180; break; 158 case 270: transform = HAL_TRANSFORM_ROT_270; break; 159 default: transform = 0; break; 160 } 161 162 if (transform) { 163 CHECK_EQ(0, native_window_set_buffers_transform( 164 mNativeWindow.get(), transform)); 165 } 166 } 167 168 AwesomeNativeWindowRenderer(const AwesomeNativeWindowRenderer &); 169 AwesomeNativeWindowRenderer &operator=( 170 const AwesomeNativeWindowRenderer &); 171}; 172 173// To collect the decoder usage 174void addBatteryData(uint32_t params) { 175 sp<IBinder> binder = 176 defaultServiceManager()->getService(String16("media.player")); 177 sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder); 178 CHECK(service.get() != NULL); 179 180 service->addBatteryData(params); 181} 182 183//////////////////////////////////////////////////////////////////////////////// 184AwesomePlayer::AwesomePlayer() 185 : mQueueStarted(false), 186 mUIDValid(false), 187 mTimeSource(NULL), 188 mVideoRendererIsPreview(false), 189 mAudioPlayer(NULL), 190 mDisplayWidth(0), 191 mDisplayHeight(0), 192 mFlags(0), 193 mExtractorFlags(0), 194 mVideoBuffer(NULL), 195 mDecryptHandle(NULL), 196 mLastVideoTimeUs(-1), 197 mTextPlayer(NULL) { 198 CHECK_EQ(mClient.connect(), (status_t)OK); 199 200 DataSource::RegisterDefaultSniffers(); 201 202 mVideoEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoEvent); 203 mVideoEventPending = false; 204 mStreamDoneEvent = new AwesomeEvent(this, &AwesomePlayer::onStreamDone); 205 mStreamDoneEventPending = false; 206 mBufferingEvent = new AwesomeEvent(this, &AwesomePlayer::onBufferingUpdate); 207 mBufferingEventPending = false; 208 mVideoLagEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoLagUpdate); 209 mVideoEventPending = false; 210 211 mCheckAudioStatusEvent = new AwesomeEvent( 212 this, &AwesomePlayer::onCheckAudioStatus); 213 214 mAudioStatusEventPending = false; 215 216 reset(); 217} 218 219AwesomePlayer::~AwesomePlayer() { 220 if (mQueueStarted) { 221 mQueue.stop(); 222 } 223 224 reset(); 225 226 mClient.disconnect(); 227} 228 229void AwesomePlayer::cancelPlayerEvents(bool keepBufferingGoing) { 230 mQueue.cancelEvent(mVideoEvent->eventID()); 231 mVideoEventPending = false; 232 mQueue.cancelEvent(mStreamDoneEvent->eventID()); 233 mStreamDoneEventPending = false; 234 mQueue.cancelEvent(mCheckAudioStatusEvent->eventID()); 235 mAudioStatusEventPending = false; 236 mQueue.cancelEvent(mVideoLagEvent->eventID()); 237 mVideoLagEventPending = false; 238 239 if (!keepBufferingGoing) { 240 mQueue.cancelEvent(mBufferingEvent->eventID()); 241 mBufferingEventPending = false; 242 } 243} 244 245void AwesomePlayer::setListener(const wp<MediaPlayerBase> &listener) { 246 Mutex::Autolock autoLock(mLock); 247 mListener = listener; 248} 249 250void AwesomePlayer::setUID(uid_t uid) { 251 LOGI("AwesomePlayer running on behalf of uid %d", uid); 252 253 mUID = uid; 254 mUIDValid = true; 255} 256 257status_t AwesomePlayer::setDataSource( 258 const char *uri, const KeyedVector<String8, String8> *headers) { 259 Mutex::Autolock autoLock(mLock); 260 return setDataSource_l(uri, headers); 261} 262 263status_t AwesomePlayer::setDataSource_l( 264 const char *uri, const KeyedVector<String8, String8> *headers) { 265 reset_l(); 266 267 mUri = uri; 268 269 if (headers) { 270 mUriHeaders = *headers; 271 272 ssize_t index = mUriHeaders.indexOfKey(String8("x-hide-urls-from-log")); 273 if (index >= 0) { 274 // Browser is in "incognito" mode, suppress logging URLs. 275 276 // This isn't something that should be passed to the server. 277 mUriHeaders.removeItemsAt(index); 278 279 modifyFlags(INCOGNITO, SET); 280 } 281 } 282 283 if (!(mFlags & INCOGNITO)) { 284 LOGI("setDataSource_l('%s')", mUri.string()); 285 } else { 286 LOGI("setDataSource_l(URL suppressed)"); 287 } 288 289 // The actual work will be done during preparation in the call to 290 // ::finishSetDataSource_l to avoid blocking the calling thread in 291 // setDataSource for any significant time. 292 293 { 294 Mutex::Autolock autoLock(mStatsLock); 295 mStats.mFd = -1; 296 mStats.mURI = mUri; 297 } 298 299 return OK; 300} 301 302status_t AwesomePlayer::setDataSource( 303 int fd, int64_t offset, int64_t length) { 304 Mutex::Autolock autoLock(mLock); 305 306 reset_l(); 307 308 sp<DataSource> dataSource = new FileSource(fd, offset, length); 309 310 status_t err = dataSource->initCheck(); 311 312 if (err != OK) { 313 return err; 314 } 315 316 mFileSource = dataSource; 317 318 { 319 Mutex::Autolock autoLock(mStatsLock); 320 mStats.mFd = fd; 321 mStats.mURI = String8(); 322 } 323 324 return setDataSource_l(dataSource); 325} 326 327status_t AwesomePlayer::setDataSource(const sp<IStreamSource> &source) { 328 return INVALID_OPERATION; 329} 330 331status_t AwesomePlayer::setDataSource_l( 332 const sp<DataSource> &dataSource) { 333 sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource); 334 335 if (extractor == NULL) { 336 return UNKNOWN_ERROR; 337 } 338 339 dataSource->getDrmInfo(mDecryptHandle, &mDrmManagerClient); 340 if (mDecryptHandle != NULL) { 341 CHECK(mDrmManagerClient); 342 if (RightsStatus::RIGHTS_VALID != mDecryptHandle->status) { 343 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_DRM_NO_LICENSE); 344 } 345 } 346 347 return setDataSource_l(extractor); 348} 349 350status_t AwesomePlayer::setDataSource_l(const sp<MediaExtractor> &extractor) { 351 // Attempt to approximate overall stream bitrate by summing all 352 // tracks' individual bitrates, if not all of them advertise bitrate, 353 // we have to fail. 354 355 int64_t totalBitRate = 0; 356 357 for (size_t i = 0; i < extractor->countTracks(); ++i) { 358 sp<MetaData> meta = extractor->getTrackMetaData(i); 359 360 int32_t bitrate; 361 if (!meta->findInt32(kKeyBitRate, &bitrate)) { 362 const char *mime; 363 CHECK(meta->findCString(kKeyMIMEType, &mime)); 364 LOGW("track of type '%s' does not publish bitrate", mime); 365 366 totalBitRate = -1; 367 break; 368 } 369 370 totalBitRate += bitrate; 371 } 372 373 mBitrate = totalBitRate; 374 375 LOGV("mBitrate = %lld bits/sec", mBitrate); 376 377 { 378 Mutex::Autolock autoLock(mStatsLock); 379 mStats.mBitrate = mBitrate; 380 mStats.mTracks.clear(); 381 mStats.mAudioTrackIndex = -1; 382 mStats.mVideoTrackIndex = -1; 383 } 384 385 bool haveAudio = false; 386 bool haveVideo = false; 387 for (size_t i = 0; i < extractor->countTracks(); ++i) { 388 sp<MetaData> meta = extractor->getTrackMetaData(i); 389 390 const char *mime; 391 CHECK(meta->findCString(kKeyMIMEType, &mime)); 392 393 if (!haveVideo && !strncasecmp(mime, "video/", 6)) { 394 setVideoSource(extractor->getTrack(i)); 395 haveVideo = true; 396 397 // Set the presentation/display size 398 int32_t displayWidth, displayHeight; 399 bool success = meta->findInt32(kKeyDisplayWidth, &displayWidth); 400 if (success) { 401 success = meta->findInt32(kKeyDisplayHeight, &displayHeight); 402 } 403 if (success) { 404 mDisplayWidth = displayWidth; 405 mDisplayHeight = displayHeight; 406 } 407 408 { 409 Mutex::Autolock autoLock(mStatsLock); 410 mStats.mVideoTrackIndex = mStats.mTracks.size(); 411 mStats.mTracks.push(); 412 TrackStat *stat = 413 &mStats.mTracks.editItemAt(mStats.mVideoTrackIndex); 414 stat->mMIME = mime; 415 } 416 } else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) { 417 setAudioSource(extractor->getTrack(i)); 418 haveAudio = true; 419 420 { 421 Mutex::Autolock autoLock(mStatsLock); 422 mStats.mAudioTrackIndex = mStats.mTracks.size(); 423 mStats.mTracks.push(); 424 TrackStat *stat = 425 &mStats.mTracks.editItemAt(mStats.mAudioTrackIndex); 426 stat->mMIME = mime; 427 } 428 429 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) { 430 // Only do this for vorbis audio, none of the other audio 431 // formats even support this ringtone specific hack and 432 // retrieving the metadata on some extractors may turn out 433 // to be very expensive. 434 sp<MetaData> fileMeta = extractor->getMetaData(); 435 int32_t loop; 436 if (fileMeta != NULL 437 && fileMeta->findInt32(kKeyAutoLoop, &loop) && loop != 0) { 438 modifyFlags(AUTO_LOOPING, SET); 439 } 440 } 441 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP)) { 442 addTextSource(extractor->getTrack(i)); 443 } 444 } 445 446 if (!haveAudio && !haveVideo) { 447 return UNKNOWN_ERROR; 448 } 449 450 mExtractorFlags = extractor->flags(); 451 452 return OK; 453} 454 455void AwesomePlayer::reset() { 456 Mutex::Autolock autoLock(mLock); 457 reset_l(); 458} 459 460void AwesomePlayer::reset_l() { 461 mDisplayWidth = 0; 462 mDisplayHeight = 0; 463 464 if (mDecryptHandle != NULL) { 465 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, 466 Playback::STOP, 0); 467 mDecryptHandle = NULL; 468 mDrmManagerClient = NULL; 469 } 470 471 if (mFlags & PLAYING) { 472 uint32_t params = IMediaPlayerService::kBatteryDataTrackDecoder; 473 if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) { 474 params |= IMediaPlayerService::kBatteryDataTrackAudio; 475 } 476 if (mVideoSource != NULL) { 477 params |= IMediaPlayerService::kBatteryDataTrackVideo; 478 } 479 addBatteryData(params); 480 } 481 482 if (mFlags & PREPARING) { 483 modifyFlags(PREPARE_CANCELLED, SET); 484 if (mConnectingDataSource != NULL) { 485 LOGI("interrupting the connection process"); 486 mConnectingDataSource->disconnect(); 487 } else if (mConnectingRTSPController != NULL) { 488 LOGI("interrupting the connection process"); 489 mConnectingRTSPController->disconnect(); 490 } 491 492 if (mFlags & PREPARING_CONNECTED) { 493 // We are basically done preparing, we're just buffering 494 // enough data to start playback, we can safely interrupt that. 495 finishAsyncPrepare_l(); 496 } 497 } 498 499 while (mFlags & PREPARING) { 500 mPreparedCondition.wait(mLock); 501 } 502 503 cancelPlayerEvents(); 504 505 mWVMExtractor.clear(); 506 mCachedSource.clear(); 507 mAudioTrack.clear(); 508 mVideoTrack.clear(); 509 510 // Shutdown audio first, so that the respone to the reset request 511 // appears to happen instantaneously as far as the user is concerned 512 // If we did this later, audio would continue playing while we 513 // shutdown the video-related resources and the player appear to 514 // not be as responsive to a reset request. 515 if (mAudioPlayer == NULL && mAudioSource != NULL) { 516 // If we had an audio player, it would have effectively 517 // taken possession of the audio source and stopped it when 518 // _it_ is stopped. Otherwise this is still our responsibility. 519 mAudioSource->stop(); 520 } 521 mAudioSource.clear(); 522 523 mTimeSource = NULL; 524 525 delete mAudioPlayer; 526 mAudioPlayer = NULL; 527 528 if (mTextPlayer != NULL) { 529 delete mTextPlayer; 530 mTextPlayer = NULL; 531 } 532 533 mVideoRenderer.clear(); 534 535 if (mRTSPController != NULL) { 536 mRTSPController->disconnect(); 537 mRTSPController.clear(); 538 } 539 540 if (mVideoSource != NULL) { 541 shutdownVideoDecoder_l(); 542 } 543 544 mDurationUs = -1; 545 modifyFlags(0, ASSIGN); 546 mExtractorFlags = 0; 547 mTimeSourceDeltaUs = 0; 548 mVideoTimeUs = 0; 549 550 mSeeking = NO_SEEK; 551 mSeekNotificationSent = false; 552 mSeekTimeUs = 0; 553 554 mUri.setTo(""); 555 mUriHeaders.clear(); 556 557 mFileSource.clear(); 558 559 mBitrate = -1; 560 mLastVideoTimeUs = -1; 561 562 { 563 Mutex::Autolock autoLock(mStatsLock); 564 mStats.mFd = -1; 565 mStats.mURI = String8(); 566 mStats.mBitrate = -1; 567 mStats.mAudioTrackIndex = -1; 568 mStats.mVideoTrackIndex = -1; 569 mStats.mNumVideoFramesDecoded = 0; 570 mStats.mNumVideoFramesDropped = 0; 571 mStats.mVideoWidth = -1; 572 mStats.mVideoHeight = -1; 573 mStats.mFlags = 0; 574 mStats.mTracks.clear(); 575 } 576 577 mWatchForAudioSeekComplete = false; 578 mWatchForAudioEOS = false; 579} 580 581void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) { 582 if (mListener != NULL) { 583 sp<MediaPlayerBase> listener = mListener.promote(); 584 585 if (listener != NULL) { 586 listener->sendEvent(msg, ext1, ext2); 587 } 588 } 589} 590 591bool AwesomePlayer::getBitrate(int64_t *bitrate) { 592 off64_t size; 593 if (mDurationUs >= 0 && mCachedSource != NULL 594 && mCachedSource->getSize(&size) == OK) { 595 *bitrate = size * 8000000ll / mDurationUs; // in bits/sec 596 return true; 597 } 598 599 if (mBitrate >= 0) { 600 *bitrate = mBitrate; 601 return true; 602 } 603 604 *bitrate = 0; 605 606 return false; 607} 608 609// Returns true iff cached duration is available/applicable. 610bool AwesomePlayer::getCachedDuration_l(int64_t *durationUs, bool *eos) { 611 int64_t bitrate; 612 613 if (mRTSPController != NULL) { 614 *durationUs = mRTSPController->getQueueDurationUs(eos); 615 return true; 616 } else if (mCachedSource != NULL && getBitrate(&bitrate)) { 617 status_t finalStatus; 618 size_t cachedDataRemaining = mCachedSource->approxDataRemaining(&finalStatus); 619 *durationUs = cachedDataRemaining * 8000000ll / bitrate; 620 *eos = (finalStatus != OK); 621 return true; 622 } else if (mWVMExtractor != NULL) { 623 status_t finalStatus; 624 *durationUs = mWVMExtractor->getCachedDurationUs(&finalStatus); 625 *eos = (finalStatus != OK); 626 return true; 627 } 628 629 return false; 630} 631 632void AwesomePlayer::ensureCacheIsFetching_l() { 633 if (mCachedSource != NULL) { 634 mCachedSource->resumeFetchingIfNecessary(); 635 } 636} 637 638void AwesomePlayer::onVideoLagUpdate() { 639 Mutex::Autolock autoLock(mLock); 640 if (!mVideoLagEventPending) { 641 return; 642 } 643 mVideoLagEventPending = false; 644 645 int64_t audioTimeUs = mAudioPlayer->getMediaTimeUs(); 646 int64_t videoLateByUs = audioTimeUs - mVideoTimeUs; 647 648 if (!(mFlags & VIDEO_AT_EOS) && videoLateByUs > 300000ll) { 649 LOGV("video late by %lld ms.", videoLateByUs / 1000ll); 650 651 notifyListener_l( 652 MEDIA_INFO, 653 MEDIA_INFO_VIDEO_TRACK_LAGGING, 654 videoLateByUs / 1000ll); 655 } 656 657 postVideoLagEvent_l(); 658} 659 660void AwesomePlayer::onBufferingUpdate() { 661 Mutex::Autolock autoLock(mLock); 662 if (!mBufferingEventPending) { 663 return; 664 } 665 mBufferingEventPending = false; 666 667 if (mCachedSource != NULL) { 668 status_t finalStatus; 669 size_t cachedDataRemaining = mCachedSource->approxDataRemaining(&finalStatus); 670 bool eos = (finalStatus != OK); 671 672 if (eos) { 673 if (finalStatus == ERROR_END_OF_STREAM) { 674 notifyListener_l(MEDIA_BUFFERING_UPDATE, 100); 675 } 676 if (mFlags & PREPARING) { 677 LOGV("cache has reached EOS, prepare is done."); 678 finishAsyncPrepare_l(); 679 } 680 } else { 681 int64_t bitrate; 682 if (getBitrate(&bitrate)) { 683 size_t cachedSize = mCachedSource->cachedSize(); 684 int64_t cachedDurationUs = cachedSize * 8000000ll / bitrate; 685 686 int percentage = 100.0 * (double)cachedDurationUs / mDurationUs; 687 if (percentage > 100) { 688 percentage = 100; 689 } 690 691 notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage); 692 } else { 693 // We don't know the bitrate of the stream, use absolute size 694 // limits to maintain the cache. 695 696 if ((mFlags & PLAYING) && !eos 697 && (cachedDataRemaining < kLowWaterMarkBytes)) { 698 LOGI("cache is running low (< %d) , pausing.", 699 kLowWaterMarkBytes); 700 modifyFlags(CACHE_UNDERRUN, SET); 701 pause_l(); 702 ensureCacheIsFetching_l(); 703 sendCacheStats(); 704 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START); 705 } else if (eos || cachedDataRemaining > kHighWaterMarkBytes) { 706 if (mFlags & CACHE_UNDERRUN) { 707 LOGI("cache has filled up (> %d), resuming.", 708 kHighWaterMarkBytes); 709 modifyFlags(CACHE_UNDERRUN, CLEAR); 710 play_l(); 711 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END); 712 } else if (mFlags & PREPARING) { 713 LOGV("cache has filled up (> %d), prepare is done", 714 kHighWaterMarkBytes); 715 finishAsyncPrepare_l(); 716 } 717 } 718 } 719 } 720 } else if (mWVMExtractor != NULL) { 721 status_t finalStatus; 722 723 int64_t cachedDurationUs 724 = mWVMExtractor->getCachedDurationUs(&finalStatus); 725 726 bool eos = (finalStatus != OK); 727 728 if (eos) { 729 if (finalStatus == ERROR_END_OF_STREAM) { 730 notifyListener_l(MEDIA_BUFFERING_UPDATE, 100); 731 } 732 if (mFlags & PREPARING) { 733 LOGV("cache has reached EOS, prepare is done."); 734 finishAsyncPrepare_l(); 735 } 736 } else { 737 int percentage = 100.0 * (double)cachedDurationUs / mDurationUs; 738 if (percentage > 100) { 739 percentage = 100; 740 } 741 742 notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage); 743 } 744 } 745 746 int64_t cachedDurationUs; 747 bool eos; 748 if (getCachedDuration_l(&cachedDurationUs, &eos)) { 749 LOGV("cachedDurationUs = %.2f secs, eos=%d", 750 cachedDurationUs / 1E6, eos); 751 752 int64_t highWaterMarkUs = 753 (mRTSPController != NULL) ? kHighWaterMarkRTSPUs : kHighWaterMarkUs; 754 755 if ((mFlags & PLAYING) && !eos 756 && (cachedDurationUs < kLowWaterMarkUs)) { 757 LOGI("cache is running low (%.2f secs) , pausing.", 758 cachedDurationUs / 1E6); 759 modifyFlags(CACHE_UNDERRUN, SET); 760 pause_l(); 761 ensureCacheIsFetching_l(); 762 sendCacheStats(); 763 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START); 764 } else if (eos || cachedDurationUs > highWaterMarkUs) { 765 if (mFlags & CACHE_UNDERRUN) { 766 LOGI("cache has filled up (%.2f secs), resuming.", 767 cachedDurationUs / 1E6); 768 modifyFlags(CACHE_UNDERRUN, CLEAR); 769 play_l(); 770 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END); 771 } else if (mFlags & PREPARING) { 772 LOGV("cache has filled up (%.2f secs), prepare is done", 773 cachedDurationUs / 1E6); 774 finishAsyncPrepare_l(); 775 } 776 } 777 } 778 779 postBufferingEvent_l(); 780} 781 782void AwesomePlayer::sendCacheStats() { 783 sp<MediaPlayerBase> listener = mListener.promote(); 784 if (listener != NULL && mCachedSource != NULL) { 785 int32_t kbps = 0; 786 status_t err = mCachedSource->getEstimatedBandwidthKbps(&kbps); 787 if (err == OK) { 788 listener->sendEvent( 789 MEDIA_INFO, MEDIA_INFO_NETWORK_BANDWIDTH, kbps); 790 } 791 } 792} 793 794void AwesomePlayer::onStreamDone() { 795 // Posted whenever any stream finishes playing. 796 797 Mutex::Autolock autoLock(mLock); 798 if (!mStreamDoneEventPending) { 799 return; 800 } 801 mStreamDoneEventPending = false; 802 803 if (mStreamDoneStatus != ERROR_END_OF_STREAM) { 804 LOGV("MEDIA_ERROR %d", mStreamDoneStatus); 805 806 notifyListener_l( 807 MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, mStreamDoneStatus); 808 809 pause_l(true /* at eos */); 810 811 modifyFlags(AT_EOS, SET); 812 return; 813 } 814 815 const bool allDone = 816 (mVideoSource == NULL || (mFlags & VIDEO_AT_EOS)) 817 && (mAudioSource == NULL || (mFlags & AUDIO_AT_EOS)); 818 819 if (!allDone) { 820 return; 821 } 822 823 if (mFlags & (LOOPING | AUTO_LOOPING)) { 824 seekTo_l(0); 825 826 if (mVideoSource != NULL) { 827 postVideoEvent_l(); 828 } 829 } else { 830 LOGV("MEDIA_PLAYBACK_COMPLETE"); 831 notifyListener_l(MEDIA_PLAYBACK_COMPLETE); 832 833 pause_l(true /* at eos */); 834 835 modifyFlags(AT_EOS, SET); 836 } 837} 838 839status_t AwesomePlayer::play() { 840 Mutex::Autolock autoLock(mLock); 841 842 modifyFlags(CACHE_UNDERRUN, CLEAR); 843 844 return play_l(); 845} 846 847status_t AwesomePlayer::play_l() { 848 modifyFlags(SEEK_PREVIEW, CLEAR); 849 850 if (mFlags & PLAYING) { 851 return OK; 852 } 853 854 if (!(mFlags & PREPARED)) { 855 status_t err = prepare_l(); 856 857 if (err != OK) { 858 return err; 859 } 860 } 861 862 modifyFlags(PLAYING, SET); 863 modifyFlags(FIRST_FRAME, SET); 864 865 if (mDecryptHandle != NULL) { 866 int64_t position; 867 getPosition(&position); 868 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, 869 Playback::START, position / 1000); 870 } 871 872 if (mAudioSource != NULL) { 873 if (mAudioPlayer == NULL) { 874 if (mAudioSink != NULL) { 875 mAudioPlayer = new AudioPlayer(mAudioSink, this); 876 mAudioPlayer->setSource(mAudioSource); 877 878 mTimeSource = mAudioPlayer; 879 880 // If there was a seek request before we ever started, 881 // honor the request now. 882 // Make sure to do this before starting the audio player 883 // to avoid a race condition. 884 seekAudioIfNecessary_l(); 885 } 886 } 887 888 CHECK(!(mFlags & AUDIO_RUNNING)); 889 890 if (mVideoSource == NULL) { 891 // We don't want to post an error notification at this point, 892 // the error returned from MediaPlayer::start() will suffice. 893 894 status_t err = startAudioPlayer_l( 895 false /* sendErrorNotification */); 896 897 if (err != OK) { 898 delete mAudioPlayer; 899 mAudioPlayer = NULL; 900 901 modifyFlags((PLAYING | FIRST_FRAME), CLEAR); 902 903 if (mDecryptHandle != NULL) { 904 mDrmManagerClient->setPlaybackStatus( 905 mDecryptHandle, Playback::STOP, 0); 906 } 907 908 return err; 909 } 910 } 911 } 912 913 if (mTimeSource == NULL && mAudioPlayer == NULL) { 914 mTimeSource = &mSystemTimeSource; 915 } 916 917 if (mVideoSource != NULL) { 918 // Kick off video playback 919 postVideoEvent_l(); 920 921 if (mAudioSource != NULL && mVideoSource != NULL) { 922 postVideoLagEvent_l(); 923 } 924 } 925 926 if (mFlags & AT_EOS) { 927 // Legacy behaviour, if a stream finishes playing and then 928 // is started again, we play from the start... 929 seekTo_l(0); 930 } 931 932 uint32_t params = IMediaPlayerService::kBatteryDataCodecStarted 933 | IMediaPlayerService::kBatteryDataTrackDecoder; 934 if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) { 935 params |= IMediaPlayerService::kBatteryDataTrackAudio; 936 } 937 if (mVideoSource != NULL) { 938 params |= IMediaPlayerService::kBatteryDataTrackVideo; 939 } 940 addBatteryData(params); 941 942 return OK; 943} 944 945status_t AwesomePlayer::startAudioPlayer_l(bool sendErrorNotification) { 946 CHECK(!(mFlags & AUDIO_RUNNING)); 947 948 if (mAudioSource == NULL || mAudioPlayer == NULL) { 949 return OK; 950 } 951 952 if (!(mFlags & AUDIOPLAYER_STARTED)) { 953 modifyFlags(AUDIOPLAYER_STARTED, SET); 954 955 bool wasSeeking = mAudioPlayer->isSeeking(); 956 957 // We've already started the MediaSource in order to enable 958 // the prefetcher to read its data. 959 status_t err = mAudioPlayer->start( 960 true /* sourceAlreadyStarted */); 961 962 if (err != OK) { 963 if (sendErrorNotification) { 964 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err); 965 } 966 967 return err; 968 } 969 970 if (wasSeeking) { 971 CHECK(!mAudioPlayer->isSeeking()); 972 973 // We will have finished the seek while starting the audio player. 974 postAudioSeekComplete_l(); 975 } 976 } else { 977 mAudioPlayer->resume(); 978 } 979 980 modifyFlags(AUDIO_RUNNING, SET); 981 982 mWatchForAudioEOS = true; 983 984 return OK; 985} 986 987void AwesomePlayer::notifyVideoSize_l() { 988 sp<MetaData> meta = mVideoSource->getFormat(); 989 990 int32_t cropLeft, cropTop, cropRight, cropBottom; 991 if (!meta->findRect( 992 kKeyCropRect, &cropLeft, &cropTop, &cropRight, &cropBottom)) { 993 int32_t width, height; 994 CHECK(meta->findInt32(kKeyWidth, &width)); 995 CHECK(meta->findInt32(kKeyHeight, &height)); 996 997 cropLeft = cropTop = 0; 998 cropRight = width - 1; 999 cropBottom = height - 1; 1000 1001 LOGV("got dimensions only %d x %d", width, height); 1002 } else { 1003 LOGV("got crop rect %d, %d, %d, %d", 1004 cropLeft, cropTop, cropRight, cropBottom); 1005 } 1006 1007 int32_t displayWidth; 1008 if (meta->findInt32(kKeyDisplayWidth, &displayWidth)) { 1009 LOGV("Display width changed (%d=>%d)", mDisplayWidth, displayWidth); 1010 mDisplayWidth = displayWidth; 1011 } 1012 int32_t displayHeight; 1013 if (meta->findInt32(kKeyDisplayHeight, &displayHeight)) { 1014 LOGV("Display height changed (%d=>%d)", mDisplayHeight, displayHeight); 1015 mDisplayHeight = displayHeight; 1016 } 1017 1018 int32_t usableWidth = cropRight - cropLeft + 1; 1019 int32_t usableHeight = cropBottom - cropTop + 1; 1020 if (mDisplayWidth != 0) { 1021 usableWidth = mDisplayWidth; 1022 } 1023 if (mDisplayHeight != 0) { 1024 usableHeight = mDisplayHeight; 1025 } 1026 1027 { 1028 Mutex::Autolock autoLock(mStatsLock); 1029 mStats.mVideoWidth = usableWidth; 1030 mStats.mVideoHeight = usableHeight; 1031 } 1032 1033 int32_t rotationDegrees; 1034 if (!mVideoTrack->getFormat()->findInt32( 1035 kKeyRotation, &rotationDegrees)) { 1036 rotationDegrees = 0; 1037 } 1038 1039 if (rotationDegrees == 90 || rotationDegrees == 270) { 1040 notifyListener_l( 1041 MEDIA_SET_VIDEO_SIZE, usableHeight, usableWidth); 1042 } else { 1043 notifyListener_l( 1044 MEDIA_SET_VIDEO_SIZE, usableWidth, usableHeight); 1045 } 1046} 1047 1048void AwesomePlayer::initRenderer_l() { 1049 if (mNativeWindow == NULL) { 1050 return; 1051 } 1052 1053 sp<MetaData> meta = mVideoSource->getFormat(); 1054 1055 int32_t format; 1056 const char *component; 1057 int32_t decodedWidth, decodedHeight; 1058 CHECK(meta->findInt32(kKeyColorFormat, &format)); 1059 CHECK(meta->findCString(kKeyDecoderComponent, &component)); 1060 CHECK(meta->findInt32(kKeyWidth, &decodedWidth)); 1061 CHECK(meta->findInt32(kKeyHeight, &decodedHeight)); 1062 1063 int32_t rotationDegrees; 1064 if (!mVideoTrack->getFormat()->findInt32( 1065 kKeyRotation, &rotationDegrees)) { 1066 rotationDegrees = 0; 1067 } 1068 1069 mVideoRenderer.clear(); 1070 1071 // Must ensure that mVideoRenderer's destructor is actually executed 1072 // before creating a new one. 1073 IPCThreadState::self()->flushCommands(); 1074 1075 if (USE_SURFACE_ALLOC 1076 && !strncmp(component, "OMX.", 4) 1077 && strncmp(component, "OMX.google.", 11)) { 1078 // Hardware decoders avoid the CPU color conversion by decoding 1079 // directly to ANativeBuffers, so we must use a renderer that 1080 // just pushes those buffers to the ANativeWindow. 1081 mVideoRenderer = 1082 new AwesomeNativeWindowRenderer(mNativeWindow, rotationDegrees); 1083 } else { 1084 // Other decoders are instantiated locally and as a consequence 1085 // allocate their buffers in local address space. This renderer 1086 // then performs a color conversion and copy to get the data 1087 // into the ANativeBuffer. 1088 mVideoRenderer = new AwesomeLocalRenderer(mNativeWindow, meta); 1089 } 1090} 1091 1092status_t AwesomePlayer::pause() { 1093 Mutex::Autolock autoLock(mLock); 1094 1095 modifyFlags(CACHE_UNDERRUN, CLEAR); 1096 1097 return pause_l(); 1098} 1099 1100status_t AwesomePlayer::pause_l(bool at_eos) { 1101 if (!(mFlags & PLAYING)) { 1102 return OK; 1103 } 1104 1105 cancelPlayerEvents(true /* keepBufferingGoing */); 1106 1107 if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) { 1108 if (at_eos) { 1109 // If we played the audio stream to completion we 1110 // want to make sure that all samples remaining in the audio 1111 // track's queue are played out. 1112 mAudioPlayer->pause(true /* playPendingSamples */); 1113 } else { 1114 mAudioPlayer->pause(); 1115 } 1116 1117 modifyFlags(AUDIO_RUNNING, CLEAR); 1118 } 1119 1120 if (mFlags & TEXTPLAYER_STARTED) { 1121 mTextPlayer->pause(); 1122 modifyFlags(TEXT_RUNNING, CLEAR); 1123 } 1124 1125 modifyFlags(PLAYING, CLEAR); 1126 1127 if (mDecryptHandle != NULL) { 1128 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, 1129 Playback::PAUSE, 0); 1130 } 1131 1132 uint32_t params = IMediaPlayerService::kBatteryDataTrackDecoder; 1133 if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) { 1134 params |= IMediaPlayerService::kBatteryDataTrackAudio; 1135 } 1136 if (mVideoSource != NULL) { 1137 params |= IMediaPlayerService::kBatteryDataTrackVideo; 1138 } 1139 1140 addBatteryData(params); 1141 1142 return OK; 1143} 1144 1145bool AwesomePlayer::isPlaying() const { 1146 return (mFlags & PLAYING) || (mFlags & CACHE_UNDERRUN); 1147} 1148 1149void AwesomePlayer::setSurface(const sp<Surface> &surface) { 1150 Mutex::Autolock autoLock(mLock); 1151 1152 mSurface = surface; 1153 setNativeWindow_l(surface); 1154} 1155 1156void AwesomePlayer::setSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture) { 1157 Mutex::Autolock autoLock(mLock); 1158 1159 mSurface.clear(); 1160 if (surfaceTexture != NULL) { 1161 setNativeWindow_l(new SurfaceTextureClient(surfaceTexture)); 1162 } else { 1163 setNativeWindow_l(NULL); 1164 } 1165} 1166 1167void AwesomePlayer::shutdownVideoDecoder_l() { 1168 if (mVideoBuffer) { 1169 mVideoBuffer->release(); 1170 mVideoBuffer = NULL; 1171 } 1172 1173 mVideoSource->stop(); 1174 1175 // The following hack is necessary to ensure that the OMX 1176 // component is completely released by the time we may try 1177 // to instantiate it again. 1178 wp<MediaSource> tmp = mVideoSource; 1179 mVideoSource.clear(); 1180 while (tmp.promote() != NULL) { 1181 usleep(1000); 1182 } 1183 IPCThreadState::self()->flushCommands(); 1184 LOGI("video decoder shutdown completed"); 1185} 1186 1187void AwesomePlayer::setNativeWindow_l(const sp<ANativeWindow> &native) { 1188 mNativeWindow = native; 1189 1190 if (mVideoSource == NULL) { 1191 return; 1192 } 1193 1194 LOGI("attempting to reconfigure to use new surface"); 1195 1196 bool wasPlaying = (mFlags & PLAYING) != 0; 1197 1198 pause_l(); 1199 mVideoRenderer.clear(); 1200 1201 shutdownVideoDecoder_l(); 1202 1203 CHECK_EQ(initVideoDecoder(), (status_t)OK); 1204 1205 if (mLastVideoTimeUs >= 0) { 1206 mSeeking = SEEK; 1207 mSeekNotificationSent = true; 1208 mSeekTimeUs = mLastVideoTimeUs; 1209 modifyFlags((AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS), CLEAR); 1210 } 1211 1212 if (wasPlaying) { 1213 play_l(); 1214 } 1215} 1216 1217void AwesomePlayer::setAudioSink( 1218 const sp<MediaPlayerBase::AudioSink> &audioSink) { 1219 Mutex::Autolock autoLock(mLock); 1220 1221 mAudioSink = audioSink; 1222} 1223 1224status_t AwesomePlayer::setLooping(bool shouldLoop) { 1225 Mutex::Autolock autoLock(mLock); 1226 1227 modifyFlags(LOOPING, CLEAR); 1228 1229 if (shouldLoop) { 1230 modifyFlags(LOOPING, SET); 1231 } 1232 1233 return OK; 1234} 1235 1236status_t AwesomePlayer::getDuration(int64_t *durationUs) { 1237 Mutex::Autolock autoLock(mMiscStateLock); 1238 1239 if (mDurationUs < 0) { 1240 return UNKNOWN_ERROR; 1241 } 1242 1243 *durationUs = mDurationUs; 1244 1245 return OK; 1246} 1247 1248status_t AwesomePlayer::getPosition(int64_t *positionUs) { 1249 if (mRTSPController != NULL) { 1250 *positionUs = mRTSPController->getNormalPlayTimeUs(); 1251 } 1252 else if (mSeeking != NO_SEEK) { 1253 *positionUs = mSeekTimeUs; 1254 } else if (mVideoSource != NULL 1255 && (mAudioPlayer == NULL || !(mFlags & VIDEO_AT_EOS))) { 1256 Mutex::Autolock autoLock(mMiscStateLock); 1257 *positionUs = mVideoTimeUs; 1258 } else if (mAudioPlayer != NULL) { 1259 *positionUs = mAudioPlayer->getMediaTimeUs(); 1260 } else { 1261 *positionUs = 0; 1262 } 1263 1264 return OK; 1265} 1266 1267status_t AwesomePlayer::seekTo(int64_t timeUs) { 1268 if (mExtractorFlags & MediaExtractor::CAN_SEEK) { 1269 Mutex::Autolock autoLock(mLock); 1270 return seekTo_l(timeUs); 1271 } 1272 1273 return OK; 1274} 1275 1276status_t AwesomePlayer::setTimedTextTrackIndex(int32_t index) { 1277 if (mTextPlayer != NULL) { 1278 if (index >= 0) { // to turn on a text track 1279 status_t err = mTextPlayer->setTimedTextTrackIndex(index); 1280 if (err != OK) { 1281 return err; 1282 } 1283 1284 modifyFlags(TEXT_RUNNING, SET); 1285 modifyFlags(TEXTPLAYER_STARTED, SET); 1286 return OK; 1287 } else { // to turn off the text track display 1288 if (mFlags & TEXT_RUNNING) { 1289 modifyFlags(TEXT_RUNNING, CLEAR); 1290 } 1291 if (mFlags & TEXTPLAYER_STARTED) { 1292 modifyFlags(TEXTPLAYER_STARTED, CLEAR); 1293 } 1294 1295 return mTextPlayer->setTimedTextTrackIndex(index); 1296 } 1297 } else { 1298 return INVALID_OPERATION; 1299 } 1300} 1301 1302// static 1303void AwesomePlayer::OnRTSPSeekDoneWrapper(void *cookie) { 1304 static_cast<AwesomePlayer *>(cookie)->onRTSPSeekDone(); 1305} 1306 1307void AwesomePlayer::onRTSPSeekDone() { 1308 notifyListener_l(MEDIA_SEEK_COMPLETE); 1309 mSeekNotificationSent = true; 1310} 1311 1312status_t AwesomePlayer::seekTo_l(int64_t timeUs) { 1313 if (mRTSPController != NULL) { 1314 mRTSPController->seekAsync(timeUs, OnRTSPSeekDoneWrapper, this); 1315 return OK; 1316 } 1317 1318 if (mFlags & CACHE_UNDERRUN) { 1319 modifyFlags(CACHE_UNDERRUN, CLEAR); 1320 play_l(); 1321 } 1322 1323 if ((mFlags & PLAYING) && mVideoSource != NULL && (mFlags & VIDEO_AT_EOS)) { 1324 // Video playback completed before, there's no pending 1325 // video event right now. In order for this new seek 1326 // to be honored, we need to post one. 1327 1328 postVideoEvent_l(); 1329 } 1330 1331 mSeeking = SEEK; 1332 mSeekNotificationSent = false; 1333 mSeekTimeUs = timeUs; 1334 modifyFlags((AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS), CLEAR); 1335 1336 seekAudioIfNecessary_l(); 1337 1338 if (mFlags & TEXTPLAYER_STARTED) { 1339 mTextPlayer->seekTo(mSeekTimeUs); 1340 } 1341 1342 if (!(mFlags & PLAYING)) { 1343 LOGV("seeking while paused, sending SEEK_COMPLETE notification" 1344 " immediately."); 1345 1346 notifyListener_l(MEDIA_SEEK_COMPLETE); 1347 mSeekNotificationSent = true; 1348 1349 if ((mFlags & PREPARED) && mVideoSource != NULL) { 1350 modifyFlags(SEEK_PREVIEW, SET); 1351 postVideoEvent_l(); 1352 } 1353 } 1354 1355 return OK; 1356} 1357 1358void AwesomePlayer::seekAudioIfNecessary_l() { 1359 if (mSeeking != NO_SEEK && mVideoSource == NULL && mAudioPlayer != NULL) { 1360 mAudioPlayer->seekTo(mSeekTimeUs); 1361 1362 mWatchForAudioSeekComplete = true; 1363 mWatchForAudioEOS = true; 1364 1365 if (mDecryptHandle != NULL) { 1366 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, 1367 Playback::PAUSE, 0); 1368 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, 1369 Playback::START, mSeekTimeUs / 1000); 1370 } 1371 } 1372} 1373 1374void AwesomePlayer::setAudioSource(sp<MediaSource> source) { 1375 CHECK(source != NULL); 1376 1377 mAudioTrack = source; 1378} 1379 1380void AwesomePlayer::addTextSource(sp<MediaSource> source) { 1381 Mutex::Autolock autoLock(mTimedTextLock); 1382 CHECK(source != NULL); 1383 1384 if (mTextPlayer == NULL) { 1385 mTextPlayer = new TimedTextPlayer(this, mListener, &mQueue); 1386 } 1387 1388 mTextPlayer->addTextSource(source); 1389} 1390 1391status_t AwesomePlayer::initAudioDecoder() { 1392 sp<MetaData> meta = mAudioTrack->getFormat(); 1393 1394 const char *mime; 1395 CHECK(meta->findCString(kKeyMIMEType, &mime)); 1396 1397 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) { 1398 mAudioSource = mAudioTrack; 1399 } else { 1400 mAudioSource = OMXCodec::Create( 1401 mClient.interface(), mAudioTrack->getFormat(), 1402 false, // createEncoder 1403 mAudioTrack); 1404 } 1405 1406 if (mAudioSource != NULL) { 1407 int64_t durationUs; 1408 if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) { 1409 Mutex::Autolock autoLock(mMiscStateLock); 1410 if (mDurationUs < 0 || durationUs > mDurationUs) { 1411 mDurationUs = durationUs; 1412 } 1413 } 1414 1415 status_t err = mAudioSource->start(); 1416 1417 if (err != OK) { 1418 mAudioSource.clear(); 1419 return err; 1420 } 1421 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_QCELP)) { 1422 // For legacy reasons we're simply going to ignore the absence 1423 // of an audio decoder for QCELP instead of aborting playback 1424 // altogether. 1425 return OK; 1426 } 1427 1428 if (mAudioSource != NULL) { 1429 Mutex::Autolock autoLock(mStatsLock); 1430 TrackStat *stat = &mStats.mTracks.editItemAt(mStats.mAudioTrackIndex); 1431 1432 const char *component; 1433 if (!mAudioSource->getFormat() 1434 ->findCString(kKeyDecoderComponent, &component)) { 1435 component = "none"; 1436 } 1437 1438 stat->mDecoderName = component; 1439 } 1440 1441 return mAudioSource != NULL ? OK : UNKNOWN_ERROR; 1442} 1443 1444void AwesomePlayer::setVideoSource(sp<MediaSource> source) { 1445 CHECK(source != NULL); 1446 1447 mVideoTrack = source; 1448} 1449 1450status_t AwesomePlayer::initVideoDecoder(uint32_t flags) { 1451 1452 // Either the application or the DRM system can independently say 1453 // that there must be a hardware-protected path to an external video sink. 1454 // For now we always require a hardware-protected path to external video sink 1455 // if content is DRMed, but eventually this could be optional per DRM agent. 1456 // When the application wants protection, then 1457 // (USE_SURFACE_ALLOC && (mSurface != 0) && 1458 // (mSurface->getFlags() & ISurfaceComposer::eProtectedByApp)) 1459 // will be true, but that part is already handled by SurfaceFlinger. 1460 1461#ifdef DEBUG_HDCP 1462 // For debugging, we allow a system property to control the protected usage. 1463 // In case of uninitialized or unexpected property, we default to "DRM only". 1464 bool setProtectionBit = false; 1465 char value[PROPERTY_VALUE_MAX]; 1466 if (property_get("persist.sys.hdcp_checking", value, NULL)) { 1467 if (!strcmp(value, "never")) { 1468 // nop 1469 } else if (!strcmp(value, "always")) { 1470 setProtectionBit = true; 1471 } else if (!strcmp(value, "drm-only")) { 1472 if (mDecryptHandle != NULL) { 1473 setProtectionBit = true; 1474 } 1475 // property value is empty, or unexpected value 1476 } else { 1477 if (mDecryptHandle != NULL) { 1478 setProtectionBit = true; 1479 } 1480 } 1481 // can' read property value 1482 } else { 1483 if (mDecryptHandle != NULL) { 1484 setProtectionBit = true; 1485 } 1486 } 1487 // note that usage bit is already cleared, so no need to clear it in the "else" case 1488 if (setProtectionBit) { 1489 flags |= OMXCodec::kEnableGrallocUsageProtected; 1490 } 1491#else 1492 if (mDecryptHandle != NULL) { 1493 flags |= OMXCodec::kEnableGrallocUsageProtected; 1494 } 1495#endif 1496 LOGV("initVideoDecoder flags=0x%x", flags); 1497 mVideoSource = OMXCodec::Create( 1498 mClient.interface(), mVideoTrack->getFormat(), 1499 false, // createEncoder 1500 mVideoTrack, 1501 NULL, flags, USE_SURFACE_ALLOC ? mNativeWindow : NULL); 1502 1503 if (mVideoSource != NULL) { 1504 int64_t durationUs; 1505 if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) { 1506 Mutex::Autolock autoLock(mMiscStateLock); 1507 if (mDurationUs < 0 || durationUs > mDurationUs) { 1508 mDurationUs = durationUs; 1509 } 1510 } 1511 1512 status_t err = mVideoSource->start(); 1513 1514 if (err != OK) { 1515 mVideoSource.clear(); 1516 return err; 1517 } 1518 } 1519 1520 if (mVideoSource != NULL) { 1521 Mutex::Autolock autoLock(mStatsLock); 1522 TrackStat *stat = &mStats.mTracks.editItemAt(mStats.mVideoTrackIndex); 1523 1524 const char *component; 1525 CHECK(mVideoSource->getFormat() 1526 ->findCString(kKeyDecoderComponent, &component)); 1527 1528 stat->mDecoderName = component; 1529 } 1530 1531 return mVideoSource != NULL ? OK : UNKNOWN_ERROR; 1532} 1533 1534void AwesomePlayer::finishSeekIfNecessary(int64_t videoTimeUs) { 1535 if (mSeeking == SEEK_VIDEO_ONLY) { 1536 mSeeking = NO_SEEK; 1537 return; 1538 } 1539 1540 if (mSeeking == NO_SEEK || (mFlags & SEEK_PREVIEW)) { 1541 return; 1542 } 1543 1544 if (mAudioPlayer != NULL) { 1545 LOGV("seeking audio to %lld us (%.2f secs).", videoTimeUs, videoTimeUs / 1E6); 1546 1547 // If we don't have a video time, seek audio to the originally 1548 // requested seek time instead. 1549 1550 mAudioPlayer->seekTo(videoTimeUs < 0 ? mSeekTimeUs : videoTimeUs); 1551 mWatchForAudioSeekComplete = true; 1552 mWatchForAudioEOS = true; 1553 } else if (!mSeekNotificationSent) { 1554 // If we're playing video only, report seek complete now, 1555 // otherwise audio player will notify us later. 1556 notifyListener_l(MEDIA_SEEK_COMPLETE); 1557 mSeekNotificationSent = true; 1558 } 1559 1560 modifyFlags(FIRST_FRAME, SET); 1561 mSeeking = NO_SEEK; 1562 1563 if (mDecryptHandle != NULL) { 1564 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, 1565 Playback::PAUSE, 0); 1566 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, 1567 Playback::START, videoTimeUs / 1000); 1568 } 1569} 1570 1571void AwesomePlayer::onVideoEvent() { 1572 Mutex::Autolock autoLock(mLock); 1573 if (!mVideoEventPending) { 1574 // The event has been cancelled in reset_l() but had already 1575 // been scheduled for execution at that time. 1576 return; 1577 } 1578 mVideoEventPending = false; 1579 1580 if (mSeeking != NO_SEEK) { 1581 if (mVideoBuffer) { 1582 mVideoBuffer->release(); 1583 mVideoBuffer = NULL; 1584 } 1585 1586 if (mSeeking == SEEK && isStreamingHTTP() && mAudioSource != NULL 1587 && !(mFlags & SEEK_PREVIEW)) { 1588 // We're going to seek the video source first, followed by 1589 // the audio source. 1590 // In order to avoid jumps in the DataSource offset caused by 1591 // the audio codec prefetching data from the old locations 1592 // while the video codec is already reading data from the new 1593 // locations, we'll "pause" the audio source, causing it to 1594 // stop reading input data until a subsequent seek. 1595 1596 if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) { 1597 mAudioPlayer->pause(); 1598 1599 modifyFlags(AUDIO_RUNNING, CLEAR); 1600 } 1601 mAudioSource->pause(); 1602 } 1603 } 1604 1605 if (!mVideoBuffer) { 1606 MediaSource::ReadOptions options; 1607 if (mSeeking != NO_SEEK) { 1608 LOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs, mSeekTimeUs / 1E6); 1609 1610 options.setSeekTo( 1611 mSeekTimeUs, 1612 mSeeking == SEEK_VIDEO_ONLY 1613 ? MediaSource::ReadOptions::SEEK_NEXT_SYNC 1614 : MediaSource::ReadOptions::SEEK_CLOSEST_SYNC); 1615 } 1616 for (;;) { 1617 status_t err = mVideoSource->read(&mVideoBuffer, &options); 1618 options.clearSeekTo(); 1619 1620 if (err != OK) { 1621 CHECK(mVideoBuffer == NULL); 1622 1623 if (err == INFO_FORMAT_CHANGED) { 1624 LOGV("VideoSource signalled format change."); 1625 1626 notifyVideoSize_l(); 1627 1628 if (mVideoRenderer != NULL) { 1629 mVideoRendererIsPreview = false; 1630 initRenderer_l(); 1631 } 1632 continue; 1633 } 1634 1635 // So video playback is complete, but we may still have 1636 // a seek request pending that needs to be applied 1637 // to the audio track. 1638 if (mSeeking != NO_SEEK) { 1639 LOGV("video stream ended while seeking!"); 1640 } 1641 finishSeekIfNecessary(-1); 1642 1643 if (mAudioPlayer != NULL 1644 && !(mFlags & (AUDIO_RUNNING | SEEK_PREVIEW))) { 1645 startAudioPlayer_l(); 1646 } 1647 1648 modifyFlags(VIDEO_AT_EOS, SET); 1649 postStreamDoneEvent_l(err); 1650 return; 1651 } 1652 1653 if (mVideoBuffer->range_length() == 0) { 1654 // Some decoders, notably the PV AVC software decoder 1655 // return spurious empty buffers that we just want to ignore. 1656 1657 mVideoBuffer->release(); 1658 mVideoBuffer = NULL; 1659 continue; 1660 } 1661 1662 break; 1663 } 1664 1665 { 1666 Mutex::Autolock autoLock(mStatsLock); 1667 ++mStats.mNumVideoFramesDecoded; 1668 } 1669 } 1670 1671 int64_t timeUs; 1672 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs)); 1673 1674 mLastVideoTimeUs = timeUs; 1675 1676 if (mSeeking == SEEK_VIDEO_ONLY) { 1677 if (mSeekTimeUs > timeUs) { 1678 LOGI("XXX mSeekTimeUs = %lld us, timeUs = %lld us", 1679 mSeekTimeUs, timeUs); 1680 } 1681 } 1682 1683 { 1684 Mutex::Autolock autoLock(mMiscStateLock); 1685 mVideoTimeUs = timeUs; 1686 } 1687 1688 SeekType wasSeeking = mSeeking; 1689 finishSeekIfNecessary(timeUs); 1690 1691 if (mAudioPlayer != NULL && !(mFlags & (AUDIO_RUNNING | SEEK_PREVIEW))) { 1692 status_t err = startAudioPlayer_l(); 1693 if (err != OK) { 1694 LOGE("Starting the audio player failed w/ err %d", err); 1695 return; 1696 } 1697 } 1698 1699 if ((mFlags & TEXTPLAYER_STARTED) && !(mFlags & (TEXT_RUNNING | SEEK_PREVIEW))) { 1700 mTextPlayer->resume(); 1701 modifyFlags(TEXT_RUNNING, SET); 1702 } 1703 1704 TimeSource *ts = (mFlags & AUDIO_AT_EOS) ? &mSystemTimeSource : mTimeSource; 1705 1706 if (mFlags & FIRST_FRAME) { 1707 modifyFlags(FIRST_FRAME, CLEAR); 1708 mTimeSourceDeltaUs = ts->getRealTimeUs() - timeUs; 1709 } 1710 1711 int64_t realTimeUs, mediaTimeUs; 1712 if (!(mFlags & AUDIO_AT_EOS) && mAudioPlayer != NULL 1713 && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) { 1714 mTimeSourceDeltaUs = realTimeUs - mediaTimeUs; 1715 } 1716 1717 if (wasSeeking == SEEK_VIDEO_ONLY) { 1718 int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs; 1719 1720 int64_t latenessUs = nowUs - timeUs; 1721 1722 if (latenessUs > 0) { 1723 LOGI("after SEEK_VIDEO_ONLY we're late by %.2f secs", latenessUs / 1E6); 1724 } 1725 } 1726 1727 if (wasSeeking == NO_SEEK) { 1728 // Let's display the first frame after seeking right away. 1729 1730 int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs; 1731 1732 int64_t latenessUs = nowUs - timeUs; 1733 1734 if (latenessUs > 500000ll 1735 && mRTSPController == NULL 1736 && mAudioPlayer != NULL 1737 && mAudioPlayer->getMediaTimeMapping( 1738 &realTimeUs, &mediaTimeUs)) { 1739 LOGI("we're much too late (%.2f secs), video skipping ahead", 1740 latenessUs / 1E6); 1741 1742 mVideoBuffer->release(); 1743 mVideoBuffer = NULL; 1744 1745 mSeeking = SEEK_VIDEO_ONLY; 1746 mSeekTimeUs = mediaTimeUs; 1747 1748 postVideoEvent_l(); 1749 return; 1750 } 1751 1752 if (latenessUs > 40000) { 1753 // We're more than 40ms late. 1754 LOGV("we're late by %lld us (%.2f secs), dropping frame", 1755 latenessUs, latenessUs / 1E6); 1756 mVideoBuffer->release(); 1757 mVideoBuffer = NULL; 1758 1759 { 1760 Mutex::Autolock autoLock(mStatsLock); 1761 ++mStats.mNumVideoFramesDropped; 1762 } 1763 1764 postVideoEvent_l(); 1765 return; 1766 } 1767 1768 if (latenessUs < -10000) { 1769 // We're more than 10ms early. 1770 1771 postVideoEvent_l(10000); 1772 return; 1773 } 1774 } 1775 1776 if ((mNativeWindow != NULL) 1777 && (mVideoRendererIsPreview || mVideoRenderer == NULL)) { 1778 mVideoRendererIsPreview = false; 1779 1780 initRenderer_l(); 1781 } 1782 1783 if (mVideoRenderer != NULL) { 1784 mVideoRenderer->render(mVideoBuffer); 1785 } 1786 1787 mVideoBuffer->release(); 1788 mVideoBuffer = NULL; 1789 1790 if (wasSeeking != NO_SEEK && (mFlags & SEEK_PREVIEW)) { 1791 modifyFlags(SEEK_PREVIEW, CLEAR); 1792 return; 1793 } 1794 1795 postVideoEvent_l(); 1796} 1797 1798void AwesomePlayer::postVideoEvent_l(int64_t delayUs) { 1799 if (mVideoEventPending) { 1800 return; 1801 } 1802 1803 mVideoEventPending = true; 1804 mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs); 1805} 1806 1807void AwesomePlayer::postStreamDoneEvent_l(status_t status) { 1808 if (mStreamDoneEventPending) { 1809 return; 1810 } 1811 mStreamDoneEventPending = true; 1812 1813 mStreamDoneStatus = status; 1814 mQueue.postEvent(mStreamDoneEvent); 1815} 1816 1817void AwesomePlayer::postBufferingEvent_l() { 1818 if (mBufferingEventPending) { 1819 return; 1820 } 1821 mBufferingEventPending = true; 1822 mQueue.postEventWithDelay(mBufferingEvent, 1000000ll); 1823} 1824 1825void AwesomePlayer::postVideoLagEvent_l() { 1826 if (mVideoLagEventPending) { 1827 return; 1828 } 1829 mVideoLagEventPending = true; 1830 mQueue.postEventWithDelay(mVideoLagEvent, 1000000ll); 1831} 1832 1833void AwesomePlayer::postCheckAudioStatusEvent_l(int64_t delayUs) { 1834 if (mAudioStatusEventPending) { 1835 return; 1836 } 1837 mAudioStatusEventPending = true; 1838 mQueue.postEventWithDelay(mCheckAudioStatusEvent, delayUs); 1839} 1840 1841void AwesomePlayer::onCheckAudioStatus() { 1842 Mutex::Autolock autoLock(mLock); 1843 if (!mAudioStatusEventPending) { 1844 // Event was dispatched and while we were blocking on the mutex, 1845 // has already been cancelled. 1846 return; 1847 } 1848 1849 mAudioStatusEventPending = false; 1850 1851 if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) { 1852 mWatchForAudioSeekComplete = false; 1853 1854 if (!mSeekNotificationSent) { 1855 notifyListener_l(MEDIA_SEEK_COMPLETE); 1856 mSeekNotificationSent = true; 1857 } 1858 1859 mSeeking = NO_SEEK; 1860 } 1861 1862 status_t finalStatus; 1863 if (mWatchForAudioEOS && mAudioPlayer->reachedEOS(&finalStatus)) { 1864 mWatchForAudioEOS = false; 1865 modifyFlags(AUDIO_AT_EOS, SET); 1866 modifyFlags(FIRST_FRAME, SET); 1867 postStreamDoneEvent_l(finalStatus); 1868 } 1869} 1870 1871status_t AwesomePlayer::prepare() { 1872 Mutex::Autolock autoLock(mLock); 1873 return prepare_l(); 1874} 1875 1876status_t AwesomePlayer::prepare_l() { 1877 if (mFlags & PREPARED) { 1878 return OK; 1879 } 1880 1881 if (mFlags & PREPARING) { 1882 return UNKNOWN_ERROR; 1883 } 1884 1885 mIsAsyncPrepare = false; 1886 status_t err = prepareAsync_l(); 1887 1888 if (err != OK) { 1889 return err; 1890 } 1891 1892 while (mFlags & PREPARING) { 1893 mPreparedCondition.wait(mLock); 1894 } 1895 1896 return mPrepareResult; 1897} 1898 1899status_t AwesomePlayer::prepareAsync() { 1900 Mutex::Autolock autoLock(mLock); 1901 1902 if (mFlags & PREPARING) { 1903 return UNKNOWN_ERROR; // async prepare already pending 1904 } 1905 1906 mIsAsyncPrepare = true; 1907 return prepareAsync_l(); 1908} 1909 1910status_t AwesomePlayer::prepareAsync_l() { 1911 if (mFlags & PREPARING) { 1912 return UNKNOWN_ERROR; // async prepare already pending 1913 } 1914 1915 if (!mQueueStarted) { 1916 mQueue.start(); 1917 mQueueStarted = true; 1918 } 1919 1920 modifyFlags(PREPARING, SET); 1921 mAsyncPrepareEvent = new AwesomeEvent( 1922 this, &AwesomePlayer::onPrepareAsyncEvent); 1923 1924 mQueue.postEvent(mAsyncPrepareEvent); 1925 1926 return OK; 1927} 1928 1929status_t AwesomePlayer::finishSetDataSource_l() { 1930 sp<DataSource> dataSource; 1931 1932 bool isWidevineStreaming = false; 1933 if (!strncasecmp("widevine://", mUri.string(), 11)) { 1934 isWidevineStreaming = true; 1935 1936 String8 newURI = String8("http://"); 1937 newURI.append(mUri.string() + 11); 1938 1939 mUri = newURI; 1940 } 1941 1942 if (!strncasecmp("http://", mUri.string(), 7) 1943 || !strncasecmp("https://", mUri.string(), 8) 1944 || isWidevineStreaming) { 1945 mConnectingDataSource = HTTPBase::Create( 1946 (mFlags & INCOGNITO) 1947 ? HTTPBase::kFlagIncognito 1948 : 0); 1949 1950 if (mUIDValid) { 1951 mConnectingDataSource->setUID(mUID); 1952 } 1953 1954 mLock.unlock(); 1955 status_t err = mConnectingDataSource->connect(mUri, &mUriHeaders); 1956 mLock.lock(); 1957 1958 if (err != OK) { 1959 mConnectingDataSource.clear(); 1960 1961 LOGI("mConnectingDataSource->connect() returned %d", err); 1962 return err; 1963 } 1964 1965 if (!isWidevineStreaming) { 1966 // The widevine extractor does its own caching. 1967 1968#if 0 1969 mCachedSource = new NuCachedSource2( 1970 new ThrottledSource( 1971 mConnectingDataSource, 50 * 1024 /* bytes/sec */)); 1972#else 1973 mCachedSource = new NuCachedSource2(mConnectingDataSource); 1974#endif 1975 1976 dataSource = mCachedSource; 1977 } else { 1978 dataSource = mConnectingDataSource; 1979 } 1980 1981 mConnectingDataSource.clear(); 1982 1983 1984 String8 contentType = dataSource->getMIMEType(); 1985 1986 if (strncasecmp(contentType.string(), "audio/", 6)) { 1987 // We're not doing this for streams that appear to be audio-only 1988 // streams to ensure that even low bandwidth streams start 1989 // playing back fairly instantly. 1990 1991 // We're going to prefill the cache before trying to instantiate 1992 // the extractor below, as the latter is an operation that otherwise 1993 // could block on the datasource for a significant amount of time. 1994 // During that time we'd be unable to abort the preparation phase 1995 // without this prefill. 1996 if (mCachedSource != NULL) { 1997 // We're going to prefill the cache before trying to instantiate 1998 // the extractor below, as the latter is an operation that otherwise 1999 // could block on the datasource for a significant amount of time. 2000 // During that time we'd be unable to abort the preparation phase 2001 // without this prefill. 2002 2003 mLock.unlock(); 2004 2005 for (;;) { 2006 status_t finalStatus; 2007 size_t cachedDataRemaining = 2008 mCachedSource->approxDataRemaining(&finalStatus); 2009 2010 if (finalStatus != OK || cachedDataRemaining >= kHighWaterMarkBytes 2011 || (mFlags & PREPARE_CANCELLED)) { 2012 break; 2013 } 2014 2015 usleep(200000); 2016 } 2017 2018 mLock.lock(); 2019 } 2020 2021 if (mFlags & PREPARE_CANCELLED) { 2022 LOGI("Prepare cancelled while waiting for initial cache fill."); 2023 return UNKNOWN_ERROR; 2024 } 2025 } 2026 } else if (!strncasecmp("rtsp://", mUri.string(), 7)) { 2027 if (mLooper == NULL) { 2028 mLooper = new ALooper; 2029 mLooper->setName("rtsp"); 2030 mLooper->start(); 2031 } 2032 mRTSPController = new ARTSPController(mLooper); 2033 mConnectingRTSPController = mRTSPController; 2034 2035 if (mUIDValid) { 2036 mConnectingRTSPController->setUID(mUID); 2037 } 2038 2039 mLock.unlock(); 2040 status_t err = mRTSPController->connect(mUri.string()); 2041 mLock.lock(); 2042 2043 mConnectingRTSPController.clear(); 2044 2045 LOGI("ARTSPController::connect returned %d", err); 2046 2047 if (err != OK) { 2048 mRTSPController.clear(); 2049 return err; 2050 } 2051 2052 sp<MediaExtractor> extractor = mRTSPController.get(); 2053 return setDataSource_l(extractor); 2054 } else { 2055 dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders); 2056 } 2057 2058 if (dataSource == NULL) { 2059 return UNKNOWN_ERROR; 2060 } 2061 2062 sp<MediaExtractor> extractor; 2063 2064 if (isWidevineStreaming) { 2065 String8 mimeType; 2066 float confidence; 2067 sp<AMessage> dummy; 2068 bool success = SniffDRM(dataSource, &mimeType, &confidence, &dummy); 2069 2070 if (!success 2071 || strcasecmp( 2072 mimeType.string(), MEDIA_MIMETYPE_CONTAINER_WVM)) { 2073 return ERROR_UNSUPPORTED; 2074 } 2075 2076 mWVMExtractor = new WVMExtractor(dataSource); 2077 mWVMExtractor->setAdaptiveStreamingMode(true); 2078 extractor = mWVMExtractor; 2079 } else { 2080 extractor = MediaExtractor::Create(dataSource); 2081 2082 if (extractor == NULL) { 2083 return UNKNOWN_ERROR; 2084 } 2085 } 2086 2087 dataSource->getDrmInfo(mDecryptHandle, &mDrmManagerClient); 2088 2089 if (mDecryptHandle != NULL) { 2090 CHECK(mDrmManagerClient); 2091 if (RightsStatus::RIGHTS_VALID != mDecryptHandle->status) { 2092 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_DRM_NO_LICENSE); 2093 } 2094 } 2095 2096 status_t err = setDataSource_l(extractor); 2097 2098 if (err != OK) { 2099 mWVMExtractor.clear(); 2100 2101 return err; 2102 } 2103 2104 return OK; 2105} 2106 2107void AwesomePlayer::abortPrepare(status_t err) { 2108 CHECK(err != OK); 2109 2110 if (mIsAsyncPrepare) { 2111 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err); 2112 } 2113 2114 mPrepareResult = err; 2115 modifyFlags((PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED), CLEAR); 2116 mAsyncPrepareEvent = NULL; 2117 mPreparedCondition.broadcast(); 2118} 2119 2120// static 2121bool AwesomePlayer::ContinuePreparation(void *cookie) { 2122 AwesomePlayer *me = static_cast<AwesomePlayer *>(cookie); 2123 2124 return (me->mFlags & PREPARE_CANCELLED) == 0; 2125} 2126 2127void AwesomePlayer::onPrepareAsyncEvent() { 2128 Mutex::Autolock autoLock(mLock); 2129 2130 if (mFlags & PREPARE_CANCELLED) { 2131 LOGI("prepare was cancelled before doing anything"); 2132 abortPrepare(UNKNOWN_ERROR); 2133 return; 2134 } 2135 2136 if (mUri.size() > 0) { 2137 status_t err = finishSetDataSource_l(); 2138 2139 if (err != OK) { 2140 abortPrepare(err); 2141 return; 2142 } 2143 } 2144 2145 if (mVideoTrack != NULL && mVideoSource == NULL) { 2146 status_t err = initVideoDecoder(); 2147 2148 if (err != OK) { 2149 abortPrepare(err); 2150 return; 2151 } 2152 } 2153 2154 if (mAudioTrack != NULL && mAudioSource == NULL) { 2155 status_t err = initAudioDecoder(); 2156 2157 if (err != OK) { 2158 abortPrepare(err); 2159 return; 2160 } 2161 } 2162 2163 modifyFlags(PREPARING_CONNECTED, SET); 2164 2165 if (isStreamingHTTP() || mRTSPController != NULL) { 2166 postBufferingEvent_l(); 2167 } else { 2168 finishAsyncPrepare_l(); 2169 } 2170} 2171 2172void AwesomePlayer::finishAsyncPrepare_l() { 2173 if (mIsAsyncPrepare) { 2174 if (mVideoSource == NULL) { 2175 notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0); 2176 } else { 2177 notifyVideoSize_l(); 2178 } 2179 2180 notifyListener_l(MEDIA_PREPARED); 2181 } 2182 2183 mPrepareResult = OK; 2184 modifyFlags((PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED), CLEAR); 2185 modifyFlags(PREPARED, SET); 2186 mAsyncPrepareEvent = NULL; 2187 mPreparedCondition.broadcast(); 2188} 2189 2190uint32_t AwesomePlayer::flags() const { 2191 return mExtractorFlags; 2192} 2193 2194void AwesomePlayer::postAudioEOS(int64_t delayUs) { 2195 Mutex::Autolock autoLock(mLock); 2196 postCheckAudioStatusEvent_l(delayUs); 2197} 2198 2199void AwesomePlayer::postAudioSeekComplete() { 2200 Mutex::Autolock autoLock(mLock); 2201 postAudioSeekComplete_l(); 2202} 2203 2204void AwesomePlayer::postAudioSeekComplete_l() { 2205 postCheckAudioStatusEvent_l(0 /* delayUs */); 2206} 2207 2208status_t AwesomePlayer::setParameter(int key, const Parcel &request) { 2209 switch (key) { 2210 case KEY_PARAMETER_TIMED_TEXT_TRACK_INDEX: 2211 { 2212 Mutex::Autolock autoLock(mTimedTextLock); 2213 return setTimedTextTrackIndex(request.readInt32()); 2214 } 2215 case KEY_PARAMETER_TIMED_TEXT_ADD_OUT_OF_BAND_SOURCE: 2216 { 2217 Mutex::Autolock autoLock(mTimedTextLock); 2218 if (mTextPlayer == NULL) { 2219 mTextPlayer = new TimedTextPlayer(this, mListener, &mQueue); 2220 } 2221 2222 return mTextPlayer->setParameter(key, request); 2223 } 2224 case KEY_PARAMETER_CACHE_STAT_COLLECT_FREQ_MS: 2225 { 2226 return setCacheStatCollectFreq(request); 2227 } 2228 default: 2229 { 2230 return ERROR_UNSUPPORTED; 2231 } 2232 } 2233} 2234 2235status_t AwesomePlayer::setCacheStatCollectFreq(const Parcel &request) { 2236 if (mCachedSource != NULL) { 2237 int32_t freqMs = request.readInt32(); 2238 LOGD("Request to keep cache stats in the past %d ms", 2239 freqMs); 2240 return mCachedSource->setCacheStatCollectFreq(freqMs); 2241 } 2242 return ERROR_UNSUPPORTED; 2243} 2244 2245status_t AwesomePlayer::getParameter(int key, Parcel *reply) { 2246 switch (key) { 2247 case KEY_PARAMETER_AUDIO_CHANNEL_COUNT: 2248 { 2249 int32_t channelCount; 2250 if (mAudioTrack == 0 || 2251 !mAudioTrack->getFormat()->findInt32(kKeyChannelCount, &channelCount)) { 2252 channelCount = 0; 2253 } 2254 reply->writeInt32(channelCount); 2255 } 2256 return OK; 2257 default: 2258 { 2259 return ERROR_UNSUPPORTED; 2260 } 2261 } 2262} 2263 2264bool AwesomePlayer::isStreamingHTTP() const { 2265 return mCachedSource != NULL || mWVMExtractor != NULL; 2266} 2267 2268status_t AwesomePlayer::dump(int fd, const Vector<String16> &args) const { 2269 Mutex::Autolock autoLock(mStatsLock); 2270 2271 FILE *out = fdopen(dup(fd), "w"); 2272 2273 fprintf(out, " AwesomePlayer\n"); 2274 if (mStats.mFd < 0) { 2275 fprintf(out, " URI(%s)", mStats.mURI.string()); 2276 } else { 2277 fprintf(out, " fd(%d)", mStats.mFd); 2278 } 2279 2280 fprintf(out, ", flags(0x%08x)", mStats.mFlags); 2281 2282 if (mStats.mBitrate >= 0) { 2283 fprintf(out, ", bitrate(%lld bps)", mStats.mBitrate); 2284 } 2285 2286 fprintf(out, "\n"); 2287 2288 for (size_t i = 0; i < mStats.mTracks.size(); ++i) { 2289 const TrackStat &stat = mStats.mTracks.itemAt(i); 2290 2291 fprintf(out, " Track %d\n", i + 1); 2292 fprintf(out, " MIME(%s)", stat.mMIME.string()); 2293 2294 if (!stat.mDecoderName.isEmpty()) { 2295 fprintf(out, ", decoder(%s)", stat.mDecoderName.string()); 2296 } 2297 2298 fprintf(out, "\n"); 2299 2300 if ((ssize_t)i == mStats.mVideoTrackIndex) { 2301 fprintf(out, 2302 " videoDimensions(%d x %d), " 2303 "numVideoFramesDecoded(%lld), " 2304 "numVideoFramesDropped(%lld)\n", 2305 mStats.mVideoWidth, 2306 mStats.mVideoHeight, 2307 mStats.mNumVideoFramesDecoded, 2308 mStats.mNumVideoFramesDropped); 2309 } 2310 } 2311 2312 fclose(out); 2313 out = NULL; 2314 2315 return OK; 2316} 2317 2318void AwesomePlayer::modifyFlags(unsigned value, FlagMode mode) { 2319 switch (mode) { 2320 case SET: 2321 mFlags |= value; 2322 break; 2323 case CLEAR: 2324 mFlags &= ~value; 2325 break; 2326 case ASSIGN: 2327 mFlags = value; 2328 break; 2329 default: 2330 TRESPASS(); 2331 } 2332 2333 { 2334 Mutex::Autolock autoLock(mStatsLock); 2335 mStats.mFlags = mFlags; 2336 } 2337} 2338 2339} // namespace android 2340