1/* 2 * Copyright (C) 2010 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//#define LOG_NDEBUG 0 18#define LOG_TAG "AMRWBEncoder" 19#include <utils/Log.h> 20 21#include "AMRWBEncoder.h" 22#include "voAMRWB.h" 23#include "cmnMemory.h" 24 25#include <media/stagefright/MediaBufferGroup.h> 26#include <media/stagefright/MediaDebug.h> 27#include <media/stagefright/MediaDefs.h> 28#include <media/stagefright/MediaErrors.h> 29#include <media/stagefright/MetaData.h> 30 31namespace android { 32 33static const int32_t kNumSamplesPerFrame = 320; 34static const int32_t kBitsPerSample = 16; 35static const int32_t kInputBufferSize = (kBitsPerSample / 8) * kNumSamplesPerFrame; 36static const int32_t kSampleRate = 16000; 37static const int32_t kNumChannels = 1; 38 39AMRWBEncoder::AMRWBEncoder(const sp<MediaSource> &source, const sp<MetaData> &meta) 40 : mSource(source), 41 mMeta(meta), 42 mStarted(false), 43 mBufferGroup(NULL), 44 mInputBuffer(NULL), 45 mEncoderHandle(NULL), 46 mApiHandle(NULL), 47 mMemOperator(NULL), 48 mAnchorTimeUs(0), 49 mNumFramesOutput(0), 50 mNumInputSamples(0) { 51} 52 53static VOAMRWBMODE pickModeFromBitRate(int32_t bps) { 54 CHECK(bps >= 0); 55 if (bps <= 6600) { 56 return VOAMRWB_MD66; 57 } else if (bps <= 8850) { 58 return VOAMRWB_MD885; 59 } else if (bps <= 12650) { 60 return VOAMRWB_MD1265; 61 } else if (bps <= 14250) { 62 return VOAMRWB_MD1425; 63 } else if (bps <= 15850) { 64 return VOAMRWB_MD1585; 65 } else if (bps <= 18250) { 66 return VOAMRWB_MD1825; 67 } else if (bps <= 19850) { 68 return VOAMRWB_MD1985; 69 } else if (bps <= 23050) { 70 return VOAMRWB_MD2305; 71 } 72 return VOAMRWB_MD2385; 73} 74 75status_t AMRWBEncoder::initCheck() { 76 CHECK(mApiHandle == NULL && mEncoderHandle == NULL); 77 CHECK(mMeta->findInt32(kKeyBitRate, &mBitRate)); 78 79 mApiHandle = new VO_AUDIO_CODECAPI; 80 CHECK(mApiHandle); 81 82 if (VO_ERR_NONE != voGetAMRWBEncAPI(mApiHandle)) { 83 LOGE("Failed to get api handle"); 84 return UNKNOWN_ERROR; 85 } 86 87 mMemOperator = new VO_MEM_OPERATOR; 88 CHECK(mMemOperator != NULL); 89 mMemOperator->Alloc = cmnMemAlloc; 90 mMemOperator->Copy = cmnMemCopy; 91 mMemOperator->Free = cmnMemFree; 92 mMemOperator->Set = cmnMemSet; 93 mMemOperator->Check = cmnMemCheck; 94 95 VO_CODEC_INIT_USERDATA userData; 96 memset(&userData, 0, sizeof(userData)); 97 userData.memflag = VO_IMF_USERMEMOPERATOR; 98 userData.memData = (VO_PTR) mMemOperator; 99 if (VO_ERR_NONE != mApiHandle->Init(&mEncoderHandle, VO_AUDIO_CodingAMRWB, &userData)) { 100 LOGE("Failed to init AMRWB encoder"); 101 return UNKNOWN_ERROR; 102 } 103 104 // Configure AMRWB encoder$ 105 VOAMRWBMODE mode = pickModeFromBitRate(mBitRate); 106 if (VO_ERR_NONE != mApiHandle->SetParam(mEncoderHandle, VO_PID_AMRWB_MODE, &mode)) { 107 LOGE("Failed to set AMRWB encoder mode to %d", mode); 108 return UNKNOWN_ERROR; 109 } 110 111 VOAMRWBFRAMETYPE type = VOAMRWB_RFC3267; 112 if (VO_ERR_NONE != mApiHandle->SetParam(mEncoderHandle, VO_PID_AMRWB_FRAMETYPE, &type)) { 113 LOGE("Failed to set AMRWB encoder frame type to %d", type); 114 return UNKNOWN_ERROR; 115 } 116 117 return OK; 118} 119 120AMRWBEncoder::~AMRWBEncoder() { 121 if (mStarted) { 122 stop(); 123 } 124} 125 126status_t AMRWBEncoder::start(MetaData *params) { 127 if (mStarted) { 128 LOGW("Call start() when encoder already started"); 129 return OK; 130 } 131 132 mBufferGroup = new MediaBufferGroup; 133 134 // The largest buffer size is header + 477 bits 135 mBufferGroup->add_buffer(new MediaBuffer(1024)); 136 137 CHECK_EQ(OK, initCheck()); 138 139 mNumFramesOutput = 0; 140 141 status_t err = mSource->start(params); 142 if (err != OK) { 143 LOGE("AudioSource is not available"); 144 return err; 145 } 146 mStarted = true; 147 148 return OK; 149} 150 151status_t AMRWBEncoder::stop() { 152 if (!mStarted) { 153 LOGW("Call stop() when encoder has not started"); 154 return OK; 155 } 156 157 if (mInputBuffer) { 158 mInputBuffer->release(); 159 mInputBuffer = NULL; 160 } 161 162 delete mBufferGroup; 163 mBufferGroup = NULL; 164 165 166 CHECK_EQ(VO_ERR_NONE, mApiHandle->Uninit(mEncoderHandle)); 167 mEncoderHandle = NULL; 168 169 delete mApiHandle; 170 mApiHandle = NULL; 171 172 delete mMemOperator; 173 mMemOperator; 174 175 mStarted = false; 176 177 mSource->stop(); 178 return OK; 179} 180 181sp<MetaData> AMRWBEncoder::getFormat() { 182 sp<MetaData> srcFormat = mSource->getFormat(); 183 184 mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_WB); 185 186 int64_t durationUs; 187 if (srcFormat->findInt64(kKeyDuration, &durationUs)) { 188 mMeta->setInt64(kKeyDuration, durationUs); 189 } 190 191 mMeta->setCString(kKeyDecoderComponent, "AMRWBEncoder"); 192 193 return mMeta; 194} 195 196status_t AMRWBEncoder::read( 197 MediaBuffer **out, const ReadOptions *options) { 198 status_t err; 199 200 *out = NULL; 201 202 int64_t seekTimeUs; 203 ReadOptions::SeekMode mode; 204 CHECK(options == NULL || !options->getSeekTo(&seekTimeUs, &mode)); 205 bool readFromSource = false; 206 int64_t wallClockTimeUs = -1; 207 208 while (mNumInputSamples < kNumSamplesPerFrame) { 209 if (mInputBuffer == NULL) { 210 err = mSource->read(&mInputBuffer, options); 211 212 if (err != OK) { 213 if (mNumInputSamples == 0) { 214 return ERROR_END_OF_STREAM; 215 } 216 memset(&mInputFrame[mNumInputSamples], 217 0, 218 sizeof(int16_t) 219 * (kNumSamplesPerFrame - mNumInputSamples)); 220 mNumInputSamples = 0; 221 break; 222 } 223 224 size_t align = mInputBuffer->range_length() % sizeof(int16_t); 225 CHECK_EQ(align, 0); 226 227 int64_t timeUs; 228 if (mInputBuffer->meta_data()->findInt64(kKeyDriftTime, &timeUs)) { 229 wallClockTimeUs = timeUs; 230 } 231 if (mInputBuffer->meta_data()->findInt64(kKeyAnchorTime, &timeUs)) { 232 mAnchorTimeUs = timeUs; 233 } 234 readFromSource = true; 235 } else { 236 readFromSource = false; 237 } 238 239 size_t copy = 240 (kNumSamplesPerFrame - mNumInputSamples) * sizeof(int16_t); 241 242 if (copy > mInputBuffer->range_length()) { 243 copy = mInputBuffer->range_length(); 244 } 245 246 memcpy(&mInputFrame[mNumInputSamples], 247 (const uint8_t *)mInputBuffer->data() 248 + mInputBuffer->range_offset(), 249 copy); 250 251 mInputBuffer->set_range( 252 mInputBuffer->range_offset() + copy, 253 mInputBuffer->range_length() - copy); 254 255 if (mInputBuffer->range_length() == 0) { 256 mInputBuffer->release(); 257 mInputBuffer = NULL; 258 } 259 260 mNumInputSamples += copy / sizeof(int16_t); 261 if (mNumInputSamples >= kNumSamplesPerFrame) { 262 mNumInputSamples %= kNumSamplesPerFrame; 263 break; // Get a whole input frame 640 bytes 264 } 265 } 266 267 VO_CODECBUFFER inputData; 268 memset(&inputData, 0, sizeof(inputData)); 269 inputData.Buffer = (unsigned char*) mInputFrame; 270 inputData.Length = kInputBufferSize; 271 CHECK(VO_ERR_NONE == mApiHandle->SetInputData(mEncoderHandle,&inputData)); 272 273 MediaBuffer *buffer; 274 CHECK_EQ(mBufferGroup->acquire_buffer(&buffer), OK); 275 uint8_t *outPtr = (uint8_t *)buffer->data(); 276 277 VO_CODECBUFFER outputData; 278 memset(&outputData, 0, sizeof(outputData)); 279 VO_AUDIO_OUTPUTINFO outputInfo; 280 memset(&outputInfo, 0, sizeof(outputInfo)); 281 282 VO_U32 ret = VO_ERR_NONE; 283 outputData.Buffer = outPtr; 284 outputData.Length = buffer->size(); 285 ret = mApiHandle->GetOutputData(mEncoderHandle, &outputData, &outputInfo); 286 CHECK(ret == VO_ERR_NONE || ret == VO_ERR_INPUT_BUFFER_SMALL); 287 288 buffer->set_range(0, outputData.Length); 289 ++mNumFramesOutput; 290 291 int64_t mediaTimeUs = mNumFramesOutput * 20000LL; 292 buffer->meta_data()->setInt64(kKeyTime, mAnchorTimeUs + mediaTimeUs); 293 if (readFromSource && wallClockTimeUs != -1) { 294 buffer->meta_data()->setInt64(kKeyDriftTime, mediaTimeUs - wallClockTimeUs); 295 } 296 297 *out = buffer; 298 return OK; 299} 300 301} // namespace android 302