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