Home | History | Annotate | Download | only in pcm_proc
      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