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