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 "AMRNBEncoder.h" 18 19#include "gsmamr_enc.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 27namespace android { 28 29static const int32_t kNumSamplesPerFrame = 160; 30static const int32_t kSampleRate = 8000; 31 32AMRNBEncoder::AMRNBEncoder(const sp<MediaSource> &source, const sp<MetaData> &meta) 33 : mSource(source), 34 mMeta(meta), 35 mStarted(false), 36 mBufferGroup(NULL), 37 mEncState(NULL), 38 mSidState(NULL), 39 mAnchorTimeUs(0), 40 mNumFramesOutput(0), 41 mInputBuffer(NULL), 42 mMode(MR475), 43 mNumInputSamples(0) { 44} 45 46AMRNBEncoder::~AMRNBEncoder() { 47 if (mStarted) { 48 stop(); 49 } 50} 51 52static Mode PickModeFromBitrate(int32_t bps) { 53 if (bps <= 4750) { 54 return MR475; 55 } else if (bps <= 5150) { 56 return MR515; 57 } else if (bps <= 5900) { 58 return MR59; 59 } else if (bps <= 6700) { 60 return MR67; 61 } else if (bps <= 7400) { 62 return MR74; 63 } else if (bps <= 7950) { 64 return MR795; 65 } else if (bps <= 10200) { 66 return MR102; 67 } else { 68 return MR122; 69 } 70} 71 72status_t AMRNBEncoder::start(MetaData *params) { 73 if (mStarted) { 74 LOGW("Call start() when encoder already started"); 75 return OK; 76 } 77 78 mBufferGroup = new MediaBufferGroup; 79 mBufferGroup->add_buffer(new MediaBuffer(32)); 80 81 CHECK_EQ(AMREncodeInit( 82 &mEncState, &mSidState, false /* dtx_enable */), 83 0); 84 85 mSource->start(params); 86 87 mAnchorTimeUs = 0; 88 mNumFramesOutput = 0; 89 mStarted = true; 90 mNumInputSamples = 0; 91 92 int32_t bitrate; 93 if (params && params->findInt32(kKeyBitRate, &bitrate)) { 94 mMode = PickModeFromBitrate(bitrate); 95 } else { 96 mMode = MR475; 97 } 98 99 return OK; 100} 101 102status_t AMRNBEncoder::stop() { 103 if (!mStarted) { 104 LOGW("Call stop() when encoder has not started."); 105 return OK; 106 } 107 108 if (mInputBuffer) { 109 mInputBuffer->release(); 110 mInputBuffer = NULL; 111 } 112 113 delete mBufferGroup; 114 mBufferGroup = NULL; 115 116 mSource->stop(); 117 118 AMREncodeExit(&mEncState, &mSidState); 119 mEncState = mSidState = NULL; 120 121 mStarted = false; 122 123 return OK; 124} 125 126sp<MetaData> AMRNBEncoder::getFormat() { 127 sp<MetaData> srcFormat = mSource->getFormat(); 128 129 mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_NB); 130 131 int64_t durationUs; 132 if (srcFormat->findInt64(kKeyDuration, &durationUs)) { 133 mMeta->setInt64(kKeyDuration, durationUs); 134 } 135 136 mMeta->setCString(kKeyDecoderComponent, "AMRNBEncoder"); 137 138 return mMeta; 139} 140 141status_t AMRNBEncoder::read( 142 MediaBuffer **out, const ReadOptions *options) { 143 status_t err; 144 145 *out = NULL; 146 147 int64_t seekTimeUs; 148 ReadOptions::SeekMode mode; 149 CHECK(options == NULL || !options->getSeekTo(&seekTimeUs, &mode)); 150 bool readFromSource = false; 151 int64_t wallClockTimeUs = -1; 152 153 while (mNumInputSamples < kNumSamplesPerFrame) { 154 if (mInputBuffer == NULL) { 155 err = mSource->read(&mInputBuffer, options); 156 157 if (err != OK) { 158 if (mNumInputSamples == 0) { 159 return ERROR_END_OF_STREAM; 160 } 161 memset(&mInputFrame[mNumInputSamples], 162 0, 163 sizeof(int16_t) 164 * (kNumSamplesPerFrame - mNumInputSamples)); 165 mNumInputSamples = kNumSamplesPerFrame; 166 break; 167 } 168 169 size_t align = mInputBuffer->range_length() % sizeof(int16_t); 170 CHECK_EQ(align, 0); 171 readFromSource = true; 172 173 int64_t timeUs; 174 if (mInputBuffer->meta_data()->findInt64(kKeyDriftTime, &timeUs)) { 175 wallClockTimeUs = timeUs; 176 } 177 if (mInputBuffer->meta_data()->findInt64(kKeyAnchorTime, &timeUs)) { 178 mAnchorTimeUs = timeUs; 179 } 180 } else { 181 readFromSource = false; 182 } 183 184 size_t copy = 185 (kNumSamplesPerFrame - mNumInputSamples) * sizeof(int16_t); 186 187 if (copy > mInputBuffer->range_length()) { 188 copy = mInputBuffer->range_length(); 189 } 190 191 memcpy(&mInputFrame[mNumInputSamples], 192 (const uint8_t *)mInputBuffer->data() 193 + mInputBuffer->range_offset(), 194 copy); 195 196 mNumInputSamples += copy / sizeof(int16_t); 197 198 mInputBuffer->set_range( 199 mInputBuffer->range_offset() + copy, 200 mInputBuffer->range_length() - copy); 201 202 if (mInputBuffer->range_length() == 0) { 203 mInputBuffer->release(); 204 mInputBuffer = NULL; 205 } 206 } 207 208 MediaBuffer *buffer; 209 CHECK_EQ(mBufferGroup->acquire_buffer(&buffer), OK); 210 211 uint8_t *outPtr = (uint8_t *)buffer->data(); 212 213 Frame_Type_3GPP frameType; 214 int res = AMREncode( 215 mEncState, mSidState, (Mode)mMode, 216 mInputFrame, outPtr, &frameType, AMR_TX_WMF); 217 218 CHECK(res >= 0); 219 CHECK((size_t)res < buffer->size()); 220 221 // Convert header byte from WMF to IETF format. 222 outPtr[0] = ((outPtr[0] << 3) | 4) & 0x7c; 223 224 buffer->set_range(0, res); 225 226 // Each frame of 160 samples is 20ms long. 227 int64_t mediaTimeUs = mNumFramesOutput * 20000LL; 228 buffer->meta_data()->setInt64( 229 kKeyTime, mAnchorTimeUs + mediaTimeUs); 230 231 if (readFromSource && wallClockTimeUs != -1) { 232 buffer->meta_data()->setInt64(kKeyDriftTime, 233 mediaTimeUs - wallClockTimeUs); 234 } 235 236 ++mNumFramesOutput; 237 238 *out = buffer; 239 240 mNumInputSamples = 0; 241 242 return OK; 243} 244 245} // namespace android 246