GenericSource.cpp revision ac6b30acb174dbdf35f845924cd63bdc48c43e8a
1/* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17//#define LOG_NDEBUG 0 18#define LOG_TAG "GenericSource" 19 20#include "GenericSource.h" 21 22#include "AnotherPacketSource.h" 23 24#include <media/IMediaHTTPService.h> 25#include <media/stagefright/foundation/ABuffer.h> 26#include <media/stagefright/foundation/ADebug.h> 27#include <media/stagefright/foundation/AMessage.h> 28#include <media/stagefright/DataSource.h> 29#include <media/stagefright/FileSource.h> 30#include <media/stagefright/MediaBuffer.h> 31#include <media/stagefright/MediaDefs.h> 32#include <media/stagefright/MediaExtractor.h> 33#include <media/stagefright/MediaSource.h> 34#include <media/stagefright/MetaData.h> 35#include <media/stagefright/Utils.h> 36#include "../../libstagefright/include/NuCachedSource2.h" 37#include "../../libstagefright/include/HTTPBase.h" 38 39namespace android { 40 41static int64_t kLowWaterMarkUs = 2000000ll; // 2secs 42static int64_t kHighWaterMarkUs = 5000000ll; // 5secs 43static int64_t kHighWaterMarkRebufferUs = 15000000ll; // 15secs 44static const ssize_t kLowWaterMarkBytes = 40000; 45static const ssize_t kHighWaterMarkBytes = 200000; 46 47NuPlayer::GenericSource::GenericSource( 48 const sp<AMessage> ¬ify, 49 bool uidValid, 50 uid_t uid) 51 : Source(notify), 52 mAudioTimeUs(0), 53 mAudioLastDequeueTimeUs(0), 54 mVideoTimeUs(0), 55 mVideoLastDequeueTimeUs(0), 56 mFetchSubtitleDataGeneration(0), 57 mFetchTimedTextDataGeneration(0), 58 mDurationUs(-1ll), 59 mAudioIsVorbis(false), 60 mIsSecure(false), 61 mIsStreaming(false), 62 mUIDValid(uidValid), 63 mUID(uid), 64 mFd(-1), 65 mDrmManagerClient(NULL), 66 mBitrate(-1ll), 67 mPendingReadBufferTypes(0) { 68 mBufferingMonitor = new BufferingMonitor(notify); 69 resetDataSource(); 70} 71 72void NuPlayer::GenericSource::resetDataSource() { 73 mHTTPService.clear(); 74 mHttpSource.clear(); 75 mUri.clear(); 76 mUriHeaders.clear(); 77 if (mFd >= 0) { 78 close(mFd); 79 mFd = -1; 80 } 81 mOffset = 0; 82 mLength = 0; 83 setDrmPlaybackStatusIfNeeded(Playback::STOP, 0); 84 mDecryptHandle = NULL; 85 mDrmManagerClient = NULL; 86 mStarted = false; 87 mStopRead = true; 88 89 if (mBufferingMonitorLooper != NULL) { 90 mBufferingMonitorLooper->unregisterHandler(mBufferingMonitor->id()); 91 mBufferingMonitorLooper->stop(); 92 mBufferingMonitorLooper = NULL; 93 } 94 mBufferingMonitor->stop(); 95} 96 97status_t NuPlayer::GenericSource::setDataSource( 98 const sp<IMediaHTTPService> &httpService, 99 const char *url, 100 const KeyedVector<String8, String8> *headers) { 101 resetDataSource(); 102 103 mHTTPService = httpService; 104 mUri = url; 105 106 if (headers) { 107 mUriHeaders = *headers; 108 } 109 110 // delay data source creation to prepareAsync() to avoid blocking 111 // the calling thread in setDataSource for any significant time. 112 return OK; 113} 114 115status_t NuPlayer::GenericSource::setDataSource( 116 int fd, int64_t offset, int64_t length) { 117 resetDataSource(); 118 119 mFd = dup(fd); 120 mOffset = offset; 121 mLength = length; 122 123 // delay data source creation to prepareAsync() to avoid blocking 124 // the calling thread in setDataSource for any significant time. 125 return OK; 126} 127 128status_t NuPlayer::GenericSource::setDataSource(const sp<DataSource>& source) { 129 resetDataSource(); 130 mDataSource = source; 131 return OK; 132} 133 134sp<MetaData> NuPlayer::GenericSource::getFileFormatMeta() const { 135 return mFileMeta; 136} 137 138status_t NuPlayer::GenericSource::initFromDataSource() { 139 sp<IMediaExtractor> extractor; 140 CHECK(mDataSource != NULL); 141 142 extractor = MediaExtractor::Create(mDataSource, NULL); 143 144 if (extractor == NULL) { 145 return UNKNOWN_ERROR; 146 } 147 148 if (extractor->getDrmFlag()) { 149 checkDrmStatus(mDataSource); 150 } 151 152 mFileMeta = extractor->getMetaData(); 153 if (mFileMeta != NULL) { 154 int64_t duration; 155 if (mFileMeta->findInt64(kKeyDuration, &duration)) { 156 mDurationUs = duration; 157 } 158 } 159 160 int32_t totalBitrate = 0; 161 162 size_t numtracks = extractor->countTracks(); 163 if (numtracks == 0) { 164 return UNKNOWN_ERROR; 165 } 166 167 for (size_t i = 0; i < numtracks; ++i) { 168 sp<IMediaSource> track = extractor->getTrack(i); 169 if (track == NULL) { 170 continue; 171 } 172 173 sp<MetaData> meta = extractor->getTrackMetaData(i); 174 if (meta == NULL) { 175 ALOGE("no metadata for track %zu", i); 176 return UNKNOWN_ERROR; 177 } 178 179 const char *mime; 180 CHECK(meta->findCString(kKeyMIMEType, &mime)); 181 182 // Do the string compare immediately with "mime", 183 // we can't assume "mime" would stay valid after another 184 // extractor operation, some extractors might modify meta 185 // during getTrack() and make it invalid. 186 if (!strncasecmp(mime, "audio/", 6)) { 187 if (mAudioTrack.mSource == NULL) { 188 mAudioTrack.mIndex = i; 189 mAudioTrack.mSource = track; 190 mAudioTrack.mPackets = 191 new AnotherPacketSource(mAudioTrack.mSource->getFormat()); 192 193 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) { 194 mAudioIsVorbis = true; 195 } else { 196 mAudioIsVorbis = false; 197 } 198 } 199 } else if (!strncasecmp(mime, "video/", 6)) { 200 if (mVideoTrack.mSource == NULL) { 201 mVideoTrack.mIndex = i; 202 mVideoTrack.mSource = track; 203 mVideoTrack.mPackets = 204 new AnotherPacketSource(mVideoTrack.mSource->getFormat()); 205 206 // check if the source requires secure buffers 207 int32_t secure; 208 if (meta->findInt32(kKeyRequiresSecureBuffers, &secure) 209 && secure) { 210 mIsSecure = true; 211 if (mUIDValid) { 212 extractor->setUID(mUID); 213 } 214 } 215 } 216 } 217 218 mSources.push(track); 219 int64_t durationUs; 220 if (meta->findInt64(kKeyDuration, &durationUs)) { 221 if (durationUs > mDurationUs) { 222 mDurationUs = durationUs; 223 } 224 } 225 226 int32_t bitrate; 227 if (totalBitrate >= 0 && meta->findInt32(kKeyBitRate, &bitrate)) { 228 totalBitrate += bitrate; 229 } else { 230 totalBitrate = -1; 231 } 232 } 233 234 if (mSources.size() == 0) { 235 ALOGE("b/23705695"); 236 return UNKNOWN_ERROR; 237 } 238 239 mBitrate = totalBitrate; 240 241 return OK; 242} 243 244status_t NuPlayer::GenericSource::startSources() { 245 // Start the selected A/V tracks now before we start buffering. 246 // Widevine sources might re-initialize crypto when starting, if we delay 247 // this to start(), all data buffered during prepare would be wasted. 248 // (We don't actually start reading until start().) 249 // 250 // TODO: this logic may no longer be relevant after the removal of widevine 251 // support 252 if (mAudioTrack.mSource != NULL && mAudioTrack.mSource->start() != OK) { 253 ALOGE("failed to start audio track!"); 254 return UNKNOWN_ERROR; 255 } 256 257 if (mVideoTrack.mSource != NULL && mVideoTrack.mSource->start() != OK) { 258 ALOGE("failed to start video track!"); 259 return UNKNOWN_ERROR; 260 } 261 262 return OK; 263} 264 265void NuPlayer::GenericSource::checkDrmStatus(const sp<DataSource>& dataSource) { 266 dataSource->getDrmInfo(mDecryptHandle, &mDrmManagerClient); 267 if (mDecryptHandle != NULL) { 268 CHECK(mDrmManagerClient); 269 if (RightsStatus::RIGHTS_VALID != mDecryptHandle->status) { 270 sp<AMessage> msg = dupNotify(); 271 msg->setInt32("what", kWhatDrmNoLicense); 272 msg->post(); 273 } 274 } 275} 276 277int64_t NuPlayer::GenericSource::getLastReadPosition() { 278 if (mAudioTrack.mSource != NULL) { 279 return mAudioTimeUs; 280 } else if (mVideoTrack.mSource != NULL) { 281 return mVideoTimeUs; 282 } else { 283 return 0; 284 } 285} 286 287status_t NuPlayer::GenericSource::setBuffers( 288 bool audio, Vector<MediaBuffer *> &buffers) { 289 if (mIsSecure && !audio && mVideoTrack.mSource != NULL) { 290 return mVideoTrack.mSource->setBuffers(buffers); 291 } 292 return INVALID_OPERATION; 293} 294 295bool NuPlayer::GenericSource::isStreaming() const { 296 return mIsStreaming; 297} 298 299void NuPlayer::GenericSource::setOffloadAudio(bool offload) { 300 mBufferingMonitor->setOffloadAudio(offload); 301} 302 303NuPlayer::GenericSource::~GenericSource() { 304 if (mLooper != NULL) { 305 mLooper->unregisterHandler(id()); 306 mLooper->stop(); 307 } 308 resetDataSource(); 309} 310 311void NuPlayer::GenericSource::prepareAsync() { 312 if (mLooper == NULL) { 313 mLooper = new ALooper; 314 mLooper->setName("generic"); 315 mLooper->start(); 316 317 mLooper->registerHandler(this); 318 } 319 320 sp<AMessage> msg = new AMessage(kWhatPrepareAsync, this); 321 msg->post(); 322} 323 324void NuPlayer::GenericSource::onPrepareAsync() { 325 // delayed data source creation 326 if (mDataSource == NULL) { 327 // set to false first, if the extractor 328 // comes back as secure, set it to true then. 329 mIsSecure = false; 330 331 if (!mUri.empty()) { 332 const char* uri = mUri.c_str(); 333 String8 contentType; 334 335 if (!strncasecmp("http://", uri, 7) || !strncasecmp("https://", uri, 8)) { 336 mHttpSource = DataSource::CreateMediaHTTP(mHTTPService); 337 if (mHttpSource == NULL) { 338 ALOGE("Failed to create http source!"); 339 notifyPreparedAndCleanup(UNKNOWN_ERROR); 340 return; 341 } 342 } 343 344 mDataSource = DataSource::CreateFromURI( 345 mHTTPService, uri, &mUriHeaders, &contentType, 346 static_cast<HTTPBase *>(mHttpSource.get())); 347 } else { 348 mDataSource = new FileSource(mFd, mOffset, mLength); 349 mFd = -1; 350 } 351 352 if (mDataSource == NULL) { 353 ALOGE("Failed to create data source!"); 354 notifyPreparedAndCleanup(UNKNOWN_ERROR); 355 return; 356 } 357 } 358 359 if (mDataSource->flags() & DataSource::kIsCachingDataSource) { 360 mCachedSource = static_cast<NuCachedSource2 *>(mDataSource.get()); 361 } 362 363 // For cached streaming cases, we need to wait for enough 364 // buffering before reporting prepared. 365 mIsStreaming = (mCachedSource != NULL); 366 367 // init extractor from data source 368 status_t err = initFromDataSource(); 369 370 if (err != OK) { 371 ALOGE("Failed to init from data source!"); 372 notifyPreparedAndCleanup(err); 373 return; 374 } 375 376 if (mVideoTrack.mSource != NULL) { 377 sp<MetaData> meta = doGetFormatMeta(false /* audio */); 378 sp<AMessage> msg = new AMessage; 379 err = convertMetaDataToMessage(meta, &msg); 380 if(err != OK) { 381 notifyPreparedAndCleanup(err); 382 return; 383 } 384 notifyVideoSizeChanged(msg); 385 } 386 387 notifyFlagsChanged( 388 (mIsSecure ? FLAG_SECURE : 0) 389 | (mDecryptHandle != NULL ? FLAG_PROTECTED : 0) 390 | FLAG_CAN_PAUSE 391 | FLAG_CAN_SEEK_BACKWARD 392 | FLAG_CAN_SEEK_FORWARD 393 | FLAG_CAN_SEEK); 394 395 if (mIsSecure) { 396 // secure decoders must be instantiated before starting widevine source 397 // 398 // TODO: mIsSecure and FLAG_SECURE may be obsolete, revisit after 399 // removing widevine 400 sp<AMessage> reply = new AMessage(kWhatSecureDecodersInstantiated, this); 401 notifyInstantiateSecureDecoders(reply); 402 } else { 403 finishPrepareAsync(); 404 } 405} 406 407void NuPlayer::GenericSource::onSecureDecodersInstantiated(status_t err) { 408 if (err != OK) { 409 ALOGE("Failed to instantiate secure decoders!"); 410 notifyPreparedAndCleanup(err); 411 return; 412 } 413 finishPrepareAsync(); 414} 415 416void NuPlayer::GenericSource::finishPrepareAsync() { 417 status_t err = startSources(); 418 if (err != OK) { 419 ALOGE("Failed to init start data source!"); 420 notifyPreparedAndCleanup(err); 421 return; 422 } 423 424 if (mIsStreaming) { 425 if (mBufferingMonitorLooper == NULL) { 426 mBufferingMonitor->prepare(mCachedSource, mDurationUs, mBitrate, 427 mIsStreaming); 428 429 mBufferingMonitorLooper = new ALooper; 430 mBufferingMonitorLooper->setName("GSBMonitor"); 431 mBufferingMonitorLooper->start(); 432 mBufferingMonitorLooper->registerHandler(mBufferingMonitor); 433 } 434 435 mBufferingMonitor->ensureCacheIsFetching(); 436 mBufferingMonitor->restartPollBuffering(); 437 } else { 438 notifyPrepared(); 439 } 440} 441 442void NuPlayer::GenericSource::notifyPreparedAndCleanup(status_t err) { 443 if (err != OK) { 444 { 445 sp<DataSource> dataSource = mDataSource; 446 sp<NuCachedSource2> cachedSource = mCachedSource; 447 sp<DataSource> httpSource = mHttpSource; 448 { 449 Mutex::Autolock _l(mDisconnectLock); 450 mDataSource.clear(); 451 mDecryptHandle = NULL; 452 mDrmManagerClient = NULL; 453 mCachedSource.clear(); 454 mHttpSource.clear(); 455 } 456 } 457 mBitrate = -1; 458 459 mBufferingMonitor->cancelPollBuffering(); 460 } 461 notifyPrepared(err); 462} 463 464void NuPlayer::GenericSource::start() { 465 ALOGI("start"); 466 467 mStopRead = false; 468 if (mAudioTrack.mSource != NULL) { 469 postReadBuffer(MEDIA_TRACK_TYPE_AUDIO); 470 } 471 472 if (mVideoTrack.mSource != NULL) { 473 postReadBuffer(MEDIA_TRACK_TYPE_VIDEO); 474 } 475 476 setDrmPlaybackStatusIfNeeded(Playback::START, getLastReadPosition() / 1000); 477 mStarted = true; 478 479 (new AMessage(kWhatStart, this))->post(); 480} 481 482void NuPlayer::GenericSource::stop() { 483 // nothing to do, just account for DRM playback status 484 setDrmPlaybackStatusIfNeeded(Playback::STOP, 0); 485 mStarted = false; 486} 487 488void NuPlayer::GenericSource::pause() { 489 // nothing to do, just account for DRM playback status 490 setDrmPlaybackStatusIfNeeded(Playback::PAUSE, 0); 491 mStarted = false; 492} 493 494void NuPlayer::GenericSource::resume() { 495 // nothing to do, just account for DRM playback status 496 setDrmPlaybackStatusIfNeeded(Playback::START, getLastReadPosition() / 1000); 497 mStarted = true; 498 499 (new AMessage(kWhatResume, this))->post(); 500} 501 502void NuPlayer::GenericSource::disconnect() { 503 sp<DataSource> dataSource, httpSource; 504 { 505 Mutex::Autolock _l(mDisconnectLock); 506 dataSource = mDataSource; 507 httpSource = mHttpSource; 508 } 509 510 if (dataSource != NULL) { 511 // disconnect data source 512 if (dataSource->flags() & DataSource::kIsCachingDataSource) { 513 static_cast<NuCachedSource2 *>(dataSource.get())->disconnect(); 514 } 515 } else if (httpSource != NULL) { 516 static_cast<HTTPBase *>(httpSource.get())->disconnect(); 517 } 518} 519 520void NuPlayer::GenericSource::setDrmPlaybackStatusIfNeeded(int playbackStatus, int64_t position) { 521 if (mDecryptHandle != NULL) { 522 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, playbackStatus, position); 523 } 524 mSubtitleTrack.mPackets = new AnotherPacketSource(NULL); 525 mTimedTextTrack.mPackets = new AnotherPacketSource(NULL); 526} 527 528status_t NuPlayer::GenericSource::feedMoreTSData() { 529 return OK; 530} 531 532void NuPlayer::GenericSource::onMessageReceived(const sp<AMessage> &msg) { 533 switch (msg->what()) { 534 case kWhatPrepareAsync: 535 { 536 onPrepareAsync(); 537 break; 538 } 539 case kWhatFetchSubtitleData: 540 { 541 fetchTextData(kWhatSendSubtitleData, MEDIA_TRACK_TYPE_SUBTITLE, 542 mFetchSubtitleDataGeneration, mSubtitleTrack.mPackets, msg); 543 break; 544 } 545 546 case kWhatFetchTimedTextData: 547 { 548 fetchTextData(kWhatSendTimedTextData, MEDIA_TRACK_TYPE_TIMEDTEXT, 549 mFetchTimedTextDataGeneration, mTimedTextTrack.mPackets, msg); 550 break; 551 } 552 553 case kWhatSendSubtitleData: 554 { 555 sendTextData(kWhatSubtitleData, MEDIA_TRACK_TYPE_SUBTITLE, 556 mFetchSubtitleDataGeneration, mSubtitleTrack.mPackets, msg); 557 break; 558 } 559 560 case kWhatSendGlobalTimedTextData: 561 { 562 sendGlobalTextData(kWhatTimedTextData, mFetchTimedTextDataGeneration, msg); 563 break; 564 } 565 case kWhatSendTimedTextData: 566 { 567 sendTextData(kWhatTimedTextData, MEDIA_TRACK_TYPE_TIMEDTEXT, 568 mFetchTimedTextDataGeneration, mTimedTextTrack.mPackets, msg); 569 break; 570 } 571 572 case kWhatChangeAVSource: 573 { 574 int32_t trackIndex; 575 CHECK(msg->findInt32("trackIndex", &trackIndex)); 576 const sp<IMediaSource> source = mSources.itemAt(trackIndex); 577 578 Track* track; 579 const char *mime; 580 media_track_type trackType, counterpartType; 581 sp<MetaData> meta = source->getFormat(); 582 meta->findCString(kKeyMIMEType, &mime); 583 if (!strncasecmp(mime, "audio/", 6)) { 584 track = &mAudioTrack; 585 trackType = MEDIA_TRACK_TYPE_AUDIO; 586 counterpartType = MEDIA_TRACK_TYPE_VIDEO;; 587 } else { 588 CHECK(!strncasecmp(mime, "video/", 6)); 589 track = &mVideoTrack; 590 trackType = MEDIA_TRACK_TYPE_VIDEO; 591 counterpartType = MEDIA_TRACK_TYPE_AUDIO;; 592 } 593 594 595 if (track->mSource != NULL) { 596 track->mSource->stop(); 597 } 598 track->mSource = source; 599 track->mSource->start(); 600 track->mIndex = trackIndex; 601 602 int64_t timeUs, actualTimeUs; 603 const bool formatChange = true; 604 if (trackType == MEDIA_TRACK_TYPE_AUDIO) { 605 timeUs = mAudioLastDequeueTimeUs; 606 } else { 607 timeUs = mVideoLastDequeueTimeUs; 608 } 609 readBuffer(trackType, timeUs, MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC /* mode */, 610 &actualTimeUs, formatChange); 611 readBuffer(counterpartType, -1, MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC /* mode */, 612 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, MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC /* mode */, &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, MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC /* mode */, &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, MediaPlayerSeekMode mode) { 1114 sp<AMessage> msg = new AMessage(kWhatSeek, this); 1115 msg->setInt64("seekTimeUs", seekTimeUs); 1116 msg->setInt32("mode", mode); 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 mode; 1130 CHECK(msg->findInt64("seekTimeUs", &seekTimeUs)); 1131 CHECK(msg->findInt32("mode", &mode)); 1132 1133 sp<AMessage> response = new AMessage; 1134 status_t err = doSeek(seekTimeUs, (MediaPlayerSeekMode)mode); 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, MediaPlayerSeekMode mode) { 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, mode, &actualTimeUs); 1156 1157 if (mode != MediaPlayerSeekMode::SEEK_CLOSEST) { 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, MediaPlayerSeekMode mode, 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, mode); 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 && mode == MediaPlayerSeekMode::SEEK_CLOSEST 1387 && seekTimeUs > timeUs) { 1388 sp<AMessage> extra = new AMessage; 1389 extra->setInt64("resume-at-mediaTimeUs", seekTimeUs); 1390 meta->setMessage("extra", extra); 1391 } 1392 } 1393 1394 track->mPackets->queueAccessUnit(buffer); 1395 formatChange = false; 1396 seeking = false; 1397 ++numBuffers; 1398 } 1399 if (id < count) { 1400 // Error, some mediaBuffer doesn't have kKeyTime. 1401 for (; id < count; ++id) { 1402 mediaBuffers[id]->release(); 1403 } 1404 break; 1405 } 1406 1407 if (err == WOULD_BLOCK) { 1408 break; 1409 } else if (err == INFO_FORMAT_CHANGED) { 1410#if 0 1411 track->mPackets->queueDiscontinuity( 1412 ATSParser::DISCONTINUITY_FORMATCHANGE, 1413 NULL, 1414 false /* discard */); 1415#endif 1416 } else if (err != OK) { 1417 queueDiscontinuityIfNeeded(seeking, formatChange, trackType, track); 1418 track->mPackets->signalEOS(err); 1419 break; 1420 } 1421 } 1422} 1423 1424void NuPlayer::GenericSource::queueDiscontinuityIfNeeded( 1425 bool seeking, bool formatChange, media_track_type trackType, Track *track) { 1426 // formatChange && seeking: track whose source is changed during selection 1427 // formatChange && !seeking: track whose source is not changed during selection 1428 // !formatChange: normal seek 1429 if ((seeking || formatChange) 1430 && (trackType == MEDIA_TRACK_TYPE_AUDIO 1431 || trackType == MEDIA_TRACK_TYPE_VIDEO)) { 1432 ATSParser::DiscontinuityType type = (formatChange && seeking) 1433 ? ATSParser::DISCONTINUITY_FORMATCHANGE 1434 : ATSParser::DISCONTINUITY_NONE; 1435 track->mPackets->queueDiscontinuity(type, NULL /* extra */, true /* discard */); 1436 } 1437} 1438 1439NuPlayer::GenericSource::BufferingMonitor::BufferingMonitor(const sp<AMessage> ¬ify) 1440 : mNotify(notify), 1441 mDurationUs(-1ll), 1442 mBitrate(-1ll), 1443 mIsStreaming(false), 1444 mAudioTimeUs(0), 1445 mVideoTimeUs(0), 1446 mPollBufferingGeneration(0), 1447 mPrepareBuffering(false), 1448 mBuffering(false), 1449 mPrevBufferPercentage(-1), 1450 mOffloadAudio(false), 1451 mFirstDequeuedBufferRealUs(-1ll), 1452 mFirstDequeuedBufferMediaUs(-1ll), 1453 mlastDequeuedBufferMediaUs(-1ll) { 1454} 1455 1456NuPlayer::GenericSource::BufferingMonitor::~BufferingMonitor() { 1457} 1458 1459void NuPlayer::GenericSource::BufferingMonitor::prepare( 1460 const sp<NuCachedSource2> &cachedSource, 1461 int64_t durationUs, 1462 int64_t bitrate, 1463 bool isStreaming) { 1464 Mutex::Autolock _l(mLock); 1465 prepare_l(cachedSource, durationUs, bitrate, isStreaming); 1466} 1467 1468void NuPlayer::GenericSource::BufferingMonitor::stop() { 1469 Mutex::Autolock _l(mLock); 1470 prepare_l(NULL /* cachedSource */, -1 /* durationUs */, 1471 -1 /* bitrate */, false /* isStreaming */); 1472} 1473 1474void NuPlayer::GenericSource::BufferingMonitor::cancelPollBuffering() { 1475 Mutex::Autolock _l(mLock); 1476 cancelPollBuffering_l(); 1477} 1478 1479void NuPlayer::GenericSource::BufferingMonitor::restartPollBuffering() { 1480 Mutex::Autolock _l(mLock); 1481 if (mIsStreaming) { 1482 cancelPollBuffering_l(); 1483 onPollBuffering_l(); 1484 } 1485} 1486 1487void NuPlayer::GenericSource::BufferingMonitor::stopBufferingIfNecessary() { 1488 Mutex::Autolock _l(mLock); 1489 stopBufferingIfNecessary_l(); 1490} 1491 1492void NuPlayer::GenericSource::BufferingMonitor::ensureCacheIsFetching() { 1493 Mutex::Autolock _l(mLock); 1494 ensureCacheIsFetching_l(); 1495} 1496 1497void NuPlayer::GenericSource::BufferingMonitor::updateQueuedTime(bool isAudio, int64_t timeUs) { 1498 Mutex::Autolock _l(mLock); 1499 if (isAudio) { 1500 mAudioTimeUs = timeUs; 1501 } else { 1502 mVideoTimeUs = timeUs; 1503 } 1504} 1505 1506void NuPlayer::GenericSource::BufferingMonitor::setOffloadAudio(bool offload) { 1507 Mutex::Autolock _l(mLock); 1508 mOffloadAudio = offload; 1509} 1510 1511void NuPlayer::GenericSource::BufferingMonitor::updateDequeuedBufferTime(int64_t mediaUs) { 1512 Mutex::Autolock _l(mLock); 1513 if (mediaUs < 0) { 1514 mFirstDequeuedBufferRealUs = -1ll; 1515 mFirstDequeuedBufferMediaUs = -1ll; 1516 } else if (mFirstDequeuedBufferRealUs < 0) { 1517 mFirstDequeuedBufferRealUs = ALooper::GetNowUs(); 1518 mFirstDequeuedBufferMediaUs = mediaUs; 1519 } 1520 mlastDequeuedBufferMediaUs = mediaUs; 1521} 1522 1523void NuPlayer::GenericSource::BufferingMonitor::prepare_l( 1524 const sp<NuCachedSource2> &cachedSource, 1525 int64_t durationUs, 1526 int64_t bitrate, 1527 bool isStreaming) { 1528 1529 mCachedSource = cachedSource; 1530 mDurationUs = durationUs; 1531 mBitrate = bitrate; 1532 mIsStreaming = isStreaming; 1533 mAudioTimeUs = 0; 1534 mVideoTimeUs = 0; 1535 mPrepareBuffering = (cachedSource != NULL); 1536 cancelPollBuffering_l(); 1537 mOffloadAudio = false; 1538 mFirstDequeuedBufferRealUs = -1ll; 1539 mFirstDequeuedBufferMediaUs = -1ll; 1540 mlastDequeuedBufferMediaUs = -1ll; 1541} 1542 1543void NuPlayer::GenericSource::BufferingMonitor::cancelPollBuffering_l() { 1544 mBuffering = false; 1545 ++mPollBufferingGeneration; 1546 mPrevBufferPercentage = -1; 1547} 1548 1549void NuPlayer::GenericSource::BufferingMonitor::notifyBufferingUpdate_l(int32_t percentage) { 1550 // Buffering percent could go backward as it's estimated from remaining 1551 // data and last access time. This could cause the buffering position 1552 // drawn on media control to jitter slightly. Remember previously reported 1553 // percentage and don't allow it to go backward. 1554 if (percentage < mPrevBufferPercentage) { 1555 percentage = mPrevBufferPercentage; 1556 } else if (percentage > 100) { 1557 percentage = 100; 1558 } 1559 1560 mPrevBufferPercentage = percentage; 1561 1562 ALOGV("notifyBufferingUpdate_l: buffering %d%%", percentage); 1563 1564 sp<AMessage> msg = mNotify->dup(); 1565 msg->setInt32("what", kWhatBufferingUpdate); 1566 msg->setInt32("percentage", percentage); 1567 msg->post(); 1568} 1569 1570void NuPlayer::GenericSource::BufferingMonitor::startBufferingIfNecessary_l() { 1571 if (mPrepareBuffering) { 1572 return; 1573 } 1574 1575 if (!mBuffering) { 1576 ALOGD("startBufferingIfNecessary_l"); 1577 1578 mBuffering = true; 1579 1580 ensureCacheIsFetching_l(); 1581 sendCacheStats_l(); 1582 1583 sp<AMessage> notify = mNotify->dup(); 1584 notify->setInt32("what", kWhatPauseOnBufferingStart); 1585 notify->post(); 1586 } 1587} 1588 1589void NuPlayer::GenericSource::BufferingMonitor::stopBufferingIfNecessary_l() { 1590 if (mPrepareBuffering) { 1591 ALOGD("stopBufferingIfNecessary_l, mBuffering=%d", mBuffering); 1592 1593 mPrepareBuffering = false; 1594 1595 sp<AMessage> notify = mNotify->dup(); 1596 notify->setInt32("what", kWhatPrepared); 1597 notify->setInt32("err", OK); 1598 notify->post(); 1599 1600 return; 1601 } 1602 1603 if (mBuffering) { 1604 ALOGD("stopBufferingIfNecessary_l"); 1605 mBuffering = false; 1606 1607 sendCacheStats_l(); 1608 1609 sp<AMessage> notify = mNotify->dup(); 1610 notify->setInt32("what", kWhatResumeOnBufferingEnd); 1611 notify->post(); 1612 } 1613} 1614 1615void NuPlayer::GenericSource::BufferingMonitor::sendCacheStats_l() { 1616 int32_t kbps = 0; 1617 status_t err = UNKNOWN_ERROR; 1618 1619 if (mCachedSource != NULL) { 1620 err = mCachedSource->getEstimatedBandwidthKbps(&kbps); 1621 } 1622 1623 if (err == OK) { 1624 sp<AMessage> notify = mNotify->dup(); 1625 notify->setInt32("what", kWhatCacheStats); 1626 notify->setInt32("bandwidth", kbps); 1627 notify->post(); 1628 } 1629} 1630 1631void NuPlayer::GenericSource::BufferingMonitor::ensureCacheIsFetching_l() { 1632 if (mCachedSource != NULL) { 1633 mCachedSource->resumeFetchingIfNecessary(); 1634 } 1635} 1636 1637void NuPlayer::GenericSource::BufferingMonitor::schedulePollBuffering_l() { 1638 sp<AMessage> msg = new AMessage(kWhatPollBuffering, this); 1639 msg->setInt32("generation", mPollBufferingGeneration); 1640 // Enquires buffering status every second. 1641 msg->post(1000000ll); 1642} 1643 1644int64_t NuPlayer::GenericSource::BufferingMonitor::getLastReadPosition_l() { 1645 if (mAudioTimeUs > 0) { 1646 return mAudioTimeUs; 1647 } else if (mVideoTimeUs > 0) { 1648 return mVideoTimeUs; 1649 } else { 1650 return 0; 1651 } 1652} 1653 1654void NuPlayer::GenericSource::BufferingMonitor::onPollBuffering_l() { 1655 status_t finalStatus = UNKNOWN_ERROR; 1656 int64_t cachedDurationUs = -1ll; 1657 ssize_t cachedDataRemaining = -1; 1658 1659 if (mCachedSource != NULL) { 1660 cachedDataRemaining = 1661 mCachedSource->approxDataRemaining(&finalStatus); 1662 1663 if (finalStatus == OK) { 1664 off64_t size; 1665 int64_t bitrate = 0ll; 1666 if (mDurationUs > 0 && mCachedSource->getSize(&size) == OK) { 1667 // |bitrate| uses bits/second unit, while size is number of bytes. 1668 bitrate = size * 8000000ll / mDurationUs; 1669 } else if (mBitrate > 0) { 1670 bitrate = mBitrate; 1671 } 1672 if (bitrate > 0) { 1673 cachedDurationUs = cachedDataRemaining * 8000000ll / bitrate; 1674 } 1675 } 1676 } 1677 1678 if (finalStatus != OK) { 1679 ALOGV("onPollBuffering_l: EOS (finalStatus = %d)", finalStatus); 1680 1681 if (finalStatus == ERROR_END_OF_STREAM) { 1682 notifyBufferingUpdate_l(100); 1683 } 1684 1685 stopBufferingIfNecessary_l(); 1686 return; 1687 } else if (cachedDurationUs >= 0ll) { 1688 if (mDurationUs > 0ll) { 1689 int64_t cachedPosUs = getLastReadPosition_l() + cachedDurationUs; 1690 int percentage = 100.0 * cachedPosUs / mDurationUs; 1691 if (percentage > 100) { 1692 percentage = 100; 1693 } 1694 1695 notifyBufferingUpdate_l(percentage); 1696 } 1697 1698 ALOGV("onPollBuffering_l: cachedDurationUs %.1f sec", 1699 cachedDurationUs / 1000000.0f); 1700 1701 if (cachedDurationUs < kLowWaterMarkUs) { 1702 // Take into account the data cached in downstream components to try to avoid 1703 // unnecessary pause. 1704 if (mOffloadAudio && mFirstDequeuedBufferRealUs >= 0) { 1705 int64_t downStreamCacheUs = mlastDequeuedBufferMediaUs - mFirstDequeuedBufferMediaUs 1706 - (ALooper::GetNowUs() - mFirstDequeuedBufferRealUs); 1707 if (downStreamCacheUs > 0) { 1708 cachedDurationUs += downStreamCacheUs; 1709 } 1710 } 1711 1712 if (cachedDurationUs < kLowWaterMarkUs) { 1713 startBufferingIfNecessary_l(); 1714 } 1715 } else { 1716 int64_t highWaterMark = mPrepareBuffering ? kHighWaterMarkUs : kHighWaterMarkRebufferUs; 1717 if (cachedDurationUs > highWaterMark) { 1718 stopBufferingIfNecessary_l(); 1719 } 1720 } 1721 } else if (cachedDataRemaining >= 0) { 1722 ALOGV("onPollBuffering_l: cachedDataRemaining %zd bytes", 1723 cachedDataRemaining); 1724 1725 if (cachedDataRemaining < kLowWaterMarkBytes) { 1726 startBufferingIfNecessary_l(); 1727 } else if (cachedDataRemaining > kHighWaterMarkBytes) { 1728 stopBufferingIfNecessary_l(); 1729 } 1730 } 1731 1732 schedulePollBuffering_l(); 1733} 1734 1735void NuPlayer::GenericSource::BufferingMonitor::onMessageReceived(const sp<AMessage> &msg) { 1736 switch (msg->what()) { 1737 case kWhatPollBuffering: 1738 { 1739 int32_t generation; 1740 CHECK(msg->findInt32("generation", &generation)); 1741 Mutex::Autolock _l(mLock); 1742 if (generation == mPollBufferingGeneration) { 1743 onPollBuffering_l(); 1744 } 1745 break; 1746 } 1747 default: 1748 TRESPASS(); 1749 break; 1750 } 1751} 1752 1753} // namespace android 1754