1 /*
2  * Copyright (C) 2018 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 #ifdef AMRNB
19 #define LOG_TAG "C2SoftAmrNbDec"
20 #else
21 #define LOG_TAG "C2SoftAmrWbDec"
22 #endif
23 #include <log/log.h>
24 
25 #include <media/stagefright/foundation/MediaDefs.h>
26 
27 #include <C2PlatformSupport.h>
28 #include <SimpleC2Interface.h>
29 
30 #include "C2SoftAmrDec.h"
31 #include "gsmamr_dec.h"
32 #include "pvamrwbdecoder.h"
33 
34 namespace android {
35 
36 namespace {
37 
38 #ifdef AMRNB
39   constexpr char COMPONENT_NAME[] = "c2.android.amrnb.decoder";
40 #else
41   constexpr char COMPONENT_NAME[] = "c2.android.amrwb.decoder";
42 #endif
43 
44 }  // namespace
45 
46 class C2SoftAmrDec::IntfImpl : public SimpleInterface<void>::BaseParams {
47 public:
IntfImpl(const std::shared_ptr<C2ReflectorHelper> & helper)48     explicit IntfImpl(const std::shared_ptr<C2ReflectorHelper> &helper)
49         : SimpleInterface<void>::BaseParams(
50                 helper,
51                 COMPONENT_NAME,
52                 C2Component::KIND_DECODER,
53                 C2Component::DOMAIN_AUDIO,
54 #ifdef AMRNB
55                 MEDIA_MIMETYPE_AUDIO_AMR_NB
56 #else
57                 MEDIA_MIMETYPE_AUDIO_AMR_WB
58 #endif
59                 ) {
60         noPrivateBuffers();
61         noInputReferences();
62         noOutputReferences();
63         noInputLatency();
64         noTimeStretch();
65         setDerivedInstance(this);
66 
67         addParameter(
68                 DefineParam(mAttrib, C2_PARAMKEY_COMPONENT_ATTRIBUTES)
69                 .withConstValue(new C2ComponentAttributesSetting(
70                     C2Component::ATTRIB_IS_TEMPORAL))
71                 .build());
72 
73         addParameter(
74                 DefineParam(mSampleRate, C2_PARAMKEY_SAMPLE_RATE)
75 #ifdef AMRNB
76                 .withDefault(new C2StreamSampleRateInfo::output(0u, 8000))
77                 .withFields({C2F(mSampleRate, value).equalTo(8000)})
78 #else
79                 .withDefault(new C2StreamSampleRateInfo::output(0u, 16000))
80                 .withFields({C2F(mSampleRate, value).equalTo(16000)})
81 #endif
82                 .withSetter((Setter<decltype(*mSampleRate)>::StrictValueWithNoDeps))
83                 .build());
84 
85         addParameter(
86                 DefineParam(mChannelCount, C2_PARAMKEY_CHANNEL_COUNT)
87                 .withDefault(new C2StreamChannelCountInfo::output(0u, 1))
88                 .withFields({C2F(mChannelCount, value).equalTo(1)})
89                 .withSetter((Setter<decltype(*mChannelCount)>::StrictValueWithNoDeps))
90                 .build());
91 
92         addParameter(
93                 DefineParam(mBitrate, C2_PARAMKEY_BITRATE)
94 #ifdef AMRNB
95                 .withDefault(new C2StreamBitrateInfo::input(0u, 4750))
96                 .withFields({C2F(mBitrate, value).inRange(4750, 12200)})
97 #else
98                 .withDefault(new C2StreamBitrateInfo::input(0u, 6600))
99                 .withFields({C2F(mBitrate, value).inRange(6600, 23850)})
100 #endif
101                 .withSetter(Setter<decltype(*mBitrate)>::NonStrictValueWithNoDeps)
102                 .build());
103 
104         addParameter(
105                 DefineParam(mInputMaxBufSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE)
106                 .withConstValue(new C2StreamMaxBufferSizeInfo::input(0u, 8192))
107                 .build());
108     }
109 
110 private:
111     std::shared_ptr<C2StreamSampleRateInfo::output> mSampleRate;
112     std::shared_ptr<C2StreamChannelCountInfo::output> mChannelCount;
113     std::shared_ptr<C2StreamBitrateInfo::input> mBitrate;
114     std::shared_ptr<C2StreamMaxBufferSizeInfo::input> mInputMaxBufSize;
115 };
116 
C2SoftAmrDec(const char * name,c2_node_id_t id,const std::shared_ptr<IntfImpl> & intfImpl)117 C2SoftAmrDec::C2SoftAmrDec(
118         const char *name,
119         c2_node_id_t id,
120         const std::shared_ptr<IntfImpl> &intfImpl)
121     : SimpleC2Component(std::make_shared<SimpleInterface<IntfImpl>>(name, id, intfImpl)),
122       mIntf(intfImpl),
123       mAmrHandle(nullptr),
124       mDecoderBuf(nullptr),
125       mDecoderCookie(nullptr) {
126 #ifdef AMRNB
127     mIsWide = false;
128 #else
129     mIsWide = true;
130 #endif
131 }
132 
~C2SoftAmrDec()133 C2SoftAmrDec::~C2SoftAmrDec() {
134     (void)onRelease();
135 }
136 
onInit()137 c2_status_t C2SoftAmrDec::onInit() {
138     status_t err = initDecoder();
139     return err == OK ? C2_OK : C2_NO_MEMORY;
140 }
141 
onStop()142 c2_status_t C2SoftAmrDec::onStop() {
143     if (!mIsWide) {
144         Speech_Decode_Frame_reset(mAmrHandle);
145     } else {
146         pvDecoder_AmrWb_Reset(mAmrHandle, 0 /* reset_all */);
147     }
148     mSignalledError = false;
149     mSignalledOutputEos = false;
150 
151     return C2_OK;
152 }
153 
onReset()154 void C2SoftAmrDec::onReset() {
155     (void)onStop();
156 }
157 
onRelease()158 void C2SoftAmrDec::onRelease() {
159     if (!mIsWide) {
160         if (mAmrHandle) {
161             GSMDecodeFrameExit(&mAmrHandle);
162         }
163         mAmrHandle = nullptr;
164     } else {
165         if (mDecoderBuf) {
166             free(mDecoderBuf);
167         }
168         mDecoderBuf = nullptr;
169         mAmrHandle = nullptr;
170         mDecoderCookie = nullptr;
171     }
172 }
173 
onFlush_sm()174 c2_status_t C2SoftAmrDec::onFlush_sm() {
175     return onStop();
176 }
177 
initDecoder()178 status_t C2SoftAmrDec::initDecoder() {
179     if (!mIsWide) {
180         if (GSMInitDecode(&mAmrHandle, (int8_t *)"AMRNBDecoder"))
181             return UNKNOWN_ERROR;
182     } else {
183         uint32_t memReq = pvDecoder_AmrWbMemRequirements();
184         mDecoderBuf = malloc(memReq);
185         if (mDecoderBuf) {
186             pvDecoder_AmrWb_Init(&mAmrHandle, mDecoderBuf, &mDecoderCookie);
187         }
188         else {
189             return NO_MEMORY;
190         }
191     }
192     mSignalledError = false;
193     mSignalledOutputEos = false;
194 
195     return OK;
196 }
197 
getFrameSize(bool isWide,unsigned FM)198 static size_t getFrameSize(bool isWide, unsigned FM) {
199     static const size_t kFrameSizeNB[16] = {
200         12, 13, 15, 17, 19, 20, 26, 31,
201         5, 6, 5, 5, // SID
202         0, 0, 0, // future use
203         0 // no data
204     };
205     static const size_t kFrameSizeWB[16] = {
206         17, 23, 32, 36, 40, 46, 50, 58, 60,
207         5, // SID
208         0, 0, 0, 0, // future use
209         0, // speech lost
210         0 // no data
211     };
212 
213     if (FM > 15 || (isWide && FM > 9 && FM < 14) || (!isWide && FM > 11 && FM < 15)) {
214         ALOGE("illegal AMR frame mode %d", FM);
215         return 0;
216     }
217     // add 1 for header byte
218     return (isWide ? kFrameSizeWB[FM] : kFrameSizeNB[FM]) + 1;
219 }
220 
calculateNumFrames(const uint8 * input,size_t inSize,std::vector<size_t> * frameSizeList,bool isWide)221 static status_t calculateNumFrames(const uint8 *input, size_t inSize,
222                                    std::vector<size_t> *frameSizeList, bool isWide) {
223     for (size_t k = 0; k < inSize;) {
224         int16_t FM = ((input[0] >> 3) & 0x0f);
225         size_t frameSize = getFrameSize(isWide, FM);
226         if (frameSize == 0) {
227             return UNKNOWN_ERROR;
228         }
229         if ((inSize - k) >= frameSize) {
230             input += frameSize;
231             k += frameSize;
232         }
233         else break;
234         frameSizeList->push_back(frameSize);
235     }
236     return OK;
237 }
238 
process(const std::unique_ptr<C2Work> & work,const std::shared_ptr<C2BlockPool> & pool)239 void C2SoftAmrDec::process(
240         const std::unique_ptr<C2Work> &work,
241         const std::shared_ptr<C2BlockPool> &pool) {
242     // Initialize output work
243     work->result = C2_OK;
244     work->workletsProcessed = 1u;
245     work->worklets.front()->output.flags = work->input.flags;
246 
247     if (mSignalledError || mSignalledOutputEos) {
248         work->result = C2_BAD_VALUE;
249         return;
250     }
251 
252     C2ReadView rView = mDummyReadView;
253     size_t inOffset = 0u;
254     size_t inSize = 0u;
255     if (!work->input.buffers.empty()) {
256         rView = work->input.buffers[0]->data().linearBlocks().front().map().get();
257         inSize = rView.capacity();
258         if (inSize && rView.error()) {
259             ALOGE("read view map failed %d", rView.error());
260             work->result = rView.error();
261             return;
262         }
263     }
264 
265     bool eos = (work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0;
266     if (inSize == 0) {
267         work->worklets.front()->output.flags = work->input.flags;
268         work->worklets.front()->output.buffers.clear();
269         work->worklets.front()->output.ordinal = work->input.ordinal;
270         if (eos) {
271             mSignalledOutputEos = true;
272             ALOGV("signalled EOS");
273         }
274         return;
275     }
276 
277     ALOGV("in buffer attr. size %zu timestamp %d frameindex %d", inSize,
278           (int)work->input.ordinal.timestamp.peeku(), (int)work->input.ordinal.frameIndex.peeku());
279 
280     std::vector<size_t> frameSizeList;
281     if (OK != calculateNumFrames(rView.data() + inOffset, inSize, &frameSizeList,
282                                  mIsWide)) {
283         work->result = C2_CORRUPTED;
284         mSignalledError = true;
285         return;
286     }
287     if (frameSizeList.empty()) {
288         ALOGE("input size smaller than expected");
289         work->result = C2_CORRUPTED;
290         mSignalledError = true;
291         return;
292     }
293 
294     int16_t outSamples = mIsWide ? kNumSamplesPerFrameWB : kNumSamplesPerFrameNB;
295     size_t calOutSize = outSamples * frameSizeList.size() * sizeof(int16_t);
296     std::shared_ptr<C2LinearBlock> block;
297     C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
298     c2_status_t err = pool->fetchLinearBlock(calOutSize, usage, &block);
299     if (err != C2_OK) {
300         ALOGE("fetchLinearBlock for Output failed with status %d", err);
301         work->result = C2_NO_MEMORY;
302         return;
303     }
304     C2WriteView wView = block->map().get();
305     if (wView.error()) {
306         ALOGE("write view map failed %d", wView.error());
307         work->result = wView.error();
308         return;
309     }
310 
311     int16_t *output = reinterpret_cast<int16_t *>(wView.data());
312     auto it = frameSizeList.begin();
313     const uint8_t *inPtr = rView.data() + inOffset;
314     size_t inPos = 0;
315     while (inPos < inSize) {
316         if (it == frameSizeList.end()) {
317             ALOGD("unexpected trailing bytes, ignoring them");
318             break;
319         }
320         uint8_t *input = const_cast<uint8_t *>(inPtr + inPos);
321         int16_t FM = ((*input >> 3) & 0x0f);
322         if (!mIsWide) {
323             int32_t numBytesRead = AMRDecode(mAmrHandle,
324                                              (Frame_Type_3GPP) FM,
325                                              input + 1, output, MIME_IETF);
326             if (static_cast<size_t>(numBytesRead + 1) != *it) {
327                 ALOGE("panic, parsed size does not match decoded size");
328                 work->result = C2_CORRUPTED;
329                 mSignalledError = true;
330                 return;
331             }
332         } else {
333             if (FM >= 9) {
334                 // Produce silence instead of comfort noise and for
335                 // speech lost/no data.
336                 memset(output, 0, outSamples * sizeof(int16_t));
337             } else {
338                 int16_t FT;
339                 int16_t numRecSamples;
340 
341                 mime_unsorting(const_cast<uint8_t *>(&input[1]),
342                                mInputSampleBuffer, &FT, &FM, 1, &mRxState);
343                 pvDecoder_AmrWb(FM, mInputSampleBuffer, output, &numRecSamples,
344                                 mDecoderBuf, FT, mDecoderCookie);
345                 if (numRecSamples != outSamples) {
346                     ALOGE("Sample output per frame incorrect");
347                     work->result = C2_CORRUPTED;
348                     mSignalledError = true;
349                     return;
350                 }
351                 /* Delete the 2 LSBs (14-bit output) */
352                 for (int i = 0; i < numRecSamples; ++i) {
353                     output[i] &= 0xfffC;
354                 }
355             }
356         }
357         inPos += *it;
358         output += outSamples;
359         ++it;
360     }
361 
362     work->worklets.front()->output.flags = work->input.flags;
363     work->worklets.front()->output.buffers.clear();
364     work->worklets.front()->output.buffers.push_back(createLinearBuffer(block));
365     work->worklets.front()->output.ordinal = work->input.ordinal;
366     if (eos) {
367         mSignalledOutputEos = true;
368         ALOGV("signalled EOS");
369     }
370 }
371 
drain(uint32_t drainMode,const std::shared_ptr<C2BlockPool> & pool)372 c2_status_t C2SoftAmrDec::drain(
373         uint32_t drainMode,
374         const std::shared_ptr<C2BlockPool> &pool) {
375     (void)pool;
376     if (drainMode == NO_DRAIN) {
377         ALOGW("drain with NO_DRAIN: no-op");
378         return C2_OK;
379     }
380     if (drainMode == DRAIN_CHAIN) {
381         ALOGW("DRAIN_CHAIN not supported");
382         return C2_OMITTED;
383     }
384     return C2_OK;
385 }
386 
387 class C2SoftAMRDecFactory : public C2ComponentFactory {
388 public:
C2SoftAMRDecFactory()389     C2SoftAMRDecFactory() : mHelper(std::static_pointer_cast<C2ReflectorHelper>(
390             GetCodec2PlatformComponentStore()->getParamReflector())) {
391     }
392 
createComponent(c2_node_id_t id,std::shared_ptr<C2Component> * const component,std::function<void (C2Component *)> deleter)393     virtual c2_status_t createComponent(
394             c2_node_id_t id,
395             std::shared_ptr<C2Component>* const component,
396             std::function<void(C2Component*)> deleter) override {
397         *component = std::shared_ptr<C2Component>(
398                 new C2SoftAmrDec(COMPONENT_NAME, id,
399                               std::make_shared<C2SoftAmrDec::IntfImpl>(mHelper)),
400                 deleter);
401         return C2_OK;
402     }
403 
createInterface(c2_node_id_t id,std::shared_ptr<C2ComponentInterface> * const interface,std::function<void (C2ComponentInterface *)> deleter)404     virtual c2_status_t createInterface(
405             c2_node_id_t id,
406             std::shared_ptr<C2ComponentInterface>* const interface,
407             std::function<void(C2ComponentInterface*)> deleter) override {
408         *interface = std::shared_ptr<C2ComponentInterface>(
409                 new SimpleInterface<C2SoftAmrDec::IntfImpl>(
410                         COMPONENT_NAME, id, std::make_shared<C2SoftAmrDec::IntfImpl>(mHelper)),
411                 deleter);
412         return C2_OK;
413     }
414 
415     virtual ~C2SoftAMRDecFactory() override = default;
416 
417 private:
418     std::shared_ptr<C2ReflectorHelper> mHelper;
419 };
420 
421 }  // namespace android
422 
CreateCodec2Factory()423 extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
424     ALOGV("in %s", __func__);
425     return new ::android::C2SoftAMRDecFactory();
426 }
427 
DestroyCodec2Factory(::C2ComponentFactory * factory)428 extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
429     ALOGV("in %s", __func__);
430     delete factory;
431 }
432