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