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