OSDN Git Service

original
[gb-231r1-is01/Gingerbread_2.3.3_r1_IS01.git] / frameworks / base / media / libstagefright / codecs / amrnb / enc / AMRNBEncoder.cpp
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     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
102 status_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
126 sp<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
141 status_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