AwesomePlayer.cpp revision 5442cb59e8483e18b3a02400d431d167ea7074b3
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 = 10000000ll; // 10secs 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 LOGI("reset"); 457 Mutex::Autolock autoLock(mLock); 458 reset_l(); 459} 460 461void AwesomePlayer::reset_l() { 462 mDisplayWidth = 0; 463 mDisplayHeight = 0; 464 465 if (mDecryptHandle != NULL) { 466 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, 467 Playback::STOP, 0); 468 mDecryptHandle = NULL; 469 mDrmManagerClient = NULL; 470 LOGI("DRM manager client stopped"); 471 } 472 473 474 if (mFlags & PLAYING) { 475 uint32_t params = IMediaPlayerService::kBatteryDataTrackDecoder; 476 if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) { 477 params |= IMediaPlayerService::kBatteryDataTrackAudio; 478 } 479 if (mVideoSource != NULL) { 480 params |= IMediaPlayerService::kBatteryDataTrackVideo; 481 } 482 addBatteryData(params); 483 } 484 485 if (mFlags & PREPARING) { 486 modifyFlags(PREPARE_CANCELLED, SET); 487 if (mConnectingDataSource != NULL) { 488 LOGI("interrupting the connection process"); 489 mConnectingDataSource->disconnect(); 490 } else if (mConnectingRTSPController != NULL) { 491 LOGI("interrupting the connection process"); 492 mConnectingRTSPController->disconnect(); 493 } 494 495 if (mFlags & PREPARING_CONNECTED) { 496 // We are basically done preparing, we're just buffering 497 // enough data to start playback, we can safely interrupt that. 498 finishAsyncPrepare_l(); 499 } 500 } 501 502 while (mFlags & PREPARING) { 503 mPreparedCondition.wait(mLock); 504 } 505 506 LOGI("cancel player events"); 507 cancelPlayerEvents(); 508 509 mWVMExtractor.clear(); 510 mCachedSource.clear(); 511 mAudioTrack.clear(); 512 mVideoTrack.clear(); 513 514 // Shutdown audio first, so that the respone to the reset request 515 // appears to happen instantaneously as far as the user is concerned 516 // If we did this later, audio would continue playing while we 517 // shutdown the video-related resources and the player appear to 518 // not be as responsive to a reset request. 519 if (mAudioPlayer == NULL && mAudioSource != NULL) { 520 // If we had an audio player, it would have effectively 521 // taken possession of the audio source and stopped it when 522 // _it_ is stopped. Otherwise this is still our responsibility. 523 mAudioSource->stop(); 524 } 525 mAudioSource.clear(); 526 527 mTimeSource = NULL; 528 529 delete mAudioPlayer; 530 mAudioPlayer = NULL; 531 532 if (mTextPlayer != NULL) { 533 delete mTextPlayer; 534 mTextPlayer = NULL; 535 } 536 537 mVideoRenderer.clear(); 538 539 if (mRTSPController != NULL) { 540 mRTSPController->disconnect(); 541 mRTSPController.clear(); 542 } 543 544 if (mVideoSource != NULL) { 545 shutdownVideoDecoder_l(); 546 } 547 548 mDurationUs = -1; 549 modifyFlags(0, ASSIGN); 550 mExtractorFlags = 0; 551 mTimeSourceDeltaUs = 0; 552 mVideoTimeUs = 0; 553 554 mSeeking = NO_SEEK; 555 mSeekNotificationSent = false; 556 mSeekTimeUs = 0; 557 558 mUri.setTo(""); 559 mUriHeaders.clear(); 560 561 mFileSource.clear(); 562 563 mBitrate = -1; 564 mLastVideoTimeUs = -1; 565 566 { 567 Mutex::Autolock autoLock(mStatsLock); 568 mStats.mFd = -1; 569 mStats.mURI = String8(); 570 mStats.mBitrate = -1; 571 mStats.mAudioTrackIndex = -1; 572 mStats.mVideoTrackIndex = -1; 573 mStats.mNumVideoFramesDecoded = 0; 574 mStats.mNumVideoFramesDropped = 0; 575 mStats.mVideoWidth = -1; 576 mStats.mVideoHeight = -1; 577 mStats.mFlags = 0; 578 mStats.mTracks.clear(); 579 } 580 581} 582 583void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) { 584 if (mListener != NULL) { 585 sp<MediaPlayerBase> listener = mListener.promote(); 586 587 if (listener != NULL) { 588 listener->sendEvent(msg, ext1, ext2); 589 } 590 } 591} 592 593bool AwesomePlayer::getBitrate(int64_t *bitrate) { 594 off64_t size; 595 if (mDurationUs >= 0 && mCachedSource != NULL 596 && mCachedSource->getSize(&size) == OK) { 597 *bitrate = size * 8000000ll / mDurationUs; // in bits/sec 598 return true; 599 } 600 601 if (mBitrate >= 0) { 602 *bitrate = mBitrate; 603 return true; 604 } 605 606 *bitrate = 0; 607 608 return false; 609} 610 611// Returns true iff cached duration is available/applicable. 612bool AwesomePlayer::getCachedDuration_l(int64_t *durationUs, bool *eos) { 613 int64_t bitrate; 614 615 if (mRTSPController != NULL) { 616 *durationUs = mRTSPController->getQueueDurationUs(eos); 617 return true; 618 } else if (mCachedSource != NULL && getBitrate(&bitrate)) { 619 status_t finalStatus; 620 size_t cachedDataRemaining = mCachedSource->approxDataRemaining(&finalStatus); 621 *durationUs = cachedDataRemaining * 8000000ll / bitrate; 622 *eos = (finalStatus != OK); 623 return true; 624 } else if (mWVMExtractor != NULL) { 625 status_t finalStatus; 626 *durationUs = mWVMExtractor->getCachedDurationUs(&finalStatus); 627 *eos = (finalStatus != OK); 628 return true; 629 } 630 631 return false; 632} 633 634void AwesomePlayer::ensureCacheIsFetching_l() { 635 if (mCachedSource != NULL) { 636 mCachedSource->resumeFetchingIfNecessary(); 637 } 638} 639 640void AwesomePlayer::onVideoLagUpdate() { 641 Mutex::Autolock autoLock(mLock); 642 if (!mVideoLagEventPending) { 643 return; 644 } 645 mVideoLagEventPending = false; 646 647 int64_t audioTimeUs = mAudioPlayer->getMediaTimeUs(); 648 int64_t videoLateByUs = audioTimeUs - mVideoTimeUs; 649 650 if (!(mFlags & VIDEO_AT_EOS) && videoLateByUs > 300000ll) { 651 LOGV("video late by %lld ms.", videoLateByUs / 1000ll); 652 653 notifyListener_l( 654 MEDIA_INFO, 655 MEDIA_INFO_VIDEO_TRACK_LAGGING, 656 videoLateByUs / 1000ll); 657 } 658 659 postVideoLagEvent_l(); 660} 661 662void AwesomePlayer::onBufferingUpdate() { 663 Mutex::Autolock autoLock(mLock); 664 if (!mBufferingEventPending) { 665 return; 666 } 667 mBufferingEventPending = false; 668 669 if (mCachedSource != NULL) { 670 status_t finalStatus; 671 size_t cachedDataRemaining = mCachedSource->approxDataRemaining(&finalStatus); 672 bool eos = (finalStatus != OK); 673 674 if (eos) { 675 if (finalStatus == ERROR_END_OF_STREAM) { 676 notifyListener_l(MEDIA_BUFFERING_UPDATE, 100); 677 } 678 if (mFlags & PREPARING) { 679 LOGV("cache has reached EOS, prepare is done."); 680 finishAsyncPrepare_l(); 681 } 682 } else { 683 int64_t bitrate; 684 if (getBitrate(&bitrate)) { 685 size_t cachedSize = mCachedSource->cachedSize(); 686 int64_t cachedDurationUs = cachedSize * 8000000ll / bitrate; 687 688 int percentage = 100.0 * (double)cachedDurationUs / mDurationUs; 689 if (percentage > 100) { 690 percentage = 100; 691 } 692 693 notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage); 694 } else { 695 // We don't know the bitrate of the stream, use absolute size 696 // limits to maintain the cache. 697 698 if ((mFlags & PLAYING) && !eos 699 && (cachedDataRemaining < kLowWaterMarkBytes)) { 700 LOGI("cache is running low (< %d) , pausing.", 701 kLowWaterMarkBytes); 702 modifyFlags(CACHE_UNDERRUN, SET); 703 pause_l(); 704 ensureCacheIsFetching_l(); 705 sendCacheStats(); 706 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START); 707 } else if (eos || cachedDataRemaining > kHighWaterMarkBytes) { 708 if (mFlags & CACHE_UNDERRUN) { 709 LOGI("cache has filled up (> %d), resuming.", 710 kHighWaterMarkBytes); 711 modifyFlags(CACHE_UNDERRUN, CLEAR); 712 play_l(); 713 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END); 714 } else if (mFlags & PREPARING) { 715 LOGV("cache has filled up (> %d), prepare is done", 716 kHighWaterMarkBytes); 717 finishAsyncPrepare_l(); 718 } 719 } 720 } 721 } 722 } else if (mWVMExtractor != NULL) { 723 status_t finalStatus; 724 725 int64_t cachedDurationUs 726 = mWVMExtractor->getCachedDurationUs(&finalStatus); 727 728 bool eos = (finalStatus != OK); 729 730 if (eos) { 731 if (finalStatus == ERROR_END_OF_STREAM) { 732 notifyListener_l(MEDIA_BUFFERING_UPDATE, 100); 733 } 734 if (mFlags & PREPARING) { 735 LOGV("cache has reached EOS, prepare is done."); 736 finishAsyncPrepare_l(); 737 } 738 } else { 739 int percentage = 100.0 * (double)cachedDurationUs / mDurationUs; 740 if (percentage > 100) { 741 percentage = 100; 742 } 743 744 notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage); 745 } 746 } 747 748 int64_t cachedDurationUs; 749 bool eos; 750 if (getCachedDuration_l(&cachedDurationUs, &eos)) { 751 LOGV("cachedDurationUs = %.2f secs, eos=%d", 752 cachedDurationUs / 1E6, eos); 753 754 int64_t highWaterMarkUs = 755 (mRTSPController != NULL) ? kHighWaterMarkRTSPUs : kHighWaterMarkUs; 756 757 if ((mFlags & PLAYING) && !eos 758 && (cachedDurationUs < kLowWaterMarkUs)) { 759 LOGI("cache is running low (%.2f secs) , pausing.", 760 cachedDurationUs / 1E6); 761 modifyFlags(CACHE_UNDERRUN, SET); 762 pause_l(); 763 ensureCacheIsFetching_l(); 764 sendCacheStats(); 765 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START); 766 } else if (eos || cachedDurationUs > highWaterMarkUs) { 767 if (mFlags & CACHE_UNDERRUN) { 768 LOGI("cache has filled up (%.2f secs), resuming.", 769 cachedDurationUs / 1E6); 770 modifyFlags(CACHE_UNDERRUN, CLEAR); 771 play_l(); 772 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END); 773 } else if (mFlags & PREPARING) { 774 LOGV("cache has filled up (%.2f secs), prepare is done", 775 cachedDurationUs / 1E6); 776 finishAsyncPrepare_l(); 777 } 778 } 779 } 780 781 postBufferingEvent_l(); 782} 783 784void AwesomePlayer::sendCacheStats() { 785 sp<MediaPlayerBase> listener = mListener.promote(); 786 if (listener != NULL && mCachedSource != NULL) { 787 int32_t kbps = 0; 788 status_t err = mCachedSource->getEstimatedBandwidthKbps(&kbps); 789 if (err == OK) { 790 listener->sendEvent( 791 MEDIA_INFO, MEDIA_INFO_NETWORK_BANDWIDTH, kbps); 792 } 793 } 794} 795 796void AwesomePlayer::onStreamDone() { 797 // Posted whenever any stream finishes playing. 798 799 Mutex::Autolock autoLock(mLock); 800 if (!mStreamDoneEventPending) { 801 return; 802 } 803 mStreamDoneEventPending = false; 804 805 if (mStreamDoneStatus != ERROR_END_OF_STREAM) { 806 LOGV("MEDIA_ERROR %d", mStreamDoneStatus); 807 808 notifyListener_l( 809 MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, mStreamDoneStatus); 810 811 pause_l(true /* at eos */); 812 813 modifyFlags(AT_EOS, SET); 814 return; 815 } 816 817 const bool allDone = 818 (mVideoSource == NULL || (mFlags & VIDEO_AT_EOS)) 819 && (mAudioSource == NULL || (mFlags & AUDIO_AT_EOS)); 820 821 if (!allDone) { 822 return; 823 } 824 825 if (mFlags & (LOOPING | AUTO_LOOPING)) { 826 seekTo_l(0); 827 828 if (mVideoSource != NULL) { 829 postVideoEvent_l(); 830 } 831 } else { 832 LOGV("MEDIA_PLAYBACK_COMPLETE"); 833 notifyListener_l(MEDIA_PLAYBACK_COMPLETE); 834 835 pause_l(true /* at eos */); 836 837 modifyFlags(AT_EOS, SET); 838 } 839} 840 841status_t AwesomePlayer::play() { 842 Mutex::Autolock autoLock(mLock); 843 844 modifyFlags(CACHE_UNDERRUN, CLEAR); 845 846 return play_l(); 847} 848 849status_t AwesomePlayer::play_l() { 850 modifyFlags(SEEK_PREVIEW, CLEAR); 851 852 if (mFlags & PLAYING) { 853 return OK; 854 } 855 856 if (!(mFlags & PREPARED)) { 857 status_t err = prepare_l(); 858 859 if (err != OK) { 860 return err; 861 } 862 } 863 864 modifyFlags(PLAYING, SET); 865 modifyFlags(FIRST_FRAME, SET); 866 867 if (mDecryptHandle != NULL) { 868 int64_t position; 869 getPosition(&position); 870 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, 871 Playback::START, position / 1000); 872 } 873 874 if (mAudioSource != NULL) { 875 if (mAudioPlayer == NULL) { 876 if (mAudioSink != NULL) { 877 mAudioPlayer = new AudioPlayer(mAudioSink, this); 878 mAudioPlayer->setSource(mAudioSource); 879 880 mTimeSource = mAudioPlayer; 881 882 // If there was a seek request before we ever started, 883 // honor the request now. 884 // Make sure to do this before starting the audio player 885 // to avoid a race condition. 886 seekAudioIfNecessary_l(); 887 } 888 } 889 890 CHECK(!(mFlags & AUDIO_RUNNING)); 891 892 if (mVideoSource == NULL) { 893 // We don't want to post an error notification at this point, 894 // the error returned from MediaPlayer::start() will suffice. 895 896 status_t err = startAudioPlayer_l( 897 false /* sendErrorNotification */); 898 899 if (err != OK) { 900 delete mAudioPlayer; 901 mAudioPlayer = NULL; 902 903 modifyFlags((PLAYING | FIRST_FRAME), CLEAR); 904 905 if (mDecryptHandle != NULL) { 906 mDrmManagerClient->setPlaybackStatus( 907 mDecryptHandle, Playback::STOP, 0); 908 } 909 910 return err; 911 } 912 } 913 } 914 915 if (mTimeSource == NULL && mAudioPlayer == NULL) { 916 mTimeSource = &mSystemTimeSource; 917 } 918 919 if (mVideoSource != NULL) { 920 // Kick off video playback 921 postVideoEvent_l(); 922 923 if (mAudioSource != NULL && mVideoSource != NULL) { 924 postVideoLagEvent_l(); 925 } 926 } 927 928 if (mFlags & AT_EOS) { 929 // Legacy behaviour, if a stream finishes playing and then 930 // is started again, we play from the start... 931 seekTo_l(0); 932 } 933 934 uint32_t params = IMediaPlayerService::kBatteryDataCodecStarted 935 | IMediaPlayerService::kBatteryDataTrackDecoder; 936 if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) { 937 params |= IMediaPlayerService::kBatteryDataTrackAudio; 938 } 939 if (mVideoSource != NULL) { 940 params |= IMediaPlayerService::kBatteryDataTrackVideo; 941 } 942 addBatteryData(params); 943 944 return OK; 945} 946 947status_t AwesomePlayer::startAudioPlayer_l(bool sendErrorNotification) { 948 CHECK(!(mFlags & AUDIO_RUNNING)); 949 950 if (mAudioSource == NULL || mAudioPlayer == NULL) { 951 return OK; 952 } 953 954 if (!(mFlags & AUDIOPLAYER_STARTED)) { 955 modifyFlags(AUDIOPLAYER_STARTED, SET); 956 957 bool wasSeeking = mAudioPlayer->isSeeking(); 958 959 // We've already started the MediaSource in order to enable 960 // the prefetcher to read its data. 961 status_t err = mAudioPlayer->start( 962 true /* sourceAlreadyStarted */); 963 964 if (err != OK) { 965 if (sendErrorNotification) { 966 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err); 967 } 968 969 return err; 970 } 971 972 if (wasSeeking) { 973 CHECK(!mAudioPlayer->isSeeking()); 974 975 // We will have finished the seek while starting the audio player. 976 postAudioSeekComplete_l(); 977 } 978 } else { 979 mAudioPlayer->resume(); 980 } 981 982 modifyFlags(AUDIO_RUNNING, SET); 983 984 mWatchForAudioEOS = true; 985 986 return OK; 987} 988 989void AwesomePlayer::notifyVideoSize_l() { 990 sp<MetaData> meta = mVideoSource->getFormat(); 991 992 int32_t cropLeft, cropTop, cropRight, cropBottom; 993 if (!meta->findRect( 994 kKeyCropRect, &cropLeft, &cropTop, &cropRight, &cropBottom)) { 995 int32_t width, height; 996 CHECK(meta->findInt32(kKeyWidth, &width)); 997 CHECK(meta->findInt32(kKeyHeight, &height)); 998 999 cropLeft = cropTop = 0; 1000 cropRight = width - 1; 1001 cropBottom = height - 1; 1002 1003 LOGV("got dimensions only %d x %d", width, height); 1004 } else { 1005 LOGV("got crop rect %d, %d, %d, %d", 1006 cropLeft, cropTop, cropRight, cropBottom); 1007 } 1008 1009 int32_t displayWidth; 1010 if (meta->findInt32(kKeyDisplayWidth, &displayWidth)) { 1011 LOGV("Display width changed (%d=>%d)", mDisplayWidth, displayWidth); 1012 mDisplayWidth = displayWidth; 1013 } 1014 int32_t displayHeight; 1015 if (meta->findInt32(kKeyDisplayHeight, &displayHeight)) { 1016 LOGV("Display height changed (%d=>%d)", mDisplayHeight, displayHeight); 1017 mDisplayHeight = displayHeight; 1018 } 1019 1020 int32_t usableWidth = cropRight - cropLeft + 1; 1021 int32_t usableHeight = cropBottom - cropTop + 1; 1022 if (mDisplayWidth != 0) { 1023 usableWidth = mDisplayWidth; 1024 } 1025 if (mDisplayHeight != 0) { 1026 usableHeight = mDisplayHeight; 1027 } 1028 1029 { 1030 Mutex::Autolock autoLock(mStatsLock); 1031 mStats.mVideoWidth = usableWidth; 1032 mStats.mVideoHeight = usableHeight; 1033 } 1034 1035 int32_t rotationDegrees; 1036 if (!mVideoTrack->getFormat()->findInt32( 1037 kKeyRotation, &rotationDegrees)) { 1038 rotationDegrees = 0; 1039 } 1040 1041 if (rotationDegrees == 90 || rotationDegrees == 270) { 1042 notifyListener_l( 1043 MEDIA_SET_VIDEO_SIZE, usableHeight, usableWidth); 1044 } else { 1045 notifyListener_l( 1046 MEDIA_SET_VIDEO_SIZE, usableWidth, usableHeight); 1047 } 1048} 1049 1050void AwesomePlayer::initRenderer_l() { 1051 if (mNativeWindow == NULL) { 1052 return; 1053 } 1054 1055 sp<MetaData> meta = mVideoSource->getFormat(); 1056 1057 int32_t format; 1058 const char *component; 1059 int32_t decodedWidth, decodedHeight; 1060 CHECK(meta->findInt32(kKeyColorFormat, &format)); 1061 CHECK(meta->findCString(kKeyDecoderComponent, &component)); 1062 CHECK(meta->findInt32(kKeyWidth, &decodedWidth)); 1063 CHECK(meta->findInt32(kKeyHeight, &decodedHeight)); 1064 1065 int32_t rotationDegrees; 1066 if (!mVideoTrack->getFormat()->findInt32( 1067 kKeyRotation, &rotationDegrees)) { 1068 rotationDegrees = 0; 1069 } 1070 1071 mVideoRenderer.clear(); 1072 1073 // Must ensure that mVideoRenderer's destructor is actually executed 1074 // before creating a new one. 1075 IPCThreadState::self()->flushCommands(); 1076 1077 if (USE_SURFACE_ALLOC 1078 && !strncmp(component, "OMX.", 4) 1079 && strncmp(component, "OMX.google.", 11)) { 1080 // Hardware decoders avoid the CPU color conversion by decoding 1081 // directly to ANativeBuffers, so we must use a renderer that 1082 // just pushes those buffers to the ANativeWindow. 1083 mVideoRenderer = 1084 new AwesomeNativeWindowRenderer(mNativeWindow, rotationDegrees); 1085 } else { 1086 // Other decoders are instantiated locally and as a consequence 1087 // allocate their buffers in local address space. This renderer 1088 // then performs a color conversion and copy to get the data 1089 // into the ANativeBuffer. 1090 mVideoRenderer = new AwesomeLocalRenderer(mNativeWindow, meta); 1091 } 1092} 1093 1094status_t AwesomePlayer::pause() { 1095 Mutex::Autolock autoLock(mLock); 1096 1097 modifyFlags(CACHE_UNDERRUN, CLEAR); 1098 1099 return pause_l(); 1100} 1101 1102status_t AwesomePlayer::pause_l(bool at_eos) { 1103 if (!(mFlags & PLAYING)) { 1104 return OK; 1105 } 1106 1107 cancelPlayerEvents(true /* keepBufferingGoing */); 1108 1109 if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) { 1110 if (at_eos) { 1111 // If we played the audio stream to completion we 1112 // want to make sure that all samples remaining in the audio 1113 // track's queue are played out. 1114 mAudioPlayer->pause(true /* playPendingSamples */); 1115 } else { 1116 mAudioPlayer->pause(); 1117 } 1118 1119 modifyFlags(AUDIO_RUNNING, CLEAR); 1120 } 1121 1122 if (mFlags & TEXTPLAYER_STARTED) { 1123 mTextPlayer->pause(); 1124 modifyFlags(TEXT_RUNNING, CLEAR); 1125 } 1126 1127 modifyFlags(PLAYING, CLEAR); 1128 1129 if (mDecryptHandle != NULL) { 1130 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, 1131 Playback::PAUSE, 0); 1132 } 1133 1134 uint32_t params = IMediaPlayerService::kBatteryDataTrackDecoder; 1135 if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) { 1136 params |= IMediaPlayerService::kBatteryDataTrackAudio; 1137 } 1138 if (mVideoSource != NULL) { 1139 params |= IMediaPlayerService::kBatteryDataTrackVideo; 1140 } 1141 1142 addBatteryData(params); 1143 1144 return OK; 1145} 1146 1147bool AwesomePlayer::isPlaying() const { 1148 return (mFlags & PLAYING) || (mFlags & CACHE_UNDERRUN); 1149} 1150 1151void AwesomePlayer::setSurface(const sp<Surface> &surface) { 1152 Mutex::Autolock autoLock(mLock); 1153 1154 mSurface = surface; 1155 setNativeWindow_l(surface); 1156} 1157 1158void AwesomePlayer::setSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture) { 1159 Mutex::Autolock autoLock(mLock); 1160 1161 mSurface.clear(); 1162 if (surfaceTexture != NULL) { 1163 setNativeWindow_l(new SurfaceTextureClient(surfaceTexture)); 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 (mVideoRendererIsPreview || mVideoRenderer == NULL) { 1777 mVideoRendererIsPreview = false; 1778 1779 initRenderer_l(); 1780 } 1781 1782 if (mVideoRenderer != NULL) { 1783 mVideoRenderer->render(mVideoBuffer); 1784 } 1785 1786 mVideoBuffer->release(); 1787 mVideoBuffer = NULL; 1788 1789 if (wasSeeking != NO_SEEK && (mFlags & SEEK_PREVIEW)) { 1790 modifyFlags(SEEK_PREVIEW, CLEAR); 1791 return; 1792 } 1793 1794 postVideoEvent_l(); 1795} 1796 1797void AwesomePlayer::postVideoEvent_l(int64_t delayUs) { 1798 if (mVideoEventPending) { 1799 return; 1800 } 1801 1802 mVideoEventPending = true; 1803 mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs); 1804} 1805 1806void AwesomePlayer::postStreamDoneEvent_l(status_t status) { 1807 if (mStreamDoneEventPending) { 1808 return; 1809 } 1810 mStreamDoneEventPending = true; 1811 1812 mStreamDoneStatus = status; 1813 mQueue.postEvent(mStreamDoneEvent); 1814} 1815 1816void AwesomePlayer::postBufferingEvent_l() { 1817 if (mBufferingEventPending) { 1818 return; 1819 } 1820 mBufferingEventPending = true; 1821 mQueue.postEventWithDelay(mBufferingEvent, 1000000ll); 1822} 1823 1824void AwesomePlayer::postVideoLagEvent_l() { 1825 if (mVideoLagEventPending) { 1826 return; 1827 } 1828 mVideoLagEventPending = true; 1829 mQueue.postEventWithDelay(mVideoLagEvent, 1000000ll); 1830} 1831 1832void AwesomePlayer::postCheckAudioStatusEvent_l(int64_t delayUs) { 1833 if (mAudioStatusEventPending) { 1834 return; 1835 } 1836 mAudioStatusEventPending = true; 1837 mQueue.postEventWithDelay(mCheckAudioStatusEvent, delayUs); 1838} 1839 1840void AwesomePlayer::onCheckAudioStatus() { 1841 Mutex::Autolock autoLock(mLock); 1842 if (!mAudioStatusEventPending) { 1843 // Event was dispatched and while we were blocking on the mutex, 1844 // has already been cancelled. 1845 return; 1846 } 1847 1848 mAudioStatusEventPending = false; 1849 1850 if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) { 1851 mWatchForAudioSeekComplete = false; 1852 1853 if (!mSeekNotificationSent) { 1854 notifyListener_l(MEDIA_SEEK_COMPLETE); 1855 mSeekNotificationSent = true; 1856 } 1857 1858 mSeeking = NO_SEEK; 1859 } 1860 1861 status_t finalStatus; 1862 if (mWatchForAudioEOS && mAudioPlayer->reachedEOS(&finalStatus)) { 1863 mWatchForAudioEOS = false; 1864 modifyFlags(AUDIO_AT_EOS, SET); 1865 modifyFlags(FIRST_FRAME, SET); 1866 postStreamDoneEvent_l(finalStatus); 1867 } 1868} 1869 1870status_t AwesomePlayer::prepare() { 1871 Mutex::Autolock autoLock(mLock); 1872 return prepare_l(); 1873} 1874 1875status_t AwesomePlayer::prepare_l() { 1876 if (mFlags & PREPARED) { 1877 return OK; 1878 } 1879 1880 if (mFlags & PREPARING) { 1881 return UNKNOWN_ERROR; 1882 } 1883 1884 mIsAsyncPrepare = false; 1885 status_t err = prepareAsync_l(); 1886 1887 if (err != OK) { 1888 return err; 1889 } 1890 1891 while (mFlags & PREPARING) { 1892 mPreparedCondition.wait(mLock); 1893 } 1894 1895 return mPrepareResult; 1896} 1897 1898status_t AwesomePlayer::prepareAsync() { 1899 Mutex::Autolock autoLock(mLock); 1900 1901 if (mFlags & PREPARING) { 1902 return UNKNOWN_ERROR; // async prepare already pending 1903 } 1904 1905 mIsAsyncPrepare = true; 1906 return prepareAsync_l(); 1907} 1908 1909status_t AwesomePlayer::prepareAsync_l() { 1910 if (mFlags & PREPARING) { 1911 return UNKNOWN_ERROR; // async prepare already pending 1912 } 1913 1914 if (!mQueueStarted) { 1915 mQueue.start(); 1916 mQueueStarted = true; 1917 } 1918 1919 modifyFlags(PREPARING, SET); 1920 mAsyncPrepareEvent = new AwesomeEvent( 1921 this, &AwesomePlayer::onPrepareAsyncEvent); 1922 1923 mQueue.postEvent(mAsyncPrepareEvent); 1924 1925 return OK; 1926} 1927 1928status_t AwesomePlayer::finishSetDataSource_l() { 1929 sp<DataSource> dataSource; 1930 1931 bool isWidevineStreaming = false; 1932 if (!strncasecmp("widevine://", mUri.string(), 11)) { 1933 isWidevineStreaming = true; 1934 1935 String8 newURI = String8("http://"); 1936 newURI.append(mUri.string() + 11); 1937 1938 mUri = newURI; 1939 } 1940 1941 if (!strncasecmp("http://", mUri.string(), 7) 1942 || !strncasecmp("https://", mUri.string(), 8) 1943 || isWidevineStreaming) { 1944 mConnectingDataSource = HTTPBase::Create( 1945 (mFlags & INCOGNITO) 1946 ? HTTPBase::kFlagIncognito 1947 : 0); 1948 1949 if (mUIDValid) { 1950 mConnectingDataSource->setUID(mUID); 1951 } 1952 1953 mLock.unlock(); 1954 status_t err = mConnectingDataSource->connect(mUri, &mUriHeaders); 1955 mLock.lock(); 1956 1957 if (err != OK) { 1958 mConnectingDataSource.clear(); 1959 1960 LOGI("mConnectingDataSource->connect() returned %d", err); 1961 return err; 1962 } 1963 1964 if (!isWidevineStreaming) { 1965 // The widevine extractor does its own caching. 1966 1967#if 0 1968 mCachedSource = new NuCachedSource2( 1969 new ThrottledSource( 1970 mConnectingDataSource, 50 * 1024 /* bytes/sec */)); 1971#else 1972 mCachedSource = new NuCachedSource2(mConnectingDataSource); 1973#endif 1974 1975 dataSource = mCachedSource; 1976 } else { 1977 dataSource = mConnectingDataSource; 1978 } 1979 1980 mConnectingDataSource.clear(); 1981 1982 1983 String8 contentType = dataSource->getMIMEType(); 1984 1985 if (strncasecmp(contentType.string(), "audio/", 6)) { 1986 // We're not doing this for streams that appear to be audio-only 1987 // streams to ensure that even low bandwidth streams start 1988 // playing back fairly instantly. 1989 1990 // We're going to prefill the cache before trying to instantiate 1991 // the extractor below, as the latter is an operation that otherwise 1992 // could block on the datasource for a significant amount of time. 1993 // During that time we'd be unable to abort the preparation phase 1994 // without this prefill. 1995 if (mCachedSource != NULL) { 1996 // We're going to prefill the cache before trying to instantiate 1997 // the extractor below, as the latter is an operation that otherwise 1998 // could block on the datasource for a significant amount of time. 1999 // During that time we'd be unable to abort the preparation phase 2000 // without this prefill. 2001 2002 mLock.unlock(); 2003 2004 for (;;) { 2005 status_t finalStatus; 2006 size_t cachedDataRemaining = 2007 mCachedSource->approxDataRemaining(&finalStatus); 2008 2009 if (finalStatus != OK || cachedDataRemaining >= kHighWaterMarkBytes 2010 || (mFlags & PREPARE_CANCELLED)) { 2011 break; 2012 } 2013 2014 usleep(200000); 2015 } 2016 2017 mLock.lock(); 2018 } 2019 2020 if (mFlags & PREPARE_CANCELLED) { 2021 LOGI("Prepare cancelled while waiting for initial cache fill."); 2022 return UNKNOWN_ERROR; 2023 } 2024 } 2025 } else if (!strncasecmp("rtsp://", mUri.string(), 7)) { 2026 if (mLooper == NULL) { 2027 mLooper = new ALooper; 2028 mLooper->setName("rtsp"); 2029 mLooper->start(); 2030 } 2031 mRTSPController = new ARTSPController(mLooper); 2032 mConnectingRTSPController = mRTSPController; 2033 2034 if (mUIDValid) { 2035 mConnectingRTSPController->setUID(mUID); 2036 } 2037 2038 mLock.unlock(); 2039 status_t err = mRTSPController->connect(mUri.string()); 2040 mLock.lock(); 2041 2042 mConnectingRTSPController.clear(); 2043 2044 LOGI("ARTSPController::connect returned %d", err); 2045 2046 if (err != OK) { 2047 mRTSPController.clear(); 2048 return err; 2049 } 2050 2051 sp<MediaExtractor> extractor = mRTSPController.get(); 2052 return setDataSource_l(extractor); 2053 } else { 2054 dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders); 2055 } 2056 2057 if (dataSource == NULL) { 2058 return UNKNOWN_ERROR; 2059 } 2060 2061 sp<MediaExtractor> extractor; 2062 2063 if (isWidevineStreaming) { 2064 String8 mimeType; 2065 float confidence; 2066 sp<AMessage> dummy; 2067 bool success = SniffDRM(dataSource, &mimeType, &confidence, &dummy); 2068 2069 if (!success 2070 || strcasecmp( 2071 mimeType.string(), MEDIA_MIMETYPE_CONTAINER_WVM)) { 2072 return ERROR_UNSUPPORTED; 2073 } 2074 2075 mWVMExtractor = new WVMExtractor(dataSource); 2076 mWVMExtractor->setAdaptiveStreamingMode(true); 2077 extractor = mWVMExtractor; 2078 } else { 2079 extractor = MediaExtractor::Create(dataSource); 2080 2081 if (extractor == NULL) { 2082 return UNKNOWN_ERROR; 2083 } 2084 } 2085 2086 dataSource->getDrmInfo(mDecryptHandle, &mDrmManagerClient); 2087 2088 if (mDecryptHandle != NULL) { 2089 CHECK(mDrmManagerClient); 2090 if (RightsStatus::RIGHTS_VALID != mDecryptHandle->status) { 2091 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_DRM_NO_LICENSE); 2092 } 2093 } 2094 2095 status_t err = setDataSource_l(extractor); 2096 2097 if (err != OK) { 2098 mWVMExtractor.clear(); 2099 2100 return err; 2101 } 2102 2103 return OK; 2104} 2105 2106void AwesomePlayer::abortPrepare(status_t err) { 2107 CHECK(err != OK); 2108 2109 if (mIsAsyncPrepare) { 2110 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err); 2111 } 2112 2113 mPrepareResult = err; 2114 modifyFlags((PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED), CLEAR); 2115 mAsyncPrepareEvent = NULL; 2116 mPreparedCondition.broadcast(); 2117} 2118 2119// static 2120bool AwesomePlayer::ContinuePreparation(void *cookie) { 2121 AwesomePlayer *me = static_cast<AwesomePlayer *>(cookie); 2122 2123 return (me->mFlags & PREPARE_CANCELLED) == 0; 2124} 2125 2126void AwesomePlayer::onPrepareAsyncEvent() { 2127 Mutex::Autolock autoLock(mLock); 2128 2129 if (mFlags & PREPARE_CANCELLED) { 2130 LOGI("prepare was cancelled before doing anything"); 2131 abortPrepare(UNKNOWN_ERROR); 2132 return; 2133 } 2134 2135 if (mUri.size() > 0) { 2136 status_t err = finishSetDataSource_l(); 2137 2138 if (err != OK) { 2139 abortPrepare(err); 2140 return; 2141 } 2142 } 2143 2144 if (mVideoTrack != NULL && mVideoSource == NULL) { 2145 status_t err = initVideoDecoder(); 2146 2147 if (err != OK) { 2148 abortPrepare(err); 2149 return; 2150 } 2151 } 2152 2153 if (mAudioTrack != NULL && mAudioSource == NULL) { 2154 status_t err = initAudioDecoder(); 2155 2156 if (err != OK) { 2157 abortPrepare(err); 2158 return; 2159 } 2160 } 2161 2162 modifyFlags(PREPARING_CONNECTED, SET); 2163 2164 if (isStreamingHTTP() || mRTSPController != NULL) { 2165 postBufferingEvent_l(); 2166 } else { 2167 finishAsyncPrepare_l(); 2168 } 2169} 2170 2171void AwesomePlayer::finishAsyncPrepare_l() { 2172 if (mIsAsyncPrepare) { 2173 if (mVideoSource == NULL) { 2174 notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0); 2175 } else { 2176 notifyVideoSize_l(); 2177 } 2178 2179 notifyListener_l(MEDIA_PREPARED); 2180 } 2181 2182 mPrepareResult = OK; 2183 modifyFlags((PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED), CLEAR); 2184 modifyFlags(PREPARED, SET); 2185 mAsyncPrepareEvent = NULL; 2186 mPreparedCondition.broadcast(); 2187} 2188 2189uint32_t AwesomePlayer::flags() const { 2190 return mExtractorFlags; 2191} 2192 2193void AwesomePlayer::postAudioEOS(int64_t delayUs) { 2194 Mutex::Autolock autoLock(mLock); 2195 postCheckAudioStatusEvent_l(delayUs); 2196} 2197 2198void AwesomePlayer::postAudioSeekComplete() { 2199 Mutex::Autolock autoLock(mLock); 2200 postAudioSeekComplete_l(); 2201} 2202 2203void AwesomePlayer::postAudioSeekComplete_l() { 2204 postCheckAudioStatusEvent_l(0 /* delayUs */); 2205} 2206 2207status_t AwesomePlayer::setParameter(int key, const Parcel &request) { 2208 switch (key) { 2209 case KEY_PARAMETER_TIMED_TEXT_TRACK_INDEX: 2210 { 2211 Mutex::Autolock autoLock(mTimedTextLock); 2212 return setTimedTextTrackIndex(request.readInt32()); 2213 } 2214 case KEY_PARAMETER_TIMED_TEXT_ADD_OUT_OF_BAND_SOURCE: 2215 { 2216 Mutex::Autolock autoLock(mTimedTextLock); 2217 if (mTextPlayer == NULL) { 2218 mTextPlayer = new TimedTextPlayer(this, mListener, &mQueue); 2219 } 2220 2221 return mTextPlayer->setParameter(key, request); 2222 } 2223 case KEY_PARAMETER_CACHE_STAT_COLLECT_FREQ_MS: 2224 { 2225 return setCacheStatCollectFreq(request); 2226 } 2227 default: 2228 { 2229 return ERROR_UNSUPPORTED; 2230 } 2231 } 2232} 2233 2234status_t AwesomePlayer::setCacheStatCollectFreq(const Parcel &request) { 2235 if (mCachedSource != NULL) { 2236 int32_t freqMs = request.readInt32(); 2237 LOGD("Request to keep cache stats in the past %d ms", 2238 freqMs); 2239 return mCachedSource->setCacheStatCollectFreq(freqMs); 2240 } 2241 return ERROR_UNSUPPORTED; 2242} 2243 2244status_t AwesomePlayer::getParameter(int key, Parcel *reply) { 2245 return OK; 2246} 2247 2248bool AwesomePlayer::isStreamingHTTP() const { 2249 return mCachedSource != NULL || mWVMExtractor != NULL; 2250} 2251 2252status_t AwesomePlayer::dump(int fd, const Vector<String16> &args) const { 2253 Mutex::Autolock autoLock(mStatsLock); 2254 2255 FILE *out = fdopen(dup(fd), "w"); 2256 2257 fprintf(out, " AwesomePlayer\n"); 2258 if (mStats.mFd < 0) { 2259 fprintf(out, " URI(%s)", mStats.mURI.string()); 2260 } else { 2261 fprintf(out, " fd(%d)", mStats.mFd); 2262 } 2263 2264 fprintf(out, ", flags(0x%08x)", mStats.mFlags); 2265 2266 if (mStats.mBitrate >= 0) { 2267 fprintf(out, ", bitrate(%lld bps)", mStats.mBitrate); 2268 } 2269 2270 fprintf(out, "\n"); 2271 2272 for (size_t i = 0; i < mStats.mTracks.size(); ++i) { 2273 const TrackStat &stat = mStats.mTracks.itemAt(i); 2274 2275 fprintf(out, " Track %d\n", i + 1); 2276 fprintf(out, " MIME(%s)", stat.mMIME.string()); 2277 2278 if (!stat.mDecoderName.isEmpty()) { 2279 fprintf(out, ", decoder(%s)", stat.mDecoderName.string()); 2280 } 2281 2282 fprintf(out, "\n"); 2283 2284 if ((ssize_t)i == mStats.mVideoTrackIndex) { 2285 fprintf(out, 2286 " videoDimensions(%d x %d), " 2287 "numVideoFramesDecoded(%lld), " 2288 "numVideoFramesDropped(%lld)\n", 2289 mStats.mVideoWidth, 2290 mStats.mVideoHeight, 2291 mStats.mNumVideoFramesDecoded, 2292 mStats.mNumVideoFramesDropped); 2293 } 2294 } 2295 2296 fclose(out); 2297 out = NULL; 2298 2299 return OK; 2300} 2301 2302void AwesomePlayer::modifyFlags(unsigned value, FlagMode mode) { 2303 switch (mode) { 2304 case SET: 2305 mFlags |= value; 2306 break; 2307 case CLEAR: 2308 mFlags &= ~value; 2309 break; 2310 case ASSIGN: 2311 mFlags = value; 2312 break; 2313 default: 2314 TRESPASS(); 2315 } 2316 2317 { 2318 Mutex::Autolock autoLock(mStatsLock); 2319 mStats.mFlags = mFlags; 2320 } 2321} 2322 2323} // namespace android 2324