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