GenericSource.cpp revision eb1735e343a93830df259ae8882160bb0d79dcb5
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#include "GenericSource.h" 18 19#include "AnotherPacketSource.h" 20 21#include <media/stagefright/foundation/ABuffer.h> 22#include <media/stagefright/foundation/ADebug.h> 23#include <media/stagefright/foundation/AMessage.h> 24#include <media/stagefright/DataSource.h> 25#include <media/stagefright/FileSource.h> 26#include <media/stagefright/MediaBuffer.h> 27#include <media/stagefright/MediaDefs.h> 28#include <media/stagefright/MediaExtractor.h> 29#include <media/stagefright/MediaSource.h> 30#include <media/stagefright/MetaData.h> 31#include "../../libstagefright/include/WVMExtractor.h" 32 33namespace android { 34 35NuPlayer::GenericSource::GenericSource( 36 const sp<AMessage> ¬ify, 37 const sp<IMediaHTTPService> &httpService, 38 const char *url, 39 const KeyedVector<String8, String8> *headers, 40 bool isWidevine, 41 bool uidValid, 42 uid_t uid) 43 : Source(notify), 44 mFetchSubtitleDataGeneration(0), 45 mFetchTimedTextDataGeneration(0), 46 mDurationUs(0ll), 47 mAudioIsVorbis(false), 48 mIsWidevine(isWidevine), 49 mUIDValid(uidValid), 50 mUID(uid) { 51 DataSource::RegisterDefaultSniffers(); 52 53 sp<DataSource> dataSource = 54 DataSource::CreateFromURI(httpService, url, headers); 55 CHECK(dataSource != NULL); 56 57 initFromDataSource(dataSource); 58} 59 60NuPlayer::GenericSource::GenericSource( 61 const sp<AMessage> ¬ify, 62 int fd, int64_t offset, int64_t length) 63 : Source(notify), 64 mFetchSubtitleDataGeneration(0), 65 mFetchTimedTextDataGeneration(0), 66 mDurationUs(0ll), 67 mAudioIsVorbis(false) { 68 DataSource::RegisterDefaultSniffers(); 69 70 sp<DataSource> dataSource = new FileSource(dup(fd), offset, length); 71 72 initFromDataSource(dataSource); 73} 74 75void NuPlayer::GenericSource::initFromDataSource( 76 const sp<DataSource> &dataSource) { 77 sp<MediaExtractor> extractor; 78 79 if (mIsWidevine) { 80 String8 mimeType; 81 float confidence; 82 sp<AMessage> dummy; 83 bool success; 84 85 success = SniffWVM(dataSource, &mimeType, &confidence, &dummy); 86 if (!success 87 || strcasecmp( 88 mimeType.string(), MEDIA_MIMETYPE_CONTAINER_WVM)) { 89 ALOGE("unsupported widevine mime: %s", mimeType.string()); 90 return; 91 } 92 93 sp<WVMExtractor> wvmExtractor = new WVMExtractor(dataSource); 94 wvmExtractor->setAdaptiveStreamingMode(true); 95 if (mUIDValid) { 96 wvmExtractor->setUID(mUID); 97 } 98 extractor = wvmExtractor; 99 } else { 100 extractor = MediaExtractor::Create(dataSource); 101 } 102 103 CHECK(extractor != NULL); 104 105 sp<MetaData> fileMeta = extractor->getMetaData(); 106 if (fileMeta != NULL) { 107 int64_t duration; 108 if (fileMeta->findInt64(kKeyDuration, &duration)) { 109 mDurationUs = duration; 110 } 111 } 112 113 for (size_t i = 0; i < extractor->countTracks(); ++i) { 114 sp<MetaData> meta = extractor->getTrackMetaData(i); 115 116 const char *mime; 117 CHECK(meta->findCString(kKeyMIMEType, &mime)); 118 119 sp<MediaSource> track = extractor->getTrack(i); 120 121 if (!strncasecmp(mime, "audio/", 6)) { 122 if (mAudioTrack.mSource == NULL) { 123 mAudioTrack.mIndex = i; 124 mAudioTrack.mSource = track; 125 126 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) { 127 mAudioIsVorbis = true; 128 } else { 129 mAudioIsVorbis = false; 130 } 131 } 132 } else if (!strncasecmp(mime, "video/", 6)) { 133 if (mVideoTrack.mSource == NULL) { 134 mVideoTrack.mIndex = i; 135 mVideoTrack.mSource = track; 136 } 137 } 138 139 if (track != NULL) { 140 CHECK_EQ(track->start(), (status_t)OK); 141 mSources.push(track); 142 int64_t durationUs; 143 if (meta->findInt64(kKeyDuration, &durationUs)) { 144 if (durationUs > mDurationUs) { 145 mDurationUs = durationUs; 146 } 147 } 148 } 149 } 150} 151 152status_t NuPlayer::GenericSource::setBuffers(bool audio, Vector<MediaBuffer *> &buffers) { 153 if (mIsWidevine && !audio) { 154 return mVideoTrack.mSource->setBuffers(buffers); 155 } 156 return INVALID_OPERATION; 157} 158 159NuPlayer::GenericSource::~GenericSource() { 160} 161 162void NuPlayer::GenericSource::prepareAsync() { 163 if (mVideoTrack.mSource != NULL) { 164 sp<MetaData> meta = mVideoTrack.mSource->getFormat(); 165 166 int32_t width, height; 167 CHECK(meta->findInt32(kKeyWidth, &width)); 168 CHECK(meta->findInt32(kKeyHeight, &height)); 169 170 notifyVideoSizeChanged(width, height); 171 } 172 173 notifyFlagsChanged( 174 (mIsWidevine ? FLAG_SECURE : 0) 175 | FLAG_CAN_PAUSE 176 | FLAG_CAN_SEEK_BACKWARD 177 | FLAG_CAN_SEEK_FORWARD 178 | FLAG_CAN_SEEK); 179 180 notifyPrepared(); 181} 182 183void NuPlayer::GenericSource::start() { 184 ALOGI("start"); 185 186 if (mAudioTrack.mSource != NULL) { 187 mAudioTrack.mPackets = 188 new AnotherPacketSource(mAudioTrack.mSource->getFormat()); 189 190 readBuffer(MEDIA_TRACK_TYPE_AUDIO); 191 } 192 193 if (mVideoTrack.mSource != NULL) { 194 mVideoTrack.mPackets = 195 new AnotherPacketSource(mVideoTrack.mSource->getFormat()); 196 197 readBuffer(MEDIA_TRACK_TYPE_VIDEO); 198 } 199} 200 201status_t NuPlayer::GenericSource::feedMoreTSData() { 202 return OK; 203} 204 205void NuPlayer::GenericSource::onMessageReceived(const sp<AMessage> &msg) { 206 switch (msg->what()) { 207 case kWhatFetchSubtitleData: 208 { 209 fetchTextData(kWhatSendSubtitleData, MEDIA_TRACK_TYPE_SUBTITLE, 210 mFetchSubtitleDataGeneration, mSubtitleTrack.mPackets, msg); 211 break; 212 } 213 214 case kWhatFetchTimedTextData: 215 { 216 fetchTextData(kWhatSendTimedTextData, MEDIA_TRACK_TYPE_TIMEDTEXT, 217 mFetchTimedTextDataGeneration, mTimedTextTrack.mPackets, msg); 218 break; 219 } 220 221 case kWhatSendSubtitleData: 222 { 223 sendTextData(kWhatSubtitleData, MEDIA_TRACK_TYPE_SUBTITLE, 224 mFetchSubtitleDataGeneration, mSubtitleTrack.mPackets, msg); 225 break; 226 } 227 228 case kWhatSendTimedTextData: 229 { 230 sendTextData(kWhatTimedTextData, MEDIA_TRACK_TYPE_TIMEDTEXT, 231 mFetchTimedTextDataGeneration, mTimedTextTrack.mPackets, msg); 232 break; 233 } 234 235 case kWhatChangeAVSource: 236 { 237 int32_t trackIndex; 238 CHECK(msg->findInt32("trackIndex", &trackIndex)); 239 const sp<MediaSource> source = mSources.itemAt(trackIndex); 240 241 Track* track; 242 const char *mime; 243 media_track_type trackType, counterpartType; 244 sp<MetaData> meta = source->getFormat(); 245 meta->findCString(kKeyMIMEType, &mime); 246 if (!strncasecmp(mime, "audio/", 6)) { 247 track = &mAudioTrack; 248 trackType = MEDIA_TRACK_TYPE_AUDIO; 249 counterpartType = MEDIA_TRACK_TYPE_VIDEO;; 250 } else { 251 CHECK(!strncasecmp(mime, "video/", 6)); 252 track = &mVideoTrack; 253 trackType = MEDIA_TRACK_TYPE_VIDEO; 254 counterpartType = MEDIA_TRACK_TYPE_AUDIO;; 255 } 256 257 258 track->mSource = source; 259 track->mIndex = trackIndex; 260 261 status_t avail; 262 if (!track->mPackets->hasBufferAvailable(&avail)) { 263 // sync from other source 264 TRESPASS(); 265 break; 266 } 267 268 int64_t timeUs, actualTimeUs; 269 const bool formatChange = true; 270 sp<AMessage> latestMeta = track->mPackets->getLatestMeta(); 271 CHECK(latestMeta != NULL && latestMeta->findInt64("timeUs", &timeUs)); 272 readBuffer(trackType, timeUs, &actualTimeUs, formatChange); 273 readBuffer(counterpartType, -1, NULL, formatChange); 274 ALOGV("timeUs %lld actualTimeUs %lld", timeUs, actualTimeUs); 275 276 break; 277 } 278 279 default: 280 Source::onMessageReceived(msg); 281 break; 282 } 283} 284 285void NuPlayer::GenericSource::fetchTextData( 286 uint32_t sendWhat, 287 media_track_type type, 288 int32_t curGen, 289 sp<AnotherPacketSource> packets, 290 sp<AMessage> msg) { 291 int32_t msgGeneration; 292 CHECK(msg->findInt32("generation", &msgGeneration)); 293 if (msgGeneration != curGen) { 294 // stale 295 return; 296 } 297 298 int32_t avail; 299 if (packets->hasBufferAvailable(&avail)) { 300 return; 301 } 302 303 int64_t timeUs; 304 CHECK(msg->findInt64("timeUs", &timeUs)); 305 306 int64_t subTimeUs; 307 readBuffer(type, timeUs, &subTimeUs); 308 309 int64_t delayUs = subTimeUs - timeUs; 310 if (msg->what() == kWhatFetchSubtitleData) { 311 const int64_t oneSecUs = 1000000ll; 312 delayUs -= oneSecUs; 313 } 314 sp<AMessage> msg2 = new AMessage(sendWhat, id()); 315 msg2->setInt32("generation", msgGeneration); 316 msg2->post(delayUs < 0 ? 0 : delayUs); 317} 318 319void NuPlayer::GenericSource::sendTextData( 320 uint32_t what, 321 media_track_type type, 322 int32_t curGen, 323 sp<AnotherPacketSource> packets, 324 sp<AMessage> msg) { 325 int32_t msgGeneration; 326 CHECK(msg->findInt32("generation", &msgGeneration)); 327 if (msgGeneration != curGen) { 328 // stale 329 return; 330 } 331 332 int64_t subTimeUs; 333 if (packets->nextBufferTime(&subTimeUs) != OK) { 334 return; 335 } 336 337 int64_t nextSubTimeUs; 338 readBuffer(type, -1, &nextSubTimeUs); 339 340 sp<ABuffer> buffer; 341 status_t dequeueStatus = packets->dequeueAccessUnit(&buffer); 342 if (dequeueStatus == OK) { 343 sp<AMessage> notify = dupNotify(); 344 notify->setInt32("what", what); 345 notify->setBuffer("buffer", buffer); 346 notify->post(); 347 348 const int64_t delayUs = nextSubTimeUs - subTimeUs; 349 msg->post(delayUs < 0 ? 0 : delayUs); 350 } 351} 352 353sp<MetaData> NuPlayer::GenericSource::getFormatMeta(bool audio) { 354 sp<MediaSource> source = audio ? mAudioTrack.mSource : mVideoTrack.mSource; 355 356 if (source == NULL) { 357 return NULL; 358 } 359 360 return source->getFormat(); 361} 362 363status_t NuPlayer::GenericSource::dequeueAccessUnit( 364 bool audio, sp<ABuffer> *accessUnit) { 365 Track *track = audio ? &mAudioTrack : &mVideoTrack; 366 367 if (track->mSource == NULL) { 368 return -EWOULDBLOCK; 369 } 370 371 if (mIsWidevine && !audio) { 372 // try to read a buffer as we may not have been able to the last time 373 readBuffer(MEDIA_TRACK_TYPE_AUDIO, -1ll); 374 } 375 376 status_t finalResult; 377 if (!track->mPackets->hasBufferAvailable(&finalResult)) { 378 return (finalResult == OK ? -EWOULDBLOCK : finalResult); 379 } 380 381 status_t result = track->mPackets->dequeueAccessUnit(accessUnit); 382 383 if (!track->mPackets->hasBufferAvailable(&finalResult)) { 384 readBuffer(audio? MEDIA_TRACK_TYPE_AUDIO : MEDIA_TRACK_TYPE_VIDEO, -1ll); 385 } 386 387 if (mSubtitleTrack.mSource == NULL && mTimedTextTrack.mSource == NULL) { 388 return result; 389 } 390 391 if (mSubtitleTrack.mSource != NULL) { 392 CHECK(mSubtitleTrack.mPackets != NULL); 393 } 394 if (mTimedTextTrack.mSource != NULL) { 395 CHECK(mTimedTextTrack.mPackets != NULL); 396 } 397 398 if (result != OK) { 399 if (mSubtitleTrack.mSource != NULL) { 400 mSubtitleTrack.mPackets->clear(); 401 mFetchSubtitleDataGeneration++; 402 } 403 if (mTimedTextTrack.mSource != NULL) { 404 mTimedTextTrack.mPackets->clear(); 405 mFetchTimedTextDataGeneration++; 406 } 407 return result; 408 } 409 410 int64_t timeUs; 411 status_t eosResult; // ignored 412 CHECK((*accessUnit)->meta()->findInt64("timeUs", &timeUs)); 413 414 if (mSubtitleTrack.mSource != NULL 415 && !mSubtitleTrack.mPackets->hasBufferAvailable(&eosResult)) { 416 sp<AMessage> msg = new AMessage(kWhatFetchSubtitleData, id()); 417 msg->setInt64("timeUs", timeUs); 418 msg->setInt32("generation", mFetchSubtitleDataGeneration); 419 msg->post(); 420 } 421 422 if (mTimedTextTrack.mSource != NULL 423 && !mTimedTextTrack.mPackets->hasBufferAvailable(&eosResult)) { 424 sp<AMessage> msg = new AMessage(kWhatFetchTimedTextData, id()); 425 msg->setInt64("timeUs", timeUs); 426 msg->setInt32("generation", mFetchTimedTextDataGeneration); 427 msg->post(); 428 } 429 430 return result; 431} 432 433status_t NuPlayer::GenericSource::getDuration(int64_t *durationUs) { 434 *durationUs = mDurationUs; 435 return OK; 436} 437 438size_t NuPlayer::GenericSource::getTrackCount() const { 439 return mSources.size(); 440} 441 442sp<AMessage> NuPlayer::GenericSource::getTrackInfo(size_t trackIndex) const { 443 size_t trackCount = mSources.size(); 444 if (trackIndex >= trackCount) { 445 return NULL; 446 } 447 448 sp<AMessage> format = new AMessage(); 449 sp<MetaData> meta = mSources.itemAt(trackIndex)->getFormat(); 450 451 const char *mime; 452 CHECK(meta->findCString(kKeyMIMEType, &mime)); 453 454 int32_t trackType; 455 if (!strncasecmp(mime, "video/", 6)) { 456 trackType = MEDIA_TRACK_TYPE_VIDEO; 457 } else if (!strncasecmp(mime, "audio/", 6)) { 458 trackType = MEDIA_TRACK_TYPE_AUDIO; 459 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP)) { 460 trackType = MEDIA_TRACK_TYPE_TIMEDTEXT; 461 } else { 462 trackType = MEDIA_TRACK_TYPE_UNKNOWN; 463 } 464 format->setInt32("type", trackType); 465 466 const char *lang; 467 if (!meta->findCString(kKeyMediaLanguage, &lang)) { 468 lang = "und"; 469 } 470 format->setString("language", lang); 471 472 if (trackType == MEDIA_TRACK_TYPE_SUBTITLE) { 473 format->setString("mime", mime); 474 475 int32_t isAutoselect = 1, isDefault = 0, isForced = 0; 476 meta->findInt32(kKeyTrackIsAutoselect, &isAutoselect); 477 meta->findInt32(kKeyTrackIsDefault, &isDefault); 478 meta->findInt32(kKeyTrackIsForced, &isForced); 479 480 format->setInt32("auto", !!isAutoselect); 481 format->setInt32("default", !!isDefault); 482 format->setInt32("forced", !!isForced); 483 } 484 485 return format; 486} 487 488ssize_t NuPlayer::GenericSource::getSelectedTrack(media_track_type type) const { 489 const Track *track = NULL; 490 switch (type) { 491 case MEDIA_TRACK_TYPE_VIDEO: 492 track = &mVideoTrack; 493 break; 494 case MEDIA_TRACK_TYPE_AUDIO: 495 track = &mAudioTrack; 496 break; 497 case MEDIA_TRACK_TYPE_TIMEDTEXT: 498 track = &mTimedTextTrack; 499 break; 500 case MEDIA_TRACK_TYPE_SUBTITLE: 501 track = &mSubtitleTrack; 502 break; 503 default: 504 break; 505 } 506 507 if (track != NULL && track->mSource != NULL) { 508 return track->mIndex; 509 } 510 511 return -1; 512} 513 514status_t NuPlayer::GenericSource::selectTrack(size_t trackIndex, bool select) { 515 ALOGV("%s track: %zu", select ? "select" : "deselect", trackIndex); 516 if (trackIndex >= mSources.size()) { 517 return BAD_INDEX; 518 } 519 520 if (!select) { 521 Track* track = NULL; 522 if (mSubtitleTrack.mSource != NULL && trackIndex == mSubtitleTrack.mIndex) { 523 track = &mSubtitleTrack; 524 mFetchSubtitleDataGeneration++; 525 } else if (mTimedTextTrack.mSource != NULL && trackIndex == mTimedTextTrack.mIndex) { 526 track = &mTimedTextTrack; 527 mFetchTimedTextDataGeneration++; 528 } 529 if (track == NULL) { 530 return INVALID_OPERATION; 531 } 532 track->mSource = NULL; 533 track->mPackets->clear(); 534 return OK; 535 } 536 537 const sp<MediaSource> source = mSources.itemAt(trackIndex); 538 sp<MetaData> meta = source->getFormat(); 539 const char *mime; 540 CHECK(meta->findCString(kKeyMIMEType, &mime)); 541 if (!strncasecmp(mime, "text/", 5)) { 542 bool isSubtitle = strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP); 543 Track *track = isSubtitle ? &mSubtitleTrack : &mTimedTextTrack; 544 if (track->mSource != NULL && track->mIndex == trackIndex) { 545 return OK; 546 } 547 track->mIndex = trackIndex; 548 track->mSource = mSources.itemAt(trackIndex); 549 if (track->mPackets == NULL) { 550 track->mPackets = new AnotherPacketSource(track->mSource->getFormat()); 551 } else { 552 track->mPackets->clear(); 553 track->mPackets->setFormat(track->mSource->getFormat()); 554 555 } 556 557 if (isSubtitle) { 558 mFetchSubtitleDataGeneration++; 559 } else { 560 mFetchTimedTextDataGeneration++; 561 } 562 563 return OK; 564 } else if (!strncasecmp(mime, "audio/", 6) || !strncasecmp(mime, "video/", 6)) { 565 bool audio = !strncasecmp(mime, "audio/", 6); 566 Track *track = audio ? &mAudioTrack : &mVideoTrack; 567 if (track->mSource != NULL && track->mIndex == trackIndex) { 568 return OK; 569 } 570 571 sp<AMessage> msg = new AMessage(kWhatChangeAVSource, id()); 572 msg->setInt32("trackIndex", trackIndex); 573 msg->post(); 574 return OK; 575 } 576 577 return INVALID_OPERATION; 578} 579 580status_t NuPlayer::GenericSource::seekTo(int64_t seekTimeUs) { 581 if (mVideoTrack.mSource != NULL) { 582 int64_t actualTimeUs; 583 readBuffer(MEDIA_TRACK_TYPE_VIDEO, seekTimeUs, &actualTimeUs); 584 585 seekTimeUs = actualTimeUs; 586 } 587 588 if (mAudioTrack.mSource != NULL) { 589 readBuffer(MEDIA_TRACK_TYPE_AUDIO, seekTimeUs); 590 } 591 592 return OK; 593} 594 595sp<ABuffer> NuPlayer::GenericSource::mediaBufferToABuffer( 596 MediaBuffer* mb, 597 media_track_type trackType, 598 int64_t *actualTimeUs) { 599 bool audio = trackType == MEDIA_TRACK_TYPE_AUDIO; 600 size_t outLength = mb->range_length(); 601 602 if (audio && mAudioIsVorbis) { 603 outLength += sizeof(int32_t); 604 } 605 606 sp<ABuffer> ab; 607 if (mIsWidevine && !audio) { 608 // data is already provided in the buffer 609 ab = new ABuffer(NULL, mb->range_length()); 610 ab->meta()->setPointer("mediaBuffer", mb); 611 mb->add_ref(); 612 } else { 613 ab = new ABuffer(outLength); 614 memcpy(ab->data(), 615 (const uint8_t *)mb->data() + mb->range_offset(), 616 mb->range_length()); 617 } 618 619 if (audio && mAudioIsVorbis) { 620 int32_t numPageSamples; 621 if (!mb->meta_data()->findInt32(kKeyValidSamples, &numPageSamples)) { 622 numPageSamples = -1; 623 } 624 625 uint8_t* abEnd = ab->data() + mb->range_length(); 626 memcpy(abEnd, &numPageSamples, sizeof(numPageSamples)); 627 } 628 629 sp<AMessage> meta = ab->meta(); 630 631 int64_t timeUs; 632 CHECK(mb->meta_data()->findInt64(kKeyTime, &timeUs)); 633 meta->setInt64("timeUs", timeUs); 634 635 if (trackType == MEDIA_TRACK_TYPE_TIMEDTEXT) { 636 const char *mime; 637 CHECK(mTimedTextTrack.mSource != NULL 638 && mTimedTextTrack.mSource->getFormat()->findCString(kKeyMIMEType, &mime)); 639 meta->setString("mime", mime); 640 } 641 642 int64_t durationUs; 643 if (mb->meta_data()->findInt64(kKeyDuration, &durationUs)) { 644 meta->setInt64("durationUs", durationUs); 645 } 646 647 if (trackType == MEDIA_TRACK_TYPE_SUBTITLE) { 648 meta->setInt32("trackIndex", mSubtitleTrack.mIndex); 649 } 650 651 if (actualTimeUs) { 652 *actualTimeUs = timeUs; 653 } 654 655 mb->release(); 656 mb = NULL; 657 658 return ab; 659} 660 661void NuPlayer::GenericSource::readBuffer( 662 media_track_type trackType, int64_t seekTimeUs, int64_t *actualTimeUs, bool formatChange) { 663 Track *track; 664 switch (trackType) { 665 case MEDIA_TRACK_TYPE_VIDEO: 666 track = &mVideoTrack; 667 break; 668 case MEDIA_TRACK_TYPE_AUDIO: 669 track = &mAudioTrack; 670 break; 671 case MEDIA_TRACK_TYPE_SUBTITLE: 672 track = &mSubtitleTrack; 673 break; 674 case MEDIA_TRACK_TYPE_TIMEDTEXT: 675 track = &mTimedTextTrack; 676 break; 677 default: 678 TRESPASS(); 679 } 680 681 if (track->mSource == NULL) { 682 return; 683 } 684 685 if (actualTimeUs) { 686 *actualTimeUs = seekTimeUs; 687 } 688 689 MediaSource::ReadOptions options; 690 691 bool seeking = false; 692 693 if (seekTimeUs >= 0) { 694 options.setSeekTo(seekTimeUs, MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC); 695 seeking = true; 696 } 697 698 if (mIsWidevine && trackType != MEDIA_TRACK_TYPE_AUDIO) { 699 options.setNonBlocking(); 700 } 701 702 for (;;) { 703 MediaBuffer *mbuf; 704 status_t err = track->mSource->read(&mbuf, &options); 705 706 options.clearSeekTo(); 707 708 if (err == OK) { 709 // formatChange && seeking: track whose source is changed during selection 710 // formatChange && !seeking: track whose source is not changed during selection 711 // !formatChange: normal seek 712 if ((seeking || formatChange) 713 && (trackType == MEDIA_TRACK_TYPE_AUDIO 714 || trackType == MEDIA_TRACK_TYPE_VIDEO)) { 715 ATSParser::DiscontinuityType type = formatChange 716 ? (seeking 717 ? ATSParser::DISCONTINUITY_FORMATCHANGE 718 : ATSParser::DISCONTINUITY_NONE) 719 : ATSParser::DISCONTINUITY_SEEK; 720 track->mPackets->queueDiscontinuity( type, NULL, true /* discard */); 721 } 722 723 sp<ABuffer> buffer = mediaBufferToABuffer(mbuf, trackType, actualTimeUs); 724 track->mPackets->queueAccessUnit(buffer); 725 break; 726 } else if (err == WOULD_BLOCK) { 727 break; 728 } else if (err == INFO_FORMAT_CHANGED) { 729#if 0 730 track->mPackets->queueDiscontinuity( 731 ATSParser::DISCONTINUITY_FORMATCHANGE, 732 NULL, 733 false /* discard */); 734#endif 735 } else { 736 track->mPackets->signalEOS(err); 737 break; 738 } 739 } 740} 741 742} // namespace android 743