AMRExtractor.cpp revision f75978f63a25e79c683e96611f95cb5cd49efd3d
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
21f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber#include <media/stagefright/AMRExtractor.h>
22f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber#include <media/stagefright/DataSource.h>
23f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber#include <media/stagefright/MediaBufferGroup.h>
24f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber#include <media/stagefright/MediaDebug.h>
25f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber#include <media/stagefright/MediaErrors.h>
26f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber#include <media/stagefright/MediaSource.h>
27f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber#include <media/stagefright/MetaData.h>
28f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber#include <utils/String8.h>
29f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
30f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Hubernamespace android {
31f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
32f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huberclass AMRSource : public MediaSource {
33f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huberpublic:
34f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    AMRSource(const sp<DataSource> &source, bool isWide);
35f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
36f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    virtual status_t start(MetaData *params = NULL);
37f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    virtual status_t stop();
38f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
39f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    virtual sp<MetaData> getFormat();
40f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
41f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    virtual status_t read(
42f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber            MediaBuffer **buffer, const ReadOptions *options = NULL);
43f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
44f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huberprotected:
45f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    virtual ~AMRSource();
46f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
47f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huberprivate:
48f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    sp<DataSource> mDataSource;
49f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    bool mIsWide;
50f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
51f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    off_t mOffset;
52f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    int64_t mCurrentTimeUs;
53f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    bool mStarted;
54f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    MediaBufferGroup *mGroup;
55f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
56f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    AMRSource(const AMRSource &);
57f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    AMRSource &operator=(const AMRSource &);
58f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber};
59f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
60f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber////////////////////////////////////////////////////////////////////////////////
61f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
62f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas HuberAMRExtractor::AMRExtractor(const sp<DataSource> &source)
63f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    : mDataSource(source),
64f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber      mInitCheck(NO_INIT) {
65f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    String8 mimeType;
66f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    float confidence;
67f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    if (SniffAMR(mDataSource, &mimeType, &confidence)) {
68f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        mInitCheck = OK;
69f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        mIsWide = (mimeType == "audio/amr-wb");
70f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    }
71f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}
72f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
73f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas HuberAMRExtractor::~AMRExtractor() {
74f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}
75f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
76f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Hubersize_t AMRExtractor::countTracks() {
77f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    return mInitCheck == OK ? 1 : 0;
78f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}
79f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
80f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Hubersp<MediaSource> AMRExtractor::getTrack(size_t index) {
81f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    if (mInitCheck != OK || index != 0) {
82f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        return NULL;
83f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    }
84f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
85f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    return new AMRSource(mDataSource, mIsWide);
86f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}
87f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
88f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Hubersp<MetaData> AMRExtractor::getTrackMetaData(size_t index) {
89f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    if (mInitCheck != OK || index != 0) {
90f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        return NULL;
91f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    }
92f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
93f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    return makeAMRFormat(mIsWide);
94f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}
95f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
96f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber// static
97f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Hubersp<MetaData> AMRExtractor::makeAMRFormat(bool isWide) {
98f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    sp<MetaData> meta = new MetaData;
99f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    meta->setCString(kKeyMIMEType, isWide ? "audio/amr-wb" : "audio/3gpp");
100f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    meta->setInt32(kKeyChannelCount, 1);
101f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    meta->setInt32(kKeySampleRate, isWide ? 16000 : 8000);
102f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
103f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    return meta;
104f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}
105f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
106f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber////////////////////////////////////////////////////////////////////////////////
107f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
108f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas HuberAMRSource::AMRSource(const sp<DataSource> &source, bool isWide)
109f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    : mDataSource(source),
110f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber      mIsWide(isWide),
111f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber      mOffset(mIsWide ? 9 : 6),
112f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber      mCurrentTimeUs(0),
113f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber      mStarted(false),
114f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber      mGroup(NULL) {
115f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}
116f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
117f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas HuberAMRSource::~AMRSource() {
118f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    if (mStarted) {
119f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        stop();
120f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    }
121f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}
122f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
123f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huberstatus_t AMRSource::start(MetaData *params) {
124f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    CHECK(!mStarted);
125f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
126f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    mOffset = mIsWide ? 9 : 6;
127f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    mCurrentTimeUs = 0;
128f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    mGroup = new MediaBufferGroup;
129f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    mGroup->add_buffer(new MediaBuffer(128));
130f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    mStarted = true;
131f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
132f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    return OK;
133f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}
134f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
135f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huberstatus_t AMRSource::stop() {
136f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    CHECK(mStarted);
137f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
138f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    delete mGroup;
139f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    mGroup = NULL;
140f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
141f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    mStarted = false;
142f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    return OK;
143f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}
144f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
145f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Hubersp<MetaData> AMRSource::getFormat() {
146f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    return AMRExtractor::makeAMRFormat(mIsWide);
147f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}
148f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
149f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huberstatus_t AMRSource::read(
150f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        MediaBuffer **out, const ReadOptions *options) {
151f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    *out = NULL;
152f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
153f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    uint8_t header;
154f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    ssize_t n = mDataSource->read_at(mOffset, &header, 1);
155f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
156f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    if (n < 1) {
157f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        return ERROR_IO;
158f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    }
159f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
160f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    MediaBuffer *buffer;
161f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    status_t err = mGroup->acquire_buffer(&buffer);
162f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    if (err != OK) {
163f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        return err;
164f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    }
165f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
166f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    if (header & 0x83) {
167f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        // Padding bits must be 0.
168f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
169f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        return ERROR_MALFORMED;
170f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    }
171f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
172f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    unsigned FT = (header >> 3) & 0x0f;
173f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
174f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    if (FT > 8 || (!mIsWide && FT > 7)) {
175f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        return ERROR_MALFORMED;
176f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    }
177f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
178f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    static const size_t kFrameSizeNB[8] = {
179f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        95, 103, 118, 134, 148, 159, 204, 244
180f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    };
181f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    static const size_t kFrameSizeWB[9] = {
182f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        132, 177, 253, 285, 317, 365, 397, 461, 477
183f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    };
184f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
185f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    size_t frameSize = mIsWide ? kFrameSizeWB[FT] : kFrameSizeNB[FT];
186f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
187f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    // Round up bits to bytes and add 1 for the header byte.
188f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    frameSize = (frameSize + 7) / 8 + 1;
189f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
190f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    n = mDataSource->read_at(mOffset, buffer->data(), frameSize);
191f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
192f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    if (n != (ssize_t)frameSize) {
193f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        buffer->release();
194f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        buffer = NULL;
195f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
196f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        return ERROR_IO;
197f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    }
198f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
199f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    buffer->set_range(0, frameSize);
200f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    buffer->meta_data()->setInt32(
201f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber            kKeyTimeUnits, (mCurrentTimeUs + 500) / 1000);
202f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    buffer->meta_data()->setInt32(
203f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber            kKeyTimeScale, 1000);
204f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
205f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    mOffset += frameSize;
206f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    mCurrentTimeUs += 20000;  // Each frame is 20ms
207f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
208f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    *out = buffer;
209f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
210f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    return OK;
211f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}
212f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
213f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber////////////////////////////////////////////////////////////////////////////////
214f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
215f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huberbool SniffAMR(
216f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence) {
217f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    char header[9];
218f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
219f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    if (source->read_at(0, header, sizeof(header)) != sizeof(header)) {
220f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        return false;
221f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    }
222f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
223f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    if (!memcmp(header, "#!AMR\n", 6)) {
224f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        *mimeType = "audio/3gpp";
225f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        *confidence = 0.5;
226f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
227f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        return true;
228f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    } else if (!memcmp(header, "#!AMR-WB\n", 9)) {
229f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        *mimeType = "audio/amr-wb";
230f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        *confidence = 0.5;
231f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
232f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber        return true;
233f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    }
234f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
235f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber    return false;
236f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}
237f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber
238f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}  // namespace android
239