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