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 "C2SoftOpusDec"
19 #include <log/log.h>
20
21 #include <media/stagefright/foundation/MediaDefs.h>
22 #include <media/stagefright/foundation/OpusHeader.h>
23 #include <C2PlatformSupport.h>
24 #include <SimpleC2Interface.h>
25 #include "C2SoftOpusDec.h"
26
27 extern "C" {
28 #include <opus.h>
29 #include <opus_multistream.h>
30 }
31
32 namespace android {
33
34 namespace {
35
36 constexpr char COMPONENT_NAME[] = "c2.android.opus.decoder";
37
38 } // namespace
39
40 class C2SoftOpusDec::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 MEDIA_MIMETYPE_AUDIO_OPUS) {
49 noPrivateBuffers();
50 noInputReferences();
51 noOutputReferences();
52 noInputLatency();
53 noTimeStretch();
54 setDerivedInstance(this);
55
56 addParameter(
57 DefineParam(mAttrib, C2_PARAMKEY_COMPONENT_ATTRIBUTES)
58 .withConstValue(new C2ComponentAttributesSetting(
59 C2Component::ATTRIB_IS_TEMPORAL))
60 .build());
61
62 addParameter(
63 DefineParam(mSampleRate, C2_PARAMKEY_SAMPLE_RATE)
64 .withDefault(new C2StreamSampleRateInfo::output(0u, 48000))
65 .withFields({C2F(mSampleRate, value).equalTo(48000)})
66 .withSetter((Setter<decltype(*mSampleRate)>::StrictValueWithNoDeps))
67 .build());
68
69 addParameter(
70 DefineParam(mChannelCount, C2_PARAMKEY_CHANNEL_COUNT)
71 .withDefault(new C2StreamChannelCountInfo::output(0u, 1))
72 .withFields({C2F(mChannelCount, value).inRange(1, 8)})
73 .withSetter(Setter<decltype(*mChannelCount)>::StrictValueWithNoDeps)
74 .build());
75
76 addParameter(
77 DefineParam(mBitrate, C2_PARAMKEY_BITRATE)
78 .withDefault(new C2StreamBitrateInfo::input(0u, 6000))
79 .withFields({C2F(mBitrate, value).inRange(6000, 510000)})
80 .withSetter(Setter<decltype(*mBitrate)>::NonStrictValueWithNoDeps)
81 .build());
82
83 addParameter(
84 DefineParam(mInputMaxBufSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE)
85 .withConstValue(new C2StreamMaxBufferSizeInfo::input(0u, 960 * 6))
86 .build());
87 }
88
89 private:
90 std::shared_ptr<C2StreamSampleRateInfo::output> mSampleRate;
91 std::shared_ptr<C2StreamChannelCountInfo::output> mChannelCount;
92 std::shared_ptr<C2StreamBitrateInfo::input> mBitrate;
93 std::shared_ptr<C2StreamMaxBufferSizeInfo::input> mInputMaxBufSize;
94 };
95
C2SoftOpusDec(const char * name,c2_node_id_t id,const std::shared_ptr<IntfImpl> & intfImpl)96 C2SoftOpusDec::C2SoftOpusDec(const char *name, c2_node_id_t id,
97 const std::shared_ptr<IntfImpl>& intfImpl)
98 : SimpleC2Component(
99 std::make_shared<SimpleInterface<IntfImpl>>(name, id, intfImpl)),
100 mIntf(intfImpl),
101 mDecoder(nullptr) {
102 }
103
~C2SoftOpusDec()104 C2SoftOpusDec::~C2SoftOpusDec() {
105 onRelease();
106 }
107
onInit()108 c2_status_t C2SoftOpusDec::onInit() {
109 status_t err = initDecoder();
110 return err == OK ? C2_OK : C2_NO_MEMORY;
111 }
112
onStop()113 c2_status_t C2SoftOpusDec::onStop() {
114 if (mDecoder) {
115 opus_multistream_decoder_destroy(mDecoder);
116 mDecoder = nullptr;
117 }
118 memset(&mHeader, 0, sizeof(mHeader));
119 mCodecDelay = 0;
120 mSeekPreRoll = 0;
121 mSamplesToDiscard = 0;
122 mInputBufferCount = 0;
123 mSignalledError = false;
124 mSignalledOutputEos = false;
125
126 return C2_OK;
127 }
128
onReset()129 void C2SoftOpusDec::onReset() {
130 (void)onStop();
131 }
132
onRelease()133 void C2SoftOpusDec::onRelease() {
134 if (mDecoder) {
135 opus_multistream_decoder_destroy(mDecoder);
136 mDecoder = nullptr;
137 }
138 }
139
initDecoder()140 status_t C2SoftOpusDec::initDecoder() {
141 memset(&mHeader, 0, sizeof(mHeader));
142 mCodecDelay = 0;
143 mSeekPreRoll = 0;
144 mSamplesToDiscard = 0;
145 mInputBufferCount = 0;
146 mSignalledError = false;
147 mSignalledOutputEos = false;
148
149 return OK;
150 }
151
onFlush_sm()152 c2_status_t C2SoftOpusDec::onFlush_sm() {
153 if (mDecoder) {
154 opus_multistream_decoder_ctl(mDecoder, OPUS_RESET_STATE);
155 mSamplesToDiscard = mSeekPreRoll;
156 mSignalledOutputEos = false;
157 }
158 return C2_OK;
159 }
160
drain(uint32_t drainMode,const std::shared_ptr<C2BlockPool> & pool)161 c2_status_t C2SoftOpusDec::drain(
162 uint32_t drainMode,
163 const std::shared_ptr<C2BlockPool> &pool) {
164 (void) pool;
165 if (drainMode == NO_DRAIN) {
166 ALOGW("drain with NO_DRAIN: no-op");
167 return C2_OK;
168 }
169 if (drainMode == DRAIN_CHAIN) {
170 ALOGW("DRAIN_CHAIN not supported");
171 return C2_OMITTED;
172 }
173
174 return C2_OK;
175 }
176
fillEmptyWork(const std::unique_ptr<C2Work> & work)177 static void fillEmptyWork(const std::unique_ptr<C2Work> &work) {
178 work->worklets.front()->output.flags = work->input.flags;
179 work->worklets.front()->output.buffers.clear();
180 work->worklets.front()->output.ordinal = work->input.ordinal;
181 work->workletsProcessed = 1u;
182 }
183
184 static const int kRate = 48000;
185
186 // Opus uses Vorbis channel mapping, and Vorbis channel mapping specifies
187 // mappings for up to 8 channels. This information is part of the Vorbis I
188 // Specification:
189 // http://www.xiph.org/vorbis/doc/Vorbis_I_spec.html
190 static const int kMaxChannels = 8;
191
192 // Maximum packet size used in Xiph's opusdec.
193 static const int kMaxOpusOutputPacketSizeSamples = 960 * 6;
194
195 // Default audio output channel layout. Used to initialize |stream_map| in
196 // OpusHeader, and passed to opus_multistream_decoder_create() when the header
197 // does not contain mapping information. The values are valid only for mono and
198 // stereo output: Opus streams with more than 2 channels require a stream map.
199 static const int kMaxChannelsWithDefaultLayout = 2;
200 static const uint8_t kDefaultOpusChannelLayout[kMaxChannelsWithDefaultLayout] = { 0, 1 };
201
202
203 // Convert nanoseconds to number of samples.
ns_to_samples(uint64_t ns,int rate)204 static uint64_t ns_to_samples(uint64_t ns, int rate) {
205 return static_cast<double>(ns) * rate / 1000000000;
206 }
207
process(const std::unique_ptr<C2Work> & work,const std::shared_ptr<C2BlockPool> & pool)208 void C2SoftOpusDec::process(
209 const std::unique_ptr<C2Work> &work,
210 const std::shared_ptr<C2BlockPool> &pool) {
211 // Initialize output work
212 work->result = C2_OK;
213 work->workletsProcessed = 1u;
214 work->worklets.front()->output.configUpdate.clear();
215 work->worklets.front()->output.flags = work->input.flags;
216
217 if (mSignalledError || mSignalledOutputEos) {
218 work->result = C2_BAD_VALUE;
219 return;
220 }
221
222 bool eos = ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0);
223 size_t inOffset = 0u;
224 size_t inSize = 0u;
225 C2ReadView rView = mDummyReadView;
226 if (!work->input.buffers.empty()) {
227 rView = work->input.buffers[0]->data().linearBlocks().front().map().get();
228 inSize = rView.capacity();
229 if (inSize && rView.error()) {
230 ALOGE("read view map failed %d", rView.error());
231 work->result = C2_CORRUPTED;
232 return;
233 }
234 }
235 if (inSize == 0) {
236 fillEmptyWork(work);
237 if (eos) {
238 mSignalledOutputEos = true;
239 ALOGV("signalled EOS");
240 }
241 return;
242 }
243
244 ALOGV("in buffer attr. size %zu timestamp %d frameindex %d", inSize,
245 (int)work->input.ordinal.timestamp.peeku(), (int)work->input.ordinal.frameIndex.peeku());
246 const uint8_t *data = rView.data() + inOffset;
247 if (mInputBufferCount < 3) {
248 if (mInputBufferCount == 0) {
249 size_t opusHeadSize = 0;
250 size_t codecDelayBufSize = 0;
251 size_t seekPreRollBufSize = 0;
252 void *opusHeadBuf = NULL;
253 void *codecDelayBuf = NULL;
254 void *seekPreRollBuf = NULL;
255
256 if (!GetOpusHeaderBuffers(data, inSize, &opusHeadBuf,
257 &opusHeadSize, &codecDelayBuf,
258 &codecDelayBufSize, &seekPreRollBuf,
259 &seekPreRollBufSize)) {
260 ALOGE("%s encountered error in GetOpusHeaderBuffers", __func__);
261 mSignalledError = true;
262 work->result = C2_CORRUPTED;
263 return;
264 }
265
266 if (!ParseOpusHeader((uint8_t *)opusHeadBuf, opusHeadSize, &mHeader)) {
267 ALOGE("%s Encountered error while Parsing Opus Header.", __func__);
268 mSignalledError = true;
269 work->result = C2_CORRUPTED;
270 return;
271 }
272 uint8_t channel_mapping[kMaxChannels] = {0};
273 if (mHeader.channels <= kMaxChannelsWithDefaultLayout) {
274 memcpy(&channel_mapping,
275 kDefaultOpusChannelLayout,
276 kMaxChannelsWithDefaultLayout);
277 } else {
278 memcpy(&channel_mapping,
279 mHeader.stream_map,
280 mHeader.channels);
281 }
282 int status = OPUS_INVALID_STATE;
283 mDecoder = opus_multistream_decoder_create(kRate,
284 mHeader.channels,
285 mHeader.num_streams,
286 mHeader.num_coupled,
287 channel_mapping,
288 &status);
289 if (!mDecoder || status != OPUS_OK) {
290 ALOGE("opus_multistream_decoder_create failed status = %s",
291 opus_strerror(status));
292 mSignalledError = true;
293 work->result = C2_CORRUPTED;
294 return;
295 }
296 status = opus_multistream_decoder_ctl(mDecoder,
297 OPUS_SET_GAIN(mHeader.gain_db));
298 if (status != OPUS_OK) {
299 ALOGE("Failed to set OPUS header gain; status = %s",
300 opus_strerror(status));
301 mSignalledError = true;
302 work->result = C2_CORRUPTED;
303 return;
304 }
305
306 if (codecDelayBuf && codecDelayBufSize == sizeof(uint64_t)) {
307 uint64_t value;
308 memcpy(&value, codecDelayBuf, sizeof(uint64_t));
309 mCodecDelay = ns_to_samples(value, kRate);
310 mSamplesToDiscard = mCodecDelay;
311 ++mInputBufferCount;
312 }
313 if (seekPreRollBuf && seekPreRollBufSize == sizeof(uint64_t)) {
314 uint64_t value;
315 memcpy(&value, seekPreRollBuf, sizeof(uint64_t));
316 mSeekPreRoll = ns_to_samples(value, kRate);
317 ++mInputBufferCount;
318 }
319 } else {
320 if (inSize < 8) {
321 ALOGE("Input sample size is too small.");
322 mSignalledError = true;
323 work->result = C2_CORRUPTED;
324 return;
325 }
326 int64_t samples = ns_to_samples( *(reinterpret_cast<int64_t*>
327 (const_cast<uint8_t *> (data))), kRate);
328 if (mInputBufferCount == 1) {
329 mCodecDelay = samples;
330 mSamplesToDiscard = mCodecDelay;
331 }
332 else {
333 mSeekPreRoll = samples;
334 }
335 }
336
337 ++mInputBufferCount;
338 if (mInputBufferCount == 3) {
339 ALOGI("Configuring decoder: %d Hz, %d channels",
340 kRate, mHeader.channels);
341 C2StreamSampleRateInfo::output sampleRateInfo(0u, kRate);
342 C2StreamChannelCountInfo::output channelCountInfo(0u, mHeader.channels);
343 std::vector<std::unique_ptr<C2SettingResult>> failures;
344 c2_status_t err = mIntf->config(
345 { &sampleRateInfo, &channelCountInfo },
346 C2_MAY_BLOCK,
347 &failures);
348 if (err == OK) {
349 work->worklets.front()->output.configUpdate.push_back(C2Param::Copy(sampleRateInfo));
350 work->worklets.front()->output.configUpdate.push_back(C2Param::Copy(channelCountInfo));
351 } else {
352 ALOGE("Config Update failed");
353 mSignalledError = true;
354 work->result = C2_CORRUPTED;
355 return;
356 }
357 }
358 fillEmptyWork(work);
359 if (eos) {
360 mSignalledOutputEos = true;
361 ALOGV("signalled EOS");
362 }
363 return;
364 }
365
366 // Ignore CSD re-submissions.
367 if ((work->input.flags & C2FrameData::FLAG_CODEC_CONFIG)) {
368 fillEmptyWork(work);
369 return;
370 }
371
372 // When seeking to zero, |mCodecDelay| samples has to be discarded
373 // instead of |mSeekPreRoll| samples (as we would when seeking to any
374 // other timestamp).
375 if (work->input.ordinal.timestamp.peeku() == 0) mSamplesToDiscard = mCodecDelay;
376
377 std::shared_ptr<C2LinearBlock> block;
378 C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
379 c2_status_t err = pool->fetchLinearBlock(
380 kMaxNumSamplesPerBuffer * kMaxChannels * sizeof(int16_t),
381 usage, &block);
382 if (err != C2_OK) {
383 ALOGE("fetchLinearBlock for Output failed with status %d", err);
384 work->result = C2_NO_MEMORY;
385 return;
386 }
387 C2WriteView wView = block->map().get();
388 if (wView.error()) {
389 ALOGE("write view map failed %d", wView.error());
390 work->result = C2_CORRUPTED;
391 return;
392 }
393
394 int numSamples = opus_multistream_decode(mDecoder,
395 data,
396 inSize,
397 reinterpret_cast<int16_t *> (wView.data()),
398 kMaxOpusOutputPacketSizeSamples,
399 0);
400 if (numSamples < 0) {
401 ALOGE("opus_multistream_decode returned numSamples %d", numSamples);
402 numSamples = 0;
403 mSignalledError = true;
404 work->result = C2_CORRUPTED;
405 return;
406 }
407
408 int outOffset = 0;
409 if (mSamplesToDiscard > 0) {
410 if (mSamplesToDiscard > numSamples) {
411 mSamplesToDiscard -= numSamples;
412 numSamples = 0;
413 } else {
414 numSamples -= mSamplesToDiscard;
415 outOffset = mSamplesToDiscard * sizeof(int16_t) * mHeader.channels;
416 mSamplesToDiscard = 0;
417 }
418 }
419
420 if (numSamples) {
421 int outSize = numSamples * sizeof(int16_t) * mHeader.channels;
422 ALOGV("out buffer attr. offset %d size %d ", outOffset, outSize);
423
424 work->worklets.front()->output.flags = work->input.flags;
425 work->worklets.front()->output.buffers.clear();
426 work->worklets.front()->output.buffers.push_back(createLinearBuffer(block, outOffset, outSize));
427 work->worklets.front()->output.ordinal = work->input.ordinal;
428 work->workletsProcessed = 1u;
429 } else {
430 fillEmptyWork(work);
431 block.reset();
432 }
433 if (eos) {
434 mSignalledOutputEos = true;
435 ALOGV("signalled EOS");
436 }
437 }
438
439 class C2SoftOpusDecFactory : public C2ComponentFactory {
440 public:
C2SoftOpusDecFactory()441 C2SoftOpusDecFactory() : mHelper(std::static_pointer_cast<C2ReflectorHelper>(
442 GetCodec2PlatformComponentStore()->getParamReflector())) {
443 }
444
createComponent(c2_node_id_t id,std::shared_ptr<C2Component> * const component,std::function<void (C2Component *)> deleter)445 virtual c2_status_t createComponent(
446 c2_node_id_t id,
447 std::shared_ptr<C2Component>* const component,
448 std::function<void(C2Component*)> deleter) override {
449 *component = std::shared_ptr<C2Component>(
450 new C2SoftOpusDec(COMPONENT_NAME,
451 id,
452 std::make_shared<C2SoftOpusDec::IntfImpl>(mHelper)),
453 deleter);
454 return C2_OK;
455 }
456
createInterface(c2_node_id_t id,std::shared_ptr<C2ComponentInterface> * const interface,std::function<void (C2ComponentInterface *)> deleter)457 virtual c2_status_t createInterface(
458 c2_node_id_t id,
459 std::shared_ptr<C2ComponentInterface>* const interface,
460 std::function<void(C2ComponentInterface*)> deleter) override {
461 *interface = std::shared_ptr<C2ComponentInterface>(
462 new SimpleInterface<C2SoftOpusDec::IntfImpl>(
463 COMPONENT_NAME, id, std::make_shared<C2SoftOpusDec::IntfImpl>(mHelper)),
464 deleter);
465 return C2_OK;
466 }
467
468 virtual ~C2SoftOpusDecFactory() override = default;
469
470 private:
471 std::shared_ptr<C2ReflectorHelper> mHelper;
472 };
473
474 } // namespace android
475
CreateCodec2Factory()476 extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
477 ALOGV("in %s", __func__);
478 return new ::android::C2SoftOpusDecFactory();
479 }
480
DestroyCodec2Factory(::C2ComponentFactory * factory)481 extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
482 ALOGV("in %s", __func__);
483 delete factory;
484 }
485