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; 1039a1a9537456e41cb8450f84a735c3d005a22ffe2Wei Jia ssize_t count = source->readAt(offset, &header, 1); 1049a1a9537456e41cb8450f84a735c3d005a22ffe2Wei Jia if (count == 0) { 1059a1a9537456e41cb8450f84a735c3d005a22ffe2Wei Jia return ERROR_END_OF_STREAM; 1069a1a9537456e41cb8450f84a735c3d005a22ffe2Wei Jia } else if (count < 0) { 10780f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang return ERROR_IO; 10880f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang } 10980f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang 11080f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang unsigned FT = (header >> 3) & 0x0f; 11180f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang 11280f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang *frameSize = getFrameSize(isWide, FT); 11380f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang if (*frameSize == 0) { 11480f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang return ERROR_MALFORMED; 11580f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang } 11680f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang return OK; 11780f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang} 11880f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang 119f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas HuberAMRExtractor::AMRExtractor(const sp<DataSource> &source) 120f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber : mDataSource(source), 12180f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang mInitCheck(NO_INIT), 12280f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang mOffsetTableLength(0) { 123f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber String8 mimeType; 124f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber float confidence; 1255a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber if (!SniffAMR(mDataSource, &mimeType, &confidence, NULL)) { 126bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber return; 127f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber } 128bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 129bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber mIsWide = (mimeType == MEDIA_MIMETYPE_AUDIO_AMR_WB); 130bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 131bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber mMeta = new MetaData; 132bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber mMeta->setCString( 133bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber kKeyMIMEType, mIsWide ? MEDIA_MIMETYPE_AUDIO_AMR_WB 134bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber : MEDIA_MIMETYPE_AUDIO_AMR_NB); 135bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 136bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber mMeta->setInt32(kKeyChannelCount, 1); 137bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber mMeta->setInt32(kKeySampleRate, mIsWide ? 16000 : 8000); 138bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 13980f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang off64_t offset = mIsWide ? 9 : 6; 140c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t streamSize; 14180f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang size_t frameSize, numFrames = 0; 14280f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang int64_t duration = 0; 143bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 14480f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang if (mDataSource->getSize(&streamSize) == OK) { 14580f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang while (offset < streamSize) { 1469a1a9537456e41cb8450f84a735c3d005a22ffe2Wei Jia status_t status = getFrameSizeByOffset(source, offset, mIsWide, &frameSize); 1479a1a9537456e41cb8450f84a735c3d005a22ffe2Wei Jia if (status == ERROR_END_OF_STREAM) { 1489a1a9537456e41cb8450f84a735c3d005a22ffe2Wei Jia break; 1499a1a9537456e41cb8450f84a735c3d005a22ffe2Wei Jia } else if (status != OK) { 15080f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang return; 15180f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang } 15280f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang 15380f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang if ((numFrames % 50 == 0) && (numFrames / 50 < OFFSET_TABLE_LEN)) { 15480f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang CHECK_EQ(mOffsetTableLength, numFrames / 50); 15580f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang mOffsetTable[mOffsetTableLength] = offset - (mIsWide ? 9: 6); 15680f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang mOffsetTableLength ++; 15780f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang } 15880f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang 15980f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang offset += frameSize; 16080f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang duration += 20000; // Each frame is 20ms 16180f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang numFrames ++; 16280f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang } 16380f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang 16480f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang mMeta->setInt64(kKeyDuration, duration); 165bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber } 166bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 167bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber mInitCheck = OK; 168f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber} 169f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 170f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas HuberAMRExtractor::~AMRExtractor() { 171f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber} 172f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 1737be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Hubersp<MetaData> AMRExtractor::getMetaData() { 1747be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber sp<MetaData> meta = new MetaData; 1757be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber 1767be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber if (mInitCheck != OK) { 1777be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber return meta; 1787be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber } 1797be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber 1807be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber meta->setCString(kKeyMIMEType, mIsWide ? "audio/amr-wb" : "audio/amr"); 1817be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber 1827be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber return meta; 1837be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber} 1847be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber 185f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Hubersize_t AMRExtractor::countTracks() { 186f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber return mInitCheck == OK ? 1 : 0; 187f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber} 188f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 189b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissensp<IMediaSource> AMRExtractor::getTrack(size_t index) { 190f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber if (mInitCheck != OK || index != 0) { 191f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber return NULL; 192f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber } 193f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 19480f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang return new AMRSource(mDataSource, mMeta, mIsWide, 19580f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang mOffsetTable, mOffsetTableLength); 196f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber} 197f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 198d411b4ca2945cd8974a3a78199fce94646950128Andreas Hubersp<MetaData> AMRExtractor::getTrackMetaData(size_t index, uint32_t /* flags */) { 199f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber if (mInitCheck != OK || index != 0) { 200f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber return NULL; 201f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber } 202f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 203bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber return mMeta; 204f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber} 205f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 206f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber//////////////////////////////////////////////////////////////////////////////// 207f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 208bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas HuberAMRSource::AMRSource( 209bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber const sp<DataSource> &source, const sp<MetaData> &meta, 21080f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang bool isWide, const off64_t *offset_table, size_t offset_table_length) 211f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber : mDataSource(source), 212bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber mMeta(meta), 213f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber mIsWide(isWide), 214f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber mOffset(mIsWide ? 9 : 6), 215f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber mCurrentTimeUs(0), 216f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber mStarted(false), 21780f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang mGroup(NULL), 21880f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang mOffsetTableLength(offset_table_length) { 21980f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang if (mOffsetTableLength > 0 && mOffsetTableLength <= OFFSET_TABLE_LEN) { 22080f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang memcpy ((char*)mOffsetTable, (char*)offset_table, sizeof(off64_t) * mOffsetTableLength); 22180f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang } 222f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber} 223f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 224f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas HuberAMRSource::~AMRSource() { 225f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber if (mStarted) { 226f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber stop(); 227f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber } 228f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber} 229f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 230d411b4ca2945cd8974a3a78199fce94646950128Andreas Huberstatus_t AMRSource::start(MetaData * /* params */) { 231f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber CHECK(!mStarted); 232f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 233f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber mOffset = mIsWide ? 9 : 6; 234f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber mCurrentTimeUs = 0; 235f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber mGroup = new MediaBufferGroup; 236f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber mGroup->add_buffer(new MediaBuffer(128)); 237f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber mStarted = true; 238f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 239f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber return OK; 240f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber} 241f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 242f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huberstatus_t AMRSource::stop() { 243f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber CHECK(mStarted); 244f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 245f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber delete mGroup; 246f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber mGroup = NULL; 247f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 248f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber mStarted = false; 249f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber return OK; 250f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber} 251f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 252f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Hubersp<MetaData> AMRSource::getFormat() { 253bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber return mMeta; 254f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber} 255f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 256f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huberstatus_t AMRSource::read( 257f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber MediaBuffer **out, const ReadOptions *options) { 258f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber *out = NULL; 259f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 260bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber int64_t seekTimeUs; 261abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber ReadOptions::SeekMode mode; 2628538a603ef992e75f29336499cb783f3ec19f18cMarco Nelissen if (mOffsetTableLength > 0 && options && options->getSeekTo(&seekTimeUs, &mode)) { 26380f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang size_t size; 264bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber int64_t seekFrame = seekTimeUs / 20000ll; // 20ms per frame. 265bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber mCurrentTimeUs = seekFrame * 20000ll; 26680f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang 267d411b4ca2945cd8974a3a78199fce94646950128Andreas Huber size_t index = seekFrame < 0 ? 0 : seekFrame / 50; 26880f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang if (index >= mOffsetTableLength) { 26980f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang index = mOffsetTableLength - 1; 27080f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang } 27180f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang 27280f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang mOffset = mOffsetTable[index] + (mIsWide ? 9 : 6); 27380f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang 274db43b34c3428e480f8c4c66e7e88f4001f37f91eMark Salyzyn for (size_t i = 0; i< seekFrame - index * 50; i++) { 27580f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang status_t err; 27680f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang if ((err = getFrameSizeByOffset(mDataSource, mOffset, 27780f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang mIsWide, &size)) != OK) { 27880f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang return err; 27980f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang } 28080f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang mOffset += size; 28180f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang } 282bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber } 283bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 284f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber uint8_t header; 28534769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber ssize_t n = mDataSource->readAt(mOffset, &header, 1); 286f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 287f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber if (n < 1) { 288aaaa12caef17f34cdcdf118fa7c2b4b8d0d7fe0eGlenn Kasten return ERROR_END_OF_STREAM; 289f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber } 290f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 291f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber if (header & 0x83) { 292f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber // Padding bits must be 0. 293f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 29429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("padding bits must be 0, header is 0x%02x", header); 2950e917ec1e86477ca22ed8d5dc87a36f4641a6733Andreas Huber 296f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber return ERROR_MALFORMED; 297f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber } 298f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 299f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber unsigned FT = (header >> 3) & 0x0f; 300f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 30180f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang size_t frameSize = getFrameSize(mIsWide, FT); 30280f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang if (frameSize == 0) { 303f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber return ERROR_MALFORMED; 304f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber } 305f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 3060e917ec1e86477ca22ed8d5dc87a36f4641a6733Andreas Huber MediaBuffer *buffer; 3070e917ec1e86477ca22ed8d5dc87a36f4641a6733Andreas Huber status_t err = mGroup->acquire_buffer(&buffer); 3080e917ec1e86477ca22ed8d5dc87a36f4641a6733Andreas Huber if (err != OK) { 3090e917ec1e86477ca22ed8d5dc87a36f4641a6733Andreas Huber return err; 3100e917ec1e86477ca22ed8d5dc87a36f4641a6733Andreas Huber } 3110e917ec1e86477ca22ed8d5dc87a36f4641a6733Andreas Huber 31234769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber n = mDataSource->readAt(mOffset, buffer->data(), frameSize); 313f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 314f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber if (n != (ssize_t)frameSize) { 315f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber buffer->release(); 316f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber buffer = NULL; 317f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 318ad78169f6dd3abd27498a68d8988e8cece44fed0Wei Jia if (n < 0) { 319ad78169f6dd3abd27498a68d8988e8cece44fed0Wei Jia return ERROR_IO; 320ad78169f6dd3abd27498a68d8988e8cece44fed0Wei Jia } else { 321ad78169f6dd3abd27498a68d8988e8cece44fed0Wei Jia // only partial frame is available, treat it as EOS. 322ad78169f6dd3abd27498a68d8988e8cece44fed0Wei Jia mOffset += n; 323ad78169f6dd3abd27498a68d8988e8cece44fed0Wei Jia return ERROR_END_OF_STREAM; 324ad78169f6dd3abd27498a68d8988e8cece44fed0Wei Jia } 325f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber } 326f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 327f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber buffer->set_range(0, frameSize); 32848c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber buffer->meta_data()->setInt64(kKeyTime, mCurrentTimeUs); 3298bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber buffer->meta_data()->setInt32(kKeyIsSyncFrame, 1); 330f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 331f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber mOffset += frameSize; 332f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber mCurrentTimeUs += 20000; // Each frame is 20ms 333f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 334f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber *out = buffer; 335f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 336f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber return OK; 337f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber} 338f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 339f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber//////////////////////////////////////////////////////////////////////////////// 340f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 341f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huberbool SniffAMR( 3425a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber const sp<DataSource> &source, String8 *mimeType, float *confidence, 3435a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber sp<AMessage> *) { 344f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber char header[9]; 345f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 34634769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber if (source->readAt(0, header, sizeof(header)) != sizeof(header)) { 347f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber return false; 348f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber } 349f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 350f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber if (!memcmp(header, "#!AMR\n", 6)) { 35118291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber *mimeType = MEDIA_MIMETYPE_AUDIO_AMR_NB; 352f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber *confidence = 0.5; 353f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 354f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber return true; 355f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber } else if (!memcmp(header, "#!AMR-WB\n", 9)) { 35618291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber *mimeType = MEDIA_MIMETYPE_AUDIO_AMR_WB; 357f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber *confidence = 0.5; 358f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 359f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber return true; 360f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber } 361f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 362f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber return false; 363f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber} 364f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 365f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber} // namespace android 366