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 "C2SoftFlacDec"
19 #include <log/log.h>
20
21 #include <media/stagefright/foundation/MediaDefs.h>
22
23 #include <C2PlatformSupport.h>
24 #include <SimpleC2Interface.h>
25
26 #include "C2SoftFlacDec.h"
27
28 namespace android {
29
30 constexpr char COMPONENT_NAME[] = "c2.android.flac.decoder";
31
32 class C2SoftFlacDec::IntfImpl : public C2InterfaceHelper {
33 public:
IntfImpl(const std::shared_ptr<C2ReflectorHelper> & helper)34 explicit IntfImpl(const std::shared_ptr<C2ReflectorHelper> &helper)
35 : C2InterfaceHelper(helper) {
36
37 setDerivedInstance(this);
38
39 addParameter(
40 DefineParam(mInputFormat, C2_NAME_INPUT_STREAM_FORMAT_SETTING)
41 .withConstValue(new C2StreamFormatConfig::input(0u, C2FormatCompressed))
42 .build());
43
44 addParameter(
45 DefineParam(mOutputFormat, C2_NAME_OUTPUT_STREAM_FORMAT_SETTING)
46 .withConstValue(new C2StreamFormatConfig::output(0u, C2FormatAudio))
47 .build());
48
49 addParameter(
50 DefineParam(mInputMediaType, C2_NAME_INPUT_PORT_MIME_SETTING)
51 .withConstValue(AllocSharedString<C2PortMimeConfig::input>(
52 MEDIA_MIMETYPE_AUDIO_FLAC))
53 .build());
54
55 addParameter(
56 DefineParam(mOutputMediaType, C2_NAME_OUTPUT_PORT_MIME_SETTING)
57 .withConstValue(AllocSharedString<C2PortMimeConfig::output>(
58 MEDIA_MIMETYPE_AUDIO_RAW))
59 .build());
60
61 addParameter(
62 DefineParam(mSampleRate, C2_NAME_STREAM_SAMPLE_RATE_SETTING)
63 .withDefault(new C2StreamSampleRateInfo::output(0u, 44100))
64 .withFields({C2F(mSampleRate, value).inRange(1, 655350)})
65 .withSetter((Setter<decltype(*mSampleRate)>::StrictValueWithNoDeps))
66 .build());
67
68 addParameter(
69 DefineParam(mChannelCount, C2_NAME_STREAM_CHANNEL_COUNT_SETTING)
70 .withDefault(new C2StreamChannelCountInfo::output(0u, 1))
71 .withFields({C2F(mChannelCount, value).inRange(1, 8)})
72 .withSetter(Setter<decltype(*mChannelCount)>::StrictValueWithNoDeps)
73 .build());
74
75 addParameter(
76 DefineParam(mBitrate, C2_NAME_STREAM_BITRATE_SETTING)
77 .withDefault(new C2BitrateTuning::input(0u, 768000))
78 .withFields({C2F(mBitrate, value).inRange(1, 21000000)})
79 .withSetter(Setter<decltype(*mBitrate)>::NonStrictValueWithNoDeps)
80 .build());
81 }
82
83 private:
84 std::shared_ptr<C2StreamFormatConfig::input> mInputFormat;
85 std::shared_ptr<C2StreamFormatConfig::output> mOutputFormat;
86 std::shared_ptr<C2PortMimeConfig::input> mInputMediaType;
87 std::shared_ptr<C2PortMimeConfig::output> mOutputMediaType;
88 std::shared_ptr<C2StreamSampleRateInfo::output> mSampleRate;
89 std::shared_ptr<C2StreamChannelCountInfo::output> mChannelCount;
90 std::shared_ptr<C2BitrateTuning::input> mBitrate;
91 };
92
C2SoftFlacDec(const char * name,c2_node_id_t id,const std::shared_ptr<IntfImpl> & intfImpl)93 C2SoftFlacDec::C2SoftFlacDec(
94 const char *name,
95 c2_node_id_t id,
96 const std::shared_ptr<IntfImpl> &intfImpl)
97 : SimpleC2Component(std::make_shared<SimpleInterface<IntfImpl>>(name, id, intfImpl)),
98 mIntf(intfImpl),
99 mFLACDecoder(nullptr) {
100 }
101
~C2SoftFlacDec()102 C2SoftFlacDec::~C2SoftFlacDec() {
103 delete mFLACDecoder;
104 }
105
onInit()106 c2_status_t C2SoftFlacDec::onInit() {
107 status_t err = initDecoder();
108 return err == OK ? C2_OK : C2_NO_MEMORY;
109 }
110
onStop()111 c2_status_t C2SoftFlacDec::onStop() {
112 if (mFLACDecoder) mFLACDecoder->flush();
113 memset(&mStreamInfo, 0, sizeof(mStreamInfo));
114 mHasStreamInfo = false;
115 mSignalledError = false;
116 mSignalledOutputEos = false;
117 mInputBufferCount = 0;
118 return C2_OK;
119 }
120
onReset()121 void C2SoftFlacDec::onReset() {
122 (void)onStop();
123 }
124
onRelease()125 void C2SoftFlacDec::onRelease() {
126 }
127
onFlush_sm()128 c2_status_t C2SoftFlacDec::onFlush_sm() {
129 return onStop();
130 }
131
initDecoder()132 status_t C2SoftFlacDec::initDecoder() {
133 if (mFLACDecoder) {
134 delete mFLACDecoder;
135 }
136 mFLACDecoder = FLACDecoder::Create();
137 if (!mFLACDecoder) {
138 ALOGE("initDecoder: failed to create FLACDecoder");
139 mSignalledError = true;
140 return NO_MEMORY;
141 }
142
143 memset(&mStreamInfo, 0, sizeof(mStreamInfo));
144 mHasStreamInfo = false;
145 mSignalledError = false;
146 mSignalledOutputEos = false;
147 mInputBufferCount = 0;
148
149 return OK;
150 }
151
fillEmptyWork(const std::unique_ptr<C2Work> & work)152 static void fillEmptyWork(const std::unique_ptr<C2Work> &work) {
153 work->worklets.front()->output.flags = work->input.flags;
154 work->worklets.front()->output.buffers.clear();
155 work->worklets.front()->output.ordinal = work->input.ordinal;
156 work->workletsProcessed = 1u;
157 }
158
159 // (TODO) add multiframe support, in plugin and FLACDecoder.cpp
process(const std::unique_ptr<C2Work> & work,const std::shared_ptr<C2BlockPool> & pool)160 void C2SoftFlacDec::process(
161 const std::unique_ptr<C2Work> &work,
162 const std::shared_ptr<C2BlockPool> &pool) {
163 work->result = C2_OK;
164 work->workletsProcessed = 0u;
165 work->worklets.front()->output.configUpdate.clear();
166 if (mSignalledError || mSignalledOutputEos) {
167 work->result = C2_BAD_VALUE;
168 return;
169 }
170
171 C2ReadView rView = mDummyReadView;
172 size_t inOffset = 0u;
173 size_t inSize = 0u;
174 if (!work->input.buffers.empty()) {
175 rView = work->input.buffers[0]->data().linearBlocks().front().map().get();
176 inSize = rView.capacity();
177 if (inSize && rView.error()) {
178 ALOGE("read view map failed %d", rView.error());
179 work->result = C2_CORRUPTED;
180 return;
181 }
182 }
183 bool eos = (work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0;
184 bool codecConfig = (work->input.flags & C2FrameData::FLAG_CODEC_CONFIG) != 0;
185
186 ALOGV("in buffer attr. size %zu timestamp %d frameindex %d", inSize,
187 (int)work->input.ordinal.timestamp.peeku(), (int)work->input.ordinal.frameIndex.peeku());
188
189 if (inSize == 0) {
190 fillEmptyWork(work);
191 if (eos) {
192 mSignalledOutputEos = true;
193 ALOGV("signalled EOS");
194 }
195 return;
196 }
197
198 if (mInputBufferCount == 0 && !codecConfig) {
199 ALOGV("First frame has to include configuration, forcing config");
200 codecConfig = true;
201 }
202
203 uint8_t *input = const_cast<uint8_t *>(rView.data() + inOffset);
204 if (codecConfig) {
205 status_t decoderErr = mFLACDecoder->parseMetadata(input, inSize);
206 if (decoderErr != OK && decoderErr != WOULD_BLOCK) {
207 ALOGE("process: FLACDecoder parseMetaData returns error %d", decoderErr);
208 mSignalledError = true;
209 work->result = C2_CORRUPTED;
210 return;
211 }
212
213 mInputBufferCount++;
214 fillEmptyWork(work);
215 if (eos) {
216 mSignalledOutputEos = true;
217 ALOGV("signalled EOS");
218 }
219
220 if (decoderErr == WOULD_BLOCK) {
221 ALOGV("process: parseMetadata is Blocking, Continue %d", decoderErr);
222 } else {
223 mStreamInfo = mFLACDecoder->getStreamInfo();
224 if (mStreamInfo.sample_rate && mStreamInfo.max_blocksize &&
225 mStreamInfo.channels) {
226 mHasStreamInfo = true;
227 C2StreamSampleRateInfo::output sampleRateInfo(
228 0u, mStreamInfo.sample_rate);
229 C2StreamChannelCountInfo::output channelCountInfo(
230 0u, mStreamInfo.channels);
231 std::vector<std::unique_ptr<C2SettingResult>> failures;
232 c2_status_t err =
233 mIntf->config({&sampleRateInfo, &channelCountInfo},
234 C2_MAY_BLOCK, &failures);
235 if (err == OK) {
236 work->worklets.front()->output.configUpdate.push_back(
237 C2Param::Copy(sampleRateInfo));
238 work->worklets.front()->output.configUpdate.push_back(
239 C2Param::Copy(channelCountInfo));
240 } else {
241 ALOGE("Config Update failed");
242 mSignalledError = true;
243 work->result = C2_CORRUPTED;
244 return;
245 }
246 }
247 ALOGD("process: decoder configuration : %d Hz, %d channels, %d samples,"
248 " %d block size", mStreamInfo.sample_rate, mStreamInfo.channels,
249 (int)mStreamInfo.total_samples, mStreamInfo.max_blocksize);
250 }
251 return;
252 }
253
254 size_t outSize;
255 if (mHasStreamInfo)
256 outSize = mStreamInfo.max_blocksize * mStreamInfo.channels * sizeof(short);
257 else
258 outSize = kMaxBlockSize * FLACDecoder::kMaxChannels * sizeof(short);
259
260 std::shared_ptr<C2LinearBlock> block;
261 C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
262 c2_status_t err = pool->fetchLinearBlock(outSize, usage, &block);
263 if (err != C2_OK) {
264 ALOGE("fetchLinearBlock for Output failed with status %d", err);
265 work->result = C2_NO_MEMORY;
266 return;
267 }
268 C2WriteView wView = block->map().get();
269 if (wView.error()) {
270 ALOGE("write view map failed %d", wView.error());
271 work->result = C2_CORRUPTED;
272 return;
273 }
274
275 short *output = reinterpret_cast<short *>(wView.data());
276 status_t decoderErr = mFLACDecoder->decodeOneFrame(
277 input, inSize, output, &outSize);
278 if (decoderErr != OK) {
279 ALOGE("process: FLACDecoder decodeOneFrame returns error %d", decoderErr);
280 mSignalledError = true;
281 work->result = C2_CORRUPTED;
282 return;
283 }
284
285 mInputBufferCount++;
286 ALOGV("out buffer attr. size %zu", outSize);
287 work->worklets.front()->output.flags = work->input.flags;
288 work->worklets.front()->output.buffers.clear();
289 work->worklets.front()->output.buffers.push_back(createLinearBuffer(block, 0, outSize));
290 work->worklets.front()->output.ordinal = work->input.ordinal;
291 work->workletsProcessed = 1u;
292 if (eos) {
293 mSignalledOutputEos = true;
294 ALOGV("signalled EOS");
295 }
296 }
297
drain(uint32_t drainMode,const std::shared_ptr<C2BlockPool> & pool)298 c2_status_t C2SoftFlacDec::drain(
299 uint32_t drainMode,
300 const std::shared_ptr<C2BlockPool> &pool) {
301 (void) pool;
302 if (drainMode == NO_DRAIN) {
303 ALOGW("drain with NO_DRAIN: no-op");
304 return C2_OK;
305 }
306 if (drainMode == DRAIN_CHAIN) {
307 ALOGW("DRAIN_CHAIN not supported");
308 return C2_OMITTED;
309 }
310
311 if (mFLACDecoder) mFLACDecoder->flush();
312
313 return C2_OK;
314 }
315
316 class C2SoftFlacDecFactory : public C2ComponentFactory {
317 public:
C2SoftFlacDecFactory()318 C2SoftFlacDecFactory() : mHelper(std::static_pointer_cast<C2ReflectorHelper>(
319 GetCodec2PlatformComponentStore()->getParamReflector())) {
320 }
321
createComponent(c2_node_id_t id,std::shared_ptr<C2Component> * const component,std::function<void (C2Component *)> deleter)322 virtual c2_status_t createComponent(
323 c2_node_id_t id,
324 std::shared_ptr<C2Component>* const component,
325 std::function<void(C2Component*)> deleter) override {
326 *component = std::shared_ptr<C2Component>(
327 new C2SoftFlacDec(COMPONENT_NAME,
328 id,
329 std::make_shared<C2SoftFlacDec::IntfImpl>(mHelper)),
330 deleter);
331 return C2_OK;
332 }
333
createInterface(c2_node_id_t id,std::shared_ptr<C2ComponentInterface> * const interface,std::function<void (C2ComponentInterface *)> deleter)334 virtual c2_status_t createInterface(
335 c2_node_id_t id,
336 std::shared_ptr<C2ComponentInterface>* const interface,
337 std::function<void(C2ComponentInterface*)> deleter) override {
338 *interface = std::shared_ptr<C2ComponentInterface>(
339 new SimpleInterface<C2SoftFlacDec::IntfImpl>(
340 COMPONENT_NAME, id, std::make_shared<C2SoftFlacDec::IntfImpl>(mHelper)),
341 deleter);
342 return C2_OK;
343 }
344
345 virtual ~C2SoftFlacDecFactory() override = default;
346
347 private:
348 std::shared_ptr<C2ReflectorHelper> mHelper;
349 };
350
351 } // namespace android
352
CreateCodec2Factory()353 extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
354 ALOGV("in %s", __func__);
355 return new ::android::C2SoftFlacDecFactory();
356 }
357
DestroyCodec2Factory(::C2ComponentFactory * factory)358 extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
359 ALOGV("in %s", __func__);
360 delete factory;
361 }
362