1 /*
2 * Copyright (C) 2014 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 "SoftOpus"
19 #include <utils/Log.h>
20
21 #include "SoftOpus.h"
22 #include <OMX_AudioExt.h>
23 #include <OMX_IndexExt.h>
24
25 #include <media/stagefright/foundation/ADebug.h>
26 #include <media/stagefright/MediaDefs.h>
27
28 extern "C" {
29 #include <opus.h>
30 #include <opus_multistream.h>
31 }
32
33 namespace android {
34
35 static const int kRate = 48000;
36
37 // Opus uses Vorbis channel mapping, and Vorbis channel mapping specifies
38 // mappings for up to 8 channels. This information is part of the Vorbis I
39 // Specification:
40 // http://www.xiph.org/vorbis/doc/Vorbis_I_spec.html
41 static const int kMaxChannels = 8;
42
43 template<class T>
InitOMXParams(T * params)44 static void InitOMXParams(T *params) {
45 params->nSize = sizeof(T);
46 params->nVersion.s.nVersionMajor = 1;
47 params->nVersion.s.nVersionMinor = 0;
48 params->nVersion.s.nRevision = 0;
49 params->nVersion.s.nStep = 0;
50 }
51
SoftOpus(const char * name,const OMX_CALLBACKTYPE * callbacks,OMX_PTR appData,OMX_COMPONENTTYPE ** component)52 SoftOpus::SoftOpus(
53 const char *name,
54 const OMX_CALLBACKTYPE *callbacks,
55 OMX_PTR appData,
56 OMX_COMPONENTTYPE **component)
57 : SimpleSoftOMXComponent(name, callbacks, appData, component),
58 mInputBufferCount(0),
59 mDecoder(NULL),
60 mHeader(NULL),
61 mNumChannels(1),
62 mSamplingRate(kRate),
63 mCodecDelay(0),
64 mSeekPreRoll(0),
65 mAnchorTimeUs(0),
66 mNumFramesOutput(0),
67 mHaveEOS(false),
68 mOutputPortSettingsChange(NONE) {
69 initPorts();
70 CHECK_EQ(initDecoder(), (status_t)OK);
71 }
72
~SoftOpus()73 SoftOpus::~SoftOpus() {
74 if (mDecoder != NULL) {
75 opus_multistream_decoder_destroy(mDecoder);
76 mDecoder = NULL;
77 }
78 if (mHeader != NULL) {
79 delete mHeader;
80 mHeader = NULL;
81 }
82 }
83
initPorts()84 void SoftOpus::initPorts() {
85 OMX_PARAM_PORTDEFINITIONTYPE def;
86 InitOMXParams(&def);
87
88 def.nPortIndex = 0;
89 def.eDir = OMX_DirInput;
90 def.nBufferCountMin = kNumBuffers;
91 def.nBufferCountActual = def.nBufferCountMin;
92 def.nBufferSize = 960 * 6;
93 def.bEnabled = OMX_TRUE;
94 def.bPopulated = OMX_FALSE;
95 def.eDomain = OMX_PortDomainAudio;
96 def.bBuffersContiguous = OMX_FALSE;
97 def.nBufferAlignment = 1;
98
99 def.format.audio.cMIMEType =
100 const_cast<char *>(MEDIA_MIMETYPE_AUDIO_OPUS);
101
102 def.format.audio.pNativeRender = NULL;
103 def.format.audio.bFlagErrorConcealment = OMX_FALSE;
104 def.format.audio.eEncoding =
105 (OMX_AUDIO_CODINGTYPE)OMX_AUDIO_CodingAndroidOPUS;
106
107 addPort(def);
108
109 def.nPortIndex = 1;
110 def.eDir = OMX_DirOutput;
111 def.nBufferCountMin = kNumBuffers;
112 def.nBufferCountActual = def.nBufferCountMin;
113 def.nBufferSize = kMaxNumSamplesPerBuffer * sizeof(int16_t) * kMaxChannels;
114 def.bEnabled = OMX_TRUE;
115 def.bPopulated = OMX_FALSE;
116 def.eDomain = OMX_PortDomainAudio;
117 def.bBuffersContiguous = OMX_FALSE;
118 def.nBufferAlignment = 2;
119
120 def.format.audio.cMIMEType = const_cast<char *>("audio/raw");
121 def.format.audio.pNativeRender = NULL;
122 def.format.audio.bFlagErrorConcealment = OMX_FALSE;
123 def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
124
125 addPort(def);
126 }
127
initDecoder()128 status_t SoftOpus::initDecoder() {
129 return OK;
130 }
131
internalGetParameter(OMX_INDEXTYPE index,OMX_PTR params)132 OMX_ERRORTYPE SoftOpus::internalGetParameter(
133 OMX_INDEXTYPE index, OMX_PTR params) {
134 switch ((int)index) {
135 case OMX_IndexParamAudioPortFormat:
136 {
137 OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
138 (OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
139
140 if (!isValidOMXParam(formatParams)) {
141 return OMX_ErrorBadParameter;
142 }
143
144 if (formatParams->nPortIndex > 1) {
145 return OMX_ErrorUndefined;
146 }
147
148 if (formatParams->nIndex > 0) {
149 return OMX_ErrorNoMore;
150 }
151
152 formatParams->eEncoding =
153 (formatParams->nPortIndex == 0)
154 ? (OMX_AUDIO_CODINGTYPE)OMX_AUDIO_CodingAndroidOPUS :
155 OMX_AUDIO_CodingPCM;
156
157 return OMX_ErrorNone;
158 }
159
160 case OMX_IndexParamAudioAndroidOpus:
161 {
162 OMX_AUDIO_PARAM_ANDROID_OPUSTYPE *opusParams =
163 (OMX_AUDIO_PARAM_ANDROID_OPUSTYPE *)params;
164
165 if (!isValidOMXParam(opusParams)) {
166 return OMX_ErrorBadParameter;
167 }
168
169 if (opusParams->nPortIndex != 0) {
170 return OMX_ErrorUndefined;
171 }
172
173 opusParams->nAudioBandWidth = 0;
174 opusParams->nSampleRate = mSamplingRate;
175 opusParams->nBitRate = 0;
176
177 if (!isConfigured()) {
178 opusParams->nChannels = mNumChannels;
179 } else {
180 opusParams->nChannels = mHeader->channels;
181 }
182
183 return OMX_ErrorNone;
184 }
185
186 case OMX_IndexParamAudioPcm:
187 {
188 OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
189 (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
190
191 if (!isValidOMXParam(pcmParams)) {
192 return OMX_ErrorBadParameter;
193 }
194
195 if (pcmParams->nPortIndex != 1) {
196 return OMX_ErrorUndefined;
197 }
198
199 pcmParams->eNumData = OMX_NumericalDataSigned;
200 pcmParams->eEndian = OMX_EndianBig;
201 pcmParams->bInterleaved = OMX_TRUE;
202 pcmParams->nBitPerSample = 16;
203 pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear;
204 pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF;
205 pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF;
206 pcmParams->nSamplingRate = kRate;
207
208 if (!isConfigured()) {
209 pcmParams->nChannels = 1;
210 } else {
211 pcmParams->nChannels = mHeader->channels;
212 }
213
214 return OMX_ErrorNone;
215 }
216
217 default:
218 return SimpleSoftOMXComponent::internalGetParameter(index, params);
219 }
220 }
221
internalSetParameter(OMX_INDEXTYPE index,const OMX_PTR params)222 OMX_ERRORTYPE SoftOpus::internalSetParameter(
223 OMX_INDEXTYPE index, const OMX_PTR params) {
224 switch ((int)index) {
225 case OMX_IndexParamStandardComponentRole:
226 {
227 const OMX_PARAM_COMPONENTROLETYPE *roleParams =
228 (const OMX_PARAM_COMPONENTROLETYPE *)params;
229
230 if (!isValidOMXParam(roleParams)) {
231 return OMX_ErrorBadParameter;
232 }
233
234 if (strncmp((const char *)roleParams->cRole,
235 "audio_decoder.opus",
236 OMX_MAX_STRINGNAME_SIZE - 1)) {
237 return OMX_ErrorUndefined;
238 }
239
240 return OMX_ErrorNone;
241 }
242
243 case OMX_IndexParamAudioPortFormat:
244 {
245 const OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
246 (const OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
247
248 if (!isValidOMXParam(formatParams)) {
249 return OMX_ErrorBadParameter;
250 }
251
252 if (formatParams->nPortIndex > 1) {
253 return OMX_ErrorUndefined;
254 }
255
256 if ((formatParams->nPortIndex == 0
257 && formatParams->eEncoding !=
258 (OMX_AUDIO_CODINGTYPE)OMX_AUDIO_CodingAndroidOPUS)
259 || (formatParams->nPortIndex == 1
260 && formatParams->eEncoding != OMX_AUDIO_CodingPCM)) {
261 return OMX_ErrorUndefined;
262 }
263
264 return OMX_ErrorNone;
265 }
266
267 case OMX_IndexParamAudioAndroidOpus:
268 {
269 const OMX_AUDIO_PARAM_ANDROID_OPUSTYPE *opusParams =
270 (const OMX_AUDIO_PARAM_ANDROID_OPUSTYPE *)params;
271
272 if (!isValidOMXParam(opusParams)) {
273 return OMX_ErrorBadParameter;
274 }
275
276 if (opusParams->nPortIndex != 0) {
277 return OMX_ErrorUndefined;
278 }
279 mNumChannels = opusParams->nChannels;
280 mSamplingRate = opusParams->nSampleRate;
281 return OMX_ErrorNone;
282 }
283
284 default:
285 return SimpleSoftOMXComponent::internalSetParameter(index, params);
286 }
287 }
288
isConfigured() const289 bool SoftOpus::isConfigured() const {
290 return mInputBufferCount >= 1;
291 }
292
ReadLE16(const uint8_t * data,size_t data_size,uint32_t read_offset)293 static uint16_t ReadLE16(const uint8_t *data, size_t data_size,
294 uint32_t read_offset) {
295 if (read_offset + 1 > data_size)
296 return 0;
297 uint16_t val;
298 val = data[read_offset];
299 val |= data[read_offset + 1] << 8;
300 return val;
301 }
302
303 // Maximum packet size used in Xiph's opusdec.
304 static const int kMaxOpusOutputPacketSizeSamples = 960 * 6;
305
306 // Default audio output channel layout. Used to initialize |stream_map| in
307 // OpusHeader, and passed to opus_multistream_decoder_create() when the header
308 // does not contain mapping information. The values are valid only for mono and
309 // stereo output: Opus streams with more than 2 channels require a stream map.
310 static const int kMaxChannelsWithDefaultLayout = 2;
311 static const uint8_t kDefaultOpusChannelLayout[kMaxChannelsWithDefaultLayout] = { 0, 1 };
312
313 // Parses Opus Header. Header spec: http://wiki.xiph.org/OggOpus#ID_Header
ParseOpusHeader(const uint8_t * data,size_t data_size,OpusHeader * header)314 static bool ParseOpusHeader(const uint8_t *data, size_t data_size,
315 OpusHeader* header) {
316 // Size of the Opus header excluding optional mapping information.
317 const size_t kOpusHeaderSize = 19;
318
319 // Offset to the channel count byte in the Opus header.
320 const size_t kOpusHeaderChannelsOffset = 9;
321
322 // Offset to the pre-skip value in the Opus header.
323 const size_t kOpusHeaderSkipSamplesOffset = 10;
324
325 // Offset to the gain value in the Opus header.
326 const size_t kOpusHeaderGainOffset = 16;
327
328 // Offset to the channel mapping byte in the Opus header.
329 const size_t kOpusHeaderChannelMappingOffset = 18;
330
331 // Opus Header contains a stream map. The mapping values are in the header
332 // beyond the always present |kOpusHeaderSize| bytes of data. The mapping
333 // data contains stream count, coupling information, and per channel mapping
334 // values:
335 // - Byte 0: Number of streams.
336 // - Byte 1: Number coupled.
337 // - Byte 2: Starting at byte 2 are |header->channels| uint8 mapping
338 // values.
339 const size_t kOpusHeaderNumStreamsOffset = kOpusHeaderSize;
340 const size_t kOpusHeaderNumCoupledOffset = kOpusHeaderNumStreamsOffset + 1;
341 const size_t kOpusHeaderStreamMapOffset = kOpusHeaderNumStreamsOffset + 2;
342
343 if (data_size < kOpusHeaderSize) {
344 ALOGV("Header size is too small.");
345 return false;
346 }
347 header->channels = *(data + kOpusHeaderChannelsOffset);
348
349 if (header->channels <= 0 || header->channels > kMaxChannels) {
350 ALOGV("Invalid Header, wrong channel count: %d", header->channels);
351 return false;
352 }
353 header->skip_samples = ReadLE16(data, data_size,
354 kOpusHeaderSkipSamplesOffset);
355 header->gain_db = static_cast<int16_t>(
356 ReadLE16(data, data_size,
357 kOpusHeaderGainOffset));
358 header->channel_mapping = *(data + kOpusHeaderChannelMappingOffset);
359 if (!header->channel_mapping) {
360 if (header->channels > kMaxChannelsWithDefaultLayout) {
361 ALOGV("Invalid Header, missing stream map.");
362 return false;
363 }
364 header->num_streams = 1;
365 header->num_coupled = header->channels > 1;
366 header->stream_map[0] = 0;
367 header->stream_map[1] = 1;
368 return true;
369 }
370 if (data_size < kOpusHeaderStreamMapOffset + header->channels) {
371 ALOGV("Invalid stream map; insufficient data for current channel "
372 "count: %d", header->channels);
373 return false;
374 }
375 header->num_streams = *(data + kOpusHeaderNumStreamsOffset);
376 header->num_coupled = *(data + kOpusHeaderNumCoupledOffset);
377 if (header->num_streams + header->num_coupled != header->channels) {
378 ALOGV("Inconsistent channel mapping.");
379 return false;
380 }
381 for (int i = 0; i < header->channels; ++i)
382 header->stream_map[i] = *(data + kOpusHeaderStreamMapOffset + i);
383 return true;
384 }
385
386 // Convert nanoseconds to number of samples.
ns_to_samples(uint64_t ns,int kRate)387 static uint64_t ns_to_samples(uint64_t ns, int kRate) {
388 return static_cast<double>(ns) * kRate / 1000000000;
389 }
390
handleEOS()391 void SoftOpus::handleEOS() {
392 List<BufferInfo *> &inQueue = getPortQueue(0);
393 List<BufferInfo *> &outQueue = getPortQueue(1);
394 CHECK(!inQueue.empty() && !outQueue.empty());
395
396 BufferInfo *outInfo = *outQueue.begin();
397 OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
398 outHeader->nFilledLen = 0;
399 outHeader->nFlags = OMX_BUFFERFLAG_EOS;
400 mHaveEOS = true;
401
402 outQueue.erase(outQueue.begin());
403 outInfo->mOwnedByUs = false;
404 notifyFillBufferDone(outHeader);
405
406 BufferInfo *inInfo = *inQueue.begin();
407 OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
408 inQueue.erase(inQueue.begin());
409 inInfo->mOwnedByUs = false;
410 notifyEmptyBufferDone(inHeader);
411
412 ++mInputBufferCount;
413 }
414
onQueueFilled(OMX_U32)415 void SoftOpus::onQueueFilled(OMX_U32 /* portIndex */) {
416 List<BufferInfo *> &inQueue = getPortQueue(0);
417 List<BufferInfo *> &outQueue = getPortQueue(1);
418
419 if (mOutputPortSettingsChange != NONE) {
420 return;
421 }
422
423 while (!mHaveEOS && !inQueue.empty() && !outQueue.empty()) {
424 BufferInfo *inInfo = *inQueue.begin();
425 OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
426
427 if (mInputBufferCount < 3) {
428 const uint8_t *data = inHeader->pBuffer + inHeader->nOffset;
429 size_t size = inHeader->nFilledLen;
430
431 if ((inHeader->nFlags & OMX_BUFFERFLAG_EOS) && size == 0) {
432 handleEOS();
433 return;
434 }
435
436 if (size < sizeof(int64_t)) {
437 // The 2nd and 3rd input buffer are expected to contain
438 // an int64_t (see below), so make sure we get at least
439 // that much. The first input buffer must contain 19 bytes,
440 // but that is checked already.
441 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
442 return;
443 }
444
445 if (mInputBufferCount == 0) {
446 delete mHeader;
447 mHeader = new OpusHeader();
448 memset(mHeader, 0, sizeof(*mHeader));
449 if (!ParseOpusHeader(data, size, mHeader)) {
450 ALOGV("Parsing Opus Header failed.");
451 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
452 return;
453 }
454
455 uint8_t channel_mapping[kMaxChannels] = {0};
456 if (mHeader->channels <= kMaxChannelsWithDefaultLayout) {
457 memcpy(&channel_mapping,
458 kDefaultOpusChannelLayout,
459 kMaxChannelsWithDefaultLayout);
460 } else {
461 memcpy(&channel_mapping,
462 mHeader->stream_map,
463 mHeader->channels);
464 }
465
466 int status = OPUS_INVALID_STATE;
467 if (mDecoder != NULL) {
468 opus_multistream_decoder_destroy(mDecoder);
469 }
470 mDecoder = opus_multistream_decoder_create(kRate,
471 mHeader->channels,
472 mHeader->num_streams,
473 mHeader->num_coupled,
474 channel_mapping,
475 &status);
476 if (!mDecoder || status != OPUS_OK) {
477 ALOGV("opus_multistream_decoder_create failed status=%s",
478 opus_strerror(status));
479 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
480 return;
481 }
482 status =
483 opus_multistream_decoder_ctl(mDecoder,
484 OPUS_SET_GAIN(mHeader->gain_db));
485 if (status != OPUS_OK) {
486 ALOGV("Failed to set OPUS header gain; status=%s",
487 opus_strerror(status));
488 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
489 return;
490 }
491 } else if (mInputBufferCount == 1) {
492 mCodecDelay = ns_to_samples(
493 *(reinterpret_cast<int64_t*>(inHeader->pBuffer +
494 inHeader->nOffset)),
495 kRate);
496 mSamplesToDiscard = mCodecDelay;
497 } else {
498 mSeekPreRoll = ns_to_samples(
499 *(reinterpret_cast<int64_t*>(inHeader->pBuffer +
500 inHeader->nOffset)),
501 kRate);
502 mSamplingRate = kRate;
503 mNumChannels = mHeader->channels;
504 notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
505 mOutputPortSettingsChange = AWAITING_DISABLED;
506 }
507
508 if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
509 handleEOS();
510 return;
511 }
512
513 inQueue.erase(inQueue.begin());
514 inInfo->mOwnedByUs = false;
515 notifyEmptyBufferDone(inHeader);
516 ++mInputBufferCount;
517
518 continue;
519 }
520
521 // Ignore CSD re-submissions.
522 if (mInputBufferCount >= 3 && (inHeader->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) {
523 if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
524 handleEOS();
525 return;
526 }
527
528 inQueue.erase(inQueue.begin());
529 inInfo->mOwnedByUs = false;
530 notifyEmptyBufferDone(inHeader);
531 continue;
532 }
533
534 BufferInfo *outInfo = *outQueue.begin();
535 OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
536
537 if ((inHeader->nFlags & OMX_BUFFERFLAG_EOS) && inHeader->nFilledLen == 0) {
538 handleEOS();
539 return;
540 }
541
542 if (inHeader->nOffset == 0) {
543 mAnchorTimeUs = inHeader->nTimeStamp;
544 mNumFramesOutput = 0;
545 }
546
547 // When seeking to zero, |mCodecDelay| samples has to be discarded
548 // instead of |mSeekPreRoll| samples (as we would when seeking to any
549 // other timestamp).
550 if (inHeader->nTimeStamp == 0) {
551 mSamplesToDiscard = mCodecDelay;
552 }
553
554 const uint8_t *data = inHeader->pBuffer + inHeader->nOffset;
555 const uint32_t size = inHeader->nFilledLen;
556 size_t frameSize = kMaxOpusOutputPacketSizeSamples;
557 if (frameSize > outHeader->nAllocLen / sizeof(int16_t) / mHeader->channels) {
558 frameSize = outHeader->nAllocLen / sizeof(int16_t) / mHeader->channels;
559 android_errorWriteLog(0x534e4554, "27833616");
560 }
561
562 int numFrames = opus_multistream_decode(mDecoder,
563 data,
564 size,
565 (int16_t *)outHeader->pBuffer,
566 frameSize,
567 0);
568 if (numFrames < 0) {
569 ALOGE("opus_multistream_decode returned %d", numFrames);
570 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
571 return;
572 }
573
574 outHeader->nOffset = 0;
575 if (mSamplesToDiscard > 0) {
576 if (mSamplesToDiscard > numFrames) {
577 mSamplesToDiscard -= numFrames;
578 numFrames = 0;
579 } else {
580 numFrames -= mSamplesToDiscard;
581 outHeader->nOffset = mSamplesToDiscard * sizeof(int16_t) *
582 mHeader->channels;
583 mSamplesToDiscard = 0;
584 }
585 }
586
587 outHeader->nFilledLen = numFrames * sizeof(int16_t) * mHeader->channels;
588
589 outHeader->nTimeStamp = mAnchorTimeUs +
590 (mNumFramesOutput * 1000000LL) /
591 kRate;
592
593 mNumFramesOutput += numFrames;
594
595 if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
596 outHeader->nFlags = OMX_BUFFERFLAG_EOS;
597 mHaveEOS = true;
598 } else {
599 outHeader->nFlags = 0;
600 }
601
602 inInfo->mOwnedByUs = false;
603 inQueue.erase(inQueue.begin());
604 notifyEmptyBufferDone(inHeader);
605 ++mInputBufferCount;
606
607 outInfo->mOwnedByUs = false;
608 outQueue.erase(outQueue.begin());
609 notifyFillBufferDone(outHeader);
610 }
611 }
612
onPortFlushCompleted(OMX_U32 portIndex)613 void SoftOpus::onPortFlushCompleted(OMX_U32 portIndex) {
614 if (portIndex == 0 && mDecoder != NULL) {
615 // Make sure that the next buffer output does not still
616 // depend on fragments from the last one decoded.
617 mNumFramesOutput = 0;
618 opus_multistream_decoder_ctl(mDecoder, OPUS_RESET_STATE);
619 mAnchorTimeUs = 0;
620 mSamplesToDiscard = mSeekPreRoll;
621 mHaveEOS = false;
622 }
623 }
624
onReset()625 void SoftOpus::onReset() {
626 mInputBufferCount = 0;
627 mNumFramesOutput = 0;
628 if (mDecoder != NULL) {
629 opus_multistream_decoder_destroy(mDecoder);
630 mDecoder = NULL;
631 }
632 if (mHeader != NULL) {
633 delete mHeader;
634 mHeader = NULL;
635 }
636
637 mOutputPortSettingsChange = NONE;
638 mHaveEOS = false;
639 }
640
onPortEnableCompleted(OMX_U32 portIndex,bool enabled)641 void SoftOpus::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) {
642 if (portIndex != 1) {
643 return;
644 }
645
646 switch (mOutputPortSettingsChange) {
647 case NONE:
648 break;
649
650 case AWAITING_DISABLED:
651 {
652 CHECK(!enabled);
653 mOutputPortSettingsChange = AWAITING_ENABLED;
654 break;
655 }
656
657 default:
658 {
659 CHECK_EQ((int)mOutputPortSettingsChange, (int)AWAITING_ENABLED);
660 CHECK(enabled);
661 mOutputPortSettingsChange = NONE;
662 break;
663 }
664 }
665 }
666
667 } // namespace android
668
669 __attribute__((cfi_canonical_jump_table))
createSoftOMXComponent(const char * name,const OMX_CALLBACKTYPE * callbacks,OMX_PTR appData,OMX_COMPONENTTYPE ** component)670 android::SoftOMXComponent *createSoftOMXComponent(
671 const char *name, const OMX_CALLBACKTYPE *callbacks,
672 OMX_PTR appData, OMX_COMPONENTTYPE **component) {
673 return new android::SoftOpus(name, callbacks, appData, component);
674 }
675