GenericSource.cpp revision 48fa06d1e80a872c7495804979256e021e566ae0
1/* 2 * Copyright (C) 2012 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//#define LOG_NDEBUG 0 18#define LOG_TAG "GenericSource" 19 20#include "GenericSource.h" 21 22#include "AnotherPacketSource.h" 23 24#include <media/IMediaHTTPService.h> 25#include <media/stagefright/foundation/ABuffer.h> 26#include <media/stagefright/foundation/ADebug.h> 27#include <media/stagefright/foundation/AMessage.h> 28#include <media/stagefright/DataSource.h> 29#include <media/stagefright/FileSource.h> 30#include <media/stagefright/MediaBuffer.h> 31#include <media/stagefright/MediaDefs.h> 32#include <media/stagefright/MediaExtractor.h> 33#include <media/stagefright/MediaSource.h> 34#include <media/stagefright/MetaData.h> 35#include <media/stagefright/Utils.h> 36#include "../../libstagefright/include/NuCachedSource2.h" 37#include "../../libstagefright/include/HTTPBase.h" 38 39namespace android { 40 41static const int kLowWaterMarkMs = 2000; // 2secs 42static const int kHighWaterMarkMs = 5000; // 5secs 43static const int kHighWaterMarkRebufferMs = 15000; // 15secs 44 45static const int kLowWaterMarkKB = 40; 46static const int kHighWaterMarkKB = 200; 47 48NuPlayer::GenericSource::GenericSource( 49 const sp<AMessage> ¬ify, 50 bool uidValid, 51 uid_t uid) 52 : Source(notify), 53 mAudioTimeUs(0), 54 mAudioLastDequeueTimeUs(0), 55 mVideoTimeUs(0), 56 mVideoLastDequeueTimeUs(0), 57 mFetchSubtitleDataGeneration(0), 58 mFetchTimedTextDataGeneration(0), 59 mDurationUs(-1ll), 60 mAudioIsVorbis(false), 61 mIsSecure(false), 62 mIsStreaming(false), 63 mUIDValid(uidValid), 64 mUID(uid), 65 mFd(-1), 66 mDrmManagerClient(NULL), 67 mBitrate(-1ll), 68 mPendingReadBufferTypes(0) { 69 mBufferingMonitor = new BufferingMonitor(notify); 70 resetDataSource(); 71} 72 73void NuPlayer::GenericSource::resetDataSource() { 74 mHTTPService.clear(); 75 mHttpSource.clear(); 76 mUri.clear(); 77 mUriHeaders.clear(); 78 if (mFd >= 0) { 79 close(mFd); 80 mFd = -1; 81 } 82 mOffset = 0; 83 mLength = 0; 84 setDrmPlaybackStatusIfNeeded(Playback::STOP, 0); 85 mDecryptHandle = NULL; 86 mDrmManagerClient = NULL; 87 mStarted = false; 88 mStopRead = true; 89 90 if (mBufferingMonitorLooper != NULL) { 91 mBufferingMonitorLooper->unregisterHandler(mBufferingMonitor->id()); 92 mBufferingMonitorLooper->stop(); 93 mBufferingMonitorLooper = NULL; 94 } 95 mBufferingMonitor->stop(); 96} 97 98status_t NuPlayer::GenericSource::setDataSource( 99 const sp<IMediaHTTPService> &httpService, 100 const char *url, 101 const KeyedVector<String8, String8> *headers) { 102 resetDataSource(); 103 104 mHTTPService = httpService; 105 mUri = url; 106 107 if (headers) { 108 mUriHeaders = *headers; 109 } 110 111 // delay data source creation to prepareAsync() to avoid blocking 112 // the calling thread in setDataSource for any significant time. 113 return OK; 114} 115 116status_t NuPlayer::GenericSource::setDataSource( 117 int fd, int64_t offset, int64_t length) { 118 resetDataSource(); 119 120 mFd = dup(fd); 121 mOffset = offset; 122 mLength = length; 123 124 // delay data source creation to prepareAsync() to avoid blocking 125 // the calling thread in setDataSource for any significant time. 126 return OK; 127} 128 129status_t NuPlayer::GenericSource::setDataSource(const sp<DataSource>& source) { 130 resetDataSource(); 131 mDataSource = source; 132 return OK; 133} 134 135sp<MetaData> NuPlayer::GenericSource::getFileFormatMeta() const { 136 return mFileMeta; 137} 138 139status_t NuPlayer::GenericSource::initFromDataSource() { 140 sp<IMediaExtractor> extractor; 141 CHECK(mDataSource != NULL); 142 143 extractor = MediaExtractor::Create(mDataSource, NULL); 144 145 if (extractor == NULL) { 146 return UNKNOWN_ERROR; 147 } 148 149 if (extractor->getDrmFlag()) { 150 checkDrmStatus(mDataSource); 151 } 152 153 mFileMeta = extractor->getMetaData(); 154 if (mFileMeta != NULL) { 155 int64_t duration; 156 if (mFileMeta->findInt64(kKeyDuration, &duration)) { 157 mDurationUs = duration; 158 } 159 } 160 161 int32_t totalBitrate = 0; 162 163 size_t numtracks = extractor->countTracks(); 164 if (numtracks == 0) { 165 return UNKNOWN_ERROR; 166 } 167 168 for (size_t i = 0; i < numtracks; ++i) { 169 sp<IMediaSource> track = extractor->getTrack(i); 170 if (track == NULL) { 171 continue; 172 } 173 174 sp<MetaData> meta = extractor->getTrackMetaData(i); 175 if (meta == NULL) { 176 ALOGE("no metadata for track %zu", i); 177 return UNKNOWN_ERROR; 178 } 179 180 const char *mime; 181 CHECK(meta->findCString(kKeyMIMEType, &mime)); 182 183 // Do the string compare immediately with "mime", 184 // we can't assume "mime" would stay valid after another 185 // extractor operation, some extractors might modify meta 186 // during getTrack() and make it invalid. 187 if (!strncasecmp(mime, "audio/", 6)) { 188 if (mAudioTrack.mSource == NULL) { 189 mAudioTrack.mIndex = i; 190 mAudioTrack.mSource = track; 191 mAudioTrack.mPackets = 192 new AnotherPacketSource(mAudioTrack.mSource->getFormat()); 193 194 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) { 195 mAudioIsVorbis = true; 196 } else { 197 mAudioIsVorbis = false; 198 } 199 } 200 } else if (!strncasecmp(mime, "video/", 6)) { 201 if (mVideoTrack.mSource == NULL) { 202 mVideoTrack.mIndex = i; 203 mVideoTrack.mSource = track; 204 mVideoTrack.mPackets = 205 new AnotherPacketSource(mVideoTrack.mSource->getFormat()); 206 207 // check if the source requires secure buffers 208 int32_t secure; 209 if (meta->findInt32(kKeyRequiresSecureBuffers, &secure) 210 && secure) { 211 mIsSecure = true; 212 if (mUIDValid) { 213 extractor->setUID(mUID); 214 } 215 } 216 } 217 } 218 219 mSources.push(track); 220 int64_t durationUs; 221 if (meta->findInt64(kKeyDuration, &durationUs)) { 222 if (durationUs > mDurationUs) { 223 mDurationUs = durationUs; 224 } 225 } 226 227 int32_t bitrate; 228 if (totalBitrate >= 0 && meta->findInt32(kKeyBitRate, &bitrate)) { 229 totalBitrate += bitrate; 230 } else { 231 totalBitrate = -1; 232 } 233 } 234 235 if (mSources.size() == 0) { 236 ALOGE("b/23705695"); 237 return UNKNOWN_ERROR; 238 } 239 240 mBitrate = totalBitrate; 241 242 return OK; 243} 244 245status_t NuPlayer::GenericSource::getDefaultBufferingSettings( 246 BufferingSettings* buffering /* nonnull */) { 247 mBufferingMonitor->getDefaultBufferingSettings(buffering); 248 return OK; 249} 250 251status_t NuPlayer::GenericSource::setBufferingSettings(const BufferingSettings& buffering) { 252 return mBufferingMonitor->setBufferingSettings(buffering); 253} 254 255status_t NuPlayer::GenericSource::startSources() { 256 // Start the selected A/V tracks now before we start buffering. 257 // Widevine sources might re-initialize crypto when starting, if we delay 258 // this to start(), all data buffered during prepare would be wasted. 259 // (We don't actually start reading until start().) 260 // 261 // TODO: this logic may no longer be relevant after the removal of widevine 262 // support 263 if (mAudioTrack.mSource != NULL && mAudioTrack.mSource->start() != OK) { 264 ALOGE("failed to start audio track!"); 265 return UNKNOWN_ERROR; 266 } 267 268 if (mVideoTrack.mSource != NULL && mVideoTrack.mSource->start() != OK) { 269 ALOGE("failed to start video track!"); 270 return UNKNOWN_ERROR; 271 } 272 273 return OK; 274} 275 276void NuPlayer::GenericSource::checkDrmStatus(const sp<DataSource>& dataSource) { 277 dataSource->getDrmInfo(mDecryptHandle, &mDrmManagerClient); 278 if (mDecryptHandle != NULL) { 279 CHECK(mDrmManagerClient); 280 if (RightsStatus::RIGHTS_VALID != mDecryptHandle->status) { 281 sp<AMessage> msg = dupNotify(); 282 msg->setInt32("what", kWhatDrmNoLicense); 283 msg->post(); 284 } 285 } 286} 287 288int64_t NuPlayer::GenericSource::getLastReadPosition() { 289 if (mAudioTrack.mSource != NULL) { 290 return mAudioTimeUs; 291 } else if (mVideoTrack.mSource != NULL) { 292 return mVideoTimeUs; 293 } else { 294 return 0; 295 } 296} 297 298status_t NuPlayer::GenericSource::setBuffers( 299 bool audio, Vector<MediaBuffer *> &buffers) { 300 if (mIsSecure && !audio && mVideoTrack.mSource != NULL) { 301 return mVideoTrack.mSource->setBuffers(buffers); 302 } 303 return INVALID_OPERATION; 304} 305 306bool NuPlayer::GenericSource::isStreaming() const { 307 return mIsStreaming; 308} 309 310void NuPlayer::GenericSource::setOffloadAudio(bool offload) { 311 mBufferingMonitor->setOffloadAudio(offload); 312} 313 314NuPlayer::GenericSource::~GenericSource() { 315 if (mLooper != NULL) { 316 mLooper->unregisterHandler(id()); 317 mLooper->stop(); 318 } 319 resetDataSource(); 320} 321 322void NuPlayer::GenericSource::prepareAsync() { 323 if (mLooper == NULL) { 324 mLooper = new ALooper; 325 mLooper->setName("generic"); 326 mLooper->start(); 327 328 mLooper->registerHandler(this); 329 } 330 331 sp<AMessage> msg = new AMessage(kWhatPrepareAsync, this); 332 msg->post(); 333} 334 335void NuPlayer::GenericSource::onPrepareAsync() { 336 // delayed data source creation 337 if (mDataSource == NULL) { 338 // set to false first, if the extractor 339 // comes back as secure, set it to true then. 340 mIsSecure = false; 341 342 if (!mUri.empty()) { 343 const char* uri = mUri.c_str(); 344 String8 contentType; 345 346 if (!strncasecmp("http://", uri, 7) || !strncasecmp("https://", uri, 8)) { 347 mHttpSource = DataSource::CreateMediaHTTP(mHTTPService); 348 if (mHttpSource == NULL) { 349 ALOGE("Failed to create http source!"); 350 notifyPreparedAndCleanup(UNKNOWN_ERROR); 351 return; 352 } 353 } 354 355 mDataSource = DataSource::CreateFromURI( 356 mHTTPService, uri, &mUriHeaders, &contentType, 357 static_cast<HTTPBase *>(mHttpSource.get())); 358 } else { 359 mDataSource = new FileSource(mFd, mOffset, mLength); 360 mFd = -1; 361 } 362 363 if (mDataSource == NULL) { 364 ALOGE("Failed to create data source!"); 365 notifyPreparedAndCleanup(UNKNOWN_ERROR); 366 return; 367 } 368 } 369 370 if (mDataSource->flags() & DataSource::kIsCachingDataSource) { 371 mCachedSource = static_cast<NuCachedSource2 *>(mDataSource.get()); 372 } 373 374 // For cached streaming cases, we need to wait for enough 375 // buffering before reporting prepared. 376 mIsStreaming = (mCachedSource != NULL); 377 378 // init extractor from data source 379 status_t err = initFromDataSource(); 380 381 if (err != OK) { 382 ALOGE("Failed to init from data source!"); 383 notifyPreparedAndCleanup(err); 384 return; 385 } 386 387 if (mVideoTrack.mSource != NULL) { 388 sp<MetaData> meta = doGetFormatMeta(false /* audio */); 389 sp<AMessage> msg = new AMessage; 390 err = convertMetaDataToMessage(meta, &msg); 391 if(err != OK) { 392 notifyPreparedAndCleanup(err); 393 return; 394 } 395 notifyVideoSizeChanged(msg); 396 } 397 398 notifyFlagsChanged( 399 (mIsSecure ? FLAG_SECURE : 0) 400 | (mDecryptHandle != NULL ? FLAG_PROTECTED : 0) 401 | FLAG_CAN_PAUSE 402 | FLAG_CAN_SEEK_BACKWARD 403 | FLAG_CAN_SEEK_FORWARD 404 | FLAG_CAN_SEEK); 405 406 if (mIsSecure) { 407 // secure decoders must be instantiated before starting widevine source 408 // 409 // TODO: mIsSecure and FLAG_SECURE may be obsolete, revisit after 410 // removing widevine 411 sp<AMessage> reply = new AMessage(kWhatSecureDecodersInstantiated, this); 412 notifyInstantiateSecureDecoders(reply); 413 } else { 414 finishPrepareAsync(); 415 } 416} 417 418void NuPlayer::GenericSource::onSecureDecodersInstantiated(status_t err) { 419 if (err != OK) { 420 ALOGE("Failed to instantiate secure decoders!"); 421 notifyPreparedAndCleanup(err); 422 return; 423 } 424 finishPrepareAsync(); 425} 426 427void NuPlayer::GenericSource::finishPrepareAsync() { 428 status_t err = startSources(); 429 if (err != OK) { 430 ALOGE("Failed to init start data source!"); 431 notifyPreparedAndCleanup(err); 432 return; 433 } 434 435 if (mIsStreaming) { 436 if (mBufferingMonitorLooper == NULL) { 437 mBufferingMonitor->prepare(mCachedSource, mDurationUs, mBitrate, 438 mIsStreaming); 439 440 mBufferingMonitorLooper = new ALooper; 441 mBufferingMonitorLooper->setName("GSBMonitor"); 442 mBufferingMonitorLooper->start(); 443 mBufferingMonitorLooper->registerHandler(mBufferingMonitor); 444 } 445 446 mBufferingMonitor->ensureCacheIsFetching(); 447 mBufferingMonitor->restartPollBuffering(); 448 } else { 449 notifyPrepared(); 450 } 451} 452 453void NuPlayer::GenericSource::notifyPreparedAndCleanup(status_t err) { 454 if (err != OK) { 455 { 456 sp<DataSource> dataSource = mDataSource; 457 sp<NuCachedSource2> cachedSource = mCachedSource; 458 sp<DataSource> httpSource = mHttpSource; 459 { 460 Mutex::Autolock _l(mDisconnectLock); 461 mDataSource.clear(); 462 mDecryptHandle = NULL; 463 mDrmManagerClient = NULL; 464 mCachedSource.clear(); 465 mHttpSource.clear(); 466 } 467 } 468 mBitrate = -1; 469 470 mBufferingMonitor->cancelPollBuffering(); 471 } 472 notifyPrepared(err); 473} 474 475void NuPlayer::GenericSource::start() { 476 ALOGI("start"); 477 478 mStopRead = false; 479 if (mAudioTrack.mSource != NULL) { 480 postReadBuffer(MEDIA_TRACK_TYPE_AUDIO); 481 } 482 483 if (mVideoTrack.mSource != NULL) { 484 postReadBuffer(MEDIA_TRACK_TYPE_VIDEO); 485 } 486 487 setDrmPlaybackStatusIfNeeded(Playback::START, getLastReadPosition() / 1000); 488 mStarted = true; 489 490 (new AMessage(kWhatStart, this))->post(); 491} 492 493void NuPlayer::GenericSource::stop() { 494 // nothing to do, just account for DRM playback status 495 setDrmPlaybackStatusIfNeeded(Playback::STOP, 0); 496 mStarted = false; 497} 498 499void NuPlayer::GenericSource::pause() { 500 // nothing to do, just account for DRM playback status 501 setDrmPlaybackStatusIfNeeded(Playback::PAUSE, 0); 502 mStarted = false; 503} 504 505void NuPlayer::GenericSource::resume() { 506 // nothing to do, just account for DRM playback status 507 setDrmPlaybackStatusIfNeeded(Playback::START, getLastReadPosition() / 1000); 508 mStarted = true; 509 510 (new AMessage(kWhatResume, this))->post(); 511} 512 513void NuPlayer::GenericSource::disconnect() { 514 sp<DataSource> dataSource, httpSource; 515 { 516 Mutex::Autolock _l(mDisconnectLock); 517 dataSource = mDataSource; 518 httpSource = mHttpSource; 519 } 520 521 if (dataSource != NULL) { 522 // disconnect data source 523 if (dataSource->flags() & DataSource::kIsCachingDataSource) { 524 static_cast<NuCachedSource2 *>(dataSource.get())->disconnect(); 525 } 526 } else if (httpSource != NULL) { 527 static_cast<HTTPBase *>(httpSource.get())->disconnect(); 528 } 529} 530 531void NuPlayer::GenericSource::setDrmPlaybackStatusIfNeeded(int playbackStatus, int64_t position) { 532 if (mDecryptHandle != NULL) { 533 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, playbackStatus, position); 534 } 535 mSubtitleTrack.mPackets = new AnotherPacketSource(NULL); 536 mTimedTextTrack.mPackets = new AnotherPacketSource(NULL); 537} 538 539status_t NuPlayer::GenericSource::feedMoreTSData() { 540 return OK; 541} 542 543void NuPlayer::GenericSource::onMessageReceived(const sp<AMessage> &msg) { 544 switch (msg->what()) { 545 case kWhatPrepareAsync: 546 { 547 onPrepareAsync(); 548 break; 549 } 550 case kWhatFetchSubtitleData: 551 { 552 fetchTextData(kWhatSendSubtitleData, MEDIA_TRACK_TYPE_SUBTITLE, 553 mFetchSubtitleDataGeneration, mSubtitleTrack.mPackets, msg); 554 break; 555 } 556 557 case kWhatFetchTimedTextData: 558 { 559 fetchTextData(kWhatSendTimedTextData, MEDIA_TRACK_TYPE_TIMEDTEXT, 560 mFetchTimedTextDataGeneration, mTimedTextTrack.mPackets, msg); 561 break; 562 } 563 564 case kWhatSendSubtitleData: 565 { 566 sendTextData(kWhatSubtitleData, MEDIA_TRACK_TYPE_SUBTITLE, 567 mFetchSubtitleDataGeneration, mSubtitleTrack.mPackets, msg); 568 break; 569 } 570 571 case kWhatSendGlobalTimedTextData: 572 { 573 sendGlobalTextData(kWhatTimedTextData, mFetchTimedTextDataGeneration, msg); 574 break; 575 } 576 case kWhatSendTimedTextData: 577 { 578 sendTextData(kWhatTimedTextData, MEDIA_TRACK_TYPE_TIMEDTEXT, 579 mFetchTimedTextDataGeneration, mTimedTextTrack.mPackets, msg); 580 break; 581 } 582 583 case kWhatChangeAVSource: 584 { 585 int32_t trackIndex; 586 CHECK(msg->findInt32("trackIndex", &trackIndex)); 587 const sp<IMediaSource> source = mSources.itemAt(trackIndex); 588 589 Track* track; 590 const char *mime; 591 media_track_type trackType, counterpartType; 592 sp<MetaData> meta = source->getFormat(); 593 meta->findCString(kKeyMIMEType, &mime); 594 if (!strncasecmp(mime, "audio/", 6)) { 595 track = &mAudioTrack; 596 trackType = MEDIA_TRACK_TYPE_AUDIO; 597 counterpartType = MEDIA_TRACK_TYPE_VIDEO;; 598 } else { 599 CHECK(!strncasecmp(mime, "video/", 6)); 600 track = &mVideoTrack; 601 trackType = MEDIA_TRACK_TYPE_VIDEO; 602 counterpartType = MEDIA_TRACK_TYPE_AUDIO;; 603 } 604 605 606 if (track->mSource != NULL) { 607 track->mSource->stop(); 608 } 609 track->mSource = source; 610 track->mSource->start(); 611 track->mIndex = trackIndex; 612 613 int64_t timeUs, actualTimeUs; 614 const bool formatChange = true; 615 if (trackType == MEDIA_TRACK_TYPE_AUDIO) { 616 timeUs = mAudioLastDequeueTimeUs; 617 } else { 618 timeUs = mVideoLastDequeueTimeUs; 619 } 620 readBuffer(trackType, timeUs, MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC /* mode */, 621 &actualTimeUs, formatChange); 622 readBuffer(counterpartType, -1, MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC /* mode */, 623 NULL, !formatChange); 624 ALOGV("timeUs %lld actualTimeUs %lld", (long long)timeUs, (long long)actualTimeUs); 625 626 break; 627 } 628 629 case kWhatStart: 630 case kWhatResume: 631 { 632 mBufferingMonitor->restartPollBuffering(); 633 break; 634 } 635 636 case kWhatGetFormat: 637 { 638 onGetFormatMeta(msg); 639 break; 640 } 641 642 case kWhatGetSelectedTrack: 643 { 644 onGetSelectedTrack(msg); 645 break; 646 } 647 648 case kWhatSelectTrack: 649 { 650 onSelectTrack(msg); 651 break; 652 } 653 654 case kWhatSeek: 655 { 656 onSeek(msg); 657 break; 658 } 659 660 case kWhatReadBuffer: 661 { 662 onReadBuffer(msg); 663 break; 664 } 665 666 case kWhatSecureDecodersInstantiated: 667 { 668 int32_t err; 669 CHECK(msg->findInt32("err", &err)); 670 onSecureDecodersInstantiated(err); 671 break; 672 } 673 674 default: 675 Source::onMessageReceived(msg); 676 break; 677 } 678} 679 680void NuPlayer::GenericSource::fetchTextData( 681 uint32_t sendWhat, 682 media_track_type type, 683 int32_t curGen, 684 const sp<AnotherPacketSource>& packets, 685 const sp<AMessage>& msg) { 686 int32_t msgGeneration; 687 CHECK(msg->findInt32("generation", &msgGeneration)); 688 if (msgGeneration != curGen) { 689 // stale 690 return; 691 } 692 693 int32_t avail; 694 if (packets->hasBufferAvailable(&avail)) { 695 return; 696 } 697 698 int64_t timeUs; 699 CHECK(msg->findInt64("timeUs", &timeUs)); 700 701 int64_t subTimeUs; 702 readBuffer(type, timeUs, MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC /* mode */, &subTimeUs); 703 704 int64_t delayUs = subTimeUs - timeUs; 705 if (msg->what() == kWhatFetchSubtitleData) { 706 const int64_t oneSecUs = 1000000ll; 707 delayUs -= oneSecUs; 708 } 709 sp<AMessage> msg2 = new AMessage(sendWhat, this); 710 msg2->setInt32("generation", msgGeneration); 711 msg2->post(delayUs < 0 ? 0 : delayUs); 712} 713 714void NuPlayer::GenericSource::sendTextData( 715 uint32_t what, 716 media_track_type type, 717 int32_t curGen, 718 const sp<AnotherPacketSource>& packets, 719 const sp<AMessage>& msg) { 720 int32_t msgGeneration; 721 CHECK(msg->findInt32("generation", &msgGeneration)); 722 if (msgGeneration != curGen) { 723 // stale 724 return; 725 } 726 727 int64_t subTimeUs; 728 if (packets->nextBufferTime(&subTimeUs) != OK) { 729 return; 730 } 731 732 int64_t nextSubTimeUs; 733 readBuffer(type, -1, MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC /* mode */, &nextSubTimeUs); 734 735 sp<ABuffer> buffer; 736 status_t dequeueStatus = packets->dequeueAccessUnit(&buffer); 737 if (dequeueStatus == OK) { 738 sp<AMessage> notify = dupNotify(); 739 notify->setInt32("what", what); 740 notify->setBuffer("buffer", buffer); 741 notify->post(); 742 743 const int64_t delayUs = nextSubTimeUs - subTimeUs; 744 msg->post(delayUs < 0 ? 0 : delayUs); 745 } 746} 747 748void NuPlayer::GenericSource::sendGlobalTextData( 749 uint32_t what, 750 int32_t curGen, 751 sp<AMessage> msg) { 752 int32_t msgGeneration; 753 CHECK(msg->findInt32("generation", &msgGeneration)); 754 if (msgGeneration != curGen) { 755 // stale 756 return; 757 } 758 759 uint32_t textType; 760 const void *data; 761 size_t size = 0; 762 if (mTimedTextTrack.mSource->getFormat()->findData( 763 kKeyTextFormatData, &textType, &data, &size)) { 764 mGlobalTimedText = new ABuffer(size); 765 if (mGlobalTimedText->data()) { 766 memcpy(mGlobalTimedText->data(), data, size); 767 sp<AMessage> globalMeta = mGlobalTimedText->meta(); 768 globalMeta->setInt64("timeUs", 0); 769 globalMeta->setString("mime", MEDIA_MIMETYPE_TEXT_3GPP); 770 globalMeta->setInt32("global", 1); 771 sp<AMessage> notify = dupNotify(); 772 notify->setInt32("what", what); 773 notify->setBuffer("buffer", mGlobalTimedText); 774 notify->post(); 775 } 776 } 777} 778 779sp<MetaData> NuPlayer::GenericSource::getFormatMeta(bool audio) { 780 sp<AMessage> msg = new AMessage(kWhatGetFormat, this); 781 msg->setInt32("audio", audio); 782 783 sp<AMessage> response; 784 sp<RefBase> format; 785 status_t err = msg->postAndAwaitResponse(&response); 786 if (err == OK && response != NULL) { 787 CHECK(response->findObject("format", &format)); 788 return static_cast<MetaData*>(format.get()); 789 } else { 790 return NULL; 791 } 792} 793 794void NuPlayer::GenericSource::onGetFormatMeta(const sp<AMessage>& msg) const { 795 int32_t audio; 796 CHECK(msg->findInt32("audio", &audio)); 797 798 sp<AMessage> response = new AMessage; 799 sp<MetaData> format = doGetFormatMeta(audio); 800 response->setObject("format", format); 801 802 sp<AReplyToken> replyID; 803 CHECK(msg->senderAwaitsResponse(&replyID)); 804 response->postReply(replyID); 805} 806 807sp<MetaData> NuPlayer::GenericSource::doGetFormatMeta(bool audio) const { 808 sp<IMediaSource> source = audio ? mAudioTrack.mSource : mVideoTrack.mSource; 809 810 if (source == NULL) { 811 return NULL; 812 } 813 814 return source->getFormat(); 815} 816 817status_t NuPlayer::GenericSource::dequeueAccessUnit( 818 bool audio, sp<ABuffer> *accessUnit) { 819 if (audio && !mStarted) { 820 return -EWOULDBLOCK; 821 } 822 823 Track *track = audio ? &mAudioTrack : &mVideoTrack; 824 825 if (track->mSource == NULL) { 826 return -EWOULDBLOCK; 827 } 828 829 status_t finalResult; 830 if (!track->mPackets->hasBufferAvailable(&finalResult)) { 831 if (finalResult == OK) { 832 postReadBuffer( 833 audio ? MEDIA_TRACK_TYPE_AUDIO : MEDIA_TRACK_TYPE_VIDEO); 834 return -EWOULDBLOCK; 835 } 836 return finalResult; 837 } 838 839 status_t result = track->mPackets->dequeueAccessUnit(accessUnit); 840 841 // start pulling in more buffers if we only have one (or no) buffer left 842 // so that decoder has less chance of being starved 843 if (track->mPackets->getAvailableBufferCount(&finalResult) < 2) { 844 postReadBuffer(audio? MEDIA_TRACK_TYPE_AUDIO : MEDIA_TRACK_TYPE_VIDEO); 845 } 846 847 if (result != OK) { 848 if (mSubtitleTrack.mSource != NULL) { 849 mSubtitleTrack.mPackets->clear(); 850 mFetchSubtitleDataGeneration++; 851 } 852 if (mTimedTextTrack.mSource != NULL) { 853 mTimedTextTrack.mPackets->clear(); 854 mFetchTimedTextDataGeneration++; 855 } 856 return result; 857 } 858 859 int64_t timeUs; 860 status_t eosResult; // ignored 861 CHECK((*accessUnit)->meta()->findInt64("timeUs", &timeUs)); 862 if (audio) { 863 mAudioLastDequeueTimeUs = timeUs; 864 mBufferingMonitor->updateDequeuedBufferTime(timeUs); 865 } else { 866 mVideoLastDequeueTimeUs = timeUs; 867 } 868 869 if (mSubtitleTrack.mSource != NULL 870 && !mSubtitleTrack.mPackets->hasBufferAvailable(&eosResult)) { 871 sp<AMessage> msg = new AMessage(kWhatFetchSubtitleData, this); 872 msg->setInt64("timeUs", timeUs); 873 msg->setInt32("generation", mFetchSubtitleDataGeneration); 874 msg->post(); 875 } 876 877 if (mTimedTextTrack.mSource != NULL 878 && !mTimedTextTrack.mPackets->hasBufferAvailable(&eosResult)) { 879 sp<AMessage> msg = new AMessage(kWhatFetchTimedTextData, this); 880 msg->setInt64("timeUs", timeUs); 881 msg->setInt32("generation", mFetchTimedTextDataGeneration); 882 msg->post(); 883 } 884 885 return result; 886} 887 888status_t NuPlayer::GenericSource::getDuration(int64_t *durationUs) { 889 *durationUs = mDurationUs; 890 return OK; 891} 892 893size_t NuPlayer::GenericSource::getTrackCount() const { 894 return mSources.size(); 895} 896 897sp<AMessage> NuPlayer::GenericSource::getTrackInfo(size_t trackIndex) const { 898 size_t trackCount = mSources.size(); 899 if (trackIndex >= trackCount) { 900 return NULL; 901 } 902 903 sp<AMessage> format = new AMessage(); 904 sp<MetaData> meta = mSources.itemAt(trackIndex)->getFormat(); 905 if (meta == NULL) { 906 ALOGE("no metadata for track %zu", trackIndex); 907 return NULL; 908 } 909 910 const char *mime; 911 CHECK(meta->findCString(kKeyMIMEType, &mime)); 912 format->setString("mime", mime); 913 914 int32_t trackType; 915 if (!strncasecmp(mime, "video/", 6)) { 916 trackType = MEDIA_TRACK_TYPE_VIDEO; 917 } else if (!strncasecmp(mime, "audio/", 6)) { 918 trackType = MEDIA_TRACK_TYPE_AUDIO; 919 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP)) { 920 trackType = MEDIA_TRACK_TYPE_TIMEDTEXT; 921 } else { 922 trackType = MEDIA_TRACK_TYPE_UNKNOWN; 923 } 924 format->setInt32("type", trackType); 925 926 const char *lang; 927 if (!meta->findCString(kKeyMediaLanguage, &lang)) { 928 lang = "und"; 929 } 930 format->setString("language", lang); 931 932 if (trackType == MEDIA_TRACK_TYPE_SUBTITLE) { 933 int32_t isAutoselect = 1, isDefault = 0, isForced = 0; 934 meta->findInt32(kKeyTrackIsAutoselect, &isAutoselect); 935 meta->findInt32(kKeyTrackIsDefault, &isDefault); 936 meta->findInt32(kKeyTrackIsForced, &isForced); 937 938 format->setInt32("auto", !!isAutoselect); 939 format->setInt32("default", !!isDefault); 940 format->setInt32("forced", !!isForced); 941 } 942 943 return format; 944} 945 946ssize_t NuPlayer::GenericSource::getSelectedTrack(media_track_type type) const { 947 sp<AMessage> msg = new AMessage(kWhatGetSelectedTrack, this); 948 msg->setInt32("type", type); 949 950 sp<AMessage> response; 951 int32_t index; 952 status_t err = msg->postAndAwaitResponse(&response); 953 if (err == OK && response != NULL) { 954 CHECK(response->findInt32("index", &index)); 955 return index; 956 } else { 957 return -1; 958 } 959} 960 961void NuPlayer::GenericSource::onGetSelectedTrack(const sp<AMessage>& msg) const { 962 int32_t tmpType; 963 CHECK(msg->findInt32("type", &tmpType)); 964 media_track_type type = (media_track_type)tmpType; 965 966 sp<AMessage> response = new AMessage; 967 ssize_t index = doGetSelectedTrack(type); 968 response->setInt32("index", index); 969 970 sp<AReplyToken> replyID; 971 CHECK(msg->senderAwaitsResponse(&replyID)); 972 response->postReply(replyID); 973} 974 975ssize_t NuPlayer::GenericSource::doGetSelectedTrack(media_track_type type) const { 976 const Track *track = NULL; 977 switch (type) { 978 case MEDIA_TRACK_TYPE_VIDEO: 979 track = &mVideoTrack; 980 break; 981 case MEDIA_TRACK_TYPE_AUDIO: 982 track = &mAudioTrack; 983 break; 984 case MEDIA_TRACK_TYPE_TIMEDTEXT: 985 track = &mTimedTextTrack; 986 break; 987 case MEDIA_TRACK_TYPE_SUBTITLE: 988 track = &mSubtitleTrack; 989 break; 990 default: 991 break; 992 } 993 994 if (track != NULL && track->mSource != NULL) { 995 return track->mIndex; 996 } 997 998 return -1; 999} 1000 1001status_t NuPlayer::GenericSource::selectTrack(size_t trackIndex, bool select, int64_t timeUs) { 1002 ALOGV("%s track: %zu", select ? "select" : "deselect", trackIndex); 1003 sp<AMessage> msg = new AMessage(kWhatSelectTrack, this); 1004 msg->setInt32("trackIndex", trackIndex); 1005 msg->setInt32("select", select); 1006 msg->setInt64("timeUs", timeUs); 1007 1008 sp<AMessage> response; 1009 status_t err = msg->postAndAwaitResponse(&response); 1010 if (err == OK && response != NULL) { 1011 CHECK(response->findInt32("err", &err)); 1012 } 1013 1014 return err; 1015} 1016 1017void NuPlayer::GenericSource::onSelectTrack(const sp<AMessage>& msg) { 1018 int32_t trackIndex, select; 1019 int64_t timeUs; 1020 CHECK(msg->findInt32("trackIndex", &trackIndex)); 1021 CHECK(msg->findInt32("select", &select)); 1022 CHECK(msg->findInt64("timeUs", &timeUs)); 1023 1024 sp<AMessage> response = new AMessage; 1025 status_t err = doSelectTrack(trackIndex, select, timeUs); 1026 response->setInt32("err", err); 1027 1028 sp<AReplyToken> replyID; 1029 CHECK(msg->senderAwaitsResponse(&replyID)); 1030 response->postReply(replyID); 1031} 1032 1033status_t NuPlayer::GenericSource::doSelectTrack(size_t trackIndex, bool select, int64_t timeUs) { 1034 if (trackIndex >= mSources.size()) { 1035 return BAD_INDEX; 1036 } 1037 1038 if (!select) { 1039 Track* track = NULL; 1040 if (mSubtitleTrack.mSource != NULL && trackIndex == mSubtitleTrack.mIndex) { 1041 track = &mSubtitleTrack; 1042 mFetchSubtitleDataGeneration++; 1043 } else if (mTimedTextTrack.mSource != NULL && trackIndex == mTimedTextTrack.mIndex) { 1044 track = &mTimedTextTrack; 1045 mFetchTimedTextDataGeneration++; 1046 } 1047 if (track == NULL) { 1048 return INVALID_OPERATION; 1049 } 1050 track->mSource->stop(); 1051 track->mSource = NULL; 1052 track->mPackets->clear(); 1053 return OK; 1054 } 1055 1056 const sp<IMediaSource> source = mSources.itemAt(trackIndex); 1057 sp<MetaData> meta = source->getFormat(); 1058 const char *mime; 1059 CHECK(meta->findCString(kKeyMIMEType, &mime)); 1060 if (!strncasecmp(mime, "text/", 5)) { 1061 bool isSubtitle = strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP); 1062 Track *track = isSubtitle ? &mSubtitleTrack : &mTimedTextTrack; 1063 if (track->mSource != NULL && track->mIndex == trackIndex) { 1064 return OK; 1065 } 1066 track->mIndex = trackIndex; 1067 if (track->mSource != NULL) { 1068 track->mSource->stop(); 1069 } 1070 track->mSource = mSources.itemAt(trackIndex); 1071 track->mSource->start(); 1072 if (track->mPackets == NULL) { 1073 track->mPackets = new AnotherPacketSource(track->mSource->getFormat()); 1074 } else { 1075 track->mPackets->clear(); 1076 track->mPackets->setFormat(track->mSource->getFormat()); 1077 1078 } 1079 1080 if (isSubtitle) { 1081 mFetchSubtitleDataGeneration++; 1082 } else { 1083 mFetchTimedTextDataGeneration++; 1084 } 1085 1086 status_t eosResult; // ignored 1087 if (mSubtitleTrack.mSource != NULL 1088 && !mSubtitleTrack.mPackets->hasBufferAvailable(&eosResult)) { 1089 sp<AMessage> msg = new AMessage(kWhatFetchSubtitleData, this); 1090 msg->setInt64("timeUs", timeUs); 1091 msg->setInt32("generation", mFetchSubtitleDataGeneration); 1092 msg->post(); 1093 } 1094 1095 sp<AMessage> msg2 = new AMessage(kWhatSendGlobalTimedTextData, this); 1096 msg2->setInt32("generation", mFetchTimedTextDataGeneration); 1097 msg2->post(); 1098 1099 if (mTimedTextTrack.mSource != NULL 1100 && !mTimedTextTrack.mPackets->hasBufferAvailable(&eosResult)) { 1101 sp<AMessage> msg = new AMessage(kWhatFetchTimedTextData, this); 1102 msg->setInt64("timeUs", timeUs); 1103 msg->setInt32("generation", mFetchTimedTextDataGeneration); 1104 msg->post(); 1105 } 1106 1107 return OK; 1108 } else if (!strncasecmp(mime, "audio/", 6) || !strncasecmp(mime, "video/", 6)) { 1109 bool audio = !strncasecmp(mime, "audio/", 6); 1110 Track *track = audio ? &mAudioTrack : &mVideoTrack; 1111 if (track->mSource != NULL && track->mIndex == trackIndex) { 1112 return OK; 1113 } 1114 1115 sp<AMessage> msg = new AMessage(kWhatChangeAVSource, this); 1116 msg->setInt32("trackIndex", trackIndex); 1117 msg->post(); 1118 return OK; 1119 } 1120 1121 return INVALID_OPERATION; 1122} 1123 1124status_t NuPlayer::GenericSource::seekTo(int64_t seekTimeUs, MediaPlayerSeekMode mode) { 1125 sp<AMessage> msg = new AMessage(kWhatSeek, this); 1126 msg->setInt64("seekTimeUs", seekTimeUs); 1127 msg->setInt32("mode", mode); 1128 1129 sp<AMessage> response; 1130 status_t err = msg->postAndAwaitResponse(&response); 1131 if (err == OK && response != NULL) { 1132 CHECK(response->findInt32("err", &err)); 1133 } 1134 1135 return err; 1136} 1137 1138void NuPlayer::GenericSource::onSeek(const sp<AMessage>& msg) { 1139 int64_t seekTimeUs; 1140 int32_t mode; 1141 CHECK(msg->findInt64("seekTimeUs", &seekTimeUs)); 1142 CHECK(msg->findInt32("mode", &mode)); 1143 1144 sp<AMessage> response = new AMessage; 1145 status_t err = doSeek(seekTimeUs, (MediaPlayerSeekMode)mode); 1146 response->setInt32("err", err); 1147 1148 sp<AReplyToken> replyID; 1149 CHECK(msg->senderAwaitsResponse(&replyID)); 1150 response->postReply(replyID); 1151} 1152 1153status_t NuPlayer::GenericSource::doSeek(int64_t seekTimeUs, MediaPlayerSeekMode mode) { 1154 mBufferingMonitor->updateDequeuedBufferTime(-1ll); 1155 1156 // If the Widevine source is stopped, do not attempt to read any 1157 // more buffers. 1158 // 1159 // TODO: revisit after widevine is removed. May be able to 1160 // combine mStopRead with mStarted. 1161 if (mStopRead) { 1162 return INVALID_OPERATION; 1163 } 1164 if (mVideoTrack.mSource != NULL) { 1165 int64_t actualTimeUs; 1166 readBuffer(MEDIA_TRACK_TYPE_VIDEO, seekTimeUs, mode, &actualTimeUs); 1167 1168 if (mode != MediaPlayerSeekMode::SEEK_CLOSEST) { 1169 seekTimeUs = actualTimeUs; 1170 } 1171 mVideoLastDequeueTimeUs = actualTimeUs; 1172 } 1173 1174 if (mAudioTrack.mSource != NULL) { 1175 readBuffer(MEDIA_TRACK_TYPE_AUDIO, seekTimeUs); 1176 mAudioLastDequeueTimeUs = seekTimeUs; 1177 } 1178 1179 setDrmPlaybackStatusIfNeeded(Playback::START, seekTimeUs / 1000); 1180 if (!mStarted) { 1181 setDrmPlaybackStatusIfNeeded(Playback::PAUSE, 0); 1182 } 1183 1184 // If currently buffering, post kWhatBufferingEnd first, so that 1185 // NuPlayer resumes. Otherwise, if cache hits high watermark 1186 // before new polling happens, no one will resume the playback. 1187 mBufferingMonitor->stopBufferingIfNecessary(); 1188 mBufferingMonitor->restartPollBuffering(); 1189 1190 return OK; 1191} 1192 1193sp<ABuffer> NuPlayer::GenericSource::mediaBufferToABuffer( 1194 MediaBuffer* mb, 1195 media_track_type trackType) { 1196 bool audio = trackType == MEDIA_TRACK_TYPE_AUDIO; 1197 size_t outLength = mb->range_length(); 1198 1199 if (audio && mAudioIsVorbis) { 1200 outLength += sizeof(int32_t); 1201 } 1202 1203 sp<ABuffer> ab; 1204 if (mIsSecure && !audio) { 1205 // data is already provided in the buffer 1206 ab = new ABuffer(NULL, mb->range_length()); 1207 mb->add_ref(); 1208 ab->setMediaBufferBase(mb); 1209 } else { 1210 ab = new ABuffer(outLength); 1211 memcpy(ab->data(), 1212 (const uint8_t *)mb->data() + mb->range_offset(), 1213 mb->range_length()); 1214 } 1215 1216 if (audio && mAudioIsVorbis) { 1217 int32_t numPageSamples; 1218 if (!mb->meta_data()->findInt32(kKeyValidSamples, &numPageSamples)) { 1219 numPageSamples = -1; 1220 } 1221 1222 uint8_t* abEnd = ab->data() + mb->range_length(); 1223 memcpy(abEnd, &numPageSamples, sizeof(numPageSamples)); 1224 } 1225 1226 sp<AMessage> meta = ab->meta(); 1227 1228 int64_t timeUs; 1229 CHECK(mb->meta_data()->findInt64(kKeyTime, &timeUs)); 1230 meta->setInt64("timeUs", timeUs); 1231 1232 if (trackType == MEDIA_TRACK_TYPE_VIDEO) { 1233 int32_t layerId; 1234 if (mb->meta_data()->findInt32(kKeyTemporalLayerId, &layerId)) { 1235 meta->setInt32("temporal-layer-id", layerId); 1236 } 1237 } 1238 1239 if (trackType == MEDIA_TRACK_TYPE_TIMEDTEXT) { 1240 const char *mime; 1241 CHECK(mTimedTextTrack.mSource != NULL 1242 && mTimedTextTrack.mSource->getFormat()->findCString(kKeyMIMEType, &mime)); 1243 meta->setString("mime", mime); 1244 } 1245 1246 int64_t durationUs; 1247 if (mb->meta_data()->findInt64(kKeyDuration, &durationUs)) { 1248 meta->setInt64("durationUs", durationUs); 1249 } 1250 1251 if (trackType == MEDIA_TRACK_TYPE_SUBTITLE) { 1252 meta->setInt32("trackIndex", mSubtitleTrack.mIndex); 1253 } 1254 1255 uint32_t dataType; // unused 1256 const void *seiData; 1257 size_t seiLength; 1258 if (mb->meta_data()->findData(kKeySEI, &dataType, &seiData, &seiLength)) { 1259 sp<ABuffer> sei = ABuffer::CreateAsCopy(seiData, seiLength);; 1260 meta->setBuffer("sei", sei); 1261 } 1262 1263 const void *mpegUserDataPointer; 1264 size_t mpegUserDataLength; 1265 if (mb->meta_data()->findData( 1266 kKeyMpegUserData, &dataType, &mpegUserDataPointer, &mpegUserDataLength)) { 1267 sp<ABuffer> mpegUserData = ABuffer::CreateAsCopy(mpegUserDataPointer, mpegUserDataLength); 1268 meta->setBuffer("mpegUserData", mpegUserData); 1269 } 1270 1271 mb->release(); 1272 mb = NULL; 1273 1274 return ab; 1275} 1276 1277void NuPlayer::GenericSource::postReadBuffer(media_track_type trackType) { 1278 Mutex::Autolock _l(mReadBufferLock); 1279 1280 if ((mPendingReadBufferTypes & (1 << trackType)) == 0) { 1281 mPendingReadBufferTypes |= (1 << trackType); 1282 sp<AMessage> msg = new AMessage(kWhatReadBuffer, this); 1283 msg->setInt32("trackType", trackType); 1284 msg->post(); 1285 } 1286} 1287 1288void NuPlayer::GenericSource::onReadBuffer(const sp<AMessage>& msg) { 1289 int32_t tmpType; 1290 CHECK(msg->findInt32("trackType", &tmpType)); 1291 media_track_type trackType = (media_track_type)tmpType; 1292 readBuffer(trackType); 1293 { 1294 // only protect the variable change, as readBuffer may 1295 // take considerable time. 1296 Mutex::Autolock _l(mReadBufferLock); 1297 mPendingReadBufferTypes &= ~(1 << trackType); 1298 } 1299} 1300 1301void NuPlayer::GenericSource::readBuffer( 1302 media_track_type trackType, int64_t seekTimeUs, MediaPlayerSeekMode mode, 1303 int64_t *actualTimeUs, bool formatChange) { 1304 // Do not read data if Widevine source is stopped 1305 // 1306 // TODO: revisit after widevine is removed. May be able to 1307 // combine mStopRead with mStarted. 1308 if (mStopRead) { 1309 return; 1310 } 1311 Track *track; 1312 size_t maxBuffers = 1; 1313 switch (trackType) { 1314 case MEDIA_TRACK_TYPE_VIDEO: 1315 track = &mVideoTrack; 1316 maxBuffers = 8; // too large of a number may influence seeks 1317 break; 1318 case MEDIA_TRACK_TYPE_AUDIO: 1319 track = &mAudioTrack; 1320 maxBuffers = 64; 1321 break; 1322 case MEDIA_TRACK_TYPE_SUBTITLE: 1323 track = &mSubtitleTrack; 1324 break; 1325 case MEDIA_TRACK_TYPE_TIMEDTEXT: 1326 track = &mTimedTextTrack; 1327 break; 1328 default: 1329 TRESPASS(); 1330 } 1331 1332 if (track->mSource == NULL) { 1333 return; 1334 } 1335 1336 if (actualTimeUs) { 1337 *actualTimeUs = seekTimeUs; 1338 } 1339 1340 MediaSource::ReadOptions options; 1341 1342 bool seeking = false; 1343 if (seekTimeUs >= 0) { 1344 options.setSeekTo(seekTimeUs, mode); 1345 seeking = true; 1346 } 1347 1348 const bool couldReadMultiple = (track->mSource->supportReadMultiple()); 1349 1350 if (couldReadMultiple) { 1351 options.setNonBlocking(); 1352 } 1353 1354 for (size_t numBuffers = 0; numBuffers < maxBuffers; ) { 1355 Vector<MediaBuffer *> mediaBuffers; 1356 status_t err = NO_ERROR; 1357 1358 if (couldReadMultiple) { 1359 err = track->mSource->readMultiple( 1360 &mediaBuffers, maxBuffers - numBuffers, &options); 1361 } else { 1362 MediaBuffer *mbuf = NULL; 1363 err = track->mSource->read(&mbuf, &options); 1364 if (err == OK && mbuf != NULL) { 1365 mediaBuffers.push_back(mbuf); 1366 } 1367 } 1368 1369 options.clearNonPersistent(); 1370 1371 size_t id = 0; 1372 size_t count = mediaBuffers.size(); 1373 for (; id < count; ++id) { 1374 int64_t timeUs; 1375 MediaBuffer *mbuf = mediaBuffers[id]; 1376 if (!mbuf->meta_data()->findInt64(kKeyTime, &timeUs)) { 1377 mbuf->meta_data()->dumpToLog(); 1378 track->mPackets->signalEOS(ERROR_MALFORMED); 1379 break; 1380 } 1381 if (trackType == MEDIA_TRACK_TYPE_AUDIO) { 1382 mAudioTimeUs = timeUs; 1383 mBufferingMonitor->updateQueuedTime(true /* isAudio */, timeUs); 1384 } else if (trackType == MEDIA_TRACK_TYPE_VIDEO) { 1385 mVideoTimeUs = timeUs; 1386 mBufferingMonitor->updateQueuedTime(false /* isAudio */, timeUs); 1387 } 1388 1389 queueDiscontinuityIfNeeded(seeking, formatChange, trackType, track); 1390 1391 sp<ABuffer> buffer = mediaBufferToABuffer(mbuf, trackType); 1392 if (numBuffers == 0 && actualTimeUs != nullptr) { 1393 *actualTimeUs = timeUs; 1394 } 1395 if (seeking && buffer != nullptr) { 1396 sp<AMessage> meta = buffer->meta(); 1397 if (meta != nullptr && mode == MediaPlayerSeekMode::SEEK_CLOSEST 1398 && seekTimeUs > timeUs) { 1399 sp<AMessage> extra = new AMessage; 1400 extra->setInt64("resume-at-mediaTimeUs", seekTimeUs); 1401 meta->setMessage("extra", extra); 1402 } 1403 } 1404 1405 track->mPackets->queueAccessUnit(buffer); 1406 formatChange = false; 1407 seeking = false; 1408 ++numBuffers; 1409 } 1410 if (id < count) { 1411 // Error, some mediaBuffer doesn't have kKeyTime. 1412 for (; id < count; ++id) { 1413 mediaBuffers[id]->release(); 1414 } 1415 break; 1416 } 1417 1418 if (err == WOULD_BLOCK) { 1419 break; 1420 } else if (err == INFO_FORMAT_CHANGED) { 1421#if 0 1422 track->mPackets->queueDiscontinuity( 1423 ATSParser::DISCONTINUITY_FORMATCHANGE, 1424 NULL, 1425 false /* discard */); 1426#endif 1427 } else if (err != OK) { 1428 queueDiscontinuityIfNeeded(seeking, formatChange, trackType, track); 1429 track->mPackets->signalEOS(err); 1430 break; 1431 } 1432 } 1433} 1434 1435void NuPlayer::GenericSource::queueDiscontinuityIfNeeded( 1436 bool seeking, bool formatChange, media_track_type trackType, Track *track) { 1437 // formatChange && seeking: track whose source is changed during selection 1438 // formatChange && !seeking: track whose source is not changed during selection 1439 // !formatChange: normal seek 1440 if ((seeking || formatChange) 1441 && (trackType == MEDIA_TRACK_TYPE_AUDIO 1442 || trackType == MEDIA_TRACK_TYPE_VIDEO)) { 1443 ATSParser::DiscontinuityType type = (formatChange && seeking) 1444 ? ATSParser::DISCONTINUITY_FORMATCHANGE 1445 : ATSParser::DISCONTINUITY_NONE; 1446 track->mPackets->queueDiscontinuity(type, NULL /* extra */, true /* discard */); 1447 } 1448} 1449 1450NuPlayer::GenericSource::BufferingMonitor::BufferingMonitor(const sp<AMessage> ¬ify) 1451 : mNotify(notify), 1452 mDurationUs(-1ll), 1453 mBitrate(-1ll), 1454 mIsStreaming(false), 1455 mAudioTimeUs(0), 1456 mVideoTimeUs(0), 1457 mPollBufferingGeneration(0), 1458 mPrepareBuffering(false), 1459 mBuffering(false), 1460 mPrevBufferPercentage(-1), 1461 mOffloadAudio(false), 1462 mFirstDequeuedBufferRealUs(-1ll), 1463 mFirstDequeuedBufferMediaUs(-1ll), 1464 mlastDequeuedBufferMediaUs(-1ll) { 1465 getDefaultBufferingSettings(&mSettings); 1466} 1467 1468NuPlayer::GenericSource::BufferingMonitor::~BufferingMonitor() { 1469} 1470 1471void NuPlayer::GenericSource::BufferingMonitor::getDefaultBufferingSettings( 1472 BufferingSettings *buffering /* nonnull */) { 1473 buffering->mInitialBufferingMode = BUFFERING_MODE_TIME_ONLY; 1474 buffering->mRebufferingMode = BUFFERING_MODE_TIME_THEN_SIZE; 1475 buffering->mInitialWatermarkMs = kHighWaterMarkMs; 1476 buffering->mRebufferingWatermarkLowMs = kLowWaterMarkMs; 1477 buffering->mRebufferingWatermarkHighMs = kHighWaterMarkRebufferMs; 1478 buffering->mRebufferingWatermarkLowKB = kLowWaterMarkKB; 1479 buffering->mRebufferingWatermarkHighKB = kHighWaterMarkKB; 1480} 1481 1482status_t NuPlayer::GenericSource::BufferingMonitor::setBufferingSettings( 1483 const BufferingSettings &buffering) { 1484 Mutex::Autolock _l(mLock); 1485 if (buffering.IsSizeBasedBufferingMode(buffering.mInitialBufferingMode) 1486 || (buffering.IsTimeBasedBufferingMode(buffering.mRebufferingMode) 1487 && buffering.mRebufferingWatermarkLowMs > buffering.mRebufferingWatermarkHighMs) 1488 || (buffering.IsSizeBasedBufferingMode(buffering.mRebufferingMode) 1489 && buffering.mRebufferingWatermarkLowKB > buffering.mRebufferingWatermarkHighKB)) { 1490 return BAD_VALUE; 1491 } 1492 mSettings = buffering; 1493 if (mSettings.mInitialBufferingMode == BUFFERING_MODE_NONE) { 1494 mSettings.mInitialWatermarkMs = BufferingSettings::kNoWatermark; 1495 } 1496 if (!mSettings.IsTimeBasedBufferingMode(mSettings.mRebufferingMode)) { 1497 mSettings.mRebufferingWatermarkLowMs = BufferingSettings::kNoWatermark; 1498 mSettings.mRebufferingWatermarkHighMs = INT32_MAX; 1499 } 1500 if (!mSettings.IsSizeBasedBufferingMode(mSettings.mRebufferingMode)) { 1501 mSettings.mRebufferingWatermarkLowKB = BufferingSettings::kNoWatermark; 1502 mSettings.mRebufferingWatermarkHighKB = INT32_MAX; 1503 } 1504 return OK; 1505} 1506 1507void NuPlayer::GenericSource::BufferingMonitor::prepare( 1508 const sp<NuCachedSource2> &cachedSource, 1509 int64_t durationUs, 1510 int64_t bitrate, 1511 bool isStreaming) { 1512 Mutex::Autolock _l(mLock); 1513 prepare_l(cachedSource, durationUs, bitrate, isStreaming); 1514} 1515 1516void NuPlayer::GenericSource::BufferingMonitor::stop() { 1517 Mutex::Autolock _l(mLock); 1518 prepare_l(NULL /* cachedSource */, -1 /* durationUs */, 1519 -1 /* bitrate */, false /* isStreaming */); 1520} 1521 1522void NuPlayer::GenericSource::BufferingMonitor::cancelPollBuffering() { 1523 Mutex::Autolock _l(mLock); 1524 cancelPollBuffering_l(); 1525} 1526 1527void NuPlayer::GenericSource::BufferingMonitor::restartPollBuffering() { 1528 Mutex::Autolock _l(mLock); 1529 if (mIsStreaming) { 1530 cancelPollBuffering_l(); 1531 onPollBuffering_l(); 1532 } 1533} 1534 1535void NuPlayer::GenericSource::BufferingMonitor::stopBufferingIfNecessary() { 1536 Mutex::Autolock _l(mLock); 1537 stopBufferingIfNecessary_l(); 1538} 1539 1540void NuPlayer::GenericSource::BufferingMonitor::ensureCacheIsFetching() { 1541 Mutex::Autolock _l(mLock); 1542 ensureCacheIsFetching_l(); 1543} 1544 1545void NuPlayer::GenericSource::BufferingMonitor::updateQueuedTime(bool isAudio, int64_t timeUs) { 1546 Mutex::Autolock _l(mLock); 1547 if (isAudio) { 1548 mAudioTimeUs = timeUs; 1549 } else { 1550 mVideoTimeUs = timeUs; 1551 } 1552} 1553 1554void NuPlayer::GenericSource::BufferingMonitor::setOffloadAudio(bool offload) { 1555 Mutex::Autolock _l(mLock); 1556 mOffloadAudio = offload; 1557} 1558 1559void NuPlayer::GenericSource::BufferingMonitor::updateDequeuedBufferTime(int64_t mediaUs) { 1560 Mutex::Autolock _l(mLock); 1561 if (mediaUs < 0) { 1562 mFirstDequeuedBufferRealUs = -1ll; 1563 mFirstDequeuedBufferMediaUs = -1ll; 1564 } else if (mFirstDequeuedBufferRealUs < 0) { 1565 mFirstDequeuedBufferRealUs = ALooper::GetNowUs(); 1566 mFirstDequeuedBufferMediaUs = mediaUs; 1567 } 1568 mlastDequeuedBufferMediaUs = mediaUs; 1569} 1570 1571void NuPlayer::GenericSource::BufferingMonitor::prepare_l( 1572 const sp<NuCachedSource2> &cachedSource, 1573 int64_t durationUs, 1574 int64_t bitrate, 1575 bool isStreaming) { 1576 1577 mCachedSource = cachedSource; 1578 mDurationUs = durationUs; 1579 mBitrate = bitrate; 1580 mIsStreaming = isStreaming; 1581 mAudioTimeUs = 0; 1582 mVideoTimeUs = 0; 1583 mPrepareBuffering = (cachedSource != NULL); 1584 cancelPollBuffering_l(); 1585 mOffloadAudio = false; 1586 mFirstDequeuedBufferRealUs = -1ll; 1587 mFirstDequeuedBufferMediaUs = -1ll; 1588 mlastDequeuedBufferMediaUs = -1ll; 1589} 1590 1591void NuPlayer::GenericSource::BufferingMonitor::cancelPollBuffering_l() { 1592 mBuffering = false; 1593 ++mPollBufferingGeneration; 1594 mPrevBufferPercentage = -1; 1595} 1596 1597void NuPlayer::GenericSource::BufferingMonitor::notifyBufferingUpdate_l(int32_t percentage) { 1598 // Buffering percent could go backward as it's estimated from remaining 1599 // data and last access time. This could cause the buffering position 1600 // drawn on media control to jitter slightly. Remember previously reported 1601 // percentage and don't allow it to go backward. 1602 if (percentage < mPrevBufferPercentage) { 1603 percentage = mPrevBufferPercentage; 1604 } else if (percentage > 100) { 1605 percentage = 100; 1606 } 1607 1608 mPrevBufferPercentage = percentage; 1609 1610 ALOGV("notifyBufferingUpdate_l: buffering %d%%", percentage); 1611 1612 sp<AMessage> msg = mNotify->dup(); 1613 msg->setInt32("what", kWhatBufferingUpdate); 1614 msg->setInt32("percentage", percentage); 1615 msg->post(); 1616} 1617 1618void NuPlayer::GenericSource::BufferingMonitor::startBufferingIfNecessary_l() { 1619 if (mPrepareBuffering) { 1620 return; 1621 } 1622 1623 if (!mBuffering) { 1624 ALOGD("startBufferingIfNecessary_l"); 1625 1626 mBuffering = true; 1627 1628 ensureCacheIsFetching_l(); 1629 sendCacheStats_l(); 1630 1631 sp<AMessage> notify = mNotify->dup(); 1632 notify->setInt32("what", kWhatPauseOnBufferingStart); 1633 notify->post(); 1634 } 1635} 1636 1637void NuPlayer::GenericSource::BufferingMonitor::stopBufferingIfNecessary_l() { 1638 if (mPrepareBuffering) { 1639 ALOGD("stopBufferingIfNecessary_l, mBuffering=%d", mBuffering); 1640 1641 mPrepareBuffering = false; 1642 1643 sp<AMessage> notify = mNotify->dup(); 1644 notify->setInt32("what", kWhatPrepared); 1645 notify->setInt32("err", OK); 1646 notify->post(); 1647 1648 return; 1649 } 1650 1651 if (mBuffering) { 1652 ALOGD("stopBufferingIfNecessary_l"); 1653 mBuffering = false; 1654 1655 sendCacheStats_l(); 1656 1657 sp<AMessage> notify = mNotify->dup(); 1658 notify->setInt32("what", kWhatResumeOnBufferingEnd); 1659 notify->post(); 1660 } 1661} 1662 1663void NuPlayer::GenericSource::BufferingMonitor::sendCacheStats_l() { 1664 int32_t kbps = 0; 1665 status_t err = UNKNOWN_ERROR; 1666 1667 if (mCachedSource != NULL) { 1668 err = mCachedSource->getEstimatedBandwidthKbps(&kbps); 1669 } 1670 1671 if (err == OK) { 1672 sp<AMessage> notify = mNotify->dup(); 1673 notify->setInt32("what", kWhatCacheStats); 1674 notify->setInt32("bandwidth", kbps); 1675 notify->post(); 1676 } 1677} 1678 1679void NuPlayer::GenericSource::BufferingMonitor::ensureCacheIsFetching_l() { 1680 if (mCachedSource != NULL) { 1681 mCachedSource->resumeFetchingIfNecessary(); 1682 } 1683} 1684 1685void NuPlayer::GenericSource::BufferingMonitor::schedulePollBuffering_l() { 1686 sp<AMessage> msg = new AMessage(kWhatPollBuffering, this); 1687 msg->setInt32("generation", mPollBufferingGeneration); 1688 // Enquires buffering status every second. 1689 msg->post(1000000ll); 1690} 1691 1692int64_t NuPlayer::GenericSource::BufferingMonitor::getLastReadPosition_l() { 1693 if (mAudioTimeUs > 0) { 1694 return mAudioTimeUs; 1695 } else if (mVideoTimeUs > 0) { 1696 return mVideoTimeUs; 1697 } else { 1698 return 0; 1699 } 1700} 1701 1702void NuPlayer::GenericSource::BufferingMonitor::onPollBuffering_l() { 1703 status_t finalStatus = UNKNOWN_ERROR; 1704 int64_t cachedDurationUs = -1ll; 1705 ssize_t cachedDataRemaining = -1; 1706 1707 if (mCachedSource != NULL) { 1708 cachedDataRemaining = 1709 mCachedSource->approxDataRemaining(&finalStatus); 1710 1711 if (finalStatus == OK) { 1712 off64_t size; 1713 int64_t bitrate = 0ll; 1714 if (mDurationUs > 0 && mCachedSource->getSize(&size) == OK) { 1715 // |bitrate| uses bits/second unit, while size is number of bytes. 1716 bitrate = size * 8000000ll / mDurationUs; 1717 } else if (mBitrate > 0) { 1718 bitrate = mBitrate; 1719 } 1720 if (bitrate > 0) { 1721 cachedDurationUs = cachedDataRemaining * 8000000ll / bitrate; 1722 } 1723 } 1724 } 1725 1726 if (finalStatus != OK) { 1727 ALOGV("onPollBuffering_l: EOS (finalStatus = %d)", finalStatus); 1728 1729 if (finalStatus == ERROR_END_OF_STREAM) { 1730 notifyBufferingUpdate_l(100); 1731 } 1732 1733 stopBufferingIfNecessary_l(); 1734 return; 1735 } 1736 1737 if (cachedDurationUs >= 0ll) { 1738 if (mDurationUs > 0ll) { 1739 int64_t cachedPosUs = getLastReadPosition_l() + cachedDurationUs; 1740 int percentage = 100.0 * cachedPosUs / mDurationUs; 1741 if (percentage > 100) { 1742 percentage = 100; 1743 } 1744 1745 notifyBufferingUpdate_l(percentage); 1746 } 1747 1748 ALOGV("onPollBuffering_l: cachedDurationUs %.1f sec", cachedDurationUs / 1000000.0f); 1749 1750 if (mPrepareBuffering) { 1751 if (cachedDurationUs > mSettings.mInitialWatermarkMs * 1000) { 1752 stopBufferingIfNecessary_l(); 1753 } 1754 } else if (mSettings.IsTimeBasedBufferingMode(mSettings.mRebufferingMode)) { 1755 if (cachedDurationUs < mSettings.mRebufferingWatermarkLowMs * 1000) { 1756 // Take into account the data cached in downstream components to try to avoid 1757 // unnecessary pause. 1758 if (mOffloadAudio && mFirstDequeuedBufferRealUs >= 0) { 1759 int64_t downStreamCacheUs = 1760 mlastDequeuedBufferMediaUs - mFirstDequeuedBufferMediaUs 1761 - (ALooper::GetNowUs() - mFirstDequeuedBufferRealUs); 1762 if (downStreamCacheUs > 0) { 1763 cachedDurationUs += downStreamCacheUs; 1764 } 1765 } 1766 1767 if (cachedDurationUs < mSettings.mRebufferingWatermarkLowMs * 1000) { 1768 startBufferingIfNecessary_l(); 1769 } 1770 } else if (cachedDurationUs > mSettings.mRebufferingWatermarkHighMs * 1000) { 1771 stopBufferingIfNecessary_l(); 1772 } 1773 } 1774 } else if (cachedDataRemaining >= 0 1775 && mSettings.IsSizeBasedBufferingMode(mSettings.mRebufferingMode)) { 1776 ALOGV("onPollBuffering_l: cachedDataRemaining %zd bytes", 1777 cachedDataRemaining); 1778 1779 if (cachedDataRemaining < (mSettings.mRebufferingWatermarkLowKB << 10)) { 1780 startBufferingIfNecessary_l(); 1781 } else if (cachedDataRemaining > (mSettings.mRebufferingWatermarkHighKB << 10)) { 1782 stopBufferingIfNecessary_l(); 1783 } 1784 } 1785 1786 schedulePollBuffering_l(); 1787} 1788 1789void NuPlayer::GenericSource::BufferingMonitor::onMessageReceived(const sp<AMessage> &msg) { 1790 switch (msg->what()) { 1791 case kWhatPollBuffering: 1792 { 1793 int32_t generation; 1794 CHECK(msg->findInt32("generation", &generation)); 1795 Mutex::Autolock _l(mLock); 1796 if (generation == mPollBufferingGeneration) { 1797 onPollBuffering_l(); 1798 } 1799 break; 1800 } 1801 default: 1802 TRESPASS(); 1803 break; 1804 } 1805} 1806 1807} // namespace android 1808