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