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