2 * Copyright (C) 2009 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include "AMRNBEncoder.h"
19 #include "gsmamr_enc.h"
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>
29 static const int32_t kNumSamplesPerFrame = 160;
30 static const int32_t kSampleRate = 8000;
32 AMRNBEncoder::AMRNBEncoder(const sp<MediaSource> &source, const sp<MetaData> &meta)
46 AMRNBEncoder::~AMRNBEncoder() {
52 static Mode PickModeFromBitrate(int32_t bps) {
55 } else if (bps <= 5150) {
57 } else if (bps <= 5900) {
59 } else if (bps <= 6700) {
61 } else if (bps <= 7400) {
63 } else if (bps <= 7950) {
65 } else if (bps <= 10200) {
72 status_t AMRNBEncoder::start(MetaData *params) {
74 LOGW("Call start() when encoder already started");
78 mBufferGroup = new MediaBufferGroup;
79 mBufferGroup->add_buffer(new MediaBuffer(32));
81 CHECK_EQ(AMREncodeInit(
82 &mEncState, &mSidState, false /* dtx_enable */),
85 mSource->start(params);
93 if (params && params->findInt32(kKeyBitRate, &bitrate)) {
94 mMode = PickModeFromBitrate(bitrate);
102 status_t AMRNBEncoder::stop() {
104 LOGW("Call stop() when encoder has not started.");
109 mInputBuffer->release();
118 AMREncodeExit(&mEncState, &mSidState);
119 mEncState = mSidState = NULL;
126 sp<MetaData> AMRNBEncoder::getFormat() {
127 sp<MetaData> srcFormat = mSource->getFormat();
129 mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_NB);
132 if (srcFormat->findInt64(kKeyDuration, &durationUs)) {
133 mMeta->setInt64(kKeyDuration, durationUs);
136 mMeta->setCString(kKeyDecoderComponent, "AMRNBEncoder");
141 status_t AMRNBEncoder::read(
142 MediaBuffer **out, const ReadOptions *options) {
148 ReadOptions::SeekMode mode;
149 CHECK(options == NULL || !options->getSeekTo(&seekTimeUs, &mode));
150 bool readFromSource = false;
151 int64_t wallClockTimeUs = -1;
153 while (mNumInputSamples < kNumSamplesPerFrame) {
154 if (mInputBuffer == NULL) {
155 err = mSource->read(&mInputBuffer, options);
158 if (mNumInputSamples == 0) {
159 return ERROR_END_OF_STREAM;
161 memset(&mInputFrame[mNumInputSamples],
164 * (kNumSamplesPerFrame - mNumInputSamples));
165 mNumInputSamples = kNumSamplesPerFrame;
169 size_t align = mInputBuffer->range_length() % sizeof(int16_t);
171 readFromSource = true;
174 if (mInputBuffer->meta_data()->findInt64(kKeyDriftTime, &timeUs)) {
175 wallClockTimeUs = timeUs;
177 if (mInputBuffer->meta_data()->findInt64(kKeyAnchorTime, &timeUs)) {
178 mAnchorTimeUs = timeUs;
181 readFromSource = false;
185 (kNumSamplesPerFrame - mNumInputSamples) * sizeof(int16_t);
187 if (copy > mInputBuffer->range_length()) {
188 copy = mInputBuffer->range_length();
191 memcpy(&mInputFrame[mNumInputSamples],
192 (const uint8_t *)mInputBuffer->data()
193 + mInputBuffer->range_offset(),
196 mNumInputSamples += copy / sizeof(int16_t);
198 mInputBuffer->set_range(
199 mInputBuffer->range_offset() + copy,
200 mInputBuffer->range_length() - copy);
202 if (mInputBuffer->range_length() == 0) {
203 mInputBuffer->release();
209 CHECK_EQ(mBufferGroup->acquire_buffer(&buffer), OK);
211 uint8_t *outPtr = (uint8_t *)buffer->data();
213 Frame_Type_3GPP frameType;
215 mEncState, mSidState, (Mode)mMode,
216 mInputFrame, outPtr, &frameType, AMR_TX_WMF);
219 CHECK((size_t)res < buffer->size());
221 // Convert header byte from WMF to IETF format.
222 outPtr[0] = ((outPtr[0] << 3) | 4) & 0x7c;
224 buffer->set_range(0, res);
226 // Each frame of 160 samples is 20ms long.
227 int64_t mediaTimeUs = mNumFramesOutput * 20000LL;
228 buffer->meta_data()->setInt64(
229 kKeyTime, mAnchorTimeUs + mediaTimeUs);
231 if (readFromSource && wallClockTimeUs != -1) {
232 buffer->meta_data()->setInt64(kKeyDriftTime,
233 mediaTimeUs - wallClockTimeUs);
240 mNumInputSamples = 0;
245 } // namespace android