15a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber/*
25a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber * Copyright (C) 2009 The Android Open Source Project
35a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber *
45a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
55a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber * you may not use this file except in compliance with the License.
65a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber * You may obtain a copy of the License at
75a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber *
85a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
95a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber *
105a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber * Unless required by applicable law or agreed to in writing, software
115a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
125a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber * See the License for the specific language governing permissions and
145a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber * limitations under the License.
155a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber */
165a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber
175a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber//#define LOG_NDEBUG 0
185a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber#define LOG_TAG "AMRExtractor"
195a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber#include <utils/Log.h>
205a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber
2157515f334bcc1f66f95e342bfcaa13bf9ca802adAndreas Huber#include "include/AMRExtractor.h"
2257515f334bcc1f66f95e342bfcaa13bf9ca802adAndreas Huber
235a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber#include <media/stagefright/DataSource.h>
245a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber#include <media/stagefright/MediaBufferGroup.h>
255a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber#include <media/stagefright/MediaDebug.h>
26e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber#include <media/stagefright/MediaDefs.h>
275a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber#include <media/stagefright/MediaErrors.h>
285a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber#include <media/stagefright/MediaSource.h>
295a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber#include <media/stagefright/MetaData.h>
305a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber#include <utils/String8.h>
315a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber
325a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Hubernamespace android {
335a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber
345a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huberclass AMRSource : public MediaSource {
355a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huberpublic:
3627366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber    AMRSource(const sp<DataSource> &source,
3727366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber              const sp<MetaData> &meta,
3827366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber              size_t frameSize,
3927366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber              bool isWide);
405a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber
415a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber    virtual status_t start(MetaData *params = NULL);
425a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber    virtual status_t stop();
435a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber
445a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber    virtual sp<MetaData> getFormat();
455a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber
465a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber    virtual status_t read(
475a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber            MediaBuffer **buffer, const ReadOptions *options = NULL);
485a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber
495a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huberprotected:
505a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber    virtual ~AMRSource();
515a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber
525a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huberprivate:
535a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber    sp<DataSource> mDataSource;
5427366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber    sp<MetaData> mMeta;
5527366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber    size_t mFrameSize;
565a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber    bool mIsWide;
575a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber
585a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber    off_t mOffset;
595a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber    int64_t mCurrentTimeUs;
605a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber    bool mStarted;
615a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber    MediaBufferGroup *mGroup;
625a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber
635a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber    AMRSource(const AMRSource &);
645a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber    AMRSource &operator=(const AMRSource &);
655a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber};
665a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber
675a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber////////////////////////////////////////////////////////////////////////////////
685a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber
6927366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huberstatic size_t getFrameSize(bool isWide, unsigned FT) {
7027366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber    static const size_t kFrameSizeNB[8] = {
7127366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber        95, 103, 118, 134, 148, 159, 204, 244
7227366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber    };
7327366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber    static const size_t kFrameSizeWB[9] = {
7427366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber        132, 177, 253, 285, 317, 365, 397, 461, 477
7527366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber    };
7627366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber
7727366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber    size_t frameSize = isWide ? kFrameSizeWB[FT] : kFrameSizeNB[FT];
7827366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber
7927366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber    // Round up bits to bytes and add 1 for the header byte.
8027366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber    frameSize = (frameSize + 7) / 8 + 1;
8127366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber
8227366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber    return frameSize;
8327366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber}
8427366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber
855a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas HuberAMRExtractor::AMRExtractor(const sp<DataSource> &source)
865a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber    : mDataSource(source),
875a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber      mInitCheck(NO_INIT) {
885a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber    String8 mimeType;
895a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber    float confidence;
90efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber    if (!SniffAMR(mDataSource, &mimeType, &confidence, NULL)) {
9127366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber        return;
925a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber    }
9327366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber
9427366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber    mIsWide = (mimeType == MEDIA_MIMETYPE_AUDIO_AMR_WB);
9527366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber
9627366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber    mMeta = new MetaData;
9727366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber    mMeta->setCString(
9827366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber            kKeyMIMEType, mIsWide ? MEDIA_MIMETYPE_AUDIO_AMR_WB
9927366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber                                  : MEDIA_MIMETYPE_AUDIO_AMR_NB);
10027366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber
10127366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber    mMeta->setInt32(kKeyChannelCount, 1);
10227366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber    mMeta->setInt32(kKeySampleRate, mIsWide ? 16000 : 8000);
10327366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber
10427366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber    size_t offset = mIsWide ? 9 : 6;
10527366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber    uint8_t header;
10627366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber    if (mDataSource->readAt(offset, &header, 1) != 1) {
10727366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber        return;
10827366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber    }
10927366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber
11027366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber    unsigned FT = (header >> 3) & 0x0f;
11127366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber
11227366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber    if (FT > 8 || (!mIsWide && FT > 7)) {
11327366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber        return;
11427366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber    }
11527366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber
11627366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber    mFrameSize = getFrameSize(mIsWide, FT);
11727366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber
11827366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber    off_t streamSize;
11927366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber    if (mDataSource->getSize(&streamSize) == OK) {
12027366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber        off_t numFrames = streamSize / mFrameSize;
12127366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber
12227366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber        mMeta->setInt64(kKeyDuration, 20000ll * numFrames);
12327366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber    }
12427366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber
12527366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber    mInitCheck = OK;
1265a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber}
1275a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber
1285a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas HuberAMRExtractor::~AMRExtractor() {
1295a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber}
1305a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber
1311cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Hubersp<MetaData> AMRExtractor::getMetaData() {
1321cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber    sp<MetaData> meta = new MetaData;
1331cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber
1341cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber    if (mInitCheck != OK) {
1351cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber        return meta;
1361cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber    }
1371cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber
1381cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber    meta->setCString(kKeyMIMEType, mIsWide ? "audio/amr-wb" : "audio/amr");
1391cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber
1401cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber    return meta;
1411cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber}
1421cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber
1435a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Hubersize_t AMRExtractor::countTracks() {
1445a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber    return mInitCheck == OK ? 1 : 0;
1455a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber}
1465a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber
1475a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Hubersp<MediaSource> AMRExtractor::getTrack(size_t index) {
1485a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber    if (mInitCheck != OK || index != 0) {
1495a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber        return NULL;
1505a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber    }
1515a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber
15227366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber    return new AMRSource(mDataSource, mMeta, mFrameSize, mIsWide);
1535a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber}
1545a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber
155e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Hubersp<MetaData> AMRExtractor::getTrackMetaData(size_t index, uint32_t flags) {
1565a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber    if (mInitCheck != OK || index != 0) {
1575a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber        return NULL;
1585a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber    }
1595a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber
16027366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber    return mMeta;
1615a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber}
1625a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber
1635a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber////////////////////////////////////////////////////////////////////////////////
1645a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber
16527366fc9540cb642ee4856957dabffe7ddf1f901Andreas HuberAMRSource::AMRSource(
16627366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber        const sp<DataSource> &source, const sp<MetaData> &meta,
16727366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber        size_t frameSize, bool isWide)
1685a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber    : mDataSource(source),
16927366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber      mMeta(meta),
17027366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber      mFrameSize(frameSize),
1715a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber      mIsWide(isWide),
1725a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber      mOffset(mIsWide ? 9 : 6),
1735a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber      mCurrentTimeUs(0),
1745a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber      mStarted(false),
1755a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber      mGroup(NULL) {
1765a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber}
1775a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber
1785a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas HuberAMRSource::~AMRSource() {
1795a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber    if (mStarted) {
1805a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber        stop();
1815a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber    }
1825a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber}
1835a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber
1845a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huberstatus_t AMRSource::start(MetaData *params) {
1855a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber    CHECK(!mStarted);
1865a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber
1875a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber    mOffset = mIsWide ? 9 : 6;
1885a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber    mCurrentTimeUs = 0;
1895a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber    mGroup = new MediaBufferGroup;
1905a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber    mGroup->add_buffer(new MediaBuffer(128));
1915a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber    mStarted = true;
1925a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber
1935a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber    return OK;
1945a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber}
1955a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber
1965a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huberstatus_t AMRSource::stop() {
1975a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber    CHECK(mStarted);
1985a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber
1995a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber    delete mGroup;
2005a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber    mGroup = NULL;
2015a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber
2025a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber    mStarted = false;
2035a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber    return OK;
2045a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber}
2055a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber
2065a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Hubersp<MetaData> AMRSource::getFormat() {
20727366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber    return mMeta;
2085a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber}
2095a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber
2105a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huberstatus_t AMRSource::read(
2115a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber        MediaBuffer **out, const ReadOptions *options) {
2125a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber    *out = NULL;
2135a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber
21427366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber    int64_t seekTimeUs;
2156624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber    ReadOptions::SeekMode mode;
2166624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
21727366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber        int64_t seekFrame = seekTimeUs / 20000ll;  // 20ms per frame.
21827366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber        mCurrentTimeUs = seekFrame * 20000ll;
21927366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber        mOffset = seekFrame * mFrameSize + (mIsWide ? 9 : 6);
22027366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber    }
22127366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber
2225a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber    uint8_t header;
2239a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber    ssize_t n = mDataSource->readAt(mOffset, &header, 1);
2245a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber
2255a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber    if (n < 1) {
226f62dd66a8aa100079e0f6db0c8557234d67453e3Glenn Kasten        return ERROR_END_OF_STREAM;
2275a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber    }
2285a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber
2295a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber    if (header & 0x83) {
2305a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber        // Padding bits must be 0.
2315a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber
232bc8342721d9e32cac624587e8e5c64372ceaff18Andreas Huber        LOGE("padding bits must be 0, header is 0x%02x", header);
233bc8342721d9e32cac624587e8e5c64372ceaff18Andreas Huber
2345a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber        return ERROR_MALFORMED;
2355a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber    }
2365a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber
2375a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber    unsigned FT = (header >> 3) & 0x0f;
2385a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber
2395a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber    if (FT > 8 || (!mIsWide && FT > 7)) {
240bc8342721d9e32cac624587e8e5c64372ceaff18Andreas Huber
241bc8342721d9e32cac624587e8e5c64372ceaff18Andreas Huber        LOGE("illegal AMR frame type %d", FT);
242bc8342721d9e32cac624587e8e5c64372ceaff18Andreas Huber
2435a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber        return ERROR_MALFORMED;
2445a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber    }
2455a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber
24627366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber    size_t frameSize = getFrameSize(mIsWide, FT);
24727366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber    CHECK_EQ(frameSize, mFrameSize);
2485a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber
249bc8342721d9e32cac624587e8e5c64372ceaff18Andreas Huber    MediaBuffer *buffer;
250bc8342721d9e32cac624587e8e5c64372ceaff18Andreas Huber    status_t err = mGroup->acquire_buffer(&buffer);
251bc8342721d9e32cac624587e8e5c64372ceaff18Andreas Huber    if (err != OK) {
252bc8342721d9e32cac624587e8e5c64372ceaff18Andreas Huber        return err;
253bc8342721d9e32cac624587e8e5c64372ceaff18Andreas Huber    }
254bc8342721d9e32cac624587e8e5c64372ceaff18Andreas Huber
2559a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber    n = mDataSource->readAt(mOffset, buffer->data(), frameSize);
2565a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber
2575a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber    if (n != (ssize_t)frameSize) {
2585a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber        buffer->release();
2595a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber        buffer = NULL;
2605a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber
2615a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber        return ERROR_IO;
2625a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber    }
2635a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber
2645a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber    buffer->set_range(0, frameSize);
265fa8de752507feaca695123911915070c1ce463b2Andreas Huber    buffer->meta_data()->setInt64(kKeyTime, mCurrentTimeUs);
266ad98d383a04fce08a147b200e23b12f12b2681a3Andreas Huber    buffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
2675a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber
2685a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber    mOffset += frameSize;
2695a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber    mCurrentTimeUs += 20000;  // Each frame is 20ms
2705a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber
2715a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber    *out = buffer;
2725a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber
2735a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber    return OK;
2745a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber}
2755a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber
2765a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber////////////////////////////////////////////////////////////////////////////////
2775a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber
2785a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huberbool SniffAMR(
279efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence,
280efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber        sp<AMessage> *) {
2815a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber    char header[9];
2825a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber
2839a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber    if (source->readAt(0, header, sizeof(header)) != sizeof(header)) {
2845a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber        return false;
2855a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber    }
2865a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber
2875a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber    if (!memcmp(header, "#!AMR\n", 6)) {
288e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber        *mimeType = MEDIA_MIMETYPE_AUDIO_AMR_NB;
2895a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber        *confidence = 0.5;
2905a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber
2915a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber        return true;
2925a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber    } else if (!memcmp(header, "#!AMR-WB\n", 9)) {
293e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber        *mimeType = MEDIA_MIMETYPE_AUDIO_AMR_WB;
2945a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber        *confidence = 0.5;
2955a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber
2965a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber        return true;
2975a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber    }
2985a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber
2995a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber    return false;
3005a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber}
3015a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber
3025a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber}  // namespace android
303