Bug 1065850 - Read as little as possible to get the MP4 track metadata; r=rillian

This commit is contained in:
Anthony Jones 2014-09-15 11:16:09 +12:00
parent 84dcaeb8a2
commit 1081d0fd6f
2 changed files with 40 additions and 67 deletions

View File

@ -48,7 +48,6 @@ public:
int32_t timeScale,
const sp<SampleTable> &sampleTable,
Vector<SidxEntry> &sidx,
off64_t firstMoofOffset,
MPEG4Extractor::TrackExtends &trackExtends);
virtual status_t start(MetaData *params = NULL);
@ -73,6 +72,7 @@ private:
uint32_t mCurrentSampleIndex;
uint32_t mCurrentFragmentIndex;
Vector<SidxEntry> &mSegments;
bool mLookedForMoof;
off64_t mFirstMoofOffset;
off64_t mCurrentMoofOffset;
off64_t mNextMoofOffset;
@ -111,6 +111,7 @@ private:
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();
struct TrackFragmentData {
TrackFragmentData(): mPresent(false), mFlags(0), mBaseMediaDecodeTime(0) {}
@ -349,7 +350,6 @@ static bool AdjustChannelsAndRate(uint32_t fourcc, uint32_t *channels, uint32_t
MPEG4Extractor::MPEG4Extractor(const sp<DataSource> &source)
: mSidxDuration(0),
mMoofOffset(0),
mDataSource(source),
mInitCheck(NO_INIT),
mHasVideo(false),
@ -386,9 +386,7 @@ MPEG4Extractor::~MPEG4Extractor() {
}
uint32_t MPEG4Extractor::flags() const {
return CAN_PAUSE |
((mMoofOffset == 0 || mSidxEntries.size() != 0) ?
(CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK) : 0);
return CAN_PAUSE | CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK;
}
sp<MetaData> MPEG4Extractor::getMetaData() {
@ -439,38 +437,6 @@ sp<MetaData> MPEG4Extractor::getTrackMetaData(
return NULL;
}
if ((flags & kIncludeExtensiveMetaData)
&& !track->includes_expensive_metadata) {
track->includes_expensive_metadata = true;
const char *mime;
CHECK(track->meta->findCString(kKeyMIMEType, &mime));
if (!strncasecmp("video/", mime, 6)) {
if (mMoofOffset > 0) {
int64_t duration;
if (track->meta->findInt64(kKeyDuration, &duration)) {
// nothing fancy, just pick a frame near 1/4th of the duration
track->meta->setInt64(
kKeyThumbnailTime, duration / 4);
}
} else {
uint32_t sampleIndex;
uint32_t sampleTime;
if (track->sampleTable->findThumbnailSample(&sampleIndex) == OK
&& track->sampleTable->getMetaDataForSample(
sampleIndex, NULL /* offset */, NULL /* size */,
&sampleTime) == OK) {
if (!track->timescale) {
return NULL;
}
track->meta->setInt64(
kKeyThumbnailTime,
((int64_t)sampleTime * 1000000) / track->timescale);
}
}
}
}
return track->meta;
}
@ -488,27 +454,9 @@ status_t MPEG4Extractor::readMetaData() {
}
off64_t offset = 0;
status_t err = OK;
while (true) {
uint32_t hdr[2];
if (mDataSource->readAt(offset, hdr, 8) < 8) {
break;
}
uint32_t chunk_type = ntohl(hdr[1]);
if (chunk_type == FOURCC('m', 'd', 'a', 't') && mFirstTrack) {
break;
}
if (chunk_type == FOURCC('m', 'o', 'o', 'f')) {
// store the offset of the first segment
mMoofOffset = offset;
break;
}
status_t err;
while (!mFirstTrack) {
err = parseChunk(&offset, 0);
if (err != OK &&
chunk_type != FOURCC('s', 'i', 'd', 'x') &&
chunk_type != FOURCC('m', 'o', 'o', 'v')) {
break;
}
}
if (mInitCheck == OK) {
@ -2253,7 +2201,7 @@ sp<MediaSource> MPEG4Extractor::getTrack(size_t index) {
return new MPEG4Source(
track->meta, mDataSource, track->timescale, track->sampleTable,
mSidxEntries, mMoofOffset, mTrackExtends);
mSidxEntries, mTrackExtends);
}
// static
@ -2412,7 +2360,6 @@ MPEG4Source::MPEG4Source(
int32_t timeScale,
const sp<SampleTable> &sampleTable,
Vector<SidxEntry> &sidx,
off64_t firstMoofOffset,
MPEG4Extractor::TrackExtends &trackExtends)
: mFormat(format),
mDataSource(dataSource),
@ -2421,8 +2368,9 @@ MPEG4Source::MPEG4Source(
mCurrentSampleIndex(0),
mCurrentFragmentIndex(0),
mSegments(sidx),
mFirstMoofOffset(firstMoofOffset),
mCurrentMoofOffset(firstMoofOffset),
mLookedForMoof(false),
mFirstMoofOffset(0),
mCurrentMoofOffset(0),
mCurrentTime(0),
mCurrentSampleInfoAllocSize(0),
mCurrentSampleInfoSizes(NULL),
@ -2470,11 +2418,6 @@ MPEG4Source::MPEG4Source(
}
CHECK(format->findInt32(kKeyTrackID, &mTrackId));
if (mFirstMoofOffset != 0) {
off64_t offset = mFirstMoofOffset;
parseChunk(&offset);
}
}
MPEG4Source::~MPEG4Source() {
@ -3131,12 +3074,43 @@ size_t MPEG4Source::parseNALSize(const uint8_t *data) const {
return 0;
}
void MPEG4Source::lookForMoof() {
off64_t offset = 0;
off64_t size;
while (true) {
uint32_t hdr[2];
auto x = mDataSource->readAt(offset, hdr, 8);
if (x < 8) {
break;
}
uint32_t chunk_size = ntohl(hdr[0]);
uint32_t chunk_type = ntohl(hdr[1]);
char chunk[5];
MakeFourCCString(chunk_type, chunk);
if (chunk_type == FOURCC('m', 'o', 'o', 'f')) {
mFirstMoofOffset = mCurrentMoofOffset = offset;
parseChunk(&offset);
break;
}
if (chunk_type == FOURCC('m', 'd', 'a', 't')) {
break;
}
offset += chunk_size;
}
}
status_t MPEG4Source::read(
MediaBuffer **out, const ReadOptions *options) {
Mutex::Autolock autoLock(mLock);
CHECK(mStarted);
if (!mLookedForMoof) {
mLookedForMoof = true;
lookForMoof();
}
if (mFirstMoofOffset > 0) {
return fragmentedRead(out, options);
}

View File

@ -93,7 +93,6 @@ private:
Vector<SidxEntry> mSidxEntries;
uint64_t mSidxDuration;
off64_t mMoofOffset;
Vector<PsshInfo> mPssh;