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