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
23f1d5aa162c02a16b7195a43a9bcea4d592600ac4James Dong#include <media/stagefright/foundation/ADebug.h>
24f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber#include <media/stagefright/DataSource.h>
25f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber#include <media/stagefright/MediaBufferGroup.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,
3880f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang              bool isWide,
3980f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang              const off64_t *offset_table,
4080f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang              size_t offset_table_length);
41f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
42f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    virtual status_t start(MetaData *params = NULL);
43f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    virtual status_t stop();
44f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
45f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    virtual sp<MetaData> getFormat();
46f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
47f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    virtual status_t read(
48f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber            MediaBuffer **buffer, const ReadOptions *options = NULL);
49f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
50f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huberprotected:
51f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    virtual ~AMRSource();
52f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
53f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huberprivate:
54f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    sp<DataSource> mDataSource;
55bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    sp<MetaData> mMeta;
56f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    bool mIsWide;
57f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
58c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t mOffset;
59f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    int64_t mCurrentTimeUs;
60f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    bool mStarted;
61f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    MediaBufferGroup *mGroup;
62f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
6380f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang    off64_t mOffsetTable[OFFSET_TABLE_LEN];
6480f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang    size_t mOffsetTableLength;
6580f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang
66f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    AMRSource(const AMRSource &);
67f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    AMRSource &operator=(const AMRSource &);
68f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber};
69f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
70f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber////////////////////////////////////////////////////////////////////////////////
71f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
72bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huberstatic size_t getFrameSize(bool isWide, unsigned FT) {
7380f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang    static const size_t kFrameSizeNB[16] = {
7480f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang        95, 103, 118, 134, 148, 159, 204, 244,
7580f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang        39, 43, 38, 37, // SID
7680f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang        0, 0, 0, // future use
7780f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang        0 // no data
78bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    };
7980f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang    static const size_t kFrameSizeWB[16] = {
8080f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang        132, 177, 253, 285, 317, 365, 397, 461, 477,
8180f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang        40, // SID
8280f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang        0, 0, 0, 0, // future use
8380f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang        0, // speech lost
8480f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang        0 // no data
85bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    };
86bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
8780f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang    if (FT > 15 || (isWide && FT > 9 && FT < 14) || (!isWide && FT > 11 && FT < 15)) {
8829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("illegal AMR frame type %d", FT);
8980f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang        return 0;
9080f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang    }
9180f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang
92bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    size_t frameSize = isWide ? kFrameSizeWB[FT] : kFrameSizeNB[FT];
93bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
94bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    // Round up bits to bytes and add 1 for the header byte.
95bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    frameSize = (frameSize + 7) / 8 + 1;
96bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
97bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    return frameSize;
98bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber}
99bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
10080f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wangstatic status_t getFrameSizeByOffset(const sp<DataSource> &source,
10180f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang        off64_t offset, bool isWide, size_t *frameSize) {
10280f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang    uint8_t header;
10380f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang    if (source->readAt(offset, &header, 1) < 1) {
10480f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang        return ERROR_IO;
10580f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang    }
10680f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang
10780f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang    unsigned FT = (header >> 3) & 0x0f;
10880f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang
10980f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang    *frameSize = getFrameSize(isWide, FT);
11080f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang    if (*frameSize == 0) {
11180f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang        return ERROR_MALFORMED;
11280f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang    }
11380f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang    return OK;
11480f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang}
11580f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang
116f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas HuberAMRExtractor::AMRExtractor(const sp<DataSource> &source)
117f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    : mDataSource(source),
11880f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang      mInitCheck(NO_INIT),
11980f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang      mOffsetTableLength(0) {
120f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    String8 mimeType;
121f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    float confidence;
1225a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber    if (!SniffAMR(mDataSource, &mimeType, &confidence, NULL)) {
123bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        return;
124f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    }
125bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
126bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    mIsWide = (mimeType == MEDIA_MIMETYPE_AUDIO_AMR_WB);
127bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
128bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    mMeta = new MetaData;
129bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    mMeta->setCString(
130bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber            kKeyMIMEType, mIsWide ? MEDIA_MIMETYPE_AUDIO_AMR_WB
131bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                                  : MEDIA_MIMETYPE_AUDIO_AMR_NB);
132bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
133bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    mMeta->setInt32(kKeyChannelCount, 1);
134bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    mMeta->setInt32(kKeySampleRate, mIsWide ? 16000 : 8000);
135bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
13680f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang    off64_t offset = mIsWide ? 9 : 6;
137c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t streamSize;
13880f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang    size_t frameSize, numFrames = 0;
13980f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang    int64_t duration = 0;
140bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
14180f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang    if (mDataSource->getSize(&streamSize) == OK) {
14280f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang         while (offset < streamSize) {
14380f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang            if (getFrameSizeByOffset(source, offset, mIsWide, &frameSize) != OK) {
14480f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang                return;
14580f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang            }
14680f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang
14780f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang            if ((numFrames % 50 == 0) && (numFrames / 50 < OFFSET_TABLE_LEN)) {
14880f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang                CHECK_EQ(mOffsetTableLength, numFrames / 50);
14980f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang                mOffsetTable[mOffsetTableLength] = offset - (mIsWide ? 9: 6);
15080f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang                mOffsetTableLength ++;
15180f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang            }
15280f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang
15380f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang            offset += frameSize;
15480f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang            duration += 20000;  // Each frame is 20ms
15580f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang            numFrames ++;
15680f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang        }
15780f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang
15880f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang        mMeta->setInt64(kKeyDuration, duration);
159bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    }
160bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
161bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    mInitCheck = OK;
162f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}
163f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
164f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas HuberAMRExtractor::~AMRExtractor() {
165f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}
166f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
1677be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Hubersp<MetaData> AMRExtractor::getMetaData() {
1687be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber    sp<MetaData> meta = new MetaData;
1697be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
1707be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber    if (mInitCheck != OK) {
1717be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber        return meta;
1727be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber    }
1737be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
1747be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber    meta->setCString(kKeyMIMEType, mIsWide ? "audio/amr-wb" : "audio/amr");
1757be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
1767be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber    return meta;
1777be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber}
1787be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
179f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Hubersize_t AMRExtractor::countTracks() {
180f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    return mInitCheck == OK ? 1 : 0;
181f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}
182f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
183f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Hubersp<MediaSource> AMRExtractor::getTrack(size_t index) {
184f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    if (mInitCheck != OK || index != 0) {
185f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        return NULL;
186f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    }
187f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
18880f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang    return new AMRSource(mDataSource, mMeta, mIsWide,
18980f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang            mOffsetTable, mOffsetTableLength);
190f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}
191f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
192d411b4ca2945cd8974a3a78199fce94646950128Andreas Hubersp<MetaData> AMRExtractor::getTrackMetaData(size_t index, uint32_t /* flags */) {
193f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    if (mInitCheck != OK || index != 0) {
194f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        return NULL;
195f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    }
196f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
197bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    return mMeta;
198f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}
199f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
200f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber////////////////////////////////////////////////////////////////////////////////
201f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
202bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas HuberAMRSource::AMRSource(
203bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        const sp<DataSource> &source, const sp<MetaData> &meta,
20480f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang        bool isWide, const off64_t *offset_table, size_t offset_table_length)
205f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    : mDataSource(source),
206bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber      mMeta(meta),
207f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber      mIsWide(isWide),
208f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber      mOffset(mIsWide ? 9 : 6),
209f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber      mCurrentTimeUs(0),
210f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber      mStarted(false),
21180f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang      mGroup(NULL),
21280f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang      mOffsetTableLength(offset_table_length) {
21380f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang    if (mOffsetTableLength > 0 && mOffsetTableLength <= OFFSET_TABLE_LEN) {
21480f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang        memcpy ((char*)mOffsetTable, (char*)offset_table, sizeof(off64_t) * mOffsetTableLength);
21580f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang    }
216f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}
217f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
218f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas HuberAMRSource::~AMRSource() {
219f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    if (mStarted) {
220f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        stop();
221f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    }
222f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}
223f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
224d411b4ca2945cd8974a3a78199fce94646950128Andreas Huberstatus_t AMRSource::start(MetaData * /* params */) {
225f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    CHECK(!mStarted);
226f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
227f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    mOffset = mIsWide ? 9 : 6;
228f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    mCurrentTimeUs = 0;
229f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    mGroup = new MediaBufferGroup;
230f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    mGroup->add_buffer(new MediaBuffer(128));
231f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    mStarted = true;
232f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
233f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    return OK;
234f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}
235f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
236f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huberstatus_t AMRSource::stop() {
237f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    CHECK(mStarted);
238f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
239f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    delete mGroup;
240f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    mGroup = NULL;
241f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
242f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    mStarted = false;
243f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    return OK;
244f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}
245f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
246f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Hubersp<MetaData> AMRSource::getFormat() {
247bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    return mMeta;
248f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}
249f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
250f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huberstatus_t AMRSource::read(
251f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        MediaBuffer **out, const ReadOptions *options) {
252f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    *out = NULL;
253f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
254bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    int64_t seekTimeUs;
255abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    ReadOptions::SeekMode mode;
256abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
25780f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang        size_t size;
258bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        int64_t seekFrame = seekTimeUs / 20000ll;  // 20ms per frame.
259bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        mCurrentTimeUs = seekFrame * 20000ll;
26080f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang
261d411b4ca2945cd8974a3a78199fce94646950128Andreas Huber        size_t index = seekFrame < 0 ? 0 : seekFrame / 50;
26280f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang        if (index >= mOffsetTableLength) {
26380f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang            index = mOffsetTableLength - 1;
26480f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang        }
26580f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang
26680f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang        mOffset = mOffsetTable[index] + (mIsWide ? 9 : 6);
26780f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang
268db43b34c3428e480f8c4c66e7e88f4001f37f91eMark Salyzyn        for (size_t i = 0; i< seekFrame - index * 50; i++) {
26980f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang            status_t err;
27080f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang            if ((err = getFrameSizeByOffset(mDataSource, mOffset,
27180f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang                            mIsWide, &size)) != OK) {
27280f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang                return err;
27380f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang            }
27480f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang            mOffset += size;
27580f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang        }
276bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    }
277bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
278f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    uint8_t header;
27934769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber    ssize_t n = mDataSource->readAt(mOffset, &header, 1);
280f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
281f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    if (n < 1) {
282aaaa12caef17f34cdcdf118fa7c2b4b8d0d7fe0eGlenn Kasten        return ERROR_END_OF_STREAM;
283f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    }
284f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
285f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    if (header & 0x83) {
286f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        // Padding bits must be 0.
287f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
28829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("padding bits must be 0, header is 0x%02x", header);
2890e917ec1e86477ca22ed8d5dc87a36f4641a6733Andreas Huber
290f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        return ERROR_MALFORMED;
291f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    }
292f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
293f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    unsigned FT = (header >> 3) & 0x0f;
294f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
29580f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang    size_t frameSize = getFrameSize(mIsWide, FT);
29680f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang    if (frameSize == 0) {
297f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        return ERROR_MALFORMED;
298f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    }
299f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
3000e917ec1e86477ca22ed8d5dc87a36f4641a6733Andreas Huber    MediaBuffer *buffer;
3010e917ec1e86477ca22ed8d5dc87a36f4641a6733Andreas Huber    status_t err = mGroup->acquire_buffer(&buffer);
3020e917ec1e86477ca22ed8d5dc87a36f4641a6733Andreas Huber    if (err != OK) {
3030e917ec1e86477ca22ed8d5dc87a36f4641a6733Andreas Huber        return err;
3040e917ec1e86477ca22ed8d5dc87a36f4641a6733Andreas Huber    }
3050e917ec1e86477ca22ed8d5dc87a36f4641a6733Andreas Huber
30634769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber    n = mDataSource->readAt(mOffset, buffer->data(), frameSize);
307f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
308f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    if (n != (ssize_t)frameSize) {
309f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        buffer->release();
310f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        buffer = NULL;
311f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
312f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        return ERROR_IO;
313f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    }
314f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
315f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    buffer->set_range(0, frameSize);
31648c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber    buffer->meta_data()->setInt64(kKeyTime, mCurrentTimeUs);
3178bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber    buffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
318f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
319f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    mOffset += frameSize;
320f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    mCurrentTimeUs += 20000;  // Each frame is 20ms
321f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
322f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    *out = buffer;
323f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
324f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    return OK;
325f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}
326f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
327f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber////////////////////////////////////////////////////////////////////////////////
328f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
329f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huberbool SniffAMR(
3305a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence,
3315a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber        sp<AMessage> *) {
332f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    char header[9];
333f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
33434769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber    if (source->readAt(0, header, sizeof(header)) != sizeof(header)) {
335f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        return false;
336f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    }
337f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
338f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    if (!memcmp(header, "#!AMR\n", 6)) {
33918291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber        *mimeType = MEDIA_MIMETYPE_AUDIO_AMR_NB;
340f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        *confidence = 0.5;
341f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
342f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        return true;
343f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    } else if (!memcmp(header, "#!AMR-WB\n", 9)) {
34418291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber        *mimeType = MEDIA_MIMETYPE_AUDIO_AMR_WB;
345f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        *confidence = 0.5;
346f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
347f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        return true;
348f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    }
349f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
350f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    return false;
351f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}
352f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
353f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}  // namespace android
354