15a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber/* 25a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber * Copyright (C) 2009 The Android Open Source Project 35a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber * 45a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber * Licensed under the Apache License, Version 2.0 (the "License"); 55a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber * you may not use this file except in compliance with the License. 65a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber * You may obtain a copy of the License at 75a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber * 85a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber * http://www.apache.org/licenses/LICENSE-2.0 95a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber * 105a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber * Unless required by applicable law or agreed to in writing, software 115a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber * distributed under the License is distributed on an "AS IS" BASIS, 125a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber * See the License for the specific language governing permissions and 145a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber * limitations under the License. 155a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber */ 165a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber 175a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber//#define LOG_NDEBUG 0 185a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber#define LOG_TAG "AMRExtractor" 195a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber#include <utils/Log.h> 205a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber 2157515f334bcc1f66f95e342bfcaa13bf9ca802adAndreas Huber#include "include/AMRExtractor.h" 2257515f334bcc1f66f95e342bfcaa13bf9ca802adAndreas Huber 235a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber#include <media/stagefright/DataSource.h> 245a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber#include <media/stagefright/MediaBufferGroup.h> 255a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber#include <media/stagefright/MediaDebug.h> 26e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber#include <media/stagefright/MediaDefs.h> 275a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber#include <media/stagefright/MediaErrors.h> 285a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber#include <media/stagefright/MediaSource.h> 295a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber#include <media/stagefright/MetaData.h> 305a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber#include <utils/String8.h> 315a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber 325a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Hubernamespace android { 335a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber 345a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huberclass AMRSource : public MediaSource { 355a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huberpublic: 3627366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber AMRSource(const sp<DataSource> &source, 3727366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber const sp<MetaData> &meta, 3827366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber size_t frameSize, 3927366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber bool isWide); 405a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber 415a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber virtual status_t start(MetaData *params = NULL); 425a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber virtual status_t stop(); 435a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber 445a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber virtual sp<MetaData> getFormat(); 455a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber 465a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber virtual status_t read( 475a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber MediaBuffer **buffer, const ReadOptions *options = NULL); 485a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber 495a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huberprotected: 505a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber virtual ~AMRSource(); 515a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber 525a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huberprivate: 535a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber sp<DataSource> mDataSource; 5427366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber sp<MetaData> mMeta; 5527366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber size_t mFrameSize; 565a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber bool mIsWide; 575a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber 585a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber off_t mOffset; 595a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber int64_t mCurrentTimeUs; 605a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber bool mStarted; 615a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber MediaBufferGroup *mGroup; 625a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber 635a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber AMRSource(const AMRSource &); 645a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber AMRSource &operator=(const AMRSource &); 655a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber}; 665a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber 675a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber//////////////////////////////////////////////////////////////////////////////// 685a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber 6927366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huberstatic size_t getFrameSize(bool isWide, unsigned FT) { 7027366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber static const size_t kFrameSizeNB[8] = { 7127366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber 95, 103, 118, 134, 148, 159, 204, 244 7227366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber }; 7327366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber static const size_t kFrameSizeWB[9] = { 7427366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber 132, 177, 253, 285, 317, 365, 397, 461, 477 7527366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber }; 7627366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber 7727366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber size_t frameSize = isWide ? kFrameSizeWB[FT] : kFrameSizeNB[FT]; 7827366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber 7927366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber // Round up bits to bytes and add 1 for the header byte. 8027366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber frameSize = (frameSize + 7) / 8 + 1; 8127366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber 8227366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber return frameSize; 8327366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber} 8427366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber 855a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas HuberAMRExtractor::AMRExtractor(const sp<DataSource> &source) 865a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber : mDataSource(source), 875a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber mInitCheck(NO_INIT) { 885a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber String8 mimeType; 895a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber float confidence; 90efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber if (!SniffAMR(mDataSource, &mimeType, &confidence, NULL)) { 9127366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber return; 925a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber } 9327366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber 9427366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber mIsWide = (mimeType == MEDIA_MIMETYPE_AUDIO_AMR_WB); 9527366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber 9627366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber mMeta = new MetaData; 9727366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber mMeta->setCString( 9827366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber kKeyMIMEType, mIsWide ? MEDIA_MIMETYPE_AUDIO_AMR_WB 9927366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber : MEDIA_MIMETYPE_AUDIO_AMR_NB); 10027366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber 10127366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber mMeta->setInt32(kKeyChannelCount, 1); 10227366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber mMeta->setInt32(kKeySampleRate, mIsWide ? 16000 : 8000); 10327366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber 10427366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber size_t offset = mIsWide ? 9 : 6; 10527366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber uint8_t header; 10627366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber if (mDataSource->readAt(offset, &header, 1) != 1) { 10727366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber return; 10827366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber } 10927366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber 11027366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber unsigned FT = (header >> 3) & 0x0f; 11127366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber 11227366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber if (FT > 8 || (!mIsWide && FT > 7)) { 11327366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber return; 11427366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber } 11527366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber 11627366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber mFrameSize = getFrameSize(mIsWide, FT); 11727366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber 11827366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber off_t streamSize; 11927366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber if (mDataSource->getSize(&streamSize) == OK) { 12027366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber off_t numFrames = streamSize / mFrameSize; 12127366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber 12227366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber mMeta->setInt64(kKeyDuration, 20000ll * numFrames); 12327366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber } 12427366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber 12527366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber mInitCheck = OK; 1265a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber} 1275a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber 1285a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas HuberAMRExtractor::~AMRExtractor() { 1295a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber} 1305a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber 1311cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Hubersp<MetaData> AMRExtractor::getMetaData() { 1321cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber sp<MetaData> meta = new MetaData; 1331cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber 1341cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber if (mInitCheck != OK) { 1351cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber return meta; 1361cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber } 1371cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber 1381cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber meta->setCString(kKeyMIMEType, mIsWide ? "audio/amr-wb" : "audio/amr"); 1391cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber 1401cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber return meta; 1411cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber} 1421cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber 1435a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Hubersize_t AMRExtractor::countTracks() { 1445a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber return mInitCheck == OK ? 1 : 0; 1455a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber} 1465a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber 1475a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Hubersp<MediaSource> AMRExtractor::getTrack(size_t index) { 1485a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber if (mInitCheck != OK || index != 0) { 1495a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber return NULL; 1505a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber } 1515a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber 15227366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber return new AMRSource(mDataSource, mMeta, mFrameSize, mIsWide); 1535a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber} 1545a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber 155e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Hubersp<MetaData> AMRExtractor::getTrackMetaData(size_t index, uint32_t flags) { 1565a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber if (mInitCheck != OK || index != 0) { 1575a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber return NULL; 1585a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber } 1595a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber 16027366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber return mMeta; 1615a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber} 1625a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber 1635a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber//////////////////////////////////////////////////////////////////////////////// 1645a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber 16527366fc9540cb642ee4856957dabffe7ddf1f901Andreas HuberAMRSource::AMRSource( 16627366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber const sp<DataSource> &source, const sp<MetaData> &meta, 16727366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber size_t frameSize, bool isWide) 1685a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber : mDataSource(source), 16927366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber mMeta(meta), 17027366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber mFrameSize(frameSize), 1715a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber mIsWide(isWide), 1725a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber mOffset(mIsWide ? 9 : 6), 1735a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber mCurrentTimeUs(0), 1745a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber mStarted(false), 1755a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber mGroup(NULL) { 1765a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber} 1775a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber 1785a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas HuberAMRSource::~AMRSource() { 1795a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber if (mStarted) { 1805a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber stop(); 1815a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber } 1825a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber} 1835a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber 1845a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huberstatus_t AMRSource::start(MetaData *params) { 1855a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber CHECK(!mStarted); 1865a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber 1875a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber mOffset = mIsWide ? 9 : 6; 1885a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber mCurrentTimeUs = 0; 1895a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber mGroup = new MediaBufferGroup; 1905a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber mGroup->add_buffer(new MediaBuffer(128)); 1915a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber mStarted = true; 1925a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber 1935a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber return OK; 1945a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber} 1955a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber 1965a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huberstatus_t AMRSource::stop() { 1975a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber CHECK(mStarted); 1985a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber 1995a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber delete mGroup; 2005a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber mGroup = NULL; 2015a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber 2025a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber mStarted = false; 2035a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber return OK; 2045a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber} 2055a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber 2065a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Hubersp<MetaData> AMRSource::getFormat() { 20727366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber return mMeta; 2085a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber} 2095a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber 2105a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huberstatus_t AMRSource::read( 2115a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber MediaBuffer **out, const ReadOptions *options) { 2125a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber *out = NULL; 2135a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber 21427366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber int64_t seekTimeUs; 2156624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber ReadOptions::SeekMode mode; 2166624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber if (options && options->getSeekTo(&seekTimeUs, &mode)) { 21727366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber int64_t seekFrame = seekTimeUs / 20000ll; // 20ms per frame. 21827366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber mCurrentTimeUs = seekFrame * 20000ll; 21927366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber mOffset = seekFrame * mFrameSize + (mIsWide ? 9 : 6); 22027366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber } 22127366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber 2225a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber uint8_t header; 2239a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber ssize_t n = mDataSource->readAt(mOffset, &header, 1); 2245a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber 2255a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber if (n < 1) { 226f62dd66a8aa100079e0f6db0c8557234d67453e3Glenn Kasten return ERROR_END_OF_STREAM; 2275a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber } 2285a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber 2295a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber if (header & 0x83) { 2305a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber // Padding bits must be 0. 2315a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber 232bc8342721d9e32cac624587e8e5c64372ceaff18Andreas Huber LOGE("padding bits must be 0, header is 0x%02x", header); 233bc8342721d9e32cac624587e8e5c64372ceaff18Andreas Huber 2345a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber return ERROR_MALFORMED; 2355a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber } 2365a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber 2375a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber unsigned FT = (header >> 3) & 0x0f; 2385a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber 2395a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber if (FT > 8 || (!mIsWide && FT > 7)) { 240bc8342721d9e32cac624587e8e5c64372ceaff18Andreas Huber 241bc8342721d9e32cac624587e8e5c64372ceaff18Andreas Huber LOGE("illegal AMR frame type %d", FT); 242bc8342721d9e32cac624587e8e5c64372ceaff18Andreas Huber 2435a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber return ERROR_MALFORMED; 2445a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber } 2455a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber 24627366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber size_t frameSize = getFrameSize(mIsWide, FT); 24727366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber CHECK_EQ(frameSize, mFrameSize); 2485a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber 249bc8342721d9e32cac624587e8e5c64372ceaff18Andreas Huber MediaBuffer *buffer; 250bc8342721d9e32cac624587e8e5c64372ceaff18Andreas Huber status_t err = mGroup->acquire_buffer(&buffer); 251bc8342721d9e32cac624587e8e5c64372ceaff18Andreas Huber if (err != OK) { 252bc8342721d9e32cac624587e8e5c64372ceaff18Andreas Huber return err; 253bc8342721d9e32cac624587e8e5c64372ceaff18Andreas Huber } 254bc8342721d9e32cac624587e8e5c64372ceaff18Andreas Huber 2559a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber n = mDataSource->readAt(mOffset, buffer->data(), frameSize); 2565a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber 2575a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber if (n != (ssize_t)frameSize) { 2585a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber buffer->release(); 2595a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber buffer = NULL; 2605a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber 2615a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber return ERROR_IO; 2625a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber } 2635a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber 2645a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber buffer->set_range(0, frameSize); 265fa8de752507feaca695123911915070c1ce463b2Andreas Huber buffer->meta_data()->setInt64(kKeyTime, mCurrentTimeUs); 266ad98d383a04fce08a147b200e23b12f12b2681a3Andreas Huber buffer->meta_data()->setInt32(kKeyIsSyncFrame, 1); 2675a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber 2685a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber mOffset += frameSize; 2695a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber mCurrentTimeUs += 20000; // Each frame is 20ms 2705a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber 2715a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber *out = buffer; 2725a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber 2735a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber return OK; 2745a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber} 2755a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber 2765a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber//////////////////////////////////////////////////////////////////////////////// 2775a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber 2785a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huberbool SniffAMR( 279efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber const sp<DataSource> &source, String8 *mimeType, float *confidence, 280efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber sp<AMessage> *) { 2815a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber char header[9]; 2825a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber 2839a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber if (source->readAt(0, header, sizeof(header)) != sizeof(header)) { 2845a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber return false; 2855a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber } 2865a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber 2875a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber if (!memcmp(header, "#!AMR\n", 6)) { 288e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber *mimeType = MEDIA_MIMETYPE_AUDIO_AMR_NB; 2895a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber *confidence = 0.5; 2905a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber 2915a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber return true; 2925a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber } else if (!memcmp(header, "#!AMR-WB\n", 9)) { 293e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber *mimeType = MEDIA_MIMETYPE_AUDIO_AMR_WB; 2945a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber *confidence = 0.5; 2955a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber 2965a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber return true; 2975a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber } 2985a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber 2995a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber return false; 3005a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber} 3015a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber 3025a65a6e22017e51ebcebb0f41510c54f1085f82cAndreas Huber} // namespace android 303