|
|
|
@ -50,8 +50,8 @@
|
|
|
|
|
namespace android {
|
|
|
|
|
|
|
|
|
|
// static
|
|
|
|
|
const int64_t PlaylistFetcher::kMinBufferedDurationUs = 30000000ll;
|
|
|
|
|
const int64_t PlaylistFetcher::kMaxMonitorDelayUs = 3000000ll;
|
|
|
|
|
const int64_t PlaylistFetcher::kMinBufferedDurationUs = 30000000LL;
|
|
|
|
|
const int64_t PlaylistFetcher::kMaxMonitorDelayUs = 3000000LL;
|
|
|
|
|
// LCM of 188 (size of a TS packet) & 1k works well
|
|
|
|
|
const int32_t PlaylistFetcher::kDownloadBlockSize = 47 * 1024;
|
|
|
|
|
|
|
|
|
@ -152,25 +152,25 @@ PlaylistFetcher::PlaylistFetcher(
|
|
|
|
|
mURI(uri),
|
|
|
|
|
mFetcherID(id),
|
|
|
|
|
mStreamTypeMask(0),
|
|
|
|
|
mStartTimeUs(-1ll),
|
|
|
|
|
mSegmentStartTimeUs(-1ll),
|
|
|
|
|
mDiscontinuitySeq(-1ll),
|
|
|
|
|
mStartTimeUs(-1LL),
|
|
|
|
|
mSegmentStartTimeUs(-1LL),
|
|
|
|
|
mDiscontinuitySeq(-1LL),
|
|
|
|
|
mStartTimeUsRelative(false),
|
|
|
|
|
mLastPlaylistFetchTimeUs(-1ll),
|
|
|
|
|
mPlaylistTimeUs(-1ll),
|
|
|
|
|
mLastPlaylistFetchTimeUs(-1LL),
|
|
|
|
|
mPlaylistTimeUs(-1LL),
|
|
|
|
|
mSeqNumber(-1),
|
|
|
|
|
mNumRetries(0),
|
|
|
|
|
mStartup(true),
|
|
|
|
|
mIDRFound(false),
|
|
|
|
|
mSeekMode(LiveSession::kSeekModeExactPosition),
|
|
|
|
|
mTimeChangeSignaled(false),
|
|
|
|
|
mNextPTSTimeUs(-1ll),
|
|
|
|
|
mNextPTSTimeUs(-1LL),
|
|
|
|
|
mMonitorQueueGeneration(0),
|
|
|
|
|
mSubtitleGeneration(subtitleGeneration),
|
|
|
|
|
mLastDiscontinuitySeq(-1ll),
|
|
|
|
|
mLastDiscontinuitySeq(-1LL),
|
|
|
|
|
mRefreshState(INITIAL_MINIMUM_RELOAD_DELAY),
|
|
|
|
|
mFirstPTSValid(false),
|
|
|
|
|
mFirstTimeUs(-1ll),
|
|
|
|
|
mFirstTimeUs(-1LL),
|
|
|
|
|
mVideoBuffer(new AnotherPacketSource(NULL)),
|
|
|
|
|
mSampleAesKeyItemChanged(false),
|
|
|
|
|
mThresholdRatio(-1.0f),
|
|
|
|
@ -200,7 +200,7 @@ int64_t PlaylistFetcher::getSegmentStartTimeUs(int32_t seqNumber) const {
|
|
|
|
|
CHECK_GE(seqNumber, firstSeqNumberInPlaylist);
|
|
|
|
|
CHECK_LE(seqNumber, lastSeqNumberInPlaylist);
|
|
|
|
|
|
|
|
|
|
int64_t segmentStartUs = 0ll;
|
|
|
|
|
int64_t segmentStartUs = 0LL;
|
|
|
|
|
for (int32_t index = 0;
|
|
|
|
|
index < seqNumber - firstSeqNumberInPlaylist; ++index) {
|
|
|
|
|
sp<AMessage> itemMeta;
|
|
|
|
@ -240,13 +240,13 @@ int64_t PlaylistFetcher::getSegmentDurationUs(int32_t seqNumber) const {
|
|
|
|
|
int64_t PlaylistFetcher::delayUsToRefreshPlaylist() const {
|
|
|
|
|
int64_t nowUs = ALooper::GetNowUs();
|
|
|
|
|
|
|
|
|
|
if (mPlaylist == NULL || mLastPlaylistFetchTimeUs < 0ll) {
|
|
|
|
|
if (mPlaylist == NULL || mLastPlaylistFetchTimeUs < 0LL) {
|
|
|
|
|
CHECK_EQ((int)mRefreshState, (int)INITIAL_MINIMUM_RELOAD_DELAY);
|
|
|
|
|
return 0ll;
|
|
|
|
|
return 0LL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (mPlaylist->isComplete()) {
|
|
|
|
|
return (~0llu >> 1);
|
|
|
|
|
return (~0LLU >> 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int64_t targetDurationUs = mPlaylist->getTargetDuration();
|
|
|
|
@ -295,7 +295,7 @@ int64_t PlaylistFetcher::delayUsToRefreshPlaylist() const {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int64_t delayUs = mLastPlaylistFetchTimeUs + minPlaylistAgeUs - nowUs;
|
|
|
|
|
return delayUs > 0ll ? delayUs : 0ll;
|
|
|
|
|
return delayUs > 0LL ? delayUs : 0LL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
status_t PlaylistFetcher::decryptBuffer(
|
|
|
|
@ -857,7 +857,7 @@ void PlaylistFetcher::onMonitorQueue() {
|
|
|
|
|
targetDurationUs = mPlaylist->getTargetDuration();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int64_t bufferedDurationUs = 0ll;
|
|
|
|
|
int64_t bufferedDurationUs = 0LL;
|
|
|
|
|
status_t finalResult = OK;
|
|
|
|
|
if (mStreamTypeMask == LiveSession::STREAMTYPE_SUBTITLES) {
|
|
|
|
|
sp<AnotherPacketSource> packetSource =
|
|
|
|
@ -870,7 +870,7 @@ void PlaylistFetcher::onMonitorQueue() {
|
|
|
|
|
// enqueued to prevent us from waiting on a non-existent stream;
|
|
|
|
|
// when we cannot make out from the manifest what streams are included in
|
|
|
|
|
// a playlist we might assume extra streams.
|
|
|
|
|
bufferedDurationUs = -1ll;
|
|
|
|
|
bufferedDurationUs = -1LL;
|
|
|
|
|
for (size_t i = 0; i < mPacketSources.size(); ++i) {
|
|
|
|
|
if ((mStreamTypeMask & mPacketSources.keyAt(i)) == 0
|
|
|
|
|
|| mPacketSources[i]->getLatestEnqueuedMeta() == NULL) {
|
|
|
|
@ -882,13 +882,13 @@ void PlaylistFetcher::onMonitorQueue() {
|
|
|
|
|
|
|
|
|
|
FSLOGV(mPacketSources.keyAt(i), "buffered %lld", (long long)bufferedStreamDurationUs);
|
|
|
|
|
|
|
|
|
|
if (bufferedDurationUs == -1ll
|
|
|
|
|
if (bufferedDurationUs == -1LL
|
|
|
|
|
|| bufferedStreamDurationUs < bufferedDurationUs) {
|
|
|
|
|
bufferedDurationUs = bufferedStreamDurationUs;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (bufferedDurationUs == -1ll) {
|
|
|
|
|
bufferedDurationUs = 0ll;
|
|
|
|
|
if (bufferedDurationUs == -1LL) {
|
|
|
|
|
bufferedDurationUs = 0LL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -901,12 +901,12 @@ void PlaylistFetcher::onMonitorQueue() {
|
|
|
|
|
// onDownloadNext();
|
|
|
|
|
sp<AMessage> msg = new AMessage(kWhatDownloadNext, this);
|
|
|
|
|
msg->setInt32("generation", mMonitorQueueGeneration);
|
|
|
|
|
msg->post(1000l);
|
|
|
|
|
msg->post(1000L);
|
|
|
|
|
} else {
|
|
|
|
|
// We'd like to maintain buffering above durationToBufferUs, so try
|
|
|
|
|
// again when buffer just about to go below durationToBufferUs
|
|
|
|
|
// (or after targetDurationUs / 2, whichever is smaller).
|
|
|
|
|
int64_t delayUs = bufferedDurationUs - kMinBufferedDurationUs + 1000000ll;
|
|
|
|
|
int64_t delayUs = bufferedDurationUs - kMinBufferedDurationUs + 1000000LL;
|
|
|
|
|
if (delayUs > targetDurationUs / 2) {
|
|
|
|
|
delayUs = targetDurationUs / 2;
|
|
|
|
|
}
|
|
|
|
@ -1073,10 +1073,10 @@ bool PlaylistFetcher::initDownloadState(
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mSegmentFirstPTS = -1ll;
|
|
|
|
|
mSegmentFirstPTS = -1LL;
|
|
|
|
|
|
|
|
|
|
if (mPlaylist != NULL && mSeqNumber < 0) {
|
|
|
|
|
CHECK_GE(mStartTimeUs, 0ll);
|
|
|
|
|
CHECK_GE(mStartTimeUs, 0LL);
|
|
|
|
|
|
|
|
|
|
if (mSegmentStartTimeUs < 0) {
|
|
|
|
|
if (!mPlaylist->isComplete() && !mPlaylist->isEvent()) {
|
|
|
|
@ -1379,7 +1379,7 @@ void PlaylistFetcher::onDownloadNext() {
|
|
|
|
|
& (LiveSession::STREAMTYPE_AUDIO
|
|
|
|
|
| LiveSession::STREAMTYPE_VIDEO))) {
|
|
|
|
|
mSession->addBandwidthMeasurement(bytesRead, delayUs);
|
|
|
|
|
if (delayUs > 2000000ll) {
|
|
|
|
|
if (delayUs > 2000000LL) {
|
|
|
|
|
FLOGV("bytesRead %zd took %.2f seconds - abnormal bandwidth dip",
|
|
|
|
|
bytesRead, (double)delayUs / 1.0e6);
|
|
|
|
|
}
|
|
|
|
@ -1553,7 +1553,7 @@ bool PlaylistFetcher::adjustSeqNumberWithAnchorTime(int64_t anchorTimeUs) {
|
|
|
|
|
// if the previous fetcher paused in the middle of a segment, we
|
|
|
|
|
// want to start at a segment that overlaps the last sample
|
|
|
|
|
minDiffUs = -mPlaylist->getTargetDuration();
|
|
|
|
|
maxDiffUs = 0ll;
|
|
|
|
|
maxDiffUs = 0LL;
|
|
|
|
|
} else {
|
|
|
|
|
// if the previous fetcher paused at the end of a segment, ideally
|
|
|
|
|
// we want to start at the segment that's roughly aligned with its
|
|
|
|
@ -1704,7 +1704,7 @@ status_t PlaylistFetcher::extractAndQueueAccessUnitsFromTs(const sp<ABuffer> &bu
|
|
|
|
|
mTSParser = new ATSParser(ATSParser::TS_TIMESTAMPS_ARE_ABSOLUTE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (mNextPTSTimeUs >= 0ll) {
|
|
|
|
|
if (mNextPTSTimeUs >= 0LL) {
|
|
|
|
|
sp<AMessage> extra = new AMessage;
|
|
|
|
|
// Since we are using absolute timestamps, signal an offset of 0 to prevent
|
|
|
|
|
// ATSParser from skewing the timestamps of access units.
|
|
|
|
@ -1719,7 +1719,7 @@ status_t PlaylistFetcher::extractAndQueueAccessUnitsFromTs(const sp<ABuffer> &bu
|
|
|
|
|
mTSParser->signalDiscontinuity(
|
|
|
|
|
ATSParser::DISCONTINUITY_TIME, extra);
|
|
|
|
|
|
|
|
|
|
mNextPTSTimeUs = -1ll;
|
|
|
|
|
mNextPTSTimeUs = -1LL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (mSampleAesKeyItemChanged) {
|
|
|
|
@ -1740,7 +1740,7 @@ status_t PlaylistFetcher::extractAndQueueAccessUnitsFromTs(const sp<ABuffer> &bu
|
|
|
|
|
// setRange to indicate consumed bytes.
|
|
|
|
|
buffer->setRange(buffer->offset() + offset, buffer->size() - offset);
|
|
|
|
|
|
|
|
|
|
if (mSegmentFirstPTS < 0ll) {
|
|
|
|
|
if (mSegmentFirstPTS < 0LL) {
|
|
|
|
|
// get the smallest first PTS from all streams present in this parser
|
|
|
|
|
for (size_t i = mPacketSources.size(); i > 0;) {
|
|
|
|
|
i--;
|
|
|
|
@ -1764,12 +1764,12 @@ status_t PlaylistFetcher::extractAndQueueAccessUnitsFromTs(const sp<ABuffer> &bu
|
|
|
|
|
if (meta != NULL) {
|
|
|
|
|
int64_t timeUs;
|
|
|
|
|
CHECK(meta->findInt64("timeUs", &timeUs));
|
|
|
|
|
if (mSegmentFirstPTS < 0ll || timeUs < mSegmentFirstPTS) {
|
|
|
|
|
if (mSegmentFirstPTS < 0LL || timeUs < mSegmentFirstPTS) {
|
|
|
|
|
mSegmentFirstPTS = timeUs;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (mSegmentFirstPTS < 0ll) {
|
|
|
|
|
if (mSegmentFirstPTS < 0LL) {
|
|
|
|
|
// didn't find any TS packet, can return early
|
|
|
|
|
return OK;
|
|
|
|
|
}
|
|
|
|
@ -1988,8 +1988,8 @@ status_t PlaylistFetcher::extractAndQueueAccessUnits(
|
|
|
|
|
return OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (mNextPTSTimeUs >= 0ll) {
|
|
|
|
|
mNextPTSTimeUs = -1ll;
|
|
|
|
|
if (mNextPTSTimeUs >= 0LL) {
|
|
|
|
|
mNextPTSTimeUs = -1LL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// This better be an ISO 13818-7 (AAC) or ISO 13818-1 (MPEG) audio
|
|
|
|
@ -2088,17 +2088,17 @@ status_t PlaylistFetcher::extractAndQueueAccessUnits(
|
|
|
|
|
packetSource->setFormat(meta);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int64_t numSamples = 0ll;
|
|
|
|
|
int64_t numSamples = 0LL;
|
|
|
|
|
int32_t sampleRate;
|
|
|
|
|
CHECK(packetSource->getFormat()->findInt32(kKeySampleRate, &sampleRate));
|
|
|
|
|
|
|
|
|
|
int64_t timeUs = (PTS * 100ll) / 9ll;
|
|
|
|
|
int64_t timeUs = (PTS * 100LL) / 9LL;
|
|
|
|
|
if (mStartup && !mFirstPTSValid) {
|
|
|
|
|
mFirstPTSValid = true;
|
|
|
|
|
mFirstTimeUs = timeUs;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (mSegmentFirstPTS < 0ll) {
|
|
|
|
|
if (mSegmentFirstPTS < 0LL) {
|
|
|
|
|
mSegmentFirstPTS = timeUs;
|
|
|
|
|
if (!mStartTimeUsRelative) {
|
|
|
|
|
// Duplicated logic from how we handle .ts playlists.
|
|
|
|
@ -2148,7 +2148,7 @@ status_t PlaylistFetcher::extractAndQueueAccessUnits(
|
|
|
|
|
|
|
|
|
|
CHECK_LE(offset + aac_frame_length, buffer->size());
|
|
|
|
|
|
|
|
|
|
int64_t unitTimeUs = timeUs + numSamples * 1000000ll / sampleRate;
|
|
|
|
|
int64_t unitTimeUs = timeUs + numSamples * 1000000LL / sampleRate;
|
|
|
|
|
offset += aac_frame_length;
|
|
|
|
|
|
|
|
|
|
// Each AAC frame encodes 1024 samples.
|
|
|
|
@ -2209,7 +2209,7 @@ status_t PlaylistFetcher::extractAndQueueAccessUnits(
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PlaylistFetcher::updateDuration() {
|
|
|
|
|
int64_t durationUs = 0ll;
|
|
|
|
|
int64_t durationUs = 0LL;
|
|
|
|
|
for (size_t index = 0; index < mPlaylist->size(); ++index) {
|
|
|
|
|
sp<AMessage> itemMeta;
|
|
|
|
|
CHECK(mPlaylist->itemAt(
|
|
|
|
|