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 #define LOG_TAG "C2SoftG711Dec"
19 #include <log/log.h>
20
21 #include <media/stagefright/foundation/MediaDefs.h>
22
23 #include <C2PlatformSupport.h>
24 #include <SimpleC2Interface.h>
25 #include <g711Dec.h>
26 #include "C2SoftG711Dec.h"
27
28 namespace android {
29
30 namespace {
31
32 #ifdef ALAW
33 constexpr char COMPONENT_NAME[] = "c2.android.g711.alaw.decoder";
34 #else
35 constexpr char COMPONENT_NAME[] = "c2.android.g711.mlaw.decoder";
36 #endif
37
38 } // namespace
39
40 class C2SoftG711Dec::IntfImpl : public SimpleInterface<void>::BaseParams {
41 public:
IntfImpl(const std::shared_ptr<C2ReflectorHelper> & helper)42 explicit IntfImpl(const std::shared_ptr<C2ReflectorHelper> &helper)
43 : SimpleInterface<void>::BaseParams(
44 helper,
45 COMPONENT_NAME,
46 C2Component::KIND_DECODER,
47 C2Component::DOMAIN_AUDIO,
48 #ifdef ALAW
49 MEDIA_MIMETYPE_AUDIO_G711_ALAW
50 #else
51 MEDIA_MIMETYPE_AUDIO_G711_MLAW
52 #endif
53 ) {
54 noPrivateBuffers();
55 noInputReferences();
56 noOutputReferences();
57 noInputLatency();
58 noTimeStretch();
59 setDerivedInstance(this);
60
61 addParameter(
62 DefineParam(mAttrib, C2_PARAMKEY_COMPONENT_ATTRIBUTES)
63 .withConstValue(new C2ComponentAttributesSetting(
64 C2Component::ATTRIB_IS_TEMPORAL))
65 .build());
66
67 addParameter(
68 DefineParam(mSampleRate, C2_PARAMKEY_SAMPLE_RATE)
69 .withDefault(new C2StreamSampleRateInfo::output(0u, 8000))
70 .withFields({C2F(mSampleRate, value).inRange(8000, 48000)})
71 .withSetter((Setter<decltype(*mSampleRate)>::StrictValueWithNoDeps))
72 .build());
73
74 addParameter(
75 DefineParam(mChannelCount, C2_PARAMKEY_CHANNEL_COUNT)
76 .withDefault(new C2StreamChannelCountInfo::output(0u, 1))
77 .withFields({C2F(mChannelCount, value).inRange(1, 6)})
78 .withSetter(Setter<decltype(*mChannelCount)>::StrictValueWithNoDeps)
79 .build());
80
81 addParameter(
82 DefineParam(mBitrate, C2_PARAMKEY_BITRATE)
83 .withDefault(new C2StreamBitrateInfo::input(0u, 64000))
84 .withFields({C2F(mBitrate, value).equalTo(64000)})
85 .withSetter(Setter<decltype(*mBitrate)>::NonStrictValueWithNoDeps)
86 .build());
87
88 addParameter(
89 DefineParam(mInputMaxBufSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE)
90 .withConstValue(new C2StreamMaxBufferSizeInfo::input(0u, 8192))
91 .build());
92 }
93
94 private:
95 std::shared_ptr<C2StreamSampleRateInfo::output> mSampleRate;
96 std::shared_ptr<C2StreamChannelCountInfo::output> mChannelCount;
97 std::shared_ptr<C2StreamBitrateInfo::input> mBitrate;
98 std::shared_ptr<C2StreamMaxBufferSizeInfo::input> mInputMaxBufSize;
99 };
100
C2SoftG711Dec(const char * name,c2_node_id_t id,const std::shared_ptr<IntfImpl> & intfImpl)101 C2SoftG711Dec::C2SoftG711Dec(
102 const char *name,
103 c2_node_id_t id,
104 const std::shared_ptr<IntfImpl> &intfImpl)
105 : SimpleC2Component(std::make_shared<SimpleInterface<IntfImpl>>(name, id, intfImpl)),
106 mIntf(intfImpl) {
107 }
108
C2SoftG711Dec(const char * name,c2_node_id_t id,const std::shared_ptr<C2ReflectorHelper> & helper)109 C2SoftG711Dec::C2SoftG711Dec(
110 const char *name,
111 c2_node_id_t id,
112 const std::shared_ptr<C2ReflectorHelper> &helper)
113 : C2SoftG711Dec(name, id, std::make_shared<IntfImpl>(helper)) {
114 }
115
~C2SoftG711Dec()116 C2SoftG711Dec::~C2SoftG711Dec() {
117 onRelease();
118 }
119
onInit()120 c2_status_t C2SoftG711Dec::onInit() {
121 mSignalledOutputEos = false;
122 return C2_OK;
123 }
124
onStop()125 c2_status_t C2SoftG711Dec::onStop() {
126 mSignalledOutputEos = false;
127 return C2_OK;
128 }
129
onReset()130 void C2SoftG711Dec::onReset() {
131 (void)onStop();
132 }
133
onRelease()134 void C2SoftG711Dec::onRelease() {
135 }
136
onFlush_sm()137 c2_status_t C2SoftG711Dec::onFlush_sm() {
138 return onStop();
139 }
140
process(const std::unique_ptr<C2Work> & work,const std::shared_ptr<C2BlockPool> & pool)141 void C2SoftG711Dec::process(
142 const std::unique_ptr<C2Work> &work,
143 const std::shared_ptr<C2BlockPool> &pool) {
144 // Initialize output work
145 work->result = C2_OK;
146 work->workletsProcessed = 1u;
147 work->worklets.front()->output.flags = work->input.flags;
148
149 if (mSignalledOutputEos) {
150 work->result = C2_BAD_VALUE;
151 return;
152 }
153
154 C2ReadView rView = mDummyReadView;
155 size_t inOffset = 0u;
156 size_t inSize = 0u;
157 if (!work->input.buffers.empty()) {
158 rView = work->input.buffers[0]->data().linearBlocks().front().map().get();
159 inSize = rView.capacity();
160 if (inSize && rView.error()) {
161 ALOGE("read view map failed %d", rView.error());
162 work->result = C2_CORRUPTED;
163 return;
164 }
165 }
166 bool eos = (work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0;
167 int outSize = inSize * sizeof(int16_t);
168
169 ALOGV("in buffer attr. size %zu timestamp %d frameindex %d", inSize,
170 (int)work->input.ordinal.timestamp.peeku(), (int)work->input.ordinal.frameIndex.peeku());
171
172 if (inSize == 0) {
173 work->worklets.front()->output.flags = work->input.flags;
174 work->worklets.front()->output.buffers.clear();
175 work->worklets.front()->output.ordinal = work->input.ordinal;
176 if (eos) {
177 mSignalledOutputEos = true;
178 ALOGV("signalled EOS");
179 }
180 return;
181 }
182
183 uint8_t *inputptr = const_cast<uint8_t *>(rView.data() + inOffset);
184
185 std::shared_ptr<C2LinearBlock> block;
186 C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
187 c2_status_t err = pool->fetchLinearBlock(outSize, usage, &block);
188 if (err != C2_OK) {
189 ALOGE("fetchLinearBlock for Output failed with status %d", err);
190 work->result = C2_NO_MEMORY;
191 return;
192 }
193 C2WriteView wView = block->map().get();
194 if (wView.error()) {
195 ALOGE("write view map failed %d", wView.error());
196 work->result = C2_CORRUPTED;
197 return;
198 }
199 int16_t *outputptr = reinterpret_cast<int16_t *>(wView.data());
200
201 #ifdef ALAW
202 DecodeALaw(outputptr, inputptr, inSize);
203 #else
204 DecodeMLaw(outputptr, inputptr, inSize);
205 #endif
206
207 work->worklets.front()->output.flags = work->input.flags;
208 work->worklets.front()->output.buffers.clear();
209 work->worklets.front()->output.buffers.push_back(createLinearBuffer(block, 0, outSize));
210 work->worklets.front()->output.ordinal = work->input.ordinal;
211
212 if (eos) {
213 mSignalledOutputEos = true;
214 ALOGV("signalled EOS");
215 }
216 }
217
drain(uint32_t drainMode,const std::shared_ptr<C2BlockPool> & pool)218 c2_status_t C2SoftG711Dec::drain(
219 uint32_t drainMode,
220 const std::shared_ptr<C2BlockPool> &pool) {
221 (void) pool;
222 if (drainMode == NO_DRAIN) {
223 ALOGW("drain with NO_DRAIN: no-op");
224 return C2_OK;
225 }
226 if (drainMode == DRAIN_CHAIN) {
227 ALOGW("DRAIN_CHAIN not supported");
228 return C2_OMITTED;
229 }
230
231 return C2_OK;
232 }
233
234 class C2SoftG711DecFactory : public C2ComponentFactory {
235 public:
C2SoftG711DecFactory()236 C2SoftG711DecFactory() : mHelper(std::static_pointer_cast<C2ReflectorHelper>(
237 GetCodec2PlatformComponentStore()->getParamReflector())) {
238 }
239
createComponent(c2_node_id_t id,std::shared_ptr<C2Component> * const component,std::function<void (C2Component *)> deleter)240 virtual c2_status_t createComponent(
241 c2_node_id_t id,
242 std::shared_ptr<C2Component>* const component,
243 std::function<void(C2Component*)> deleter) override {
244 *component = std::shared_ptr<C2Component>(
245 new C2SoftG711Dec(COMPONENT_NAME, id,
246 std::make_shared<C2SoftG711Dec::IntfImpl>(mHelper)),
247 deleter);
248 return C2_OK;
249 }
250
createInterface(c2_node_id_t id,std::shared_ptr<C2ComponentInterface> * const interface,std::function<void (C2ComponentInterface *)> deleter)251 virtual c2_status_t createInterface(
252 c2_node_id_t id, std::shared_ptr<C2ComponentInterface>* const interface,
253 std::function<void(C2ComponentInterface*)> deleter) override {
254 *interface = std::shared_ptr<C2ComponentInterface>(
255 new SimpleInterface<C2SoftG711Dec::IntfImpl>(
256 COMPONENT_NAME, id, std::make_shared<C2SoftG711Dec::IntfImpl>(mHelper)),
257 deleter);
258 return C2_OK;
259 }
260
261 virtual ~C2SoftG711DecFactory() override = default;
262
263 private:
264 std::shared_ptr<C2ReflectorHelper> mHelper;
265 };
266
267 } // namespace android
268
269 __attribute__((cfi_canonical_jump_table))
CreateCodec2Factory()270 extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
271 ALOGV("in %s", __func__);
272 return new ::android::C2SoftG711DecFactory();
273 }
274
275 __attribute__((cfi_canonical_jump_table))
DestroyCodec2Factory(::C2ComponentFactory * factory)276 extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
277 ALOGV("in %s", __func__);
278 delete factory;
279 }
280