AwesomePlayer.cpp revision 908ea6603c64e29e40277a74c9fb0e776c097830
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#define ATRACE_TAG ATRACE_TAG_VIDEO 22#include <inttypes.h> 23#include <utils/Log.h> 24#include <utils/Trace.h> 25 26#include <dlfcn.h> 27 28#include "include/AwesomePlayer.h" 29#include "include/DRMExtractor.h" 30#include "include/SoftwareRenderer.h" 31#include "include/NuCachedSource2.h" 32#include "include/ThrottledSource.h" 33#include "include/MPEG2TSExtractor.h" 34#include "include/WVMExtractor.h" 35 36#include <binder/IPCThreadState.h> 37#include <binder/IServiceManager.h> 38#include <media/IMediaHTTPConnection.h> 39#include <media/IMediaHTTPService.h> 40#include <media/IMediaPlayerService.h> 41#include <media/stagefright/foundation/hexdump.h> 42#include <media/stagefright/foundation/ADebug.h> 43#include <media/stagefright/timedtext/TimedTextDriver.h> 44#include <media/stagefright/AudioPlayer.h> 45#include <media/stagefright/ClockEstimator.h> 46#include <media/stagefright/DataSource.h> 47#include <media/stagefright/FileSource.h> 48#include <media/stagefright/MediaBuffer.h> 49#include <media/stagefright/MediaDefs.h> 50#include <media/stagefright/MediaExtractor.h> 51#include <media/stagefright/MediaHTTP.h> 52#include <media/stagefright/MediaSource.h> 53#include <media/stagefright/MetaData.h> 54#include <media/stagefright/OMXCodec.h> 55#include <media/stagefright/Utils.h> 56 57#include <gui/IGraphicBufferProducer.h> 58#include <gui/Surface.h> 59 60#include <media/stagefright/foundation/AMessage.h> 61 62#include <cutils/properties.h> 63 64#define USE_SURFACE_ALLOC 1 65#define FRAME_DROP_FREQ 0 66 67namespace android { 68 69static int64_t kLowWaterMarkUs = 2000000ll; // 2secs 70static int64_t kHighWaterMarkUs = 5000000ll; // 5secs 71static const size_t kLowWaterMarkBytes = 40000; 72static const size_t kHighWaterMarkBytes = 200000; 73 74// maximum time in paused state when offloading audio decompression. When elapsed, the AudioPlayer 75// is destroyed to allow the audio DSP to power down. 76static int64_t kOffloadPauseMaxUs = 60000000ll; 77 78 79struct AwesomeEvent : public TimedEventQueue::Event { 80 AwesomeEvent( 81 AwesomePlayer *player, 82 void (AwesomePlayer::*method)()) 83 : mPlayer(player), 84 mMethod(method) { 85 } 86 87protected: 88 virtual ~AwesomeEvent() {} 89 90 virtual void fire(TimedEventQueue * /* queue */, int64_t /* now_us */) { 91 (mPlayer->*mMethod)(); 92 } 93 94private: 95 AwesomePlayer *mPlayer; 96 void (AwesomePlayer::*mMethod)(); 97 98 AwesomeEvent(const AwesomeEvent &); 99 AwesomeEvent &operator=(const AwesomeEvent &); 100}; 101 102struct AwesomeLocalRenderer : public AwesomeRenderer { 103 AwesomeLocalRenderer( 104 const sp<ANativeWindow> &nativeWindow, const sp<MetaData> &meta) 105 : mTarget(new SoftwareRenderer(nativeWindow, meta)) { 106 } 107 108 virtual void render(MediaBuffer *buffer) { 109 int64_t timeUs; 110 CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs)); 111 112 render((const uint8_t *)buffer->data() + buffer->range_offset(), 113 buffer->range_length(), timeUs * 1000); 114 } 115 116 void render(const void *data, size_t size, int64_t timestampNs) { 117 mTarget->render(data, size, timestampNs, NULL); 118 } 119 120protected: 121 virtual ~AwesomeLocalRenderer() { 122 delete mTarget; 123 mTarget = NULL; 124 } 125 126private: 127 SoftwareRenderer *mTarget; 128 129 AwesomeLocalRenderer(const AwesomeLocalRenderer &); 130 AwesomeLocalRenderer &operator=(const AwesomeLocalRenderer &);; 131}; 132 133struct AwesomeNativeWindowRenderer : public AwesomeRenderer { 134 AwesomeNativeWindowRenderer( 135 const sp<ANativeWindow> &nativeWindow, 136 int32_t rotationDegrees) 137 : mNativeWindow(nativeWindow) { 138 applyRotation(rotationDegrees); 139 } 140 141 virtual void render(MediaBuffer *buffer) { 142 ATRACE_CALL(); 143 int64_t timeUs; 144 CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs)); 145 native_window_set_buffers_timestamp(mNativeWindow.get(), timeUs * 1000); 146 status_t err = mNativeWindow->queueBuffer( 147 mNativeWindow.get(), buffer->graphicBuffer().get(), -1); 148 if (err != 0) { 149 ALOGE("queueBuffer failed with error %s (%d)", strerror(-err), 150 -err); 151 return; 152 } 153 154 sp<MetaData> metaData = buffer->meta_data(); 155 metaData->setInt32(kKeyRendered, 1); 156 } 157 158protected: 159 virtual ~AwesomeNativeWindowRenderer() {} 160 161private: 162 sp<ANativeWindow> mNativeWindow; 163 164 void applyRotation(int32_t rotationDegrees) { 165 uint32_t transform; 166 switch (rotationDegrees) { 167 case 0: transform = 0; break; 168 case 90: transform = HAL_TRANSFORM_ROT_90; break; 169 case 180: transform = HAL_TRANSFORM_ROT_180; break; 170 case 270: transform = HAL_TRANSFORM_ROT_270; break; 171 default: transform = 0; break; 172 } 173 174 if (transform) { 175 CHECK_EQ(0, native_window_set_buffers_transform( 176 mNativeWindow.get(), transform)); 177 } 178 } 179 180 AwesomeNativeWindowRenderer(const AwesomeNativeWindowRenderer &); 181 AwesomeNativeWindowRenderer &operator=( 182 const AwesomeNativeWindowRenderer &); 183}; 184 185// To collect the decoder usage 186void addBatteryData(uint32_t params) { 187 sp<IBinder> binder = 188 defaultServiceManager()->getService(String16("media.player")); 189 sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder); 190 CHECK(service.get() != NULL); 191 192 service->addBatteryData(params); 193} 194 195//////////////////////////////////////////////////////////////////////////////// 196AwesomePlayer::AwesomePlayer() 197 : mQueueStarted(false), 198 mUIDValid(false), 199 mTimeSource(NULL), 200 mVideoRenderingStarted(false), 201 mVideoRendererIsPreview(false), 202 mMediaRenderingStartGeneration(0), 203 mStartGeneration(0), 204 mAudioPlayer(NULL), 205 mDisplayWidth(0), 206 mDisplayHeight(0), 207 mVideoScalingMode(NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW), 208 mFlags(0), 209 mExtractorFlags(0), 210 mVideoBuffer(NULL), 211 mDecryptHandle(NULL), 212 mLastVideoTimeUs(-1), 213 mTextDriver(NULL), 214 mOffloadAudio(false), 215 mAudioTearDown(false) { 216 CHECK_EQ(mClient.connect(), (status_t)OK); 217 218 DataSource::RegisterDefaultSniffers(); 219 220 mVideoEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoEvent); 221 mVideoEventPending = false; 222 mStreamDoneEvent = new AwesomeEvent(this, &AwesomePlayer::onStreamDone); 223 mStreamDoneEventPending = false; 224 mBufferingEvent = new AwesomeEvent(this, &AwesomePlayer::onBufferingUpdate); 225 mBufferingEventPending = false; 226 mVideoLagEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoLagUpdate); 227 mVideoLagEventPending = false; 228 229 mCheckAudioStatusEvent = new AwesomeEvent( 230 this, &AwesomePlayer::onCheckAudioStatus); 231 232 mAudioStatusEventPending = false; 233 234 mAudioTearDownEvent = new AwesomeEvent(this, 235 &AwesomePlayer::onAudioTearDownEvent); 236 mAudioTearDownEventPending = false; 237 238 mClockEstimator = new WindowedLinearFitEstimator(); 239 240 reset(); 241} 242 243AwesomePlayer::~AwesomePlayer() { 244 if (mQueueStarted) { 245 mQueue.stop(); 246 } 247 248 reset(); 249 250 mClient.disconnect(); 251} 252 253void AwesomePlayer::cancelPlayerEvents(bool keepNotifications) { 254 mQueue.cancelEvent(mVideoEvent->eventID()); 255 mVideoEventPending = false; 256 mQueue.cancelEvent(mVideoLagEvent->eventID()); 257 mVideoLagEventPending = false; 258 259 if (mOffloadAudio) { 260 mQueue.cancelEvent(mAudioTearDownEvent->eventID()); 261 mAudioTearDownEventPending = false; 262 } 263 264 if (!keepNotifications) { 265 mQueue.cancelEvent(mStreamDoneEvent->eventID()); 266 mStreamDoneEventPending = false; 267 mQueue.cancelEvent(mCheckAudioStatusEvent->eventID()); 268 mAudioStatusEventPending = false; 269 270 mQueue.cancelEvent(mBufferingEvent->eventID()); 271 mBufferingEventPending = false; 272 mAudioTearDown = false; 273 } 274} 275 276void AwesomePlayer::setListener(const wp<MediaPlayerBase> &listener) { 277 Mutex::Autolock autoLock(mLock); 278 mListener = listener; 279} 280 281void AwesomePlayer::setUID(uid_t uid) { 282 ALOGV("AwesomePlayer running on behalf of uid %d", uid); 283 284 mUID = uid; 285 mUIDValid = true; 286} 287 288status_t AwesomePlayer::setDataSource( 289 const sp<IMediaHTTPService> &httpService, 290 const char *uri, 291 const KeyedVector<String8, String8> *headers) { 292 Mutex::Autolock autoLock(mLock); 293 return setDataSource_l(httpService, uri, headers); 294} 295 296status_t AwesomePlayer::setDataSource_l( 297 const sp<IMediaHTTPService> &httpService, 298 const char *uri, 299 const KeyedVector<String8, String8> *headers) { 300 reset_l(); 301 302 mHTTPService = httpService; 303 mUri = uri; 304 305 if (headers) { 306 mUriHeaders = *headers; 307 308 ssize_t index = mUriHeaders.indexOfKey(String8("x-hide-urls-from-log")); 309 if (index >= 0) { 310 // Browser is in "incognito" mode, suppress logging URLs. 311 312 // This isn't something that should be passed to the server. 313 mUriHeaders.removeItemsAt(index); 314 315 modifyFlags(INCOGNITO, SET); 316 } 317 } 318 319 ALOGI("setDataSource_l(%s)", uriDebugString(mUri, mFlags & INCOGNITO).c_str()); 320 321 // The actual work will be done during preparation in the call to 322 // ::finishSetDataSource_l to avoid blocking the calling thread in 323 // setDataSource for any significant time. 324 325 { 326 Mutex::Autolock autoLock(mStatsLock); 327 mStats.mFd = -1; 328 mStats.mURI = mUri; 329 } 330 331 return OK; 332} 333 334status_t AwesomePlayer::setDataSource( 335 int fd, int64_t offset, int64_t length) { 336 Mutex::Autolock autoLock(mLock); 337 338 reset_l(); 339 340 sp<DataSource> dataSource = new FileSource(fd, offset, length); 341 342 status_t err = dataSource->initCheck(); 343 344 if (err != OK) { 345 return err; 346 } 347 348 mFileSource = dataSource; 349 350 { 351 Mutex::Autolock autoLock(mStatsLock); 352 mStats.mFd = fd; 353 mStats.mURI = String8(); 354 } 355 356 return setDataSource_l(dataSource); 357} 358 359status_t AwesomePlayer::setDataSource(const sp<IStreamSource> &source) { 360 return INVALID_OPERATION; 361} 362 363status_t AwesomePlayer::setDataSource_l( 364 const sp<DataSource> &dataSource) { 365 sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource); 366 367 if (extractor == NULL) { 368 return UNKNOWN_ERROR; 369 } 370 371 if (extractor->getDrmFlag()) { 372 checkDrmStatus(dataSource); 373 } 374 375 return setDataSource_l(extractor); 376} 377 378void AwesomePlayer::checkDrmStatus(const sp<DataSource>& dataSource) { 379 dataSource->getDrmInfo(mDecryptHandle, &mDrmManagerClient); 380 if (mDecryptHandle != NULL) { 381 CHECK(mDrmManagerClient); 382 if (RightsStatus::RIGHTS_VALID != mDecryptHandle->status) { 383 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_DRM_NO_LICENSE); 384 } 385 } 386} 387 388status_t AwesomePlayer::setDataSource_l(const sp<MediaExtractor> &extractor) { 389 // Attempt to approximate overall stream bitrate by summing all 390 // tracks' individual bitrates, if not all of them advertise bitrate, 391 // we have to fail. 392 393 int64_t totalBitRate = 0; 394 395 mExtractor = extractor; 396 for (size_t i = 0; i < extractor->countTracks(); ++i) { 397 sp<MetaData> meta = extractor->getTrackMetaData(i); 398 399 int32_t bitrate; 400 if (!meta->findInt32(kKeyBitRate, &bitrate)) { 401 const char *mime; 402 CHECK(meta->findCString(kKeyMIMEType, &mime)); 403 ALOGV("track of type '%s' does not publish bitrate", mime); 404 405 totalBitRate = -1; 406 break; 407 } 408 409 totalBitRate += bitrate; 410 } 411 412 mBitrate = totalBitRate; 413 414 ALOGV("mBitrate = %lld bits/sec", mBitrate); 415 416 { 417 Mutex::Autolock autoLock(mStatsLock); 418 mStats.mBitrate = mBitrate; 419 mStats.mTracks.clear(); 420 mStats.mAudioTrackIndex = -1; 421 mStats.mVideoTrackIndex = -1; 422 } 423 424 bool haveAudio = false; 425 bool haveVideo = false; 426 for (size_t i = 0; i < extractor->countTracks(); ++i) { 427 sp<MetaData> meta = extractor->getTrackMetaData(i); 428 429 const char *_mime; 430 CHECK(meta->findCString(kKeyMIMEType, &_mime)); 431 432 String8 mime = String8(_mime); 433 434 if (!haveVideo && !strncasecmp(mime.string(), "video/", 6)) { 435 setVideoSource(extractor->getTrack(i)); 436 haveVideo = true; 437 438 // Set the presentation/display size 439 int32_t displayWidth, displayHeight; 440 bool success = meta->findInt32(kKeyDisplayWidth, &displayWidth); 441 if (success) { 442 success = meta->findInt32(kKeyDisplayHeight, &displayHeight); 443 } 444 if (success) { 445 mDisplayWidth = displayWidth; 446 mDisplayHeight = displayHeight; 447 } 448 449 { 450 Mutex::Autolock autoLock(mStatsLock); 451 mStats.mVideoTrackIndex = mStats.mTracks.size(); 452 mStats.mTracks.push(); 453 TrackStat *stat = 454 &mStats.mTracks.editItemAt(mStats.mVideoTrackIndex); 455 stat->mMIME = mime.string(); 456 } 457 } else if (!haveAudio && !strncasecmp(mime.string(), "audio/", 6)) { 458 setAudioSource(extractor->getTrack(i)); 459 haveAudio = true; 460 mActiveAudioTrackIndex = i; 461 462 { 463 Mutex::Autolock autoLock(mStatsLock); 464 mStats.mAudioTrackIndex = mStats.mTracks.size(); 465 mStats.mTracks.push(); 466 TrackStat *stat = 467 &mStats.mTracks.editItemAt(mStats.mAudioTrackIndex); 468 stat->mMIME = mime.string(); 469 } 470 471 if (!strcasecmp(mime.string(), MEDIA_MIMETYPE_AUDIO_VORBIS)) { 472 // Only do this for vorbis audio, none of the other audio 473 // formats even support this ringtone specific hack and 474 // retrieving the metadata on some extractors may turn out 475 // to be very expensive. 476 sp<MetaData> fileMeta = extractor->getMetaData(); 477 int32_t loop; 478 if (fileMeta != NULL 479 && fileMeta->findInt32(kKeyAutoLoop, &loop) && loop != 0) { 480 modifyFlags(AUTO_LOOPING, SET); 481 } 482 } 483 } else if (!strcasecmp(mime.string(), MEDIA_MIMETYPE_TEXT_3GPP)) { 484 addTextSource_l(i, extractor->getTrack(i)); 485 } 486 } 487 488 if (!haveAudio && !haveVideo) { 489 if (mWVMExtractor != NULL) { 490 return mWVMExtractor->getError(); 491 } else { 492 return UNKNOWN_ERROR; 493 } 494 } 495 496 mExtractorFlags = extractor->flags(); 497 498 return OK; 499} 500 501void AwesomePlayer::reset() { 502 Mutex::Autolock autoLock(mLock); 503 reset_l(); 504} 505 506void AwesomePlayer::reset_l() { 507 mVideoRenderingStarted = false; 508 mActiveAudioTrackIndex = -1; 509 mDisplayWidth = 0; 510 mDisplayHeight = 0; 511 512 notifyListener_l(MEDIA_STOPPED); 513 514 if (mDecryptHandle != NULL) { 515 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, 516 Playback::STOP, 0); 517 mDecryptHandle = NULL; 518 mDrmManagerClient = NULL; 519 } 520 521 if (mFlags & PLAYING) { 522 uint32_t params = IMediaPlayerService::kBatteryDataTrackDecoder; 523 if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) { 524 params |= IMediaPlayerService::kBatteryDataTrackAudio; 525 } 526 if (mVideoSource != NULL) { 527 params |= IMediaPlayerService::kBatteryDataTrackVideo; 528 } 529 addBatteryData(params); 530 } 531 532 if (mFlags & PREPARING) { 533 modifyFlags(PREPARE_CANCELLED, SET); 534 if (mConnectingDataSource != NULL) { 535 ALOGI("interrupting the connection process"); 536 mConnectingDataSource->disconnect(); 537 } 538 539 if (mFlags & PREPARING_CONNECTED) { 540 // We are basically done preparing, we're just buffering 541 // enough data to start playback, we can safely interrupt that. 542 finishAsyncPrepare_l(); 543 } 544 } 545 546 while (mFlags & PREPARING) { 547 mPreparedCondition.wait(mLock); 548 } 549 550 cancelPlayerEvents(); 551 552 mWVMExtractor.clear(); 553 mCachedSource.clear(); 554 mAudioTrack.clear(); 555 mVideoTrack.clear(); 556 mExtractor.clear(); 557 558 // Shutdown audio first, so that the response to the reset request 559 // appears to happen instantaneously as far as the user is concerned 560 // If we did this later, audio would continue playing while we 561 // shutdown the video-related resources and the player appear to 562 // not be as responsive to a reset request. 563 if ((mAudioPlayer == NULL || !(mFlags & AUDIOPLAYER_STARTED)) 564 && mAudioSource != NULL) { 565 // If we had an audio player, it would have effectively 566 // taken possession of the audio source and stopped it when 567 // _it_ is stopped. Otherwise this is still our responsibility. 568 mAudioSource->stop(); 569 } 570 mAudioSource.clear(); 571 mOmxSource.clear(); 572 573 mTimeSource = NULL; 574 575 delete mAudioPlayer; 576 mAudioPlayer = NULL; 577 578 if (mTextDriver != NULL) { 579 delete mTextDriver; 580 mTextDriver = NULL; 581 } 582 583 mVideoRenderer.clear(); 584 585 if (mVideoSource != NULL) { 586 shutdownVideoDecoder_l(); 587 } 588 589 mDurationUs = -1; 590 modifyFlags(0, ASSIGN); 591 mExtractorFlags = 0; 592 mTimeSourceDeltaUs = 0; 593 mVideoTimeUs = 0; 594 595 mSeeking = NO_SEEK; 596 mSeekNotificationSent = true; 597 mSeekTimeUs = 0; 598 599 mHTTPService.clear(); 600 mUri.setTo(""); 601 mUriHeaders.clear(); 602 603 mFileSource.clear(); 604 605 mBitrate = -1; 606 mLastVideoTimeUs = -1; 607 608 { 609 Mutex::Autolock autoLock(mStatsLock); 610 mStats.mFd = -1; 611 mStats.mURI = String8(); 612 mStats.mBitrate = -1; 613 mStats.mAudioTrackIndex = -1; 614 mStats.mVideoTrackIndex = -1; 615 mStats.mNumVideoFramesDecoded = 0; 616 mStats.mNumVideoFramesDropped = 0; 617 mStats.mVideoWidth = -1; 618 mStats.mVideoHeight = -1; 619 mStats.mFlags = 0; 620 mStats.mTracks.clear(); 621 } 622 623 mWatchForAudioSeekComplete = false; 624 mWatchForAudioEOS = false; 625 626 mMediaRenderingStartGeneration = 0; 627 mStartGeneration = 0; 628} 629 630void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) { 631 if ((mListener != NULL) && !mAudioTearDown) { 632 sp<MediaPlayerBase> listener = mListener.promote(); 633 634 if (listener != NULL) { 635 listener->sendEvent(msg, ext1, ext2); 636 } 637 } 638} 639 640bool AwesomePlayer::getBitrate(int64_t *bitrate) { 641 off64_t size; 642 if (mDurationUs > 0 && mCachedSource != NULL 643 && mCachedSource->getSize(&size) == OK) { 644 *bitrate = size * 8000000ll / mDurationUs; // in bits/sec 645 return true; 646 } 647 648 if (mBitrate >= 0) { 649 *bitrate = mBitrate; 650 return true; 651 } 652 653 *bitrate = 0; 654 655 return false; 656} 657 658// Returns true iff cached duration is available/applicable. 659bool AwesomePlayer::getCachedDuration_l(int64_t *durationUs, bool *eos) { 660 int64_t bitrate; 661 662 if (mCachedSource != NULL && getBitrate(&bitrate) && (bitrate > 0)) { 663 status_t finalStatus; 664 size_t cachedDataRemaining = mCachedSource->approxDataRemaining(&finalStatus); 665 *durationUs = cachedDataRemaining * 8000000ll / bitrate; 666 *eos = (finalStatus != OK); 667 return true; 668 } else if (mWVMExtractor != NULL) { 669 status_t finalStatus; 670 *durationUs = mWVMExtractor->getCachedDurationUs(&finalStatus); 671 *eos = (finalStatus != OK); 672 return true; 673 } 674 675 return false; 676} 677 678void AwesomePlayer::ensureCacheIsFetching_l() { 679 if (mCachedSource != NULL) { 680 mCachedSource->resumeFetchingIfNecessary(); 681 } 682} 683 684void AwesomePlayer::onVideoLagUpdate() { 685 Mutex::Autolock autoLock(mLock); 686 if (!mVideoLagEventPending) { 687 return; 688 } 689 mVideoLagEventPending = false; 690 691 int64_t audioTimeUs = mAudioPlayer->getMediaTimeUs(); 692 int64_t videoLateByUs = audioTimeUs - mVideoTimeUs; 693 694 if (!(mFlags & VIDEO_AT_EOS) && videoLateByUs > 300000ll) { 695 ALOGV("video late by %lld ms.", videoLateByUs / 1000ll); 696 697 notifyListener_l( 698 MEDIA_INFO, 699 MEDIA_INFO_VIDEO_TRACK_LAGGING, 700 videoLateByUs / 1000ll); 701 } 702 703 postVideoLagEvent_l(); 704} 705 706void AwesomePlayer::onBufferingUpdate() { 707 Mutex::Autolock autoLock(mLock); 708 if (!mBufferingEventPending) { 709 return; 710 } 711 mBufferingEventPending = false; 712 713 if (mCachedSource != NULL) { 714 status_t finalStatus; 715 size_t cachedDataRemaining = mCachedSource->approxDataRemaining(&finalStatus); 716 bool eos = (finalStatus != OK); 717 718 if (eos) { 719 if (finalStatus == ERROR_END_OF_STREAM) { 720 notifyListener_l(MEDIA_BUFFERING_UPDATE, 100); 721 } 722 if (mFlags & PREPARING) { 723 ALOGV("cache has reached EOS, prepare is done."); 724 finishAsyncPrepare_l(); 725 } 726 } else { 727 bool eos2; 728 int64_t cachedDurationUs; 729 if (getCachedDuration_l(&cachedDurationUs, &eos2) && mDurationUs > 0) { 730 int percentage = 100.0 * (double)cachedDurationUs / mDurationUs; 731 if (percentage > 100) { 732 percentage = 100; 733 } 734 735 notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage); 736 } else { 737 // We don't know the bitrate/duration of the stream, use absolute size 738 // limits to maintain the cache. 739 740 if ((mFlags & PLAYING) && !eos 741 && (cachedDataRemaining < kLowWaterMarkBytes)) { 742 ALOGI("cache is running low (< %zu) , pausing.", 743 kLowWaterMarkBytes); 744 modifyFlags(CACHE_UNDERRUN, SET); 745 pause_l(); 746 ensureCacheIsFetching_l(); 747 sendCacheStats(); 748 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START); 749 } else if (eos || cachedDataRemaining > kHighWaterMarkBytes) { 750 if (mFlags & CACHE_UNDERRUN) { 751 ALOGI("cache has filled up (> %zu), resuming.", 752 kHighWaterMarkBytes); 753 modifyFlags(CACHE_UNDERRUN, CLEAR); 754 play_l(); 755 } else if (mFlags & PREPARING) { 756 ALOGV("cache has filled up (> %zu), prepare is done", 757 kHighWaterMarkBytes); 758 finishAsyncPrepare_l(); 759 } 760 } 761 } 762 } 763 } else if (mWVMExtractor != NULL) { 764 status_t finalStatus; 765 766 int64_t cachedDurationUs 767 = mWVMExtractor->getCachedDurationUs(&finalStatus); 768 769 bool eos = (finalStatus != OK); 770 771 if (eos) { 772 if (finalStatus == ERROR_END_OF_STREAM) { 773 notifyListener_l(MEDIA_BUFFERING_UPDATE, 100); 774 } 775 if (mFlags & PREPARING) { 776 ALOGV("cache has reached EOS, prepare is done."); 777 finishAsyncPrepare_l(); 778 } 779 } else { 780 int percentage = 100.0 * (double)cachedDurationUs / mDurationUs; 781 if (percentage > 100) { 782 percentage = 100; 783 } 784 785 notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage); 786 } 787 } 788 789 int64_t cachedDurationUs; 790 bool eos; 791 if (getCachedDuration_l(&cachedDurationUs, &eos)) { 792 ALOGV("cachedDurationUs = %.2f secs, eos=%d", 793 cachedDurationUs / 1E6, eos); 794 795 if ((mFlags & PLAYING) && !eos 796 && (cachedDurationUs < kLowWaterMarkUs)) { 797 modifyFlags(CACHE_UNDERRUN, SET); 798 ALOGI("cache is running low (%.2f secs) , pausing.", 799 cachedDurationUs / 1E6); 800 pause_l(); 801 ensureCacheIsFetching_l(); 802 sendCacheStats(); 803 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START); 804 } else if (eos || cachedDurationUs > kHighWaterMarkUs) { 805 if (mFlags & CACHE_UNDERRUN) { 806 modifyFlags(CACHE_UNDERRUN, CLEAR); 807 ALOGI("cache has filled up (%.2f secs), resuming.", 808 cachedDurationUs / 1E6); 809 play_l(); 810 } else if (mFlags & PREPARING) { 811 ALOGV("cache has filled up (%.2f secs), prepare is done", 812 cachedDurationUs / 1E6); 813 finishAsyncPrepare_l(); 814 } 815 } 816 } 817 818 if (mFlags & (PLAYING | PREPARING | CACHE_UNDERRUN)) { 819 postBufferingEvent_l(); 820 } 821} 822 823void AwesomePlayer::sendCacheStats() { 824 sp<MediaPlayerBase> listener = mListener.promote(); 825 if (listener != NULL) { 826 int32_t kbps = 0; 827 status_t err = UNKNOWN_ERROR; 828 if (mCachedSource != NULL) { 829 err = mCachedSource->getEstimatedBandwidthKbps(&kbps); 830 } else if (mWVMExtractor != NULL) { 831 err = mWVMExtractor->getEstimatedBandwidthKbps(&kbps); 832 } 833 if (err == OK) { 834 listener->sendEvent( 835 MEDIA_INFO, MEDIA_INFO_NETWORK_BANDWIDTH, kbps); 836 } 837 } 838} 839 840void AwesomePlayer::onStreamDone() { 841 // Posted whenever any stream finishes playing. 842 ATRACE_CALL(); 843 844 Mutex::Autolock autoLock(mLock); 845 if (!mStreamDoneEventPending) { 846 return; 847 } 848 mStreamDoneEventPending = false; 849 850 if (mStreamDoneStatus != ERROR_END_OF_STREAM) { 851 ALOGV("MEDIA_ERROR %d", mStreamDoneStatus); 852 853 notifyListener_l( 854 MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, mStreamDoneStatus); 855 856 pause_l(true /* at eos */); 857 858 modifyFlags(AT_EOS, SET); 859 return; 860 } 861 862 const bool allDone = 863 (mVideoSource == NULL || (mFlags & VIDEO_AT_EOS)) 864 && (mAudioSource == NULL || (mFlags & AUDIO_AT_EOS)); 865 866 if (!allDone) { 867 return; 868 } 869 870 if ((mFlags & LOOPING) 871 || ((mFlags & AUTO_LOOPING) 872 && (mAudioSink == NULL || mAudioSink->realtime()))) { 873 // Don't AUTO_LOOP if we're being recorded, since that cannot be 874 // turned off and recording would go on indefinitely. 875 876 seekTo_l(0); 877 878 if (mVideoSource != NULL) { 879 postVideoEvent_l(); 880 } 881 } else { 882 ALOGV("MEDIA_PLAYBACK_COMPLETE"); 883 notifyListener_l(MEDIA_PLAYBACK_COMPLETE); 884 885 pause_l(true /* at eos */); 886 887 // If audio hasn't completed MEDIA_SEEK_COMPLETE yet, 888 // notify MEDIA_SEEK_COMPLETE to observer immediately for state persistence. 889 if (mWatchForAudioSeekComplete) { 890 notifyListener_l(MEDIA_SEEK_COMPLETE); 891 mWatchForAudioSeekComplete = false; 892 } 893 894 modifyFlags(AT_EOS, SET); 895 } 896} 897 898status_t AwesomePlayer::play() { 899 ATRACE_CALL(); 900 901 Mutex::Autolock autoLock(mLock); 902 903 modifyFlags(CACHE_UNDERRUN, CLEAR); 904 905 return play_l(); 906} 907 908status_t AwesomePlayer::play_l() { 909 modifyFlags(SEEK_PREVIEW, CLEAR); 910 911 if (mFlags & PLAYING) { 912 return OK; 913 } 914 915 mMediaRenderingStartGeneration = ++mStartGeneration; 916 917 if (!(mFlags & PREPARED)) { 918 status_t err = prepare_l(); 919 920 if (err != OK) { 921 return err; 922 } 923 } 924 925 modifyFlags(PLAYING, SET); 926 modifyFlags(FIRST_FRAME, SET); 927 928 if (mDecryptHandle != NULL) { 929 int64_t position; 930 getPosition(&position); 931 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, 932 Playback::START, position / 1000); 933 } 934 935 if (mAudioSource != NULL) { 936 if (mAudioPlayer == NULL) { 937 createAudioPlayer_l(); 938 } 939 940 CHECK(!(mFlags & AUDIO_RUNNING)); 941 942 if (mVideoSource == NULL) { 943 944 // We don't want to post an error notification at this point, 945 // the error returned from MediaPlayer::start() will suffice. 946 947 status_t err = startAudioPlayer_l( 948 false /* sendErrorNotification */); 949 950 if ((err != OK) && mOffloadAudio) { 951 ALOGI("play_l() cannot create offload output, fallback to sw decode"); 952 int64_t curTimeUs; 953 getPosition(&curTimeUs); 954 955 delete mAudioPlayer; 956 mAudioPlayer = NULL; 957 // if the player was started it will take care of stopping the source when destroyed 958 if (!(mFlags & AUDIOPLAYER_STARTED)) { 959 mAudioSource->stop(); 960 } 961 modifyFlags((AUDIO_RUNNING | AUDIOPLAYER_STARTED), CLEAR); 962 mOffloadAudio = false; 963 mAudioSource = mOmxSource; 964 if (mAudioSource != NULL) { 965 err = mAudioSource->start(); 966 967 if (err != OK) { 968 mAudioSource.clear(); 969 } else { 970 mSeekNotificationSent = true; 971 if (mExtractorFlags & MediaExtractor::CAN_SEEK) { 972 seekTo_l(curTimeUs); 973 } 974 createAudioPlayer_l(); 975 err = startAudioPlayer_l(false); 976 } 977 } 978 } 979 980 if (err != OK) { 981 delete mAudioPlayer; 982 mAudioPlayer = NULL; 983 984 modifyFlags((PLAYING | FIRST_FRAME), CLEAR); 985 986 if (mDecryptHandle != NULL) { 987 mDrmManagerClient->setPlaybackStatus( 988 mDecryptHandle, Playback::STOP, 0); 989 } 990 991 return err; 992 } 993 } 994 } 995 996 if (mTimeSource == NULL && mAudioPlayer == NULL) { 997 mTimeSource = &mSystemTimeSource; 998 } 999 1000 if (mVideoSource != NULL) { 1001 // Kick off video playback 1002 postVideoEvent_l(); 1003 1004 if (mAudioSource != NULL && mVideoSource != NULL) { 1005 postVideoLagEvent_l(); 1006 } 1007 } 1008 1009 if (mFlags & AT_EOS) { 1010 // Legacy behaviour, if a stream finishes playing and then 1011 // is started again, we play from the start... 1012 seekTo_l(0); 1013 } 1014 1015 uint32_t params = IMediaPlayerService::kBatteryDataCodecStarted 1016 | IMediaPlayerService::kBatteryDataTrackDecoder; 1017 if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) { 1018 params |= IMediaPlayerService::kBatteryDataTrackAudio; 1019 } 1020 if (mVideoSource != NULL) { 1021 params |= IMediaPlayerService::kBatteryDataTrackVideo; 1022 } 1023 addBatteryData(params); 1024 1025 if (isStreamingHTTP()) { 1026 postBufferingEvent_l(); 1027 } 1028 1029 return OK; 1030} 1031 1032void AwesomePlayer::createAudioPlayer_l() 1033{ 1034 uint32_t flags = 0; 1035 int64_t cachedDurationUs; 1036 bool eos; 1037 1038 if (mOffloadAudio) { 1039 flags |= AudioPlayer::USE_OFFLOAD; 1040 } else if (mVideoSource == NULL 1041 && (mDurationUs > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US || 1042 (getCachedDuration_l(&cachedDurationUs, &eos) && 1043 cachedDurationUs > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US))) { 1044 flags |= AudioPlayer::ALLOW_DEEP_BUFFERING; 1045 } 1046 if (isStreamingHTTP()) { 1047 flags |= AudioPlayer::IS_STREAMING; 1048 } 1049 if (mVideoSource != NULL) { 1050 flags |= AudioPlayer::HAS_VIDEO; 1051 } 1052 1053 mAudioPlayer = new AudioPlayer(mAudioSink, flags, this); 1054 mAudioPlayer->setSource(mAudioSource); 1055 1056 mTimeSource = mAudioPlayer; 1057 1058 // If there was a seek request before we ever started, 1059 // honor the request now. 1060 // Make sure to do this before starting the audio player 1061 // to avoid a race condition. 1062 seekAudioIfNecessary_l(); 1063} 1064 1065void AwesomePlayer::notifyIfMediaStarted_l() { 1066 if (mMediaRenderingStartGeneration == mStartGeneration) { 1067 mMediaRenderingStartGeneration = -1; 1068 notifyListener_l(MEDIA_STARTED); 1069 } 1070} 1071 1072status_t AwesomePlayer::startAudioPlayer_l(bool sendErrorNotification) { 1073 CHECK(!(mFlags & AUDIO_RUNNING)); 1074 status_t err = OK; 1075 1076 if (mAudioSource == NULL || mAudioPlayer == NULL) { 1077 return OK; 1078 } 1079 1080 if (mOffloadAudio) { 1081 mQueue.cancelEvent(mAudioTearDownEvent->eventID()); 1082 mAudioTearDownEventPending = false; 1083 } 1084 1085 if (!(mFlags & AUDIOPLAYER_STARTED)) { 1086 bool wasSeeking = mAudioPlayer->isSeeking(); 1087 1088 // We've already started the MediaSource in order to enable 1089 // the prefetcher to read its data. 1090 err = mAudioPlayer->start( 1091 true /* sourceAlreadyStarted */); 1092 1093 if (err != OK) { 1094 if (sendErrorNotification) { 1095 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err); 1096 } 1097 1098 return err; 1099 } 1100 1101 modifyFlags(AUDIOPLAYER_STARTED, SET); 1102 1103 if (wasSeeking) { 1104 CHECK(!mAudioPlayer->isSeeking()); 1105 1106 // We will have finished the seek while starting the audio player. 1107 postAudioSeekComplete(); 1108 } else { 1109 notifyIfMediaStarted_l(); 1110 } 1111 } else { 1112 err = mAudioPlayer->resume(); 1113 } 1114 1115 if (err == OK) { 1116 modifyFlags(AUDIO_RUNNING, SET); 1117 1118 mWatchForAudioEOS = true; 1119 } 1120 1121 return err; 1122} 1123 1124void AwesomePlayer::notifyVideoSize_l() { 1125 ATRACE_CALL(); 1126 sp<MetaData> meta = mVideoSource->getFormat(); 1127 1128 int32_t cropLeft, cropTop, cropRight, cropBottom; 1129 if (!meta->findRect( 1130 kKeyCropRect, &cropLeft, &cropTop, &cropRight, &cropBottom)) { 1131 int32_t width, height; 1132 CHECK(meta->findInt32(kKeyWidth, &width)); 1133 CHECK(meta->findInt32(kKeyHeight, &height)); 1134 1135 cropLeft = cropTop = 0; 1136 cropRight = width - 1; 1137 cropBottom = height - 1; 1138 1139 ALOGV("got dimensions only %d x %d", width, height); 1140 } else { 1141 ALOGV("got crop rect %d, %d, %d, %d", 1142 cropLeft, cropTop, cropRight, cropBottom); 1143 } 1144 1145 int32_t displayWidth; 1146 if (meta->findInt32(kKeyDisplayWidth, &displayWidth)) { 1147 ALOGV("Display width changed (%d=>%d)", mDisplayWidth, displayWidth); 1148 mDisplayWidth = displayWidth; 1149 } 1150 int32_t displayHeight; 1151 if (meta->findInt32(kKeyDisplayHeight, &displayHeight)) { 1152 ALOGV("Display height changed (%d=>%d)", mDisplayHeight, displayHeight); 1153 mDisplayHeight = displayHeight; 1154 } 1155 1156 int32_t usableWidth = cropRight - cropLeft + 1; 1157 int32_t usableHeight = cropBottom - cropTop + 1; 1158 if (mDisplayWidth != 0) { 1159 usableWidth = mDisplayWidth; 1160 } 1161 if (mDisplayHeight != 0) { 1162 usableHeight = mDisplayHeight; 1163 } 1164 1165 { 1166 Mutex::Autolock autoLock(mStatsLock); 1167 mStats.mVideoWidth = usableWidth; 1168 mStats.mVideoHeight = usableHeight; 1169 } 1170 1171 int32_t rotationDegrees; 1172 if (!mVideoTrack->getFormat()->findInt32( 1173 kKeyRotation, &rotationDegrees)) { 1174 rotationDegrees = 0; 1175 } 1176 1177 if (rotationDegrees == 90 || rotationDegrees == 270) { 1178 notifyListener_l( 1179 MEDIA_SET_VIDEO_SIZE, usableHeight, usableWidth); 1180 } else { 1181 notifyListener_l( 1182 MEDIA_SET_VIDEO_SIZE, usableWidth, usableHeight); 1183 } 1184} 1185 1186void AwesomePlayer::initRenderer_l() { 1187 ATRACE_CALL(); 1188 1189 if (mNativeWindow == NULL) { 1190 return; 1191 } 1192 1193 sp<MetaData> meta = mVideoSource->getFormat(); 1194 1195 int32_t format; 1196 const char *component; 1197 int32_t decodedWidth, decodedHeight; 1198 CHECK(meta->findInt32(kKeyColorFormat, &format)); 1199 CHECK(meta->findCString(kKeyDecoderComponent, &component)); 1200 CHECK(meta->findInt32(kKeyWidth, &decodedWidth)); 1201 CHECK(meta->findInt32(kKeyHeight, &decodedHeight)); 1202 1203 int32_t rotationDegrees; 1204 if (!mVideoTrack->getFormat()->findInt32( 1205 kKeyRotation, &rotationDegrees)) { 1206 rotationDegrees = 0; 1207 } 1208 1209 mVideoRenderer.clear(); 1210 1211 // Must ensure that mVideoRenderer's destructor is actually executed 1212 // before creating a new one. 1213 IPCThreadState::self()->flushCommands(); 1214 1215 // Even if set scaling mode fails, we will continue anyway 1216 setVideoScalingMode_l(mVideoScalingMode); 1217 if (USE_SURFACE_ALLOC 1218 && !strncmp(component, "OMX.", 4) 1219 && strncmp(component, "OMX.google.", 11)) { 1220 // Hardware decoders avoid the CPU color conversion by decoding 1221 // directly to ANativeBuffers, so we must use a renderer that 1222 // just pushes those buffers to the ANativeWindow. 1223 mVideoRenderer = 1224 new AwesomeNativeWindowRenderer(mNativeWindow, rotationDegrees); 1225 } else { 1226 // Other decoders are instantiated locally and as a consequence 1227 // allocate their buffers in local address space. This renderer 1228 // then performs a color conversion and copy to get the data 1229 // into the ANativeBuffer. 1230 mVideoRenderer = new AwesomeLocalRenderer(mNativeWindow, meta); 1231 } 1232} 1233 1234status_t AwesomePlayer::pause() { 1235 ATRACE_CALL(); 1236 1237 Mutex::Autolock autoLock(mLock); 1238 1239 modifyFlags(CACHE_UNDERRUN, CLEAR); 1240 1241 return pause_l(); 1242} 1243 1244status_t AwesomePlayer::pause_l(bool at_eos) { 1245 if (!(mFlags & PLAYING)) { 1246 if (mAudioTearDown && mAudioTearDownWasPlaying) { 1247 ALOGV("pause_l() during teardown and finishSetDataSource_l() mFlags %x" , mFlags); 1248 mAudioTearDownWasPlaying = false; 1249 notifyListener_l(MEDIA_PAUSED); 1250 mMediaRenderingStartGeneration = ++mStartGeneration; 1251 } 1252 return OK; 1253 } 1254 1255 notifyListener_l(MEDIA_PAUSED); 1256 mMediaRenderingStartGeneration = ++mStartGeneration; 1257 1258 cancelPlayerEvents(true /* keepNotifications */); 1259 1260 if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) { 1261 // If we played the audio stream to completion we 1262 // want to make sure that all samples remaining in the audio 1263 // track's queue are played out. 1264 mAudioPlayer->pause(at_eos /* playPendingSamples */); 1265 // send us a reminder to tear down the AudioPlayer if paused for too long. 1266 if (mOffloadAudio) { 1267 postAudioTearDownEvent(kOffloadPauseMaxUs); 1268 } 1269 modifyFlags(AUDIO_RUNNING, CLEAR); 1270 } 1271 1272 if (mFlags & TEXTPLAYER_INITIALIZED) { 1273 mTextDriver->pause(); 1274 modifyFlags(TEXT_RUNNING, CLEAR); 1275 } 1276 1277 modifyFlags(PLAYING, CLEAR); 1278 1279 if (mDecryptHandle != NULL) { 1280 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, 1281 Playback::PAUSE, 0); 1282 } 1283 1284 uint32_t params = IMediaPlayerService::kBatteryDataTrackDecoder; 1285 if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) { 1286 params |= IMediaPlayerService::kBatteryDataTrackAudio; 1287 } 1288 if (mVideoSource != NULL) { 1289 params |= IMediaPlayerService::kBatteryDataTrackVideo; 1290 } 1291 1292 addBatteryData(params); 1293 1294 return OK; 1295} 1296 1297bool AwesomePlayer::isPlaying() const { 1298 return (mFlags & PLAYING) || (mFlags & CACHE_UNDERRUN); 1299} 1300 1301status_t AwesomePlayer::setSurfaceTexture(const sp<IGraphicBufferProducer> &bufferProducer) { 1302 Mutex::Autolock autoLock(mLock); 1303 1304 status_t err; 1305 if (bufferProducer != NULL) { 1306 err = setNativeWindow_l(new Surface(bufferProducer)); 1307 } else { 1308 err = setNativeWindow_l(NULL); 1309 } 1310 1311 return err; 1312} 1313 1314void AwesomePlayer::shutdownVideoDecoder_l() { 1315 if (mVideoBuffer) { 1316 mVideoBuffer->release(); 1317 mVideoBuffer = NULL; 1318 } 1319 1320 mVideoSource->stop(); 1321 1322 // The following hack is necessary to ensure that the OMX 1323 // component is completely released by the time we may try 1324 // to instantiate it again. 1325 wp<MediaSource> tmp = mVideoSource; 1326 mVideoSource.clear(); 1327 while (tmp.promote() != NULL) { 1328 usleep(1000); 1329 } 1330 IPCThreadState::self()->flushCommands(); 1331 ALOGV("video decoder shutdown completed"); 1332} 1333 1334status_t AwesomePlayer::setNativeWindow_l(const sp<ANativeWindow> &native) { 1335 mNativeWindow = native; 1336 1337 if (mVideoSource == NULL) { 1338 return OK; 1339 } 1340 1341 ALOGV("attempting to reconfigure to use new surface"); 1342 1343 bool wasPlaying = (mFlags & PLAYING) != 0; 1344 1345 pause_l(); 1346 mVideoRenderer.clear(); 1347 1348 shutdownVideoDecoder_l(); 1349 1350 status_t err = initVideoDecoder(); 1351 1352 if (err != OK) { 1353 ALOGE("failed to reinstantiate video decoder after surface change."); 1354 return err; 1355 } 1356 1357 if (mLastVideoTimeUs >= 0) { 1358 mSeeking = SEEK; 1359 mSeekTimeUs = mLastVideoTimeUs; 1360 modifyFlags((AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS), CLEAR); 1361 } 1362 1363 if (wasPlaying) { 1364 play_l(); 1365 } 1366 1367 return OK; 1368} 1369 1370void AwesomePlayer::setAudioSink( 1371 const sp<MediaPlayerBase::AudioSink> &audioSink) { 1372 Mutex::Autolock autoLock(mLock); 1373 1374 mAudioSink = audioSink; 1375} 1376 1377status_t AwesomePlayer::setLooping(bool shouldLoop) { 1378 Mutex::Autolock autoLock(mLock); 1379 1380 modifyFlags(LOOPING, CLEAR); 1381 1382 if (shouldLoop) { 1383 modifyFlags(LOOPING, SET); 1384 } 1385 1386 return OK; 1387} 1388 1389status_t AwesomePlayer::getDuration(int64_t *durationUs) { 1390 Mutex::Autolock autoLock(mMiscStateLock); 1391 1392 if (mDurationUs < 0) { 1393 return UNKNOWN_ERROR; 1394 } 1395 1396 *durationUs = mDurationUs; 1397 1398 return OK; 1399} 1400 1401status_t AwesomePlayer::getPosition(int64_t *positionUs) { 1402 if (mSeeking != NO_SEEK) { 1403 *positionUs = mSeekTimeUs; 1404 } else if (mVideoSource != NULL 1405 && (mAudioPlayer == NULL || !(mFlags & VIDEO_AT_EOS))) { 1406 Mutex::Autolock autoLock(mMiscStateLock); 1407 *positionUs = mVideoTimeUs; 1408 } else if (mAudioPlayer != NULL) { 1409 *positionUs = mAudioPlayer->getMediaTimeUs(); 1410 } else { 1411 *positionUs = 0; 1412 } 1413 return OK; 1414} 1415 1416status_t AwesomePlayer::seekTo(int64_t timeUs) { 1417 ATRACE_CALL(); 1418 1419 if (mExtractorFlags & MediaExtractor::CAN_SEEK) { 1420 Mutex::Autolock autoLock(mLock); 1421 return seekTo_l(timeUs); 1422 } 1423 1424 return OK; 1425} 1426 1427status_t AwesomePlayer::seekTo_l(int64_t timeUs) { 1428 if (mFlags & CACHE_UNDERRUN) { 1429 modifyFlags(CACHE_UNDERRUN, CLEAR); 1430 play_l(); 1431 } 1432 1433 if ((mFlags & PLAYING) && mVideoSource != NULL && (mFlags & VIDEO_AT_EOS)) { 1434 // Video playback completed before, there's no pending 1435 // video event right now. In order for this new seek 1436 // to be honored, we need to post one. 1437 1438 postVideoEvent_l(); 1439 } 1440 1441 mSeeking = SEEK; 1442 mSeekNotificationSent = false; 1443 mSeekTimeUs = timeUs; 1444 modifyFlags((AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS), CLEAR); 1445 1446 if (mFlags & PLAYING) { 1447 notifyListener_l(MEDIA_PAUSED); 1448 mMediaRenderingStartGeneration = ++mStartGeneration; 1449 } 1450 1451 seekAudioIfNecessary_l(); 1452 1453 if (mFlags & TEXTPLAYER_INITIALIZED) { 1454 mTextDriver->seekToAsync(mSeekTimeUs); 1455 } 1456 1457 if (!(mFlags & PLAYING)) { 1458 ALOGV("seeking while paused, sending SEEK_COMPLETE notification" 1459 " immediately."); 1460 1461 notifyListener_l(MEDIA_SEEK_COMPLETE); 1462 mSeekNotificationSent = true; 1463 1464 if ((mFlags & PREPARED) && mVideoSource != NULL) { 1465 modifyFlags(SEEK_PREVIEW, SET); 1466 postVideoEvent_l(); 1467 } 1468 } 1469 1470 return OK; 1471} 1472 1473void AwesomePlayer::seekAudioIfNecessary_l() { 1474 if (mSeeking != NO_SEEK && mVideoSource == NULL && mAudioPlayer != NULL) { 1475 mAudioPlayer->seekTo(mSeekTimeUs); 1476 1477 mWatchForAudioSeekComplete = true; 1478 mWatchForAudioEOS = true; 1479 1480 if (mDecryptHandle != NULL) { 1481 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, 1482 Playback::PAUSE, 0); 1483 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, 1484 Playback::START, mSeekTimeUs / 1000); 1485 } 1486 } 1487} 1488 1489void AwesomePlayer::setAudioSource(sp<MediaSource> source) { 1490 CHECK(source != NULL); 1491 1492 mAudioTrack = source; 1493} 1494 1495void AwesomePlayer::addTextSource_l(size_t trackIndex, const sp<MediaSource>& source) { 1496 CHECK(source != NULL); 1497 1498 if (mTextDriver == NULL) { 1499 mTextDriver = new TimedTextDriver(mListener, mHTTPService); 1500 } 1501 1502 mTextDriver->addInBandTextSource(trackIndex, source); 1503} 1504 1505status_t AwesomePlayer::initAudioDecoder() { 1506 ATRACE_CALL(); 1507 1508 sp<MetaData> meta = mAudioTrack->getFormat(); 1509 1510 const char *mime; 1511 CHECK(meta->findCString(kKeyMIMEType, &mime)); 1512 // Check whether there is a hardware codec for this stream 1513 // This doesn't guarantee that the hardware has a free stream 1514 // but it avoids us attempting to open (and re-open) an offload 1515 // stream to hardware that doesn't have the necessary codec 1516 audio_stream_type_t streamType = AUDIO_STREAM_MUSIC; 1517 if (mAudioSink != NULL) { 1518 streamType = mAudioSink->getAudioStreamType(); 1519 } 1520 1521 mOffloadAudio = canOffloadStream(meta, (mVideoSource != NULL), 1522 isStreamingHTTP(), streamType); 1523 1524 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) { 1525 ALOGV("createAudioPlayer: bypass OMX (raw)"); 1526 mAudioSource = mAudioTrack; 1527 } else { 1528 // If offloading we still create a OMX decoder as a fall-back 1529 // but we don't start it 1530 mOmxSource = OMXCodec::Create( 1531 mClient.interface(), mAudioTrack->getFormat(), 1532 false, // createEncoder 1533 mAudioTrack); 1534 1535 if (mOffloadAudio) { 1536 ALOGV("createAudioPlayer: bypass OMX (offload)"); 1537 mAudioSource = mAudioTrack; 1538 } else { 1539 mAudioSource = mOmxSource; 1540 } 1541 } 1542 1543 if (mAudioSource != NULL) { 1544 int64_t durationUs; 1545 if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) { 1546 Mutex::Autolock autoLock(mMiscStateLock); 1547 if (mDurationUs < 0 || durationUs > mDurationUs) { 1548 mDurationUs = durationUs; 1549 } 1550 } 1551 1552 status_t err = mAudioSource->start(); 1553 1554 if (err != OK) { 1555 mAudioSource.clear(); 1556 mOmxSource.clear(); 1557 return err; 1558 } 1559 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_QCELP)) { 1560 // For legacy reasons we're simply going to ignore the absence 1561 // of an audio decoder for QCELP instead of aborting playback 1562 // altogether. 1563 return OK; 1564 } 1565 1566 if (mAudioSource != NULL) { 1567 Mutex::Autolock autoLock(mStatsLock); 1568 TrackStat *stat = &mStats.mTracks.editItemAt(mStats.mAudioTrackIndex); 1569 const char *component; 1570 if (!mAudioSource->getFormat() 1571 ->findCString(kKeyDecoderComponent, &component)) { 1572 component = "none"; 1573 } 1574 1575 stat->mDecoderName = component; 1576 } 1577 1578 return mAudioSource != NULL ? OK : UNKNOWN_ERROR; 1579} 1580 1581void AwesomePlayer::setVideoSource(sp<MediaSource> source) { 1582 CHECK(source != NULL); 1583 1584 mVideoTrack = source; 1585} 1586 1587status_t AwesomePlayer::initVideoDecoder(uint32_t flags) { 1588 ATRACE_CALL(); 1589 1590 // Either the application or the DRM system can independently say 1591 // that there must be a hardware-protected path to an external video sink. 1592 // For now we always require a hardware-protected path to external video sink 1593 // if content is DRMed, but eventually this could be optional per DRM agent. 1594 // When the application wants protection, then 1595 // (USE_SURFACE_ALLOC && (mSurface != 0) && 1596 // (mSurface->getFlags() & ISurfaceComposer::eProtectedByApp)) 1597 // will be true, but that part is already handled by SurfaceFlinger. 1598 1599#ifdef DEBUG_HDCP 1600 // For debugging, we allow a system property to control the protected usage. 1601 // In case of uninitialized or unexpected property, we default to "DRM only". 1602 bool setProtectionBit = false; 1603 char value[PROPERTY_VALUE_MAX]; 1604 if (property_get("persist.sys.hdcp_checking", value, NULL)) { 1605 if (!strcmp(value, "never")) { 1606 // nop 1607 } else if (!strcmp(value, "always")) { 1608 setProtectionBit = true; 1609 } else if (!strcmp(value, "drm-only")) { 1610 if (mDecryptHandle != NULL) { 1611 setProtectionBit = true; 1612 } 1613 // property value is empty, or unexpected value 1614 } else { 1615 if (mDecryptHandle != NULL) { 1616 setProtectionBit = true; 1617 } 1618 } 1619 // can' read property value 1620 } else { 1621 if (mDecryptHandle != NULL) { 1622 setProtectionBit = true; 1623 } 1624 } 1625 // note that usage bit is already cleared, so no need to clear it in the "else" case 1626 if (setProtectionBit) { 1627 flags |= OMXCodec::kEnableGrallocUsageProtected; 1628 } 1629#else 1630 if (mDecryptHandle != NULL) { 1631 flags |= OMXCodec::kEnableGrallocUsageProtected; 1632 } 1633#endif 1634 ALOGV("initVideoDecoder flags=0x%x", flags); 1635 mVideoSource = OMXCodec::Create( 1636 mClient.interface(), mVideoTrack->getFormat(), 1637 false, // createEncoder 1638 mVideoTrack, 1639 NULL, flags, USE_SURFACE_ALLOC ? mNativeWindow : NULL); 1640 1641 if (mVideoSource != NULL) { 1642 int64_t durationUs; 1643 if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) { 1644 Mutex::Autolock autoLock(mMiscStateLock); 1645 if (mDurationUs < 0 || durationUs > mDurationUs) { 1646 mDurationUs = durationUs; 1647 } 1648 } 1649 1650 status_t err = mVideoSource->start(); 1651 1652 if (err != OK) { 1653 ALOGE("failed to start video source"); 1654 mVideoSource.clear(); 1655 return err; 1656 } 1657 } 1658 1659 if (mVideoSource != NULL) { 1660 const char *componentName; 1661 CHECK(mVideoSource->getFormat() 1662 ->findCString(kKeyDecoderComponent, &componentName)); 1663 1664 { 1665 Mutex::Autolock autoLock(mStatsLock); 1666 TrackStat *stat = &mStats.mTracks.editItemAt(mStats.mVideoTrackIndex); 1667 1668 stat->mDecoderName = componentName; 1669 } 1670 1671 static const char *kPrefix = "OMX.Nvidia."; 1672 static const char *kSuffix = ".decode"; 1673 static const size_t kSuffixLength = strlen(kSuffix); 1674 1675 size_t componentNameLength = strlen(componentName); 1676 1677 if (!strncmp(componentName, kPrefix, strlen(kPrefix)) 1678 && componentNameLength >= kSuffixLength 1679 && !strcmp(&componentName[ 1680 componentNameLength - kSuffixLength], kSuffix)) { 1681 modifyFlags(SLOW_DECODER_HACK, SET); 1682 } 1683 } 1684 1685 return mVideoSource != NULL ? OK : UNKNOWN_ERROR; 1686} 1687 1688void AwesomePlayer::finishSeekIfNecessary(int64_t videoTimeUs) { 1689 ATRACE_CALL(); 1690 1691 if (mSeeking == SEEK_VIDEO_ONLY) { 1692 mSeeking = NO_SEEK; 1693 return; 1694 } 1695 1696 if (mSeeking == NO_SEEK || (mFlags & SEEK_PREVIEW)) { 1697 return; 1698 } 1699 1700 // If we paused, then seeked, then resumed, it is possible that we have 1701 // signaled SEEK_COMPLETE at a copmletely different media time than where 1702 // we are now resuming. Signal new position to media time provider. 1703 // Cannot signal another SEEK_COMPLETE, as existing clients may not expect 1704 // multiple SEEK_COMPLETE responses to a single seek() request. 1705 if (mSeekNotificationSent && abs(mSeekTimeUs - videoTimeUs) > 10000) { 1706 // notify if we are resuming more than 10ms away from desired seek time 1707 notifyListener_l(MEDIA_SKIPPED); 1708 } 1709 1710 if (mAudioPlayer != NULL) { 1711 ALOGV("seeking audio to %lld us (%.2f secs).", videoTimeUs, videoTimeUs / 1E6); 1712 1713 // If we don't have a video time, seek audio to the originally 1714 // requested seek time instead. 1715 1716 mAudioPlayer->seekTo(videoTimeUs < 0 ? mSeekTimeUs : videoTimeUs); 1717 mWatchForAudioSeekComplete = true; 1718 mWatchForAudioEOS = true; 1719 } else if (!mSeekNotificationSent) { 1720 // If we're playing video only, report seek complete now, 1721 // otherwise audio player will notify us later. 1722 notifyListener_l(MEDIA_SEEK_COMPLETE); 1723 mSeekNotificationSent = true; 1724 } 1725 1726 modifyFlags(FIRST_FRAME, SET); 1727 mSeeking = NO_SEEK; 1728 1729 if (mDecryptHandle != NULL) { 1730 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, 1731 Playback::PAUSE, 0); 1732 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, 1733 Playback::START, videoTimeUs / 1000); 1734 } 1735} 1736 1737void AwesomePlayer::onVideoEvent() { 1738 ATRACE_CALL(); 1739 Mutex::Autolock autoLock(mLock); 1740 if (!mVideoEventPending) { 1741 // The event has been cancelled in reset_l() but had already 1742 // been scheduled for execution at that time. 1743 return; 1744 } 1745 mVideoEventPending = false; 1746 1747 if (mSeeking != NO_SEEK) { 1748 if (mVideoBuffer) { 1749 mVideoBuffer->release(); 1750 mVideoBuffer = NULL; 1751 } 1752 1753 if (mSeeking == SEEK && isStreamingHTTP() && mAudioSource != NULL 1754 && !(mFlags & SEEK_PREVIEW)) { 1755 // We're going to seek the video source first, followed by 1756 // the audio source. 1757 // In order to avoid jumps in the DataSource offset caused by 1758 // the audio codec prefetching data from the old locations 1759 // while the video codec is already reading data from the new 1760 // locations, we'll "pause" the audio source, causing it to 1761 // stop reading input data until a subsequent seek. 1762 1763 if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) { 1764 mAudioPlayer->pause(); 1765 1766 modifyFlags(AUDIO_RUNNING, CLEAR); 1767 } 1768 mAudioSource->pause(); 1769 } 1770 } 1771 1772 if (!mVideoBuffer) { 1773 MediaSource::ReadOptions options; 1774 if (mSeeking != NO_SEEK) { 1775 ALOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs, mSeekTimeUs / 1E6); 1776 1777 options.setSeekTo( 1778 mSeekTimeUs, 1779 mSeeking == SEEK_VIDEO_ONLY 1780 ? MediaSource::ReadOptions::SEEK_NEXT_SYNC 1781 : MediaSource::ReadOptions::SEEK_CLOSEST_SYNC); 1782 } 1783 for (;;) { 1784 status_t err = mVideoSource->read(&mVideoBuffer, &options); 1785 options.clearSeekTo(); 1786 1787 if (err != OK) { 1788 CHECK(mVideoBuffer == NULL); 1789 1790 if (err == INFO_FORMAT_CHANGED) { 1791 ALOGV("VideoSource signalled format change."); 1792 1793 notifyVideoSize_l(); 1794 1795 if (mVideoRenderer != NULL) { 1796 mVideoRendererIsPreview = false; 1797 initRenderer_l(); 1798 } 1799 continue; 1800 } 1801 1802 // So video playback is complete, but we may still have 1803 // a seek request pending that needs to be applied 1804 // to the audio track. 1805 if (mSeeking != NO_SEEK) { 1806 ALOGV("video stream ended while seeking!"); 1807 } 1808 finishSeekIfNecessary(-1); 1809 1810 if (mAudioPlayer != NULL 1811 && !(mFlags & (AUDIO_RUNNING | SEEK_PREVIEW))) { 1812 startAudioPlayer_l(); 1813 } 1814 1815 modifyFlags(VIDEO_AT_EOS, SET); 1816 postStreamDoneEvent_l(err); 1817 return; 1818 } 1819 1820 if (mVideoBuffer->range_length() == 0) { 1821 // Some decoders, notably the PV AVC software decoder 1822 // return spurious empty buffers that we just want to ignore. 1823 1824 mVideoBuffer->release(); 1825 mVideoBuffer = NULL; 1826 continue; 1827 } 1828 1829 break; 1830 } 1831 1832 { 1833 Mutex::Autolock autoLock(mStatsLock); 1834 ++mStats.mNumVideoFramesDecoded; 1835 } 1836 } 1837 1838 int64_t timeUs; 1839 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs)); 1840 1841 mLastVideoTimeUs = timeUs; 1842 1843 if (mSeeking == SEEK_VIDEO_ONLY) { 1844 if (mSeekTimeUs > timeUs) { 1845 ALOGI("XXX mSeekTimeUs = %lld us, timeUs = %lld us", 1846 mSeekTimeUs, timeUs); 1847 } 1848 } 1849 1850 { 1851 Mutex::Autolock autoLock(mMiscStateLock); 1852 mVideoTimeUs = timeUs; 1853 } 1854 1855 SeekType wasSeeking = mSeeking; 1856 finishSeekIfNecessary(timeUs); 1857 1858 if (mAudioPlayer != NULL && !(mFlags & (AUDIO_RUNNING | SEEK_PREVIEW))) { 1859 status_t err = startAudioPlayer_l(); 1860 if (err != OK) { 1861 ALOGE("Starting the audio player failed w/ err %d", err); 1862 return; 1863 } 1864 } 1865 1866 if ((mFlags & TEXTPLAYER_INITIALIZED) 1867 && !(mFlags & (TEXT_RUNNING | SEEK_PREVIEW))) { 1868 mTextDriver->start(); 1869 modifyFlags(TEXT_RUNNING, SET); 1870 } 1871 1872 TimeSource *ts = 1873 ((mFlags & AUDIO_AT_EOS) || !(mFlags & AUDIOPLAYER_STARTED)) 1874 ? &mSystemTimeSource : mTimeSource; 1875 int64_t systemTimeUs = mSystemTimeSource.getRealTimeUs(); 1876 int64_t looperTimeUs = ALooper::GetNowUs(); 1877 1878 if (mFlags & FIRST_FRAME) { 1879 modifyFlags(FIRST_FRAME, CLEAR); 1880 mSinceLastDropped = 0; 1881 mClockEstimator->reset(); 1882 mTimeSourceDeltaUs = estimateRealTimeUs(ts, systemTimeUs) - timeUs; 1883 } 1884 1885 int64_t realTimeUs, mediaTimeUs; 1886 if (!(mFlags & AUDIO_AT_EOS) && mAudioPlayer != NULL 1887 && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) { 1888 ALOGV("updating TSdelta (%" PRId64 " => %" PRId64 " change %" PRId64 ")", 1889 mTimeSourceDeltaUs, realTimeUs - mediaTimeUs, 1890 mTimeSourceDeltaUs - (realTimeUs - mediaTimeUs)); 1891 ATRACE_INT("TS delta change (ms)", (mTimeSourceDeltaUs - (realTimeUs - mediaTimeUs)) / 1E3); 1892 mTimeSourceDeltaUs = realTimeUs - mediaTimeUs; 1893 } 1894 1895 if (wasSeeking == SEEK_VIDEO_ONLY) { 1896 int64_t nowUs = estimateRealTimeUs(ts, systemTimeUs) - mTimeSourceDeltaUs; 1897 1898 int64_t latenessUs = nowUs - timeUs; 1899 1900 ATRACE_INT("Video Lateness (ms)", latenessUs / 1E3); 1901 1902 if (latenessUs > 0) { 1903 ALOGI("after SEEK_VIDEO_ONLY we're late by %.2f secs", latenessUs / 1E6); 1904 } 1905 } 1906 1907 int64_t latenessUs = 0; 1908 if (wasSeeking == NO_SEEK) { 1909 // Let's display the first frame after seeking right away. 1910 1911 int64_t nowUs = estimateRealTimeUs(ts, systemTimeUs) - mTimeSourceDeltaUs; 1912 1913 latenessUs = nowUs - timeUs; 1914 1915 ATRACE_INT("Video Lateness (ms)", latenessUs / 1E3); 1916 1917 if (latenessUs > 500000ll 1918 && mAudioPlayer != NULL 1919 && mAudioPlayer->getMediaTimeMapping( 1920 &realTimeUs, &mediaTimeUs)) { 1921 if (mWVMExtractor == NULL) { 1922 ALOGI("we're much too late (%.2f secs), video skipping ahead", 1923 latenessUs / 1E6); 1924 1925 mVideoBuffer->release(); 1926 mVideoBuffer = NULL; 1927 1928 mSeeking = SEEK_VIDEO_ONLY; 1929 mSeekTimeUs = mediaTimeUs; 1930 1931 postVideoEvent_l(); 1932 return; 1933 } else { 1934 // The widevine extractor doesn't deal well with seeking 1935 // audio and video independently. We'll just have to wait 1936 // until the decoder catches up, which won't be long at all. 1937 ALOGI("we're very late (%.2f secs)", latenessUs / 1E6); 1938 } 1939 } 1940 1941 if (latenessUs > 40000) { 1942 // We're more than 40ms late. 1943 ALOGV("we're late by %lld us (%.2f secs)", 1944 latenessUs, latenessUs / 1E6); 1945 1946 if (!(mFlags & SLOW_DECODER_HACK) 1947 || mSinceLastDropped > FRAME_DROP_FREQ) 1948 { 1949 ALOGV("we're late by %lld us (%.2f secs) dropping " 1950 "one after %d frames", 1951 latenessUs, latenessUs / 1E6, mSinceLastDropped); 1952 1953 mSinceLastDropped = 0; 1954 mVideoBuffer->release(); 1955 mVideoBuffer = NULL; 1956 1957 { 1958 Mutex::Autolock autoLock(mStatsLock); 1959 ++mStats.mNumVideoFramesDropped; 1960 } 1961 1962 postVideoEvent_l(0); 1963 return; 1964 } 1965 } 1966 1967 if (latenessUs < -30000) { 1968 // We're more than 30ms early, schedule at most 20 ms before time due 1969 postVideoEvent_l(latenessUs < -60000 ? 30000 : -latenessUs - 20000); 1970 return; 1971 } 1972 } 1973 1974 if ((mNativeWindow != NULL) 1975 && (mVideoRendererIsPreview || mVideoRenderer == NULL)) { 1976 mVideoRendererIsPreview = false; 1977 1978 initRenderer_l(); 1979 } 1980 1981 if (mVideoRenderer != NULL) { 1982 mSinceLastDropped++; 1983 mVideoBuffer->meta_data()->setInt64(kKeyTime, looperTimeUs - latenessUs); 1984 1985 mVideoRenderer->render(mVideoBuffer); 1986 if (!mVideoRenderingStarted) { 1987 mVideoRenderingStarted = true; 1988 notifyListener_l(MEDIA_INFO, MEDIA_INFO_RENDERING_START); 1989 } 1990 1991 if (mFlags & PLAYING) { 1992 notifyIfMediaStarted_l(); 1993 } 1994 } 1995 1996 mVideoBuffer->release(); 1997 mVideoBuffer = NULL; 1998 1999 if (wasSeeking != NO_SEEK && (mFlags & SEEK_PREVIEW)) { 2000 modifyFlags(SEEK_PREVIEW, CLEAR); 2001 return; 2002 } 2003 2004 /* get next frame time */ 2005 if (wasSeeking == NO_SEEK) { 2006 MediaSource::ReadOptions options; 2007 for (;;) { 2008 status_t err = mVideoSource->read(&mVideoBuffer, &options); 2009 if (err != OK) { 2010 // deal with any errors next time 2011 CHECK(mVideoBuffer == NULL); 2012 postVideoEvent_l(0); 2013 return; 2014 } 2015 2016 if (mVideoBuffer->range_length() != 0) { 2017 break; 2018 } 2019 2020 // Some decoders, notably the PV AVC software decoder 2021 // return spurious empty buffers that we just want to ignore. 2022 2023 mVideoBuffer->release(); 2024 mVideoBuffer = NULL; 2025 } 2026 2027 { 2028 Mutex::Autolock autoLock(mStatsLock); 2029 ++mStats.mNumVideoFramesDecoded; 2030 } 2031 2032 int64_t nextTimeUs; 2033 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &nextTimeUs)); 2034 systemTimeUs = mSystemTimeSource.getRealTimeUs(); 2035 int64_t delayUs = nextTimeUs - estimateRealTimeUs(ts, systemTimeUs) + mTimeSourceDeltaUs; 2036 ATRACE_INT("Frame delta (ms)", (nextTimeUs - timeUs) / 1E3); 2037 ALOGV("next frame in %" PRId64, delayUs); 2038 // try to schedule 30ms before time due 2039 postVideoEvent_l(delayUs > 60000 ? 30000 : (delayUs < 30000 ? 0 : delayUs - 30000)); 2040 return; 2041 } 2042 2043 postVideoEvent_l(); 2044} 2045 2046int64_t AwesomePlayer::estimateRealTimeUs(TimeSource *ts, int64_t systemTimeUs) { 2047 if (ts == &mSystemTimeSource) { 2048 return systemTimeUs; 2049 } else { 2050 return (int64_t)mClockEstimator->estimate(systemTimeUs, ts->getRealTimeUs()); 2051 } 2052} 2053 2054void AwesomePlayer::postVideoEvent_l(int64_t delayUs) { 2055 ATRACE_CALL(); 2056 2057 if (mVideoEventPending) { 2058 return; 2059 } 2060 2061 mVideoEventPending = true; 2062 mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs); 2063} 2064 2065void AwesomePlayer::postStreamDoneEvent_l(status_t status) { 2066 if (mStreamDoneEventPending) { 2067 return; 2068 } 2069 mStreamDoneEventPending = true; 2070 2071 mStreamDoneStatus = status; 2072 mQueue.postEvent(mStreamDoneEvent); 2073} 2074 2075void AwesomePlayer::postBufferingEvent_l() { 2076 if (mBufferingEventPending) { 2077 return; 2078 } 2079 mBufferingEventPending = true; 2080 mQueue.postEventWithDelay(mBufferingEvent, 1000000ll); 2081} 2082 2083void AwesomePlayer::postVideoLagEvent_l() { 2084 if (mVideoLagEventPending) { 2085 return; 2086 } 2087 mVideoLagEventPending = true; 2088 mQueue.postEventWithDelay(mVideoLagEvent, 1000000ll); 2089} 2090 2091void AwesomePlayer::postCheckAudioStatusEvent(int64_t delayUs) { 2092 Mutex::Autolock autoLock(mAudioLock); 2093 if (mAudioStatusEventPending) { 2094 return; 2095 } 2096 mAudioStatusEventPending = true; 2097 // Do not honor delay when looping in order to limit audio gap 2098 if (mFlags & (LOOPING | AUTO_LOOPING)) { 2099 delayUs = 0; 2100 } 2101 mQueue.postEventWithDelay(mCheckAudioStatusEvent, delayUs); 2102} 2103 2104void AwesomePlayer::postAudioTearDownEvent(int64_t delayUs) { 2105 Mutex::Autolock autoLock(mAudioLock); 2106 if (mAudioTearDownEventPending) { 2107 return; 2108 } 2109 mAudioTearDownEventPending = true; 2110 mQueue.postEventWithDelay(mAudioTearDownEvent, delayUs); 2111} 2112 2113void AwesomePlayer::onCheckAudioStatus() { 2114 { 2115 Mutex::Autolock autoLock(mAudioLock); 2116 if (!mAudioStatusEventPending) { 2117 // Event was dispatched and while we were blocking on the mutex, 2118 // has already been cancelled. 2119 return; 2120 } 2121 2122 mAudioStatusEventPending = false; 2123 } 2124 2125 Mutex::Autolock autoLock(mLock); 2126 2127 if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) { 2128 mWatchForAudioSeekComplete = false; 2129 2130 if (!mSeekNotificationSent) { 2131 notifyListener_l(MEDIA_SEEK_COMPLETE); 2132 mSeekNotificationSent = true; 2133 } 2134 2135 if (mVideoSource == NULL) { 2136 // For video the mSeeking flag is always reset in finishSeekIfNecessary 2137 mSeeking = NO_SEEK; 2138 } 2139 2140 notifyIfMediaStarted_l(); 2141 } 2142 2143 status_t finalStatus; 2144 if (mWatchForAudioEOS && mAudioPlayer->reachedEOS(&finalStatus)) { 2145 mWatchForAudioEOS = false; 2146 modifyFlags(AUDIO_AT_EOS, SET); 2147 modifyFlags(FIRST_FRAME, SET); 2148 postStreamDoneEvent_l(finalStatus); 2149 } 2150} 2151 2152status_t AwesomePlayer::prepare() { 2153 ATRACE_CALL(); 2154 Mutex::Autolock autoLock(mLock); 2155 return prepare_l(); 2156} 2157 2158status_t AwesomePlayer::prepare_l() { 2159 if (mFlags & PREPARED) { 2160 return OK; 2161 } 2162 2163 if (mFlags & PREPARING) { 2164 return UNKNOWN_ERROR; 2165 } 2166 2167 mIsAsyncPrepare = false; 2168 status_t err = prepareAsync_l(); 2169 2170 if (err != OK) { 2171 return err; 2172 } 2173 2174 while (mFlags & PREPARING) { 2175 mPreparedCondition.wait(mLock); 2176 } 2177 2178 return mPrepareResult; 2179} 2180 2181status_t AwesomePlayer::prepareAsync() { 2182 ATRACE_CALL(); 2183 Mutex::Autolock autoLock(mLock); 2184 2185 if (mFlags & PREPARING) { 2186 return UNKNOWN_ERROR; // async prepare already pending 2187 } 2188 2189 mIsAsyncPrepare = true; 2190 return prepareAsync_l(); 2191} 2192 2193status_t AwesomePlayer::prepareAsync_l() { 2194 if (mFlags & PREPARING) { 2195 return UNKNOWN_ERROR; // async prepare already pending 2196 } 2197 2198 if (!mQueueStarted) { 2199 mQueue.start(); 2200 mQueueStarted = true; 2201 } 2202 2203 modifyFlags(PREPARING, SET); 2204 mAsyncPrepareEvent = new AwesomeEvent( 2205 this, &AwesomePlayer::onPrepareAsyncEvent); 2206 2207 mQueue.postEvent(mAsyncPrepareEvent); 2208 2209 return OK; 2210} 2211 2212status_t AwesomePlayer::finishSetDataSource_l() { 2213 ATRACE_CALL(); 2214 sp<DataSource> dataSource; 2215 2216 bool isWidevineStreaming = false; 2217 if (!strncasecmp("widevine://", mUri.string(), 11)) { 2218 isWidevineStreaming = true; 2219 2220 String8 newURI = String8("http://"); 2221 newURI.append(mUri.string() + 11); 2222 2223 mUri = newURI; 2224 } 2225 2226 AString sniffedMIME; 2227 2228 if (!strncasecmp("http://", mUri.string(), 7) 2229 || !strncasecmp("https://", mUri.string(), 8) 2230 || isWidevineStreaming) { 2231 if (mHTTPService == NULL) { 2232 ALOGE("Attempt to play media from http URI without HTTP service."); 2233 return UNKNOWN_ERROR; 2234 } 2235 2236 sp<IMediaHTTPConnection> conn = mHTTPService->makeHTTPConnection(); 2237 mConnectingDataSource = new MediaHTTP(conn); 2238 2239 String8 cacheConfig; 2240 bool disconnectAtHighwatermark; 2241 NuCachedSource2::RemoveCacheSpecificHeaders( 2242 &mUriHeaders, &cacheConfig, &disconnectAtHighwatermark); 2243 2244 mLock.unlock(); 2245 status_t err = mConnectingDataSource->connect(mUri, &mUriHeaders); 2246 // force connection at this point, to avoid a race condition between getMIMEType and the 2247 // caching datasource constructed below, which could result in multiple requests to the 2248 // server, and/or failed connections. 2249 String8 contentType = mConnectingDataSource->getMIMEType(); 2250 mLock.lock(); 2251 2252 if (err != OK) { 2253 mConnectingDataSource.clear(); 2254 2255 ALOGI("mConnectingDataSource->connect() returned %d", err); 2256 return err; 2257 } 2258 2259 if (!isWidevineStreaming) { 2260 // The widevine extractor does its own caching. 2261 2262#if 0 2263 mCachedSource = new NuCachedSource2( 2264 new ThrottledSource( 2265 mConnectingDataSource, 50 * 1024 /* bytes/sec */)); 2266#else 2267 mCachedSource = new NuCachedSource2( 2268 mConnectingDataSource, 2269 cacheConfig.isEmpty() ? NULL : cacheConfig.string(), 2270 disconnectAtHighwatermark); 2271#endif 2272 2273 dataSource = mCachedSource; 2274 } else { 2275 dataSource = mConnectingDataSource; 2276 } 2277 2278 mConnectingDataSource.clear(); 2279 2280 if (strncasecmp(contentType.string(), "audio/", 6)) { 2281 // We're not doing this for streams that appear to be audio-only 2282 // streams to ensure that even low bandwidth streams start 2283 // playing back fairly instantly. 2284 2285 // We're going to prefill the cache before trying to instantiate 2286 // the extractor below, as the latter is an operation that otherwise 2287 // could block on the datasource for a significant amount of time. 2288 // During that time we'd be unable to abort the preparation phase 2289 // without this prefill. 2290 if (mCachedSource != NULL) { 2291 // We're going to prefill the cache before trying to instantiate 2292 // the extractor below, as the latter is an operation that otherwise 2293 // could block on the datasource for a significant amount of time. 2294 // During that time we'd be unable to abort the preparation phase 2295 // without this prefill. 2296 2297 mLock.unlock(); 2298 2299 // Initially make sure we have at least 192 KB for the sniff 2300 // to complete without blocking. 2301 static const size_t kMinBytesForSniffing = 192 * 1024; 2302 2303 off64_t metaDataSize = -1ll; 2304 for (;;) { 2305 status_t finalStatus; 2306 size_t cachedDataRemaining = 2307 mCachedSource->approxDataRemaining(&finalStatus); 2308 2309 if (finalStatus != OK 2310 || (metaDataSize >= 0 2311 && cachedDataRemaining >= metaDataSize) 2312 || (mFlags & PREPARE_CANCELLED)) { 2313 break; 2314 } 2315 2316 ALOGV("now cached %d bytes of data", cachedDataRemaining); 2317 2318 if (metaDataSize < 0 2319 && cachedDataRemaining >= kMinBytesForSniffing) { 2320 String8 tmp; 2321 float confidence; 2322 sp<AMessage> meta; 2323 if (!dataSource->sniff(&tmp, &confidence, &meta)) { 2324 mLock.lock(); 2325 return UNKNOWN_ERROR; 2326 } 2327 2328 // We successfully identified the file's extractor to 2329 // be, remember this mime type so we don't have to 2330 // sniff it again when we call MediaExtractor::Create() 2331 // below. 2332 sniffedMIME = tmp.string(); 2333 2334 if (meta == NULL 2335 || !meta->findInt64("meta-data-size", 2336 reinterpret_cast<int64_t*>(&metaDataSize))) { 2337 metaDataSize = kHighWaterMarkBytes; 2338 } 2339 2340 CHECK_GE(metaDataSize, 0ll); 2341 ALOGV("metaDataSize = %lld bytes", metaDataSize); 2342 } 2343 2344 usleep(200000); 2345 } 2346 2347 mLock.lock(); 2348 } 2349 2350 if (mFlags & PREPARE_CANCELLED) { 2351 ALOGI("Prepare cancelled while waiting for initial cache fill."); 2352 return UNKNOWN_ERROR; 2353 } 2354 } 2355 } else { 2356 dataSource = DataSource::CreateFromURI( 2357 mHTTPService, mUri.string(), &mUriHeaders); 2358 } 2359 2360 if (dataSource == NULL) { 2361 return UNKNOWN_ERROR; 2362 } 2363 2364 sp<MediaExtractor> extractor; 2365 2366 if (isWidevineStreaming) { 2367 String8 mimeType; 2368 float confidence; 2369 sp<AMessage> dummy; 2370 bool success; 2371 2372 // SniffWVM is potentially blocking since it may require network access. 2373 // Do not call it with mLock held. 2374 mLock.unlock(); 2375 success = SniffWVM(dataSource, &mimeType, &confidence, &dummy); 2376 mLock.lock(); 2377 2378 if (!success 2379 || strcasecmp( 2380 mimeType.string(), MEDIA_MIMETYPE_CONTAINER_WVM)) { 2381 return ERROR_UNSUPPORTED; 2382 } 2383 2384 mWVMExtractor = new WVMExtractor(dataSource); 2385 mWVMExtractor->setAdaptiveStreamingMode(true); 2386 if (mUIDValid) 2387 mWVMExtractor->setUID(mUID); 2388 extractor = mWVMExtractor; 2389 } else { 2390 extractor = MediaExtractor::Create( 2391 dataSource, sniffedMIME.empty() ? NULL : sniffedMIME.c_str()); 2392 2393 if (extractor == NULL) { 2394 return UNKNOWN_ERROR; 2395 } 2396 } 2397 2398 if (extractor->getDrmFlag()) { 2399 checkDrmStatus(dataSource); 2400 } 2401 2402 status_t err = setDataSource_l(extractor); 2403 2404 if (err != OK) { 2405 mWVMExtractor.clear(); 2406 2407 return err; 2408 } 2409 2410 return OK; 2411} 2412 2413void AwesomePlayer::abortPrepare(status_t err) { 2414 CHECK(err != OK); 2415 2416 if (mIsAsyncPrepare) { 2417 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err); 2418 } 2419 2420 mPrepareResult = err; 2421 modifyFlags((PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED), CLEAR); 2422 mAsyncPrepareEvent = NULL; 2423 mPreparedCondition.broadcast(); 2424 mAudioTearDown = false; 2425} 2426 2427// static 2428bool AwesomePlayer::ContinuePreparation(void *cookie) { 2429 AwesomePlayer *me = static_cast<AwesomePlayer *>(cookie); 2430 2431 return (me->mFlags & PREPARE_CANCELLED) == 0; 2432} 2433 2434void AwesomePlayer::onPrepareAsyncEvent() { 2435 Mutex::Autolock autoLock(mLock); 2436 beginPrepareAsync_l(); 2437} 2438 2439void AwesomePlayer::beginPrepareAsync_l() { 2440 if (mFlags & PREPARE_CANCELLED) { 2441 ALOGI("prepare was cancelled before doing anything"); 2442 abortPrepare(UNKNOWN_ERROR); 2443 return; 2444 } 2445 2446 if (mUri.size() > 0) { 2447 status_t err = finishSetDataSource_l(); 2448 2449 if (err != OK) { 2450 abortPrepare(err); 2451 return; 2452 } 2453 } 2454 2455 if (mVideoTrack != NULL && mVideoSource == NULL) { 2456 status_t err = initVideoDecoder(); 2457 2458 if (err != OK) { 2459 abortPrepare(err); 2460 return; 2461 } 2462 } 2463 2464 if (mAudioTrack != NULL && mAudioSource == NULL) { 2465 status_t err = initAudioDecoder(); 2466 2467 if (err != OK) { 2468 abortPrepare(err); 2469 return; 2470 } 2471 } 2472 2473 modifyFlags(PREPARING_CONNECTED, SET); 2474 2475 if (isStreamingHTTP()) { 2476 postBufferingEvent_l(); 2477 } else { 2478 finishAsyncPrepare_l(); 2479 } 2480} 2481 2482void AwesomePlayer::finishAsyncPrepare_l() { 2483 if (mIsAsyncPrepare) { 2484 if (mVideoSource == NULL) { 2485 notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0); 2486 } else { 2487 notifyVideoSize_l(); 2488 } 2489 2490 notifyListener_l(MEDIA_PREPARED); 2491 } 2492 2493 mPrepareResult = OK; 2494 modifyFlags((PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED), CLEAR); 2495 modifyFlags(PREPARED, SET); 2496 mAsyncPrepareEvent = NULL; 2497 mPreparedCondition.broadcast(); 2498 2499 if (mAudioTearDown) { 2500 if (mPrepareResult == OK) { 2501 if (mExtractorFlags & MediaExtractor::CAN_SEEK) { 2502 seekTo_l(mAudioTearDownPosition); 2503 } 2504 2505 if (mAudioTearDownWasPlaying) { 2506 modifyFlags(CACHE_UNDERRUN, CLEAR); 2507 play_l(); 2508 } 2509 } 2510 mAudioTearDown = false; 2511 } 2512} 2513 2514uint32_t AwesomePlayer::flags() const { 2515 return mExtractorFlags; 2516} 2517 2518void AwesomePlayer::postAudioEOS(int64_t delayUs) { 2519 postCheckAudioStatusEvent(delayUs); 2520} 2521 2522void AwesomePlayer::postAudioSeekComplete() { 2523 postCheckAudioStatusEvent(0); 2524} 2525 2526void AwesomePlayer::postAudioTearDown() { 2527 postAudioTearDownEvent(0); 2528} 2529 2530status_t AwesomePlayer::setParameter(int key, const Parcel &request) { 2531 switch (key) { 2532 case KEY_PARAMETER_CACHE_STAT_COLLECT_FREQ_MS: 2533 { 2534 return setCacheStatCollectFreq(request); 2535 } 2536 case KEY_PARAMETER_PLAYBACK_RATE_PERMILLE: 2537 { 2538 if (mAudioPlayer != NULL) { 2539 return mAudioPlayer->setPlaybackRatePermille(request.readInt32()); 2540 } else { 2541 return NO_INIT; 2542 } 2543 } 2544 default: 2545 { 2546 return ERROR_UNSUPPORTED; 2547 } 2548 } 2549} 2550 2551status_t AwesomePlayer::setCacheStatCollectFreq(const Parcel &request) { 2552 if (mCachedSource != NULL) { 2553 int32_t freqMs = request.readInt32(); 2554 ALOGD("Request to keep cache stats in the past %d ms", 2555 freqMs); 2556 return mCachedSource->setCacheStatCollectFreq(freqMs); 2557 } 2558 return ERROR_UNSUPPORTED; 2559} 2560 2561status_t AwesomePlayer::getParameter(int key, Parcel *reply) { 2562 switch (key) { 2563 case KEY_PARAMETER_AUDIO_CHANNEL_COUNT: 2564 { 2565 int32_t channelCount; 2566 if (mAudioTrack == 0 || 2567 !mAudioTrack->getFormat()->findInt32(kKeyChannelCount, &channelCount)) { 2568 channelCount = 0; 2569 } 2570 reply->writeInt32(channelCount); 2571 } 2572 return OK; 2573 default: 2574 { 2575 return ERROR_UNSUPPORTED; 2576 } 2577 } 2578} 2579 2580status_t AwesomePlayer::getTrackInfo(Parcel *reply) const { 2581 Mutex::Autolock autoLock(mLock); 2582 size_t trackCount = mExtractor->countTracks(); 2583 if (mTextDriver != NULL) { 2584 trackCount += mTextDriver->countExternalTracks(); 2585 } 2586 2587 reply->writeInt32(trackCount); 2588 for (size_t i = 0; i < mExtractor->countTracks(); ++i) { 2589 sp<MetaData> meta = mExtractor->getTrackMetaData(i); 2590 2591 const char *_mime; 2592 CHECK(meta->findCString(kKeyMIMEType, &_mime)); 2593 2594 String8 mime = String8(_mime); 2595 2596 reply->writeInt32(2); // 2 fields 2597 2598 if (!strncasecmp(mime.string(), "video/", 6)) { 2599 reply->writeInt32(MEDIA_TRACK_TYPE_VIDEO); 2600 } else if (!strncasecmp(mime.string(), "audio/", 6)) { 2601 reply->writeInt32(MEDIA_TRACK_TYPE_AUDIO); 2602 } else if (!strcasecmp(mime.string(), MEDIA_MIMETYPE_TEXT_3GPP)) { 2603 reply->writeInt32(MEDIA_TRACK_TYPE_TIMEDTEXT); 2604 } else { 2605 reply->writeInt32(MEDIA_TRACK_TYPE_UNKNOWN); 2606 } 2607 2608 const char *lang; 2609 if (!meta->findCString(kKeyMediaLanguage, &lang)) { 2610 lang = "und"; 2611 } 2612 reply->writeString16(String16(lang)); 2613 } 2614 2615 if (mTextDriver != NULL) { 2616 mTextDriver->getExternalTrackInfo(reply); 2617 } 2618 return OK; 2619} 2620 2621status_t AwesomePlayer::selectAudioTrack_l( 2622 const sp<MediaSource>& source, size_t trackIndex) { 2623 2624 ALOGI("selectAudioTrack_l: trackIndex=%zu, mFlags=0x%x", trackIndex, mFlags); 2625 2626 { 2627 Mutex::Autolock autoLock(mStatsLock); 2628 if ((ssize_t)trackIndex == mActiveAudioTrackIndex) { 2629 ALOGI("Track %zu is active. Does nothing.", trackIndex); 2630 return OK; 2631 } 2632 //mStats.mFlags = mFlags; 2633 } 2634 2635 if (mSeeking != NO_SEEK) { 2636 ALOGE("Selecting a track while seeking is not supported"); 2637 return ERROR_UNSUPPORTED; 2638 } 2639 2640 if ((mFlags & PREPARED) == 0) { 2641 ALOGE("Data source has not finished preparation"); 2642 return ERROR_UNSUPPORTED; 2643 } 2644 2645 CHECK(source != NULL); 2646 bool wasPlaying = (mFlags & PLAYING) != 0; 2647 2648 pause_l(); 2649 2650 int64_t curTimeUs; 2651 CHECK_EQ(getPosition(&curTimeUs), (status_t)OK); 2652 2653 if ((mAudioPlayer == NULL || !(mFlags & AUDIOPLAYER_STARTED)) 2654 && mAudioSource != NULL) { 2655 // If we had an audio player, it would have effectively 2656 // taken possession of the audio source and stopped it when 2657 // _it_ is stopped. Otherwise this is still our responsibility. 2658 mAudioSource->stop(); 2659 } 2660 mAudioSource.clear(); 2661 mOmxSource.clear(); 2662 2663 mTimeSource = NULL; 2664 2665 delete mAudioPlayer; 2666 mAudioPlayer = NULL; 2667 2668 modifyFlags(AUDIOPLAYER_STARTED, CLEAR); 2669 2670 setAudioSource(source); 2671 2672 modifyFlags(AUDIO_AT_EOS, CLEAR); 2673 modifyFlags(AT_EOS, CLEAR); 2674 2675 status_t err; 2676 if ((err = initAudioDecoder()) != OK) { 2677 ALOGE("Failed to init audio decoder: 0x%x", err); 2678 return err; 2679 } 2680 2681 mSeekNotificationSent = true; 2682 seekTo_l(curTimeUs); 2683 2684 if (wasPlaying) { 2685 play_l(); 2686 } 2687 2688 mActiveAudioTrackIndex = trackIndex; 2689 2690 return OK; 2691} 2692 2693status_t AwesomePlayer::selectTrack(size_t trackIndex, bool select) { 2694 ATRACE_CALL(); 2695 ALOGV("selectTrack: trackIndex = %d and select=%d", trackIndex, select); 2696 Mutex::Autolock autoLock(mLock); 2697 size_t trackCount = mExtractor->countTracks(); 2698 if (mTextDriver != NULL) { 2699 trackCount += mTextDriver->countExternalTracks(); 2700 } 2701 if (trackIndex >= trackCount) { 2702 ALOGE("Track index (%zu) is out of range [0, %zu)", trackIndex, trackCount); 2703 return ERROR_OUT_OF_RANGE; 2704 } 2705 2706 bool isAudioTrack = false; 2707 if (trackIndex < mExtractor->countTracks()) { 2708 sp<MetaData> meta = mExtractor->getTrackMetaData(trackIndex); 2709 const char *mime; 2710 CHECK(meta->findCString(kKeyMIMEType, &mime)); 2711 isAudioTrack = !strncasecmp(mime, "audio/", 6); 2712 2713 if (!isAudioTrack && strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP) != 0) { 2714 ALOGE("Track %zu is not either audio or timed text", trackIndex); 2715 return ERROR_UNSUPPORTED; 2716 } 2717 } 2718 2719 if (isAudioTrack) { 2720 if (!select) { 2721 ALOGE("Deselect an audio track (%zu) is not supported", trackIndex); 2722 return ERROR_UNSUPPORTED; 2723 } 2724 return selectAudioTrack_l(mExtractor->getTrack(trackIndex), trackIndex); 2725 } 2726 2727 // Timed text track handling 2728 if (mTextDriver == NULL) { 2729 return INVALID_OPERATION; 2730 } 2731 2732 status_t err = OK; 2733 if (select) { 2734 err = mTextDriver->selectTrack(trackIndex); 2735 if (err == OK) { 2736 modifyFlags(TEXTPLAYER_INITIALIZED, SET); 2737 if (mFlags & PLAYING && !(mFlags & TEXT_RUNNING)) { 2738 mTextDriver->start(); 2739 modifyFlags(TEXT_RUNNING, SET); 2740 } 2741 } 2742 } else { 2743 err = mTextDriver->unselectTrack(trackIndex); 2744 if (err == OK) { 2745 modifyFlags(TEXTPLAYER_INITIALIZED, CLEAR); 2746 modifyFlags(TEXT_RUNNING, CLEAR); 2747 } 2748 } 2749 return err; 2750} 2751 2752size_t AwesomePlayer::countTracks() const { 2753 return mExtractor->countTracks() + mTextDriver->countExternalTracks(); 2754} 2755 2756status_t AwesomePlayer::setVideoScalingMode(int32_t mode) { 2757 Mutex::Autolock lock(mLock); 2758 return setVideoScalingMode_l(mode); 2759} 2760 2761status_t AwesomePlayer::setVideoScalingMode_l(int32_t mode) { 2762 mVideoScalingMode = mode; 2763 if (mNativeWindow != NULL) { 2764 status_t err = native_window_set_scaling_mode( 2765 mNativeWindow.get(), mVideoScalingMode); 2766 if (err != OK) { 2767 ALOGW("Failed to set scaling mode: %d", err); 2768 } 2769 return err; 2770 } 2771 return OK; 2772} 2773 2774status_t AwesomePlayer::invoke(const Parcel &request, Parcel *reply) { 2775 ATRACE_CALL(); 2776 if (NULL == reply) { 2777 return android::BAD_VALUE; 2778 } 2779 int32_t methodId; 2780 status_t ret = request.readInt32(&methodId); 2781 if (ret != android::OK) { 2782 return ret; 2783 } 2784 switch(methodId) { 2785 case INVOKE_ID_SET_VIDEO_SCALING_MODE: 2786 { 2787 int mode = request.readInt32(); 2788 return setVideoScalingMode(mode); 2789 } 2790 2791 case INVOKE_ID_GET_TRACK_INFO: 2792 { 2793 return getTrackInfo(reply); 2794 } 2795 case INVOKE_ID_ADD_EXTERNAL_SOURCE: 2796 { 2797 Mutex::Autolock autoLock(mLock); 2798 if (mTextDriver == NULL) { 2799 mTextDriver = new TimedTextDriver(mListener, mHTTPService); 2800 } 2801 // String values written in Parcel are UTF-16 values. 2802 String8 uri(request.readString16()); 2803 String8 mimeType(request.readString16()); 2804 size_t nTracks = countTracks(); 2805 return mTextDriver->addOutOfBandTextSource(nTracks, uri, mimeType); 2806 } 2807 case INVOKE_ID_ADD_EXTERNAL_SOURCE_FD: 2808 { 2809 Mutex::Autolock autoLock(mLock); 2810 if (mTextDriver == NULL) { 2811 mTextDriver = new TimedTextDriver(mListener, mHTTPService); 2812 } 2813 int fd = request.readFileDescriptor(); 2814 off64_t offset = request.readInt64(); 2815 off64_t length = request.readInt64(); 2816 String8 mimeType(request.readString16()); 2817 size_t nTracks = countTracks(); 2818 return mTextDriver->addOutOfBandTextSource( 2819 nTracks, fd, offset, length, mimeType); 2820 } 2821 case INVOKE_ID_SELECT_TRACK: 2822 { 2823 int trackIndex = request.readInt32(); 2824 return selectTrack(trackIndex, true /* select */); 2825 } 2826 case INVOKE_ID_UNSELECT_TRACK: 2827 { 2828 int trackIndex = request.readInt32(); 2829 return selectTrack(trackIndex, false /* select */); 2830 } 2831 default: 2832 { 2833 return ERROR_UNSUPPORTED; 2834 } 2835 } 2836 // It will not reach here. 2837 return OK; 2838} 2839 2840bool AwesomePlayer::isStreamingHTTP() const { 2841 return mCachedSource != NULL || mWVMExtractor != NULL; 2842} 2843 2844status_t AwesomePlayer::dump( 2845 int fd, const Vector<String16> & /* args */) const { 2846 Mutex::Autolock autoLock(mStatsLock); 2847 2848 FILE *out = fdopen(dup(fd), "w"); 2849 2850 fprintf(out, " AwesomePlayer\n"); 2851 if (mStats.mFd < 0) { 2852 fprintf(out, " URI(%s)", uriDebugString(mUri, mFlags & INCOGNITO).c_str()); 2853 } else { 2854 fprintf(out, " fd(%d)", mStats.mFd); 2855 } 2856 2857 fprintf(out, ", flags(0x%08x)", mStats.mFlags); 2858 2859 if (mStats.mBitrate >= 0) { 2860 fprintf(out, ", bitrate(%" PRId64 " bps)", mStats.mBitrate); 2861 } 2862 2863 fprintf(out, "\n"); 2864 2865 for (size_t i = 0; i < mStats.mTracks.size(); ++i) { 2866 const TrackStat &stat = mStats.mTracks.itemAt(i); 2867 2868 fprintf(out, " Track %zu\n", i + 1); 2869 fprintf(out, " MIME(%s)", stat.mMIME.string()); 2870 2871 if (!stat.mDecoderName.isEmpty()) { 2872 fprintf(out, ", decoder(%s)", stat.mDecoderName.string()); 2873 } 2874 2875 fprintf(out, "\n"); 2876 2877 if ((ssize_t)i == mStats.mVideoTrackIndex) { 2878 fprintf(out, 2879 " videoDimensions(%d x %d), " 2880 "numVideoFramesDecoded(%" PRId64 "), " 2881 "numVideoFramesDropped(%" PRId64 ")\n", 2882 mStats.mVideoWidth, 2883 mStats.mVideoHeight, 2884 mStats.mNumVideoFramesDecoded, 2885 mStats.mNumVideoFramesDropped); 2886 } 2887 } 2888 2889 fclose(out); 2890 out = NULL; 2891 2892 return OK; 2893} 2894 2895void AwesomePlayer::modifyFlags(unsigned value, FlagMode mode) { 2896 switch (mode) { 2897 case SET: 2898 mFlags |= value; 2899 break; 2900 case CLEAR: 2901 if ((value & CACHE_UNDERRUN) && (mFlags & CACHE_UNDERRUN)) { 2902 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END); 2903 } 2904 mFlags &= ~value; 2905 break; 2906 case ASSIGN: 2907 mFlags = value; 2908 break; 2909 default: 2910 TRESPASS(); 2911 } 2912 2913 { 2914 Mutex::Autolock autoLock(mStatsLock); 2915 mStats.mFlags = mFlags; 2916 } 2917} 2918 2919void AwesomePlayer::onAudioTearDownEvent() { 2920 2921 Mutex::Autolock autoLock(mLock); 2922 if (!mAudioTearDownEventPending) { 2923 return; 2924 } 2925 mAudioTearDownEventPending = false; 2926 2927 ALOGV("onAudioTearDownEvent"); 2928 2929 // stream info is cleared by reset_l() so copy what we need 2930 mAudioTearDownWasPlaying = (mFlags & PLAYING); 2931 KeyedVector<String8, String8> uriHeaders(mUriHeaders); 2932 sp<DataSource> fileSource(mFileSource); 2933 2934 mStatsLock.lock(); 2935 String8 uri(mStats.mURI); 2936 mStatsLock.unlock(); 2937 2938 // get current position so we can start recreated stream from here 2939 getPosition(&mAudioTearDownPosition); 2940 2941 sp<IMediaHTTPService> savedHTTPService = mHTTPService; 2942 2943 // Reset and recreate 2944 reset_l(); 2945 2946 status_t err; 2947 2948 if (fileSource != NULL) { 2949 mFileSource = fileSource; 2950 err = setDataSource_l(fileSource); 2951 } else { 2952 err = setDataSource_l(savedHTTPService, uri, &uriHeaders); 2953 } 2954 2955 mFlags |= PREPARING; 2956 if ( err != OK ) { 2957 // This will force beingPrepareAsync_l() to notify 2958 // a MEDIA_ERROR to the client and abort the prepare 2959 mFlags |= PREPARE_CANCELLED; 2960 } 2961 2962 mAudioTearDown = true; 2963 mIsAsyncPrepare = true; 2964 2965 // Call prepare for the host decoding 2966 beginPrepareAsync_l(); 2967} 2968 2969} // namespace android 2970