PlaylistFetcher.cpp revision 25f82752942b1c78aec8ee303d61afff85cff9d1
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 "PlaylistFetcher" 19#include <utils/Log.h> 20 21#include "PlaylistFetcher.h" 22 23#include "LiveDataSource.h" 24#include "LiveSession.h" 25#include "M3UParser.h" 26 27#include "include/avc_utils.h" 28#include "include/HTTPBase.h" 29#include "include/ID3.h" 30#include "mpeg2ts/AnotherPacketSource.h" 31 32#include <media/IStreamSource.h> 33#include <media/stagefright/foundation/ABitReader.h> 34#include <media/stagefright/foundation/ABuffer.h> 35#include <media/stagefright/foundation/ADebug.h> 36#include <media/stagefright/foundation/AUtils.h> 37#include <media/stagefright/foundation/hexdump.h> 38#include <media/stagefright/FileSource.h> 39#include <media/stagefright/MediaDefs.h> 40#include <media/stagefright/MetaData.h> 41#include <media/stagefright/Utils.h> 42 43#include <ctype.h> 44#include <inttypes.h> 45#include <openssl/aes.h> 46#include <openssl/md5.h> 47 48#define FLOGV(fmt, ...) ALOGV("[fetcher-%d] " fmt, mFetcherID, ##__VA_ARGS__) 49#define FSLOGV(stream, fmt, ...) ALOGV("[fetcher-%d] [%s] " fmt, mFetcherID, \ 50 LiveSession::getNameForStream(stream), ##__VA_ARGS__) 51 52namespace android { 53 54// static 55const int64_t PlaylistFetcher::kMinBufferedDurationUs = 30000000ll; 56const int64_t PlaylistFetcher::kMaxMonitorDelayUs = 3000000ll; 57// LCM of 188 (size of a TS packet) & 1k works well 58const int32_t PlaylistFetcher::kDownloadBlockSize = 47 * 1024; 59 60struct PlaylistFetcher::DownloadState : public RefBase { 61 DownloadState(); 62 void resetState(); 63 bool hasSavedState() const; 64 void restoreState( 65 AString &uri, 66 sp<AMessage> &itemMeta, 67 sp<ABuffer> &buffer, 68 sp<ABuffer> &tsBuffer, 69 int32_t &firstSeqNumberInPlaylist, 70 int32_t &lastSeqNumberInPlaylist); 71 void saveState( 72 AString &uri, 73 sp<AMessage> &itemMeta, 74 sp<ABuffer> &buffer, 75 sp<ABuffer> &tsBuffer, 76 int32_t &firstSeqNumberInPlaylist, 77 int32_t &lastSeqNumberInPlaylist); 78 79private: 80 bool mHasSavedState; 81 AString mUri; 82 sp<AMessage> mItemMeta; 83 sp<ABuffer> mBuffer; 84 sp<ABuffer> mTsBuffer; 85 int32_t mFirstSeqNumberInPlaylist; 86 int32_t mLastSeqNumberInPlaylist; 87}; 88 89PlaylistFetcher::DownloadState::DownloadState() { 90 resetState(); 91} 92 93bool PlaylistFetcher::DownloadState::hasSavedState() const { 94 return mHasSavedState; 95} 96 97void PlaylistFetcher::DownloadState::resetState() { 98 mHasSavedState = false; 99 100 mUri.clear(); 101 mItemMeta = NULL; 102 mBuffer = NULL; 103 mTsBuffer = NULL; 104 mFirstSeqNumberInPlaylist = 0; 105 mLastSeqNumberInPlaylist = 0; 106} 107 108void PlaylistFetcher::DownloadState::restoreState( 109 AString &uri, 110 sp<AMessage> &itemMeta, 111 sp<ABuffer> &buffer, 112 sp<ABuffer> &tsBuffer, 113 int32_t &firstSeqNumberInPlaylist, 114 int32_t &lastSeqNumberInPlaylist) { 115 if (!mHasSavedState) { 116 return; 117 } 118 119 uri = mUri; 120 itemMeta = mItemMeta; 121 buffer = mBuffer; 122 tsBuffer = mTsBuffer; 123 firstSeqNumberInPlaylist = mFirstSeqNumberInPlaylist; 124 lastSeqNumberInPlaylist = mLastSeqNumberInPlaylist; 125 126 resetState(); 127} 128 129void PlaylistFetcher::DownloadState::saveState( 130 AString &uri, 131 sp<AMessage> &itemMeta, 132 sp<ABuffer> &buffer, 133 sp<ABuffer> &tsBuffer, 134 int32_t &firstSeqNumberInPlaylist, 135 int32_t &lastSeqNumberInPlaylist) { 136 mHasSavedState = true; 137 138 mUri = uri; 139 mItemMeta = itemMeta; 140 mBuffer = buffer; 141 mTsBuffer = tsBuffer; 142 mFirstSeqNumberInPlaylist = firstSeqNumberInPlaylist; 143 mLastSeqNumberInPlaylist = lastSeqNumberInPlaylist; 144} 145 146PlaylistFetcher::PlaylistFetcher( 147 const sp<AMessage> ¬ify, 148 const sp<LiveSession> &session, 149 const char *uri, 150 int32_t id, 151 int32_t subtitleGeneration) 152 : mNotify(notify), 153 mSession(session), 154 mURI(uri), 155 mFetcherID(id), 156 mStreamTypeMask(0), 157 mStartTimeUs(-1ll), 158 mSegmentStartTimeUs(-1ll), 159 mDiscontinuitySeq(-1ll), 160 mStartTimeUsRelative(false), 161 mLastPlaylistFetchTimeUs(-1ll), 162 mSeqNumber(-1), 163 mNumRetries(0), 164 mStartup(true), 165 mIDRFound(false), 166 mSeekMode(LiveSession::kSeekModeExactPosition), 167 mTimeChangeSignaled(false), 168 mNextPTSTimeUs(-1ll), 169 mMonitorQueueGeneration(0), 170 mSubtitleGeneration(subtitleGeneration), 171 mLastDiscontinuitySeq(-1ll), 172 mRefreshState(INITIAL_MINIMUM_RELOAD_DELAY), 173 mFirstPTSValid(false), 174 mFirstTimeUs(-1ll), 175 mVideoBuffer(new AnotherPacketSource(NULL)), 176 mThresholdRatio(-1.0f), 177 mDownloadState(new DownloadState()) { 178 memset(mPlaylistHash, 0, sizeof(mPlaylistHash)); 179 mHTTPDataSource = mSession->getHTTPDataSource(); 180} 181 182PlaylistFetcher::~PlaylistFetcher() { 183} 184 185int32_t PlaylistFetcher::getFetcherID() const { 186 return mFetcherID; 187} 188 189int64_t PlaylistFetcher::getSegmentStartTimeUs(int32_t seqNumber) const { 190 CHECK(mPlaylist != NULL); 191 192 int32_t firstSeqNumberInPlaylist; 193 if (mPlaylist->meta() == NULL || !mPlaylist->meta()->findInt32( 194 "media-sequence", &firstSeqNumberInPlaylist)) { 195 firstSeqNumberInPlaylist = 0; 196 } 197 198 int32_t lastSeqNumberInPlaylist = 199 firstSeqNumberInPlaylist + (int32_t)mPlaylist->size() - 1; 200 201 CHECK_GE(seqNumber, firstSeqNumberInPlaylist); 202 CHECK_LE(seqNumber, lastSeqNumberInPlaylist); 203 204 int64_t segmentStartUs = 0ll; 205 for (int32_t index = 0; 206 index < seqNumber - firstSeqNumberInPlaylist; ++index) { 207 sp<AMessage> itemMeta; 208 CHECK(mPlaylist->itemAt( 209 index, NULL /* uri */, &itemMeta)); 210 211 int64_t itemDurationUs; 212 CHECK(itemMeta->findInt64("durationUs", &itemDurationUs)); 213 214 segmentStartUs += itemDurationUs; 215 } 216 217 return segmentStartUs; 218} 219 220int64_t PlaylistFetcher::getSegmentDurationUs(int32_t seqNumber) const { 221 CHECK(mPlaylist != NULL); 222 223 int32_t firstSeqNumberInPlaylist; 224 if (mPlaylist->meta() == NULL || !mPlaylist->meta()->findInt32( 225 "media-sequence", &firstSeqNumberInPlaylist)) { 226 firstSeqNumberInPlaylist = 0; 227 } 228 229 int32_t lastSeqNumberInPlaylist = 230 firstSeqNumberInPlaylist + (int32_t)mPlaylist->size() - 1; 231 232 CHECK_GE(seqNumber, firstSeqNumberInPlaylist); 233 CHECK_LE(seqNumber, lastSeqNumberInPlaylist); 234 235 int32_t index = seqNumber - firstSeqNumberInPlaylist; 236 sp<AMessage> itemMeta; 237 CHECK(mPlaylist->itemAt( 238 index, NULL /* uri */, &itemMeta)); 239 240 int64_t itemDurationUs; 241 CHECK(itemMeta->findInt64("durationUs", &itemDurationUs)); 242 243 return itemDurationUs; 244} 245 246int64_t PlaylistFetcher::delayUsToRefreshPlaylist() const { 247 int64_t nowUs = ALooper::GetNowUs(); 248 249 if (mPlaylist == NULL || mLastPlaylistFetchTimeUs < 0ll) { 250 CHECK_EQ((int)mRefreshState, (int)INITIAL_MINIMUM_RELOAD_DELAY); 251 return 0ll; 252 } 253 254 if (mPlaylist->isComplete()) { 255 return (~0llu >> 1); 256 } 257 258 int32_t targetDurationSecs; 259 CHECK(mPlaylist->meta()->findInt32("target-duration", &targetDurationSecs)); 260 261 int64_t targetDurationUs = targetDurationSecs * 1000000ll; 262 263 int64_t minPlaylistAgeUs; 264 265 switch (mRefreshState) { 266 case INITIAL_MINIMUM_RELOAD_DELAY: 267 { 268 size_t n = mPlaylist->size(); 269 if (n > 0) { 270 sp<AMessage> itemMeta; 271 CHECK(mPlaylist->itemAt(n - 1, NULL /* uri */, &itemMeta)); 272 273 int64_t itemDurationUs; 274 CHECK(itemMeta->findInt64("durationUs", &itemDurationUs)); 275 276 minPlaylistAgeUs = itemDurationUs; 277 break; 278 } 279 280 // fall through 281 } 282 283 case FIRST_UNCHANGED_RELOAD_ATTEMPT: 284 { 285 minPlaylistAgeUs = targetDurationUs / 2; 286 break; 287 } 288 289 case SECOND_UNCHANGED_RELOAD_ATTEMPT: 290 { 291 minPlaylistAgeUs = (targetDurationUs * 3) / 2; 292 break; 293 } 294 295 case THIRD_UNCHANGED_RELOAD_ATTEMPT: 296 { 297 minPlaylistAgeUs = targetDurationUs * 3; 298 break; 299 } 300 301 default: 302 TRESPASS(); 303 break; 304 } 305 306 int64_t delayUs = mLastPlaylistFetchTimeUs + minPlaylistAgeUs - nowUs; 307 return delayUs > 0ll ? delayUs : 0ll; 308} 309 310status_t PlaylistFetcher::decryptBuffer( 311 size_t playlistIndex, const sp<ABuffer> &buffer, 312 bool first) { 313 sp<AMessage> itemMeta; 314 bool found = false; 315 AString method; 316 317 for (ssize_t i = playlistIndex; i >= 0; --i) { 318 AString uri; 319 CHECK(mPlaylist->itemAt(i, &uri, &itemMeta)); 320 321 if (itemMeta->findString("cipher-method", &method)) { 322 found = true; 323 break; 324 } 325 } 326 327 if (!found) { 328 method = "NONE"; 329 } 330 buffer->meta()->setString("cipher-method", method.c_str()); 331 332 if (method == "NONE") { 333 return OK; 334 } else if (!(method == "AES-128")) { 335 ALOGE("Unsupported cipher method '%s'", method.c_str()); 336 return ERROR_UNSUPPORTED; 337 } 338 339 AString keyURI; 340 if (!itemMeta->findString("cipher-uri", &keyURI)) { 341 ALOGE("Missing key uri"); 342 return ERROR_MALFORMED; 343 } 344 345 ssize_t index = mAESKeyForURI.indexOfKey(keyURI); 346 347 sp<ABuffer> key; 348 if (index >= 0) { 349 key = mAESKeyForURI.valueAt(index); 350 } else { 351 ssize_t err = mSession->fetchFile(keyURI.c_str(), &key); 352 353 if (err < 0) { 354 ALOGE("failed to fetch cipher key from '%s'.", keyURI.c_str()); 355 return ERROR_IO; 356 } else if (key->size() != 16) { 357 ALOGE("key file '%s' wasn't 16 bytes in size.", keyURI.c_str()); 358 return ERROR_MALFORMED; 359 } 360 361 mAESKeyForURI.add(keyURI, key); 362 } 363 364 AES_KEY aes_key; 365 if (AES_set_decrypt_key(key->data(), 128, &aes_key) != 0) { 366 ALOGE("failed to set AES decryption key."); 367 return UNKNOWN_ERROR; 368 } 369 370 size_t n = buffer->size(); 371 if (!n) { 372 return OK; 373 } 374 CHECK(n % 16 == 0); 375 376 if (first) { 377 // If decrypting the first block in a file, read the iv from the manifest 378 // or derive the iv from the file's sequence number. 379 380 AString iv; 381 if (itemMeta->findString("cipher-iv", &iv)) { 382 if ((!iv.startsWith("0x") && !iv.startsWith("0X")) 383 || iv.size() != 16 * 2 + 2) { 384 ALOGE("malformed cipher IV '%s'.", iv.c_str()); 385 return ERROR_MALFORMED; 386 } 387 388 memset(mAESInitVec, 0, sizeof(mAESInitVec)); 389 for (size_t i = 0; i < 16; ++i) { 390 char c1 = tolower(iv.c_str()[2 + 2 * i]); 391 char c2 = tolower(iv.c_str()[3 + 2 * i]); 392 if (!isxdigit(c1) || !isxdigit(c2)) { 393 ALOGE("malformed cipher IV '%s'.", iv.c_str()); 394 return ERROR_MALFORMED; 395 } 396 uint8_t nibble1 = isdigit(c1) ? c1 - '0' : c1 - 'a' + 10; 397 uint8_t nibble2 = isdigit(c2) ? c2 - '0' : c2 - 'a' + 10; 398 399 mAESInitVec[i] = nibble1 << 4 | nibble2; 400 } 401 } else { 402 memset(mAESInitVec, 0, sizeof(mAESInitVec)); 403 mAESInitVec[15] = mSeqNumber & 0xff; 404 mAESInitVec[14] = (mSeqNumber >> 8) & 0xff; 405 mAESInitVec[13] = (mSeqNumber >> 16) & 0xff; 406 mAESInitVec[12] = (mSeqNumber >> 24) & 0xff; 407 } 408 } 409 410 AES_cbc_encrypt( 411 buffer->data(), buffer->data(), buffer->size(), 412 &aes_key, mAESInitVec, AES_DECRYPT); 413 414 return OK; 415} 416 417status_t PlaylistFetcher::checkDecryptPadding(const sp<ABuffer> &buffer) { 418 AString method; 419 CHECK(buffer->meta()->findString("cipher-method", &method)); 420 if (method == "NONE") { 421 return OK; 422 } 423 424 uint8_t padding = 0; 425 if (buffer->size() > 0) { 426 padding = buffer->data()[buffer->size() - 1]; 427 } 428 429 if (padding > 16) { 430 return ERROR_MALFORMED; 431 } 432 433 for (size_t i = buffer->size() - padding; i < padding; i++) { 434 if (buffer->data()[i] != padding) { 435 return ERROR_MALFORMED; 436 } 437 } 438 439 buffer->setRange(buffer->offset(), buffer->size() - padding); 440 return OK; 441} 442 443void PlaylistFetcher::postMonitorQueue(int64_t delayUs, int64_t minDelayUs) { 444 int64_t maxDelayUs = delayUsToRefreshPlaylist(); 445 if (maxDelayUs < minDelayUs) { 446 maxDelayUs = minDelayUs; 447 } 448 if (delayUs > maxDelayUs) { 449 FLOGV("Need to refresh playlist in %lld", (long long)maxDelayUs); 450 delayUs = maxDelayUs; 451 } 452 sp<AMessage> msg = new AMessage(kWhatMonitorQueue, this); 453 msg->setInt32("generation", mMonitorQueueGeneration); 454 msg->post(delayUs); 455} 456 457void PlaylistFetcher::cancelMonitorQueue() { 458 ++mMonitorQueueGeneration; 459} 460 461void PlaylistFetcher::setStoppingThreshold(float thresholdRatio) { 462 AutoMutex _l(mThresholdLock); 463 if (mStreamTypeMask == LiveSession::STREAMTYPE_SUBTITLES) { 464 return; 465 } 466 mThresholdRatio = thresholdRatio; 467} 468 469void PlaylistFetcher::startAsync( 470 const sp<AnotherPacketSource> &audioSource, 471 const sp<AnotherPacketSource> &videoSource, 472 const sp<AnotherPacketSource> &subtitleSource, 473 int64_t startTimeUs, 474 int64_t segmentStartTimeUs, 475 int32_t startDiscontinuitySeq, 476 LiveSession::SeekMode seekMode) { 477 sp<AMessage> msg = new AMessage(kWhatStart, this); 478 479 uint32_t streamTypeMask = 0ul; 480 481 if (audioSource != NULL) { 482 msg->setPointer("audioSource", audioSource.get()); 483 streamTypeMask |= LiveSession::STREAMTYPE_AUDIO; 484 } 485 486 if (videoSource != NULL) { 487 msg->setPointer("videoSource", videoSource.get()); 488 streamTypeMask |= LiveSession::STREAMTYPE_VIDEO; 489 } 490 491 if (subtitleSource != NULL) { 492 msg->setPointer("subtitleSource", subtitleSource.get()); 493 streamTypeMask |= LiveSession::STREAMTYPE_SUBTITLES; 494 } 495 496 msg->setInt32("streamTypeMask", streamTypeMask); 497 msg->setInt64("startTimeUs", startTimeUs); 498 msg->setInt64("segmentStartTimeUs", segmentStartTimeUs); 499 msg->setInt32("startDiscontinuitySeq", startDiscontinuitySeq); 500 msg->setInt32("seekMode", seekMode); 501 msg->post(); 502} 503 504void PlaylistFetcher::pauseAsync(float thresholdRatio) { 505 if (thresholdRatio >= 0.0f) { 506 setStoppingThreshold(thresholdRatio); 507 } 508 (new AMessage(kWhatPause, this))->post(); 509} 510 511void PlaylistFetcher::stopAsync(bool clear) { 512 setStoppingThreshold(0.0f); 513 514 sp<AMessage> msg = new AMessage(kWhatStop, this); 515 msg->setInt32("clear", clear); 516 msg->post(); 517} 518 519void PlaylistFetcher::resumeUntilAsync(const sp<AMessage> ¶ms) { 520 FLOGV("resumeUntilAsync: params=%s", params->debugString().c_str()); 521 522 AMessage* msg = new AMessage(kWhatResumeUntil, this); 523 msg->setMessage("params", params); 524 msg->post(); 525} 526 527void PlaylistFetcher::onMessageReceived(const sp<AMessage> &msg) { 528 switch (msg->what()) { 529 case kWhatStart: 530 { 531 status_t err = onStart(msg); 532 533 sp<AMessage> notify = mNotify->dup(); 534 notify->setInt32("what", kWhatStarted); 535 notify->setInt32("err", err); 536 notify->post(); 537 break; 538 } 539 540 case kWhatPause: 541 { 542 onPause(); 543 544 sp<AMessage> notify = mNotify->dup(); 545 notify->setInt32("what", kWhatPaused); 546 notify->setInt32("seekMode", 547 mDownloadState->hasSavedState() 548 ? LiveSession::kSeekModeNextSample 549 : LiveSession::kSeekModeNextSegment); 550 notify->post(); 551 break; 552 } 553 554 case kWhatStop: 555 { 556 onStop(msg); 557 558 sp<AMessage> notify = mNotify->dup(); 559 notify->setInt32("what", kWhatStopped); 560 notify->post(); 561 break; 562 } 563 564 case kWhatMonitorQueue: 565 case kWhatDownloadNext: 566 { 567 int32_t generation; 568 CHECK(msg->findInt32("generation", &generation)); 569 570 if (generation != mMonitorQueueGeneration) { 571 // Stale event 572 break; 573 } 574 575 if (msg->what() == kWhatMonitorQueue) { 576 onMonitorQueue(); 577 } else { 578 onDownloadNext(); 579 } 580 break; 581 } 582 583 case kWhatResumeUntil: 584 { 585 onResumeUntil(msg); 586 break; 587 } 588 589 default: 590 TRESPASS(); 591 } 592} 593 594status_t PlaylistFetcher::onStart(const sp<AMessage> &msg) { 595 mPacketSources.clear(); 596 mStopParams.clear(); 597 mStartTimeUsNotify = mNotify->dup(); 598 mStartTimeUsNotify->setInt32("what", kWhatStartedAt); 599 mStartTimeUsNotify->setString("uri", mURI); 600 601 uint32_t streamTypeMask; 602 CHECK(msg->findInt32("streamTypeMask", (int32_t *)&streamTypeMask)); 603 604 int64_t startTimeUs; 605 int64_t segmentStartTimeUs; 606 int32_t startDiscontinuitySeq; 607 int32_t seekMode; 608 CHECK(msg->findInt64("startTimeUs", &startTimeUs)); 609 CHECK(msg->findInt64("segmentStartTimeUs", &segmentStartTimeUs)); 610 CHECK(msg->findInt32("startDiscontinuitySeq", &startDiscontinuitySeq)); 611 CHECK(msg->findInt32("seekMode", &seekMode)); 612 613 if (streamTypeMask & LiveSession::STREAMTYPE_AUDIO) { 614 void *ptr; 615 CHECK(msg->findPointer("audioSource", &ptr)); 616 617 mPacketSources.add( 618 LiveSession::STREAMTYPE_AUDIO, 619 static_cast<AnotherPacketSource *>(ptr)); 620 } 621 622 if (streamTypeMask & LiveSession::STREAMTYPE_VIDEO) { 623 void *ptr; 624 CHECK(msg->findPointer("videoSource", &ptr)); 625 626 mPacketSources.add( 627 LiveSession::STREAMTYPE_VIDEO, 628 static_cast<AnotherPacketSource *>(ptr)); 629 } 630 631 if (streamTypeMask & LiveSession::STREAMTYPE_SUBTITLES) { 632 void *ptr; 633 CHECK(msg->findPointer("subtitleSource", &ptr)); 634 635 mPacketSources.add( 636 LiveSession::STREAMTYPE_SUBTITLES, 637 static_cast<AnotherPacketSource *>(ptr)); 638 } 639 640 mStreamTypeMask = streamTypeMask; 641 642 mSegmentStartTimeUs = segmentStartTimeUs; 643 644 if (startDiscontinuitySeq >= 0) { 645 mDiscontinuitySeq = startDiscontinuitySeq; 646 } 647 648 mRefreshState = INITIAL_MINIMUM_RELOAD_DELAY; 649 mSeekMode = (LiveSession::SeekMode) seekMode; 650 651 if (startTimeUs >= 0 || mSeekMode == LiveSession::kSeekModeNextSample) { 652 mStartup = true; 653 mIDRFound = false; 654 mVideoBuffer->clear(); 655 } 656 657 if (startTimeUs >= 0) { 658 mStartTimeUs = startTimeUs; 659 mFirstPTSValid = false; 660 mSeqNumber = -1; 661 mTimeChangeSignaled = false; 662 mDownloadState->resetState(); 663 } 664 665 postMonitorQueue(); 666 667 return OK; 668} 669 670void PlaylistFetcher::onPause() { 671 cancelMonitorQueue(); 672 mLastDiscontinuitySeq = mDiscontinuitySeq; 673 674 setStoppingThreshold(-1.0f); 675} 676 677void PlaylistFetcher::onStop(const sp<AMessage> &msg) { 678 cancelMonitorQueue(); 679 680 int32_t clear; 681 CHECK(msg->findInt32("clear", &clear)); 682 if (clear) { 683 for (size_t i = 0; i < mPacketSources.size(); i++) { 684 sp<AnotherPacketSource> packetSource = mPacketSources.valueAt(i); 685 packetSource->clear(); 686 } 687 } 688 689 // close off the connection after use 690 mHTTPDataSource->disconnect(); 691 692 mDownloadState->resetState(); 693 mPacketSources.clear(); 694 mStreamTypeMask = 0; 695 696 setStoppingThreshold(-1.0f); 697} 698 699// Resume until we have reached the boundary timestamps listed in `msg`; when 700// the remaining time is too short (within a resume threshold) stop immediately 701// instead. 702status_t PlaylistFetcher::onResumeUntil(const sp<AMessage> &msg) { 703 sp<AMessage> params; 704 CHECK(msg->findMessage("params", ¶ms)); 705 706 mStopParams = params; 707 onDownloadNext(); 708 709 return OK; 710} 711 712void PlaylistFetcher::notifyStopReached() { 713 sp<AMessage> notify = mNotify->dup(); 714 notify->setInt32("what", kWhatStopReached); 715 notify->post(); 716} 717 718void PlaylistFetcher::notifyError(status_t err) { 719 sp<AMessage> notify = mNotify->dup(); 720 notify->setInt32("what", kWhatError); 721 notify->setInt32("err", err); 722 notify->post(); 723} 724 725void PlaylistFetcher::queueDiscontinuity( 726 ATSParser::DiscontinuityType type, const sp<AMessage> &extra) { 727 for (size_t i = 0; i < mPacketSources.size(); ++i) { 728 // do not discard buffer upon #EXT-X-DISCONTINUITY tag 729 // (seek will discard buffer by abandoning old fetchers) 730 mPacketSources.valueAt(i)->queueDiscontinuity( 731 type, extra, false /* discard */); 732 } 733} 734 735void PlaylistFetcher::onMonitorQueue() { 736 bool downloadMore = false; 737 738 // in the middle of an unfinished download, delay 739 // playlist refresh as it'll change seq numbers 740 if (!mDownloadState->hasSavedState()) { 741 refreshPlaylist(); 742 } 743 744 int32_t targetDurationSecs; 745 int64_t targetDurationUs = kMinBufferedDurationUs; 746 if (mPlaylist != NULL) { 747 if (mPlaylist->meta() == NULL || !mPlaylist->meta()->findInt32( 748 "target-duration", &targetDurationSecs)) { 749 ALOGE("Playlist is missing required EXT-X-TARGETDURATION tag"); 750 notifyError(ERROR_MALFORMED); 751 return; 752 } 753 targetDurationUs = targetDurationSecs * 1000000ll; 754 } 755 756 int64_t bufferedDurationUs = 0ll; 757 status_t finalResult = OK; 758 if (mStreamTypeMask == LiveSession::STREAMTYPE_SUBTITLES) { 759 sp<AnotherPacketSource> packetSource = 760 mPacketSources.valueFor(LiveSession::STREAMTYPE_SUBTITLES); 761 762 bufferedDurationUs = 763 packetSource->getBufferedDurationUs(&finalResult); 764 } else { 765 // Use min stream duration, but ignore streams that never have any packet 766 // enqueued to prevent us from waiting on a non-existent stream; 767 // when we cannot make out from the manifest what streams are included in 768 // a playlist we might assume extra streams. 769 bufferedDurationUs = -1ll; 770 for (size_t i = 0; i < mPacketSources.size(); ++i) { 771 if ((mStreamTypeMask & mPacketSources.keyAt(i)) == 0 772 || mPacketSources[i]->getLatestEnqueuedMeta() == NULL) { 773 continue; 774 } 775 776 int64_t bufferedStreamDurationUs = 777 mPacketSources.valueAt(i)->getBufferedDurationUs(&finalResult); 778 779 FSLOGV(mPacketSources.keyAt(i), "buffered %lld", (long long)bufferedStreamDurationUs); 780 781 if (bufferedDurationUs == -1ll 782 || bufferedStreamDurationUs < bufferedDurationUs) { 783 bufferedDurationUs = bufferedStreamDurationUs; 784 } 785 } 786 if (bufferedDurationUs == -1ll) { 787 bufferedDurationUs = 0ll; 788 } 789 } 790 791 if (finalResult == OK && bufferedDurationUs < kMinBufferedDurationUs) { 792 FLOGV("monitoring, buffered=%lld < %lld", 793 (long long)bufferedDurationUs, (long long)kMinBufferedDurationUs); 794 795 // delay the next download slightly; hopefully this gives other concurrent fetchers 796 // a better chance to run. 797 // onDownloadNext(); 798 sp<AMessage> msg = new AMessage(kWhatDownloadNext, this); 799 msg->setInt32("generation", mMonitorQueueGeneration); 800 msg->post(1000l); 801 } else { 802 // We'd like to maintain buffering above durationToBufferUs, so try 803 // again when buffer just about to go below durationToBufferUs 804 // (or after targetDurationUs / 2, whichever is smaller). 805 int64_t delayUs = bufferedDurationUs - kMinBufferedDurationUs + 1000000ll; 806 if (delayUs > targetDurationUs / 2) { 807 delayUs = targetDurationUs / 2; 808 } 809 810 FLOGV("pausing for %lld, buffered=%lld > %lld", 811 (long long)delayUs, 812 (long long)bufferedDurationUs, 813 (long long)kMinBufferedDurationUs); 814 815 postMonitorQueue(delayUs); 816 } 817} 818 819status_t PlaylistFetcher::refreshPlaylist() { 820 if (delayUsToRefreshPlaylist() <= 0) { 821 bool unchanged; 822 sp<M3UParser> playlist = mSession->fetchPlaylist( 823 mURI.c_str(), mPlaylistHash, &unchanged); 824 825 if (playlist == NULL) { 826 if (unchanged) { 827 // We succeeded in fetching the playlist, but it was 828 // unchanged from the last time we tried. 829 830 if (mRefreshState != THIRD_UNCHANGED_RELOAD_ATTEMPT) { 831 mRefreshState = (RefreshState)(mRefreshState + 1); 832 } 833 } else { 834 ALOGE("failed to load playlist at url '%s'", uriDebugString(mURI).c_str()); 835 return ERROR_IO; 836 } 837 } else { 838 mRefreshState = INITIAL_MINIMUM_RELOAD_DELAY; 839 mPlaylist = playlist; 840 841 if (mPlaylist->isComplete() || mPlaylist->isEvent()) { 842 updateDuration(); 843 } 844 // Notify LiveSession to use target-duration based buffering level 845 // for up/down switch. Default LiveSession::kUpSwitchMark may not 846 // be reachable for live streams, as our max buffering amount is 847 // limited to 3 segments. 848 if (!mPlaylist->isComplete()) { 849 updateTargetDuration(); 850 } 851 } 852 853 mLastPlaylistFetchTimeUs = ALooper::GetNowUs(); 854 } 855 return OK; 856} 857 858// static 859bool PlaylistFetcher::bufferStartsWithTsSyncByte(const sp<ABuffer>& buffer) { 860 return buffer->size() > 0 && buffer->data()[0] == 0x47; 861} 862 863bool PlaylistFetcher::shouldPauseDownload() { 864 if (mStreamTypeMask == LiveSession::STREAMTYPE_SUBTITLES) { 865 // doesn't apply to subtitles 866 return false; 867 } 868 869 // Calculate threshold to abort current download 870 int32_t targetDurationSecs; 871 CHECK(mPlaylist->meta()->findInt32("target-duration", &targetDurationSecs)); 872 int64_t targetDurationUs = targetDurationSecs * 1000000ll; 873 int64_t thresholdUs = -1; 874 { 875 AutoMutex _l(mThresholdLock); 876 thresholdUs = (mThresholdRatio < 0.0f) ? 877 -1ll : mThresholdRatio * targetDurationUs; 878 } 879 880 if (thresholdUs < 0) { 881 // never abort 882 return false; 883 } else if (thresholdUs == 0) { 884 // immediately abort 885 return true; 886 } 887 888 // now we have a positive thresholdUs, abort if remaining 889 // portion to download is over that threshold. 890 if (mSegmentFirstPTS < 0) { 891 // this means we haven't even find the first access unit, 892 // abort now as we must be very far away from the end. 893 return true; 894 } 895 int64_t lastEnqueueUs = mSegmentFirstPTS; 896 for (size_t i = 0; i < mPacketSources.size(); ++i) { 897 if ((mStreamTypeMask & mPacketSources.keyAt(i)) == 0) { 898 continue; 899 } 900 sp<AMessage> meta = mPacketSources[i]->getLatestEnqueuedMeta(); 901 int32_t type; 902 if (meta == NULL || meta->findInt32("discontinuity", &type)) { 903 continue; 904 } 905 int64_t tmpUs; 906 CHECK(meta->findInt64("timeUs", &tmpUs)); 907 if (tmpUs > lastEnqueueUs) { 908 lastEnqueueUs = tmpUs; 909 } 910 } 911 lastEnqueueUs -= mSegmentFirstPTS; 912 913 FLOGV("%spausing now, thresholdUs %lld, remaining %lld", 914 targetDurationUs - lastEnqueueUs > thresholdUs ? "" : "not ", 915 (long long)thresholdUs, 916 (long long)(targetDurationUs - lastEnqueueUs)); 917 918 if (targetDurationUs - lastEnqueueUs > thresholdUs) { 919 return true; 920 } 921 return false; 922} 923 924bool PlaylistFetcher::initDownloadState( 925 AString &uri, 926 sp<AMessage> &itemMeta, 927 int32_t &firstSeqNumberInPlaylist, 928 int32_t &lastSeqNumberInPlaylist) { 929 status_t err = refreshPlaylist(); 930 firstSeqNumberInPlaylist = 0; 931 lastSeqNumberInPlaylist = 0; 932 bool discontinuity = false; 933 934 if (mPlaylist != NULL) { 935 if (mPlaylist->meta() != NULL) { 936 mPlaylist->meta()->findInt32("media-sequence", &firstSeqNumberInPlaylist); 937 } 938 939 lastSeqNumberInPlaylist = 940 firstSeqNumberInPlaylist + (int32_t)mPlaylist->size() - 1; 941 942 if (mDiscontinuitySeq < 0) { 943 mDiscontinuitySeq = mPlaylist->getDiscontinuitySeq(); 944 } 945 } 946 947 mSegmentFirstPTS = -1ll; 948 949 if (mPlaylist != NULL && mSeqNumber < 0) { 950 CHECK_GE(mStartTimeUs, 0ll); 951 952 if (mSegmentStartTimeUs < 0) { 953 if (!mPlaylist->isComplete() && !mPlaylist->isEvent()) { 954 // If this is a live session, start 3 segments from the end on connect 955 mSeqNumber = lastSeqNumberInPlaylist - 3; 956 if (mSeqNumber < firstSeqNumberInPlaylist) { 957 mSeqNumber = firstSeqNumberInPlaylist; 958 } 959 } else { 960 // When seeking mSegmentStartTimeUs is unavailable (< 0), we 961 // use mStartTimeUs (client supplied timestamp) to determine both start segment 962 // and relative position inside a segment 963 mSeqNumber = getSeqNumberForTime(mStartTimeUs); 964 mStartTimeUs -= getSegmentStartTimeUs(mSeqNumber); 965 } 966 mStartTimeUsRelative = true; 967 FLOGV("Initial sequence number for time %lld is %d from (%d .. %d)", 968 (long long)mStartTimeUs, mSeqNumber, firstSeqNumberInPlaylist, 969 lastSeqNumberInPlaylist); 970 } else { 971 // When adapting or track switching, mSegmentStartTimeUs (relative 972 // to media time 0) is used to determine the start segment; mStartTimeUs (absolute 973 // timestamps coming from the media container) is used to determine the position 974 // inside a segments. 975 mSeqNumber = getSeqNumberForTime(mSegmentStartTimeUs); 976 if (mStreamTypeMask != LiveSession::STREAMTYPE_SUBTITLES 977 && mSeekMode != LiveSession::kSeekModeNextSample) { 978 // avoid double fetch/decode 979 mSeqNumber += 1; 980 } 981 ssize_t minSeq = getSeqNumberForDiscontinuity(mDiscontinuitySeq); 982 if (mSeqNumber < minSeq) { 983 mSeqNumber = minSeq; 984 } 985 986 if (mSeqNumber < firstSeqNumberInPlaylist) { 987 mSeqNumber = firstSeqNumberInPlaylist; 988 } 989 990 if (mSeqNumber > lastSeqNumberInPlaylist) { 991 mSeqNumber = lastSeqNumberInPlaylist; 992 } 993 FLOGV("Initial sequence number is %d from (%d .. %d)", 994 mSeqNumber, firstSeqNumberInPlaylist, 995 lastSeqNumberInPlaylist); 996 } 997 } 998 999 // if mPlaylist is NULL then err must be non-OK; but the other way around might not be true 1000 if (mSeqNumber < firstSeqNumberInPlaylist 1001 || mSeqNumber > lastSeqNumberInPlaylist 1002 || err != OK) { 1003 if ((err != OK || !mPlaylist->isComplete()) && mNumRetries < kMaxNumRetries) { 1004 ++mNumRetries; 1005 1006 if (mSeqNumber > lastSeqNumberInPlaylist || err != OK) { 1007 // make sure we reach this retry logic on refresh failures 1008 // by adding an err != OK clause to all enclosing if's. 1009 1010 // refresh in increasing fraction (1/2, 1/3, ...) of the 1011 // playlist's target duration or 3 seconds, whichever is less 1012 int64_t delayUs = kMaxMonitorDelayUs; 1013 if (mPlaylist != NULL && mPlaylist->meta() != NULL) { 1014 int32_t targetDurationSecs; 1015 CHECK(mPlaylist->meta()->findInt32("target-duration", &targetDurationSecs)); 1016 delayUs = mPlaylist->size() * targetDurationSecs * 1017 1000000ll / (1 + mNumRetries); 1018 } 1019 if (delayUs > kMaxMonitorDelayUs) { 1020 delayUs = kMaxMonitorDelayUs; 1021 } 1022 FLOGV("sequence number high: %d from (%d .. %d), " 1023 "monitor in %lld (retry=%d)", 1024 mSeqNumber, firstSeqNumberInPlaylist, 1025 lastSeqNumberInPlaylist, (long long)delayUs, mNumRetries); 1026 postMonitorQueue(delayUs); 1027 return false; 1028 } 1029 1030 if (err != OK) { 1031 notifyError(err); 1032 return false; 1033 } 1034 1035 // we've missed the boat, let's start 3 segments prior to the latest sequence 1036 // number available and signal a discontinuity. 1037 1038 ALOGI("We've missed the boat, restarting playback." 1039 " mStartup=%d, was looking for %d in %d-%d", 1040 mStartup, mSeqNumber, firstSeqNumberInPlaylist, 1041 lastSeqNumberInPlaylist); 1042 if (mStopParams != NULL) { 1043 // we should have kept on fetching until we hit the boundaries in mStopParams, 1044 // but since the segments we are supposed to fetch have already rolled off 1045 // the playlist, i.e. we have already missed the boat, we inevitably have to 1046 // skip. 1047 notifyStopReached(); 1048 return false; 1049 } 1050 mSeqNumber = lastSeqNumberInPlaylist - 3; 1051 if (mSeqNumber < firstSeqNumberInPlaylist) { 1052 mSeqNumber = firstSeqNumberInPlaylist; 1053 } 1054 discontinuity = true; 1055 1056 // fall through 1057 } else { 1058 if (mPlaylist != NULL) { 1059 ALOGE("Cannot find sequence number %d in playlist " 1060 "(contains %d - %d)", 1061 mSeqNumber, firstSeqNumberInPlaylist, 1062 firstSeqNumberInPlaylist + (int32_t)mPlaylist->size() - 1); 1063 1064 notifyError(ERROR_END_OF_STREAM); 1065 } else { 1066 // It's possible that we were never able to download the playlist. 1067 // In this case we should notify error, instead of EOS, as EOS during 1068 // prepare means we succeeded in downloading everything. 1069 ALOGE("Failed to download playlist!"); 1070 notifyError(ERROR_IO); 1071 } 1072 1073 return false; 1074 } 1075 } 1076 1077 mNumRetries = 0; 1078 1079 CHECK(mPlaylist->itemAt( 1080 mSeqNumber - firstSeqNumberInPlaylist, 1081 &uri, 1082 &itemMeta)); 1083 1084 CHECK(itemMeta->findInt32("discontinuity-sequence", &mDiscontinuitySeq)); 1085 1086 int32_t val; 1087 if (itemMeta->findInt32("discontinuity", &val) && val != 0) { 1088 discontinuity = true; 1089 } else if (mLastDiscontinuitySeq >= 0 1090 && mDiscontinuitySeq != mLastDiscontinuitySeq) { 1091 // Seek jumped to a new discontinuity sequence. We need to signal 1092 // a format change to decoder. Decoder needs to shutdown and be 1093 // created again if seamless format change is unsupported. 1094 FLOGV("saw discontinuity: mStartup %d, mLastDiscontinuitySeq %d, " 1095 "mDiscontinuitySeq %d, mStartTimeUs %lld", 1096 mStartup, mLastDiscontinuitySeq, mDiscontinuitySeq, (long long)mStartTimeUs); 1097 discontinuity = true; 1098 } 1099 mLastDiscontinuitySeq = -1; 1100 1101 // decrypt a junk buffer to prefetch key; since a session uses only one http connection, 1102 // this avoids interleaved connections to the key and segment file. 1103 { 1104 sp<ABuffer> junk = new ABuffer(16); 1105 junk->setRange(0, 16); 1106 status_t err = decryptBuffer(mSeqNumber - firstSeqNumberInPlaylist, junk, 1107 true /* first */); 1108 if (err != OK) { 1109 notifyError(err); 1110 return false; 1111 } 1112 } 1113 1114 if ((mStartup && !mTimeChangeSignaled) || discontinuity) { 1115 // We need to signal a time discontinuity to ATSParser on the 1116 // first segment after start, or on a discontinuity segment. 1117 // Setting mNextPTSTimeUs informs extractAndQueueAccessUnitsXX() 1118 // to send the time discontinuity. 1119 if (mPlaylist->isComplete() || mPlaylist->isEvent()) { 1120 // If this was a live event this made no sense since 1121 // we don't have access to all the segment before the current 1122 // one. 1123 mNextPTSTimeUs = getSegmentStartTimeUs(mSeqNumber); 1124 } 1125 1126 // Setting mTimeChangeSignaled to true, so that if start time 1127 // searching goes into 2nd segment (without a discontinuity), 1128 // we don't reset time again. It causes corruption when pending 1129 // data in ATSParser is cleared. 1130 mTimeChangeSignaled = true; 1131 } 1132 1133 if (discontinuity) { 1134 ALOGI("queueing discontinuity (explicit=%d)", discontinuity); 1135 1136 // Signal a format discontinuity to ATSParser to clear partial data 1137 // from previous streams. Not doing this causes bitstream corruption. 1138 if (mTSParser != NULL) { 1139 mTSParser->signalDiscontinuity( 1140 ATSParser::DISCONTINUITY_FORMATCHANGE, NULL /* extra */); 1141 } 1142 1143 queueDiscontinuity( 1144 ATSParser::DISCONTINUITY_FORMATCHANGE, 1145 NULL /* extra */); 1146 1147 if (mStartup && mStartTimeUsRelative && mFirstPTSValid) { 1148 // This means we guessed mStartTimeUs to be in the previous 1149 // segment (likely very close to the end), but either video or 1150 // audio has not found start by the end of that segment. 1151 // 1152 // If this new segment is not a discontinuity, keep searching. 1153 // 1154 // If this new segment even got a discontinuity marker, just 1155 // set mStartTimeUs=0, and take all samples from now on. 1156 mStartTimeUs = 0; 1157 mFirstPTSValid = false; 1158 } 1159 } 1160 1161 FLOGV("fetching segment %d from (%d .. %d)", 1162 mSeqNumber, firstSeqNumberInPlaylist, lastSeqNumberInPlaylist); 1163 return true; 1164} 1165 1166void PlaylistFetcher::onDownloadNext() { 1167 AString uri; 1168 sp<AMessage> itemMeta; 1169 sp<ABuffer> buffer; 1170 sp<ABuffer> tsBuffer; 1171 int32_t firstSeqNumberInPlaylist = 0; 1172 int32_t lastSeqNumberInPlaylist = 0; 1173 bool connectHTTP = true; 1174 1175 if (mDownloadState->hasSavedState()) { 1176 mDownloadState->restoreState( 1177 uri, 1178 itemMeta, 1179 buffer, 1180 tsBuffer, 1181 firstSeqNumberInPlaylist, 1182 lastSeqNumberInPlaylist); 1183 connectHTTP = false; 1184 FLOGV("resuming: '%s'", uri.c_str()); 1185 } else { 1186 if (!initDownloadState( 1187 uri, 1188 itemMeta, 1189 firstSeqNumberInPlaylist, 1190 lastSeqNumberInPlaylist)) { 1191 return; 1192 } 1193 FLOGV("fetching: '%s'", uri.c_str()); 1194 } 1195 1196 int64_t range_offset, range_length; 1197 if (!itemMeta->findInt64("range-offset", &range_offset) 1198 || !itemMeta->findInt64("range-length", &range_length)) { 1199 range_offset = 0; 1200 range_length = -1; 1201 } 1202 1203 // block-wise download 1204 bool shouldPause = false; 1205 ssize_t bytesRead; 1206 do { 1207 sp<DataSource> source = mHTTPDataSource; 1208 1209 int64_t startUs = ALooper::GetNowUs(); 1210 bytesRead = mSession->fetchFile( 1211 uri.c_str(), &buffer, range_offset, range_length, kDownloadBlockSize, 1212 &source, NULL, connectHTTP); 1213 1214 // add sample for bandwidth estimation, excluding samples from subtitles (as 1215 // its too small), or during startup/resumeUntil (when we could have more than 1216 // one connection open which affects bandwidth) 1217 if (!mStartup && mStopParams == NULL && bytesRead > 0 1218 && (mStreamTypeMask 1219 & (LiveSession::STREAMTYPE_AUDIO 1220 | LiveSession::STREAMTYPE_VIDEO))) { 1221 int64_t delayUs = ALooper::GetNowUs() - startUs; 1222 mSession->addBandwidthMeasurement(bytesRead, delayUs); 1223 1224 if (delayUs > 2000000ll) { 1225 FLOGV("bytesRead %zd took %.2f seconds - abnormal bandwidth dip", 1226 bytesRead, (double)delayUs / 1.0e6); 1227 } 1228 } 1229 1230 connectHTTP = false; 1231 1232 if (bytesRead < 0) { 1233 status_t err = bytesRead; 1234 ALOGE("failed to fetch .ts segment at url '%s'", uri.c_str()); 1235 notifyError(err); 1236 return; 1237 } 1238 1239 CHECK(buffer != NULL); 1240 1241 size_t size = buffer->size(); 1242 // Set decryption range. 1243 buffer->setRange(size - bytesRead, bytesRead); 1244 status_t err = decryptBuffer(mSeqNumber - firstSeqNumberInPlaylist, buffer, 1245 buffer->offset() == 0 /* first */); 1246 // Unset decryption range. 1247 buffer->setRange(0, size); 1248 1249 if (err != OK) { 1250 ALOGE("decryptBuffer failed w/ error %d", err); 1251 1252 notifyError(err); 1253 return; 1254 } 1255 1256 bool startUp = mStartup; // save current start up state 1257 1258 err = OK; 1259 if (bufferStartsWithTsSyncByte(buffer)) { 1260 // Incremental extraction is only supported for MPEG2 transport streams. 1261 if (tsBuffer == NULL) { 1262 tsBuffer = new ABuffer(buffer->data(), buffer->capacity()); 1263 tsBuffer->setRange(0, 0); 1264 } else if (tsBuffer->capacity() != buffer->capacity()) { 1265 size_t tsOff = tsBuffer->offset(), tsSize = tsBuffer->size(); 1266 tsBuffer = new ABuffer(buffer->data(), buffer->capacity()); 1267 tsBuffer->setRange(tsOff, tsSize); 1268 } 1269 tsBuffer->setRange(tsBuffer->offset(), tsBuffer->size() + bytesRead); 1270 err = extractAndQueueAccessUnitsFromTs(tsBuffer); 1271 } 1272 1273 if (err == -EAGAIN) { 1274 // starting sequence number too low/high 1275 mTSParser.clear(); 1276 for (size_t i = 0; i < mPacketSources.size(); i++) { 1277 sp<AnotherPacketSource> packetSource = mPacketSources.valueAt(i); 1278 packetSource->clear(); 1279 } 1280 postMonitorQueue(); 1281 return; 1282 } else if (err == ERROR_OUT_OF_RANGE) { 1283 // reached stopping point 1284 notifyStopReached(); 1285 return; 1286 } else if (err != OK) { 1287 notifyError(err); 1288 return; 1289 } 1290 // If we're switching, post start notification 1291 // this should only be posted when the last chunk is full processed by TSParser 1292 if (mSeekMode != LiveSession::kSeekModeExactPosition && startUp != mStartup) { 1293 CHECK(mStartTimeUsNotify != NULL); 1294 mStartTimeUsNotify->post(); 1295 mStartTimeUsNotify.clear(); 1296 shouldPause = true; 1297 } 1298 if (shouldPause || shouldPauseDownload()) { 1299 // save state and return if this is not the last chunk, 1300 // leaving the fetcher in paused state. 1301 if (bytesRead != 0) { 1302 mDownloadState->saveState( 1303 uri, 1304 itemMeta, 1305 buffer, 1306 tsBuffer, 1307 firstSeqNumberInPlaylist, 1308 lastSeqNumberInPlaylist); 1309 return; 1310 } 1311 shouldPause = true; 1312 } 1313 } while (bytesRead != 0); 1314 1315 if (bufferStartsWithTsSyncByte(buffer)) { 1316 // If we don't see a stream in the program table after fetching a full ts segment 1317 // mark it as nonexistent. 1318 const size_t kNumTypes = ATSParser::NUM_SOURCE_TYPES; 1319 ATSParser::SourceType srcTypes[kNumTypes] = 1320 { ATSParser::VIDEO, ATSParser::AUDIO }; 1321 LiveSession::StreamType streamTypes[kNumTypes] = 1322 { LiveSession::STREAMTYPE_VIDEO, LiveSession::STREAMTYPE_AUDIO }; 1323 1324 for (size_t i = 0; i < kNumTypes; i++) { 1325 ATSParser::SourceType srcType = srcTypes[i]; 1326 LiveSession::StreamType streamType = streamTypes[i]; 1327 1328 sp<AnotherPacketSource> source = 1329 static_cast<AnotherPacketSource *>( 1330 mTSParser->getSource(srcType).get()); 1331 1332 if (!mTSParser->hasSource(srcType)) { 1333 ALOGW("MPEG2 Transport stream does not contain %s data.", 1334 srcType == ATSParser::VIDEO ? "video" : "audio"); 1335 1336 mStreamTypeMask &= ~streamType; 1337 mPacketSources.removeItem(streamType); 1338 } 1339 } 1340 1341 } 1342 1343 if (checkDecryptPadding(buffer) != OK) { 1344 ALOGE("Incorrect padding bytes after decryption."); 1345 notifyError(ERROR_MALFORMED); 1346 return; 1347 } 1348 1349 if (tsBuffer != NULL) { 1350 AString method; 1351 CHECK(buffer->meta()->findString("cipher-method", &method)); 1352 if ((tsBuffer->size() > 0 && method == "NONE") 1353 || tsBuffer->size() > 16) { 1354 ALOGE("MPEG2 transport stream is not an even multiple of 188 " 1355 "bytes in length."); 1356 notifyError(ERROR_MALFORMED); 1357 return; 1358 } 1359 } 1360 1361 // bulk extract non-ts files 1362 bool startUp = mStartup; 1363 if (tsBuffer == NULL) { 1364 status_t err = extractAndQueueAccessUnits(buffer, itemMeta); 1365 if (err == -EAGAIN) { 1366 // starting sequence number too low/high 1367 postMonitorQueue(); 1368 return; 1369 } else if (err == ERROR_OUT_OF_RANGE) { 1370 // reached stopping point 1371 notifyStopReached(); 1372 return; 1373 } else if (err != OK) { 1374 notifyError(err); 1375 return; 1376 } 1377 } 1378 1379 ++mSeqNumber; 1380 1381 // if adapting, pause after found the next starting point 1382 if (mSeekMode != LiveSession::kSeekModeExactPosition && startUp != mStartup) { 1383 CHECK(mStartTimeUsNotify != NULL); 1384 mStartTimeUsNotify->post(); 1385 mStartTimeUsNotify.clear(); 1386 shouldPause = true; 1387 } 1388 1389 if (!shouldPause) { 1390 postMonitorQueue(); 1391 } 1392} 1393 1394int32_t PlaylistFetcher::getSeqNumberWithAnchorTime( 1395 int64_t anchorTimeUs, int64_t targetDiffUs) const { 1396 int32_t firstSeqNumberInPlaylist, lastSeqNumberInPlaylist; 1397 if (mPlaylist->meta() == NULL 1398 || !mPlaylist->meta()->findInt32("media-sequence", &firstSeqNumberInPlaylist)) { 1399 firstSeqNumberInPlaylist = 0; 1400 } 1401 lastSeqNumberInPlaylist = firstSeqNumberInPlaylist + mPlaylist->size() - 1; 1402 1403 int32_t index = mSeqNumber - firstSeqNumberInPlaylist - 1; 1404 // adjust anchorTimeUs to within targetDiffUs from mStartTimeUs 1405 while (index >= 0 && anchorTimeUs - mStartTimeUs > targetDiffUs) { 1406 sp<AMessage> itemMeta; 1407 CHECK(mPlaylist->itemAt(index, NULL /* uri */, &itemMeta)); 1408 1409 int64_t itemDurationUs; 1410 CHECK(itemMeta->findInt64("durationUs", &itemDurationUs)); 1411 1412 anchorTimeUs -= itemDurationUs; 1413 --index; 1414 } 1415 1416 int32_t newSeqNumber = firstSeqNumberInPlaylist + index + 1; 1417 if (newSeqNumber <= lastSeqNumberInPlaylist) { 1418 return newSeqNumber; 1419 } else { 1420 return lastSeqNumberInPlaylist; 1421 } 1422} 1423 1424int32_t PlaylistFetcher::getSeqNumberForDiscontinuity(size_t discontinuitySeq) const { 1425 int32_t firstSeqNumberInPlaylist; 1426 if (mPlaylist->meta() == NULL || !mPlaylist->meta()->findInt32( 1427 "media-sequence", &firstSeqNumberInPlaylist)) { 1428 firstSeqNumberInPlaylist = 0; 1429 } 1430 1431 size_t index = 0; 1432 while (index < mPlaylist->size()) { 1433 sp<AMessage> itemMeta; 1434 CHECK(mPlaylist->itemAt( index, NULL /* uri */, &itemMeta)); 1435 size_t curDiscontinuitySeq; 1436 CHECK(itemMeta->findInt32("discontinuity-sequence", (int32_t *)&curDiscontinuitySeq)); 1437 int32_t seqNumber = firstSeqNumberInPlaylist + index; 1438 if (curDiscontinuitySeq == discontinuitySeq) { 1439 return seqNumber; 1440 } else if (curDiscontinuitySeq > discontinuitySeq) { 1441 return seqNumber <= 0 ? 0 : seqNumber - 1; 1442 } 1443 1444 ++index; 1445 } 1446 1447 return firstSeqNumberInPlaylist + mPlaylist->size(); 1448} 1449 1450int32_t PlaylistFetcher::getSeqNumberForTime(int64_t timeUs) const { 1451 int32_t firstSeqNumberInPlaylist; 1452 if (mPlaylist->meta() == NULL || !mPlaylist->meta()->findInt32( 1453 "media-sequence", &firstSeqNumberInPlaylist)) { 1454 firstSeqNumberInPlaylist = 0; 1455 } 1456 1457 size_t index = 0; 1458 int64_t segmentStartUs = 0; 1459 while (index < mPlaylist->size()) { 1460 sp<AMessage> itemMeta; 1461 CHECK(mPlaylist->itemAt( 1462 index, NULL /* uri */, &itemMeta)); 1463 1464 int64_t itemDurationUs; 1465 CHECK(itemMeta->findInt64("durationUs", &itemDurationUs)); 1466 1467 if (timeUs < segmentStartUs + itemDurationUs) { 1468 break; 1469 } 1470 1471 segmentStartUs += itemDurationUs; 1472 ++index; 1473 } 1474 1475 if (index >= mPlaylist->size()) { 1476 index = mPlaylist->size() - 1; 1477 } 1478 1479 return firstSeqNumberInPlaylist + index; 1480} 1481 1482const sp<ABuffer> &PlaylistFetcher::setAccessUnitProperties( 1483 const sp<ABuffer> &accessUnit, const sp<AnotherPacketSource> &source, bool discard) { 1484 sp<MetaData> format = source->getFormat(); 1485 if (format != NULL) { 1486 // for simplicity, store a reference to the format in each unit 1487 accessUnit->meta()->setObject("format", format); 1488 } 1489 1490 if (discard) { 1491 accessUnit->meta()->setInt32("discard", discard); 1492 } 1493 1494 int32_t targetDurationSecs; 1495 if (mPlaylist->meta()->findInt32("target-duration", &targetDurationSecs)) { 1496 accessUnit->meta()->setInt32("targetDuration", targetDurationSecs); 1497 } 1498 1499 accessUnit->meta()->setInt32("discontinuitySeq", mDiscontinuitySeq); 1500 accessUnit->meta()->setInt64("segmentStartTimeUs", getSegmentStartTimeUs(mSeqNumber)); 1501 accessUnit->meta()->setInt64("segmentDurationUs", getSegmentDurationUs(mSeqNumber)); 1502 return accessUnit; 1503} 1504 1505status_t PlaylistFetcher::extractAndQueueAccessUnitsFromTs(const sp<ABuffer> &buffer) { 1506 if (mTSParser == NULL) { 1507 // Use TS_TIMESTAMPS_ARE_ABSOLUTE so pts carry over between fetchers. 1508 mTSParser = new ATSParser(ATSParser::TS_TIMESTAMPS_ARE_ABSOLUTE); 1509 } 1510 1511 if (mNextPTSTimeUs >= 0ll) { 1512 sp<AMessage> extra = new AMessage; 1513 // Since we are using absolute timestamps, signal an offset of 0 to prevent 1514 // ATSParser from skewing the timestamps of access units. 1515 extra->setInt64(IStreamListener::kKeyMediaTimeUs, 0); 1516 1517 // When adapting, signal a recent media time to the parser, 1518 // so that PTS wrap around is handled for the new variant. 1519 if (mStartTimeUs >= 0 && !mStartTimeUsRelative) { 1520 extra->setInt64(IStreamListener::kKeyRecentMediaTimeUs, mStartTimeUs); 1521 } 1522 1523 mTSParser->signalDiscontinuity( 1524 ATSParser::DISCONTINUITY_TIME, extra); 1525 1526 mNextPTSTimeUs = -1ll; 1527 } 1528 1529 size_t offset = 0; 1530 while (offset + 188 <= buffer->size()) { 1531 status_t err = mTSParser->feedTSPacket(buffer->data() + offset, 188); 1532 1533 if (err != OK) { 1534 return err; 1535 } 1536 1537 offset += 188; 1538 } 1539 // setRange to indicate consumed bytes. 1540 buffer->setRange(buffer->offset() + offset, buffer->size() - offset); 1541 1542 status_t err = OK; 1543 for (size_t i = mPacketSources.size(); i-- > 0;) { 1544 sp<AnotherPacketSource> packetSource = mPacketSources.valueAt(i); 1545 1546 const LiveSession::StreamType stream = mPacketSources.keyAt(i); 1547 if (stream == LiveSession::STREAMTYPE_SUBTITLES) { 1548 ALOGE("MPEG2 Transport streams do not contain subtitles."); 1549 return ERROR_MALFORMED; 1550 } 1551 const char *key = LiveSession::getKeyForStream(stream); 1552 ATSParser::SourceType type = 1553 (stream == LiveSession::STREAMTYPE_AUDIO) ? 1554 ATSParser::AUDIO : ATSParser::VIDEO; 1555 1556 sp<AnotherPacketSource> source = 1557 static_cast<AnotherPacketSource *>( 1558 mTSParser->getSource(type).get()); 1559 1560 if (source == NULL) { 1561 continue; 1562 } 1563 1564 const char *mime; 1565 sp<MetaData> format = source->getFormat(); 1566 bool isAvc = format != NULL && format->findCString(kKeyMIMEType, &mime) 1567 && !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC); 1568 1569 sp<ABuffer> accessUnit; 1570 status_t finalResult; 1571 while (source->hasBufferAvailable(&finalResult) 1572 && source->dequeueAccessUnit(&accessUnit) == OK) { 1573 1574 int64_t timeUs; 1575 CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs)); 1576 1577 if (mSegmentFirstPTS < 0ll) { 1578 mSegmentFirstPTS = timeUs; 1579 if (!mStartTimeUsRelative) { 1580 int32_t firstSeqNumberInPlaylist; 1581 if (mPlaylist->meta() == NULL || !mPlaylist->meta()->findInt32( 1582 "media-sequence", &firstSeqNumberInPlaylist)) { 1583 firstSeqNumberInPlaylist = 0; 1584 } 1585 1586 int32_t targetDurationSecs; 1587 CHECK(mPlaylist->meta()->findInt32("target-duration", &targetDurationSecs)); 1588 int64_t targetDurationUs = targetDurationSecs * 1000000ll; 1589 // mStartup 1590 // mStartup is true until we have queued a packet for all the streams 1591 // we are fetching. We queue packets whose timestamps are greater than 1592 // mStartTimeUs. 1593 // mSegmentStartTimeUs >= 0 1594 // mSegmentStartTimeUs is non-negative when adapting or switching tracks 1595 // mSeqNumber > firstSeqNumberInPlaylist 1596 // don't decrement mSeqNumber if it already points to the 1st segment 1597 // timeUs - mStartTimeUs > targetDurationUs: 1598 // This and the 2 above conditions should only happen when adapting in a live 1599 // stream; the old fetcher has already fetched to mStartTimeUs; the new fetcher 1600 // would start fetching after timeUs, which should be greater than mStartTimeUs; 1601 // the old fetcher would then continue fetching data until timeUs. We don't want 1602 // timeUs to be too far ahead of mStartTimeUs because we want the old fetcher to 1603 // stop as early as possible. The definition of being "too far ahead" is 1604 // arbitrary; here we use targetDurationUs as threshold. 1605 int64_t targetDiffUs = (mSeekMode == LiveSession::kSeekModeNextSample 1606 ? 0 : targetDurationUs); 1607 if (mStartup && mSegmentStartTimeUs >= 0 1608 && mSeqNumber > firstSeqNumberInPlaylist 1609 && timeUs - mStartTimeUs > targetDiffUs) { 1610 // we just guessed a starting timestamp that is too high when adapting in a 1611 // live stream; re-adjust based on the actual timestamp extracted from the 1612 // media segment; if we didn't move backward after the re-adjustment 1613 // (newSeqNumber), start at least 1 segment prior. 1614 int32_t newSeqNumber = getSeqNumberWithAnchorTime( 1615 timeUs, targetDiffUs); 1616 1617 FLOGV("guessed wrong seq number: timeUs=%lld, mStartTimeUs=%lld, " 1618 "targetDurationUs=%lld, mSeqNumber=%d, newSeq=%d, firstSeq=%d", 1619 (long long)timeUs, 1620 (long long)mStartTimeUs, 1621 (long long)targetDurationUs, 1622 mSeqNumber, 1623 newSeqNumber, 1624 firstSeqNumberInPlaylist); 1625 1626 if (newSeqNumber >= mSeqNumber) { 1627 --mSeqNumber; 1628 } else { 1629 mSeqNumber = newSeqNumber; 1630 } 1631 mStartTimeUsNotify = mNotify->dup(); 1632 mStartTimeUsNotify->setInt32("what", kWhatStartedAt); 1633 mStartTimeUsNotify->setString("uri", mURI); 1634 mIDRFound = false; 1635 return -EAGAIN; 1636 } 1637 } 1638 } 1639 if (mStartup) { 1640 if (!mFirstPTSValid) { 1641 mFirstTimeUs = timeUs; 1642 mFirstPTSValid = true; 1643 } 1644 bool startTimeReached = true; 1645 if (mStartTimeUsRelative) { 1646 FLOGV("startTimeUsRelative, timeUs (%lld) - %lld = %lld", 1647 (long long)timeUs, 1648 (long long)mFirstTimeUs, 1649 (long long)(timeUs - mFirstTimeUs)); 1650 timeUs -= mFirstTimeUs; 1651 if (timeUs < 0) { 1652 FLOGV("clamp negative timeUs to 0"); 1653 timeUs = 0; 1654 } 1655 startTimeReached = (timeUs >= mStartTimeUs); 1656 } 1657 1658 if (!startTimeReached || (isAvc && !mIDRFound)) { 1659 // buffer up to the closest preceding IDR frame in the next segement, 1660 // or the closest succeeding IDR frame after the exact position 1661 FSLOGV(stream, "timeUs=%lld, mStartTimeUs=%lld, mIDRFound=%d", 1662 (long long)timeUs, (long long)mStartTimeUs, mIDRFound); 1663 if (isAvc) { 1664 if (IsIDR(accessUnit)) { 1665 mVideoBuffer->clear(); 1666 FSLOGV(stream, "found IDR, clear mVideoBuffer"); 1667 mIDRFound = true; 1668 } 1669 if (mIDRFound && mStartTimeUsRelative && !startTimeReached) { 1670 mVideoBuffer->queueAccessUnit(accessUnit); 1671 FSLOGV(stream, "saving AVC video AccessUnit"); 1672 } 1673 } 1674 if (!startTimeReached || (isAvc && !mIDRFound)) { 1675 continue; 1676 } 1677 } 1678 } 1679 1680 if (mStartTimeUsNotify != NULL) { 1681 uint32_t streamMask = 0; 1682 mStartTimeUsNotify->findInt32("streamMask", (int32_t *) &streamMask); 1683 if (!(streamMask & mPacketSources.keyAt(i))) { 1684 streamMask |= mPacketSources.keyAt(i); 1685 mStartTimeUsNotify->setInt32("streamMask", streamMask); 1686 FSLOGV(stream, "found start point, timeUs=%lld, streamMask becomes %x", 1687 (long long)timeUs, streamMask); 1688 1689 if (streamMask == mStreamTypeMask) { 1690 FLOGV("found start point for all streams"); 1691 mStartup = false; 1692 } 1693 } 1694 } 1695 1696 if (mStopParams != NULL) { 1697 int32_t discontinuitySeq; 1698 int64_t stopTimeUs; 1699 if (!mStopParams->findInt32("discontinuitySeq", &discontinuitySeq) 1700 || discontinuitySeq > mDiscontinuitySeq 1701 || !mStopParams->findInt64(key, &stopTimeUs) 1702 || (discontinuitySeq == mDiscontinuitySeq 1703 && timeUs >= stopTimeUs)) { 1704 FSLOGV(stream, "reached stop point, timeUs=%lld", (long long)timeUs); 1705 mStreamTypeMask &= ~stream; 1706 mPacketSources.removeItemsAt(i); 1707 break; 1708 } 1709 } 1710 1711 if (stream == LiveSession::STREAMTYPE_VIDEO) { 1712 const bool discard = true; 1713 status_t status; 1714 while (mVideoBuffer->hasBufferAvailable(&status)) { 1715 sp<ABuffer> videoBuffer; 1716 mVideoBuffer->dequeueAccessUnit(&videoBuffer); 1717 setAccessUnitProperties(videoBuffer, source, discard); 1718 packetSource->queueAccessUnit(videoBuffer); 1719 int64_t bufferTimeUs; 1720 CHECK(videoBuffer->meta()->findInt64("timeUs", &bufferTimeUs)); 1721 FSLOGV(stream, "queueAccessUnit (saved), timeUs=%lld", 1722 (long long)bufferTimeUs); 1723 } 1724 } 1725 1726 setAccessUnitProperties(accessUnit, source); 1727 packetSource->queueAccessUnit(accessUnit); 1728 FSLOGV(stream, "queueAccessUnit, timeUs=%lld", (long long)timeUs); 1729 } 1730 1731 if (err != OK) { 1732 break; 1733 } 1734 } 1735 1736 if (err != OK) { 1737 for (size_t i = mPacketSources.size(); i-- > 0;) { 1738 sp<AnotherPacketSource> packetSource = mPacketSources.valueAt(i); 1739 packetSource->clear(); 1740 } 1741 return err; 1742 } 1743 1744 if (!mStreamTypeMask) { 1745 // Signal gap is filled between original and new stream. 1746 FLOGV("reached stop point for all streams"); 1747 return ERROR_OUT_OF_RANGE; 1748 } 1749 1750 return OK; 1751} 1752 1753/* static */ 1754bool PlaylistFetcher::bufferStartsWithWebVTTMagicSequence( 1755 const sp<ABuffer> &buffer) { 1756 size_t pos = 0; 1757 1758 // skip possible BOM 1759 if (buffer->size() >= pos + 3 && 1760 !memcmp("\xef\xbb\xbf", buffer->data() + pos, 3)) { 1761 pos += 3; 1762 } 1763 1764 // accept WEBVTT followed by SPACE, TAB or (CR) LF 1765 if (buffer->size() < pos + 6 || 1766 memcmp("WEBVTT", buffer->data() + pos, 6)) { 1767 return false; 1768 } 1769 pos += 6; 1770 1771 if (buffer->size() == pos) { 1772 return true; 1773 } 1774 1775 uint8_t sep = buffer->data()[pos]; 1776 return sep == ' ' || sep == '\t' || sep == '\n' || sep == '\r'; 1777} 1778 1779status_t PlaylistFetcher::extractAndQueueAccessUnits( 1780 const sp<ABuffer> &buffer, const sp<AMessage> &itemMeta) { 1781 if (bufferStartsWithWebVTTMagicSequence(buffer)) { 1782 if (mStreamTypeMask != LiveSession::STREAMTYPE_SUBTITLES) { 1783 ALOGE("This stream only contains subtitles."); 1784 return ERROR_MALFORMED; 1785 } 1786 1787 const sp<AnotherPacketSource> packetSource = 1788 mPacketSources.valueFor(LiveSession::STREAMTYPE_SUBTITLES); 1789 1790 int64_t durationUs; 1791 CHECK(itemMeta->findInt64("durationUs", &durationUs)); 1792 buffer->meta()->setInt64("timeUs", getSegmentStartTimeUs(mSeqNumber)); 1793 buffer->meta()->setInt64("durationUs", durationUs); 1794 buffer->meta()->setInt64("segmentStartTimeUs", getSegmentStartTimeUs(mSeqNumber)); 1795 buffer->meta()->setInt32("discontinuitySeq", mDiscontinuitySeq); 1796 buffer->meta()->setInt32("subtitleGeneration", mSubtitleGeneration); 1797 1798 packetSource->queueAccessUnit(buffer); 1799 return OK; 1800 } 1801 1802 if (mNextPTSTimeUs >= 0ll) { 1803 mNextPTSTimeUs = -1ll; 1804 } 1805 1806 // This better be an ISO 13818-7 (AAC) or ISO 13818-1 (MPEG) audio 1807 // stream prefixed by an ID3 tag. 1808 1809 bool firstID3Tag = true; 1810 uint64_t PTS = 0; 1811 1812 for (;;) { 1813 // Make sure to skip all ID3 tags preceding the audio data. 1814 // At least one must be present to provide the PTS timestamp. 1815 1816 ID3 id3(buffer->data(), buffer->size(), true /* ignoreV1 */); 1817 if (!id3.isValid()) { 1818 if (firstID3Tag) { 1819 ALOGE("Unable to parse ID3 tag."); 1820 return ERROR_MALFORMED; 1821 } else { 1822 break; 1823 } 1824 } 1825 1826 if (firstID3Tag) { 1827 bool found = false; 1828 1829 ID3::Iterator it(id3, "PRIV"); 1830 while (!it.done()) { 1831 size_t length; 1832 const uint8_t *data = it.getData(&length); 1833 1834 static const char *kMatchName = 1835 "com.apple.streaming.transportStreamTimestamp"; 1836 static const size_t kMatchNameLen = strlen(kMatchName); 1837 1838 if (length == kMatchNameLen + 1 + 8 1839 && !strncmp((const char *)data, kMatchName, kMatchNameLen)) { 1840 found = true; 1841 PTS = U64_AT(&data[kMatchNameLen + 1]); 1842 } 1843 1844 it.next(); 1845 } 1846 1847 if (!found) { 1848 ALOGE("Unable to extract transportStreamTimestamp from ID3 tag."); 1849 return ERROR_MALFORMED; 1850 } 1851 } 1852 1853 // skip the ID3 tag 1854 buffer->setRange( 1855 buffer->offset() + id3.rawSize(), buffer->size() - id3.rawSize()); 1856 1857 firstID3Tag = false; 1858 } 1859 1860 if (mStreamTypeMask != LiveSession::STREAMTYPE_AUDIO) { 1861 ALOGW("This stream only contains audio data!"); 1862 1863 mStreamTypeMask &= LiveSession::STREAMTYPE_AUDIO; 1864 1865 if (mStreamTypeMask == 0) { 1866 return OK; 1867 } 1868 } 1869 1870 sp<AnotherPacketSource> packetSource = 1871 mPacketSources.valueFor(LiveSession::STREAMTYPE_AUDIO); 1872 1873 if (packetSource->getFormat() == NULL && buffer->size() >= 7) { 1874 ABitReader bits(buffer->data(), buffer->size()); 1875 1876 // adts_fixed_header 1877 1878 CHECK_EQ(bits.getBits(12), 0xfffu); 1879 bits.skipBits(3); // ID, layer 1880 bool protection_absent __unused = bits.getBits(1) != 0; 1881 1882 unsigned profile = bits.getBits(2); 1883 CHECK_NE(profile, 3u); 1884 unsigned sampling_freq_index = bits.getBits(4); 1885 bits.getBits(1); // private_bit 1886 unsigned channel_configuration = bits.getBits(3); 1887 CHECK_NE(channel_configuration, 0u); 1888 bits.skipBits(2); // original_copy, home 1889 1890 sp<MetaData> meta = MakeAACCodecSpecificData( 1891 profile, sampling_freq_index, channel_configuration); 1892 1893 meta->setInt32(kKeyIsADTS, true); 1894 1895 packetSource->setFormat(meta); 1896 } 1897 1898 int64_t numSamples = 0ll; 1899 int32_t sampleRate; 1900 CHECK(packetSource->getFormat()->findInt32(kKeySampleRate, &sampleRate)); 1901 1902 int64_t timeUs = (PTS * 100ll) / 9ll; 1903 if (mStartup && !mFirstPTSValid) { 1904 mFirstPTSValid = true; 1905 mFirstTimeUs = timeUs; 1906 } 1907 1908 size_t offset = 0; 1909 while (offset < buffer->size()) { 1910 const uint8_t *adtsHeader = buffer->data() + offset; 1911 CHECK_LT(offset + 5, buffer->size()); 1912 1913 unsigned aac_frame_length = 1914 ((adtsHeader[3] & 3) << 11) 1915 | (adtsHeader[4] << 3) 1916 | (adtsHeader[5] >> 5); 1917 1918 if (aac_frame_length == 0) { 1919 const uint8_t *id3Header = adtsHeader; 1920 if (!memcmp(id3Header, "ID3", 3)) { 1921 ID3 id3(id3Header, buffer->size() - offset, true); 1922 if (id3.isValid()) { 1923 offset += id3.rawSize(); 1924 continue; 1925 }; 1926 } 1927 return ERROR_MALFORMED; 1928 } 1929 1930 CHECK_LE(offset + aac_frame_length, buffer->size()); 1931 1932 int64_t unitTimeUs = timeUs + numSamples * 1000000ll / sampleRate; 1933 offset += aac_frame_length; 1934 1935 // Each AAC frame encodes 1024 samples. 1936 numSamples += 1024; 1937 1938 if (mStartup) { 1939 int64_t startTimeUs = unitTimeUs; 1940 if (mStartTimeUsRelative) { 1941 startTimeUs -= mFirstTimeUs; 1942 if (startTimeUs < 0) { 1943 startTimeUs = 0; 1944 } 1945 } 1946 if (startTimeUs < mStartTimeUs) { 1947 continue; 1948 } 1949 1950 if (mStartTimeUsNotify != NULL) { 1951 int32_t targetDurationSecs; 1952 CHECK(mPlaylist->meta()->findInt32("target-duration", &targetDurationSecs)); 1953 int64_t targetDurationUs = targetDurationSecs * 1000000ll; 1954 1955 int64_t targetDiffUs =(mSeekMode == LiveSession::kSeekModeNextSample 1956 ? 0 : targetDurationUs); 1957 // Duplicated logic from how we handle .ts playlists. 1958 if (mStartup && mSegmentStartTimeUs >= 0 1959 && timeUs - mStartTimeUs > targetDiffUs) { 1960 int32_t newSeqNumber = getSeqNumberWithAnchorTime( 1961 timeUs, targetDiffUs); 1962 if (newSeqNumber >= mSeqNumber) { 1963 --mSeqNumber; 1964 } else { 1965 mSeqNumber = newSeqNumber; 1966 } 1967 return -EAGAIN; 1968 } 1969 1970 mStartTimeUsNotify->setInt32("streamMask", LiveSession::STREAMTYPE_AUDIO); 1971 mStartup = false; 1972 } 1973 } 1974 1975 if (mStopParams != NULL) { 1976 int32_t discontinuitySeq; 1977 int64_t stopTimeUs; 1978 if (!mStopParams->findInt32("discontinuitySeq", &discontinuitySeq) 1979 || discontinuitySeq > mDiscontinuitySeq 1980 || !mStopParams->findInt64("timeUsAudio", &stopTimeUs) 1981 || (discontinuitySeq == mDiscontinuitySeq && unitTimeUs >= stopTimeUs)) { 1982 mStreamTypeMask = 0; 1983 mPacketSources.clear(); 1984 return ERROR_OUT_OF_RANGE; 1985 } 1986 } 1987 1988 sp<ABuffer> unit = new ABuffer(aac_frame_length); 1989 memcpy(unit->data(), adtsHeader, aac_frame_length); 1990 1991 unit->meta()->setInt64("timeUs", unitTimeUs); 1992 setAccessUnitProperties(unit, packetSource); 1993 packetSource->queueAccessUnit(unit); 1994 } 1995 1996 return OK; 1997} 1998 1999void PlaylistFetcher::updateDuration() { 2000 int64_t durationUs = 0ll; 2001 for (size_t index = 0; index < mPlaylist->size(); ++index) { 2002 sp<AMessage> itemMeta; 2003 CHECK(mPlaylist->itemAt( 2004 index, NULL /* uri */, &itemMeta)); 2005 2006 int64_t itemDurationUs; 2007 CHECK(itemMeta->findInt64("durationUs", &itemDurationUs)); 2008 2009 durationUs += itemDurationUs; 2010 } 2011 2012 sp<AMessage> msg = mNotify->dup(); 2013 msg->setInt32("what", kWhatDurationUpdate); 2014 msg->setInt64("durationUs", durationUs); 2015 msg->post(); 2016} 2017 2018void PlaylistFetcher::updateTargetDuration() { 2019 int32_t targetDurationSecs; 2020 CHECK(mPlaylist->meta()->findInt32("target-duration", &targetDurationSecs)); 2021 int64_t targetDurationUs = targetDurationSecs * 1000000ll; 2022 2023 sp<AMessage> msg = mNotify->dup(); 2024 msg->setInt32("what", kWhatTargetDurationUpdate); 2025 msg->setInt64("targetDurationUs", targetDurationUs); 2026 msg->post(); 2027} 2028 2029} // namespace android 2030