summaryrefslogtreecommitdiffstats
path: root/media/libstagefright/AMRExtractor.cpp
diff options
context:
space:
mode:
authorAndreas Huber <andih@google.com>2009-11-20 09:32:46 -0800
committerAndreas Huber <andih@google.com>2009-11-23 10:44:30 -0800
commitbfa6b2d7a1be1832ac40ed90aece1834f720b5c6 (patch)
tree5b4948c52fde583d593d088ffc4a7f772c904a86 /media/libstagefright/AMRExtractor.cpp
parentbf89c099fc97717e3008a481aeddc76c1ac5e00d (diff)
downloadframeworks_av-bfa6b2d7a1be1832ac40ed90aece1834f720b5c6.zip
frameworks_av-bfa6b2d7a1be1832ac40ed90aece1834f720b5c6.tar.gz
frameworks_av-bfa6b2d7a1be1832ac40ed90aece1834f720b5c6.tar.bz2
Squashed commit of the following:
commit 1efc38dc3c33fef57b759002db3965ed07a28cb0 Author: Andreas Huber <andih@google.com> Date: Thu Nov 19 14:36:14 2009 -0800 Sending the SEEK-COMPLETE notification temporarily broke seeking backwards in time behaviour. This is now fixed. Also, get rid of the semi-random delay after posting buffers to surface flinger in favour of delaying the buffer release until the next frame is displayed. commit 51973062eb5ee63fd64b845d72bac517cc3369cf Author: Andreas Huber <andih@google.com> Date: Wed Nov 18 14:01:43 2009 -0800 Fix one more unit test, properly send seek-complete notification only after seek actually completed. commit cb22250b34b1fcfe1bf459723a761fd003950229 Author: Andreas Huber <andih@google.com> Date: Wed Nov 18 12:31:36 2009 -0800 Fix seek-while-paused in AwesomePlayer, revert to using FileSource if MmapSource fails. commit 25eb9241138ddf7bb27ce90657116c5f8a94d880 Author: Andreas Huber <andih@google.com> Date: Wed Nov 18 12:30:40 2009 -0800 Support seeking and duration in AMRExtractor, assuming all frames are the same size. commit 44192f2ebb7ea3bbd3ba5910025692dbc6a08faa Author: Andreas Huber <andih@google.com> Date: Wed Nov 18 10:21:44 2009 -0800 MediaPlayerImpl is dead, long live AwesomePlayer. commit c5b52d3c0674f5dc94db506afbce52401cceddac Author: Andreas Huber <andih@google.com> Date: Wed Nov 18 09:42:23 2009 -0800 New implementation of the stagefright mediaplayer.
Diffstat (limited to 'media/libstagefright/AMRExtractor.cpp')
-rw-r--r--media/libstagefright/AMRExtractor.cpp106
1 files changed, 74 insertions, 32 deletions
diff --git a/media/libstagefright/AMRExtractor.cpp b/media/libstagefright/AMRExtractor.cpp
index 1e3c5a4..bdd7550 100644
--- a/media/libstagefright/AMRExtractor.cpp
+++ b/media/libstagefright/AMRExtractor.cpp
@@ -33,7 +33,10 @@ namespace android {
class AMRSource : public MediaSource {
public:
- AMRSource(const sp<DataSource> &source, bool isWide);
+ AMRSource(const sp<DataSource> &source,
+ const sp<MetaData> &meta,
+ size_t frameSize,
+ bool isWide);
virtual status_t start(MetaData *params = NULL);
virtual status_t stop();
@@ -48,6 +51,8 @@ protected:
private:
sp<DataSource> mDataSource;
+ sp<MetaData> mMeta;
+ size_t mFrameSize;
bool mIsWide;
off_t mOffset;
@@ -61,15 +66,63 @@ private:
////////////////////////////////////////////////////////////////////////////////
+static size_t getFrameSize(bool isWide, unsigned FT) {
+ static const size_t kFrameSizeNB[8] = {
+ 95, 103, 118, 134, 148, 159, 204, 244
+ };
+ static const size_t kFrameSizeWB[9] = {
+ 132, 177, 253, 285, 317, 365, 397, 461, 477
+ };
+
+ size_t frameSize = isWide ? kFrameSizeWB[FT] : kFrameSizeNB[FT];
+
+ // Round up bits to bytes and add 1 for the header byte.
+ frameSize = (frameSize + 7) / 8 + 1;
+
+ return frameSize;
+}
+
AMRExtractor::AMRExtractor(const sp<DataSource> &source)
: mDataSource(source),
mInitCheck(NO_INIT) {
String8 mimeType;
float confidence;
- if (SniffAMR(mDataSource, &mimeType, &confidence)) {
- mInitCheck = OK;
- mIsWide = (mimeType == MEDIA_MIMETYPE_AUDIO_AMR_WB);
+ if (!SniffAMR(mDataSource, &mimeType, &confidence)) {
+ return;
}
+
+ mIsWide = (mimeType == MEDIA_MIMETYPE_AUDIO_AMR_WB);
+
+ mMeta = new MetaData;
+ mMeta->setCString(
+ kKeyMIMEType, mIsWide ? MEDIA_MIMETYPE_AUDIO_AMR_WB
+ : MEDIA_MIMETYPE_AUDIO_AMR_NB);
+
+ mMeta->setInt32(kKeyChannelCount, 1);
+ mMeta->setInt32(kKeySampleRate, mIsWide ? 16000 : 8000);
+
+ size_t offset = mIsWide ? 9 : 6;
+ uint8_t header;
+ if (mDataSource->readAt(offset, &header, 1) != 1) {
+ return;
+ }
+
+ unsigned FT = (header >> 3) & 0x0f;
+
+ if (FT > 8 || (!mIsWide && FT > 7)) {
+ return;
+ }
+
+ mFrameSize = getFrameSize(mIsWide, FT);
+
+ off_t streamSize;
+ if (mDataSource->getSize(&streamSize) == OK) {
+ off_t numFrames = streamSize / mFrameSize;
+
+ mMeta->setInt64(kKeyDuration, 20000ll * numFrames);
+ }
+
+ mInitCheck = OK;
}
AMRExtractor::~AMRExtractor() {
@@ -84,7 +137,7 @@ sp<MediaSource> AMRExtractor::getTrack(size_t index) {
return NULL;
}
- return new AMRSource(mDataSource, mIsWide);
+ return new AMRSource(mDataSource, mMeta, mFrameSize, mIsWide);
}
sp<MetaData> AMRExtractor::getTrackMetaData(size_t index, uint32_t flags) {
@@ -92,26 +145,17 @@ sp<MetaData> AMRExtractor::getTrackMetaData(size_t index, uint32_t flags) {
return NULL;
}
- return makeAMRFormat(mIsWide);
-}
-
-// static
-sp<MetaData> AMRExtractor::makeAMRFormat(bool isWide) {
- sp<MetaData> meta = new MetaData;
- meta->setCString(
- kKeyMIMEType, isWide ? MEDIA_MIMETYPE_AUDIO_AMR_WB
- : MEDIA_MIMETYPE_AUDIO_AMR_NB);
-
- meta->setInt32(kKeyChannelCount, 1);
- meta->setInt32(kKeySampleRate, isWide ? 16000 : 8000);
-
- return meta;
+ return mMeta;
}
////////////////////////////////////////////////////////////////////////////////
-AMRSource::AMRSource(const sp<DataSource> &source, bool isWide)
+AMRSource::AMRSource(
+ const sp<DataSource> &source, const sp<MetaData> &meta,
+ size_t frameSize, bool isWide)
: mDataSource(source),
+ mMeta(meta),
+ mFrameSize(frameSize),
mIsWide(isWide),
mOffset(mIsWide ? 9 : 6),
mCurrentTimeUs(0),
@@ -148,13 +192,20 @@ status_t AMRSource::stop() {
}
sp<MetaData> AMRSource::getFormat() {
- return AMRExtractor::makeAMRFormat(mIsWide);
+ return mMeta;
}
status_t AMRSource::read(
MediaBuffer **out, const ReadOptions *options) {
*out = NULL;
+ int64_t seekTimeUs;
+ if (options && options->getSeekTo(&seekTimeUs)) {
+ int64_t seekFrame = seekTimeUs / 20000ll; // 20ms per frame.
+ mCurrentTimeUs = seekFrame * 20000ll;
+ mOffset = seekFrame * mFrameSize + (mIsWide ? 9 : 6);
+ }
+
uint8_t header;
ssize_t n = mDataSource->readAt(mOffset, &header, 1);
@@ -180,17 +231,8 @@ status_t AMRSource::read(
return ERROR_MALFORMED;
}
- static const size_t kFrameSizeNB[8] = {
- 95, 103, 118, 134, 148, 159, 204, 244
- };
- static const size_t kFrameSizeWB[9] = {
- 132, 177, 253, 285, 317, 365, 397, 461, 477
- };
-
- size_t frameSize = mIsWide ? kFrameSizeWB[FT] : kFrameSizeNB[FT];
-
- // Round up bits to bytes and add 1 for the header byte.
- frameSize = (frameSize + 7) / 8 + 1;
+ size_t frameSize = getFrameSize(mIsWide, FT);
+ CHECK_EQ(frameSize, mFrameSize);
n = mDataSource->readAt(mOffset, buffer->data(), frameSize);