PlaylistFetcher.cpp revision 7a39abac839092298cd184c5996dc82010d60a20
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/hexdump.h> 37#include <media/stagefright/FileSource.h> 38#include <media/stagefright/MediaDefs.h> 39#include <media/stagefright/MetaData.h> 40#include <media/stagefright/Utils.h> 41 42#include <ctype.h> 43#include <openssl/aes.h> 44#include <openssl/md5.h> 45 46namespace android { 47 48// static 49const int64_t PlaylistFetcher::kMinBufferedDurationUs = 10000000ll; 50const int64_t PlaylistFetcher::kMaxMonitorDelayUs = 3000000ll; 51const int32_t PlaylistFetcher::kDownloadBlockSize = 192; 52const int32_t PlaylistFetcher::kNumSkipFrames = 10; 53 54PlaylistFetcher::PlaylistFetcher( 55 const sp<AMessage> ¬ify, 56 const sp<LiveSession> &session, 57 const char *uri) 58 : mNotify(notify), 59 mStartTimeUsNotify(notify->dup()), 60 mSession(session), 61 mURI(uri), 62 mStreamTypeMask(0), 63 mStartTimeUs(-1ll), 64 mMinStartTimeUs(0ll), 65 mStopParams(NULL), 66 mLastPlaylistFetchTimeUs(-1ll), 67 mSeqNumber(-1), 68 mNumRetries(0), 69 mStartup(true), 70 mPrepared(false), 71 mNextPTSTimeUs(-1ll), 72 mMonitorQueueGeneration(0), 73 mRefreshState(INITIAL_MINIMUM_RELOAD_DELAY), 74 mFirstPTSValid(false), 75 mAbsoluteTimeAnchorUs(0ll) { 76 memset(mPlaylistHash, 0, sizeof(mPlaylistHash)); 77 mStartTimeUsNotify->setInt32("what", kWhatStartedAt); 78 mStartTimeUsNotify->setInt32("streamMask", 0); 79} 80 81PlaylistFetcher::~PlaylistFetcher() { 82} 83 84int64_t PlaylistFetcher::getSegmentStartTimeUs(int32_t seqNumber) const { 85 CHECK(mPlaylist != NULL); 86 87 int32_t firstSeqNumberInPlaylist; 88 if (mPlaylist->meta() == NULL || !mPlaylist->meta()->findInt32( 89 "media-sequence", &firstSeqNumberInPlaylist)) { 90 firstSeqNumberInPlaylist = 0; 91 } 92 93 int32_t lastSeqNumberInPlaylist = 94 firstSeqNumberInPlaylist + (int32_t)mPlaylist->size() - 1; 95 96 CHECK_GE(seqNumber, firstSeqNumberInPlaylist); 97 CHECK_LE(seqNumber, lastSeqNumberInPlaylist); 98 99 int64_t segmentStartUs = 0ll; 100 for (int32_t index = 0; 101 index < seqNumber - firstSeqNumberInPlaylist; ++index) { 102 sp<AMessage> itemMeta; 103 CHECK(mPlaylist->itemAt( 104 index, NULL /* uri */, &itemMeta)); 105 106 int64_t itemDurationUs; 107 CHECK(itemMeta->findInt64("durationUs", &itemDurationUs)); 108 109 segmentStartUs += itemDurationUs; 110 } 111 112 return segmentStartUs; 113} 114 115int64_t PlaylistFetcher::delayUsToRefreshPlaylist() const { 116 int64_t nowUs = ALooper::GetNowUs(); 117 118 if (mPlaylist == NULL || mLastPlaylistFetchTimeUs < 0ll) { 119 CHECK_EQ((int)mRefreshState, (int)INITIAL_MINIMUM_RELOAD_DELAY); 120 return 0ll; 121 } 122 123 if (mPlaylist->isComplete()) { 124 return (~0llu >> 1); 125 } 126 127 int32_t targetDurationSecs; 128 CHECK(mPlaylist->meta()->findInt32("target-duration", &targetDurationSecs)); 129 130 int64_t targetDurationUs = targetDurationSecs * 1000000ll; 131 132 int64_t minPlaylistAgeUs; 133 134 switch (mRefreshState) { 135 case INITIAL_MINIMUM_RELOAD_DELAY: 136 { 137 size_t n = mPlaylist->size(); 138 if (n > 0) { 139 sp<AMessage> itemMeta; 140 CHECK(mPlaylist->itemAt(n - 1, NULL /* uri */, &itemMeta)); 141 142 int64_t itemDurationUs; 143 CHECK(itemMeta->findInt64("durationUs", &itemDurationUs)); 144 145 minPlaylistAgeUs = itemDurationUs; 146 break; 147 } 148 149 // fall through 150 } 151 152 case FIRST_UNCHANGED_RELOAD_ATTEMPT: 153 { 154 minPlaylistAgeUs = targetDurationUs / 2; 155 break; 156 } 157 158 case SECOND_UNCHANGED_RELOAD_ATTEMPT: 159 { 160 minPlaylistAgeUs = (targetDurationUs * 3) / 2; 161 break; 162 } 163 164 case THIRD_UNCHANGED_RELOAD_ATTEMPT: 165 { 166 minPlaylistAgeUs = targetDurationUs * 3; 167 break; 168 } 169 170 default: 171 TRESPASS(); 172 break; 173 } 174 175 int64_t delayUs = mLastPlaylistFetchTimeUs + minPlaylistAgeUs - nowUs; 176 return delayUs > 0ll ? delayUs : 0ll; 177} 178 179status_t PlaylistFetcher::decryptBuffer( 180 size_t playlistIndex, const sp<ABuffer> &buffer, 181 bool first) { 182 sp<AMessage> itemMeta; 183 bool found = false; 184 AString method; 185 186 for (ssize_t i = playlistIndex; i >= 0; --i) { 187 AString uri; 188 CHECK(mPlaylist->itemAt(i, &uri, &itemMeta)); 189 190 if (itemMeta->findString("cipher-method", &method)) { 191 found = true; 192 break; 193 } 194 } 195 196 if (!found) { 197 method = "NONE"; 198 } 199 buffer->meta()->setString("cipher-method", method.c_str()); 200 201 if (method == "NONE") { 202 return OK; 203 } else if (!(method == "AES-128")) { 204 ALOGE("Unsupported cipher method '%s'", method.c_str()); 205 return ERROR_UNSUPPORTED; 206 } 207 208 AString keyURI; 209 if (!itemMeta->findString("cipher-uri", &keyURI)) { 210 ALOGE("Missing key uri"); 211 return ERROR_MALFORMED; 212 } 213 214 ssize_t index = mAESKeyForURI.indexOfKey(keyURI); 215 216 sp<ABuffer> key; 217 if (index >= 0) { 218 key = mAESKeyForURI.valueAt(index); 219 } else { 220 ssize_t err = mSession->fetchFile(keyURI.c_str(), &key); 221 222 if (err < 0) { 223 ALOGE("failed to fetch cipher key from '%s'.", keyURI.c_str()); 224 return ERROR_IO; 225 } else if (key->size() != 16) { 226 ALOGE("key file '%s' wasn't 16 bytes in size.", keyURI.c_str()); 227 return ERROR_MALFORMED; 228 } 229 230 mAESKeyForURI.add(keyURI, key); 231 } 232 233 AES_KEY aes_key; 234 if (AES_set_decrypt_key(key->data(), 128, &aes_key) != 0) { 235 ALOGE("failed to set AES decryption key."); 236 return UNKNOWN_ERROR; 237 } 238 239 size_t n = buffer->size(); 240 if (!n) { 241 return OK; 242 } 243 CHECK(n % 16 == 0); 244 245 if (first) { 246 // If decrypting the first block in a file, read the iv from the manifest 247 // or derive the iv from the file's sequence number. 248 249 AString iv; 250 if (itemMeta->findString("cipher-iv", &iv)) { 251 if ((!iv.startsWith("0x") && !iv.startsWith("0X")) 252 || iv.size() != 16 * 2 + 2) { 253 ALOGE("malformed cipher IV '%s'.", iv.c_str()); 254 return ERROR_MALFORMED; 255 } 256 257 memset(mAESInitVec, 0, sizeof(mAESInitVec)); 258 for (size_t i = 0; i < 16; ++i) { 259 char c1 = tolower(iv.c_str()[2 + 2 * i]); 260 char c2 = tolower(iv.c_str()[3 + 2 * i]); 261 if (!isxdigit(c1) || !isxdigit(c2)) { 262 ALOGE("malformed cipher IV '%s'.", iv.c_str()); 263 return ERROR_MALFORMED; 264 } 265 uint8_t nibble1 = isdigit(c1) ? c1 - '0' : c1 - 'a' + 10; 266 uint8_t nibble2 = isdigit(c2) ? c2 - '0' : c2 - 'a' + 10; 267 268 mAESInitVec[i] = nibble1 << 4 | nibble2; 269 } 270 } else { 271 memset(mAESInitVec, 0, sizeof(mAESInitVec)); 272 mAESInitVec[15] = mSeqNumber & 0xff; 273 mAESInitVec[14] = (mSeqNumber >> 8) & 0xff; 274 mAESInitVec[13] = (mSeqNumber >> 16) & 0xff; 275 mAESInitVec[12] = (mSeqNumber >> 24) & 0xff; 276 } 277 } 278 279 AES_cbc_encrypt( 280 buffer->data(), buffer->data(), buffer->size(), 281 &aes_key, mAESInitVec, AES_DECRYPT); 282 283 return OK; 284} 285 286status_t PlaylistFetcher::checkDecryptPadding(const sp<ABuffer> &buffer) { 287 status_t err; 288 AString method; 289 CHECK(buffer->meta()->findString("cipher-method", &method)); 290 if (method == "NONE") { 291 return OK; 292 } 293 294 uint8_t padding = 0; 295 if (buffer->size() > 0) { 296 padding = buffer->data()[buffer->size() - 1]; 297 } 298 299 if (padding > 16) { 300 return ERROR_MALFORMED; 301 } 302 303 for (size_t i = buffer->size() - padding; i < padding; i++) { 304 if (buffer->data()[i] != padding) { 305 return ERROR_MALFORMED; 306 } 307 } 308 309 buffer->setRange(buffer->offset(), buffer->size() - padding); 310 return OK; 311} 312 313void PlaylistFetcher::postMonitorQueue(int64_t delayUs, int64_t minDelayUs) { 314 int64_t maxDelayUs = delayUsToRefreshPlaylist(); 315 if (maxDelayUs < minDelayUs) { 316 maxDelayUs = minDelayUs; 317 } 318 if (delayUs > maxDelayUs) { 319 ALOGV("Need to refresh playlist in %lld", maxDelayUs); 320 delayUs = maxDelayUs; 321 } 322 sp<AMessage> msg = new AMessage(kWhatMonitorQueue, id()); 323 msg->setInt32("generation", mMonitorQueueGeneration); 324 msg->post(delayUs); 325} 326 327void PlaylistFetcher::cancelMonitorQueue() { 328 ++mMonitorQueueGeneration; 329} 330 331void PlaylistFetcher::startAsync( 332 const sp<AnotherPacketSource> &audioSource, 333 const sp<AnotherPacketSource> &videoSource, 334 const sp<AnotherPacketSource> &subtitleSource, 335 int64_t startTimeUs, 336 int64_t minStartTimeUs, 337 int32_t startSeqNumberHint) { 338 sp<AMessage> msg = new AMessage(kWhatStart, id()); 339 340 uint32_t streamTypeMask = 0ul; 341 342 if (audioSource != NULL) { 343 msg->setPointer("audioSource", audioSource.get()); 344 streamTypeMask |= LiveSession::STREAMTYPE_AUDIO; 345 } 346 347 if (videoSource != NULL) { 348 msg->setPointer("videoSource", videoSource.get()); 349 streamTypeMask |= LiveSession::STREAMTYPE_VIDEO; 350 } 351 352 if (subtitleSource != NULL) { 353 msg->setPointer("subtitleSource", subtitleSource.get()); 354 streamTypeMask |= LiveSession::STREAMTYPE_SUBTITLES; 355 } 356 357 msg->setInt32("streamTypeMask", streamTypeMask); 358 msg->setInt64("startTimeUs", startTimeUs); 359 msg->setInt64("minStartTimeUs", minStartTimeUs); 360 msg->setInt32("startSeqNumberHint", startSeqNumberHint); 361 msg->post(); 362} 363 364void PlaylistFetcher::pauseAsync() { 365 (new AMessage(kWhatPause, id()))->post(); 366} 367 368void PlaylistFetcher::stopAsync(bool selfTriggered) { 369 sp<AMessage> msg = new AMessage(kWhatStop, id()); 370 msg->setInt32("selfTriggered", selfTriggered); 371 msg->post(); 372} 373 374void PlaylistFetcher::resumeUntilAsync(const sp<AMessage> ¶ms) { 375 AMessage* msg = new AMessage(kWhatResumeUntil, id()); 376 msg->setMessage("params", params); 377 msg->post(); 378} 379 380void PlaylistFetcher::onMessageReceived(const sp<AMessage> &msg) { 381 switch (msg->what()) { 382 case kWhatStart: 383 { 384 status_t err = onStart(msg); 385 386 sp<AMessage> notify = mNotify->dup(); 387 notify->setInt32("what", kWhatStarted); 388 notify->setInt32("err", err); 389 notify->post(); 390 break; 391 } 392 393 case kWhatPause: 394 { 395 onPause(); 396 397 sp<AMessage> notify = mNotify->dup(); 398 notify->setInt32("what", kWhatPaused); 399 notify->post(); 400 break; 401 } 402 403 case kWhatStop: 404 { 405 onStop(msg); 406 407 sp<AMessage> notify = mNotify->dup(); 408 notify->setInt32("what", kWhatStopped); 409 notify->post(); 410 break; 411 } 412 413 case kWhatMonitorQueue: 414 case kWhatDownloadNext: 415 { 416 int32_t generation; 417 CHECK(msg->findInt32("generation", &generation)); 418 419 if (generation != mMonitorQueueGeneration) { 420 // Stale event 421 break; 422 } 423 424 if (msg->what() == kWhatMonitorQueue) { 425 onMonitorQueue(); 426 } else { 427 onDownloadNext(); 428 } 429 break; 430 } 431 432 case kWhatResumeUntil: 433 { 434 onResumeUntil(msg); 435 break; 436 } 437 438 default: 439 TRESPASS(); 440 } 441} 442 443status_t PlaylistFetcher::onStart(const sp<AMessage> &msg) { 444 mPacketSources.clear(); 445 446 uint32_t streamTypeMask; 447 CHECK(msg->findInt32("streamTypeMask", (int32_t *)&streamTypeMask)); 448 449 int64_t startTimeUs; 450 int32_t startSeqNumberHint; 451 CHECK(msg->findInt64("startTimeUs", &startTimeUs)); 452 CHECK(msg->findInt64("minStartTimeUs", (int64_t *) &mMinStartTimeUs)); 453 CHECK(msg->findInt32("startSeqNumberHint", &startSeqNumberHint)); 454 455 if (streamTypeMask & LiveSession::STREAMTYPE_AUDIO) { 456 void *ptr; 457 CHECK(msg->findPointer("audioSource", &ptr)); 458 459 mPacketSources.add( 460 LiveSession::STREAMTYPE_AUDIO, 461 static_cast<AnotherPacketSource *>(ptr)); 462 } 463 464 if (streamTypeMask & LiveSession::STREAMTYPE_VIDEO) { 465 void *ptr; 466 CHECK(msg->findPointer("videoSource", &ptr)); 467 468 mPacketSources.add( 469 LiveSession::STREAMTYPE_VIDEO, 470 static_cast<AnotherPacketSource *>(ptr)); 471 } 472 473 if (streamTypeMask & LiveSession::STREAMTYPE_SUBTITLES) { 474 void *ptr; 475 CHECK(msg->findPointer("subtitleSource", &ptr)); 476 477 mPacketSources.add( 478 LiveSession::STREAMTYPE_SUBTITLES, 479 static_cast<AnotherPacketSource *>(ptr)); 480 } 481 482 mStreamTypeMask = streamTypeMask; 483 mStartTimeUs = startTimeUs; 484 485 if (mStartTimeUs >= 0ll) { 486 mSeqNumber = -1; 487 mStartup = true; 488 mPrepared = false; 489 } 490 491 if (startSeqNumberHint >= 0) { 492 mSeqNumber = startSeqNumberHint; 493 } 494 495 postMonitorQueue(); 496 497 return OK; 498} 499 500void PlaylistFetcher::onPause() { 501 cancelMonitorQueue(); 502} 503 504void PlaylistFetcher::onStop(const sp<AMessage> &msg) { 505 cancelMonitorQueue(); 506 507 int32_t selfTriggered; 508 CHECK(msg->findInt32("selfTriggered", &selfTriggered)); 509 if (!selfTriggered) { 510 // Self triggered stops only happen during switching, in which case we do not want 511 // to clear the discontinuities queued at the end of packet sources. 512 for (size_t i = 0; i < mPacketSources.size(); i++) { 513 sp<AnotherPacketSource> packetSource = mPacketSources.valueAt(i); 514 packetSource->clear(); 515 } 516 } 517 518 mPacketSources.clear(); 519 mStreamTypeMask = 0; 520} 521 522// Resume until we have reached the boundary timestamps listed in `msg`; when 523// the remaining time is too short (within a resume threshold) stop immediately 524// instead. 525status_t PlaylistFetcher::onResumeUntil(const sp<AMessage> &msg) { 526 sp<AMessage> params; 527 CHECK(msg->findMessage("params", ¶ms)); 528 529 bool stop = false; 530 for (size_t i = 0; i < mPacketSources.size(); i++) { 531 sp<AnotherPacketSource> packetSource = mPacketSources.valueAt(i); 532 533 const char *stopKey; 534 int streamType = mPacketSources.keyAt(i); 535 switch (streamType) { 536 case LiveSession::STREAMTYPE_VIDEO: 537 stopKey = "timeUsVideo"; 538 break; 539 540 case LiveSession::STREAMTYPE_AUDIO: 541 stopKey = "timeUsAudio"; 542 break; 543 544 case LiveSession::STREAMTYPE_SUBTITLES: 545 stopKey = "timeUsSubtitle"; 546 break; 547 548 default: 549 TRESPASS(); 550 } 551 552 // Don't resume if we would stop within a resume threshold. 553 int64_t latestTimeUs = 0, stopTimeUs = 0; 554 sp<AMessage> latestMeta = packetSource->getLatestMeta(); 555 if (latestMeta != NULL 556 && (latestMeta->findInt64("timeUs", &latestTimeUs) 557 && params->findInt64(stopKey, &stopTimeUs))) { 558 int64_t diffUs = stopTimeUs - latestTimeUs; 559 if (diffUs < resumeThreshold(latestMeta)) { 560 stop = true; 561 } 562 } 563 } 564 565 if (stop) { 566 for (size_t i = 0; i < mPacketSources.size(); i++) { 567 mPacketSources.valueAt(i)->queueAccessUnit(mSession->createFormatChangeBuffer()); 568 } 569 stopAsync(/* selfTriggered = */ true); 570 return OK; 571 } 572 573 mStopParams = params; 574 postMonitorQueue(); 575 576 return OK; 577} 578 579void PlaylistFetcher::notifyError(status_t err) { 580 sp<AMessage> notify = mNotify->dup(); 581 notify->setInt32("what", kWhatError); 582 notify->setInt32("err", err); 583 notify->post(); 584} 585 586void PlaylistFetcher::queueDiscontinuity( 587 ATSParser::DiscontinuityType type, const sp<AMessage> &extra) { 588 for (size_t i = 0; i < mPacketSources.size(); ++i) { 589 mPacketSources.valueAt(i)->queueDiscontinuity(type, extra); 590 } 591} 592 593void PlaylistFetcher::onMonitorQueue() { 594 bool downloadMore = false; 595 refreshPlaylist(); 596 597 int32_t targetDurationSecs; 598 int64_t targetDurationUs = kMinBufferedDurationUs; 599 if (mPlaylist != NULL) { 600 CHECK(mPlaylist->meta()->findInt32("target-duration", &targetDurationSecs)); 601 targetDurationUs = targetDurationSecs * 1000000ll; 602 } 603 604 // buffer at least 3 times the target duration, or up to 10 seconds 605 int64_t durationToBufferUs = targetDurationUs * 3; 606 if (durationToBufferUs > kMinBufferedDurationUs) { 607 durationToBufferUs = kMinBufferedDurationUs; 608 } 609 610 int64_t bufferedDurationUs = 0ll; 611 status_t finalResult = NOT_ENOUGH_DATA; 612 if (mStreamTypeMask == LiveSession::STREAMTYPE_SUBTITLES) { 613 sp<AnotherPacketSource> packetSource = 614 mPacketSources.valueFor(LiveSession::STREAMTYPE_SUBTITLES); 615 616 bufferedDurationUs = 617 packetSource->getBufferedDurationUs(&finalResult); 618 finalResult = OK; 619 } else { 620 // Use max stream duration to prevent us from waiting on a non-existent stream; 621 // when we cannot make out from the manifest what streams are included in a playlist 622 // we might assume extra streams. 623 for (size_t i = 0; i < mPacketSources.size(); ++i) { 624 if ((mStreamTypeMask & mPacketSources.keyAt(i)) == 0) { 625 continue; 626 } 627 628 int64_t bufferedStreamDurationUs = 629 mPacketSources.valueAt(i)->getBufferedDurationUs(&finalResult); 630 ALOGV("buffered %lld for stream %d", 631 bufferedStreamDurationUs, mPacketSources.keyAt(i)); 632 if (bufferedStreamDurationUs > bufferedDurationUs) { 633 bufferedDurationUs = bufferedStreamDurationUs; 634 } 635 } 636 } 637 downloadMore = (bufferedDurationUs < durationToBufferUs); 638 639 // signal start if buffered up at least the target size 640 if (!mPrepared && bufferedDurationUs > targetDurationUs && downloadMore) { 641 mPrepared = true; 642 643 ALOGV("prepared, buffered=%lld > %lld", 644 bufferedDurationUs, targetDurationUs); 645 sp<AMessage> msg = mNotify->dup(); 646 msg->setInt32("what", kWhatTemporarilyDoneFetching); 647 msg->post(); 648 } 649 650 if (finalResult == OK && downloadMore) { 651 ALOGV("monitoring, buffered=%lld < %lld", 652 bufferedDurationUs, durationToBufferUs); 653 // delay the next download slightly; hopefully this gives other concurrent fetchers 654 // a better chance to run. 655 // onDownloadNext(); 656 sp<AMessage> msg = new AMessage(kWhatDownloadNext, id()); 657 msg->setInt32("generation", mMonitorQueueGeneration); 658 msg->post(1000l); 659 } else { 660 // Nothing to do yet, try again in a second. 661 662 sp<AMessage> msg = mNotify->dup(); 663 msg->setInt32("what", kWhatTemporarilyDoneFetching); 664 msg->post(); 665 666 int64_t delayUs = mPrepared ? kMaxMonitorDelayUs : targetDurationUs / 2; 667 ALOGV("pausing for %lld, buffered=%lld > %lld", 668 delayUs, bufferedDurationUs, durationToBufferUs); 669 // :TRICKY: need to enforce minimum delay because the delay to 670 // refresh the playlist will become 0 671 postMonitorQueue(delayUs, mPrepared ? targetDurationUs * 2 : 0); 672 } 673} 674 675status_t PlaylistFetcher::refreshPlaylist() { 676 if (delayUsToRefreshPlaylist() <= 0) { 677 bool unchanged; 678 sp<M3UParser> playlist = mSession->fetchPlaylist( 679 mURI.c_str(), mPlaylistHash, &unchanged); 680 681 if (playlist == NULL) { 682 if (unchanged) { 683 // We succeeded in fetching the playlist, but it was 684 // unchanged from the last time we tried. 685 686 if (mRefreshState != THIRD_UNCHANGED_RELOAD_ATTEMPT) { 687 mRefreshState = (RefreshState)(mRefreshState + 1); 688 } 689 } else { 690 ALOGE("failed to load playlist at url '%s'", mURI.c_str()); 691 notifyError(ERROR_IO); 692 return ERROR_IO; 693 } 694 } else { 695 mRefreshState = INITIAL_MINIMUM_RELOAD_DELAY; 696 mPlaylist = playlist; 697 698 if (mPlaylist->isComplete() || mPlaylist->isEvent()) { 699 updateDuration(); 700 } 701 } 702 703 mLastPlaylistFetchTimeUs = ALooper::GetNowUs(); 704 } 705 return OK; 706} 707 708// static 709bool PlaylistFetcher::bufferStartsWithTsSyncByte(const sp<ABuffer>& buffer) { 710 return buffer->size() > 0 && buffer->data()[0] == 0x47; 711} 712 713void PlaylistFetcher::onDownloadNext() { 714 if (refreshPlaylist() != OK) { 715 return; 716 } 717 718 int32_t firstSeqNumberInPlaylist; 719 if (mPlaylist->meta() == NULL || !mPlaylist->meta()->findInt32( 720 "media-sequence", &firstSeqNumberInPlaylist)) { 721 firstSeqNumberInPlaylist = 0; 722 } 723 724 bool seekDiscontinuity = false; 725 bool explicitDiscontinuity = false; 726 727 const int32_t lastSeqNumberInPlaylist = 728 firstSeqNumberInPlaylist + (int32_t)mPlaylist->size() - 1; 729 730 if (mStartup && mSeqNumber >= 0 731 && (mSeqNumber < firstSeqNumberInPlaylist || mSeqNumber > lastSeqNumberInPlaylist)) { 732 // in case we guessed wrong during reconfiguration, try fetching the latest content. 733 mSeqNumber = lastSeqNumberInPlaylist; 734 } 735 736 if (mSeqNumber < 0) { 737 CHECK_GE(mStartTimeUs, 0ll); 738 739 if (mPlaylist->isComplete() || mPlaylist->isEvent()) { 740 mSeqNumber = getSeqNumberForTime(mStartTimeUs); 741 ALOGV("Initial sequence number for time %lld is %d from (%d .. %d)", 742 mStartTimeUs, mSeqNumber, firstSeqNumberInPlaylist, 743 lastSeqNumberInPlaylist); 744 } else { 745 // If this is a live session, start 3 segments from the end. 746 mSeqNumber = lastSeqNumberInPlaylist - 3; 747 if (mSeqNumber < firstSeqNumberInPlaylist) { 748 mSeqNumber = firstSeqNumberInPlaylist; 749 } 750 ALOGV("Initial sequence number for live event %d from (%d .. %d)", 751 mSeqNumber, firstSeqNumberInPlaylist, 752 lastSeqNumberInPlaylist); 753 } 754 755 mStartTimeUs = -1ll; 756 } 757 758 if (mSeqNumber < firstSeqNumberInPlaylist 759 || mSeqNumber > lastSeqNumberInPlaylist) { 760 if (!mPlaylist->isComplete() && mNumRetries < kMaxNumRetries) { 761 ++mNumRetries; 762 763 if (mSeqNumber > lastSeqNumberInPlaylist) { 764 // refresh in increasing fraction (1/2, 1/3, ...) of the 765 // playlist's target duration or 3 seconds, whichever is less 766 int32_t targetDurationSecs; 767 CHECK(mPlaylist->meta()->findInt32( 768 "target-duration", &targetDurationSecs)); 769 int64_t delayUs = mPlaylist->size() * targetDurationSecs * 770 1000000ll / (1 + mNumRetries); 771 if (delayUs > kMaxMonitorDelayUs) { 772 delayUs = kMaxMonitorDelayUs; 773 } 774 ALOGV("sequence number high: %d from (%d .. %d), " 775 "monitor in %lld (retry=%d)", 776 mSeqNumber, firstSeqNumberInPlaylist, 777 lastSeqNumberInPlaylist, delayUs, mNumRetries); 778 postMonitorQueue(delayUs); 779 return; 780 } 781 782 // we've missed the boat, let's start from the lowest sequence 783 // number available and signal a discontinuity. 784 785 ALOGI("We've missed the boat, restarting playback." 786 " mStartup=%d, was looking for %d in %d-%d", 787 mStartup, mSeqNumber, firstSeqNumberInPlaylist, 788 lastSeqNumberInPlaylist); 789 mSeqNumber = lastSeqNumberInPlaylist - 3; 790 if (mSeqNumber < firstSeqNumberInPlaylist) { 791 mSeqNumber = firstSeqNumberInPlaylist; 792 } 793 explicitDiscontinuity = true; 794 795 // fall through 796 } else { 797 ALOGE("Cannot find sequence number %d in playlist " 798 "(contains %d - %d)", 799 mSeqNumber, firstSeqNumberInPlaylist, 800 firstSeqNumberInPlaylist + mPlaylist->size() - 1); 801 802 notifyError(ERROR_END_OF_STREAM); 803 return; 804 } 805 } 806 807 mNumRetries = 0; 808 809 AString uri; 810 sp<AMessage> itemMeta; 811 CHECK(mPlaylist->itemAt( 812 mSeqNumber - firstSeqNumberInPlaylist, 813 &uri, 814 &itemMeta)); 815 816 int32_t val; 817 if (itemMeta->findInt32("discontinuity", &val) && val != 0) { 818 explicitDiscontinuity = true; 819 } 820 821 int64_t range_offset, range_length; 822 if (!itemMeta->findInt64("range-offset", &range_offset) 823 || !itemMeta->findInt64("range-length", &range_length)) { 824 range_offset = 0; 825 range_length = -1; 826 } 827 828 ALOGV("fetching segment %d from (%d .. %d)", 829 mSeqNumber, firstSeqNumberInPlaylist, lastSeqNumberInPlaylist); 830 831 ALOGV("fetching '%s'", uri.c_str()); 832 833 sp<DataSource> source; 834 sp<ABuffer> buffer, tsBuffer; 835 // decrypt a junk buffer to prefetch key; since a session uses only one http connection, 836 // this avoids interleaved connections to the key and segment file. 837 { 838 sp<ABuffer> junk = new ABuffer(16); 839 junk->setRange(0, 16); 840 status_t err = decryptBuffer(mSeqNumber - firstSeqNumberInPlaylist, junk, 841 true /* first */); 842 if (err != OK) { 843 notifyError(err); 844 return; 845 } 846 } 847 848 // block-wise download 849 ssize_t bytesRead; 850 do { 851 bytesRead = mSession->fetchFile( 852 uri.c_str(), &buffer, range_offset, range_length, kDownloadBlockSize, &source); 853 854 if (bytesRead < 0) { 855 status_t err = bytesRead; 856 ALOGE("failed to fetch .ts segment at url '%s'", uri.c_str()); 857 notifyError(err); 858 return; 859 } 860 861 CHECK(buffer != NULL); 862 863 size_t size = buffer->size(); 864 // Set decryption range. 865 buffer->setRange(size - bytesRead, bytesRead); 866 status_t err = decryptBuffer(mSeqNumber - firstSeqNumberInPlaylist, buffer, 867 buffer->offset() == 0 /* first */); 868 // Unset decryption range. 869 buffer->setRange(0, size); 870 871 if (err != OK) { 872 ALOGE("decryptBuffer failed w/ error %d", err); 873 874 notifyError(err); 875 return; 876 } 877 878 if (mStartup || seekDiscontinuity || explicitDiscontinuity) { 879 // Signal discontinuity. 880 881 if (mPlaylist->isComplete() || mPlaylist->isEvent()) { 882 // If this was a live event this made no sense since 883 // we don't have access to all the segment before the current 884 // one. 885 mNextPTSTimeUs = getSegmentStartTimeUs(mSeqNumber); 886 } 887 888 if (seekDiscontinuity || explicitDiscontinuity) { 889 ALOGI("queueing discontinuity (seek=%d, explicit=%d)", 890 seekDiscontinuity, explicitDiscontinuity); 891 892 queueDiscontinuity( 893 explicitDiscontinuity 894 ? ATSParser::DISCONTINUITY_FORMATCHANGE 895 : ATSParser::DISCONTINUITY_SEEK, 896 NULL /* extra */); 897 } 898 } 899 900 err = OK; 901 if (bufferStartsWithTsSyncByte(buffer)) { 902 // Incremental extraction is only supported for MPEG2 transport streams. 903 if (tsBuffer == NULL) { 904 tsBuffer = new ABuffer(buffer->data(), buffer->capacity()); 905 tsBuffer->setRange(0, 0); 906 } else if (tsBuffer->capacity() != buffer->capacity()) { 907 size_t tsOff = tsBuffer->offset(), tsSize = tsBuffer->size(); 908 tsBuffer = new ABuffer(buffer->data(), buffer->capacity()); 909 tsBuffer->setRange(tsOff, tsSize); 910 } 911 tsBuffer->setRange(tsBuffer->offset(), tsBuffer->size() + bytesRead); 912 913 err = extractAndQueueAccessUnitsFromTs(tsBuffer); 914 } 915 916 if (err == -EAGAIN) { 917 // bad starting sequence number hint 918 postMonitorQueue(); 919 return; 920 } 921 922 if (err == ERROR_OUT_OF_RANGE) { 923 // reached stopping point 924 stopAsync(/* selfTriggered = */ true); 925 return; 926 } 927 928 if (err != OK) { 929 notifyError(err); 930 return; 931 } 932 933 mStartup = false; 934 } while (bytesRead != 0); 935 936 if (bufferStartsWithTsSyncByte(buffer)) { 937 // If we still don't see a stream after fetching a full ts segment mark it as 938 // nonexistent. 939 const size_t kNumTypes = ATSParser::NUM_SOURCE_TYPES; 940 ATSParser::SourceType srcTypes[kNumTypes] = 941 { ATSParser::VIDEO, ATSParser::AUDIO }; 942 LiveSession::StreamType streamTypes[kNumTypes] = 943 { LiveSession::STREAMTYPE_VIDEO, LiveSession::STREAMTYPE_AUDIO }; 944 945 for (size_t i = 0; i < kNumTypes; i++) { 946 ATSParser::SourceType srcType = srcTypes[i]; 947 LiveSession::StreamType streamType = streamTypes[i]; 948 949 sp<AnotherPacketSource> source = 950 static_cast<AnotherPacketSource *>( 951 mTSParser->getSource(srcType).get()); 952 953 if (source == NULL) { 954 ALOGW("MPEG2 Transport stream does not contain %s data.", 955 srcType == ATSParser::VIDEO ? "video" : "audio"); 956 957 mStreamTypeMask &= ~streamType; 958 mPacketSources.removeItem(streamType); 959 } 960 } 961 962 } 963 964 if (checkDecryptPadding(buffer) != OK) { 965 ALOGE("Incorrect padding bytes after decryption."); 966 notifyError(ERROR_MALFORMED); 967 return; 968 } 969 970 status_t err = OK; 971 if (tsBuffer != NULL) { 972 AString method; 973 CHECK(buffer->meta()->findString("cipher-method", &method)); 974 if ((tsBuffer->size() > 0 && method == "NONE") 975 || tsBuffer->size() > 16) { 976 ALOGE("MPEG2 transport stream is not an even multiple of 188 " 977 "bytes in length."); 978 notifyError(ERROR_MALFORMED); 979 return; 980 } 981 } 982 983 // bulk extract non-ts files 984 if (tsBuffer == NULL) { 985 err = extractAndQueueAccessUnits(buffer, itemMeta); 986 } 987 988 if (err != OK) { 989 notifyError(err); 990 return; 991 } 992 993 ++mSeqNumber; 994 995 postMonitorQueue(); 996} 997 998int32_t PlaylistFetcher::getSeqNumberForTime(int64_t timeUs) const { 999 int32_t firstSeqNumberInPlaylist; 1000 if (mPlaylist->meta() == NULL || !mPlaylist->meta()->findInt32( 1001 "media-sequence", &firstSeqNumberInPlaylist)) { 1002 firstSeqNumberInPlaylist = 0; 1003 } 1004 1005 size_t index = 0; 1006 int64_t segmentStartUs = 0; 1007 while (index < mPlaylist->size()) { 1008 sp<AMessage> itemMeta; 1009 CHECK(mPlaylist->itemAt( 1010 index, NULL /* uri */, &itemMeta)); 1011 1012 int64_t itemDurationUs; 1013 CHECK(itemMeta->findInt64("durationUs", &itemDurationUs)); 1014 1015 if (timeUs < segmentStartUs + itemDurationUs) { 1016 break; 1017 } 1018 1019 segmentStartUs += itemDurationUs; 1020 ++index; 1021 } 1022 1023 if (index >= mPlaylist->size()) { 1024 index = mPlaylist->size() - 1; 1025 } 1026 1027 return firstSeqNumberInPlaylist + index; 1028} 1029 1030status_t PlaylistFetcher::extractAndQueueAccessUnitsFromTs(const sp<ABuffer> &buffer) { 1031 if (mTSParser == NULL) { 1032 // Use TS_TIMESTAMPS_ARE_ABSOLUTE so pts carry over between fetchers. 1033 mTSParser = new ATSParser(ATSParser::TS_TIMESTAMPS_ARE_ABSOLUTE); 1034 } 1035 1036 if (mNextPTSTimeUs >= 0ll) { 1037 sp<AMessage> extra = new AMessage; 1038 // Since we are using absolute timestamps, signal an offset of 0 to prevent 1039 // ATSParser from skewing the timestamps of access units. 1040 extra->setInt64(IStreamListener::kKeyMediaTimeUs, 0); 1041 1042 mTSParser->signalDiscontinuity( 1043 ATSParser::DISCONTINUITY_SEEK, extra); 1044 1045 mNextPTSTimeUs = -1ll; 1046 } 1047 1048 size_t offset = 0; 1049 while (offset + 188 <= buffer->size()) { 1050 status_t err = mTSParser->feedTSPacket(buffer->data() + offset, 188); 1051 1052 if (err != OK) { 1053 return err; 1054 } 1055 1056 offset += 188; 1057 } 1058 // setRange to indicate consumed bytes. 1059 buffer->setRange(buffer->offset() + offset, buffer->size() - offset); 1060 1061 status_t err = OK; 1062 for (size_t i = mPacketSources.size(); i-- > 0;) { 1063 sp<AnotherPacketSource> packetSource = mPacketSources.valueAt(i); 1064 1065 const char *key; 1066 ATSParser::SourceType type; 1067 const LiveSession::StreamType stream = mPacketSources.keyAt(i); 1068 switch (stream) { 1069 case LiveSession::STREAMTYPE_VIDEO: 1070 type = ATSParser::VIDEO; 1071 key = "timeUsVideo"; 1072 break; 1073 1074 case LiveSession::STREAMTYPE_AUDIO: 1075 type = ATSParser::AUDIO; 1076 key = "timeUsAudio"; 1077 break; 1078 1079 case LiveSession::STREAMTYPE_SUBTITLES: 1080 { 1081 ALOGE("MPEG2 Transport streams do not contain subtitles."); 1082 return ERROR_MALFORMED; 1083 break; 1084 } 1085 1086 default: 1087 TRESPASS(); 1088 } 1089 1090 sp<AnotherPacketSource> source = 1091 static_cast<AnotherPacketSource *>( 1092 mTSParser->getSource(type).get()); 1093 1094 if (source == NULL) { 1095 continue; 1096 } 1097 1098 int64_t timeUs; 1099 sp<ABuffer> accessUnit; 1100 status_t finalResult; 1101 while (source->hasBufferAvailable(&finalResult) 1102 && source->dequeueAccessUnit(&accessUnit) == OK) { 1103 1104 CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs)); 1105 if (mMinStartTimeUs > 0) { 1106 if (timeUs < mMinStartTimeUs) { 1107 // TODO untested path 1108 // try a later ts 1109 int32_t targetDuration; 1110 mPlaylist->meta()->findInt32("target-duration", &targetDuration); 1111 int32_t incr = (mMinStartTimeUs - timeUs) / 1000000 / targetDuration; 1112 if (incr == 0) { 1113 // increment mSeqNumber by at least one 1114 incr = 1; 1115 } 1116 mSeqNumber += incr; 1117 err = -EAGAIN; 1118 break; 1119 } else { 1120 int64_t startTimeUs; 1121 if (mStartTimeUsNotify != NULL 1122 && !mStartTimeUsNotify->findInt64(key, &startTimeUs)) { 1123 mStartTimeUsNotify->setInt64(key, timeUs); 1124 1125 uint32_t streamMask = 0; 1126 mStartTimeUsNotify->findInt32("streamMask", (int32_t *) &streamMask); 1127 streamMask |= mPacketSources.keyAt(i); 1128 mStartTimeUsNotify->setInt32("streamMask", streamMask); 1129 1130 if (streamMask == mStreamTypeMask) { 1131 mStartTimeUsNotify->post(); 1132 mStartTimeUsNotify.clear(); 1133 } 1134 } 1135 } 1136 } 1137 1138 if (mStopParams != NULL) { 1139 // Queue discontinuity in original stream. 1140 int64_t stopTimeUs; 1141 if (!mStopParams->findInt64(key, &stopTimeUs) || timeUs >= stopTimeUs) { 1142 packetSource->queueAccessUnit(mSession->createFormatChangeBuffer()); 1143 mStreamTypeMask &= ~stream; 1144 mPacketSources.removeItemsAt(i); 1145 break; 1146 } 1147 } 1148 1149 // Note that we do NOT dequeue any discontinuities except for format change. 1150 1151 // for simplicity, store a reference to the format in each unit 1152 sp<MetaData> format = source->getFormat(); 1153 if (format != NULL) { 1154 accessUnit->meta()->setObject("format", format); 1155 } 1156 1157 // Stash the sequence number so we can hint future playlist where to start at. 1158 accessUnit->meta()->setInt32("seq", mSeqNumber); 1159 packetSource->queueAccessUnit(accessUnit); 1160 } 1161 1162 if (err != OK) { 1163 break; 1164 } 1165 } 1166 1167 if (err != OK) { 1168 for (size_t i = mPacketSources.size(); i-- > 0;) { 1169 sp<AnotherPacketSource> packetSource = mPacketSources.valueAt(i); 1170 packetSource->clear(); 1171 } 1172 return err; 1173 } 1174 1175 if (!mStreamTypeMask) { 1176 // Signal gap is filled between original and new stream. 1177 ALOGV("ERROR OUT OF RANGE"); 1178 return ERROR_OUT_OF_RANGE; 1179 } 1180 1181 return OK; 1182} 1183 1184status_t PlaylistFetcher::extractAndQueueAccessUnits( 1185 const sp<ABuffer> &buffer, const sp<AMessage> &itemMeta) { 1186 if (buffer->size() >= 7 && !memcmp("WEBVTT\n", buffer->data(), 7)) { 1187 if (mStreamTypeMask != LiveSession::STREAMTYPE_SUBTITLES) { 1188 ALOGE("This stream only contains subtitles."); 1189 return ERROR_MALFORMED; 1190 } 1191 1192 const sp<AnotherPacketSource> packetSource = 1193 mPacketSources.valueFor(LiveSession::STREAMTYPE_SUBTITLES); 1194 1195 int64_t durationUs; 1196 CHECK(itemMeta->findInt64("durationUs", &durationUs)); 1197 buffer->meta()->setInt64("timeUs", getSegmentStartTimeUs(mSeqNumber)); 1198 buffer->meta()->setInt64("durationUs", durationUs); 1199 buffer->meta()->setInt32("seq", mSeqNumber); 1200 1201 packetSource->queueAccessUnit(buffer); 1202 return OK; 1203 } 1204 1205 if (mNextPTSTimeUs >= 0ll) { 1206 mFirstPTSValid = false; 1207 mAbsoluteTimeAnchorUs = mNextPTSTimeUs; 1208 mNextPTSTimeUs = -1ll; 1209 } 1210 1211 // This better be an ISO 13818-7 (AAC) or ISO 13818-1 (MPEG) audio 1212 // stream prefixed by an ID3 tag. 1213 1214 bool firstID3Tag = true; 1215 uint64_t PTS = 0; 1216 1217 for (;;) { 1218 // Make sure to skip all ID3 tags preceding the audio data. 1219 // At least one must be present to provide the PTS timestamp. 1220 1221 ID3 id3(buffer->data(), buffer->size(), true /* ignoreV1 */); 1222 if (!id3.isValid()) { 1223 if (firstID3Tag) { 1224 ALOGE("Unable to parse ID3 tag."); 1225 return ERROR_MALFORMED; 1226 } else { 1227 break; 1228 } 1229 } 1230 1231 if (firstID3Tag) { 1232 bool found = false; 1233 1234 ID3::Iterator it(id3, "PRIV"); 1235 while (!it.done()) { 1236 size_t length; 1237 const uint8_t *data = it.getData(&length); 1238 1239 static const char *kMatchName = 1240 "com.apple.streaming.transportStreamTimestamp"; 1241 static const size_t kMatchNameLen = strlen(kMatchName); 1242 1243 if (length == kMatchNameLen + 1 + 8 1244 && !strncmp((const char *)data, kMatchName, kMatchNameLen)) { 1245 found = true; 1246 PTS = U64_AT(&data[kMatchNameLen + 1]); 1247 } 1248 1249 it.next(); 1250 } 1251 1252 if (!found) { 1253 ALOGE("Unable to extract transportStreamTimestamp from ID3 tag."); 1254 return ERROR_MALFORMED; 1255 } 1256 } 1257 1258 // skip the ID3 tag 1259 buffer->setRange( 1260 buffer->offset() + id3.rawSize(), buffer->size() - id3.rawSize()); 1261 1262 firstID3Tag = false; 1263 } 1264 1265 if (!mFirstPTSValid) { 1266 mFirstPTSValid = true; 1267 mFirstPTS = PTS; 1268 } 1269 PTS -= mFirstPTS; 1270 1271 int64_t timeUs = (PTS * 100ll) / 9ll + mAbsoluteTimeAnchorUs; 1272 1273 if (mStreamTypeMask != LiveSession::STREAMTYPE_AUDIO) { 1274 ALOGW("This stream only contains audio data!"); 1275 1276 mStreamTypeMask &= LiveSession::STREAMTYPE_AUDIO; 1277 1278 if (mStreamTypeMask == 0) { 1279 return OK; 1280 } 1281 } 1282 1283 sp<AnotherPacketSource> packetSource = 1284 mPacketSources.valueFor(LiveSession::STREAMTYPE_AUDIO); 1285 1286 if (packetSource->getFormat() == NULL && buffer->size() >= 7) { 1287 ABitReader bits(buffer->data(), buffer->size()); 1288 1289 // adts_fixed_header 1290 1291 CHECK_EQ(bits.getBits(12), 0xfffu); 1292 bits.skipBits(3); // ID, layer 1293 bool protection_absent = bits.getBits(1) != 0; 1294 1295 unsigned profile = bits.getBits(2); 1296 CHECK_NE(profile, 3u); 1297 unsigned sampling_freq_index = bits.getBits(4); 1298 bits.getBits(1); // private_bit 1299 unsigned channel_configuration = bits.getBits(3); 1300 CHECK_NE(channel_configuration, 0u); 1301 bits.skipBits(2); // original_copy, home 1302 1303 sp<MetaData> meta = MakeAACCodecSpecificData( 1304 profile, sampling_freq_index, channel_configuration); 1305 1306 meta->setInt32(kKeyIsADTS, true); 1307 1308 packetSource->setFormat(meta); 1309 } 1310 1311 int64_t numSamples = 0ll; 1312 int32_t sampleRate; 1313 CHECK(packetSource->getFormat()->findInt32(kKeySampleRate, &sampleRate)); 1314 1315 size_t offset = 0; 1316 while (offset < buffer->size()) { 1317 const uint8_t *adtsHeader = buffer->data() + offset; 1318 CHECK_LT(offset + 5, buffer->size()); 1319 1320 unsigned aac_frame_length = 1321 ((adtsHeader[3] & 3) << 11) 1322 | (adtsHeader[4] << 3) 1323 | (adtsHeader[5] >> 5); 1324 1325 if (aac_frame_length == 0) { 1326 const uint8_t *id3Header = adtsHeader; 1327 if (!memcmp(id3Header, "ID3", 3)) { 1328 ID3 id3(id3Header, buffer->size() - offset, true); 1329 if (id3.isValid()) { 1330 offset += id3.rawSize(); 1331 continue; 1332 }; 1333 } 1334 return ERROR_MALFORMED; 1335 } 1336 1337 CHECK_LE(offset + aac_frame_length, buffer->size()); 1338 1339 sp<ABuffer> unit = new ABuffer(aac_frame_length); 1340 memcpy(unit->data(), adtsHeader, aac_frame_length); 1341 1342 int64_t unitTimeUs = timeUs + numSamples * 1000000ll / sampleRate; 1343 unit->meta()->setInt64("timeUs", unitTimeUs); 1344 1345 // Each AAC frame encodes 1024 samples. 1346 numSamples += 1024; 1347 1348 unit->meta()->setInt32("seq", mSeqNumber); 1349 packetSource->queueAccessUnit(unit); 1350 1351 offset += aac_frame_length; 1352 } 1353 1354 return OK; 1355} 1356 1357void PlaylistFetcher::updateDuration() { 1358 int64_t durationUs = 0ll; 1359 for (size_t index = 0; index < mPlaylist->size(); ++index) { 1360 sp<AMessage> itemMeta; 1361 CHECK(mPlaylist->itemAt( 1362 index, NULL /* uri */, &itemMeta)); 1363 1364 int64_t itemDurationUs; 1365 CHECK(itemMeta->findInt64("durationUs", &itemDurationUs)); 1366 1367 durationUs += itemDurationUs; 1368 } 1369 1370 sp<AMessage> msg = mNotify->dup(); 1371 msg->setInt32("what", kWhatDurationUpdate); 1372 msg->setInt64("durationUs", durationUs); 1373 msg->post(); 1374} 1375 1376int64_t PlaylistFetcher::resumeThreshold(const sp<AMessage> &msg) { 1377 int64_t durationUs, threshold; 1378 if (msg->findInt64("durationUs", &durationUs)) { 1379 return kNumSkipFrames * durationUs; 1380 } 1381 1382 sp<RefBase> obj; 1383 msg->findObject("format", &obj); 1384 MetaData *format = static_cast<MetaData *>(obj.get()); 1385 1386 const char *mime; 1387 CHECK(format->findCString(kKeyMIMEType, &mime)); 1388 bool audio = !strncasecmp(mime, "audio/", 6); 1389 if (audio) { 1390 // Assumes 1000 samples per frame. 1391 int32_t sampleRate; 1392 CHECK(format->findInt32(kKeySampleRate, &sampleRate)); 1393 return kNumSkipFrames /* frames */ * 1000 /* samples */ 1394 * (1000000 / sampleRate) /* sample duration (us) */; 1395 } else { 1396 int32_t frameRate; 1397 if (format->findInt32(kKeyFrameRate, &frameRate) && frameRate > 0) { 1398 return kNumSkipFrames * (1000000 / frameRate); 1399 } 1400 } 1401 1402 return 500000ll; 1403} 1404 1405} // namespace android 1406