AMRExtractor.cpp revision 7be6407f2ad7f2b0782d195d9f792072c084d6f5
1f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber/*
2f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber * Copyright (C) 2009 The Android Open Source Project
3f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber *
4f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
5f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber * you may not use this file except in compliance with the License.
6f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber * You may obtain a copy of the License at
7f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber *
8f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
9f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber *
10f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber * Unless required by applicable law or agreed to in writing, software
11f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
12f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber * See the License for the specific language governing permissions and
14f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber * limitations under the License.
15f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber */
16f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
17f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber//#define LOG_NDEBUG 0
18f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber#define LOG_TAG "AMRExtractor"
19f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber#include <utils/Log.h>
20f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
2166326a5ee0869f1ee4d136a477e6effba428b3cbAndreas Huber#include "include/AMRExtractor.h"
2266326a5ee0869f1ee4d136a477e6effba428b3cbAndreas Huber
23f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber#include <media/stagefright/DataSource.h>
24f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber#include <media/stagefright/MediaBufferGroup.h>
25f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber#include <media/stagefright/MediaDebug.h>
2618291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber#include <media/stagefright/MediaDefs.h>
27f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber#include <media/stagefright/MediaErrors.h>
28f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber#include <media/stagefright/MediaSource.h>
29f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber#include <media/stagefright/MetaData.h>
30f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber#include <utils/String8.h>
31f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
32f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Hubernamespace android {
33f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
34f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huberclass AMRSource : public MediaSource {
35f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huberpublic:
36bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    AMRSource(const sp<DataSource> &source,
37bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber              const sp<MetaData> &meta,
38bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber              size_t frameSize,
39bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber              bool isWide);
40f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
41f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    virtual status_t start(MetaData *params = NULL);
42f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    virtual status_t stop();
43f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
44f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    virtual sp<MetaData> getFormat();
45f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
46f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    virtual status_t read(
47f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber            MediaBuffer **buffer, const ReadOptions *options = NULL);
48f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
49f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huberprotected:
50f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    virtual ~AMRSource();
51f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
52f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huberprivate:
53f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    sp<DataSource> mDataSource;
54bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    sp<MetaData> mMeta;
55bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    size_t mFrameSize;
56f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    bool mIsWide;
57f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
58f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    off_t mOffset;
59f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    int64_t mCurrentTimeUs;
60f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    bool mStarted;
61f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    MediaBufferGroup *mGroup;
62f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
63f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    AMRSource(const AMRSource &);
64f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    AMRSource &operator=(const AMRSource &);
65f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber};
66f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
67f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber////////////////////////////////////////////////////////////////////////////////
68f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
69bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huberstatic size_t getFrameSize(bool isWide, unsigned FT) {
70bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    static const size_t kFrameSizeNB[8] = {
71bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        95, 103, 118, 134, 148, 159, 204, 244
72bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    };
73bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    static const size_t kFrameSizeWB[9] = {
74bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        132, 177, 253, 285, 317, 365, 397, 461, 477
75bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    };
76bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
77bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    size_t frameSize = isWide ? kFrameSizeWB[FT] : kFrameSizeNB[FT];
78bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
79bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    // Round up bits to bytes and add 1 for the header byte.
80bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    frameSize = (frameSize + 7) / 8 + 1;
81bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
82bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    return frameSize;
83bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber}
84bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
85f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas HuberAMRExtractor::AMRExtractor(const sp<DataSource> &source)
86f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    : mDataSource(source),
87f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber      mInitCheck(NO_INIT) {
88f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    String8 mimeType;
89f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    float confidence;
90bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    if (!SniffAMR(mDataSource, &mimeType, &confidence)) {
91bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        return;
92f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    }
93bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
94bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    mIsWide = (mimeType == MEDIA_MIMETYPE_AUDIO_AMR_WB);
95bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
96bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    mMeta = new MetaData;
97bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    mMeta->setCString(
98bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber            kKeyMIMEType, mIsWide ? MEDIA_MIMETYPE_AUDIO_AMR_WB
99bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                                  : MEDIA_MIMETYPE_AUDIO_AMR_NB);
100bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
101bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    mMeta->setInt32(kKeyChannelCount, 1);
102bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    mMeta->setInt32(kKeySampleRate, mIsWide ? 16000 : 8000);
103bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
104bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    size_t offset = mIsWide ? 9 : 6;
105bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    uint8_t header;
106bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    if (mDataSource->readAt(offset, &header, 1) != 1) {
107bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        return;
108bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    }
109bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
110bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    unsigned FT = (header >> 3) & 0x0f;
111bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
112bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    if (FT > 8 || (!mIsWide && FT > 7)) {
113bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        return;
114bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    }
115bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
116bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    mFrameSize = getFrameSize(mIsWide, FT);
117bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
118bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    off_t streamSize;
119bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    if (mDataSource->getSize(&streamSize) == OK) {
120bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        off_t numFrames = streamSize / mFrameSize;
121bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
122bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        mMeta->setInt64(kKeyDuration, 20000ll * numFrames);
123bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    }
124bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
125bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    mInitCheck = OK;
126f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}
127f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
128f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas HuberAMRExtractor::~AMRExtractor() {
129f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}
130f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
1317be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Hubersp<MetaData> AMRExtractor::getMetaData() {
1327be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber    sp<MetaData> meta = new MetaData;
1337be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
1347be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber    if (mInitCheck != OK) {
1357be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber        return meta;
1367be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber    }
1377be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
1387be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber    meta->setCString(kKeyMIMEType, mIsWide ? "audio/amr-wb" : "audio/amr");
1397be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
1407be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber    return meta;
1417be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber}
1427be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
143f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Hubersize_t AMRExtractor::countTracks() {
144f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    return mInitCheck == OK ? 1 : 0;
145f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}
146f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
147f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Hubersp<MediaSource> AMRExtractor::getTrack(size_t index) {
148f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    if (mInitCheck != OK || index != 0) {
149f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        return NULL;
150f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    }
151f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
152bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    return new AMRSource(mDataSource, mMeta, mFrameSize, mIsWide);
153f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}
154f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
1557e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Hubersp<MetaData> AMRExtractor::getTrackMetaData(size_t index, uint32_t flags) {
156f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    if (mInitCheck != OK || index != 0) {
157f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        return NULL;
158f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    }
159f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
160bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    return mMeta;
161f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}
162f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
163f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber////////////////////////////////////////////////////////////////////////////////
164f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
165bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas HuberAMRSource::AMRSource(
166bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        const sp<DataSource> &source, const sp<MetaData> &meta,
167bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        size_t frameSize, bool isWide)
168f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    : mDataSource(source),
169bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber      mMeta(meta),
170bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber      mFrameSize(frameSize),
171f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber      mIsWide(isWide),
172f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber      mOffset(mIsWide ? 9 : 6),
173f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber      mCurrentTimeUs(0),
174f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber      mStarted(false),
175f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber      mGroup(NULL) {
176f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}
177f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
178f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas HuberAMRSource::~AMRSource() {
179f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    if (mStarted) {
180f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        stop();
181f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    }
182f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}
183f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
184f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huberstatus_t AMRSource::start(MetaData *params) {
185f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    CHECK(!mStarted);
186f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
187f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    mOffset = mIsWide ? 9 : 6;
188f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    mCurrentTimeUs = 0;
189f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    mGroup = new MediaBufferGroup;
190f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    mGroup->add_buffer(new MediaBuffer(128));
191f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    mStarted = true;
192f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
193f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    return OK;
194f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}
195f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
196f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huberstatus_t AMRSource::stop() {
197f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    CHECK(mStarted);
198f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
199f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    delete mGroup;
200f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    mGroup = NULL;
201f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
202f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    mStarted = false;
203f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    return OK;
204f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}
205f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
206f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Hubersp<MetaData> AMRSource::getFormat() {
207bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    return mMeta;
208f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}
209f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
210f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huberstatus_t AMRSource::read(
211f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        MediaBuffer **out, const ReadOptions *options) {
212f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    *out = NULL;
213f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
214bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    int64_t seekTimeUs;
215bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    if (options && options->getSeekTo(&seekTimeUs)) {
216bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        int64_t seekFrame = seekTimeUs / 20000ll;  // 20ms per frame.
217bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        mCurrentTimeUs = seekFrame * 20000ll;
218bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        mOffset = seekFrame * mFrameSize + (mIsWide ? 9 : 6);
219bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    }
220bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
221f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    uint8_t header;
22234769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber    ssize_t n = mDataSource->readAt(mOffset, &header, 1);
223f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
224f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    if (n < 1) {
225f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        return ERROR_IO;
226f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    }
227f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
228f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    MediaBuffer *buffer;
229f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    status_t err = mGroup->acquire_buffer(&buffer);
230f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    if (err != OK) {
231f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        return err;
232f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    }
233f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
234f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    if (header & 0x83) {
235f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        // Padding bits must be 0.
236f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
237f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        return ERROR_MALFORMED;
238f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    }
239f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
240f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    unsigned FT = (header >> 3) & 0x0f;
241f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
242f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    if (FT > 8 || (!mIsWide && FT > 7)) {
243f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        return ERROR_MALFORMED;
244f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    }
245f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
246bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    size_t frameSize = getFrameSize(mIsWide, FT);
247bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    CHECK_EQ(frameSize, mFrameSize);
248f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
24934769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber    n = mDataSource->readAt(mOffset, buffer->data(), frameSize);
250f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
251f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    if (n != (ssize_t)frameSize) {
252f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        buffer->release();
253f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        buffer = NULL;
254f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
255f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        return ERROR_IO;
256f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    }
257f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
258f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    buffer->set_range(0, frameSize);
25948c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber    buffer->meta_data()->setInt64(kKeyTime, mCurrentTimeUs);
260f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
261f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    mOffset += frameSize;
262f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    mCurrentTimeUs += 20000;  // Each frame is 20ms
263f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
264f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    *out = buffer;
265f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
266f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    return OK;
267f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}
268f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
269f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber////////////////////////////////////////////////////////////////////////////////
270f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
271f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huberbool SniffAMR(
272f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence) {
273f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    char header[9];
274f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
27534769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber    if (source->readAt(0, header, sizeof(header)) != sizeof(header)) {
276f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        return false;
277f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    }
278f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
279f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    if (!memcmp(header, "#!AMR\n", 6)) {
28018291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber        *mimeType = MEDIA_MIMETYPE_AUDIO_AMR_NB;
281f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        *confidence = 0.5;
282f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
283f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        return true;
284f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    } else if (!memcmp(header, "#!AMR-WB\n", 9)) {
28518291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber        *mimeType = MEDIA_MIMETYPE_AUDIO_AMR_WB;
286f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        *confidence = 0.5;
287f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
288f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        return true;
289f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    }
290f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
291f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    return false;
292f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}
293f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
294f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}  // namespace android
295