xref: /aosp_15_r20/frameworks/av/media/libstagefright/codecs/raw/SoftRaw.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
1 /*
2  * Copyright (C) 2012 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 "SoftRaw"
19 #include <utils/Log.h>
20 
21 #include "SoftRaw.h"
22 
23 #include <media/stagefright/foundation/ADebug.h>
24 #include <media/stagefright/foundation/hexdump.h>
25 
26 namespace android {
27 
28 template<class T>
InitOMXParams(T * params)29 static void InitOMXParams(T *params) {
30     params->nSize = sizeof(T);
31     params->nVersion.s.nVersionMajor = 1;
32     params->nVersion.s.nVersionMinor = 0;
33     params->nVersion.s.nRevision = 0;
34     params->nVersion.s.nStep = 0;
35 }
36 
SoftRaw(const char * name,const OMX_CALLBACKTYPE * callbacks,OMX_PTR appData,OMX_COMPONENTTYPE ** component)37 SoftRaw::SoftRaw(
38         const char *name,
39         const OMX_CALLBACKTYPE *callbacks,
40         OMX_PTR appData,
41         OMX_COMPONENTTYPE **component)
42     : SimpleSoftOMXComponent(name, callbacks, appData, component),
43       mSignalledError(false),
44       mChannelCount(2),
45       mSampleRate(44100),
46       mNumericalData(OMX_NumericalDataSigned),
47       mBitsPerSample(16) {
48     initPorts();
49     CHECK_EQ(initDecoder(), (status_t)OK);
50 }
51 
~SoftRaw()52 SoftRaw::~SoftRaw() {
53 }
54 
initPorts()55 void SoftRaw::initPorts() {
56     OMX_PARAM_PORTDEFINITIONTYPE def;
57     InitOMXParams(&def);
58 
59     def.nPortIndex = 0;
60     def.eDir = OMX_DirInput;
61     def.nBufferCountMin = kNumBuffers;
62     def.nBufferCountActual = def.nBufferCountMin;
63     def.nBufferSize = 192 * 1024;
64     def.bEnabled = OMX_TRUE;
65     def.bPopulated = OMX_FALSE;
66     def.eDomain = OMX_PortDomainAudio;
67     def.bBuffersContiguous = OMX_FALSE;
68     def.nBufferAlignment = 1;
69 
70     def.format.audio.cMIMEType = const_cast<char *>("audio/raw");
71     def.format.audio.pNativeRender = NULL;
72     def.format.audio.bFlagErrorConcealment = OMX_FALSE;
73     def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
74 
75     addPort(def);
76 
77     def.nPortIndex = 1;
78     def.eDir = OMX_DirOutput;
79     def.nBufferCountMin = kNumBuffers;
80     def.nBufferCountActual = def.nBufferCountMin;
81     def.nBufferSize = 192 * 1024;
82     def.bEnabled = OMX_TRUE;
83     def.bPopulated = OMX_FALSE;
84     def.eDomain = OMX_PortDomainAudio;
85     def.bBuffersContiguous = OMX_FALSE;
86     def.nBufferAlignment = 2;
87 
88     def.format.audio.cMIMEType = const_cast<char *>("audio/raw");
89     def.format.audio.pNativeRender = NULL;
90     def.format.audio.bFlagErrorConcealment = OMX_FALSE;
91     def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
92 
93     addPort(def);
94 }
95 
initDecoder()96 status_t SoftRaw::initDecoder() {
97     return OK;
98 }
99 
internalGetParameter(OMX_INDEXTYPE index,OMX_PTR params)100 OMX_ERRORTYPE SoftRaw::internalGetParameter(
101         OMX_INDEXTYPE index, OMX_PTR params) {
102     switch (index) {
103         case OMX_IndexParamAudioPortFormat:
104         {
105             OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
106                 (OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
107 
108             if (!isValidOMXParam(formatParams)) {
109                 return OMX_ErrorBadParameter;
110             }
111 
112             if (formatParams->nPortIndex > 1) {
113                 return OMX_ErrorUndefined;
114             }
115 
116             if (formatParams->nIndex > 0) {
117                 return OMX_ErrorNoMore;
118             }
119 
120             formatParams->eEncoding = OMX_AUDIO_CodingPCM;
121 
122             return OMX_ErrorNone;
123         }
124 
125         case OMX_IndexParamAudioPcm:
126         {
127             OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
128                 (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
129 
130             if (!isValidOMXParam(pcmParams)) {
131                 return OMX_ErrorBadParameter;
132             }
133 
134             if (pcmParams->nPortIndex != 0 && pcmParams->nPortIndex != 1) {
135                 return OMX_ErrorUndefined;
136             }
137 
138             pcmParams->eNumData = (OMX_NUMERICALDATATYPE)mNumericalData;
139             pcmParams->eEndian = OMX_EndianBig;
140             pcmParams->bInterleaved = OMX_TRUE;
141             pcmParams->nBitPerSample = mBitsPerSample;
142             pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear;
143             pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF;
144             pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF;
145 
146             pcmParams->nChannels = mChannelCount;
147             pcmParams->nSamplingRate = mSampleRate;
148 
149             return OMX_ErrorNone;
150         }
151 
152         default:
153             return SimpleSoftOMXComponent::internalGetParameter(index, params);
154     }
155 }
156 
internalSetParameter(OMX_INDEXTYPE index,const OMX_PTR params)157 OMX_ERRORTYPE SoftRaw::internalSetParameter(
158         OMX_INDEXTYPE index, const OMX_PTR params) {
159     switch (index) {
160         case OMX_IndexParamStandardComponentRole:
161         {
162             const OMX_PARAM_COMPONENTROLETYPE *roleParams =
163                 (const OMX_PARAM_COMPONENTROLETYPE *)params;
164 
165             if (!isValidOMXParam(roleParams)) {
166                 return OMX_ErrorBadParameter;
167             }
168 
169             if (strncmp((const char *)roleParams->cRole,
170                         "audio_decoder.raw",
171                         OMX_MAX_STRINGNAME_SIZE - 1)) {
172                 return OMX_ErrorUndefined;
173             }
174 
175             return OMX_ErrorNone;
176         }
177 
178         case OMX_IndexParamAudioPortFormat:
179         {
180             const OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
181                 (const OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
182 
183             if (!isValidOMXParam(formatParams)) {
184                 return OMX_ErrorBadParameter;
185             }
186 
187             if (formatParams->nPortIndex > 1) {
188                 return OMX_ErrorUndefined;
189             }
190 
191             if (formatParams->eEncoding != OMX_AUDIO_CodingPCM) {
192                 return OMX_ErrorUndefined;
193             }
194 
195             return OMX_ErrorNone;
196         }
197 
198         case OMX_IndexParamAudioPcm:
199         {
200             const OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
201                 (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
202 
203             if (!isValidOMXParam(pcmParams)) {
204                 return OMX_ErrorBadParameter;
205             }
206 
207             if (pcmParams->nPortIndex != 0) {
208                 return OMX_ErrorUndefined;
209             }
210 
211             mChannelCount = pcmParams->nChannels;
212             mSampleRate = pcmParams->nSamplingRate;
213             mNumericalData = pcmParams->eNumData;
214             mBitsPerSample = pcmParams->nBitPerSample;
215 
216             return OMX_ErrorNone;
217         }
218 
219         default:
220         {
221             OMX_ERRORTYPE err = SimpleSoftOMXComponent::internalSetParameter(
222                     index, params);
223             // In case inPort->mDef.nBufferSize changed, the output buffer size
224             // should match the input buffer size.
225             PortInfo *inPort = editPortInfo(0);
226             PortInfo *outPort = editPortInfo(1);
227             outPort->mDef.nBufferSize = inPort->mDef.nBufferSize;
228             return err;
229         }
230     }
231 }
232 
onQueueFilled(OMX_U32)233 void SoftRaw::onQueueFilled(OMX_U32 /* portIndex */) {
234     if (mSignalledError) {
235         return;
236     }
237 
238     List<BufferInfo *> &inQueue = getPortQueue(0);
239     List<BufferInfo *> &outQueue = getPortQueue(1);
240 
241     while (!inQueue.empty() && !outQueue.empty()) {
242         BufferInfo *inInfo = *inQueue.begin();
243         OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
244 
245         BufferInfo *outInfo = *outQueue.begin();
246         OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
247 
248         CHECK_GE(outHeader->nAllocLen, inHeader->nFilledLen);
249         memcpy(outHeader->pBuffer,
250                inHeader->pBuffer + inHeader->nOffset,
251                inHeader->nFilledLen);
252 
253         outHeader->nFlags = inHeader->nFlags;
254         outHeader->nOffset = 0;
255         outHeader->nFilledLen = inHeader->nFilledLen;
256         outHeader->nTimeStamp = inHeader->nTimeStamp;
257 
258         bool sawEOS = (inHeader->nFlags & OMX_BUFFERFLAG_EOS) != 0;
259 
260         inQueue.erase(inQueue.begin());
261         inInfo->mOwnedByUs = false;
262         notifyEmptyBufferDone(inHeader);
263 
264         outQueue.erase(outQueue.begin());
265         outInfo->mOwnedByUs = false;
266         notifyFillBufferDone(outHeader);
267 
268         if (sawEOS) {
269             break;
270         }
271     }
272 }
273 
274 }  // namespace android
275 
276 __attribute__((cfi_canonical_jump_table))
createSoftOMXComponent(const char * name,const OMX_CALLBACKTYPE * callbacks,OMX_PTR appData,OMX_COMPONENTTYPE ** component)277 android::SoftOMXComponent *createSoftOMXComponent(
278         const char *name, const OMX_CALLBACKTYPE *callbacks,
279         OMX_PTR appData, OMX_COMPONENTTYPE **component) {
280     return new android::SoftRaw(name, callbacks, appData, component);
281 }
282