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;
1032a5e49c984befa066e966cd9af2303a54976f163Wei Jia    ssize_t count = source->readAt(offset, &header, 1);
1042a5e49c984befa066e966cd9af2303a54976f163Wei Jia    if (count == 0) {
1052a5e49c984befa066e966cd9af2303a54976f163Wei Jia        return ERROR_END_OF_STREAM;
1062a5e49c984befa066e966cd9af2303a54976f163Wei Jia    } else if (count < 0) {
10780f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang        return ERROR_IO;
10880f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang    }
10980f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang
11080f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang    unsigned FT = (header >> 3) & 0x0f;
11180f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang
11280f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang    *frameSize = getFrameSize(isWide, FT);
11380f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang    if (*frameSize == 0) {
11480f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang        return ERROR_MALFORMED;
11580f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang    }
11680f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang    return OK;
11780f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang}
11880f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang
119f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas HuberAMRExtractor::AMRExtractor(const sp<DataSource> &source)
120f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    : mDataSource(source),
12180f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang      mInitCheck(NO_INIT),
12280f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang      mOffsetTableLength(0) {
123f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    String8 mimeType;
124f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    float confidence;
1255a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber    if (!SniffAMR(mDataSource, &mimeType, &confidence, NULL)) {
126bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        return;
127f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    }
128bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
129bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    mIsWide = (mimeType == MEDIA_MIMETYPE_AUDIO_AMR_WB);
130bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
131bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    mMeta = new MetaData;
132bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    mMeta->setCString(
133bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber            kKeyMIMEType, mIsWide ? MEDIA_MIMETYPE_AUDIO_AMR_WB
134bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                                  : MEDIA_MIMETYPE_AUDIO_AMR_NB);
135bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
136bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    mMeta->setInt32(kKeyChannelCount, 1);
137bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    mMeta->setInt32(kKeySampleRate, mIsWide ? 16000 : 8000);
138bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
13980f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang    off64_t offset = mIsWide ? 9 : 6;
140c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t streamSize;
14180f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang    size_t frameSize, numFrames = 0;
14280f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang    int64_t duration = 0;
143bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
14480f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang    if (mDataSource->getSize(&streamSize) == OK) {
14580f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang         while (offset < streamSize) {
1462a5e49c984befa066e966cd9af2303a54976f163Wei Jia             status_t status = getFrameSizeByOffset(source, offset, mIsWide, &frameSize);
1472a5e49c984befa066e966cd9af2303a54976f163Wei Jia             if (status == ERROR_END_OF_STREAM) {
1482a5e49c984befa066e966cd9af2303a54976f163Wei Jia                 break;
1492a5e49c984befa066e966cd9af2303a54976f163Wei Jia             } else if (status != OK) {
15080f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang                return;
15180f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang            }
15280f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang
15380f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang            if ((numFrames % 50 == 0) && (numFrames / 50 < OFFSET_TABLE_LEN)) {
15480f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang                CHECK_EQ(mOffsetTableLength, numFrames / 50);
15580f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang                mOffsetTable[mOffsetTableLength] = offset - (mIsWide ? 9: 6);
15680f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang                mOffsetTableLength ++;
15780f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang            }
15880f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang
15980f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang            offset += frameSize;
16080f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang            duration += 20000;  // Each frame is 20ms
16180f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang            numFrames ++;
16280f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang        }
16380f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang
16480f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang        mMeta->setInt64(kKeyDuration, duration);
165bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    }
166bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
167bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    mInitCheck = OK;
168f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}
169f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
170f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas HuberAMRExtractor::~AMRExtractor() {
171f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}
172f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
1737be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Hubersp<MetaData> AMRExtractor::getMetaData() {
1747be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber    sp<MetaData> meta = new MetaData;
1757be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
1767be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber    if (mInitCheck != OK) {
1777be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber        return meta;
1787be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber    }
1797be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
1807be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber    meta->setCString(kKeyMIMEType, mIsWide ? "audio/amr-wb" : "audio/amr");
1817be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
1827be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber    return meta;
1837be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber}
1847be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
185f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Hubersize_t AMRExtractor::countTracks() {
186f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    return mInitCheck == OK ? 1 : 0;
187f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}
188f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
189b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissensp<IMediaSource> AMRExtractor::getTrack(size_t index) {
190f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    if (mInitCheck != OK || index != 0) {
191f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        return NULL;
192f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    }
193f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
19480f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang    return new AMRSource(mDataSource, mMeta, mIsWide,
19580f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang            mOffsetTable, mOffsetTableLength);
196f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}
197f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
198d411b4ca2945cd8974a3a78199fce94646950128Andreas Hubersp<MetaData> AMRExtractor::getTrackMetaData(size_t index, uint32_t /* flags */) {
199f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    if (mInitCheck != OK || index != 0) {
200f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        return NULL;
201f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    }
202f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
203bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    return mMeta;
204f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}
205f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
206f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber////////////////////////////////////////////////////////////////////////////////
207f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
208bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas HuberAMRSource::AMRSource(
209bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        const sp<DataSource> &source, const sp<MetaData> &meta,
21080f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang        bool isWide, const off64_t *offset_table, size_t offset_table_length)
211f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    : mDataSource(source),
212bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber      mMeta(meta),
213f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber      mIsWide(isWide),
214f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber      mOffset(mIsWide ? 9 : 6),
215f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber      mCurrentTimeUs(0),
216f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber      mStarted(false),
21780f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang      mGroup(NULL),
21880f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang      mOffsetTableLength(offset_table_length) {
21980f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang    if (mOffsetTableLength > 0 && mOffsetTableLength <= OFFSET_TABLE_LEN) {
22080f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang        memcpy ((char*)mOffsetTable, (char*)offset_table, sizeof(off64_t) * mOffsetTableLength);
22180f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang    }
222f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}
223f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
224f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas HuberAMRSource::~AMRSource() {
225f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    if (mStarted) {
226f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        stop();
227f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    }
228f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}
229f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
230d411b4ca2945cd8974a3a78199fce94646950128Andreas Huberstatus_t AMRSource::start(MetaData * /* params */) {
231f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    CHECK(!mStarted);
232f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
233f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    mOffset = mIsWide ? 9 : 6;
234f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    mCurrentTimeUs = 0;
235f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    mGroup = new MediaBufferGroup;
236f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    mGroup->add_buffer(new MediaBuffer(128));
237f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    mStarted = true;
238f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
239f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    return OK;
240f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}
241f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
242f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huberstatus_t AMRSource::stop() {
243f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    CHECK(mStarted);
244f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
245f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    delete mGroup;
246f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    mGroup = NULL;
247f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
248f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    mStarted = false;
249f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    return OK;
250f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}
251f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
252f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Hubersp<MetaData> AMRSource::getFormat() {
253bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    return mMeta;
254f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}
255f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
256f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huberstatus_t AMRSource::read(
257f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        MediaBuffer **out, const ReadOptions *options) {
258f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    *out = NULL;
259f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
260bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    int64_t seekTimeUs;
261abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    ReadOptions::SeekMode mode;
26236b04932bb93cc3269279282686b439a17a89920Marco Nelissen    if (mOffsetTableLength > 0 && options && options->getSeekTo(&seekTimeUs, &mode)) {
26380f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang        size_t size;
264bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        int64_t seekFrame = seekTimeUs / 20000ll;  // 20ms per frame.
265bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        mCurrentTimeUs = seekFrame * 20000ll;
26680f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang
267d411b4ca2945cd8974a3a78199fce94646950128Andreas Huber        size_t index = seekFrame < 0 ? 0 : seekFrame / 50;
26880f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang        if (index >= mOffsetTableLength) {
26980f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang            index = mOffsetTableLength - 1;
27080f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang        }
27180f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang
27280f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang        mOffset = mOffsetTable[index] + (mIsWide ? 9 : 6);
27380f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang
274db43b34c3428e480f8c4c66e7e88f4001f37f91eMark Salyzyn        for (size_t i = 0; i< seekFrame - index * 50; i++) {
27580f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang            status_t err;
27680f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang            if ((err = getFrameSizeByOffset(mDataSource, mOffset,
27780f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang                            mIsWide, &size)) != OK) {
27880f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang                return err;
27980f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang            }
28080f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang            mOffset += size;
28180f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang        }
282bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    }
283bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
284f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    uint8_t header;
28534769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber    ssize_t n = mDataSource->readAt(mOffset, &header, 1);
286f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
287f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    if (n < 1) {
288aaaa12caef17f34cdcdf118fa7c2b4b8d0d7fe0eGlenn Kasten        return ERROR_END_OF_STREAM;
289f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    }
290f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
291f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    if (header & 0x83) {
292f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        // Padding bits must be 0.
293f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
29429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("padding bits must be 0, header is 0x%02x", header);
2950e917ec1e86477ca22ed8d5dc87a36f4641a6733Andreas Huber
296f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        return ERROR_MALFORMED;
297f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    }
298f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
299f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    unsigned FT = (header >> 3) & 0x0f;
300f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
30180f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang    size_t frameSize = getFrameSize(mIsWide, FT);
30280f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang    if (frameSize == 0) {
303f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        return ERROR_MALFORMED;
304f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    }
305f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
3060e917ec1e86477ca22ed8d5dc87a36f4641a6733Andreas Huber    MediaBuffer *buffer;
3070e917ec1e86477ca22ed8d5dc87a36f4641a6733Andreas Huber    status_t err = mGroup->acquire_buffer(&buffer);
3080e917ec1e86477ca22ed8d5dc87a36f4641a6733Andreas Huber    if (err != OK) {
3090e917ec1e86477ca22ed8d5dc87a36f4641a6733Andreas Huber        return err;
3100e917ec1e86477ca22ed8d5dc87a36f4641a6733Andreas Huber    }
3110e917ec1e86477ca22ed8d5dc87a36f4641a6733Andreas Huber
31234769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber    n = mDataSource->readAt(mOffset, buffer->data(), frameSize);
313f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
314f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    if (n != (ssize_t)frameSize) {
315f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        buffer->release();
316f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        buffer = NULL;
317f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
318ad78169f6dd3abd27498a68d8988e8cece44fed0Wei Jia        if (n < 0) {
319ad78169f6dd3abd27498a68d8988e8cece44fed0Wei Jia            return ERROR_IO;
320ad78169f6dd3abd27498a68d8988e8cece44fed0Wei Jia        } else {
321ad78169f6dd3abd27498a68d8988e8cece44fed0Wei Jia            // only partial frame is available, treat it as EOS.
322ad78169f6dd3abd27498a68d8988e8cece44fed0Wei Jia            mOffset += n;
323ad78169f6dd3abd27498a68d8988e8cece44fed0Wei Jia            return ERROR_END_OF_STREAM;
324ad78169f6dd3abd27498a68d8988e8cece44fed0Wei Jia        }
325f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    }
326f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
327f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    buffer->set_range(0, frameSize);
32848c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber    buffer->meta_data()->setInt64(kKeyTime, mCurrentTimeUs);
3298bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber    buffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
330f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
331f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    mOffset += frameSize;
332f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    mCurrentTimeUs += 20000;  // Each frame is 20ms
333f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
334f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    *out = buffer;
335f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
336f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    return OK;
337f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}
338f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
339f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber////////////////////////////////////////////////////////////////////////////////
340f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
341f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huberbool SniffAMR(
3425a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence,
3435a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber        sp<AMessage> *) {
344f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    char header[9];
345f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
34634769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber    if (source->readAt(0, header, sizeof(header)) != sizeof(header)) {
347f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        return false;
348f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    }
349f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
350f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    if (!memcmp(header, "#!AMR\n", 6)) {
35118291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber        *mimeType = MEDIA_MIMETYPE_AUDIO_AMR_NB;
352f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        *confidence = 0.5;
353f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
354f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        return true;
355f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    } else if (!memcmp(header, "#!AMR-WB\n", 9)) {
35618291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber        *mimeType = MEDIA_MIMETYPE_AUDIO_AMR_WB;
357f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        *confidence = 0.5;
358f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
359f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        return true;
360f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    }
361f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
362f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    return false;
363f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}
364f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
365f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}  // namespace android
366