AMRExtractor.cpp revision c7fc37a3dab9bd1f96713649f351b5990e6316ff
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 23f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber#include <media/stagefright/DataSource.h> 24f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber#include <media/stagefright/MediaBufferGroup.h> 25f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber#include <media/stagefright/MediaDebug.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, 38bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber size_t frameSize, 39bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber bool isWide); 40f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 41f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber virtual status_t start(MetaData *params = NULL); 42f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber virtual status_t stop(); 43f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 44f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber virtual sp<MetaData> getFormat(); 45f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 46f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber virtual status_t read( 47f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber MediaBuffer **buffer, const ReadOptions *options = NULL); 48f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 49f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huberprotected: 50f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber virtual ~AMRSource(); 51f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 52f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huberprivate: 53f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber sp<DataSource> mDataSource; 54bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber sp<MetaData> mMeta; 55bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber size_t mFrameSize; 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 63f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber AMRSource(const AMRSource &); 64f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber AMRSource &operator=(const AMRSource &); 65f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}; 66f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 67f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber//////////////////////////////////////////////////////////////////////////////// 68f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 69bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huberstatic size_t getFrameSize(bool isWide, unsigned FT) { 70bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber static const size_t kFrameSizeNB[8] = { 71bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 95, 103, 118, 134, 148, 159, 204, 244 72bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber }; 73bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber static const size_t kFrameSizeWB[9] = { 74bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 132, 177, 253, 285, 317, 365, 397, 461, 477 75bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber }; 76bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 77bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber size_t frameSize = isWide ? kFrameSizeWB[FT] : kFrameSizeNB[FT]; 78bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 79bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber // Round up bits to bytes and add 1 for the header byte. 80bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber frameSize = (frameSize + 7) / 8 + 1; 81bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 82bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber return frameSize; 83bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber} 84bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 85f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas HuberAMRExtractor::AMRExtractor(const sp<DataSource> &source) 86f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber : mDataSource(source), 87f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber mInitCheck(NO_INIT) { 88f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber String8 mimeType; 89f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber float confidence; 905a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber if (!SniffAMR(mDataSource, &mimeType, &confidence, NULL)) { 91bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber return; 92f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber } 93bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 94bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber mIsWide = (mimeType == MEDIA_MIMETYPE_AUDIO_AMR_WB); 95bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 96bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber mMeta = new MetaData; 97bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber mMeta->setCString( 98bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber kKeyMIMEType, mIsWide ? MEDIA_MIMETYPE_AUDIO_AMR_WB 99bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber : MEDIA_MIMETYPE_AUDIO_AMR_NB); 100bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 101bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber mMeta->setInt32(kKeyChannelCount, 1); 102bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber mMeta->setInt32(kKeySampleRate, mIsWide ? 16000 : 8000); 103bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 104bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber size_t offset = mIsWide ? 9 : 6; 105bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber uint8_t header; 106bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber if (mDataSource->readAt(offset, &header, 1) != 1) { 107bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber return; 108bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber } 109bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 110bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber unsigned FT = (header >> 3) & 0x0f; 111bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 112bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber if (FT > 8 || (!mIsWide && FT > 7)) { 113bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber return; 114bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber } 115bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 116bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber mFrameSize = getFrameSize(mIsWide, FT); 117bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 118c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t streamSize; 119bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber if (mDataSource->getSize(&streamSize) == OK) { 120c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t numFrames = streamSize / mFrameSize; 121bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 122bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber mMeta->setInt64(kKeyDuration, 20000ll * numFrames); 123bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber } 124bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 125bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber mInitCheck = OK; 126f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber} 127f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 128f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas HuberAMRExtractor::~AMRExtractor() { 129f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber} 130f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 1317be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Hubersp<MetaData> AMRExtractor::getMetaData() { 1327be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber sp<MetaData> meta = new MetaData; 1337be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber 1347be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber if (mInitCheck != OK) { 1357be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber return meta; 1367be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber } 1377be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber 1387be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber meta->setCString(kKeyMIMEType, mIsWide ? "audio/amr-wb" : "audio/amr"); 1397be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber 1407be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber return meta; 1417be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber} 1427be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber 143f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Hubersize_t AMRExtractor::countTracks() { 144f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber return mInitCheck == OK ? 1 : 0; 145f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber} 146f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 147f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Hubersp<MediaSource> AMRExtractor::getTrack(size_t index) { 148f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber if (mInitCheck != OK || index != 0) { 149f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber return NULL; 150f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber } 151f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 152bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber return new AMRSource(mDataSource, mMeta, mFrameSize, mIsWide); 153f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber} 154f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 1557e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Hubersp<MetaData> AMRExtractor::getTrackMetaData(size_t index, uint32_t flags) { 156f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber if (mInitCheck != OK || index != 0) { 157f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber return NULL; 158f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber } 159f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 160bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber return mMeta; 161f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber} 162f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 163f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber//////////////////////////////////////////////////////////////////////////////// 164f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 165bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas HuberAMRSource::AMRSource( 166bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber const sp<DataSource> &source, const sp<MetaData> &meta, 167bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber size_t frameSize, bool isWide) 168f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber : mDataSource(source), 169bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber mMeta(meta), 170bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber mFrameSize(frameSize), 171f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber mIsWide(isWide), 172f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber mOffset(mIsWide ? 9 : 6), 173f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber mCurrentTimeUs(0), 174f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber mStarted(false), 175f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber mGroup(NULL) { 176f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber} 177f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 178f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas HuberAMRSource::~AMRSource() { 179f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber if (mStarted) { 180f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber stop(); 181f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber } 182f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber} 183f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 184f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huberstatus_t AMRSource::start(MetaData *params) { 185f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber CHECK(!mStarted); 186f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 187f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber mOffset = mIsWide ? 9 : 6; 188f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber mCurrentTimeUs = 0; 189f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber mGroup = new MediaBufferGroup; 190f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber mGroup->add_buffer(new MediaBuffer(128)); 191f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber mStarted = true; 192f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 193f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber return OK; 194f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber} 195f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 196f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huberstatus_t AMRSource::stop() { 197f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber CHECK(mStarted); 198f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 199f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber delete mGroup; 200f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber mGroup = NULL; 201f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 202f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber mStarted = false; 203f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber return OK; 204f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber} 205f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 206f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Hubersp<MetaData> AMRSource::getFormat() { 207bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber return mMeta; 208f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber} 209f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 210f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huberstatus_t AMRSource::read( 211f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber MediaBuffer **out, const ReadOptions *options) { 212f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber *out = NULL; 213f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 214bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber int64_t seekTimeUs; 215abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber ReadOptions::SeekMode mode; 216abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber if (options && options->getSeekTo(&seekTimeUs, &mode)) { 217bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber int64_t seekFrame = seekTimeUs / 20000ll; // 20ms per frame. 218bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber mCurrentTimeUs = seekFrame * 20000ll; 219bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber mOffset = seekFrame * mFrameSize + (mIsWide ? 9 : 6); 220bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber } 221bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 222f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber uint8_t header; 22334769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber ssize_t n = mDataSource->readAt(mOffset, &header, 1); 224f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 225f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber if (n < 1) { 226aaaa12caef17f34cdcdf118fa7c2b4b8d0d7fe0eGlenn Kasten return ERROR_END_OF_STREAM; 227f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber } 228f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 229f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber if (header & 0x83) { 230f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber // Padding bits must be 0. 231f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 2320e917ec1e86477ca22ed8d5dc87a36f4641a6733Andreas Huber LOGE("padding bits must be 0, header is 0x%02x", header); 2330e917ec1e86477ca22ed8d5dc87a36f4641a6733Andreas Huber 234f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber return ERROR_MALFORMED; 235f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber } 236f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 237f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber unsigned FT = (header >> 3) & 0x0f; 238f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 239f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber if (FT > 8 || (!mIsWide && FT > 7)) { 2400e917ec1e86477ca22ed8d5dc87a36f4641a6733Andreas Huber 2410e917ec1e86477ca22ed8d5dc87a36f4641a6733Andreas Huber LOGE("illegal AMR frame type %d", FT); 2420e917ec1e86477ca22ed8d5dc87a36f4641a6733Andreas Huber 243f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber return ERROR_MALFORMED; 244f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber } 245f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 246bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber size_t frameSize = getFrameSize(mIsWide, FT); 247bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber CHECK_EQ(frameSize, mFrameSize); 248f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 2490e917ec1e86477ca22ed8d5dc87a36f4641a6733Andreas Huber MediaBuffer *buffer; 2500e917ec1e86477ca22ed8d5dc87a36f4641a6733Andreas Huber status_t err = mGroup->acquire_buffer(&buffer); 2510e917ec1e86477ca22ed8d5dc87a36f4641a6733Andreas Huber if (err != OK) { 2520e917ec1e86477ca22ed8d5dc87a36f4641a6733Andreas Huber return err; 2530e917ec1e86477ca22ed8d5dc87a36f4641a6733Andreas Huber } 2540e917ec1e86477ca22ed8d5dc87a36f4641a6733Andreas Huber 25534769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber n = mDataSource->readAt(mOffset, buffer->data(), frameSize); 256f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 257f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber if (n != (ssize_t)frameSize) { 258f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber buffer->release(); 259f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber buffer = NULL; 260f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 261f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber return ERROR_IO; 262f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber } 263f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 264f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber buffer->set_range(0, frameSize); 26548c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber buffer->meta_data()->setInt64(kKeyTime, mCurrentTimeUs); 2668bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber buffer->meta_data()->setInt32(kKeyIsSyncFrame, 1); 267f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 268f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber mOffset += frameSize; 269f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber mCurrentTimeUs += 20000; // Each frame is 20ms 270f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 271f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber *out = buffer; 272f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 273f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber return OK; 274f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber} 275f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 276f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber//////////////////////////////////////////////////////////////////////////////// 277f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 278f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huberbool SniffAMR( 2795a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber const sp<DataSource> &source, String8 *mimeType, float *confidence, 2805a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber sp<AMessage> *) { 281f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber char header[9]; 282f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 28334769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber if (source->readAt(0, header, sizeof(header)) != sizeof(header)) { 284f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber return false; 285f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber } 286f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 287f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber if (!memcmp(header, "#!AMR\n", 6)) { 28818291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber *mimeType = MEDIA_MIMETYPE_AUDIO_AMR_NB; 289f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber *confidence = 0.5; 290f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 291f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber return true; 292f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber } else if (!memcmp(header, "#!AMR-WB\n", 9)) { 29318291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber *mimeType = MEDIA_MIMETYPE_AUDIO_AMR_WB; 294f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber *confidence = 0.5; 295f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 296f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber return true; 297f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber } 298f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 299f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber return false; 300f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber} 301f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 302f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber} // namespace android 303