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