Bug 1098126 - Remove duplication in MP4 demuxer seek; r=mattwoodrow
--- a/media/libstagefright/frameworks/av/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/frameworks/av/media/libstagefright/MPEG4Extractor.cpp
@@ -107,16 +107,17 @@ private:
size_t parseNALSize(const uint8_t *data) const;
status_t parseChunk(off64_t *offset);
status_t parseTrackFragmentData(off64_t offset, off64_t size);
status_t parseTrackFragmentHeader(off64_t offset, off64_t size);
status_t parseTrackFragmentRun(off64_t offset, off64_t size);
status_t parseSampleAuxiliaryInformationSizes(off64_t offset, off64_t size);
status_t parseSampleAuxiliaryInformationOffsets(off64_t offset, off64_t size);
void lookForMoof();
+ status_t moveToNextFragment();
struct TrackFragmentHeaderInfo {
enum Flags {
kBaseDataOffsetPresent = 0x01,
kSampleDescriptionIndexPresent = 0x02,
kDefaultSampleDurationPresent = 0x08,
kDefaultSampleSizePresent = 0x10,
kDefaultSampleFlagsPresent = 0x20,
@@ -3578,35 +3579,59 @@ status_t MPEG4Source::read(
*out = mBuffer;
mBuffer = NULL;
return OK;
}
}
+status_t MPEG4Source::moveToNextFragment() {
+ off64_t nextMoof = mNextMoofOffset;
+ mCurrentSamples.clear();
+ mDeferredSaio.clear();
+ mDeferredSaiz.clear();
+ mCurrentSampleIndex = 0;
+ uint32_t hdr[2];
+ do {
+ if (mDataSource->readAt(nextMoof, hdr, 8) < 8) {
+ return ERROR_END_OF_STREAM;
+ }
+ uint64_t chunk_size = ntohl(hdr[0]);
+ uint32_t chunk_type = ntohl(hdr[1]);
+
+ // Skip over anything that isn't a moof
+ if (chunk_type != FOURCC('m', 'o', 'o', 'f')) {
+ nextMoof += chunk_size;
+ continue;
+ }
+ mCurrentMoofOffset = nextMoof;
+ status_t ret = parseChunk(&nextMoof);
+ if (ret != OK) {
+ return ret;
+ }
+ } while (mCurrentSamples.size() == 0);
+ return OK;
+}
+
status_t MPEG4Source::fragmentedRead(
MediaBuffer **out, const ReadOptions *options) {
ALOGV("MPEG4Source::fragmentedRead");
CHECK(mStarted);
*out = NULL;
int64_t targetSampleTimeUs = -1;
int64_t seekTimeUs;
ReadOptions::SeekMode mode;
if (options && options->getSeekTo(&seekTimeUs, &mode)) {
- mCurrentSamples.clear();
- mDeferredSaio.clear();
- mDeferredSaiz.clear();
- mCurrentSampleIndex = 0;
int numSidxEntries = mSegments.size();
if (numSidxEntries != 0) {
int64_t totalTime = 0;
off64_t totalOffset = mFirstMoofOffset;
for (int i = 0; i < numSidxEntries; i++) {
const SidxEntry *se = &mSegments[i];
if (totalTime + se->mDurationUs > seekTimeUs) {
// The requested time is somewhere in this segment
@@ -3619,65 +3644,44 @@ status_t MPEG4Source::fragmentedRead(
totalOffset += se->mSize;
}
break;
}
totalTime += se->mDurationUs;
totalOffset += se->mSize;
}
mCurrentMoofOffset = totalOffset;
+ mCurrentSamples.clear();
+ mDeferredSaio.clear();
+ mDeferredSaiz.clear();
+ mCurrentSampleIndex = 0;
+ mCurrentTime = totalTime * mTimescale / 1000000ll;
mNextMoofOffset = totalOffset;
- mCurrentTime = totalTime * mTimescale / 1000000ll;
}
else {
mNextMoofOffset = mFirstMoofOffset;
uint32_t seekTime = (int32_t) ((seekTimeUs * mTimescale) / 1000000ll);
while (true) {
-
- uint32_t hdr[2];
- do {
- off64_t moofOffset = mNextMoofOffset; // lastSample.offset + lastSample.size;
- if (mDataSource->readAt(moofOffset, hdr, 8) < 8) {
- ALOGV("Seek ERROR_END_OF_STREAM\n");
- return ERROR_END_OF_STREAM;
- }
- uint64_t chunk_size = ntohl(hdr[0]);
- uint32_t chunk_type = ntohl(hdr[1]);
- char chunk[5];
- MakeFourCCString(chunk_type, chunk);
-
- // If we're pointing to a segment type or sidx box then we skip them.
- if (chunk_type != FOURCC('m', 'o', 'o', 'f')) {
- mNextMoofOffset += chunk_size;
- continue;
- }
- mCurrentMoofOffset = moofOffset;
- status_t ret = parseChunk(&moofOffset);
- if (ret != OK) {
- return ret;
- }
- } while (mCurrentSamples.size() == 0);
+ status_t ret = moveToNextFragment();
+ if (ret != OK) {
+ return ret;
+ }
uint32_t time = mCurrentTime;
int i;
for (i = 0; i < mCurrentSamples.size() && time <= seekTime; i++) {
const Sample *smpl = &mCurrentSamples[i];
if (smpl->isSync()) {
mCurrentSampleIndex = i;
mCurrentTime = time;
}
time += smpl->duration;
}
if (i != mCurrentSamples.size()) {
break;
}
-
- mCurrentSamples.clear();
- mDeferredSaio.clear();
- mDeferredSaiz.clear();
- mCurrentSampleIndex = 0;
}
ALOGV("Seeking offset %d; %ldus\n", mCurrentTime - seekTime,
(((int64_t) mCurrentTime - seekTime) * 1000000ll) / mTimescale);
}
if (mBuffer != NULL) {
mBuffer->release();
mBuffer = NULL;
@@ -3692,42 +3696,20 @@ status_t MPEG4Source::fragmentedRead(
int64_t cts = 0;
uint32_t duration = 0;
bool isSyncSample = false;
bool newBuffer = false;
if (mBuffer == NULL) {
newBuffer = true;
if (mCurrentSampleIndex >= mCurrentSamples.size()) {
- // move to next fragment
- off64_t nextMoof = mNextMoofOffset; // lastSample.offset + lastSample.size;
- mCurrentSamples.clear();
- mDeferredSaio.clear();
- mDeferredSaiz.clear();
- mCurrentSampleIndex = 0;
- uint32_t hdr[2];
- do {
- if (mDataSource->readAt(nextMoof, hdr, 8) < 8) {
- return ERROR_END_OF_STREAM;
- }
- uint64_t chunk_size = ntohl(hdr[0]);
- uint32_t chunk_type = ntohl(hdr[1]);
-
- // If we're pointing to a segment type or sidx box then we skip them.
- if (chunk_type == FOURCC('s', 't', 'y', 'p') ||
- chunk_type == FOURCC('s', 'i', 'd', 'x')) {
- nextMoof += chunk_size;
- continue;
- }
- mCurrentMoofOffset = nextMoof;
- status_t ret = parseChunk(&nextMoof);
- if (ret != OK) {
- return ret;
- }
- } while (mCurrentSamples.size() == 0);
+ status_t ret = moveToNextFragment();
+ if (ret != OK) {
+ return ret;
+ }
}
const Sample *smpl = &mCurrentSamples[mCurrentSampleIndex];
offset = smpl->offset;
size = smpl->size;
dts = mCurrentTime;
cts = mCurrentTime + smpl->ctsOffset;
duration = smpl->duration;