1 /* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "AMRNBDecoder.h" 18 19 #include "gsmamr_dec.h" 20 21 #include <media/stagefright/MediaBufferGroup.h> 22 #include <media/stagefright/MediaDebug.h> 23 #include <media/stagefright/MediaDefs.h> 24 #include <media/stagefright/MediaErrors.h> 25 #include <media/stagefright/MetaData.h> 26 27 namespace android { 28 29 static const int32_t kNumSamplesPerFrame = 160; 30 static const int32_t kSampleRate = 8000; 31 32 AMRNBDecoder::AMRNBDecoder(const sp<MediaSource> &source) 33 : mSource(source), 34 mStarted(false), 35 mBufferGroup(NULL), 36 mState(NULL), 37 mAnchorTimeUs(0), 38 mNumSamplesOutput(0), 39 mInputBuffer(NULL) { 40 } 41 42 AMRNBDecoder::~AMRNBDecoder() { 43 if (mStarted) { 44 stop(); 45 } 46 } 47 48 status_t AMRNBDecoder::start(MetaData *params) { 49 CHECK(!mStarted); 50 51 mBufferGroup = new MediaBufferGroup; 52 mBufferGroup->add_buffer( 53 new MediaBuffer(kNumSamplesPerFrame * sizeof(int16_t))); 54 55 CHECK_EQ(GSMInitDecode(&mState, (Word8 *)"AMRNBDecoder"), 0); 56 57 mSource->start(); 58 59 mAnchorTimeUs = 0; 60 mNumSamplesOutput = 0; 61 mStarted = true; 62 63 return OK; 64 } 65 66 status_t AMRNBDecoder::stop() { 67 CHECK(mStarted); 68 69 if (mInputBuffer) { 70 mInputBuffer->release(); 71 mInputBuffer = NULL; 72 } 73 74 delete mBufferGroup; 75 mBufferGroup = NULL; 76 77 GSMDecodeFrameExit(&mState); 78 79 mSource->stop(); 80 81 mStarted = false; 82 83 return OK; 84 } 85 86 sp<MetaData> AMRNBDecoder::getFormat() { 87 sp<MetaData> srcFormat = mSource->getFormat(); 88 89 int32_t numChannels; 90 int32_t sampleRate; 91 92 CHECK(srcFormat->findInt32(kKeyChannelCount, &numChannels)); 93 CHECK_EQ(numChannels, 1); 94 95 CHECK(srcFormat->findInt32(kKeySampleRate, &sampleRate)); 96 CHECK_EQ(sampleRate, kSampleRate); 97 98 sp<MetaData> meta = new MetaData; 99 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW); 100 meta->setInt32(kKeyChannelCount, numChannels); 101 meta->setInt32(kKeySampleRate, sampleRate); 102 103 int64_t durationUs; 104 if (srcFormat->findInt64(kKeyDuration, &durationUs)) { 105 meta->setInt64(kKeyDuration, durationUs); 106 } 107 108 meta->setCString(kKeyDecoderComponent, "AMRNBDecoder"); 109 110 return meta; 111 } 112 113 status_t AMRNBDecoder::read( 114 MediaBuffer **out, const ReadOptions *options) { 115 status_t err; 116 117 *out = NULL; 118 119 int64_t seekTimeUs; 120 if (options && options->getSeekTo(&seekTimeUs)) { 121 CHECK(seekTimeUs >= 0); 122 123 mNumSamplesOutput = 0; 124 125 if (mInputBuffer) { 126 mInputBuffer->release(); 127 mInputBuffer = NULL; 128 } 129 } else { 130 seekTimeUs = -1; 131 } 132 133 if (mInputBuffer == NULL) { 134 err = mSource->read(&mInputBuffer, options); 135 136 if (err != OK) { 137 return err; 138 } 139 140 int64_t timeUs; 141 if (mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) { 142 mAnchorTimeUs = timeUs; 143 mNumSamplesOutput = 0; 144 } else { 145 // We must have a new timestamp after seeking. 146 CHECK(seekTimeUs < 0); 147 } 148 } 149 150 MediaBuffer *buffer; 151 CHECK_EQ(mBufferGroup->acquire_buffer(&buffer), OK); 152 153 const uint8_t *inputPtr = 154 (const uint8_t *)mInputBuffer->data() + mInputBuffer->range_offset(); 155 156 size_t numBytesRead = 157 AMRDecode(mState, 158 (Frame_Type_3GPP)((inputPtr[0] >> 3) & 0x0f), 159 (UWord8 *)&inputPtr[1], 160 static_cast<int16_t *>(buffer->data()), 161 MIME_IETF); 162 163 ++numBytesRead; // Include the frame type header byte. 164 165 buffer->set_range(0, kNumSamplesPerFrame * sizeof(int16_t)); 166 167 if (numBytesRead > mInputBuffer->range_length()) { 168 // This is bad, should never have happened, but did. Abort now. 169 170 buffer->release(); 171 buffer = NULL; 172 173 return ERROR_MALFORMED; 174 } 175 176 mInputBuffer->set_range( 177 mInputBuffer->range_offset() + numBytesRead, 178 mInputBuffer->range_length() - numBytesRead); 179 180 if (mInputBuffer->range_length() == 0) { 181 mInputBuffer->release(); 182 mInputBuffer = NULL; 183 } 184 185 buffer->meta_data()->setInt64( 186 kKeyTime, 187 mAnchorTimeUs 188 + (mNumSamplesOutput * 1000000) / kSampleRate); 189 190 mNumSamplesOutput += kNumSamplesPerFrame; 191 192 *out = buffer; 193 194 return OK; 195 } 196 197 } // namespace android 198