Merge "Proper recovery of timestamp information in the transport stream parser."
This commit is contained in:
committed by
Android (Google) Code Review
commit
ebf90ac7a8
@@ -21,8 +21,8 @@
|
||||
|
||||
#include "pvmp4audiodecoder_api.h"
|
||||
|
||||
#include <media/stagefright/foundation/ADebug.h>
|
||||
#include <media/stagefright/MediaBufferGroup.h>
|
||||
#include <media/stagefright/MediaDebug.h>
|
||||
#include <media/stagefright/MediaDefs.h>
|
||||
#include <media/stagefright/MetaData.h>
|
||||
|
||||
@@ -84,7 +84,7 @@ status_t AACDecoder::initCheck() {
|
||||
sp<MetaData> meta = mSource->getFormat();
|
||||
if (meta->findData(kKeyESDS, &type, &data, &size)) {
|
||||
ESDS esds((const char *)data, size);
|
||||
CHECK_EQ(esds.InitCheck(), OK);
|
||||
CHECK_EQ(esds.InitCheck(), (status_t)OK);
|
||||
|
||||
const void *codec_specific_data;
|
||||
size_t codec_specific_data_size;
|
||||
@@ -197,7 +197,7 @@ status_t AACDecoder::read(
|
||||
}
|
||||
|
||||
MediaBuffer *buffer;
|
||||
CHECK_EQ(mBufferGroup->acquire_buffer(&buffer), OK);
|
||||
CHECK_EQ(mBufferGroup->acquire_buffer(&buffer), (status_t)OK);
|
||||
|
||||
mConfig->pInputBuffer =
|
||||
(UChar *)mInputBuffer->data() + mInputBuffer->range_offset();
|
||||
|
||||
@@ -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<ABuffer> ElementaryStreamQueue::dequeueAccessUnit() {
|
||||
}
|
||||
|
||||
sp<ABuffer> ElementaryStreamQueue::dequeueAccessUnitAAC() {
|
||||
Vector<size_t> ranges;
|
||||
Vector<size_t> frameOffsets;
|
||||
Vector<size_t> frameSizes;
|
||||
size_t auSize = 0;
|
||||
@@ -239,6 +250,7 @@ sp<ABuffer> 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<ABuffer> 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<ABuffer> 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<ABuffer> 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<MetaData> ElementaryStreamQueue::MakeAACCodecSpecificData(
|
||||
unsigned profile, unsigned sampling_freq_index,
|
||||
@@ -410,9 +467,8 @@ sp<ABuffer> 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);
|
||||
|
||||
|
||||
@@ -42,16 +42,25 @@ struct ElementaryStreamQueue {
|
||||
sp<MetaData> getFormat();
|
||||
|
||||
private:
|
||||
struct RangeInfo {
|
||||
int64_t mTimestampUs;
|
||||
size_t mLength;
|
||||
};
|
||||
|
||||
Mode mMode;
|
||||
|
||||
sp<ABuffer> mBuffer;
|
||||
List<int64_t> mTimestamps;
|
||||
List<RangeInfo> mRangeInfos;
|
||||
|
||||
sp<MetaData> mFormat;
|
||||
|
||||
sp<ABuffer> dequeueAccessUnitH264();
|
||||
sp<ABuffer> 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<MetaData> MakeAACCodecSpecificData(
|
||||
unsigned profile, unsigned sampling_freq_index,
|
||||
unsigned channel_configuration);
|
||||
|
||||
Reference in New Issue
Block a user