AMRExtractor.cpp revision d411b4ca2945cd8974a3a78199fce94646950128
1f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber/* 2f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber * Copyright (C) 2009 The Android Open Source Project 3f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber * 4f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber * Licensed under the Apache License, Version 2.0 (the "License"); 5f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber * you may not use this file except in compliance with the License. 6f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber * You may obtain a copy of the License at 7f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber * 8f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber * http://www.apache.org/licenses/LICENSE-2.0 9f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber * 10f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber * Unless required by applicable law or agreed to in writing, software 11f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber * distributed under the License is distributed on an "AS IS" BASIS, 12f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber * See the License for the specific language governing permissions and 14f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber * limitations under the License. 15f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber */ 16f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 17f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber//#define LOG_NDEBUG 0 18f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber#define LOG_TAG "AMRExtractor" 19f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber#include <utils/Log.h> 20f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 2166326a5ee0869f1ee4d136a477e6effba428b3cbAndreas Huber#include "include/AMRExtractor.h" 2266326a5ee0869f1ee4d136a477e6effba428b3cbAndreas Huber 23f1d5aa162c02a16b7195a43a9bcea4d592600ac4James Dong#include <media/stagefright/foundation/ADebug.h> 24f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber#include <media/stagefright/DataSource.h> 25f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber#include <media/stagefright/MediaBufferGroup.h> 2618291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber#include <media/stagefright/MediaDefs.h> 27f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber#include <media/stagefright/MediaErrors.h> 28f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber#include <media/stagefright/MediaSource.h> 29f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber#include <media/stagefright/MetaData.h> 30f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber#include <utils/String8.h> 31f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 32f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Hubernamespace android { 33f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 34f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huberclass AMRSource : public MediaSource { 35f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huberpublic: 36bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber AMRSource(const sp<DataSource> &source, 37bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber const sp<MetaData> &meta, 3880f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang bool isWide, 3980f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang const off64_t *offset_table, 4080f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang size_t offset_table_length); 41f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 42f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber virtual status_t start(MetaData *params = NULL); 43f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber virtual status_t stop(); 44f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 45f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber virtual sp<MetaData> getFormat(); 46f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 47f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber virtual status_t read( 48f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber MediaBuffer **buffer, const ReadOptions *options = NULL); 49f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 50f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huberprotected: 51f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber virtual ~AMRSource(); 52f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 53f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huberprivate: 54f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber sp<DataSource> mDataSource; 55bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber sp<MetaData> mMeta; 56f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber bool mIsWide; 57f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 58c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t mOffset; 59f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber int64_t mCurrentTimeUs; 60f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber bool mStarted; 61f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber MediaBufferGroup *mGroup; 62f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 6380f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang off64_t mOffsetTable[OFFSET_TABLE_LEN]; 6480f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang size_t mOffsetTableLength; 6580f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang 66f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber AMRSource(const AMRSource &); 67f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber AMRSource &operator=(const AMRSource &); 68f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}; 69f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 70f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber//////////////////////////////////////////////////////////////////////////////// 71f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 72bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huberstatic size_t getFrameSize(bool isWide, unsigned FT) { 7380f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang static const size_t kFrameSizeNB[16] = { 7480f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang 95, 103, 118, 134, 148, 159, 204, 244, 7580f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang 39, 43, 38, 37, // SID 7680f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang 0, 0, 0, // future use 7780f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang 0 // no data 78bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber }; 7980f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang static const size_t kFrameSizeWB[16] = { 8080f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang 132, 177, 253, 285, 317, 365, 397, 461, 477, 8180f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang 40, // SID 8280f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang 0, 0, 0, 0, // future use 8380f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang 0, // speech lost 8480f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang 0 // no data 85bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber }; 86bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 8780f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang if (FT > 15 || (isWide && FT > 9 && FT < 14) || (!isWide && FT > 11 && FT < 15)) { 8829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("illegal AMR frame type %d", FT); 8980f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang return 0; 9080f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang } 9180f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang 92bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber size_t frameSize = isWide ? kFrameSizeWB[FT] : kFrameSizeNB[FT]; 93bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 94bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber // Round up bits to bytes and add 1 for the header byte. 95bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber frameSize = (frameSize + 7) / 8 + 1; 96bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 97bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber return frameSize; 98bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber} 99bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 10080f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wangstatic status_t getFrameSizeByOffset(const sp<DataSource> &source, 10180f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang off64_t offset, bool isWide, size_t *frameSize) { 10280f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang uint8_t header; 10380f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang if (source->readAt(offset, &header, 1) < 1) { 10480f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang return ERROR_IO; 10580f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang } 10680f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang 10780f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang unsigned FT = (header >> 3) & 0x0f; 10880f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang 10980f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang *frameSize = getFrameSize(isWide, FT); 11080f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang if (*frameSize == 0) { 11180f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang return ERROR_MALFORMED; 11280f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang } 11380f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang return OK; 11480f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang} 11580f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang 116f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas HuberAMRExtractor::AMRExtractor(const sp<DataSource> &source) 117f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber : mDataSource(source), 11880f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang mInitCheck(NO_INIT), 11980f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang mOffsetTableLength(0) { 120f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber String8 mimeType; 121f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber float confidence; 1225a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber if (!SniffAMR(mDataSource, &mimeType, &confidence, NULL)) { 123bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber return; 124f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber } 125bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 126bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber mIsWide = (mimeType == MEDIA_MIMETYPE_AUDIO_AMR_WB); 127bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 128bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber mMeta = new MetaData; 129bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber mMeta->setCString( 130bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber kKeyMIMEType, mIsWide ? MEDIA_MIMETYPE_AUDIO_AMR_WB 131bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber : MEDIA_MIMETYPE_AUDIO_AMR_NB); 132bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 133bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber mMeta->setInt32(kKeyChannelCount, 1); 134bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber mMeta->setInt32(kKeySampleRate, mIsWide ? 16000 : 8000); 135bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 13680f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang off64_t offset = mIsWide ? 9 : 6; 137c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t streamSize; 13880f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang size_t frameSize, numFrames = 0; 13980f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang int64_t duration = 0; 140bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 14180f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang if (mDataSource->getSize(&streamSize) == OK) { 14280f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang while (offset < streamSize) { 14380f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang if (getFrameSizeByOffset(source, offset, mIsWide, &frameSize) != OK) { 14480f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang return; 14580f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang } 14680f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang 14780f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang if ((numFrames % 50 == 0) && (numFrames / 50 < OFFSET_TABLE_LEN)) { 14880f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang CHECK_EQ(mOffsetTableLength, numFrames / 50); 14980f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang mOffsetTable[mOffsetTableLength] = offset - (mIsWide ? 9: 6); 15080f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang mOffsetTableLength ++; 15180f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang } 15280f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang 15380f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang offset += frameSize; 15480f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang duration += 20000; // Each frame is 20ms 15580f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang numFrames ++; 15680f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang } 15780f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang 15880f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang mMeta->setInt64(kKeyDuration, duration); 159bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber } 160bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 161bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber mInitCheck = OK; 162f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber} 163f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 164f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas HuberAMRExtractor::~AMRExtractor() { 165f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber} 166f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 1677be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Hubersp<MetaData> AMRExtractor::getMetaData() { 1687be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber sp<MetaData> meta = new MetaData; 1697be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber 1707be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber if (mInitCheck != OK) { 1717be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber return meta; 1727be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber } 1737be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber 1747be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber meta->setCString(kKeyMIMEType, mIsWide ? "audio/amr-wb" : "audio/amr"); 1757be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber 1767be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber return meta; 1777be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber} 1787be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber 179f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Hubersize_t AMRExtractor::countTracks() { 180f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber return mInitCheck == OK ? 1 : 0; 181f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber} 182f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 183f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Hubersp<MediaSource> AMRExtractor::getTrack(size_t index) { 184f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber if (mInitCheck != OK || index != 0) { 185f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber return NULL; 186f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber } 187f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 18880f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang return new AMRSource(mDataSource, mMeta, mIsWide, 18980f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang mOffsetTable, mOffsetTableLength); 190f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber} 191f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 192d411b4ca2945cd8974a3a78199fce94646950128Andreas Hubersp<MetaData> AMRExtractor::getTrackMetaData(size_t index, uint32_t /* flags */) { 193f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber if (mInitCheck != OK || index != 0) { 194f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber return NULL; 195f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber } 196f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 197bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber return mMeta; 198f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber} 199f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 200f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber//////////////////////////////////////////////////////////////////////////////// 201f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 202bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas HuberAMRSource::AMRSource( 203bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber const sp<DataSource> &source, const sp<MetaData> &meta, 20480f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang bool isWide, const off64_t *offset_table, size_t offset_table_length) 205f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber : mDataSource(source), 206bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber mMeta(meta), 207f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber mIsWide(isWide), 208f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber mOffset(mIsWide ? 9 : 6), 209f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber mCurrentTimeUs(0), 210f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber mStarted(false), 21180f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang mGroup(NULL), 21280f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang mOffsetTableLength(offset_table_length) { 21380f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang if (mOffsetTableLength > 0 && mOffsetTableLength <= OFFSET_TABLE_LEN) { 21480f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang memcpy ((char*)mOffsetTable, (char*)offset_table, sizeof(off64_t) * mOffsetTableLength); 21580f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang } 216f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber} 217f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 218f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas HuberAMRSource::~AMRSource() { 219f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber if (mStarted) { 220f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber stop(); 221f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber } 222f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber} 223f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 224d411b4ca2945cd8974a3a78199fce94646950128Andreas Huberstatus_t AMRSource::start(MetaData * /* params */) { 225f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber CHECK(!mStarted); 226f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 227f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber mOffset = mIsWide ? 9 : 6; 228f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber mCurrentTimeUs = 0; 229f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber mGroup = new MediaBufferGroup; 230f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber mGroup->add_buffer(new MediaBuffer(128)); 231f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber mStarted = true; 232f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 233f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber return OK; 234f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber} 235f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 236f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huberstatus_t AMRSource::stop() { 237f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber CHECK(mStarted); 238f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 239f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber delete mGroup; 240f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber mGroup = NULL; 241f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 242f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber mStarted = false; 243f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber return OK; 244f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber} 245f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 246f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Hubersp<MetaData> AMRSource::getFormat() { 247bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber return mMeta; 248f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber} 249f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 250f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huberstatus_t AMRSource::read( 251f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber MediaBuffer **out, const ReadOptions *options) { 252f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber *out = NULL; 253f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 254bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber int64_t seekTimeUs; 255abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber ReadOptions::SeekMode mode; 256abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber if (options && options->getSeekTo(&seekTimeUs, &mode)) { 25780f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang size_t size; 258bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber int64_t seekFrame = seekTimeUs / 20000ll; // 20ms per frame. 259bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber mCurrentTimeUs = seekFrame * 20000ll; 26080f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang 261d411b4ca2945cd8974a3a78199fce94646950128Andreas Huber size_t index = seekFrame < 0 ? 0 : seekFrame / 50; 26280f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang if (index >= mOffsetTableLength) { 26380f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang index = mOffsetTableLength - 1; 26480f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang } 26580f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang 26680f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang mOffset = mOffsetTable[index] + (mIsWide ? 9 : 6); 26780f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang 26880f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang for (int i = 0; i< seekFrame - index * 50; i++) { 26980f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang status_t err; 27080f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang if ((err = getFrameSizeByOffset(mDataSource, mOffset, 27180f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang mIsWide, &size)) != OK) { 27280f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang return err; 27380f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang } 27480f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang mOffset += size; 27580f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang } 276bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber } 277bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 278f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber uint8_t header; 27934769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber ssize_t n = mDataSource->readAt(mOffset, &header, 1); 280f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 281f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber if (n < 1) { 282aaaa12caef17f34cdcdf118fa7c2b4b8d0d7fe0eGlenn Kasten return ERROR_END_OF_STREAM; 283f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber } 284f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 285f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber if (header & 0x83) { 286f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber // Padding bits must be 0. 287f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 28829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("padding bits must be 0, header is 0x%02x", header); 2890e917ec1e86477ca22ed8d5dc87a36f4641a6733Andreas Huber 290f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber return ERROR_MALFORMED; 291f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber } 292f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 293f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber unsigned FT = (header >> 3) & 0x0f; 294f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 29580f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang size_t frameSize = getFrameSize(mIsWide, FT); 29680f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang if (frameSize == 0) { 297f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber return ERROR_MALFORMED; 298f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber } 299f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 3000e917ec1e86477ca22ed8d5dc87a36f4641a6733Andreas Huber MediaBuffer *buffer; 3010e917ec1e86477ca22ed8d5dc87a36f4641a6733Andreas Huber status_t err = mGroup->acquire_buffer(&buffer); 3020e917ec1e86477ca22ed8d5dc87a36f4641a6733Andreas Huber if (err != OK) { 3030e917ec1e86477ca22ed8d5dc87a36f4641a6733Andreas Huber return err; 3040e917ec1e86477ca22ed8d5dc87a36f4641a6733Andreas Huber } 3050e917ec1e86477ca22ed8d5dc87a36f4641a6733Andreas Huber 30634769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber n = mDataSource->readAt(mOffset, buffer->data(), frameSize); 307f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 308f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber if (n != (ssize_t)frameSize) { 309f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber buffer->release(); 310f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber buffer = NULL; 311f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 312f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber return ERROR_IO; 313f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber } 314f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 315f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber buffer->set_range(0, frameSize); 31648c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber buffer->meta_data()->setInt64(kKeyTime, mCurrentTimeUs); 3178bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber buffer->meta_data()->setInt32(kKeyIsSyncFrame, 1); 318f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 319f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber mOffset += frameSize; 320f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber mCurrentTimeUs += 20000; // Each frame is 20ms 321f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 322f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber *out = buffer; 323f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 324f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber return OK; 325f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber} 326f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 327f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber//////////////////////////////////////////////////////////////////////////////// 328f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 329f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huberbool SniffAMR( 3305a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber const sp<DataSource> &source, String8 *mimeType, float *confidence, 3315a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber sp<AMessage> *) { 332f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber char header[9]; 333f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 33434769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber if (source->readAt(0, header, sizeof(header)) != sizeof(header)) { 335f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber return false; 336f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber } 337f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 338f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber if (!memcmp(header, "#!AMR\n", 6)) { 33918291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber *mimeType = MEDIA_MIMETYPE_AUDIO_AMR_NB; 340f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber *confidence = 0.5; 341f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 342f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber return true; 343f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber } else if (!memcmp(header, "#!AMR-WB\n", 9)) { 34418291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber *mimeType = MEDIA_MIMETYPE_AUDIO_AMR_WB; 345f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber *confidence = 0.5; 346f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 347f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber return true; 348f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber } 349f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 350f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber return false; 351f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber} 352f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 353f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber} // namespace android 354