diff options
author | Andreas Huber <andih@google.com> | 2010-09-08 14:32:20 -0700 |
---|---|---|
committer | Andreas Huber <andih@google.com> | 2010-10-07 11:41:43 -0700 |
commit | 2a4d22d79e927f2245537921e10fc5fda1c47a29 (patch) | |
tree | 1452ec4c157a5f701d4aea84f2107477d5324d94 /media/libstagefright/mpeg2ts | |
parent | 2b82e9652ba049e754c2cc74e381282f231d5fbf (diff) | |
download | frameworks_av-2a4d22d79e927f2245537921e10fc5fda1c47a29.zip frameworks_av-2a4d22d79e927f2245537921e10fc5fda1c47a29.tar.gz frameworks_av-2a4d22d79e927f2245537921e10fc5fda1c47a29.tar.bz2 |
Work to support switching transport streams mid-stream and signalling discontinuities to the decoder.
Change-Id: I7150e5e7342e1117c524856b204aadcb763e06ed
related-to-bug: 2368598
Diffstat (limited to 'media/libstagefright/mpeg2ts')
-rw-r--r-- | media/libstagefright/mpeg2ts/ATSParser.cpp | 34 | ||||
-rw-r--r-- | media/libstagefright/mpeg2ts/ATSParser.h | 1 | ||||
-rw-r--r-- | media/libstagefright/mpeg2ts/AnotherPacketSource.cpp | 36 | ||||
-rw-r--r-- | media/libstagefright/mpeg2ts/AnotherPacketSource.h | 1 | ||||
-rw-r--r-- | media/libstagefright/mpeg2ts/ESQueue.cpp | 9 | ||||
-rw-r--r-- | media/libstagefright/mpeg2ts/ESQueue.h | 1 | ||||
-rw-r--r-- | media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp | 14 |
7 files changed, 80 insertions, 16 deletions
diff --git a/media/libstagefright/mpeg2ts/ATSParser.cpp b/media/libstagefright/mpeg2ts/ATSParser.cpp index bcaab9f..7c9b83a 100644 --- a/media/libstagefright/mpeg2ts/ATSParser.cpp +++ b/media/libstagefright/mpeg2ts/ATSParser.cpp @@ -49,6 +49,8 @@ struct ATSParser::Program : public RefBase { unsigned pid, unsigned payload_unit_start_indicator, ABitReader *br); + void signalDiscontinuity(); + sp<MediaSource> getSource(SourceType type); private: @@ -67,6 +69,8 @@ struct ATSParser::Stream : public RefBase { unsigned payload_unit_start_indicator, ABitReader *br); + void signalDiscontinuity(); + sp<MediaSource> getSource(SourceType type); protected: @@ -124,6 +128,12 @@ bool ATSParser::Program::parsePID( return true; } +void ATSParser::Program::signalDiscontinuity() { + for (size_t i = 0; i < mStreams.size(); ++i) { + mStreams.editValueAt(i)->signalDiscontinuity(); + } +} + void ATSParser::Program::parseProgramMap(ABitReader *br) { unsigned table_id = br->getBits(8); LOGV(" table_id = %u", table_id); @@ -271,6 +281,19 @@ void ATSParser::Stream::parse( mBuffer->setRange(0, mBuffer->size() + payloadSizeBits / 8); } +void ATSParser::Stream::signalDiscontinuity() { + LOGV("Stream discontinuity"); + mPayloadStarted = false; + mBuffer->setRange(0, 0); + + mQueue.clear(); + + if (mStreamType == 0x1b && mSource != NULL) { + // Don't signal discontinuities on audio streams. + mSource->queueDiscontinuity(); + } +} + void ATSParser::Stream::parsePES(ABitReader *br) { unsigned packet_startcode_prefix = br->getBits(24); @@ -459,7 +482,10 @@ void ATSParser::Stream::onPayloadData( mSource = new AnotherPacketSource(meta); mSource->queueAccessUnit(accessUnit); } - } else { + } else if (mQueue.getFormat() != NULL) { + // After a discontinuity we invalidate the queue's format + // and won't enqueue any access units to the source until + // the queue has reestablished the new format. mSource->queueAccessUnit(accessUnit); } } @@ -489,6 +515,12 @@ void ATSParser::feedTSPacket(const void *data, size_t size) { parseTS(&br); } +void ATSParser::signalDiscontinuity() { + for (size_t i = 0; i < mPrograms.size(); ++i) { + mPrograms.editItemAt(i)->signalDiscontinuity(); + } +} + void ATSParser::parseProgramAssociationTable(ABitReader *br) { unsigned table_id = br->getBits(8); LOGV(" table_id = %u", table_id); diff --git a/media/libstagefright/mpeg2ts/ATSParser.h b/media/libstagefright/mpeg2ts/ATSParser.h index 1e22e7b..9ec6d7b 100644 --- a/media/libstagefright/mpeg2ts/ATSParser.h +++ b/media/libstagefright/mpeg2ts/ATSParser.h @@ -33,6 +33,7 @@ struct ATSParser : public RefBase { ATSParser(); void feedTSPacket(const void *data, size_t size); + void signalDiscontinuity(); enum SourceType { AVC_VIDEO, diff --git a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp index 3d51177..3f76820 100644 --- a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp +++ b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp @@ -59,21 +59,26 @@ status_t AnotherPacketSource::read( if (!mBuffers.empty()) { const sp<ABuffer> buffer = *mBuffers.begin(); + mBuffers.erase(mBuffers.begin()); - uint64_t timeUs; - CHECK(buffer->meta()->findInt64( - "time", (int64_t *)&timeUs)); - - MediaBuffer *mediaBuffer = new MediaBuffer(buffer->size()); - mediaBuffer->meta_data()->setInt64(kKeyTime, timeUs); + int32_t discontinuity; + if (buffer->meta()->findInt32("discontinuity", &discontinuity) + && discontinuity) { + return INFO_DISCONTINUITY; + } else { + uint64_t timeUs; + CHECK(buffer->meta()->findInt64( + "time", (int64_t *)&timeUs)); - // hexdump(buffer->data(), buffer->size()); + MediaBuffer *mediaBuffer = new MediaBuffer(buffer->size()); + mediaBuffer->meta_data()->setInt64(kKeyTime, timeUs); - memcpy(mediaBuffer->data(), buffer->data(), buffer->size()); - *out = mediaBuffer; + // hexdump(buffer->data(), buffer->size()); - mBuffers.erase(mBuffers.begin()); - return OK; + memcpy(mediaBuffer->data(), buffer->data(), buffer->size()); + *out = mediaBuffer; + return OK; + } } return mEOSResult; @@ -91,6 +96,15 @@ void AnotherPacketSource::queueAccessUnit(const sp<ABuffer> &buffer) { mCondition.signal(); } +void AnotherPacketSource::queueDiscontinuity() { + sp<ABuffer> buffer = new ABuffer(0); + buffer->meta()->setInt32("discontinuity", true); + + Mutex::Autolock autoLock(mLock); + mBuffers.push_back(buffer); + mCondition.signal(); +} + void AnotherPacketSource::signalEOS(status_t result) { CHECK(result != OK); diff --git a/media/libstagefright/mpeg2ts/AnotherPacketSource.h b/media/libstagefright/mpeg2ts/AnotherPacketSource.h index ce83d21..6b43c4e 100644 --- a/media/libstagefright/mpeg2ts/AnotherPacketSource.h +++ b/media/libstagefright/mpeg2ts/AnotherPacketSource.h @@ -40,6 +40,7 @@ struct AnotherPacketSource : public MediaSource { bool hasBufferAvailable(status_t *finalResult); void queueAccessUnit(const sp<ABuffer> &buffer); + void queueDiscontinuity(); void signalEOS(status_t result); protected: diff --git a/media/libstagefright/mpeg2ts/ESQueue.cpp b/media/libstagefright/mpeg2ts/ESQueue.cpp index d87040b..4a75ee4 100644 --- a/media/libstagefright/mpeg2ts/ESQueue.cpp +++ b/media/libstagefright/mpeg2ts/ESQueue.cpp @@ -115,6 +115,11 @@ static status_t getNextNALUnit( return OK; } +void ElementaryStreamQueue::clear() { + mBuffer->setRange(0, 0); + mFormat.clear(); +} + status_t ElementaryStreamQueue::appendData( const void *data, size_t size, int64_t timeUs) { if (mBuffer == NULL || mBuffer->size() == 0) { @@ -147,7 +152,7 @@ status_t ElementaryStreamQueue::appendData( if (mBuffer == NULL || neededSize > mBuffer->capacity()) { neededSize = (neededSize + 65535) & ~65535; - LOGI("resizing buffer to size %d", neededSize); + LOGV("resizing buffer to size %d", neededSize); sp<ABuffer> buffer = new ABuffer(neededSize); if (mBuffer != NULL) { @@ -498,6 +503,8 @@ sp<MetaData> ElementaryStreamQueue::MakeAVCCodecSpecificData( meta->setInt32(kKeyWidth, width); meta->setInt32(kKeyHeight, height); + LOGI("found AVC codec config (%d x %d)", width, height); + return meta; } diff --git a/media/libstagefright/mpeg2ts/ESQueue.h b/media/libstagefright/mpeg2ts/ESQueue.h index d2e87f2..246c390 100644 --- a/media/libstagefright/mpeg2ts/ESQueue.h +++ b/media/libstagefright/mpeg2ts/ESQueue.h @@ -35,6 +35,7 @@ struct ElementaryStreamQueue { ElementaryStreamQueue(Mode mode); status_t appendData(const void *data, size_t size, int64_t timeUs); + void clear(); sp<ABuffer> dequeueAccessUnit(); diff --git a/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp b/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp index c5257bb..0d96bd1 100644 --- a/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp +++ b/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp @@ -165,18 +165,26 @@ void MPEG2TSExtractor::init() { LOGI("haveAudio=%d, haveVideo=%d", haveAudio, haveVideo); } +static bool isDiscontinuity(const uint8_t *data, ssize_t size) { + return size == 188 && data[0] == 0x00; +} + status_t MPEG2TSExtractor::feedMore() { Mutex::Autolock autoLock(mLock); uint8_t packet[kTSPacketSize]; ssize_t n = mDataSource->readAt(mOffset, packet, kTSPacketSize); - if (n < (ssize_t)kTSPacketSize) { + if (isDiscontinuity(packet, n)) { + LOGI("XXX discontinuity detected"); + mParser->signalDiscontinuity(); + } else if (n < (ssize_t)kTSPacketSize) { return (n < 0) ? (status_t)n : ERROR_END_OF_STREAM; + } else { + mParser->feedTSPacket(packet, kTSPacketSize); } - mOffset += kTSPacketSize; - mParser->feedTSPacket(packet, kTSPacketSize); + mOffset += n; return OK; } |