From 7de73f4eb68f3aa478e19ba05a13bc84296f9894 Mon Sep 17 00:00:00 2001 From: Andreas Huber Date: Tue, 13 Sep 2011 11:12:57 -0700 Subject: Support .avi tracks that have a sample size of 1, i.e. samples != chunks Assume for now that all chunks are the same size, i.e. have the same number of samples. Change-Id: Ib8a7dfeb16cc3e5be199ff9d98b68dd0b9c23eb8 related-to-bug: 5279872 --- media/libstagefright/AVIExtractor.cpp | 59 ++++++++++++++++++++++------- media/libstagefright/include/AVIExtractor.h | 11 +++++- 2 files changed, 56 insertions(+), 14 deletions(-) (limited to 'media') diff --git a/media/libstagefright/AVIExtractor.cpp b/media/libstagefright/AVIExtractor.cpp index 62d17da..4e46414 100644 --- a/media/libstagefright/AVIExtractor.cpp +++ b/media/libstagefright/AVIExtractor.cpp @@ -117,14 +117,12 @@ status_t AVIExtractor::AVISource::read( } } - int64_t timeUs = - (mSampleIndex * 1000000ll * mTrack.mRate) / mTrack.mScale; - off64_t offset; size_t size; bool isKey; + int64_t timeUs; status_t err = mExtractor->getSampleInfo( - mTrackIndex, mSampleIndex, &offset, &size, &isKey); + mTrackIndex, mSampleIndex, &offset, &size, &isKey, &timeUs); ++mSampleIndex; @@ -396,6 +394,8 @@ status_t AVIExtractor::parseStreamHeader(off64_t offset, size_t size) { uint32_t rate = U32LE_AT(&data[20]); uint32_t scale = U32LE_AT(&data[24]); + uint32_t sampleSize = U32LE_AT(&data[44]); + const char *mime = NULL; Track::Kind kind = Track::OTHER; @@ -427,6 +427,7 @@ status_t AVIExtractor::parseStreamHeader(off64_t offset, size_t size) { track->mMeta = meta; track->mRate = rate; track->mScale = scale; + track->mBytesPerSample = sampleSize; track->mKind = kind; track->mNumSyncSamples = 0; track->mThumbnailSampleSize = 0; @@ -612,11 +613,12 @@ status_t AVIExtractor::parseIndex(off64_t offset, size_t size) { off64_t offset; size_t size; 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) { mOffsetsAreAbsolute = !mOffsetsAreAbsolute; - err = getSampleInfo(0, 0, &offset, &size, &isKey); + err = getSampleInfo(0, 0, &offset, &size, &isKey, &timeUs); if (err != OK) { 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) { Track *track = &mTracks.editItemAt(i); - int64_t durationUs = - (track->mSamples.size() * 1000000ll * track->mRate) / track->mScale; + int64_t durationUs; + CHECK_EQ((status_t)OK, + getSampleTime(i, track->mSamples.size() - 1, &durationUs)); 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) && track->mThumbnailSampleIndex >= 0) { - int64_t thumbnailTimeUs = - (track->mThumbnailSampleIndex * 1000000ll * track->mRate) - / track->mScale; + int64_t thumbnailTimeUs; + CHECK_EQ((status_t)OK, + getSampleTime(i, track->mThumbnailSampleIndex, + &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; @@ -720,7 +739,9 @@ status_t AVIExtractor::addMPEG4CodecSpecificData(size_t trackIndex) { off64_t offset; size_t size; 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) { return err; @@ -762,7 +783,8 @@ status_t AVIExtractor::addMPEG4CodecSpecificData(size_t trackIndex) { status_t AVIExtractor::getSampleInfo( 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()) { return -ERANGE; } @@ -801,9 +823,20 @@ status_t AVIExtractor::getSampleInfo( *isKey = info.mIsKey; + *sampleTimeUs = (sampleIndex * 1000000ll * track.mRate) / track.mScale; + 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( size_t trackIndex, int64_t timeUs, MediaSource::ReadOptions::SeekMode mode, diff --git a/media/libstagefright/include/AVIExtractor.h b/media/libstagefright/include/AVIExtractor.h index 375a94d..b575347 100644 --- a/media/libstagefright/include/AVIExtractor.h +++ b/media/libstagefright/include/AVIExtractor.h @@ -54,6 +54,11 @@ private: uint32_t mRate; 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 { AUDIO, VIDEO, @@ -84,7 +89,11 @@ private: status_t getSampleInfo( 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( size_t trackIndex, -- cgit v1.1