1 /*******************************************************************************
2 * Copyright (C) 2018 Cadence Design Systems, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * "Software"), to use this Software with Cadence processor cores only and
7 * not with any other processors and platforms, subject to
8 * the following conditions:
9 *
10 * The above copyright notice and this permission notice shall be included
11 * in all copies or substantial portions of the Software.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
14 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
15 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
16 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
17 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
18 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
19 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21 ******************************************************************************/
22
23 /*******************************************************************************
24 * xa-pcm.c
25 *
26 * PCM format converter plugin
27 *
28 ******************************************************************************/
29
30 #define MODULE_TAG PCM
31
32 /*******************************************************************************
33 * Includes
34 ******************************************************************************/
35
36 #include "xf-plugin.h"
37 #include "xa-audio-decoder-api.h"
38 #include "xa-pcm-api.h"
39
40 #include <fcntl.h>
41
42 /*******************************************************************************
43 * Tracing configuration
44 ******************************************************************************/
45
46 TRACE_TAG(INIT, 1);
47 TRACE_TAG(PROCESS, 0);
48
49 /*******************************************************************************
50 * Local typedefs
51 ******************************************************************************/
52
53 /* ...API structure */
54 typedef struct XAPcmCodec
55 {
56 /* ...codec state */
57 u32 state;
58
59 /* ...sampling rate of input/output signal (informative only) */
60 u32 sample_rate;
61
62 /* ...number of input/output channels */
63 u8 in_channels, out_channels;
64
65 /* ...PCM sample width of input/output streams */
66 u8 in_pcm_width, out_pcm_width;
67
68 /* ...input/output stride size */
69 u8 in_stride, out_stride;
70
71 /* ...channel routing map between input and output */
72 u32 chan_routing;
73
74 /* ...data processing hook */
75 XA_ERRORCODE (*process)(struct XAPcmCodec *);
76
77 /* ...number of samples in input/output buffers */
78 u32 insize, outsize;
79
80 /* ...input/output memory indices */
81 u32 input_idx, output_idx;
82
83 /* ...input/output buffers passed from/to caller */
84 void *input, *output;
85
86 /* ...number of input bytes consumed/produced */
87 u32 consumed, produced;
88
89 /* ...debug - file handles */
90 int f_input, f_output;
91
92 } XAPcmCodec;
93
94 /*******************************************************************************
95 * Local execution flags
96 ******************************************************************************/
97
98 #define XA_PCM_FLAG_PREINIT_DONE (1 << 0)
99 #define XA_PCM_FLAG_POSTINIT_DONE (1 << 1)
100 #define XA_PCM_FLAG_RUNNING (1 << 2)
101 #define XA_PCM_FLAG_EOS (1 << 3)
102 #define XA_PCM_FLAG_COMPLETE (1 << 4)
103
104 /*******************************************************************************
105 * Local constants definitions
106 ******************************************************************************/
107
108 /* ...process at most 1024 samples per call */
109 #define XA_PCM_MAX_SAMPLES 1024
110
111 /*******************************************************************************
112 * Internal processing functions
113 ******************************************************************************/
114
115 /* ...identity translation of PCM16/24 */
xa_pcm_do_execute_copy(XAPcmCodec * d)116 static XA_ERRORCODE xa_pcm_do_execute_copy(XAPcmCodec *d)
117 {
118 u32 n = d->insize;
119 u8 k = d->in_channels;
120 u32 length = n * k * (d->in_pcm_width == 16 ? 2 : 4);
121 s16 *input = d->input, *output = d->output;
122
123 TRACE(PROCESS, _b("Copy PCM%d %p to %p (%u samples)"), d->in_pcm_width, input, output, n);
124
125 /* ...check if we have all data setup */
126 XF_CHK_ERR(input && n && output, XA_PCM_EXEC_FATAL_STATE);
127
128 /* ...copy the samples without any processing */
129 memcpy(output, input, length);
130
131 /* ...set number of consumed/produced bytes */
132 d->consumed = length;
133 d->produced = length;
134
135 /* ...reset input buffer length */
136 d->insize = 0;
137
138 /* ...copy input to output */
139 return XA_NO_ERROR;
140 }
141
142 /* ...data processing for PCM16, channel mapping case */
xa_pcm_do_execute_pcm16_chmap(XAPcmCodec * d)143 static XA_ERRORCODE xa_pcm_do_execute_pcm16_chmap(XAPcmCodec *d)
144 {
145 u32 n = d->insize, i;
146 u8 k = d->in_channels, j;
147 u32 chmap = d->chan_routing, map;
148 s16 *input = d->input, *output = d->output;
149 u32 length = n * k * (d->in_pcm_width == 16 ? 2 : 4);
150
151 TRACE(PROCESS, _b("Map PCM16 %p to %p (%u samples, map: %X)"), input, output, n, chmap);
152
153 /* ...check if we have all data setup */
154 XF_CHK_ERR(input && n && output, XA_PCM_EXEC_FATAL_STATE);
155
156 #if 0
157 /* ...convert individual samples (that function could be CPU-optimized - tbd) */
158 for (i = 0; i < n; i++, input += k)
159 {
160 /* ...process individual channels in a sample */
161 for (j = 0, map = chmap; j < k; j++, map >>= 4)
162 {
163 u8 m = map & 0xF;
164
165 /* ...fill output channel (zero unused channel) */
166 *output++ = (m < 8 ? input[m] : 0);
167 }
168 }
169
170 /* ...set number of consumed/produced bytes */
171 d->consumed = (u32)((u8 *)input - (u8 *)d->input);
172 d->produced = (u32)((u8 *)output - (u8 *)d->output);
173 #else
174 memcpy(output, input, length);
175 /* ...set number of consumed/produced bytes */
176 d->consumed = length;
177 d->produced = length;
178 #endif
179 /* ...reset input buffer length */
180 d->insize = 0;
181
182 /* ...copy input to output */
183 return XA_NO_ERROR;
184 }
185
186 /* ...data processing for PCM24/PCM32, channel mapping case */
xa_pcm_do_execute_pcm24_chmap(XAPcmCodec * d)187 static XA_ERRORCODE xa_pcm_do_execute_pcm24_chmap(XAPcmCodec *d)
188 {
189 u32 n = d->insize, i;
190 u8 k = d->in_channels, j;
191 u32 chmap = d->chan_routing, map;
192 s32 *input = d->input, *output = d->output;
193
194 TRACE(PROCESS, _b("Map PCM24 %p to %p (%u samples, map: %X)"), input, output, n, chmap);
195
196 /* ...check if we have all data setup */
197 XF_CHK_ERR(input && n && output, XA_PCM_EXEC_FATAL_STATE);
198
199 /* ...convert individual samples (that function could be CPU-optimized - tbd) */
200 for (i = 0; i < n; i++, input += k)
201 {
202 /* ...process individual channels in a sample */
203 for (j = 0, map = chmap; j < k; j++, map >>= 4)
204 {
205 u8 m = map & 0xF;
206
207 /* ...fill output channel (zero unused channel) */
208 *output++ = (m < 8 ? input[m] : 0);
209 }
210 }
211
212 /* ...set number of consumed/produced bytes */
213 d->consumed = (u32)((u8 *)input - (u8 *)d->input);
214 d->produced = (u32)((u8 *)output - (u8 *)d->output);
215
216 /* ...reset input buffer length */
217 d->insize = 0;
218
219 /* ...copy input to output */
220 return XA_NO_ERROR;
221 }
222
223 /* ...convert multichannel 24-bit PCM to 16-bit PCM with channel mapping */
xa_pcm_do_execute_pcm24_to_pcm16(XAPcmCodec * d)224 static XA_ERRORCODE xa_pcm_do_execute_pcm24_to_pcm16(XAPcmCodec *d)
225 {
226 u32 n = d->insize, i;
227 u8 k = d->in_channels, j;
228 u32 chmap = d->chan_routing, map;
229 s32 *input = d->input;
230 s16 *output = d->output;
231
232 TRACE(PROCESS, _b("Convert PCM24 %p to PCM16 %p (%u samples, map: %X)"), input, output, n, chmap);
233
234 /* ...check if we have all data setup */
235 XF_CHK_ERR(input && n && output, XA_PCM_EXEC_FATAL_STATE);
236
237 /* ...convert individual samples (that function could be CPU-optimized - tbd) */
238 for (i = 0; i < n; i++, input += k)
239 {
240 /* ...process individual channels in a sample */
241 for (j = 0, map = chmap; j < k; j++, map >>= 4)
242 {
243 u8 m = map & 0xF;
244
245 /* ...convert and zero out unused channels */
246 *output++ = (m < 8 ? input[m] >> 16 : 0);
247 }
248 }
249
250 /* ...set number of consumed/produced bytes */
251 d->consumed = (u32)((u8 *)input - (u8 *)d->input);
252 d->produced = (u32)((u8 *)output - (u8 *)d->output);
253
254 /* ...dump output data */
255 //BUG(write(d->f_input, d->input, d->consumed) != d->consumed, _x("%m"));
256 //BUG(write(d->f_output, d->output, d->produced) != d->produced, _x("%m"));
257
258 /* ...reset input buffer length (tbd - need that?) */
259 d->insize = 0;
260
261 /* ...copy input to output */
262 return XA_NO_ERROR;
263 }
264
265 /* ...convert multichannel 16-bit PCM to 24-bit PCM with channel mapping */
xa_pcm_do_execute_pcm16_to_pcm24(XAPcmCodec * d)266 static XA_ERRORCODE xa_pcm_do_execute_pcm16_to_pcm24(XAPcmCodec *d)
267 {
268 u32 n = d->insize, i;
269 u8 k = d->in_channels, j;
270 u32 chmap = d->chan_routing, map;
271 s16 *input = d->input;
272 s32 *output = d->output;
273
274 TRACE(PROCESS, _b("Convert PCM16 %p to PCM24 %p (%u samples, map: %X)"), input, output, n, chmap);
275
276 /* ...check if we have all data setup */
277 XF_CHK_ERR(input && n && output, XA_PCM_EXEC_FATAL_STATE);
278
279 /* ...convert individual samples (that function could be CPU-optimized - tbd) */
280 for (i = 0; i < n; i++, input += k)
281 {
282 /* ...process individual channels in a sample */
283 for (j = 0, map = chmap; j < k; j++, map >>= 4)
284 {
285 u8 m = map & 0xF;
286
287 /* ...convert and zero out unused channels */
288 *output++ = (m < 8 ? input[m] << 16 : 0);
289 }
290 }
291
292 /* ...set number of consumed/produced bytes */
293 d->consumed = (u32)((u8 *)input - (u8 *)d->input);
294 d->produced = (u32)((u8 *)output - (u8 *)d->output);
295
296 /* ...reset input buffer length (tbd - need that?) */
297 d->insize = 0;
298
299 /* ...copy input to output */
300 return XA_NO_ERROR;
301 }
302
303 /* ...determine if we need to do a channel routing */
xa_pcm_is_identity_mapping(u32 chmap,u8 k)304 static inline int xa_pcm_is_identity_mapping(u32 chmap, u8 k)
305 {
306 u8 j;
307
308 for (j = 0; j < k; j++, chmap >>= 4)
309 if ((chmap & 0xF) != j)
310 return 0;
311
312 return 1;
313 }
314
315 /* ...runtime initialization */
xa_pcm_do_runtime_init(XAPcmCodec * d)316 static inline XA_ERRORCODE xa_pcm_do_runtime_init(XAPcmCodec *d)
317 {
318 u8 in_width = d->in_pcm_width, out_width = d->out_pcm_width;
319 u8 in_ch = d->in_channels, out_ch = d->out_channels;
320 u32 chmap = d->chan_routing;
321
322 /* ...check for supported processing schemes */
323 if (in_width == out_width)
324 {
325 /* ...check if we need to do a channel mapping */
326 if (in_ch != out_ch || !xa_pcm_is_identity_mapping(chmap, in_ch))
327 {
328 /* ...mapping is needed */
329 d->process = (in_width == 16 ? xa_pcm_do_execute_pcm16_chmap : xa_pcm_do_execute_pcm24_chmap);
330 }
331 else
332 {
333 /* ...setup identity translation */
334 d->process = xa_pcm_do_execute_copy;
335 }
336 }
337 else
338 {
339 /* ...samples converion is required */
340 d->process = (in_width == 16 ? xa_pcm_do_execute_pcm16_to_pcm24 : xa_pcm_do_execute_pcm24_to_pcm16);
341 }
342
343 /* ...mark the runtime initialization is completed */
344 d->state = XA_PCM_FLAG_PREINIT_DONE | XA_PCM_FLAG_POSTINIT_DONE | XA_PCM_FLAG_RUNNING;
345
346 TRACE(INIT, _b("PCM format converter initialized: PCM%u -> PCM%u, ich=%u, och=%u, map=%X"), in_width, out_width, in_ch, out_ch, chmap);
347
348 return XA_NO_ERROR;
349 }
350
351 /*******************************************************************************
352 * Commands processing
353 ******************************************************************************/
354
355 /* ...standard codec initialization routine */
xa_pcm_get_api_size(XAPcmCodec * d,WORD32 i_idx,pVOID pv_value)356 static XA_ERRORCODE xa_pcm_get_api_size(XAPcmCodec *d, WORD32 i_idx, pVOID pv_value)
357 {
358 /* ...return API structure size */
359 *(WORD32 *)pv_value = sizeof(*d);
360
361 return XA_NO_ERROR;
362 }
363
364 /* ...standard codec initialization routine */
xa_pcm_init(XAPcmCodec * d,WORD32 i_idx,pVOID pv_value)365 static XA_ERRORCODE xa_pcm_init(XAPcmCodec *d, WORD32 i_idx, pVOID pv_value)
366 {
367 /* ...validity check */
368 XF_CHK_ERR(d, XA_API_FATAL_INVALID_CMD_TYPE);
369
370 /* ...process particular initialization type */
371 switch (i_idx)
372 {
373 case XA_CMD_TYPE_INIT_API_PRE_CONFIG_PARAMS:
374 {
375 /* ...pre-configuration initialization; reset internal data */
376 memset(d, 0, sizeof(*d));
377
378 /* ...set default parameters */
379 d->in_pcm_width = d->out_pcm_width = 16;
380 d->in_channels = d->out_channels = 2;
381 d->chan_routing = (0 << 0) | (1 << 1);
382 d->sample_rate = 48000;
383
384 /* ...open debug files */
385 //BUG((d->f_input = open("pcm-in.dat", O_WRONLY | O_CREAT, 0664)) < 0, _x("%m"));
386 //BUG((d->f_output = open("pcm-out.dat", O_WRONLY | O_CREAT, 0664)) < 0, _x("%m"));
387
388 /* ...mark pre-initialization is done */
389 d->state = XA_PCM_FLAG_PREINIT_DONE;
390
391 return XA_NO_ERROR;
392 }
393
394 case XA_CMD_TYPE_INIT_API_POST_CONFIG_PARAMS:
395 {
396 /* ...post-configuration initialization (all parameters are set) */
397 XF_CHK_ERR(d->state & XA_PCM_FLAG_PREINIT_DONE, XA_API_FATAL_INVALID_CMD_TYPE);
398
399 /* ...calculate input sample stride size */
400 d->in_stride = d->in_channels * (d->in_pcm_width == 16 ? 2 : 4);
401 d->out_stride = d->out_channels * (d->out_pcm_width == 16 ? 2 : 4);
402
403 /* ...mark post-initialization is complete */
404 d->state |= XA_PCM_FLAG_POSTINIT_DONE;
405
406 return XA_NO_ERROR;
407 }
408
409 case XA_CMD_TYPE_INIT_PROCESS:
410 {
411 /* ...run-time initialization process; make sure post-init is complete */
412 XF_CHK_ERR(d->state & XA_PCM_FLAG_POSTINIT_DONE, XA_API_FATAL_INVALID_CMD_TYPE);
413
414 /* ...initialize runtime for specified transformation function */
415 return xa_pcm_do_runtime_init(d);
416 }
417
418 case XA_CMD_TYPE_INIT_DONE_QUERY:
419 {
420 /* ...check for runtime initialization completion; maske usre post-init is complete */
421 XF_CHK_ERR(d->state & XA_PCM_FLAG_POSTINIT_DONE, XA_API_FATAL_INVALID_CMD_TYPE);
422
423 /* ...put current status */
424 *(WORD32 *)pv_value = (d->state & XA_PCM_FLAG_RUNNING ? 1 : 0);
425
426 return XA_NO_ERROR;
427 }
428
429 default:
430 /* ...unrecognized command */
431 return XF_CHK_ERR(0, XA_API_FATAL_INVALID_CMD_TYPE);
432 }
433 }
434
435 /* ...set configuration parameter */
xa_pcm_set_config_param(XAPcmCodec * d,WORD32 i_idx,pVOID pv_value)436 static XA_ERRORCODE xa_pcm_set_config_param(XAPcmCodec *d, WORD32 i_idx, pVOID pv_value)
437 {
438 WORD32 i_value;
439
440 /* ...validity check */
441 XF_CHK_ERR(d && pv_value, XA_API_FATAL_INVALID_CMD_TYPE);
442
443 /* ...configuration is allowed only in PRE-CONFIG state */
444 XF_CHK_ERR(d->state == XA_PCM_FLAG_PREINIT_DONE, XA_PCM_CONFIG_NONFATAL_STATE);
445
446 /* ...get integer parameter value */
447 i_value = *(WORD32 *)pv_value;
448
449 /* ...process individual configuration parameter */
450 switch (i_idx)
451 {
452 case XA_CODEC_CONFIG_PARAM_SAMPLE_RATE:
453 case XA_PCM_CONFIG_PARAM_SAMPLE_RATE:
454 /* ...accept any sampling rate */
455 d->sample_rate = (u32)i_value;
456 return XA_NO_ERROR;
457
458 case XA_PCM_CONFIG_PARAM_IN_PCM_WIDTH:
459 /* ...return input sample bit-width */
460 XF_CHK_ERR(i_value == 16 || i_value == 24, XA_PCM_CONFIG_NONFATAL_RANGE);
461 d->in_pcm_width = (u8)i_value;
462 return XA_NO_ERROR;
463
464 case XA_PCM_CONFIG_PARAM_IN_CHANNELS:
465 /* ...support at most 8-channels stream */
466 XF_CHK_ERR(i_value > 0 && i_value <= 8, XA_PCM_CONFIG_NONFATAL_RANGE);
467 d->in_channels = (u8)i_value;
468 return XA_NO_ERROR;
469
470 case XA_CODEC_CONFIG_PARAM_PCM_WIDTH:
471 case XA_PCM_CONFIG_PARAM_OUT_PCM_WIDTH:
472 /* ...we only support PCM16 and PCM24 */
473 XF_CHK_ERR(i_value == 16 || i_value == 24, XA_PCM_CONFIG_NONFATAL_RANGE);
474 d->out_pcm_width = (u8)i_value;
475 return XA_NO_ERROR;
476
477 case XA_CODEC_CONFIG_PARAM_CHANNELS:
478 case XA_PCM_CONFIG_PARAM_OUT_CHANNELS:
479 /* ...support at most 8-channels stream */
480 XF_CHK_ERR(i_value > 0 && i_value <= 8, XA_API_FATAL_INVALID_CMD_TYPE);
481 d->out_channels = (u8)i_value;
482 return XA_NO_ERROR;
483
484 case XA_PCM_CONFIG_PARAM_CHANROUTING:
485 /* ...accept any channel routing mask */
486 d->chan_routing = (u32)i_value;
487 return XA_NO_ERROR;
488
489 default:
490 /* ...unrecognized parameter */
491 return XF_CHK_ERR(0, XA_API_FATAL_INVALID_CMD_TYPE);
492 }
493 }
494
495 /* ...retrieve configuration parameter */
xa_pcm_get_config_param(XAPcmCodec * d,WORD32 i_idx,pVOID pv_value)496 static XA_ERRORCODE xa_pcm_get_config_param(XAPcmCodec *d, WORD32 i_idx, pVOID pv_value)
497 {
498 /* ...validity check */
499 XF_CHK_ERR(d && pv_value, XA_API_FATAL_INVALID_CMD_TYPE);
500
501 /* ...make sure pre-configuration is completed */
502 XF_CHK_ERR(d->state & XA_PCM_FLAG_PREINIT_DONE, XA_PCM_CONFIG_NONFATAL_STATE);
503
504 /* ...process individual parameter */
505 switch (i_idx)
506 {
507 case XA_CODEC_CONFIG_PARAM_SAMPLE_RATE:
508 case XA_PCM_CONFIG_PARAM_SAMPLE_RATE:
509 /* ...return output sampling frequency */
510 *(WORD32 *)pv_value = d->sample_rate;
511 return XA_NO_ERROR;
512
513 case XA_PCM_CONFIG_PARAM_IN_PCM_WIDTH:
514 /* ...return input sample bit-width */
515 *(WORD32 *)pv_value = d->in_pcm_width;
516 return XA_NO_ERROR;
517
518 case XA_PCM_CONFIG_PARAM_IN_CHANNELS:
519 /* ...return number of input channels */
520 *(WORD32 *)pv_value = d->in_channels;
521 return XA_NO_ERROR;
522
523 case XA_CODEC_CONFIG_PARAM_PCM_WIDTH:
524 case XA_PCM_CONFIG_PARAM_OUT_PCM_WIDTH:
525 /* ...return output sample bit-width */
526 *(WORD32 *)pv_value = d->out_pcm_width;
527 return XA_NO_ERROR;
528
529 case XA_CODEC_CONFIG_PARAM_CHANNELS:
530 case XA_PCM_CONFIG_PARAM_OUT_CHANNELS:
531 /* ...return number of output channels */
532 *(WORD32 *)pv_value = d->out_channels;
533 return XA_NO_ERROR;
534
535 case XA_PCM_CONFIG_PARAM_CHANROUTING:
536 /* ...return current channel routing mask */
537 *(WORD32 *)pv_value = d->chan_routing;
538 return XA_NO_ERROR;
539
540 default:
541 /* ...unrecognized parameter */
542 return XF_CHK_ERR(0, XA_API_FATAL_INVALID_CMD_TYPE);
543 }
544 }
545
546 /* ...execution command */
xa_pcm_execute(XAPcmCodec * d,WORD32 i_idx,pVOID pv_value)547 static XA_ERRORCODE xa_pcm_execute(XAPcmCodec *d, WORD32 i_idx, pVOID pv_value)
548 {
549 /* ...basic validity check */
550 XF_CHK_ERR(d, XA_API_FATAL_INVALID_CMD_TYPE);
551
552 /* ...codec must be in running state */
553 XF_CHK_ERR(d->state & XA_PCM_FLAG_RUNNING, XA_API_FATAL_INVALID_CMD_TYPE);
554
555 /* ...process individual command type */
556 switch (i_idx)
557 {
558 case XA_CMD_TYPE_DO_EXECUTE:
559 /* ...do data processing (tbd - result code is bad) */
560 if (d->insize != 0)
561 {
562 XF_CHK_ERR(!XA_ERROR_SEVERITY(d->process(d)), XA_PCM_EXEC_FATAL_STATE);
563 }
564
565 /* ...process end-of-stream condition */
566 (d->state & XA_PCM_FLAG_EOS ? d->state ^= XA_PCM_FLAG_EOS | XA_PCM_FLAG_COMPLETE : 0);
567
568 return XA_NO_ERROR;
569
570 case XA_CMD_TYPE_DONE_QUERY:
571 /* ...check if processing is complete */
572 XF_CHK_ERR(pv_value, XA_API_FATAL_INVALID_CMD_TYPE);
573
574 /* ...return completion status */
575 *(WORD32 *)pv_value = (d->state & XA_PCM_FLAG_COMPLETE ? 1 : 0);
576
577 return XA_NO_ERROR;
578
579 case XA_CMD_TYPE_DO_RUNTIME_INIT:
580 /* ...reset codec operation */
581 return xa_pcm_do_runtime_init(d);
582
583 default:
584 /* ...unrecognized command */
585 return XF_CHK_ERR(0, XA_API_FATAL_INVALID_CMD_TYPE);
586 }
587 }
588
589 /* ...set number of input bytes */
xa_pcm_set_input_bytes(XAPcmCodec * d,WORD32 i_idx,pVOID pv_value)590 static XA_ERRORCODE xa_pcm_set_input_bytes(XAPcmCodec *d, WORD32 i_idx, pVOID pv_value)
591 {
592 u32 in_stride = d->in_stride;
593 u32 insize;
594
595 /* ...validity check */
596 XF_CHK_ERR(d && pv_value, XA_API_FATAL_INVALID_CMD_TYPE);
597
598 /* ...track index must be valid */
599 XF_CHK_ERR(i_idx == 0, XA_API_FATAL_INVALID_CMD_TYPE);
600
601 /* ...component must be initialized */
602 XF_CHK_ERR(d->state & XA_PCM_FLAG_POSTINIT_DONE, XA_API_FATAL_INVALID_CMD_TYPE);
603
604 /* ...input buffer must exist */
605 XF_CHK_ERR(d->input, XA_API_FATAL_INVALID_CMD_TYPE);
606
607 /* ...convert bytes into samples (don't like division, but still...) */
608 insize = *(WORD32 *)pv_value / in_stride;
609
610 /* ...make sure we have integral amount of samples */
611 XF_CHK_ERR(*(WORD32 *)pv_value == insize * in_stride, XA_API_FATAL_INVALID_CMD_TYPE);
612
613 /* ...limit input buffer size to maximal value*/
614 d->insize = (insize > XA_PCM_MAX_SAMPLES ? XA_PCM_MAX_SAMPLES : insize);
615
616 return XA_NO_ERROR;
617 }
618
619 /* ...get number of output bytes produced */
xa_pcm_get_output_bytes(XAPcmCodec * d,WORD32 i_idx,pVOID pv_value)620 static XA_ERRORCODE xa_pcm_get_output_bytes(XAPcmCodec *d, WORD32 i_idx, pVOID pv_value)
621 {
622 /* ...validity check */
623 XF_CHK_ERR(d && pv_value, XA_API_FATAL_INVALID_CMD_TYPE);
624
625 /* ...buffer index must be valid */
626 XF_CHK_ERR(i_idx == 1, XA_API_FATAL_INVALID_CMD_TYPE);
627
628 /* ...component must be initialized */
629 XF_CHK_ERR(d->state & XA_PCM_FLAG_POSTINIT_DONE, XA_API_FATAL_INVALID_CMD_TYPE);
630
631 /* ...output buffer must exist */
632 XF_CHK_ERR(d->output, XA_API_FATAL_INVALID_CMD_TYPE);
633
634 /* ...return number of produced bytes (and reset instantly? - tbd) */
635 *(WORD32 *)pv_value = d->produced;
636
637 return XA_NO_ERROR;
638 }
639
640 /* ...get number of consumed bytes */
xa_pcm_get_curidx_input_buf(XAPcmCodec * d,WORD32 i_idx,pVOID pv_value)641 static XA_ERRORCODE xa_pcm_get_curidx_input_buf(XAPcmCodec *d, WORD32 i_idx, pVOID pv_value)
642 {
643 /* ...validity check */
644 XF_CHK_ERR(d && pv_value, XA_API_FATAL_INVALID_CMD_TYPE);
645
646 /* ...index must be valid */
647 XF_CHK_ERR(i_idx == 0, XA_API_FATAL_INVALID_CMD_TYPE);
648
649 /* ...input buffer must exist */
650 XF_CHK_ERR(d->input, XA_PCM_EXEC_NONFATAL_INPUT);
651
652 /* ...return number of bytes consumed */
653 *(WORD32 *)pv_value = d->consumed;
654
655 return XA_NO_ERROR;
656 }
657
658 /* ...end-of-stream processing */
xa_pcm_input_over(XAPcmCodec * d,WORD32 i_idx,pVOID pv_value)659 static XA_ERRORCODE xa_pcm_input_over(XAPcmCodec *d, WORD32 i_idx, pVOID pv_value)
660 {
661 /* ...validity check */
662 XF_CHK_ERR(d, XA_API_FATAL_INVALID_CMD_TYPE);
663
664 /* ...put end-of-stream flag */
665 d->state |= XA_PCM_FLAG_EOS;
666
667 TRACE(PROCESS, _b("Input-over-condition signalled"));
668
669 return XA_NO_ERROR;
670 }
671
672 /* ..get total amount of data for memory tables */
xa_pcm_get_memtabs_size(XAPcmCodec * d,WORD32 i_idx,pVOID pv_value)673 static XA_ERRORCODE xa_pcm_get_memtabs_size(XAPcmCodec *d, WORD32 i_idx, pVOID pv_value)
674 {
675 /* ...basic validity checks */
676 XF_CHK_ERR(d && pv_value, XA_API_FATAL_INVALID_CMD_TYPE);
677
678 /* ...check mixer is pre-initialized */
679 XF_CHK_ERR(d->state & XA_PCM_FLAG_PREINIT_DONE, XA_API_FATAL_INVALID_CMD_TYPE);
680
681 /* ...we have all our tables inside API structure */
682 *(WORD32 *)pv_value = 0;
683
684 return XA_NO_ERROR;
685 }
686
687 /* ...return total amount of memory buffers */
xa_pcm_get_n_memtabs(XAPcmCodec * d,WORD32 i_idx,pVOID pv_value)688 static XA_ERRORCODE xa_pcm_get_n_memtabs(XAPcmCodec *d, WORD32 i_idx, pVOID pv_value)
689 {
690 /* ...basic validity checks */
691 XF_CHK_ERR(d && pv_value, XA_API_FATAL_INVALID_CMD_TYPE);
692
693 /* ...we have 1 input buffer and 1 output buffer */
694 *(WORD32 *)pv_value = 1 + 1;
695
696 return XA_NO_ERROR;
697 }
698
699 /* ...return memory type data */
xa_pcm_get_mem_info_type(XAPcmCodec * d,WORD32 i_idx,pVOID pv_value)700 static XA_ERRORCODE xa_pcm_get_mem_info_type(XAPcmCodec *d, WORD32 i_idx, pVOID pv_value)
701 {
702 /* ...basic validity check */
703 XF_CHK_ERR(d && pv_value, XA_API_FATAL_INVALID_CMD_TYPE);
704
705 /* ...codec must be in post-init state */
706 XF_CHK_ERR(d->state & XA_PCM_FLAG_POSTINIT_DONE, XA_API_FATAL_INVALID_CMD_TYPE);
707
708 /* ...check buffer type */
709 switch (i_idx)
710 {
711 case 0:
712 *(WORD32 *)pv_value = XA_MEMTYPE_INPUT;
713 return XA_NO_ERROR;
714
715 case 1:
716 *(WORD32 *)pv_value = XA_MEMTYPE_OUTPUT;
717 return XA_NO_ERROR;
718
719 default:
720 return XF_CHK_ERR(0, XA_API_FATAL_INVALID_CMD_TYPE);
721 }
722 }
723
724 /* ...return memory buffer size */
xa_pcm_get_mem_info_size(XAPcmCodec * d,WORD32 i_idx,pVOID pv_value)725 static XA_ERRORCODE xa_pcm_get_mem_info_size(XAPcmCodec *d, WORD32 i_idx, pVOID pv_value)
726 {
727 /* ...basic validity check */
728 XF_CHK_ERR(d && pv_value, XA_API_FATAL_INVALID_CMD_TYPE);
729
730 /* ...codec must be in post-init state */
731 XF_CHK_ERR(d->state & XA_PCM_FLAG_POSTINIT_DONE, XA_API_FATAL_INVALID_CMD_TYPE);
732
733 /* ...determine particular buffer */
734 switch (i_idx)
735 {
736 case 0:
737 /* ...input buffer size can be any */
738 *(WORD32 *)pv_value = 0;
739 return XA_NO_ERROR;
740
741 case 1:
742 /* ...output buffer size is dependent on stride */
743 *(WORD32 *)pv_value = XA_PCM_MAX_SAMPLES * d->out_stride;
744 return XA_NO_ERROR;
745
746 default:
747 /* ...invalid buffer index */
748 return XF_CHK_ERR(0, XA_API_FATAL_INVALID_CMD_TYPE);
749 }
750 }
751
752 /* ...return memory alignment data */
xa_pcm_get_mem_info_alignment(XAPcmCodec * d,WORD32 i_idx,pVOID pv_value)753 static XA_ERRORCODE xa_pcm_get_mem_info_alignment(XAPcmCodec *d, WORD32 i_idx, pVOID pv_value)
754 {
755 /* ...basic validity check */
756 XF_CHK_ERR(d && pv_value, XA_API_FATAL_INVALID_CMD_TYPE);
757
758 /* ...codec must be in post-initialization state */
759 XF_CHK_ERR(d->state & XA_PCM_FLAG_POSTINIT_DONE, XA_API_FATAL_INVALID_CMD_TYPE);
760
761 /* ...all buffers are 4-bytes aligned */
762 *(WORD32 *)pv_value = 4;
763
764 return XA_NO_ERROR;
765 }
766
767 /* ...set memory pointer */
xa_pcm_set_mem_ptr(XAPcmCodec * d,WORD32 i_idx,pVOID pv_value)768 static XA_ERRORCODE xa_pcm_set_mem_ptr(XAPcmCodec *d, WORD32 i_idx, pVOID pv_value)
769 {
770 /* ...basic validity check */
771 XF_CHK_ERR(d, XA_API_FATAL_INVALID_CMD_TYPE);
772 XF_CHK_ERR(pv_value, XA_API_FATAL_INVALID_CMD_TYPE);
773
774 /* ...codec must be in post-initialized state */
775 XF_CHK_ERR(d->state & XA_PCM_FLAG_POSTINIT_DONE, XA_API_FATAL_INVALID_CMD_TYPE);
776
777 /* ...select memory buffer */
778 switch (i_idx)
779 {
780 case 0:
781 /* ...input buffer */
782 d->input = pv_value;
783 return XA_NO_ERROR;
784
785 case 1:
786 /* ...output buffer */
787 d->output = pv_value;
788 return XA_NO_ERROR;
789
790 default:
791 /* ...invalid index */
792 return XF_CHK_ERR(0, XA_API_FATAL_INVALID_CMD_TYPE);
793 }
794 }
795
796 /*******************************************************************************
797 * API command hooks
798 ******************************************************************************/
799
800 static XA_ERRORCODE (* const xa_pcm_api[])(XAPcmCodec *, WORD32, pVOID) =
801 {
802 [XA_API_CMD_GET_API_SIZE] = xa_pcm_get_api_size,
803
804 [XA_API_CMD_INIT] = xa_pcm_init,
805 [XA_API_CMD_SET_CONFIG_PARAM] = xa_pcm_set_config_param,
806 [XA_API_CMD_GET_CONFIG_PARAM] = xa_pcm_get_config_param,
807
808 [XA_API_CMD_EXECUTE] = xa_pcm_execute,
809 [XA_API_CMD_SET_INPUT_BYTES] = xa_pcm_set_input_bytes,
810 [XA_API_CMD_GET_OUTPUT_BYTES] = xa_pcm_get_output_bytes,
811 [XA_API_CMD_GET_CURIDX_INPUT_BUF] = xa_pcm_get_curidx_input_buf,
812 [XA_API_CMD_INPUT_OVER] = xa_pcm_input_over,
813
814 [XA_API_CMD_GET_MEMTABS_SIZE] = xa_pcm_get_memtabs_size,
815 [XA_API_CMD_GET_N_MEMTABS] = xa_pcm_get_n_memtabs,
816 [XA_API_CMD_GET_MEM_INFO_TYPE] = xa_pcm_get_mem_info_type,
817 [XA_API_CMD_GET_MEM_INFO_SIZE] = xa_pcm_get_mem_info_size,
818 [XA_API_CMD_GET_MEM_INFO_ALIGNMENT] = xa_pcm_get_mem_info_alignment,
819 [XA_API_CMD_SET_MEM_PTR] = xa_pcm_set_mem_ptr,
820 };
821
822 /* ...total numer of commands supported */
823 #define XA_PCM_API_COMMANDS_NUM (sizeof(xa_pcm_api) / sizeof(xa_pcm_api[0]))
824
825 /*******************************************************************************
826 * API entry point
827 ******************************************************************************/
828
xa_pcm_codec(xa_codec_handle_t p_xa_module_obj,WORD32 i_cmd,WORD32 i_idx,pVOID pv_value)829 XA_ERRORCODE xa_pcm_codec(xa_codec_handle_t p_xa_module_obj, WORD32 i_cmd, WORD32 i_idx, pVOID pv_value)
830 {
831 XAPcmCodec *d = (XAPcmCodec *) p_xa_module_obj;
832
833 /* ...check if command index is valid */
834 XF_CHK_ERR(i_cmd < XA_PCM_API_COMMANDS_NUM, XA_API_FATAL_INVALID_CMD);
835
836 /* ...see if command is defined */
837 XF_CHK_ERR(xa_pcm_api[i_cmd], XA_API_FATAL_INVALID_CMD);
838
839 /* ...execute requested command */
840 return xa_pcm_api[i_cmd](d, i_idx, pv_value);
841 }
842