Merge "Make sure timestamps attached to encoded media are composition timestamps."
This commit is contained in:
committed by
Android (Google) Code Review
commit
1122fe90f2
@@ -1074,6 +1074,20 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) {
|
||||
break;
|
||||
}
|
||||
|
||||
case FOURCC('c', 't', 't', 's'):
|
||||
{
|
||||
status_t err =
|
||||
mLastTrack->sampleTable->setCompositionTimeToSampleParams(
|
||||
data_offset, chunk_data_size);
|
||||
|
||||
if (err != OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
*offset += chunk_size;
|
||||
break;
|
||||
}
|
||||
|
||||
case FOURCC('s', 't', 's', 's'):
|
||||
{
|
||||
status_t err =
|
||||
|
||||
@@ -307,6 +307,8 @@ status_t SampleIterator::findSampleTime(
|
||||
|
||||
*time = mTTSSampleTime + mTTSDuration * (sampleIndex - mTTSSampleIndex);
|
||||
|
||||
*time += mTable->getCompositionTimeOffset(sampleIndex);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -53,6 +53,8 @@ SampleTable::SampleTable(const sp<DataSource> &source)
|
||||
mNumSampleSizes(0),
|
||||
mTimeToSampleCount(0),
|
||||
mTimeToSample(NULL),
|
||||
mCompositionTimeDeltaEntries(NULL),
|
||||
mNumCompositionTimeDeltaEntries(0),
|
||||
mSyncSampleOffset(-1),
|
||||
mNumSyncSamples(0),
|
||||
mSyncSamples(NULL),
|
||||
@@ -68,6 +70,9 @@ SampleTable::~SampleTable() {
|
||||
delete[] mSyncSamples;
|
||||
mSyncSamples = NULL;
|
||||
|
||||
delete[] mCompositionTimeDeltaEntries;
|
||||
mCompositionTimeDeltaEntries = NULL;
|
||||
|
||||
delete[] mTimeToSample;
|
||||
mTimeToSample = NULL;
|
||||
|
||||
@@ -260,6 +265,51 @@ status_t SampleTable::setTimeToSampleParams(
|
||||
return OK;
|
||||
}
|
||||
|
||||
status_t SampleTable::setCompositionTimeToSampleParams(
|
||||
off64_t data_offset, size_t data_size) {
|
||||
LOGI("There are reordered frames present.");
|
||||
|
||||
if (mCompositionTimeDeltaEntries != NULL || data_size < 8) {
|
||||
return ERROR_MALFORMED;
|
||||
}
|
||||
|
||||
uint8_t header[8];
|
||||
if (mDataSource->readAt(
|
||||
data_offset, header, sizeof(header))
|
||||
< (ssize_t)sizeof(header)) {
|
||||
return ERROR_IO;
|
||||
}
|
||||
|
||||
if (U32_AT(header) != 0) {
|
||||
// Expected version = 0, flags = 0.
|
||||
return ERROR_MALFORMED;
|
||||
}
|
||||
|
||||
size_t numEntries = U32_AT(&header[4]);
|
||||
|
||||
if (data_size != (numEntries + 1) * 8) {
|
||||
return ERROR_MALFORMED;
|
||||
}
|
||||
|
||||
mNumCompositionTimeDeltaEntries = numEntries;
|
||||
mCompositionTimeDeltaEntries = new uint32_t[2 * numEntries];
|
||||
|
||||
if (mDataSource->readAt(
|
||||
data_offset + 8, mCompositionTimeDeltaEntries, numEntries * 8)
|
||||
< (ssize_t)numEntries * 8) {
|
||||
delete[] mCompositionTimeDeltaEntries;
|
||||
mCompositionTimeDeltaEntries = NULL;
|
||||
|
||||
return ERROR_IO;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < 2 * numEntries; ++i) {
|
||||
mCompositionTimeDeltaEntries[i] = ntohl(mCompositionTimeDeltaEntries[i]);
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
status_t SampleTable::setSyncSampleParams(off64_t data_offset, size_t data_size) {
|
||||
if (mSyncSampleOffset >= 0 || data_size < 8) {
|
||||
return ERROR_MALFORMED;
|
||||
@@ -333,6 +383,8 @@ uint32_t abs_difference(uint32_t time1, uint32_t time2) {
|
||||
|
||||
status_t SampleTable::findSampleAtTime(
|
||||
uint32_t req_time, uint32_t *sample_index, uint32_t flags) {
|
||||
// XXX this currently uses decoding time, instead of composition time.
|
||||
|
||||
*sample_index = 0;
|
||||
|
||||
Mutex::Autolock autoLock(mLock);
|
||||
@@ -607,5 +659,26 @@ status_t SampleTable::getMetaDataForSample(
|
||||
return OK;
|
||||
}
|
||||
|
||||
uint32_t SampleTable::getCompositionTimeOffset(uint32_t sampleIndex) const {
|
||||
if (mCompositionTimeDeltaEntries == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t curSample = 0;
|
||||
for (size_t i = 0; i < mNumCompositionTimeDeltaEntries; ++i) {
|
||||
uint32_t sampleCount = mCompositionTimeDeltaEntries[2 * i];
|
||||
|
||||
if (sampleIndex < curSample + sampleCount) {
|
||||
uint32_t sampleDelta = mCompositionTimeDeltaEntries[2 * i + 1];
|
||||
|
||||
return sampleDelta;
|
||||
}
|
||||
|
||||
curSample += sampleCount;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
|
||||
|
||||
@@ -46,6 +46,9 @@ public:
|
||||
|
||||
status_t setTimeToSampleParams(off64_t data_offset, size_t data_size);
|
||||
|
||||
status_t setCompositionTimeToSampleParams(
|
||||
off64_t data_offset, size_t data_size);
|
||||
|
||||
status_t setSyncSampleParams(off64_t data_offset, size_t data_size);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
@@ -104,6 +107,9 @@ private:
|
||||
uint32_t mTimeToSampleCount;
|
||||
uint32_t *mTimeToSample;
|
||||
|
||||
uint32_t *mCompositionTimeDeltaEntries;
|
||||
size_t mNumCompositionTimeDeltaEntries;
|
||||
|
||||
off64_t mSyncSampleOffset;
|
||||
uint32_t mNumSyncSamples;
|
||||
uint32_t *mSyncSamples;
|
||||
@@ -122,6 +128,8 @@ private:
|
||||
|
||||
status_t getSampleSize_l(uint32_t sample_index, size_t *sample_size);
|
||||
|
||||
uint32_t getCompositionTimeOffset(uint32_t sampleIndex) const;
|
||||
|
||||
SampleTable(const SampleTable &);
|
||||
SampleTable &operator=(const SampleTable &);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user