Merge "Support .avi tracks that have a sample size of 1, i.e. samples != chunks"

This commit is contained in:
Andreas Huber
2011-09-13 11:37:22 -07:00
committed by Android (Google) Code Review
2 changed files with 56 additions and 14 deletions

View File

@@ -117,14 +117,12 @@ status_t AVIExtractor::AVISource::read(
} }
} }
int64_t timeUs =
(mSampleIndex * 1000000ll * mTrack.mRate) / mTrack.mScale;
off64_t offset; off64_t offset;
size_t size; size_t size;
bool isKey; bool isKey;
int64_t timeUs;
status_t err = mExtractor->getSampleInfo( status_t err = mExtractor->getSampleInfo(
mTrackIndex, mSampleIndex, &offset, &size, &isKey); mTrackIndex, mSampleIndex, &offset, &size, &isKey, &timeUs);
++mSampleIndex; ++mSampleIndex;
@@ -396,6 +394,8 @@ status_t AVIExtractor::parseStreamHeader(off64_t offset, size_t size) {
uint32_t rate = U32LE_AT(&data[20]); uint32_t rate = U32LE_AT(&data[20]);
uint32_t scale = U32LE_AT(&data[24]); uint32_t scale = U32LE_AT(&data[24]);
uint32_t sampleSize = U32LE_AT(&data[44]);
const char *mime = NULL; const char *mime = NULL;
Track::Kind kind = Track::OTHER; Track::Kind kind = Track::OTHER;
@@ -427,6 +427,7 @@ status_t AVIExtractor::parseStreamHeader(off64_t offset, size_t size) {
track->mMeta = meta; track->mMeta = meta;
track->mRate = rate; track->mRate = rate;
track->mScale = scale; track->mScale = scale;
track->mBytesPerSample = sampleSize;
track->mKind = kind; track->mKind = kind;
track->mNumSyncSamples = 0; track->mNumSyncSamples = 0;
track->mThumbnailSampleSize = 0; track->mThumbnailSampleSize = 0;
@@ -612,11 +613,12 @@ status_t AVIExtractor::parseIndex(off64_t offset, size_t size) {
off64_t offset; off64_t offset;
size_t size; size_t size;
bool isKey; bool isKey;
status_t err = getSampleInfo(0, 0, &offset, &size, &isKey); int64_t timeUs;
status_t err = getSampleInfo(0, 0, &offset, &size, &isKey, &timeUs);
if (err != OK) { if (err != OK) {
mOffsetsAreAbsolute = !mOffsetsAreAbsolute; mOffsetsAreAbsolute = !mOffsetsAreAbsolute;
err = getSampleInfo(0, 0, &offset, &size, &isKey); err = getSampleInfo(0, 0, &offset, &size, &isKey, &timeUs);
if (err != OK) { if (err != OK) {
return err; return err;
@@ -630,8 +632,9 @@ status_t AVIExtractor::parseIndex(off64_t offset, size_t size) {
for (size_t i = 0; i < mTracks.size(); ++i) { for (size_t i = 0; i < mTracks.size(); ++i) {
Track *track = &mTracks.editItemAt(i); Track *track = &mTracks.editItemAt(i);
int64_t durationUs = int64_t durationUs;
(track->mSamples.size() * 1000000ll * track->mRate) / track->mScale; CHECK_EQ((status_t)OK,
getSampleTime(i, track->mSamples.size() - 1, &durationUs));
LOGV("track %d duration = %.2f secs", i, durationUs / 1E6); LOGV("track %d duration = %.2f secs", i, durationUs / 1E6);
@@ -645,9 +648,10 @@ status_t AVIExtractor::parseIndex(off64_t offset, size_t size) {
if (!strncasecmp("video/", mime.c_str(), 6) if (!strncasecmp("video/", mime.c_str(), 6)
&& track->mThumbnailSampleIndex >= 0) { && track->mThumbnailSampleIndex >= 0) {
int64_t thumbnailTimeUs = int64_t thumbnailTimeUs;
(track->mThumbnailSampleIndex * 1000000ll * track->mRate) CHECK_EQ((status_t)OK,
/ track->mScale; getSampleTime(i, track->mThumbnailSampleIndex,
&thumbnailTimeUs));
track->mMeta->setInt64(kKeyThumbnailTime, thumbnailTimeUs); track->mMeta->setInt64(kKeyThumbnailTime, thumbnailTimeUs);
@@ -659,6 +663,21 @@ status_t AVIExtractor::parseIndex(off64_t offset, size_t size) {
} }
} }
} }
if (track->mBytesPerSample != 0) {
// Assume all chunks are the same size for now.
off64_t offset;
size_t size;
bool isKey;
int64_t sampleTimeUs;
CHECK_EQ((status_t)OK,
getSampleInfo(
i, 0,
&offset, &size, &isKey, &sampleTimeUs));
track->mRate *= size / track->mBytesPerSample;
}
} }
mFoundIndex = true; mFoundIndex = true;
@@ -720,7 +739,9 @@ status_t AVIExtractor::addMPEG4CodecSpecificData(size_t trackIndex) {
off64_t offset; off64_t offset;
size_t size; size_t size;
bool isKey; bool isKey;
status_t err = getSampleInfo(trackIndex, 0, &offset, &size, &isKey); int64_t timeUs;
status_t err =
getSampleInfo(trackIndex, 0, &offset, &size, &isKey, &timeUs);
if (err != OK) { if (err != OK) {
return err; return err;
@@ -762,7 +783,8 @@ status_t AVIExtractor::addMPEG4CodecSpecificData(size_t trackIndex) {
status_t AVIExtractor::getSampleInfo( status_t AVIExtractor::getSampleInfo(
size_t trackIndex, size_t sampleIndex, size_t trackIndex, size_t sampleIndex,
off64_t *offset, size_t *size, bool *isKey) { off64_t *offset, size_t *size, bool *isKey,
int64_t *sampleTimeUs) {
if (trackIndex >= mTracks.size()) { if (trackIndex >= mTracks.size()) {
return -ERANGE; return -ERANGE;
} }
@@ -801,9 +823,20 @@ status_t AVIExtractor::getSampleInfo(
*isKey = info.mIsKey; *isKey = info.mIsKey;
*sampleTimeUs = (sampleIndex * 1000000ll * track.mRate) / track.mScale;
return OK; return OK;
} }
status_t AVIExtractor::getSampleTime(
size_t trackIndex, size_t sampleIndex, int64_t *sampleTimeUs) {
off64_t offset;
size_t size;
bool isKey;
return getSampleInfo(
trackIndex, sampleIndex, &offset, &size, &isKey, sampleTimeUs);
}
status_t AVIExtractor::getSampleIndexAtTime( status_t AVIExtractor::getSampleIndexAtTime(
size_t trackIndex, size_t trackIndex,
int64_t timeUs, MediaSource::ReadOptions::SeekMode mode, int64_t timeUs, MediaSource::ReadOptions::SeekMode mode,

View File

@@ -54,6 +54,11 @@ private:
uint32_t mRate; uint32_t mRate;
uint32_t mScale; uint32_t mScale;
// If bytes per sample == 0, each chunk represents a single sample,
// otherwise each chunk should me a multiple of bytes-per-sample in
// size.
uint32_t mBytesPerSample;
enum Kind { enum Kind {
AUDIO, AUDIO,
VIDEO, VIDEO,
@@ -84,7 +89,11 @@ private:
status_t getSampleInfo( status_t getSampleInfo(
size_t trackIndex, size_t sampleIndex, size_t trackIndex, size_t sampleIndex,
off64_t *offset, size_t *size, bool *isKey); off64_t *offset, size_t *size, bool *isKey,
int64_t *sampleTimeUs);
status_t getSampleTime(
size_t trackIndex, size_t sampleIndex, int64_t *sampleTimeUs);
status_t getSampleIndexAtTime( status_t getSampleIndexAtTime(
size_t trackIndex, size_t trackIndex,