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