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 2175226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen#include "AMRExtractor.h" 2266326a5ee0869f1ee4d136a477e6effba428b3cbAndreas Huber 232a243f08193fe9ff1afe018e9953f01c44ced9deMarco Nelissen#include <media/DataSourceBase.h> 243d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen#include <media/MediaTrack.h> 25f1d5aa162c02a16b7195a43a9bcea4d592600ac4James Dong#include <media/stagefright/foundation/ADebug.h> 26f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber#include <media/stagefright/MediaBufferGroup.h> 2718291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber#include <media/stagefright/MediaDefs.h> 28f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber#include <media/stagefright/MediaErrors.h> 29f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber#include <media/stagefright/MetaData.h> 30f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber#include <utils/String8.h> 31f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 32f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Hubernamespace android { 33f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 343d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissenclass AMRSource : public MediaTrack { 35f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huberpublic: 363d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen AMRSource( 373d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen DataSourceBase *source, 383d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen MetaDataBase &meta, 393d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen bool isWide, 403d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen const off64_t *offset_table, 413d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen size_t offset_table_length); 423d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen 433d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen virtual status_t start(MetaDataBase *params = NULL); 44f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber virtual status_t stop(); 45f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 463d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen virtual status_t getFormat(MetaDataBase &); 47f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 48f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber virtual status_t read( 491889c3edad32995c0cf26ae2248fe7c957b7ec84Dongwon Kang MediaBufferBase **buffer, const ReadOptions *options = NULL); 50f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 51f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huberprotected: 52f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber virtual ~AMRSource(); 53f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 54f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huberprivate: 552a243f08193fe9ff1afe018e9953f01c44ced9deMarco Nelissen DataSourceBase *mDataSource; 563d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen MetaDataBase mMeta; 57f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber bool mIsWide; 58f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 59c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t mOffset; 60f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber int64_t mCurrentTimeUs; 61f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber bool mStarted; 62f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber MediaBufferGroup *mGroup; 63f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 6480f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang off64_t mOffsetTable[OFFSET_TABLE_LEN]; 6580f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang size_t mOffsetTableLength; 6680f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang 67f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber AMRSource(const AMRSource &); 68f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber AMRSource &operator=(const AMRSource &); 69f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber}; 70f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 71f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber//////////////////////////////////////////////////////////////////////////////// 72f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 73bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huberstatic size_t getFrameSize(bool isWide, unsigned FT) { 7480f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang static const size_t kFrameSizeNB[16] = { 7580f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang 95, 103, 118, 134, 148, 159, 204, 244, 7680f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang 39, 43, 38, 37, // SID 7780f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang 0, 0, 0, // future use 7880f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang 0 // no data 79bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber }; 8080f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang static const size_t kFrameSizeWB[16] = { 8180f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang 132, 177, 253, 285, 317, 365, 397, 461, 477, 8280f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang 40, // SID 8380f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang 0, 0, 0, 0, // future use 8480f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang 0, // speech lost 8580f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang 0 // no data 86bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber }; 87bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 8880f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang if (FT > 15 || (isWide && FT > 9 && FT < 14) || (!isWide && FT > 11 && FT < 15)) { 8929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("illegal AMR frame type %d", FT); 9080f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang return 0; 9180f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang } 9280f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang 93bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber size_t frameSize = isWide ? kFrameSizeWB[FT] : kFrameSizeNB[FT]; 94bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 95bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber // Round up bits to bytes and add 1 for the header byte. 96bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber frameSize = (frameSize + 7) / 8 + 1; 97bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 98bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber return frameSize; 99bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber} 100bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 1012a243f08193fe9ff1afe018e9953f01c44ced9deMarco Nelissenstatic status_t getFrameSizeByOffset(DataSourceBase *source, 10280f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang off64_t offset, bool isWide, size_t *frameSize) { 10380f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang uint8_t header; 1049a1a9537456e41cb8450f84a735c3d005a22ffe2Wei Jia ssize_t count = source->readAt(offset, &header, 1); 1059a1a9537456e41cb8450f84a735c3d005a22ffe2Wei Jia if (count == 0) { 1069a1a9537456e41cb8450f84a735c3d005a22ffe2Wei Jia return ERROR_END_OF_STREAM; 1079a1a9537456e41cb8450f84a735c3d005a22ffe2Wei Jia } else if (count < 0) { 10880f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang return ERROR_IO; 10980f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang } 11080f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang 11180f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang unsigned FT = (header >> 3) & 0x0f; 11280f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang 11380f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang *frameSize = getFrameSize(isWide, FT); 11480f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang if (*frameSize == 0) { 11580f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang return ERROR_MALFORMED; 11680f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang } 11780f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang return OK; 11880f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang} 11980f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang 1203d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissenstatic bool SniffAMR( 1213d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen DataSourceBase *source, bool *isWide, float *confidence) { 1223d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen char header[9]; 1233d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen 1243d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen if (source->readAt(0, header, sizeof(header)) != sizeof(header)) { 1253d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen return false; 1263d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen } 1273d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen 1283d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen if (!memcmp(header, "#!AMR\n", 6)) { 1293d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen if (isWide != nullptr) { 1303d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen *isWide = false; 1313d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen } 1323d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen *confidence = 0.5; 1333d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen 1343d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen return true; 1353d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen } else if (!memcmp(header, "#!AMR-WB\n", 9)) { 1363d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen if (isWide != nullptr) { 1373d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen *isWide = true; 1383d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen } 1393d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen *confidence = 0.5; 1403d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen 1413d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen return true; 1423d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen } 1433d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen 1443d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen return false; 1453d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen} 1463d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen 1472a243f08193fe9ff1afe018e9953f01c44ced9deMarco NelissenAMRExtractor::AMRExtractor(DataSourceBase *source) 148f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber : mDataSource(source), 14980f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang mInitCheck(NO_INIT), 15080f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang mOffsetTableLength(0) { 151f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber float confidence; 1523d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen if (!SniffAMR(mDataSource, &mIsWide, &confidence)) { 153bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber return; 154f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber } 155bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 1563d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen mMeta.setCString( 157bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber kKeyMIMEType, mIsWide ? MEDIA_MIMETYPE_AUDIO_AMR_WB 158bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber : MEDIA_MIMETYPE_AUDIO_AMR_NB); 159bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 1603d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen mMeta.setInt32(kKeyChannelCount, 1); 1613d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen mMeta.setInt32(kKeySampleRate, mIsWide ? 16000 : 8000); 162bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 16380f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang off64_t offset = mIsWide ? 9 : 6; 164c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t streamSize; 16580f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang size_t frameSize, numFrames = 0; 16680f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang int64_t duration = 0; 167bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 16880f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang if (mDataSource->getSize(&streamSize) == OK) { 16980f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang while (offset < streamSize) { 1709a1a9537456e41cb8450f84a735c3d005a22ffe2Wei Jia status_t status = getFrameSizeByOffset(source, offset, mIsWide, &frameSize); 1719a1a9537456e41cb8450f84a735c3d005a22ffe2Wei Jia if (status == ERROR_END_OF_STREAM) { 1729a1a9537456e41cb8450f84a735c3d005a22ffe2Wei Jia break; 1739a1a9537456e41cb8450f84a735c3d005a22ffe2Wei Jia } else if (status != OK) { 17480f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang return; 17580f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang } 17680f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang 17780f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang if ((numFrames % 50 == 0) && (numFrames / 50 < OFFSET_TABLE_LEN)) { 17880f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang CHECK_EQ(mOffsetTableLength, numFrames / 50); 17980f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang mOffsetTable[mOffsetTableLength] = offset - (mIsWide ? 9: 6); 18080f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang mOffsetTableLength ++; 18180f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang } 18280f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang 18380f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang offset += frameSize; 18480f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang duration += 20000; // Each frame is 20ms 18580f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang numFrames ++; 18680f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang } 18780f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang 1883d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen mMeta.setInt64(kKeyDuration, duration); 189bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber } 190bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 191bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber mInitCheck = OK; 192f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber} 193f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 194f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas HuberAMRExtractor::~AMRExtractor() { 195f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber} 196f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 1973d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissenstatus_t AMRExtractor::getMetaData(MetaDataBase &meta) { 1983d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen meta.clear(); 1997be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber 2003d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen if (mInitCheck == OK) { 2013d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen meta.setCString(kKeyMIMEType, mIsWide ? "audio/amr-wb" : "audio/amr"); 2027be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber } 2037be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber 2043d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen return OK; 2057be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber} 2067be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber 207f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Hubersize_t AMRExtractor::countTracks() { 208f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber return mInitCheck == OK ? 1 : 0; 209f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber} 210f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 2113d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco NelissenMediaTrack *AMRExtractor::getTrack(size_t index) { 212f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber if (mInitCheck != OK || index != 0) { 213f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber return NULL; 214f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber } 215f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 21680f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang return new AMRSource(mDataSource, mMeta, mIsWide, 21780f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang mOffsetTable, mOffsetTableLength); 218f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber} 219f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 2203d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissenstatus_t AMRExtractor::getTrackMetaData(MetaDataBase &meta, size_t index, uint32_t /* flags */) { 221f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber if (mInitCheck != OK || index != 0) { 2223d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen return UNKNOWN_ERROR; 223f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber } 224f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 2253d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen meta = mMeta; 2263d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen return OK; 227f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber} 228f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 229f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber//////////////////////////////////////////////////////////////////////////////// 230f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 231bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas HuberAMRSource::AMRSource( 2323d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen DataSourceBase *source, MetaDataBase &meta, 23380f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang bool isWide, const off64_t *offset_table, size_t offset_table_length) 234f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber : mDataSource(source), 235bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber mMeta(meta), 236f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber mIsWide(isWide), 237f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber mOffset(mIsWide ? 9 : 6), 238f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber mCurrentTimeUs(0), 239f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber mStarted(false), 24080f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang mGroup(NULL), 24180f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang mOffsetTableLength(offset_table_length) { 24280f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang if (mOffsetTableLength > 0 && mOffsetTableLength <= OFFSET_TABLE_LEN) { 24380f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang memcpy ((char*)mOffsetTable, (char*)offset_table, sizeof(off64_t) * mOffsetTableLength); 24480f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang } 245f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber} 246f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 247f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas HuberAMRSource::~AMRSource() { 248f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber if (mStarted) { 249f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber stop(); 250f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber } 251f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber} 252f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 2533d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissenstatus_t AMRSource::start(MetaDataBase * /* params */) { 254f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber CHECK(!mStarted); 255f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 256f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber mOffset = mIsWide ? 9 : 6; 257f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber mCurrentTimeUs = 0; 258f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber mGroup = new MediaBufferGroup; 2591889c3edad32995c0cf26ae2248fe7c957b7ec84Dongwon Kang mGroup->add_buffer(MediaBufferBase::Create(128)); 260f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber mStarted = true; 261f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 262f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber return OK; 263f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber} 264f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 265f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huberstatus_t AMRSource::stop() { 266f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber CHECK(mStarted); 267f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 268f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber delete mGroup; 269f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber mGroup = NULL; 270f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 271f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber mStarted = false; 272f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber return OK; 273f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber} 274f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 2753d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissenstatus_t AMRSource::getFormat(MetaDataBase &meta) { 2763d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen meta = mMeta; 2773d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen return OK; 278f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber} 279f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 280f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huberstatus_t AMRSource::read( 2811889c3edad32995c0cf26ae2248fe7c957b7ec84Dongwon Kang MediaBufferBase **out, const ReadOptions *options) { 282f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber *out = NULL; 283f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 284bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber int64_t seekTimeUs; 285abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber ReadOptions::SeekMode mode; 2868538a603ef992e75f29336499cb783f3ec19f18cMarco Nelissen if (mOffsetTableLength > 0 && options && options->getSeekTo(&seekTimeUs, &mode)) { 28780f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang size_t size; 288bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber int64_t seekFrame = seekTimeUs / 20000ll; // 20ms per frame. 289bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber mCurrentTimeUs = seekFrame * 20000ll; 29080f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang 291d411b4ca2945cd8974a3a78199fce94646950128Andreas Huber size_t index = seekFrame < 0 ? 0 : seekFrame / 50; 29280f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang if (index >= mOffsetTableLength) { 29380f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang index = mOffsetTableLength - 1; 29480f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang } 29580f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang 29680f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang mOffset = mOffsetTable[index] + (mIsWide ? 9 : 6); 29780f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang 298db43b34c3428e480f8c4c66e7e88f4001f37f91eMark Salyzyn for (size_t i = 0; i< seekFrame - index * 50; i++) { 29980f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang status_t err; 30080f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang if ((err = getFrameSizeByOffset(mDataSource, mOffset, 30180f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang mIsWide, &size)) != OK) { 30280f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang return err; 30380f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang } 30480f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang mOffset += size; 30580f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang } 306bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber } 307bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber 308f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber uint8_t header; 30934769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber ssize_t n = mDataSource->readAt(mOffset, &header, 1); 310f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 311f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber if (n < 1) { 312aaaa12caef17f34cdcdf118fa7c2b4b8d0d7fe0eGlenn Kasten return ERROR_END_OF_STREAM; 313f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber } 314f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 315f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber if (header & 0x83) { 316f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber // Padding bits must be 0. 317f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 31829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("padding bits must be 0, header is 0x%02x", header); 3190e917ec1e86477ca22ed8d5dc87a36f4641a6733Andreas Huber 320f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber return ERROR_MALFORMED; 321f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber } 322f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 323f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber unsigned FT = (header >> 3) & 0x0f; 324f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 32580f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang size_t frameSize = getFrameSize(mIsWide, FT); 32680f68ce02c91f188bb0cb0019fd25df2b8115f18Gloria Wang if (frameSize == 0) { 327f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber return ERROR_MALFORMED; 328f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber } 329f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 3301889c3edad32995c0cf26ae2248fe7c957b7ec84Dongwon Kang MediaBufferBase *buffer; 3310e917ec1e86477ca22ed8d5dc87a36f4641a6733Andreas Huber status_t err = mGroup->acquire_buffer(&buffer); 3320e917ec1e86477ca22ed8d5dc87a36f4641a6733Andreas Huber if (err != OK) { 3330e917ec1e86477ca22ed8d5dc87a36f4641a6733Andreas Huber return err; 3340e917ec1e86477ca22ed8d5dc87a36f4641a6733Andreas Huber } 3350e917ec1e86477ca22ed8d5dc87a36f4641a6733Andreas Huber 33634769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber n = mDataSource->readAt(mOffset, buffer->data(), frameSize); 337f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 338f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber if (n != (ssize_t)frameSize) { 339f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber buffer->release(); 340f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber buffer = NULL; 341f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 342ad78169f6dd3abd27498a68d8988e8cece44fed0Wei Jia if (n < 0) { 343ad78169f6dd3abd27498a68d8988e8cece44fed0Wei Jia return ERROR_IO; 344ad78169f6dd3abd27498a68d8988e8cece44fed0Wei Jia } else { 345ad78169f6dd3abd27498a68d8988e8cece44fed0Wei Jia // only partial frame is available, treat it as EOS. 346ad78169f6dd3abd27498a68d8988e8cece44fed0Wei Jia mOffset += n; 347ad78169f6dd3abd27498a68d8988e8cece44fed0Wei Jia return ERROR_END_OF_STREAM; 348ad78169f6dd3abd27498a68d8988e8cece44fed0Wei Jia } 349f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber } 350f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 351f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber buffer->set_range(0, frameSize); 3523d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen buffer->meta_data().setInt64(kKeyTime, mCurrentTimeUs); 3533d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen buffer->meta_data().setInt32(kKeyIsSyncFrame, 1); 354f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 355f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber mOffset += frameSize; 356f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber mCurrentTimeUs += 20000; // Each frame is 20ms 357f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 358f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber *out = buffer; 359f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 360f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber return OK; 361f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber} 362f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 363f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber//////////////////////////////////////////////////////////////////////////////// 364f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber 36575226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissenextern "C" { 36675226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen// This is the only symbol that needs to be exported 36775226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen__attribute__ ((visibility ("default"))) 36875226177f20a176d50e3e53bbb34067cb49112c3Marco NelissenMediaExtractor::ExtractorDef GETEXTRACTORDEF() { 36975226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen return { 37075226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen MediaExtractor::EXTRACTORDEF_VERSION, 37175226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen UUID("c86639c9-2f31-40ac-a715-fa01b4493aaf"), 37275226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen 1, 37375226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen "AMR Extractor", 37475226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen []( 3752a243f08193fe9ff1afe018e9953f01c44ced9deMarco Nelissen DataSourceBase *source, 37675226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen float *confidence, 37717e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang void **, 37817e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang MediaExtractor::FreeMetaFunc *) -> MediaExtractor::CreatorFunc { 37917e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang if (SniffAMR(source, nullptr, confidence)) { 38075226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen return []( 3812a243f08193fe9ff1afe018e9953f01c44ced9deMarco Nelissen DataSourceBase *source, 38217e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang void *) -> MediaExtractor* { 38375226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen return new AMRExtractor(source);}; 38475226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen } 38575226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen return NULL; 38675226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen } 38775226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen }; 38875226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen} 38975226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen 39075226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen} // extern "C" 39175226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen 392f75978f63a25e79c683e96611f95cb5cd49efd3dAndreas Huber} // namespace android 393