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                 RX_State_wb rx_state;
340                 int16_t numRecSamples;
341 
342                 mime_unsorting(const_cast<uint8_t *>(&input[1]),
343                                mInputSampleBuffer, &FT, &FM, 1, &rx_state);
344                 pvDecoder_AmrWb(FM, mInputSampleBuffer, output, &numRecSamples,
345                                 mDecoderBuf, FT, mDecoderCookie);
346                 if (numRecSamples != outSamples) {
347                     ALOGE("Sample output per frame incorrect");
348                     work->result = C2_CORRUPTED;
349                     mSignalledError = true;
350                     return;
351                 }
352                 /* Delete the 2 LSBs (14-bit output) */
353                 for (int i = 0; i < numRecSamples; ++i) {
354                     output[i] &= 0xfffC;
355                 }
356             }
357         }
358         inPos += *it;
359         output += outSamples;
360         ++it;
361     }
362 
363     work->worklets.front()->output.flags = work->input.flags;
364     work->worklets.front()->output.buffers.clear();
365     work->worklets.front()->output.buffers.push_back(createLinearBuffer(block));
366     work->worklets.front()->output.ordinal = work->input.ordinal;
367     if (eos) {
368         mSignalledOutputEos = true;
369         ALOGV("signalled EOS");
370     }
371 }
372 
drain(uint32_t drainMode,const std::shared_ptr<C2BlockPool> & pool)373 c2_status_t C2SoftAmrDec::drain(
374         uint32_t drainMode,
375         const std::shared_ptr<C2BlockPool> &pool) {
376     (void)pool;
377     if (drainMode == NO_DRAIN) {
378         ALOGW("drain with NO_DRAIN: no-op");
379         return C2_OK;
380     }
381     if (drainMode == DRAIN_CHAIN) {
382         ALOGW("DRAIN_CHAIN not supported");
383         return C2_OMITTED;
384     }
385     return C2_OK;
386 }
387 
388 class C2SoftAMRDecFactory : public C2ComponentFactory {
389 public:
C2SoftAMRDecFactory()390     C2SoftAMRDecFactory() : mHelper(std::static_pointer_cast<C2ReflectorHelper>(
391             GetCodec2PlatformComponentStore()->getParamReflector())) {
392     }
393 
createComponent(c2_node_id_t id,std::shared_ptr<C2Component> * const component,std::function<void (C2Component *)> deleter)394     virtual c2_status_t createComponent(
395             c2_node_id_t id,
396             std::shared_ptr<C2Component>* const component,
397             std::function<void(C2Component*)> deleter) override {
398         *component = std::shared_ptr<C2Component>(
399                 new C2SoftAmrDec(COMPONENT_NAME, id,
400                               std::make_shared<C2SoftAmrDec::IntfImpl>(mHelper)),
401                 deleter);
402         return C2_OK;
403     }
404 
createInterface(c2_node_id_t id,std::shared_ptr<C2ComponentInterface> * const interface,std::function<void (C2ComponentInterface *)> deleter)405     virtual c2_status_t createInterface(
406             c2_node_id_t id,
407             std::shared_ptr<C2ComponentInterface>* const interface,
408             std::function<void(C2ComponentInterface*)> deleter) override {
409         *interface = std::shared_ptr<C2ComponentInterface>(
410                 new SimpleInterface<C2SoftAmrDec::IntfImpl>(
411                         COMPONENT_NAME, id, std::make_shared<C2SoftAmrDec::IntfImpl>(mHelper)),
412                 deleter);
413         return C2_OK;
414     }
415 
416     virtual ~C2SoftAMRDecFactory() override = default;
417 
418 private:
419     std::shared_ptr<C2ReflectorHelper> mHelper;
420 };
421 
422 }  // namespace android
423 
CreateCodec2Factory()424 extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
425     ALOGV("in %s", __func__);
426     return new ::android::C2SoftAMRDecFactory();
427 }
428 
DestroyCodec2Factory(::C2ComponentFactory * factory)429 extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
430     ALOGV("in %s", __func__);
431     delete factory;
432 }
433