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