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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 365 static XA_ERRORCODE xa_pcm_init(XAPcmCodec *d, WORD32 i_idx, pVOID pv_value) 366 { 367 /* ...sanity 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 */ 436 static XA_ERRORCODE xa_pcm_set_config_param(XAPcmCodec *d, WORD32 i_idx, pVOID pv_value) 437 { 438 WORD32 i_value; 439 440 /* ...sanity 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 */ 496 static XA_ERRORCODE xa_pcm_get_config_param(XAPcmCodec *d, WORD32 i_idx, pVOID pv_value) 497 { 498 /* ...sanity 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 */ 547 static XA_ERRORCODE xa_pcm_execute(XAPcmCodec *d, WORD32 i_idx, pVOID pv_value) 548 { 549 /* ...basic sanity 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 */ 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 /* ...sanity 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 */ 620 static XA_ERRORCODE xa_pcm_get_output_bytes(XAPcmCodec *d, WORD32 i_idx, pVOID pv_value) 621 { 622 /* ...sanity check */ 623 XF_CHK_ERR(d && pv_value, XA_API_FATAL_INVALID_CMD_TYPE); 624 625 /* ...buffer index must be sane */ 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 */ 641 static XA_ERRORCODE xa_pcm_get_curidx_input_buf(XAPcmCodec *d, WORD32 i_idx, pVOID pv_value) 642 { 643 /* ...sanity 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 */ 659 static XA_ERRORCODE xa_pcm_input_over(XAPcmCodec *d, WORD32 i_idx, pVOID pv_value) 660 { 661 /* ...sanity 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 */ 673 static XA_ERRORCODE xa_pcm_get_memtabs_size(XAPcmCodec *d, WORD32 i_idx, pVOID pv_value) 674 { 675 /* ...basic sanity 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 */ 688 static XA_ERRORCODE xa_pcm_get_n_memtabs(XAPcmCodec *d, WORD32 i_idx, pVOID pv_value) 689 { 690 /* ...basic sanity 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 */ 700 static XA_ERRORCODE xa_pcm_get_mem_info_type(XAPcmCodec *d, WORD32 i_idx, pVOID pv_value) 701 { 702 /* ...basic sanity 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 */ 725 static XA_ERRORCODE xa_pcm_get_mem_info_size(XAPcmCodec *d, WORD32 i_idx, pVOID pv_value) 726 { 727 /* ...basic sanity 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 */ 753 static XA_ERRORCODE xa_pcm_get_mem_info_alignment(XAPcmCodec *d, WORD32 i_idx, pVOID pv_value) 754 { 755 /* ...basic sanity 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 */ 768 static XA_ERRORCODE xa_pcm_set_mem_ptr(XAPcmCodec *d, WORD32 i_idx, pVOID pv_value) 769 { 770 /* ...basic sanity 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 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 sane */ 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