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
2175226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen#include "AMRExtractor.h"
2266326a5ee0869f1ee4d136a477e6effba428b3cbAndreas Huber
232a243f08193fe9ff1afe018e9953f01c44ced9deMarco Nelissen#include <media/DataSourceBase.h>
243d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen#include <media/MediaTrack.h>
25f1d5aa162c02a16b7195a43a9bcea4d592600ac4James Dong#include <media/stagefright/foundation/ADebug.h>
26f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber#include <media/stagefright/MediaBufferGroup.h>
2718291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber#include <media/stagefright/MediaDefs.h>
28f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber#include <media/stagefright/MediaErrors.h>
29f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber#include <media/stagefright/MetaData.h>
30f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber#include <utils/String8.h>
31f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
32f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Hubernamespace android {
33f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
343d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissenclass AMRSource : public MediaTrack {
35f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huberpublic:
363d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen    AMRSource(
373d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen            DataSourceBase *source,
383d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen            MetaDataBase &meta,
393d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen            bool isWide,
403d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen            const off64_t *offset_table,
413d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen            size_t offset_table_length);
423d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen
433d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen    virtual status_t start(MetaDataBase *params = NULL);
44f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    virtual status_t stop();
45f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
463d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen    virtual status_t getFormat(MetaDataBase &);
47f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
48f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    virtual status_t read(
491889c3edad32995c0cf26ae2248fe7c957b7ec84Dongwon Kang            MediaBufferBase **buffer, const ReadOptions *options = NULL);
50f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
51f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huberprotected:
52f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    virtual ~AMRSource();
53f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
54f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huberprivate:
552a243f08193fe9ff1afe018e9953f01c44ced9deMarco Nelissen    DataSourceBase *mDataSource;
563d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen    MetaDataBase mMeta;
57f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    bool mIsWide;
58f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
59c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t mOffset;
60f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    int64_t mCurrentTimeUs;
61f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    bool mStarted;
62f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    MediaBufferGroup *mGroup;
63f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
6480f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang    off64_t mOffsetTable[OFFSET_TABLE_LEN];
6580f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang    size_t mOffsetTableLength;
6680f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang
67f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    AMRSource(const AMRSource &);
68f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    AMRSource &operator=(const AMRSource &);
69f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber};
70f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
71f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber////////////////////////////////////////////////////////////////////////////////
72f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
73bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huberstatic size_t getFrameSize(bool isWide, unsigned FT) {
7480f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang    static const size_t kFrameSizeNB[16] = {
7580f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang        95, 103, 118, 134, 148, 159, 204, 244,
7680f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang        39, 43, 38, 37, // SID
7780f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang        0, 0, 0, // future use
7880f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang        0 // no data
79bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    };
8080f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang    static const size_t kFrameSizeWB[16] = {
8180f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang        132, 177, 253, 285, 317, 365, 397, 461, 477,
8280f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang        40, // SID
8380f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang        0, 0, 0, 0, // future use
8480f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang        0, // speech lost
8580f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang        0 // no data
86bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    };
87bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
8880f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang    if (FT > 15 || (isWide && FT > 9 && FT < 14) || (!isWide && FT > 11 && FT < 15)) {
8929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("illegal AMR frame type %d", FT);
9080f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang        return 0;
9180f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang    }
9280f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang
93bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    size_t frameSize = isWide ? kFrameSizeWB[FT] : kFrameSizeNB[FT];
94bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
95bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    // Round up bits to bytes and add 1 for the header byte.
96bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    frameSize = (frameSize + 7) / 8 + 1;
97bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
98bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    return frameSize;
99bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber}
100bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
1012a243f08193fe9ff1afe018e9953f01c44ced9deMarco Nelissenstatic status_t getFrameSizeByOffset(DataSourceBase *source,
10280f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang        off64_t offset, bool isWide, size_t *frameSize) {
10380f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang    uint8_t header;
1049a1a9537456e41cb8450f84a735c3d005a22ffe2Wei Jia    ssize_t count = source->readAt(offset, &header, 1);
1059a1a9537456e41cb8450f84a735c3d005a22ffe2Wei Jia    if (count == 0) {
1069a1a9537456e41cb8450f84a735c3d005a22ffe2Wei Jia        return ERROR_END_OF_STREAM;
1079a1a9537456e41cb8450f84a735c3d005a22ffe2Wei Jia    } else if (count < 0) {
10880f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang        return ERROR_IO;
10980f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang    }
11080f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang
11180f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang    unsigned FT = (header >> 3) & 0x0f;
11280f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang
11380f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang    *frameSize = getFrameSize(isWide, FT);
11480f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang    if (*frameSize == 0) {
11580f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang        return ERROR_MALFORMED;
11680f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang    }
11780f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang    return OK;
11880f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang}
11980f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang
1203d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissenstatic bool SniffAMR(
1213d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen        DataSourceBase *source, bool *isWide, float *confidence) {
1223d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen    char header[9];
1233d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen
1243d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen    if (source->readAt(0, header, sizeof(header)) != sizeof(header)) {
1253d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen        return false;
1263d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen    }
1273d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen
1283d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen    if (!memcmp(header, "#!AMR\n", 6)) {
1293d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen        if (isWide != nullptr) {
1303d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen            *isWide = false;
1313d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen        }
1323d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen        *confidence = 0.5;
1333d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen
1343d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen        return true;
1353d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen    } else if (!memcmp(header, "#!AMR-WB\n", 9)) {
1363d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen        if (isWide != nullptr) {
1373d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen            *isWide = true;
1383d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen        }
1393d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen        *confidence = 0.5;
1403d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen
1413d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen        return true;
1423d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen    }
1433d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen
1443d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen    return false;
1453d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen}
1463d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen
1472a243f08193fe9ff1afe018e9953f01c44ced9deMarco NelissenAMRExtractor::AMRExtractor(DataSourceBase *source)
148f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    : mDataSource(source),
14980f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang      mInitCheck(NO_INIT),
15080f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang      mOffsetTableLength(0) {
151f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    float confidence;
1523d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen    if (!SniffAMR(mDataSource, &mIsWide, &confidence)) {
153bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        return;
154f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    }
155bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
1563d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen    mMeta.setCString(
157bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber            kKeyMIMEType, mIsWide ? MEDIA_MIMETYPE_AUDIO_AMR_WB
158bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber                                  : MEDIA_MIMETYPE_AUDIO_AMR_NB);
159bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
1603d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen    mMeta.setInt32(kKeyChannelCount, 1);
1613d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen    mMeta.setInt32(kKeySampleRate, mIsWide ? 16000 : 8000);
162bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
16380f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang    off64_t offset = mIsWide ? 9 : 6;
164c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t streamSize;
16580f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang    size_t frameSize, numFrames = 0;
16680f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang    int64_t duration = 0;
167bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
16880f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang    if (mDataSource->getSize(&streamSize) == OK) {
16980f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang         while (offset < streamSize) {
1709a1a9537456e41cb8450f84a735c3d005a22ffe2Wei Jia             status_t status = getFrameSizeByOffset(source, offset, mIsWide, &frameSize);
1719a1a9537456e41cb8450f84a735c3d005a22ffe2Wei Jia             if (status == ERROR_END_OF_STREAM) {
1729a1a9537456e41cb8450f84a735c3d005a22ffe2Wei Jia                 break;
1739a1a9537456e41cb8450f84a735c3d005a22ffe2Wei Jia             } else if (status != OK) {
17480f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang                return;
17580f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang            }
17680f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang
17780f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang            if ((numFrames % 50 == 0) && (numFrames / 50 < OFFSET_TABLE_LEN)) {
17880f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang                CHECK_EQ(mOffsetTableLength, numFrames / 50);
17980f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang                mOffsetTable[mOffsetTableLength] = offset - (mIsWide ? 9: 6);
18080f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang                mOffsetTableLength ++;
18180f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang            }
18280f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang
18380f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang            offset += frameSize;
18480f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang            duration += 20000;  // Each frame is 20ms
18580f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang            numFrames ++;
18680f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang        }
18780f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang
1883d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen        mMeta.setInt64(kKeyDuration, duration);
189bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    }
190bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
191bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    mInitCheck = OK;
192f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}
193f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
194f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas HuberAMRExtractor::~AMRExtractor() {
195f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}
196f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
1973d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissenstatus_t AMRExtractor::getMetaData(MetaDataBase &meta) {
1983d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen    meta.clear();
1997be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
2003d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen    if (mInitCheck == OK) {
2013d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen        meta.setCString(kKeyMIMEType, mIsWide ? "audio/amr-wb" : "audio/amr");
2027be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber    }
2037be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
2043d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen    return OK;
2057be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber}
2067be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
207f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Hubersize_t AMRExtractor::countTracks() {
208f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    return mInitCheck == OK ? 1 : 0;
209f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}
210f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
2113d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco NelissenMediaTrack *AMRExtractor::getTrack(size_t index) {
212f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    if (mInitCheck != OK || index != 0) {
213f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        return NULL;
214f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    }
215f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
21680f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang    return new AMRSource(mDataSource, mMeta, mIsWide,
21780f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang            mOffsetTable, mOffsetTableLength);
218f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}
219f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
2203d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissenstatus_t AMRExtractor::getTrackMetaData(MetaDataBase &meta, size_t index, uint32_t /* flags */) {
221f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    if (mInitCheck != OK || index != 0) {
2223d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen        return UNKNOWN_ERROR;
223f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    }
224f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
2253d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen    meta = mMeta;
2263d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen    return OK;
227f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}
228f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
229f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber////////////////////////////////////////////////////////////////////////////////
230f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
231bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas HuberAMRSource::AMRSource(
2323d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen        DataSourceBase *source, MetaDataBase &meta,
23380f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang        bool isWide, const off64_t *offset_table, size_t offset_table_length)
234f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    : mDataSource(source),
235bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber      mMeta(meta),
236f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber      mIsWide(isWide),
237f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber      mOffset(mIsWide ? 9 : 6),
238f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber      mCurrentTimeUs(0),
239f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber      mStarted(false),
24080f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang      mGroup(NULL),
24180f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang      mOffsetTableLength(offset_table_length) {
24280f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang    if (mOffsetTableLength > 0 && mOffsetTableLength <= OFFSET_TABLE_LEN) {
24380f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang        memcpy ((char*)mOffsetTable, (char*)offset_table, sizeof(off64_t) * mOffsetTableLength);
24480f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang    }
245f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}
246f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
247f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas HuberAMRSource::~AMRSource() {
248f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    if (mStarted) {
249f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        stop();
250f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    }
251f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}
252f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
2533d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissenstatus_t AMRSource::start(MetaDataBase * /* params */) {
254f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    CHECK(!mStarted);
255f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
256f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    mOffset = mIsWide ? 9 : 6;
257f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    mCurrentTimeUs = 0;
258f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    mGroup = new MediaBufferGroup;
2591889c3edad32995c0cf26ae2248fe7c957b7ec84Dongwon Kang    mGroup->add_buffer(MediaBufferBase::Create(128));
260f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    mStarted = true;
261f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
262f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    return OK;
263f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}
264f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
265f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huberstatus_t AMRSource::stop() {
266f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    CHECK(mStarted);
267f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
268f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    delete mGroup;
269f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    mGroup = NULL;
270f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
271f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    mStarted = false;
272f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    return OK;
273f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}
274f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
2753d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissenstatus_t AMRSource::getFormat(MetaDataBase &meta) {
2763d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen    meta = mMeta;
2773d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen    return OK;
278f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}
279f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
280f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huberstatus_t AMRSource::read(
2811889c3edad32995c0cf26ae2248fe7c957b7ec84Dongwon Kang        MediaBufferBase **out, const ReadOptions *options) {
282f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    *out = NULL;
283f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
284bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    int64_t seekTimeUs;
285abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    ReadOptions::SeekMode mode;
2868538a603ef992e75f29336499cb783f3ec19f18cMarco Nelissen    if (mOffsetTableLength > 0 && options && options->getSeekTo(&seekTimeUs, &mode)) {
28780f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang        size_t size;
288bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        int64_t seekFrame = seekTimeUs / 20000ll;  // 20ms per frame.
289bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber        mCurrentTimeUs = seekFrame * 20000ll;
29080f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang
291d411b4ca2945cd8974a3a78199fce94646950128Andreas Huber        size_t index = seekFrame < 0 ? 0 : seekFrame / 50;
29280f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang        if (index >= mOffsetTableLength) {
29380f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang            index = mOffsetTableLength - 1;
29480f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang        }
29580f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang
29680f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang        mOffset = mOffsetTable[index] + (mIsWide ? 9 : 6);
29780f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang
298db43b34c3428e480f8c4c66e7e88f4001f37f91eMark Salyzyn        for (size_t i = 0; i< seekFrame - index * 50; i++) {
29980f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang            status_t err;
30080f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang            if ((err = getFrameSizeByOffset(mDataSource, mOffset,
30180f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang                            mIsWide, &size)) != OK) {
30280f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang                return err;
30380f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang            }
30480f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang            mOffset += size;
30580f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang        }
306bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber    }
307bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber
308f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    uint8_t header;
30934769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber    ssize_t n = mDataSource->readAt(mOffset, &header, 1);
310f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
311f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    if (n < 1) {
312aaaa12caef17f34cdcdf118fa7c2b4b8d0d7fe0eGlenn Kasten        return ERROR_END_OF_STREAM;
313f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    }
314f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
315f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    if (header & 0x83) {
316f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        // Padding bits must be 0.
317f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
31829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("padding bits must be 0, header is 0x%02x", header);
3190e917ec1e86477ca22ed8d5dc87a36f4641a6733Andreas Huber
320f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        return ERROR_MALFORMED;
321f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    }
322f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
323f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    unsigned FT = (header >> 3) & 0x0f;
324f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
32580f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang    size_t frameSize = getFrameSize(mIsWide, FT);
32680f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang    if (frameSize == 0) {
327f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        return ERROR_MALFORMED;
328f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    }
329f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
3301889c3edad32995c0cf26ae2248fe7c957b7ec84Dongwon Kang    MediaBufferBase *buffer;
3310e917ec1e86477ca22ed8d5dc87a36f4641a6733Andreas Huber    status_t err = mGroup->acquire_buffer(&buffer);
3320e917ec1e86477ca22ed8d5dc87a36f4641a6733Andreas Huber    if (err != OK) {
3330e917ec1e86477ca22ed8d5dc87a36f4641a6733Andreas Huber        return err;
3340e917ec1e86477ca22ed8d5dc87a36f4641a6733Andreas Huber    }
3350e917ec1e86477ca22ed8d5dc87a36f4641a6733Andreas Huber
33634769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber    n = mDataSource->readAt(mOffset, buffer->data(), frameSize);
337f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
338f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    if (n != (ssize_t)frameSize) {
339f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        buffer->release();
340f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        buffer = NULL;
341f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
342ad78169f6dd3abd27498a68d8988e8cece44fed0Wei Jia        if (n < 0) {
343ad78169f6dd3abd27498a68d8988e8cece44fed0Wei Jia            return ERROR_IO;
344ad78169f6dd3abd27498a68d8988e8cece44fed0Wei Jia        } else {
345ad78169f6dd3abd27498a68d8988e8cece44fed0Wei Jia            // only partial frame is available, treat it as EOS.
346ad78169f6dd3abd27498a68d8988e8cece44fed0Wei Jia            mOffset += n;
347ad78169f6dd3abd27498a68d8988e8cece44fed0Wei Jia            return ERROR_END_OF_STREAM;
348ad78169f6dd3abd27498a68d8988e8cece44fed0Wei Jia        }
349f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    }
350f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
351f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    buffer->set_range(0, frameSize);
3523d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen    buffer->meta_data().setInt64(kKeyTime, mCurrentTimeUs);
3533d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen    buffer->meta_data().setInt32(kKeyIsSyncFrame, 1);
354f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
355f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    mOffset += frameSize;
356f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    mCurrentTimeUs += 20000;  // Each frame is 20ms
357f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
358f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    *out = buffer;
359f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
360f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    return OK;
361f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}
362f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
363f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber////////////////////////////////////////////////////////////////////////////////
364f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
36575226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissenextern "C" {
36675226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen// This is the only symbol that needs to be exported
36775226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen__attribute__ ((visibility ("default")))
36875226177f20a176d50e3e53bbb34067cb49112c3Marco NelissenMediaExtractor::ExtractorDef GETEXTRACTORDEF() {
36975226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen    return {
37075226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen        MediaExtractor::EXTRACTORDEF_VERSION,
37175226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen        UUID("c86639c9-2f31-40ac-a715-fa01b4493aaf"),
37275226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen        1,
37375226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen        "AMR Extractor",
37475226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen        [](
3752a243f08193fe9ff1afe018e9953f01c44ced9deMarco Nelissen                DataSourceBase *source,
37675226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen                float *confidence,
37717e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang                void **,
37817e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang                MediaExtractor::FreeMetaFunc *) -> MediaExtractor::CreatorFunc {
37917e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang            if (SniffAMR(source, nullptr, confidence)) {
38075226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen                return [](
3812a243f08193fe9ff1afe018e9953f01c44ced9deMarco Nelissen                        DataSourceBase *source,
38217e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang                        void *) -> MediaExtractor* {
38375226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen                    return new AMRExtractor(source);};
38475226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen            }
38575226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen            return NULL;
38675226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen        }
38775226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen    };
38875226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen}
38975226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen
39075226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen} // extern "C"
39175226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen
392f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}  // namespace android
393