From 9c5d62a5be43904081575a943fe04d3cfcc2dda8 Mon Sep 17 00:00:00 2001 From: Andreas Huber Date: Wed, 15 Dec 2010 14:07:50 -0800 Subject: Proper recovery of timestamp information in the transport stream parser. Change-Id: I647c73688c95529f54f0bb6af17d109dfe2bb11d --- media/libstagefright/mpeg2ts/ESQueue.cpp | 78 +++++++++++++++++++++++++++----- media/libstagefright/mpeg2ts/ESQueue.h | 11 ++++- 2 files changed, 77 insertions(+), 12 deletions(-) (limited to 'media/libstagefright/mpeg2ts') diff --git a/media/libstagefright/mpeg2ts/ESQueue.cpp b/media/libstagefright/mpeg2ts/ESQueue.cpp index 1fb7c39..4b4490d 100644 --- a/media/libstagefright/mpeg2ts/ESQueue.cpp +++ b/media/libstagefright/mpeg2ts/ESQueue.cpp @@ -45,7 +45,7 @@ void ElementaryStreamQueue::clear() { mBuffer->setRange(0, 0); } - mTimestamps.clear(); + mRangeInfos.clear(); mFormat.clear(); } @@ -171,7 +171,17 @@ status_t ElementaryStreamQueue::appendData( memcpy(mBuffer->data() + mBuffer->size(), data, size); mBuffer->setRange(0, mBuffer->size() + size); - mTimestamps.push_back(timeUs); + RangeInfo info; + info.mLength = size; + info.mTimestampUs = timeUs; + mRangeInfos.push_back(info); + +#if 0 + if (mMode == AAC) { + LOGI("size = %d, timeUs = %.2f secs", size, timeUs / 1E6); + hexdump(data, size); + } +#endif return OK; } @@ -186,6 +196,7 @@ sp ElementaryStreamQueue::dequeueAccessUnit() { } sp ElementaryStreamQueue::dequeueAccessUnitAAC() { + Vector ranges; Vector frameOffsets; Vector frameSizes; size_t auSize = 0; @@ -239,6 +250,7 @@ sp ElementaryStreamQueue::dequeueAccessUnitAAC() { size_t headerSize = protection_absent ? 7 : 9; + ranges.push(aac_frame_length); frameOffsets.push(offset + headerSize); frameSizes.push(aac_frame_length - headerSize); auSize += aac_frame_length - headerSize; @@ -250,11 +262,23 @@ sp ElementaryStreamQueue::dequeueAccessUnitAAC() { return NULL; } + int64_t timeUs = -1; + + for (size_t i = 0; i < ranges.size(); ++i) { + int64_t tmpUs = fetchTimestamp(ranges.itemAt(i)); + + if (i == 0) { + timeUs = tmpUs; + } + } + sp accessUnit = new ABuffer(auSize); size_t dstOffset = 0; for (size_t i = 0; i < frameOffsets.size(); ++i) { + size_t frameOffset = frameOffsets.itemAt(i); + memcpy(accessUnit->data() + dstOffset, - mBuffer->data() + frameOffsets.itemAt(i), + mBuffer->data() + frameOffset, frameSizes.itemAt(i)); dstOffset += frameSizes.itemAt(i); @@ -264,15 +288,48 @@ sp ElementaryStreamQueue::dequeueAccessUnitAAC() { mBuffer->size() - offset); mBuffer->setRange(0, mBuffer->size() - offset); - CHECK_GT(mTimestamps.size(), 0u); - int64_t timeUs = *mTimestamps.begin(); - mTimestamps.erase(mTimestamps.begin()); - - accessUnit->meta()->setInt64("time", timeUs); + if (timeUs >= 0) { + accessUnit->meta()->setInt64("time", timeUs); + } else { + LOGW("no time for AAC access unit"); + } return accessUnit; } +int64_t ElementaryStreamQueue::fetchTimestamp(size_t size) { + int64_t timeUs = -1; + bool first = true; + + while (size > 0) { + CHECK(!mRangeInfos.empty()); + + RangeInfo *info = &*mRangeInfos.begin(); + + if (first) { + timeUs = info->mTimestampUs; + first = false; + } + + if (info->mLength > size) { + info->mLength -= size; + + if (first) { + info->mTimestampUs = -1; + } + + size = 0; + } else { + size -= info->mLength; + + mRangeInfos.erase(mRangeInfos.begin()); + info = NULL; + } + } + + return timeUs; +} + // static sp ElementaryStreamQueue::MakeAACCodecSpecificData( unsigned profile, unsigned sampling_freq_index, @@ -410,9 +467,8 @@ sp ElementaryStreamQueue::dequeueAccessUnitH264() { mBuffer->setRange(0, mBuffer->size() - nextScan); - CHECK_GT(mTimestamps.size(), 0u); - int64_t timeUs = *mTimestamps.begin(); - mTimestamps.erase(mTimestamps.begin()); + int64_t timeUs = fetchTimestamp(nextScan); + CHECK_GE(timeUs, 0ll); accessUnit->meta()->setInt64("time", timeUs); diff --git a/media/libstagefright/mpeg2ts/ESQueue.h b/media/libstagefright/mpeg2ts/ESQueue.h index 9eaf834..adce153 100644 --- a/media/libstagefright/mpeg2ts/ESQueue.h +++ b/media/libstagefright/mpeg2ts/ESQueue.h @@ -42,16 +42,25 @@ struct ElementaryStreamQueue { sp getFormat(); private: + struct RangeInfo { + int64_t mTimestampUs; + size_t mLength; + }; + Mode mMode; sp mBuffer; - List mTimestamps; + List mRangeInfos; sp mFormat; sp dequeueAccessUnitH264(); sp dequeueAccessUnitAAC(); + // consume a logical (compressed) access unit of size "size", + // returns its timestamp in us (or -1 if no time information). + int64_t fetchTimestamp(size_t size); + static sp MakeAACCodecSpecificData( unsigned profile, unsigned sampling_freq_index, unsigned channel_configuration); -- cgit v1.1