xref: /aosp_15_r20/frameworks/av/media/libstagefright/codecs/flac/dec/SoftFlacDecoder.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
1 /*
2  * Copyright (C) 2017 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 "SoftFlacDecoder"
19 #include <utils/Log.h>
20 
21 #include "SoftFlacDecoder.h"
22 #include <OMX_AudioExt.h>
23 #include <OMX_IndexExt.h>
24 
25 #include <cutils/properties.h>
26 #include <media/stagefright/foundation/ADebug.h>
27 #include <media/stagefright/MediaErrors.h>
28 #include <utils/misc.h>
29 
30 namespace android {
31 
32 template<class T>
InitOMXParams(T * params)33 static void InitOMXParams(T *params) {
34     params->nSize = sizeof(T);
35     params->nVersion.s.nVersionMajor = 1;
36     params->nVersion.s.nVersionMinor = 0;
37     params->nVersion.s.nRevision = 0;
38     params->nVersion.s.nStep = 0;
39 }
40 
SoftFlacDecoder(const char * name,const OMX_CALLBACKTYPE * callbacks,OMX_PTR appData,OMX_COMPONENTTYPE ** component)41 SoftFlacDecoder::SoftFlacDecoder(
42         const char *name,
43         const OMX_CALLBACKTYPE *callbacks,
44         OMX_PTR appData,
45         OMX_COMPONENTTYPE **component)
46     : SimpleSoftOMXComponent(name, callbacks, appData, component),
47       mFLACDecoder(NULL),
48       mInputBufferCount(0),
49       mHasStreamInfo(false),
50       mSignalledError(false),
51       mSawInputEOS(false),
52       mFinishedDecoder(false),
53       mOutputPortSettingsChange(NONE) {
54     ALOGV("ctor:");
55     memset(&mStreamInfo, 0, sizeof(mStreamInfo));
56     initPorts();
57     initDecoder();
58 }
59 
~SoftFlacDecoder()60 SoftFlacDecoder::~SoftFlacDecoder() {
61     ALOGV("dtor:");
62     delete mFLACDecoder;
63 }
64 
initPorts()65 void SoftFlacDecoder::initPorts() {
66     ALOGV("initPorts:");
67     OMX_PARAM_PORTDEFINITIONTYPE def;
68     InitOMXParams(&def);
69 
70     def.nPortIndex = 0;
71     def.eDir = OMX_DirInput;
72     def.nBufferCountMin = kNumInputBuffers;
73     def.nBufferCountActual = def.nBufferCountMin;
74     def.nBufferSize = 32768;
75     def.bEnabled = OMX_TRUE;
76     def.bPopulated = OMX_FALSE;
77     def.eDomain = OMX_PortDomainAudio;
78     def.bBuffersContiguous = OMX_FALSE;
79     def.nBufferAlignment = 1;
80 
81     def.format.audio.cMIMEType = const_cast<char *>("audio/flac");
82     def.format.audio.pNativeRender = NULL;
83     def.format.audio.bFlagErrorConcealment = OMX_FALSE;
84     def.format.audio.eEncoding = OMX_AUDIO_CodingFLAC;
85 
86     addPort(def);
87 
88     def.nPortIndex = 1;
89     def.eDir = OMX_DirOutput;
90     def.nBufferCountMin = kNumOutputBuffers;
91     def.nBufferCountActual = def.nBufferCountMin;
92     def.nBufferSize = kNumSamplesPerFrame * FLACDecoder::kMaxChannels * sizeof(float);
93     def.bEnabled = OMX_TRUE;
94     def.bPopulated = OMX_FALSE;
95     def.eDomain = OMX_PortDomainAudio;
96     def.bBuffersContiguous = OMX_FALSE;
97     def.nBufferAlignment = sizeof(float);
98 
99     def.format.audio.cMIMEType = const_cast<char *>("audio/raw");
100     def.format.audio.pNativeRender = NULL;
101     def.format.audio.bFlagErrorConcealment = OMX_FALSE;
102     def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
103 
104     addPort(def);
105 }
106 
initDecoder()107 void SoftFlacDecoder::initDecoder() {
108     ALOGV("initDecoder:");
109     mFLACDecoder = FLACDecoder::Create();
110     if (mFLACDecoder == NULL) {
111         ALOGE("initDecoder: failed to create FLACDecoder");
112         mSignalledError = true;
113     }
114 }
115 
initCheck() const116 OMX_ERRORTYPE SoftFlacDecoder::initCheck() const {
117     if (mSignalledError) {
118         if (mFLACDecoder == NULL) {
119             ALOGE("initCheck: failed due to NULL encoder");
120             return OMX_ErrorDynamicResourcesUnavailable;
121         }
122         return OMX_ErrorUndefined;
123     }
124 
125     return SimpleSoftOMXComponent::initCheck();
126 }
127 
internalGetParameter(OMX_INDEXTYPE index,OMX_PTR params)128 OMX_ERRORTYPE SoftFlacDecoder::internalGetParameter(
129         OMX_INDEXTYPE index, OMX_PTR params) {
130     ALOGV("internalGetParameter: index(%x)", index);
131     switch ((OMX_U32)index) {
132         case OMX_IndexParamAudioPortFormat:
133         {
134             OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
135                 (OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
136 
137             if (!isValidOMXParam(formatParams)) {
138                 return OMX_ErrorBadParameter;
139             }
140 
141             if (formatParams->nPortIndex > 1) {
142                 return OMX_ErrorUndefined;
143             }
144 
145             if (formatParams->nIndex > 0) {
146                 return OMX_ErrorNoMore;
147             }
148 
149             formatParams->eEncoding =
150                 (formatParams->nPortIndex == 0)
151                     ? OMX_AUDIO_CodingFLAC : OMX_AUDIO_CodingPCM;
152 
153             return OMX_ErrorNone;
154         }
155         case OMX_IndexParamAudioFlac:
156         {
157             OMX_AUDIO_PARAM_FLACTYPE *flacParams =
158                 (OMX_AUDIO_PARAM_FLACTYPE *)params;
159 
160             if (!isValidOMXParam(flacParams)) {
161                 ALOGE("internalGetParameter(OMX_IndexParamAudioFlac): invalid omx params");
162                 return OMX_ErrorBadParameter;
163             }
164 
165             if (flacParams->nPortIndex != 0) {
166                 ALOGE("internalGetParameter(OMX_IndexParamAudioFlac): bad port index");
167                 return OMX_ErrorBadPortIndex;
168             }
169 
170             flacParams->nCompressionLevel = 0;
171 
172             if (isConfigured()) {
173                 flacParams->nChannels = mStreamInfo.channels;
174                 flacParams->nSampleRate = mStreamInfo.sample_rate;
175             } else {
176                 flacParams->nChannels = 2;
177                 flacParams->nSampleRate = 44100;
178             }
179 
180             return OMX_ErrorNone;
181         }
182 
183         case OMX_IndexParamAudioPcm:
184         {
185             OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
186                 (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
187 
188             if (!isValidOMXParam(pcmParams)) {
189                 ALOGE("internalGetParameter(OMX_IndexParamAudioPcm): invalid omx params");
190                 return OMX_ErrorBadParameter;
191             }
192 
193             if (pcmParams->nPortIndex != 1) {
194                 ALOGE("internalGetParameter(OMX_IndexParamAudioPcm): bad port index");
195                 return OMX_ErrorBadPortIndex;
196             }
197 
198             pcmParams->eNumData = mNumericalData;
199             pcmParams->eEndian = OMX_EndianBig;
200             pcmParams->bInterleaved = OMX_TRUE;
201             pcmParams->nBitPerSample = mBitsPerSample;
202             pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear;
203             pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF;
204             pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF;
205             pcmParams->eChannelMapping[2] = OMX_AUDIO_ChannelCF;
206             pcmParams->eChannelMapping[3] = OMX_AUDIO_ChannelLFE;
207             pcmParams->eChannelMapping[4] = OMX_AUDIO_ChannelLS;
208             pcmParams->eChannelMapping[5] = OMX_AUDIO_ChannelRS;
209 
210             if (isConfigured()) {
211                 pcmParams->nChannels = mStreamInfo.channels;
212                 pcmParams->nSamplingRate = mStreamInfo.sample_rate;
213             } else {
214                 pcmParams->nChannels = 2;
215                 pcmParams->nSamplingRate = 44100;
216             }
217 
218             return OMX_ErrorNone;
219         }
220 
221         default:
222             return SimpleSoftOMXComponent::internalGetParameter(index, params);
223     }
224 }
225 
internalSetParameter(OMX_INDEXTYPE index,const OMX_PTR params)226 OMX_ERRORTYPE SoftFlacDecoder::internalSetParameter(
227         OMX_INDEXTYPE index, const OMX_PTR params) {
228     ALOGV("internalSetParameter: index(%x)", (int)index);
229     switch ((int)index) {
230         case OMX_IndexParamStandardComponentRole:
231         {
232             const OMX_PARAM_COMPONENTROLETYPE *roleParams =
233                 (const OMX_PARAM_COMPONENTROLETYPE *)params;
234 
235             if (!isValidOMXParam(roleParams)) {
236                 return OMX_ErrorBadParameter;
237             }
238 
239             if (strncmp((const char *)roleParams->cRole,
240                         "audio_decoder.flac",
241                         OMX_MAX_STRINGNAME_SIZE - 1) != 0) {
242                 return OMX_ErrorInvalidComponentName;
243             }
244 
245             return OMX_ErrorNone;
246         }
247 
248         case OMX_IndexParamAudioPortFormat:
249         {
250             const OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
251                 (const OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
252 
253             if (!isValidOMXParam(formatParams)) {
254                 return OMX_ErrorBadParameter;
255             }
256 
257             if (formatParams->nPortIndex > 1) {
258                 return OMX_ErrorUndefined;
259             }
260 
261             if ((formatParams->nPortIndex == 0
262                         && formatParams->eEncoding != OMX_AUDIO_CodingFLAC)
263                 || (formatParams->nPortIndex == 1
264                         && formatParams->eEncoding != OMX_AUDIO_CodingPCM)) {
265                 return OMX_ErrorUndefined;
266             }
267 
268             return OMX_ErrorNone;
269         }
270 
271         case OMX_IndexParamAudioPcm:
272         {
273             const OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
274                 (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
275 
276             if (!isValidOMXParam(pcmParams)) {
277                 return OMX_ErrorBadParameter;
278             }
279 
280             if (pcmParams->nPortIndex != 1) {
281                 return OMX_ErrorBadPortIndex;
282             }
283 
284             if (pcmParams->eNumData == OMX_NumericalDataFloat && pcmParams->nBitPerSample == 32) {
285                 mNumericalData = OMX_NumericalDataFloat;
286                 mBitsPerSample = 32;
287             } else if (pcmParams->eNumData == OMX_NumericalDataSigned
288                      && pcmParams->nBitPerSample == 16) {
289                 mNumericalData = OMX_NumericalDataSigned;
290                 mBitsPerSample = 16;
291             } else {
292                 ALOGE("Invalid eNumData %d, nBitsPerSample %d",
293                         pcmParams->eNumData, pcmParams->nBitPerSample);
294                 return OMX_ErrorUndefined;
295             }
296 
297             return OMX_ErrorNone;
298         }
299 
300         default:
301             return SimpleSoftOMXComponent::internalSetParameter(index, params);
302     }
303 }
304 
isConfigured() const305 bool SoftFlacDecoder::isConfigured() const {
306     return mHasStreamInfo;
307 }
308 
onQueueFilled(OMX_U32)309 void SoftFlacDecoder::onQueueFilled(OMX_U32 /* portIndex */) {
310     if (mSignalledError || mOutputPortSettingsChange != NONE) {
311         return;
312     }
313 
314     List<BufferInfo *> &inQueue = getPortQueue(0);
315     List<BufferInfo *> &outQueue = getPortQueue(1);
316 
317     const bool outputFloat = mNumericalData == OMX_NumericalDataFloat;
318 
319     ALOGV("onQueueFilled %d/%d:", inQueue.empty(), outQueue.empty());
320     while ((!inQueue.empty() || mSawInputEOS) && !outQueue.empty() && !mFinishedDecoder) {
321         BufferInfo *outInfo = *outQueue.begin();
322         OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
323         void *outBuffer = reinterpret_cast<void *>(outHeader->pBuffer + outHeader->nOffset);
324         size_t outBufferSize = outHeader->nAllocLen - outHeader->nOffset;
325         int64_t timeStamp = 0;
326 
327         if (!inQueue.empty()) {
328             BufferInfo *inInfo = *inQueue.begin();
329             OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
330             uint8_t* inBuffer = inHeader->pBuffer + inHeader->nOffset;
331             uint32_t inBufferLength = inHeader->nFilledLen;
332             ALOGV("input: %u bytes", inBufferLength);
333             if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
334                 ALOGV("saw EOS");
335                 mSawInputEOS = true;
336                 if (mInputBufferCount == 0 && inHeader->nFilledLen == 0) {
337                     // first buffer was empty and EOS: signal EOS on output and return
338                     ALOGV("empty first EOS");
339                     outHeader->nFilledLen = 0;
340                     outHeader->nTimeStamp = inHeader->nTimeStamp;
341                     outHeader->nFlags = OMX_BUFFERFLAG_EOS;
342                     outInfo->mOwnedByUs = false;
343                     outQueue.erase(outQueue.begin());
344                     notifyFillBufferDone(outHeader);
345                     mFinishedDecoder = true;
346                     inInfo->mOwnedByUs = false;
347                     inQueue.erase(inQueue.begin());
348                     notifyEmptyBufferDone(inHeader);
349                     return;
350                 }
351             }
352 
353             if (mInputBufferCount == 0 && !(inHeader->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) {
354                 ALOGE("onQueueFilled: first buffer should have OMX_BUFFERFLAG_CODECCONFIG set");
355                 inHeader->nFlags |= OMX_BUFFERFLAG_CODECCONFIG;
356             }
357             if ((inHeader->nFlags & OMX_BUFFERFLAG_CODECCONFIG) != 0) {
358                 ALOGV("received config buffer of size %u", inBufferLength);
359                 status_t decoderErr = mFLACDecoder->parseMetadata(inBuffer, inBufferLength);
360                 mInputBufferCount++;
361 
362                 if (decoderErr != OK && decoderErr != WOULD_BLOCK) {
363                     ALOGE("onQueueFilled: FLACDecoder parseMetaData returns error %d", decoderErr);
364                     mSignalledError = true;
365                     notify(OMX_EventError, OMX_ErrorStreamCorrupt, decoderErr, NULL);
366                     return;
367                 }
368 
369                 inInfo->mOwnedByUs = false;
370                 inQueue.erase(inQueue.begin());
371                 notifyEmptyBufferDone(inHeader);
372 
373                 if (decoderErr == WOULD_BLOCK) {
374                     continue;
375                 }
376                 mStreamInfo = mFLACDecoder->getStreamInfo();
377                 mHasStreamInfo = true;
378 
379                 // Only send out port settings changed event if both sample rate
380                 // and numChannels are valid.
381                 if (mStreamInfo.sample_rate && mStreamInfo.channels) {
382                     ALOGD("onQueueFilled: initially configuring decoder: %d Hz, %d channels",
383                         mStreamInfo.sample_rate, mStreamInfo.channels);
384 
385                     notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
386                     mOutputPortSettingsChange = AWAITING_DISABLED;
387                 }
388                 return;
389             }
390 
391             status_t decoderErr = mFLACDecoder->decodeOneFrame(
392                     inBuffer, inBufferLength, outBuffer, &outBufferSize, outputFloat);
393             if (decoderErr != OK) {
394                 ALOGE("onQueueFilled: FLACDecoder decodeOneFrame returns error %d", decoderErr);
395                 mSignalledError = true;
396                 notify(OMX_EventError, OMX_ErrorStreamCorrupt, decoderErr, NULL);
397                 return;
398             }
399 
400             mInputBufferCount++;
401             timeStamp = inHeader->nTimeStamp;
402             inInfo->mOwnedByUs = false;
403             inQueue.erase(inQueue.begin());
404             notifyEmptyBufferDone(inHeader);
405 
406             if (outBufferSize == 0) {
407                 ALOGV("no output, trying again");
408                 continue;
409             }
410         } else if (mSawInputEOS) {
411             status_t decoderErr = mFLACDecoder->decodeOneFrame(
412                     nullptr /* inBuffer */, 0 /* inBufferLen */,
413                     outBuffer, &outBufferSize, outputFloat);
414             mFinishedDecoder = true;
415             if (decoderErr != OK) {
416                 ALOGE("onQueueFilled: FLACDecoder finish returns error %d", decoderErr);
417                 mSignalledError = true;
418                 notify(OMX_EventError, OMX_ErrorStreamCorrupt, decoderErr, NULL);
419                 return;
420             }
421             outHeader->nFlags = OMX_BUFFERFLAG_EOS;
422         } else {
423             // no more input buffers at this time, loop and see if there is more output
424             continue;
425         }
426 
427         outHeader->nFilledLen = outBufferSize;
428         outHeader->nTimeStamp = timeStamp;
429 
430         outInfo->mOwnedByUs = false;
431         outQueue.erase(outQueue.begin());
432         notifyFillBufferDone(outHeader);
433     }
434 }
435 
onPortFlushCompleted(OMX_U32 portIndex)436 void SoftFlacDecoder::onPortFlushCompleted(OMX_U32 portIndex) {
437     ALOGV("onPortFlushCompleted: portIndex(%u)", portIndex);
438     if (portIndex == 0) {
439         drainDecoder();
440     }
441 }
442 
drainDecoder()443 void SoftFlacDecoder::drainDecoder() {
444     mFLACDecoder->flush();
445     mSawInputEOS = false;
446     mFinishedDecoder = false;
447 }
448 
onReset()449 void SoftFlacDecoder::onReset() {
450     ALOGV("onReset");
451     drainDecoder();
452 
453     memset(&mStreamInfo, 0, sizeof(mStreamInfo));
454     mHasStreamInfo = false;
455     mInputBufferCount = 0;
456     mSignalledError = false;
457     mOutputPortSettingsChange = NONE;
458 }
459 
onPortEnableCompleted(OMX_U32 portIndex,bool enabled)460 void SoftFlacDecoder::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) {
461     ALOGV("onPortEnableCompleted: portIndex(%u), enabled(%d)", portIndex, enabled);
462     if (portIndex != 1) {
463         return;
464     }
465 
466     switch (mOutputPortSettingsChange) {
467         case NONE:
468             break;
469 
470         case AWAITING_DISABLED:
471         {
472             CHECK(!enabled);
473             mOutputPortSettingsChange = AWAITING_ENABLED;
474             PortInfo *info = editPortInfo(1 /* portIndex */);
475             if (!info->mDef.bEnabled) {
476                 info->mDef.nBufferSize =
477                         mStreamInfo.max_blocksize * mStreamInfo.channels * sizeof(float);
478             }
479             break;
480         }
481 
482         default:
483         {
484             CHECK_EQ((int)mOutputPortSettingsChange, (int)AWAITING_ENABLED);
485             CHECK(enabled);
486             mOutputPortSettingsChange = NONE;
487             break;
488         }
489     }
490 }
491 
492 }  // namespace android
493 
494 __attribute__((cfi_canonical_jump_table))
createSoftOMXComponent(const char * name,const OMX_CALLBACKTYPE * callbacks,OMX_PTR appData,OMX_COMPONENTTYPE ** component)495 android::SoftOMXComponent *createSoftOMXComponent(
496         const char *name, const OMX_CALLBACKTYPE *callbacks,
497         OMX_PTR appData, OMX_COMPONENTTYPE **component) {
498     ALOGV("createSoftOMXComponent: flac decoder");
499     return new android::SoftFlacDecoder(name, callbacks, appData, component);
500 }
501