AwesomePlayer.cpp revision af64a8a6ad89f52685e822dca30742a4132c9ae6
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 = true; 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 mSeekTimeUs = mLastVideoTimeUs; 1208 modifyFlags((AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS), CLEAR); 1209 } 1210 1211 if (wasPlaying) { 1212 play_l(); 1213 } 1214} 1215 1216void AwesomePlayer::setAudioSink( 1217 const sp<MediaPlayerBase::AudioSink> &audioSink) { 1218 Mutex::Autolock autoLock(mLock); 1219 1220 mAudioSink = audioSink; 1221} 1222 1223status_t AwesomePlayer::setLooping(bool shouldLoop) { 1224 Mutex::Autolock autoLock(mLock); 1225 1226 modifyFlags(LOOPING, CLEAR); 1227 1228 if (shouldLoop) { 1229 modifyFlags(LOOPING, SET); 1230 } 1231 1232 return OK; 1233} 1234 1235status_t AwesomePlayer::getDuration(int64_t *durationUs) { 1236 Mutex::Autolock autoLock(mMiscStateLock); 1237 1238 if (mDurationUs < 0) { 1239 return UNKNOWN_ERROR; 1240 } 1241 1242 *durationUs = mDurationUs; 1243 1244 return OK; 1245} 1246 1247status_t AwesomePlayer::getPosition(int64_t *positionUs) { 1248 if (mRTSPController != NULL) { 1249 *positionUs = mRTSPController->getNormalPlayTimeUs(); 1250 } 1251 else if (mSeeking != NO_SEEK) { 1252 *positionUs = mSeekTimeUs; 1253 } else if (mVideoSource != NULL 1254 && (mAudioPlayer == NULL || !(mFlags & VIDEO_AT_EOS))) { 1255 Mutex::Autolock autoLock(mMiscStateLock); 1256 *positionUs = mVideoTimeUs; 1257 } else if (mAudioPlayer != NULL) { 1258 *positionUs = mAudioPlayer->getMediaTimeUs(); 1259 } else { 1260 *positionUs = 0; 1261 } 1262 1263 return OK; 1264} 1265 1266status_t AwesomePlayer::seekTo(int64_t timeUs) { 1267 if (mExtractorFlags & MediaExtractor::CAN_SEEK) { 1268 Mutex::Autolock autoLock(mLock); 1269 return seekTo_l(timeUs); 1270 } 1271 1272 return OK; 1273} 1274 1275status_t AwesomePlayer::setTimedTextTrackIndex(int32_t index) { 1276 if (mTextPlayer != NULL) { 1277 if (index >= 0) { // to turn on a text track 1278 status_t err = mTextPlayer->setTimedTextTrackIndex(index); 1279 if (err != OK) { 1280 return err; 1281 } 1282 1283 modifyFlags(TEXT_RUNNING, SET); 1284 modifyFlags(TEXTPLAYER_STARTED, SET); 1285 return OK; 1286 } else { // to turn off the text track display 1287 if (mFlags & TEXT_RUNNING) { 1288 modifyFlags(TEXT_RUNNING, CLEAR); 1289 } 1290 if (mFlags & TEXTPLAYER_STARTED) { 1291 modifyFlags(TEXTPLAYER_STARTED, CLEAR); 1292 } 1293 1294 return mTextPlayer->setTimedTextTrackIndex(index); 1295 } 1296 } else { 1297 return INVALID_OPERATION; 1298 } 1299} 1300 1301// static 1302void AwesomePlayer::OnRTSPSeekDoneWrapper(void *cookie) { 1303 static_cast<AwesomePlayer *>(cookie)->onRTSPSeekDone(); 1304} 1305 1306void AwesomePlayer::onRTSPSeekDone() { 1307 if (!mSeekNotificationSent) { 1308 notifyListener_l(MEDIA_SEEK_COMPLETE); 1309 mSeekNotificationSent = true; 1310 } 1311} 1312 1313status_t AwesomePlayer::seekTo_l(int64_t timeUs) { 1314 if (mRTSPController != NULL) { 1315 mRTSPController->seekAsync(timeUs, OnRTSPSeekDoneWrapper, this); 1316 return OK; 1317 } 1318 1319 if (mFlags & CACHE_UNDERRUN) { 1320 modifyFlags(CACHE_UNDERRUN, CLEAR); 1321 play_l(); 1322 } 1323 1324 if ((mFlags & PLAYING) && mVideoSource != NULL && (mFlags & VIDEO_AT_EOS)) { 1325 // Video playback completed before, there's no pending 1326 // video event right now. In order for this new seek 1327 // to be honored, we need to post one. 1328 1329 postVideoEvent_l(); 1330 } 1331 1332 mSeeking = SEEK; 1333 mSeekNotificationSent = false; 1334 mSeekTimeUs = timeUs; 1335 modifyFlags((AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS), CLEAR); 1336 1337 seekAudioIfNecessary_l(); 1338 1339 if (mFlags & TEXTPLAYER_STARTED) { 1340 mTextPlayer->seekTo(mSeekTimeUs); 1341 } 1342 1343 if (!(mFlags & PLAYING)) { 1344 LOGV("seeking while paused, sending SEEK_COMPLETE notification" 1345 " immediately."); 1346 1347 notifyListener_l(MEDIA_SEEK_COMPLETE); 1348 mSeekNotificationSent = true; 1349 1350 if ((mFlags & PREPARED) && mVideoSource != NULL) { 1351 modifyFlags(SEEK_PREVIEW, SET); 1352 postVideoEvent_l(); 1353 } 1354 } 1355 1356 return OK; 1357} 1358 1359void AwesomePlayer::seekAudioIfNecessary_l() { 1360 if (mSeeking != NO_SEEK && mVideoSource == NULL && mAudioPlayer != NULL) { 1361 mAudioPlayer->seekTo(mSeekTimeUs); 1362 1363 mWatchForAudioSeekComplete = true; 1364 mWatchForAudioEOS = true; 1365 1366 if (mDecryptHandle != NULL) { 1367 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, 1368 Playback::PAUSE, 0); 1369 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, 1370 Playback::START, mSeekTimeUs / 1000); 1371 } 1372 } 1373} 1374 1375void AwesomePlayer::setAudioSource(sp<MediaSource> source) { 1376 CHECK(source != NULL); 1377 1378 mAudioTrack = source; 1379} 1380 1381void AwesomePlayer::addTextSource(sp<MediaSource> source) { 1382 Mutex::Autolock autoLock(mTimedTextLock); 1383 CHECK(source != NULL); 1384 1385 if (mTextPlayer == NULL) { 1386 mTextPlayer = new TimedTextPlayer(this, mListener, &mQueue); 1387 } 1388 1389 mTextPlayer->addTextSource(source); 1390} 1391 1392status_t AwesomePlayer::initAudioDecoder() { 1393 sp<MetaData> meta = mAudioTrack->getFormat(); 1394 1395 const char *mime; 1396 CHECK(meta->findCString(kKeyMIMEType, &mime)); 1397 1398 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) { 1399 mAudioSource = mAudioTrack; 1400 } else { 1401 mAudioSource = OMXCodec::Create( 1402 mClient.interface(), mAudioTrack->getFormat(), 1403 false, // createEncoder 1404 mAudioTrack); 1405 } 1406 1407 if (mAudioSource != NULL) { 1408 int64_t durationUs; 1409 if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) { 1410 Mutex::Autolock autoLock(mMiscStateLock); 1411 if (mDurationUs < 0 || durationUs > mDurationUs) { 1412 mDurationUs = durationUs; 1413 } 1414 } 1415 1416 status_t err = mAudioSource->start(); 1417 1418 if (err != OK) { 1419 mAudioSource.clear(); 1420 return err; 1421 } 1422 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_QCELP)) { 1423 // For legacy reasons we're simply going to ignore the absence 1424 // of an audio decoder for QCELP instead of aborting playback 1425 // altogether. 1426 return OK; 1427 } 1428 1429 if (mAudioSource != NULL) { 1430 Mutex::Autolock autoLock(mStatsLock); 1431 TrackStat *stat = &mStats.mTracks.editItemAt(mStats.mAudioTrackIndex); 1432 1433 const char *component; 1434 if (!mAudioSource->getFormat() 1435 ->findCString(kKeyDecoderComponent, &component)) { 1436 component = "none"; 1437 } 1438 1439 stat->mDecoderName = component; 1440 } 1441 1442 return mAudioSource != NULL ? OK : UNKNOWN_ERROR; 1443} 1444 1445void AwesomePlayer::setVideoSource(sp<MediaSource> source) { 1446 CHECK(source != NULL); 1447 1448 mVideoTrack = source; 1449} 1450 1451status_t AwesomePlayer::initVideoDecoder(uint32_t flags) { 1452 1453 // Either the application or the DRM system can independently say 1454 // that there must be a hardware-protected path to an external video sink. 1455 // For now we always require a hardware-protected path to external video sink 1456 // if content is DRMed, but eventually this could be optional per DRM agent. 1457 // When the application wants protection, then 1458 // (USE_SURFACE_ALLOC && (mSurface != 0) && 1459 // (mSurface->getFlags() & ISurfaceComposer::eProtectedByApp)) 1460 // will be true, but that part is already handled by SurfaceFlinger. 1461 1462#ifdef DEBUG_HDCP 1463 // For debugging, we allow a system property to control the protected usage. 1464 // In case of uninitialized or unexpected property, we default to "DRM only". 1465 bool setProtectionBit = false; 1466 char value[PROPERTY_VALUE_MAX]; 1467 if (property_get("persist.sys.hdcp_checking", value, NULL)) { 1468 if (!strcmp(value, "never")) { 1469 // nop 1470 } else if (!strcmp(value, "always")) { 1471 setProtectionBit = true; 1472 } else if (!strcmp(value, "drm-only")) { 1473 if (mDecryptHandle != NULL) { 1474 setProtectionBit = true; 1475 } 1476 // property value is empty, or unexpected value 1477 } else { 1478 if (mDecryptHandle != NULL) { 1479 setProtectionBit = true; 1480 } 1481 } 1482 // can' read property value 1483 } else { 1484 if (mDecryptHandle != NULL) { 1485 setProtectionBit = true; 1486 } 1487 } 1488 // note that usage bit is already cleared, so no need to clear it in the "else" case 1489 if (setProtectionBit) { 1490 flags |= OMXCodec::kEnableGrallocUsageProtected; 1491 } 1492#else 1493 if (mDecryptHandle != NULL) { 1494 flags |= OMXCodec::kEnableGrallocUsageProtected; 1495 } 1496#endif 1497 LOGV("initVideoDecoder flags=0x%x", flags); 1498 mVideoSource = OMXCodec::Create( 1499 mClient.interface(), mVideoTrack->getFormat(), 1500 false, // createEncoder 1501 mVideoTrack, 1502 NULL, flags, USE_SURFACE_ALLOC ? mNativeWindow : NULL); 1503 1504 if (mVideoSource != NULL) { 1505 int64_t durationUs; 1506 if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) { 1507 Mutex::Autolock autoLock(mMiscStateLock); 1508 if (mDurationUs < 0 || durationUs > mDurationUs) { 1509 mDurationUs = durationUs; 1510 } 1511 } 1512 1513 status_t err = mVideoSource->start(); 1514 1515 if (err != OK) { 1516 mVideoSource.clear(); 1517 return err; 1518 } 1519 } 1520 1521 if (mVideoSource != NULL) { 1522 Mutex::Autolock autoLock(mStatsLock); 1523 TrackStat *stat = &mStats.mTracks.editItemAt(mStats.mVideoTrackIndex); 1524 1525 const char *component; 1526 CHECK(mVideoSource->getFormat() 1527 ->findCString(kKeyDecoderComponent, &component)); 1528 1529 stat->mDecoderName = component; 1530 } 1531 1532 return mVideoSource != NULL ? OK : UNKNOWN_ERROR; 1533} 1534 1535void AwesomePlayer::finishSeekIfNecessary(int64_t videoTimeUs) { 1536 if (mSeeking == SEEK_VIDEO_ONLY) { 1537 mSeeking = NO_SEEK; 1538 return; 1539 } 1540 1541 if (mSeeking == NO_SEEK || (mFlags & SEEK_PREVIEW)) { 1542 return; 1543 } 1544 1545 if (mAudioPlayer != NULL) { 1546 LOGV("seeking audio to %lld us (%.2f secs).", videoTimeUs, videoTimeUs / 1E6); 1547 1548 // If we don't have a video time, seek audio to the originally 1549 // requested seek time instead. 1550 1551 mAudioPlayer->seekTo(videoTimeUs < 0 ? mSeekTimeUs : videoTimeUs); 1552 mWatchForAudioSeekComplete = true; 1553 mWatchForAudioEOS = true; 1554 } else if (!mSeekNotificationSent) { 1555 // If we're playing video only, report seek complete now, 1556 // otherwise audio player will notify us later. 1557 notifyListener_l(MEDIA_SEEK_COMPLETE); 1558 mSeekNotificationSent = true; 1559 } 1560 1561 modifyFlags(FIRST_FRAME, SET); 1562 mSeeking = NO_SEEK; 1563 1564 if (mDecryptHandle != NULL) { 1565 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, 1566 Playback::PAUSE, 0); 1567 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, 1568 Playback::START, videoTimeUs / 1000); 1569 } 1570} 1571 1572void AwesomePlayer::onVideoEvent() { 1573 Mutex::Autolock autoLock(mLock); 1574 if (!mVideoEventPending) { 1575 // The event has been cancelled in reset_l() but had already 1576 // been scheduled for execution at that time. 1577 return; 1578 } 1579 mVideoEventPending = false; 1580 1581 if (mSeeking != NO_SEEK) { 1582 if (mVideoBuffer) { 1583 mVideoBuffer->release(); 1584 mVideoBuffer = NULL; 1585 } 1586 1587 if (mSeeking == SEEK && isStreamingHTTP() && mAudioSource != NULL 1588 && !(mFlags & SEEK_PREVIEW)) { 1589 // We're going to seek the video source first, followed by 1590 // the audio source. 1591 // In order to avoid jumps in the DataSource offset caused by 1592 // the audio codec prefetching data from the old locations 1593 // while the video codec is already reading data from the new 1594 // locations, we'll "pause" the audio source, causing it to 1595 // stop reading input data until a subsequent seek. 1596 1597 if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) { 1598 mAudioPlayer->pause(); 1599 1600 modifyFlags(AUDIO_RUNNING, CLEAR); 1601 } 1602 mAudioSource->pause(); 1603 } 1604 } 1605 1606 if (!mVideoBuffer) { 1607 MediaSource::ReadOptions options; 1608 if (mSeeking != NO_SEEK) { 1609 LOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs, mSeekTimeUs / 1E6); 1610 1611 options.setSeekTo( 1612 mSeekTimeUs, 1613 mSeeking == SEEK_VIDEO_ONLY 1614 ? MediaSource::ReadOptions::SEEK_NEXT_SYNC 1615 : MediaSource::ReadOptions::SEEK_CLOSEST_SYNC); 1616 } 1617 for (;;) { 1618 status_t err = mVideoSource->read(&mVideoBuffer, &options); 1619 options.clearSeekTo(); 1620 1621 if (err != OK) { 1622 CHECK(mVideoBuffer == NULL); 1623 1624 if (err == INFO_FORMAT_CHANGED) { 1625 LOGV("VideoSource signalled format change."); 1626 1627 notifyVideoSize_l(); 1628 1629 if (mVideoRenderer != NULL) { 1630 mVideoRendererIsPreview = false; 1631 initRenderer_l(); 1632 } 1633 continue; 1634 } 1635 1636 // So video playback is complete, but we may still have 1637 // a seek request pending that needs to be applied 1638 // to the audio track. 1639 if (mSeeking != NO_SEEK) { 1640 LOGV("video stream ended while seeking!"); 1641 } 1642 finishSeekIfNecessary(-1); 1643 1644 if (mAudioPlayer != NULL 1645 && !(mFlags & (AUDIO_RUNNING | SEEK_PREVIEW))) { 1646 startAudioPlayer_l(); 1647 } 1648 1649 modifyFlags(VIDEO_AT_EOS, SET); 1650 postStreamDoneEvent_l(err); 1651 return; 1652 } 1653 1654 if (mVideoBuffer->range_length() == 0) { 1655 // Some decoders, notably the PV AVC software decoder 1656 // return spurious empty buffers that we just want to ignore. 1657 1658 mVideoBuffer->release(); 1659 mVideoBuffer = NULL; 1660 continue; 1661 } 1662 1663 break; 1664 } 1665 1666 { 1667 Mutex::Autolock autoLock(mStatsLock); 1668 ++mStats.mNumVideoFramesDecoded; 1669 } 1670 } 1671 1672 int64_t timeUs; 1673 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs)); 1674 1675 mLastVideoTimeUs = timeUs; 1676 1677 if (mSeeking == SEEK_VIDEO_ONLY) { 1678 if (mSeekTimeUs > timeUs) { 1679 LOGI("XXX mSeekTimeUs = %lld us, timeUs = %lld us", 1680 mSeekTimeUs, timeUs); 1681 } 1682 } 1683 1684 { 1685 Mutex::Autolock autoLock(mMiscStateLock); 1686 mVideoTimeUs = timeUs; 1687 } 1688 1689 SeekType wasSeeking = mSeeking; 1690 finishSeekIfNecessary(timeUs); 1691 1692 if (mAudioPlayer != NULL && !(mFlags & (AUDIO_RUNNING | SEEK_PREVIEW))) { 1693 status_t err = startAudioPlayer_l(); 1694 if (err != OK) { 1695 LOGE("Starting the audio player failed w/ err %d", err); 1696 return; 1697 } 1698 } 1699 1700 if ((mFlags & TEXTPLAYER_STARTED) && !(mFlags & (TEXT_RUNNING | SEEK_PREVIEW))) { 1701 mTextPlayer->resume(); 1702 modifyFlags(TEXT_RUNNING, SET); 1703 } 1704 1705 TimeSource *ts = (mFlags & AUDIO_AT_EOS) ? &mSystemTimeSource : mTimeSource; 1706 1707 if (mFlags & FIRST_FRAME) { 1708 modifyFlags(FIRST_FRAME, CLEAR); 1709 mTimeSourceDeltaUs = ts->getRealTimeUs() - timeUs; 1710 } 1711 1712 int64_t realTimeUs, mediaTimeUs; 1713 if (!(mFlags & AUDIO_AT_EOS) && mAudioPlayer != NULL 1714 && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) { 1715 mTimeSourceDeltaUs = realTimeUs - mediaTimeUs; 1716 } 1717 1718 if (wasSeeking == SEEK_VIDEO_ONLY) { 1719 int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs; 1720 1721 int64_t latenessUs = nowUs - timeUs; 1722 1723 if (latenessUs > 0) { 1724 LOGI("after SEEK_VIDEO_ONLY we're late by %.2f secs", latenessUs / 1E6); 1725 } 1726 } 1727 1728 if (wasSeeking == NO_SEEK) { 1729 // Let's display the first frame after seeking right away. 1730 1731 int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs; 1732 1733 int64_t latenessUs = nowUs - timeUs; 1734 1735 if (latenessUs > 500000ll 1736 && mRTSPController == NULL 1737 && mAudioPlayer != NULL 1738 && mAudioPlayer->getMediaTimeMapping( 1739 &realTimeUs, &mediaTimeUs)) { 1740 LOGI("we're much too late (%.2f secs), video skipping ahead", 1741 latenessUs / 1E6); 1742 1743 mVideoBuffer->release(); 1744 mVideoBuffer = NULL; 1745 1746 mSeeking = SEEK_VIDEO_ONLY; 1747 mSeekTimeUs = mediaTimeUs; 1748 1749 postVideoEvent_l(); 1750 return; 1751 } 1752 1753 if (latenessUs > 40000) { 1754 // We're more than 40ms late. 1755 LOGV("we're late by %lld us (%.2f secs), dropping frame", 1756 latenessUs, latenessUs / 1E6); 1757 mVideoBuffer->release(); 1758 mVideoBuffer = NULL; 1759 1760 { 1761 Mutex::Autolock autoLock(mStatsLock); 1762 ++mStats.mNumVideoFramesDropped; 1763 } 1764 1765 postVideoEvent_l(); 1766 return; 1767 } 1768 1769 if (latenessUs < -10000) { 1770 // We're more than 10ms early. 1771 1772 postVideoEvent_l(10000); 1773 return; 1774 } 1775 } 1776 1777 if ((mNativeWindow != NULL) 1778 && (mVideoRendererIsPreview || mVideoRenderer == NULL)) { 1779 mVideoRendererIsPreview = false; 1780 1781 initRenderer_l(); 1782 } 1783 1784 if (mVideoRenderer != NULL) { 1785 mVideoRenderer->render(mVideoBuffer); 1786 } 1787 1788 mVideoBuffer->release(); 1789 mVideoBuffer = NULL; 1790 1791 if (wasSeeking != NO_SEEK && (mFlags & SEEK_PREVIEW)) { 1792 modifyFlags(SEEK_PREVIEW, CLEAR); 1793 return; 1794 } 1795 1796 postVideoEvent_l(); 1797} 1798 1799void AwesomePlayer::postVideoEvent_l(int64_t delayUs) { 1800 if (mVideoEventPending) { 1801 return; 1802 } 1803 1804 mVideoEventPending = true; 1805 mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs); 1806} 1807 1808void AwesomePlayer::postStreamDoneEvent_l(status_t status) { 1809 if (mStreamDoneEventPending) { 1810 return; 1811 } 1812 mStreamDoneEventPending = true; 1813 1814 mStreamDoneStatus = status; 1815 mQueue.postEvent(mStreamDoneEvent); 1816} 1817 1818void AwesomePlayer::postBufferingEvent_l() { 1819 if (mBufferingEventPending) { 1820 return; 1821 } 1822 mBufferingEventPending = true; 1823 mQueue.postEventWithDelay(mBufferingEvent, 1000000ll); 1824} 1825 1826void AwesomePlayer::postVideoLagEvent_l() { 1827 if (mVideoLagEventPending) { 1828 return; 1829 } 1830 mVideoLagEventPending = true; 1831 mQueue.postEventWithDelay(mVideoLagEvent, 1000000ll); 1832} 1833 1834void AwesomePlayer::postCheckAudioStatusEvent_l(int64_t delayUs) { 1835 if (mAudioStatusEventPending) { 1836 return; 1837 } 1838 mAudioStatusEventPending = true; 1839 mQueue.postEventWithDelay(mCheckAudioStatusEvent, delayUs); 1840} 1841 1842void AwesomePlayer::onCheckAudioStatus() { 1843 Mutex::Autolock autoLock(mLock); 1844 if (!mAudioStatusEventPending) { 1845 // Event was dispatched and while we were blocking on the mutex, 1846 // has already been cancelled. 1847 return; 1848 } 1849 1850 mAudioStatusEventPending = false; 1851 1852 if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) { 1853 mWatchForAudioSeekComplete = false; 1854 1855 if (!mSeekNotificationSent) { 1856 notifyListener_l(MEDIA_SEEK_COMPLETE); 1857 mSeekNotificationSent = true; 1858 } 1859 1860 mSeeking = NO_SEEK; 1861 } 1862 1863 status_t finalStatus; 1864 if (mWatchForAudioEOS && mAudioPlayer->reachedEOS(&finalStatus)) { 1865 mWatchForAudioEOS = false; 1866 modifyFlags(AUDIO_AT_EOS, SET); 1867 modifyFlags(FIRST_FRAME, SET); 1868 postStreamDoneEvent_l(finalStatus); 1869 } 1870} 1871 1872status_t AwesomePlayer::prepare() { 1873 Mutex::Autolock autoLock(mLock); 1874 return prepare_l(); 1875} 1876 1877status_t AwesomePlayer::prepare_l() { 1878 if (mFlags & PREPARED) { 1879 return OK; 1880 } 1881 1882 if (mFlags & PREPARING) { 1883 return UNKNOWN_ERROR; 1884 } 1885 1886 mIsAsyncPrepare = false; 1887 status_t err = prepareAsync_l(); 1888 1889 if (err != OK) { 1890 return err; 1891 } 1892 1893 while (mFlags & PREPARING) { 1894 mPreparedCondition.wait(mLock); 1895 } 1896 1897 return mPrepareResult; 1898} 1899 1900status_t AwesomePlayer::prepareAsync() { 1901 Mutex::Autolock autoLock(mLock); 1902 1903 if (mFlags & PREPARING) { 1904 return UNKNOWN_ERROR; // async prepare already pending 1905 } 1906 1907 mIsAsyncPrepare = true; 1908 return prepareAsync_l(); 1909} 1910 1911status_t AwesomePlayer::prepareAsync_l() { 1912 if (mFlags & PREPARING) { 1913 return UNKNOWN_ERROR; // async prepare already pending 1914 } 1915 1916 if (!mQueueStarted) { 1917 mQueue.start(); 1918 mQueueStarted = true; 1919 } 1920 1921 modifyFlags(PREPARING, SET); 1922 mAsyncPrepareEvent = new AwesomeEvent( 1923 this, &AwesomePlayer::onPrepareAsyncEvent); 1924 1925 mQueue.postEvent(mAsyncPrepareEvent); 1926 1927 return OK; 1928} 1929 1930status_t AwesomePlayer::finishSetDataSource_l() { 1931 sp<DataSource> dataSource; 1932 1933 bool isWidevineStreaming = false; 1934 if (!strncasecmp("widevine://", mUri.string(), 11)) { 1935 isWidevineStreaming = true; 1936 1937 String8 newURI = String8("http://"); 1938 newURI.append(mUri.string() + 11); 1939 1940 mUri = newURI; 1941 } 1942 1943 if (!strncasecmp("http://", mUri.string(), 7) 1944 || !strncasecmp("https://", mUri.string(), 8) 1945 || isWidevineStreaming) { 1946 mConnectingDataSource = HTTPBase::Create( 1947 (mFlags & INCOGNITO) 1948 ? HTTPBase::kFlagIncognito 1949 : 0); 1950 1951 if (mUIDValid) { 1952 mConnectingDataSource->setUID(mUID); 1953 } 1954 1955 mLock.unlock(); 1956 status_t err = mConnectingDataSource->connect(mUri, &mUriHeaders); 1957 mLock.lock(); 1958 1959 if (err != OK) { 1960 mConnectingDataSource.clear(); 1961 1962 LOGI("mConnectingDataSource->connect() returned %d", err); 1963 return err; 1964 } 1965 1966 if (!isWidevineStreaming) { 1967 // The widevine extractor does its own caching. 1968 1969#if 0 1970 mCachedSource = new NuCachedSource2( 1971 new ThrottledSource( 1972 mConnectingDataSource, 50 * 1024 /* bytes/sec */)); 1973#else 1974 mCachedSource = new NuCachedSource2(mConnectingDataSource); 1975#endif 1976 1977 dataSource = mCachedSource; 1978 } else { 1979 dataSource = mConnectingDataSource; 1980 } 1981 1982 mConnectingDataSource.clear(); 1983 1984 1985 String8 contentType = dataSource->getMIMEType(); 1986 1987 if (strncasecmp(contentType.string(), "audio/", 6)) { 1988 // We're not doing this for streams that appear to be audio-only 1989 // streams to ensure that even low bandwidth streams start 1990 // playing back fairly instantly. 1991 1992 // We're going to prefill the cache before trying to instantiate 1993 // the extractor below, as the latter is an operation that otherwise 1994 // could block on the datasource for a significant amount of time. 1995 // During that time we'd be unable to abort the preparation phase 1996 // without this prefill. 1997 if (mCachedSource != NULL) { 1998 // We're going to prefill the cache before trying to instantiate 1999 // the extractor below, as the latter is an operation that otherwise 2000 // could block on the datasource for a significant amount of time. 2001 // During that time we'd be unable to abort the preparation phase 2002 // without this prefill. 2003 2004 mLock.unlock(); 2005 2006 for (;;) { 2007 status_t finalStatus; 2008 size_t cachedDataRemaining = 2009 mCachedSource->approxDataRemaining(&finalStatus); 2010 2011 if (finalStatus != OK || cachedDataRemaining >= kHighWaterMarkBytes 2012 || (mFlags & PREPARE_CANCELLED)) { 2013 break; 2014 } 2015 2016 usleep(200000); 2017 } 2018 2019 mLock.lock(); 2020 } 2021 2022 if (mFlags & PREPARE_CANCELLED) { 2023 LOGI("Prepare cancelled while waiting for initial cache fill."); 2024 return UNKNOWN_ERROR; 2025 } 2026 } 2027 } else if (!strncasecmp("rtsp://", mUri.string(), 7)) { 2028 if (mLooper == NULL) { 2029 mLooper = new ALooper; 2030 mLooper->setName("rtsp"); 2031 mLooper->start(); 2032 } 2033 mRTSPController = new ARTSPController(mLooper); 2034 mConnectingRTSPController = mRTSPController; 2035 2036 if (mUIDValid) { 2037 mConnectingRTSPController->setUID(mUID); 2038 } 2039 2040 mLock.unlock(); 2041 status_t err = mRTSPController->connect(mUri.string()); 2042 mLock.lock(); 2043 2044 mConnectingRTSPController.clear(); 2045 2046 LOGI("ARTSPController::connect returned %d", err); 2047 2048 if (err != OK) { 2049 mRTSPController.clear(); 2050 return err; 2051 } 2052 2053 sp<MediaExtractor> extractor = mRTSPController.get(); 2054 return setDataSource_l(extractor); 2055 } else { 2056 dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders); 2057 } 2058 2059 if (dataSource == NULL) { 2060 return UNKNOWN_ERROR; 2061 } 2062 2063 sp<MediaExtractor> extractor; 2064 2065 if (isWidevineStreaming) { 2066 String8 mimeType; 2067 float confidence; 2068 sp<AMessage> dummy; 2069 bool success = SniffDRM(dataSource, &mimeType, &confidence, &dummy); 2070 2071 if (!success 2072 || strcasecmp( 2073 mimeType.string(), MEDIA_MIMETYPE_CONTAINER_WVM)) { 2074 return ERROR_UNSUPPORTED; 2075 } 2076 2077 mWVMExtractor = new WVMExtractor(dataSource); 2078 mWVMExtractor->setAdaptiveStreamingMode(true); 2079 extractor = mWVMExtractor; 2080 } else { 2081 extractor = MediaExtractor::Create(dataSource); 2082 2083 if (extractor == NULL) { 2084 return UNKNOWN_ERROR; 2085 } 2086 } 2087 2088 dataSource->getDrmInfo(mDecryptHandle, &mDrmManagerClient); 2089 2090 if (mDecryptHandle != NULL) { 2091 CHECK(mDrmManagerClient); 2092 if (RightsStatus::RIGHTS_VALID != mDecryptHandle->status) { 2093 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_DRM_NO_LICENSE); 2094 } 2095 } 2096 2097 status_t err = setDataSource_l(extractor); 2098 2099 if (err != OK) { 2100 mWVMExtractor.clear(); 2101 2102 return err; 2103 } 2104 2105 return OK; 2106} 2107 2108void AwesomePlayer::abortPrepare(status_t err) { 2109 CHECK(err != OK); 2110 2111 if (mIsAsyncPrepare) { 2112 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err); 2113 } 2114 2115 mPrepareResult = err; 2116 modifyFlags((PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED), CLEAR); 2117 mAsyncPrepareEvent = NULL; 2118 mPreparedCondition.broadcast(); 2119} 2120 2121// static 2122bool AwesomePlayer::ContinuePreparation(void *cookie) { 2123 AwesomePlayer *me = static_cast<AwesomePlayer *>(cookie); 2124 2125 return (me->mFlags & PREPARE_CANCELLED) == 0; 2126} 2127 2128void AwesomePlayer::onPrepareAsyncEvent() { 2129 Mutex::Autolock autoLock(mLock); 2130 2131 if (mFlags & PREPARE_CANCELLED) { 2132 LOGI("prepare was cancelled before doing anything"); 2133 abortPrepare(UNKNOWN_ERROR); 2134 return; 2135 } 2136 2137 if (mUri.size() > 0) { 2138 status_t err = finishSetDataSource_l(); 2139 2140 if (err != OK) { 2141 abortPrepare(err); 2142 return; 2143 } 2144 } 2145 2146 if (mVideoTrack != NULL && mVideoSource == NULL) { 2147 status_t err = initVideoDecoder(); 2148 2149 if (err != OK) { 2150 abortPrepare(err); 2151 return; 2152 } 2153 } 2154 2155 if (mAudioTrack != NULL && mAudioSource == NULL) { 2156 status_t err = initAudioDecoder(); 2157 2158 if (err != OK) { 2159 abortPrepare(err); 2160 return; 2161 } 2162 } 2163 2164 modifyFlags(PREPARING_CONNECTED, SET); 2165 2166 if (isStreamingHTTP() || mRTSPController != NULL) { 2167 postBufferingEvent_l(); 2168 } else { 2169 finishAsyncPrepare_l(); 2170 } 2171} 2172 2173void AwesomePlayer::finishAsyncPrepare_l() { 2174 if (mIsAsyncPrepare) { 2175 if (mVideoSource == NULL) { 2176 notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0); 2177 } else { 2178 notifyVideoSize_l(); 2179 } 2180 2181 notifyListener_l(MEDIA_PREPARED); 2182 } 2183 2184 mPrepareResult = OK; 2185 modifyFlags((PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED), CLEAR); 2186 modifyFlags(PREPARED, SET); 2187 mAsyncPrepareEvent = NULL; 2188 mPreparedCondition.broadcast(); 2189} 2190 2191uint32_t AwesomePlayer::flags() const { 2192 return mExtractorFlags; 2193} 2194 2195void AwesomePlayer::postAudioEOS(int64_t delayUs) { 2196 Mutex::Autolock autoLock(mLock); 2197 postCheckAudioStatusEvent_l(delayUs); 2198} 2199 2200void AwesomePlayer::postAudioSeekComplete() { 2201 Mutex::Autolock autoLock(mLock); 2202 postAudioSeekComplete_l(); 2203} 2204 2205void AwesomePlayer::postAudioSeekComplete_l() { 2206 postCheckAudioStatusEvent_l(0 /* delayUs */); 2207} 2208 2209status_t AwesomePlayer::setParameter(int key, const Parcel &request) { 2210 switch (key) { 2211 case KEY_PARAMETER_TIMED_TEXT_TRACK_INDEX: 2212 { 2213 Mutex::Autolock autoLock(mTimedTextLock); 2214 return setTimedTextTrackIndex(request.readInt32()); 2215 } 2216 case KEY_PARAMETER_TIMED_TEXT_ADD_OUT_OF_BAND_SOURCE: 2217 { 2218 Mutex::Autolock autoLock(mTimedTextLock); 2219 if (mTextPlayer == NULL) { 2220 mTextPlayer = new TimedTextPlayer(this, mListener, &mQueue); 2221 } 2222 2223 return mTextPlayer->setParameter(key, request); 2224 } 2225 case KEY_PARAMETER_CACHE_STAT_COLLECT_FREQ_MS: 2226 { 2227 return setCacheStatCollectFreq(request); 2228 } 2229 default: 2230 { 2231 return ERROR_UNSUPPORTED; 2232 } 2233 } 2234} 2235 2236status_t AwesomePlayer::setCacheStatCollectFreq(const Parcel &request) { 2237 if (mCachedSource != NULL) { 2238 int32_t freqMs = request.readInt32(); 2239 LOGD("Request to keep cache stats in the past %d ms", 2240 freqMs); 2241 return mCachedSource->setCacheStatCollectFreq(freqMs); 2242 } 2243 return ERROR_UNSUPPORTED; 2244} 2245 2246status_t AwesomePlayer::getParameter(int key, Parcel *reply) { 2247 switch (key) { 2248 case KEY_PARAMETER_AUDIO_CHANNEL_COUNT: 2249 { 2250 int32_t channelCount; 2251 if (mAudioTrack == 0 || 2252 !mAudioTrack->getFormat()->findInt32(kKeyChannelCount, &channelCount)) { 2253 channelCount = 0; 2254 } 2255 reply->writeInt32(channelCount); 2256 } 2257 return OK; 2258 default: 2259 { 2260 return ERROR_UNSUPPORTED; 2261 } 2262 } 2263} 2264 2265bool AwesomePlayer::isStreamingHTTP() const { 2266 return mCachedSource != NULL || mWVMExtractor != NULL; 2267} 2268 2269status_t AwesomePlayer::dump(int fd, const Vector<String16> &args) const { 2270 Mutex::Autolock autoLock(mStatsLock); 2271 2272 FILE *out = fdopen(dup(fd), "w"); 2273 2274 fprintf(out, " AwesomePlayer\n"); 2275 if (mStats.mFd < 0) { 2276 fprintf(out, " URI(%s)", mStats.mURI.string()); 2277 } else { 2278 fprintf(out, " fd(%d)", mStats.mFd); 2279 } 2280 2281 fprintf(out, ", flags(0x%08x)", mStats.mFlags); 2282 2283 if (mStats.mBitrate >= 0) { 2284 fprintf(out, ", bitrate(%lld bps)", mStats.mBitrate); 2285 } 2286 2287 fprintf(out, "\n"); 2288 2289 for (size_t i = 0; i < mStats.mTracks.size(); ++i) { 2290 const TrackStat &stat = mStats.mTracks.itemAt(i); 2291 2292 fprintf(out, " Track %d\n", i + 1); 2293 fprintf(out, " MIME(%s)", stat.mMIME.string()); 2294 2295 if (!stat.mDecoderName.isEmpty()) { 2296 fprintf(out, ", decoder(%s)", stat.mDecoderName.string()); 2297 } 2298 2299 fprintf(out, "\n"); 2300 2301 if ((ssize_t)i == mStats.mVideoTrackIndex) { 2302 fprintf(out, 2303 " videoDimensions(%d x %d), " 2304 "numVideoFramesDecoded(%lld), " 2305 "numVideoFramesDropped(%lld)\n", 2306 mStats.mVideoWidth, 2307 mStats.mVideoHeight, 2308 mStats.mNumVideoFramesDecoded, 2309 mStats.mNumVideoFramesDropped); 2310 } 2311 } 2312 2313 fclose(out); 2314 out = NULL; 2315 2316 return OK; 2317} 2318 2319void AwesomePlayer::modifyFlags(unsigned value, FlagMode mode) { 2320 switch (mode) { 2321 case SET: 2322 mFlags |= value; 2323 break; 2324 case CLEAR: 2325 mFlags &= ~value; 2326 break; 2327 case ASSIGN: 2328 mFlags = value; 2329 break; 2330 default: 2331 TRESPASS(); 2332 } 2333 2334 { 2335 Mutex::Autolock autoLock(mStatsLock); 2336 mStats.mFlags = mFlags; 2337 } 2338} 2339 2340} // namespace android 2341