From d47dfcb5a2e5901c96fc92662cec7aa30f7f8843 Mon Sep 17 00:00:00 2001 From: Chong Zhang Date: Fri, 27 Mar 2015 15:53:45 -0700 Subject: HLS: misc bug fixes - fix no target-duration case - fix for audio-only <=> audio/video switching - disable audio-only variants if there is at least one variant with video - fix mpeg2ts PTS wraparound when bandwidth adapting - tweak up/down switch marks bug: 19567254 Change-Id: Ib46144203c56dfc96eccd6ddaa3867e8a4f2c6a9 --- media/libstagefright/mpeg2ts/ATSParser.cpp | 31 ++++++--- media/libstagefright/mpeg2ts/ATSParser.h | 1 + .../libstagefright/mpeg2ts/AnotherPacketSource.cpp | 79 +++++++++++++--------- media/libstagefright/mpeg2ts/AnotherPacketSource.h | 4 +- 4 files changed, 71 insertions(+), 44 deletions(-) (limited to 'media/libstagefright/mpeg2ts') diff --git a/media/libstagefright/mpeg2ts/ATSParser.cpp b/media/libstagefright/mpeg2ts/ATSParser.cpp index 6786506..ac6982e 100644 --- a/media/libstagefright/mpeg2ts/ATSParser.cpp +++ b/media/libstagefright/mpeg2ts/ATSParser.cpp @@ -48,7 +48,8 @@ namespace android { static const size_t kTSPacketSize = 188; struct ATSParser::Program : public RefBase { - Program(ATSParser *parser, unsigned programNumber, unsigned programMapPID); + Program(ATSParser *parser, unsigned programNumber, unsigned programMapPID, + int64_t lastRecoveredPTS); bool parsePSISection( unsigned pid, ABitReader *br, status_t *err); @@ -186,13 +187,14 @@ private: //////////////////////////////////////////////////////////////////////////////// ATSParser::Program::Program( - ATSParser *parser, unsigned programNumber, unsigned programMapPID) + ATSParser *parser, unsigned programNumber, unsigned programMapPID, + int64_t lastRecoveredPTS) : mParser(parser), mProgramNumber(programNumber), mProgramMapPID(programMapPID), mFirstPTSValid(false), mFirstPTS(0), - mLastRecoveredPTS(-1ll) { + mLastRecoveredPTS(lastRecoveredPTS) { ALOGV("new program number %u", programNumber); } @@ -1037,6 +1039,7 @@ ATSParser::ATSParser(uint32_t flags) mAbsoluteTimeAnchorUs(-1ll), mTimeOffsetValid(false), mTimeOffsetUs(0ll), + mLastRecoveredPTS(-1ll), mNumTSPacketsParsed(0), mNumPCRs(0) { mPSISections.add(0 /* PID */, new PSISection); @@ -1055,11 +1058,21 @@ status_t ATSParser::feedTSPacket(const void *data, size_t size) { void ATSParser::signalDiscontinuity( DiscontinuityType type, const sp &extra) { int64_t mediaTimeUs; - if ((type & DISCONTINUITY_TIME) - && extra != NULL - && extra->findInt64( - IStreamListener::kKeyMediaTimeUs, &mediaTimeUs)) { - mAbsoluteTimeAnchorUs = mediaTimeUs; + if ((type & DISCONTINUITY_TIME) && extra != NULL) { + if (extra->findInt64(IStreamListener::kKeyMediaTimeUs, &mediaTimeUs)) { + mAbsoluteTimeAnchorUs = mediaTimeUs; + } + if ((mFlags & TS_TIMESTAMPS_ARE_ABSOLUTE) + && extra->findInt64( + IStreamListener::kKeyRecentMediaTimeUs, &mediaTimeUs)) { + if (mAbsoluteTimeAnchorUs >= 0ll) { + mediaTimeUs -= mAbsoluteTimeAnchorUs; + } + if (mTimeOffsetValid) { + mediaTimeUs -= mTimeOffsetUs; + } + mLastRecoveredPTS = (mediaTimeUs * 9) / 100; + } } else if (type == DISCONTINUITY_ABSOLUTE_TIME) { int64_t timeUs; CHECK(extra->findInt64("timeUs", &timeUs)); @@ -1143,7 +1156,7 @@ void ATSParser::parseProgramAssociationTable(ABitReader *br) { if (!found) { mPrograms.push( - new Program(this, program_number, programMapPID)); + new Program(this, program_number, programMapPID, mLastRecoveredPTS)); } if (mPSISections.indexOfKey(programMapPID) < 0) { diff --git a/media/libstagefright/mpeg2ts/ATSParser.h b/media/libstagefright/mpeg2ts/ATSParser.h index 5c50747..a1405bd 100644 --- a/media/libstagefright/mpeg2ts/ATSParser.h +++ b/media/libstagefright/mpeg2ts/ATSParser.h @@ -118,6 +118,7 @@ private: bool mTimeOffsetValid; int64_t mTimeOffsetUs; + int64_t mLastRecoveredPTS; size_t mNumTSPacketsParsed; diff --git a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp index c2f1527..c5bb41b 100644 --- a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp +++ b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -461,6 +462,10 @@ void AnotherPacketSource::enable(bool enable) { mEnabled = enable; } +/* + * returns the sample meta that's delayUs after queue head + * (NULL if such sample is unavailable) + */ sp AnotherPacketSource::getMetaAfterLastDequeued(int64_t delayUs) { Mutex::Autolock autoLock(mLock); int64_t firstUs = -1; @@ -490,19 +495,28 @@ sp AnotherPacketSource::getMetaAfterLastDequeued(int64_t delayUs) { } } } - return mLatestEnqueuedMeta; + return NULL; } -void AnotherPacketSource::trimBuffersAfterTimeUs( - size_t discontinuitySeq, int64_t timeUs) { - ALOGV("trimBuffersAfterTimeUs: discontinuitySeq %zu, timeUs %lld", - discontinuitySeq, (long long)timeUs); +/* + * removes samples with time equal or after meta + */ +void AnotherPacketSource::trimBuffersAfterMeta( + const sp &meta) { + if (meta == NULL) { + ALOGW("trimming with NULL meta, ignoring"); + return; + } Mutex::Autolock autoLock(mLock); if (mBuffers.empty()) { return; } + HLSTime stopTime(meta); + ALOGV("trimBuffersAfterMeta: discontinuitySeq %zu, timeUs %lld", + stopTime.mSeq, (long long)stopTime.mTimeUs); + List >::iterator it; sp newLatestEnqueuedMeta = NULL; int64_t newLastQueuedTimeUs = 0; @@ -514,20 +528,15 @@ void AnotherPacketSource::trimBuffersAfterTimeUs( newDiscontinuityCount++; continue; } - size_t curDiscontinuitySeq; - int64_t curTimeUs; - CHECK(buffer->meta()->findInt32( - "discontinuitySeq", (int32_t*)&curDiscontinuitySeq)); - CHECK(buffer->meta()->findInt64("timeUs", &curTimeUs)); - if ((curDiscontinuitySeq > discontinuitySeq - || (curDiscontinuitySeq == discontinuitySeq - && curTimeUs >= timeUs))) { - ALOGI("trimming from %lld (inclusive) to end", - (long long)curTimeUs); + + HLSTime curTime(buffer->meta()); + if (!(curTime < stopTime)) { + ALOGV("trimming from %lld (inclusive) to end", + (long long)curTime.mTimeUs); break; } newLatestEnqueuedMeta = buffer->meta(); - newLastQueuedTimeUs = curTimeUs; + newLastQueuedTimeUs = curTime.mTimeUs; } mBuffers.erase(it, mBuffers.end()); mLatestEnqueuedMeta = newLatestEnqueuedMeta; @@ -535,11 +544,20 @@ void AnotherPacketSource::trimBuffersAfterTimeUs( mQueuedDiscontinuityCount = newDiscontinuityCount; } -sp AnotherPacketSource::trimBuffersBeforeTimeUs( - size_t discontinuitySeq, int64_t timeUs) { - ALOGV("trimBuffersBeforeTimeUs: discontinuitySeq %zu, timeUs %lld", - discontinuitySeq, (long long)timeUs); - sp meta; +/* + * removes samples with time equal or before meta; + * returns first sample left in the queue. + * + * (for AVC, if trim happens, the samples left will always start + * at next IDR.) + */ +sp AnotherPacketSource::trimBuffersBeforeMeta( + const sp &meta) { + HLSTime startTime(meta); + ALOGV("trimBuffersBeforeMeta: discontinuitySeq %zu, timeUs %lld", + startTime.mSeq, (long long)startTime.mTimeUs); + + sp firstMeta; Mutex::Autolock autoLock(mLock); if (mBuffers.empty()) { return NULL; @@ -572,24 +590,19 @@ sp AnotherPacketSource::trimBuffersBeforeTimeUs( if (isAvc && !IsIDR(buffer)) { continue; } - size_t curDiscontinuitySeq; - int64_t curTimeUs; - CHECK(buffer->meta()->findInt32( - "discontinuitySeq", (int32_t*)&curDiscontinuitySeq)); - CHECK(buffer->meta()->findInt64("timeUs", &curTimeUs)); - if ((curDiscontinuitySeq > discontinuitySeq - || (curDiscontinuitySeq == discontinuitySeq - && curTimeUs > timeUs))) { - ALOGI("trimming from beginning to %lld (not inclusive)", - (long long)curTimeUs); - meta = buffer->meta(); + + HLSTime curTime(buffer->meta()); + if (startTime < curTime) { + ALOGV("trimming from beginning to %lld (not inclusive)", + (long long)curTime.mTimeUs); + firstMeta = buffer->meta(); break; } } mBuffers.erase(mBuffers.begin(), it); mQueuedDiscontinuityCount -= discontinuityCount; mLatestDequeuedMeta = NULL; - return meta; + return firstMeta; } } // namespace android diff --git a/media/libstagefright/mpeg2ts/AnotherPacketSource.h b/media/libstagefright/mpeg2ts/AnotherPacketSource.h index e126006..fa7dd6a 100644 --- a/media/libstagefright/mpeg2ts/AnotherPacketSource.h +++ b/media/libstagefright/mpeg2ts/AnotherPacketSource.h @@ -76,8 +76,8 @@ struct AnotherPacketSource : public MediaSource { sp getLatestDequeuedMeta(); sp getMetaAfterLastDequeued(int64_t delayUs); - void trimBuffersAfterTimeUs(size_t discontinuitySeq, int64_t timeUs); - sp trimBuffersBeforeTimeUs(size_t discontinuitySeq, int64_t timeUs); + void trimBuffersAfterMeta(const sp &meta); + sp trimBuffersBeforeMeta(const sp &meta); protected: virtual ~AnotherPacketSource(); -- cgit v1.1