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