diff options
Diffstat (limited to 'hifi/xaf/hifi-dpf/audio')
-rw-r--r-- | hifi/xaf/hifi-dpf/audio/xa-class-audio-codec.c | 785 | ||||
-rw-r--r-- | hifi/xaf/hifi-dpf/audio/xa-class-base.c | 537 | ||||
-rw-r--r-- | hifi/xaf/hifi-dpf/audio/xa-class-base.h | 263 | ||||
-rw-r--r-- | hifi/xaf/hifi-dpf/audio/xa-class-mixer.c | 870 |
4 files changed, 0 insertions, 2455 deletions
diff --git a/hifi/xaf/hifi-dpf/audio/xa-class-audio-codec.c b/hifi/xaf/hifi-dpf/audio/xa-class-audio-codec.c deleted file mode 100644 index 3806548f..00000000 --- a/hifi/xaf/hifi-dpf/audio/xa-class-audio-codec.c +++ /dev/null @@ -1,785 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2018 Cadence Design Systems, Inc. -* -* Permission is hereby granted, free of charge, to any person obtaining -* a copy of this software and associated documentation files (the -* "Software"), to use this Software with Cadence processor cores only and -* not with any other processors and platforms, subject to -* the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -******************************************************************************/ - -/******************************************************************************* - * xa-class-audio-codec.c - * - * Generic audio codec task implementation - * - ******************************************************************************/ - -#define MODULE_TAG CODEC - -/******************************************************************************* - * Includes - ******************************************************************************/ - -#include "xf.h" -#include "xa-class-base.h" -#include "audio/xa-audio-decoder-api.h" - -/******************************************************************************* - * Tracing configuration - ******************************************************************************/ - -TRACE_TAG(INIT, 1); -TRACE_TAG(WARNING, 1); -TRACE_TAG(INFO, 1); -TRACE_TAG(INPUT, 1); -TRACE_TAG(OUTPUT, 1); -TRACE_TAG(DECODE, 1); - -/******************************************************************************* - * Internal functions definitions - ******************************************************************************/ - -typedef struct XAAudioCodec -{ - /*************************************************************************** - * Control data - **************************************************************************/ - - /* ...generic audio codec data */ - XACodecBase base; - - /* ...input port data */ - xf_input_port_t input; - - /* ...output port data */ - xf_output_port_t output; - - /* ...input port index */ - WORD32 in_idx; - - /* ...output port index */ - WORD32 out_idx; - - /*************************************************************************** - * Run-time configuration parameters - **************************************************************************/ - - /* ...sample size in bytes */ - u32 sample_size; - - /* ...audio sample duration */ - u32 factor; - - /* ...total number of produced audio frames since last reset */ - u32 produced; - -} XAAudioCodec; - -/******************************************************************************* - * Auxiliary codec execution flags - ******************************************************************************/ - -/* ...input port setup condition */ -#define XA_CODEC_FLAG_INPUT_SETUP __XA_BASE_FLAG(1 << 0) - -/* ...output port setup condition */ -#define XA_CODEC_FLAG_OUTPUT_SETUP __XA_BASE_FLAG(1 << 1) - -/******************************************************************************* - * Data processing scheduling - ******************************************************************************/ - -/* ...prepare codec for steady operation (tbd - don't absolutely like it) */ -static inline XA_ERRORCODE xa_codec_prepare_runtime(XAAudioCodec *codec) -{ - XACodecBase *base = (XACodecBase *)codec; - xf_message_t *m = xf_msg_queue_head(&codec->output.queue); - xf_start_msg_t *msg = m->buffer; - u32 frame_size; - u32 factor; - - /* ...fill-in buffer parameters */ - XA_API(base, XA_API_CMD_GET_CONFIG_PARAM, XA_CODEC_CONFIG_PARAM_SAMPLE_RATE, &msg->sample_rate); - XA_API(base, XA_API_CMD_GET_CONFIG_PARAM, XA_CODEC_CONFIG_PARAM_CHANNELS, &msg->channels); - XA_API(base, XA_API_CMD_GET_CONFIG_PARAM, XA_CODEC_CONFIG_PARAM_PCM_WIDTH, &msg->pcm_width); - XA_API(base, XA_API_CMD_GET_MEM_INFO_SIZE, codec->in_idx, &msg->input_length); - XA_API(base, XA_API_CMD_GET_MEM_INFO_SIZE, codec->out_idx, &msg->output_length); - - TRACE(INIT, _b("codec[%p]::runtime init: f=%u, c=%u, w=%u, i=%u, o=%u"), codec, msg->sample_rate, msg->channels, msg->pcm_width, msg->input_length, msg->output_length); - - /* ...reallocate input port buffer as needed - tbd */ - BUG(msg->input_length > codec->input.length, _x("Input buffer reallocation required: %u to %u"), codec->input.length, msg->input_length); - - /* ...save sample size in bytes */ - codec->sample_size = msg->channels * (msg->pcm_width == 16 ? 2 : 4); - - /* ...calculate frame duration; get number of samples in the frame (don't like division here - tbd) */ - frame_size = msg->output_length / codec->sample_size; - - /* ...it must be a multiple */ - XF_CHK_ERR(frame_size * codec->sample_size == msg->output_length, XA_API_FATAL_INVALID_CMD_TYPE); - - /* ...retrieve upsampling factor for given sample rate */ - XF_CHK_ERR(factor = xf_timebase_factor(msg->sample_rate), XA_API_FATAL_INVALID_CMD_TYPE); - - /* ...set frame duration factor (converts number of bytes into timebase units) */ - codec->factor = factor / codec->sample_size; - - TRACE(INIT, _b("ts-factor: %u (%u)"), codec->factor, factor); - - BUG(codec->factor * codec->sample_size != factor, _x("Freq mismatch: %u vs %u"), codec->factor * codec->sample_size, factor); - - /* ...pass response to caller (push out of output port) */ - xf_output_port_produce(&codec->output, sizeof(*msg)); - - /* ...codec runtime initialization is completed */ - TRACE(INIT, _b("codec[%p] runtime initialized: i=%u, o=%u"), codec, msg->input_length, msg->output_length); - - return XA_NO_ERROR; -} - -/******************************************************************************* - * Commands processing - ******************************************************************************/ - -/* ...EMPTY-THIS-BUFFER command processing */ -static XA_ERRORCODE xa_codec_empty_this_buffer(XACodecBase *base, xf_message_t *m) -{ - XAAudioCodec *codec = (XAAudioCodec *) base; - - /* ...make sure the port is sane */ - XF_CHK_ERR(XF_MSG_DST_PORT(m->id) == 0, XA_API_FATAL_INVALID_CMD); - - /* ...command is allowed only in post-init state */ - XF_CHK_ERR(base->state & XA_BASE_FLAG_POSTINIT, XA_API_FATAL_INVALID_CMD); - - /* ...put message into input queue */ - if (xf_input_port_put(&codec->input, m)) - { - /* ...restart stream if it is in completed state */ - if (base->state & XA_BASE_FLAG_COMPLETED) - { - /* ...reset execution stage */ - base->state = XA_BASE_FLAG_POSTINIT | XA_BASE_FLAG_EXECUTION; - - /* ...reset execution runtime */ - XA_API(base, XA_API_CMD_EXECUTE, XA_CMD_TYPE_DO_RUNTIME_INIT, NULL); - - /* ...reset produced samples counter */ - codec->produced = 0; - } - - /* ...codec must be in one of these states */ - XF_CHK_ERR(base->state & (XA_BASE_FLAG_RUNTIME_INIT | XA_BASE_FLAG_EXECUTION), XA_API_FATAL_INVALID_CMD); - - /* ...schedule data processing if output is ready */ - if (xf_output_port_ready(&codec->output)) - { - xa_base_schedule(base, 0); - } - } - - TRACE(INPUT, _b("Received buffer [%p]:%u"), m->buffer, m->length); - - return XA_NO_ERROR; -} - -/* ...FILL-THIS-BUFFER command processing */ -static XA_ERRORCODE xa_codec_fill_this_buffer(XACodecBase *base, xf_message_t *m) -{ - XAAudioCodec *codec = (XAAudioCodec *) base; - - /* ...make sure the port is sane */ - XF_CHK_ERR(XF_MSG_DST_PORT(m->id) == 1, XA_API_FATAL_INVALID_CMD); - - /* ...command is allowed only in postinit state */ - XF_CHK_ERR(base->state & XA_BASE_FLAG_POSTINIT, XA_API_FATAL_INVALID_CMD); - - /* ...special handling of zero-length buffer */ - if (base->state & XA_BASE_FLAG_RUNTIME_INIT) - { - /* ...message must be zero-length */ - BUG(m->length != 0, _x("Invalid message length: %u"), m->length); - } - else if (m == xf_output_port_control_msg(&codec->output)) - { - /* ...end-of-stream processing indication received; check the state */ - BUG((base->state & XA_BASE_FLAG_COMPLETED) == 0, _x("invalid state: %x"), base->state); - - /* ... mark flushing sequence is done */ - xf_output_port_flush_done(&codec->output); - - /* ...complete pending zero-length input buffer */ - xf_input_port_purge(&codec->input); - - TRACE(INFO, _b("codec[%p] playback completed"), codec); - - /* ...playback is over */ - return XA_NO_ERROR; - } - else if ((base->state & XA_BASE_FLAG_COMPLETED) && !xf_output_port_routed(&codec->output)) - { - /* ...return message arrived from application immediately */ - xf_response_ok(m); - - return XA_NO_ERROR; - } - else - { - TRACE(OUTPUT, _b("Received output buffer [%p]:%u"), m->buffer, m->length); - - /* ...adjust message length (may be shorter than original) */ - m->length = codec->output.length; - } - - /* ...place message into output port */ - if (xf_output_port_put(&codec->output, m) && xf_input_port_ready(&codec->input)) - { - /* ...schedule data processing instantly */ - if (base->state & (XA_BASE_FLAG_RUNTIME_INIT | XA_BASE_FLAG_EXECUTION)) - { - xa_base_schedule(base, 0); - } - } - - return XA_NO_ERROR; -} - -/* ...output port routing */ -static XA_ERRORCODE xa_codec_port_route(XACodecBase *base, xf_message_t *m) -{ - XAAudioCodec *codec = (XAAudioCodec *) base; - xf_route_port_msg_t *cmd = m->buffer; - xf_output_port_t *port = &codec->output; - u32 src = XF_MSG_DST(m->id); - u32 dst = cmd->dst; - - /* ...command is allowed only in "postinit" state */ - XF_CHK_ERR(base->state & XA_BASE_FLAG_POSTINIT, XA_API_FATAL_INVALID_CMD); - - /* ...make sure output port is addressed */ - XF_CHK_ERR(XF_MSG_DST_PORT(m->id) == 1, XA_API_FATAL_INVALID_CMD_TYPE); - - /* ...make sure port is not routed yet */ - XF_CHK_ERR(!xf_output_port_routed(port), XA_API_FATAL_INVALID_CMD_TYPE); - - /* ...route output port - allocate queue */ - XF_CHK_ERR(xf_output_port_route(port, __XF_MSG_ID(dst, src), cmd->alloc_number, cmd->alloc_size, cmd->alloc_align) == 0, XA_API_FATAL_MEM_ALLOC); - - /* ...schedule processing instantly */ - xa_base_schedule(base, 0); - - /* ...pass success result to caller */ - xf_response_ok(m); - - return XA_NO_ERROR; -} - -/* ...port unroute command */ -static XA_ERRORCODE xa_codec_port_unroute(XACodecBase *base, xf_message_t *m) -{ - XAAudioCodec *codec = (XAAudioCodec *) base; - - /* ...command is allowed only in "postinit" state */ - XF_CHK_ERR(base->state & XA_BASE_FLAG_POSTINIT, XA_API_FATAL_INVALID_CMD); - - /* ...make sure output port is addressed */ - XF_CHK_ERR(XF_MSG_DST_PORT(m->id) == 1, XA_API_FATAL_INVALID_CMD_TYPE); - - /* ...cancel any pending processing */ - xa_base_cancel(base); - - /* ...clear output-port-setup condition */ - base->state &= ~XA_CODEC_FLAG_OUTPUT_SETUP; - - /* ...pass flush command down the graph */ - if (xf_output_port_flush(&codec->output, XF_FLUSH)) - { - TRACE(INFO, _b("port is idle; instantly unroute")); - - /* ...flushing sequence is not needed; command may be satisfied instantly */ - xf_output_port_unroute(&codec->output); - - /* ...pass response to the proxy */ - xf_response_ok(m); - } - else - { - TRACE(INFO, _b("port is busy; propagate unroute command")); - - /* ...flushing sequence is started; save flow-control message */ - xf_output_port_unroute_start(&codec->output, m); - } - - return XA_NO_ERROR; -} - -/* ...FLUSH command processing */ -static XA_ERRORCODE xa_codec_flush(XACodecBase *base, xf_message_t *m) -{ - XAAudioCodec *codec = (XAAudioCodec *) base; - - /* ...command is allowed only in "postinit" state */ - XF_CHK_ERR(base->state & XA_BASE_FLAG_POSTINIT, XA_API_FATAL_INVALID_CMD); - - /* ...ensure input parameter length is zero */ - XF_CHK_ERR(m->length == 0, XA_API_FATAL_INVALID_CMD_TYPE); - - TRACE(1, _b("flush command received")); - - /* ...flush command must be addressed to input port */ - if (XF_MSG_DST_PORT(m->id) == 0) - { - /* ...cancel data processing message if needed */ - xa_base_cancel(base); - - /* ...input port flushing; purge content of input buffer */ - xf_input_port_purge(&codec->input); - - /* ...clear input-ready condition */ - base->state &= ~XA_CODEC_FLAG_INPUT_SETUP; - - /* ...reset execution runtime */ - XA_API(base, XA_API_CMD_EXECUTE, XA_CMD_TYPE_DO_RUNTIME_INIT, NULL); - - /* ...reset produced samples counter */ - codec->produced = 0; - - /* ...propagate flushing command to output port */ - if (xf_output_port_flush(&codec->output, XF_FLUSH)) - { - /* ...flushing sequence is not needed; satisfy command instantly */ - xf_response(m); - } - else - { - /* ...flushing sequence is started; save flow-control message at input port */ - xf_input_port_control_save(&codec->input, m); - } - } - else if (xf_output_port_unrouting(&codec->output)) - { - /* ...flushing during port unrouting; complete unroute sequence */ - xf_output_port_unroute_done(&codec->output); - - TRACE(INFO, _b("port is unrouted")); - } - else - { - /* ...output port flush command/response; check if the port is routed */ - if (!xf_output_port_routed(&codec->output)) - { - /* ...complete all queued messages */ - xf_output_port_flush(&codec->output, XF_FLUSH); - - /* ...and pass response to flushing command */ - xf_response(m); - } - else - { - /* ...response to flushing command received */ - BUG(m != xf_output_port_control_msg(&codec->output), _x("invalid message: %p"), m); - - /* ...mark flushing sequence is completed */ - xf_output_port_flush_done(&codec->output); - - /* ...complete original flow-control command */ - xf_input_port_purge_done(&codec->input); - } - - /* ...clear output-setup condition */ - base->state &= ~XA_CODEC_FLAG_OUTPUT_SETUP; - } - - return XA_NO_ERROR; -} - -/******************************************************************************* - * Generic codec API - ******************************************************************************/ - -/* ...memory buffer handling */ -static XA_ERRORCODE xa_codec_memtab(XACodecBase *base, WORD32 idx, WORD32 type, WORD32 size, WORD32 align, u32 core) -{ - XAAudioCodec *codec = (XAAudioCodec *) base; - - if (type == XA_MEMTYPE_INPUT) - { - /* ...input port specification; allocate internal buffer */ - XF_CHK_ERR(xf_input_port_init(&codec->input, size, align, core) == 0, XA_API_FATAL_MEM_ALLOC); - - /* ...save input port index */ - codec->in_idx = idx; - - /* ...set input buffer pointer as needed */ - (size ? XA_API(base, XA_API_CMD_SET_MEM_PTR, idx, codec->input.buffer) : 0); - - (size ? TRACE(1, _x("set input ptr: %p"), codec->input.buffer) : 0); - } - else - { - /* ...output buffer specification */ - XF_CHK_ERR(type == XA_MEMTYPE_OUTPUT, XA_API_FATAL_INVALID_CMD_TYPE); - - /* ...initialize output port queue (no allocation here yet) */ - XF_CHK_ERR(xf_output_port_init(&codec->output, size) == 0, XA_API_FATAL_MEM_ALLOC); - - /* ...save output port index */ - codec->out_idx = idx; - } - - return XA_NO_ERROR; -} - -/* ...prepare input/output buffers */ -static XA_ERRORCODE xa_codec_preprocess(XACodecBase *base) -{ - XAAudioCodec *codec = (XAAudioCodec *) base; - - /* ...prepare output buffer if needed */ - if (!(base->state & XA_CODEC_FLAG_OUTPUT_SETUP)) - { - void *output; - - /* ...get output buffer from port, if possible */ - if (base->state & XA_BASE_FLAG_RUNTIME_INIT) - { - /* ...run-time is not initialized yet; use scratch buffer */ - output = base->scratch; - } - else if ((output = xf_output_port_data(&codec->output)) == NULL) - { - /* ...no output buffer available */ - return XA_CODEC_EXEC_NO_DATA; - } - - /* ...set the output buffer pointer */ - XA_API(base, XA_API_CMD_SET_MEM_PTR, codec->out_idx, output); - - TRACE(1, _x("set output ptr: %p"), output); - - /* ...mark output port is setup */ - base->state ^= XA_CODEC_FLAG_OUTPUT_SETUP; - } - - /* ...prepare input data if needed */ - if (!(base->state & XA_CODEC_FLAG_INPUT_SETUP)) - { - void *input; - u32 filled; - - /* ...fill input buffer */ - if (xf_input_port_bypass(&codec->input)) - { - /* ...use input buffer directly; check if there is data available */ - if ((input = xf_input_port_data(&codec->input)) != NULL) - { - /* ...set input data buffer pointer */ - XA_API(base, XA_API_CMD_SET_MEM_PTR, codec->in_idx, input); - - /* ...retrieve number of input bytes */ - filled = xf_input_port_length(&codec->input); - } - else if (!xf_input_port_done(&codec->input)) - { - /* ...return non-fatal indication to prevent further processing */ - return XA_CODEC_EXEC_NO_DATA; - } - else - { - /* ...mark we have no data in current buffer */ - filled = 0; - } - } - else - { - /* ...port is in non-bypass mode; try to fill internal buffer */ - if (xf_input_port_done(&codec->input) || xf_input_port_fill(&codec->input)) - { - /* ...retrieve number of bytes in input buffer (not really - tbd) */ - filled = xf_input_port_level(&codec->input); - } - else - { - /* ...return non-fatal indication to prevent further processing */ - return XA_CODEC_EXEC_NO_DATA; - } - } - - /* ...check if input stream is over */ - if (xf_input_port_done(&codec->input)) - { - /* ...pass input-over command to the codec to indicate the final buffer */ - XA_API(base, XA_API_CMD_INPUT_OVER, codec->in_idx, NULL); - - TRACE(INFO, _b("codec[%p]: signal input-over (filled: %u)"), codec, filled); - } - - TRACE(INPUT, _b("input-buffer fill-level: %u bytes"), filled); - - /* ...specify number of bytes available in the input buffer */ - XA_API(base, XA_API_CMD_SET_INPUT_BYTES, codec->in_idx, &filled); - - /* ...mark input port is setup */ - base->state ^= XA_CODEC_FLAG_INPUT_SETUP; - } - - return XA_NO_ERROR; -} - -/* ...post-processing operation; input/output ports maintenance */ -static XA_ERRORCODE xa_codec_postprocess(XACodecBase *base, int done) -{ - XAAudioCodec *codec = (XAAudioCodec *) base; - WORD32 consumed = 0; - WORD32 produced = 0; - - /* ...get number of consumed / produced bytes */ - XA_API(base, XA_API_CMD_GET_CURIDX_INPUT_BUF, codec->in_idx, &consumed); - - /* ...get number of produced bytes only if runtime is initialized (sample size is known) */ - (codec->sample_size ? XA_API(base, XA_API_CMD_GET_OUTPUT_BYTES, codec->out_idx, &produced) : 0); - - TRACE(DECODE, _b("codec[%p]::postprocess(c=%u, p=%u, d=%u)"), codec, consumed, produced, done); - - /* ...input buffer maintenance; check if we consumed anything */ - if (consumed) - { - /* ...consume specified number of bytes from input port */ - xf_input_port_consume(&codec->input, consumed); - - /* ...clear input-setup flag */ - base->state ^= XA_CODEC_FLAG_INPUT_SETUP; - } - - /* ...output buffer maintenance; check if we have produced anything */ - if (produced) - { - /* ...increment total number of produced samples (really don't like division here - tbd) */ - codec->produced += produced / codec->sample_size; - - /* ...immediately complete output buffer (don't wait until it gets filled) */ - xf_output_port_produce(&codec->output, produced); - - /* ...clear output port setup flag */ - base->state ^= XA_CODEC_FLAG_OUTPUT_SETUP; - } - - /* ...process execution stage transition */ - if (done) - { - if (base->state & XA_BASE_FLAG_RUNTIME_INIT) - { - /* ...stream is completed while codec is in runtime initialization stage */ - BUG(1, _x("breakpoint")); - } - else if (base->state & XA_BASE_FLAG_EXECUTION) - { - /* ...runtime initialization done */ - XA_CHK(xa_codec_prepare_runtime(codec)); - - /* ...clear output port setup flag as we were using scratch buffer; - * technically, no need to repeat setup of input buffer, but some codecs require - * it as well - */ - base->state &= ~(XA_CODEC_FLAG_INPUT_SETUP | XA_CODEC_FLAG_OUTPUT_SETUP); - } - else - { - /* ...output stream is over; propagate condition to sink port */ - if (xf_output_port_flush(&codec->output, XF_FILL_THIS_BUFFER)) - { - /* ...flushing sequence is not needed; complete pending zero-length input */ - xf_input_port_purge(&codec->input); - - /* ...no propagation to output port */ - TRACE(INFO, _b("codec[%p] playback completed"), codec); - } - else - { - /* ...flushing sequence is started; wait until flow-control message returns */ - TRACE(INFO, _b("propagate end-of-stream condition")); - } - } - - /* ...return early to prevent task rescheduling */ - return XA_NO_ERROR; - } - - /* ...reschedule processing if needed */ - if (xf_input_port_ready(&codec->input) && xf_output_port_ready(&codec->output)) - { - /* ...schedule data processing with respect to its urgency */ - xa_base_schedule(base, produced * codec->factor); - } - - return XA_NO_ERROR; -} - -/* ...configuration parameter retrieval */ -static XA_ERRORCODE xa_codec_getparam(XACodecBase *base, WORD32 id, pVOID value) -{ - XAAudioCodec *codec = (XAAudioCodec *) base; - - if (id == XA_CODEC_CONFIG_PARAM_PRODUCED) - { - /* ...retrieve number of produced samples since last reset */ - *(u32 *)value = codec->produced; - - return XA_NO_ERROR; - } - else - { - /* ...pass command to underlying codec plugin */ - return XA_API(base, XA_API_CMD_GET_CONFIG_PARAM, id, value); - } -} - -/******************************************************************************* - * Component entry point - ******************************************************************************/ - -/* ...command hooks */ -static XA_ERRORCODE (* const xa_codec_cmd[])(XACodecBase *, xf_message_t *) = -{ - [XF_OPCODE_TYPE(XF_SET_PARAM)] = xa_base_set_param, - [XF_OPCODE_TYPE(XF_GET_PARAM)] = xa_base_get_param, - [XF_OPCODE_TYPE(XF_ROUTE)] = xa_codec_port_route, - [XF_OPCODE_TYPE(XF_UNROUTE)] = xa_codec_port_unroute, - [XF_OPCODE_TYPE(XF_EMPTY_THIS_BUFFER)] = xa_codec_empty_this_buffer, - [XF_OPCODE_TYPE(XF_FILL_THIS_BUFFER)] = xa_codec_fill_this_buffer, - [XF_OPCODE_TYPE(XF_FLUSH)] = xa_codec_flush, - [XF_OPCODE_TYPE(XF_SET_PARAM_EXT)] = xa_base_set_param_ext, - [XF_OPCODE_TYPE(XF_GET_PARAM_EXT)] = xa_base_get_param_ext, -}; - -/* ...total number of commands supported */ -#define XA_CODEC_CMD_NUM (sizeof(xa_codec_cmd) / sizeof(xa_codec_cmd[0])) - -/* ...command processor for termination state (only for routed port case) */ -static int xa_audio_codec_terminate(xf_component_t *component, xf_message_t *m) -{ - XAAudioCodec *codec = (XAAudioCodec *) component; - u32 opcode = m->opcode; - - /* ...check if we received output port control message */ - if (m == xf_output_port_control_msg(&codec->output)) - { - /* ...output port flushing complete; mark port is idle and terminate */ - xf_output_port_flush_done(&codec->output); - return -1; - } - else if (opcode == XF_FILL_THIS_BUFFER) - { - /* ...output buffer returned by the sink component; ignore and keep waiting */ - TRACE(OUTPUT, _b("collect output buffer")); - return 0; - } - else if (opcode == XF_UNREGISTER) - { - /* ...ignore subsequent unregister command/response - tbd */ - return 0; - } - else - { - /* ...everything else is responded with generic failure */ - xf_response_err(m); - return 0; - } -} - -/* ...audio codec destructor */ -static int xa_audio_codec_destroy(xf_component_t *component, xf_message_t *m) -{ - XAAudioCodec *codec = (XAAudioCodec *) component; - u32 core = xf_component_core(component); - - /* ...destroy input port */ - xf_input_port_destroy(&codec->input, core); - - /* ...destroy output port */ - xf_output_port_destroy(&codec->output, core); - - /* ...deallocate all resources */ - xa_base_destroy(&codec->base, XF_MM(sizeof(*codec)), core); - - TRACE(INIT, _b("audio-codec[%p@%u] destroyed"), codec, core); - - /* ...indicate the client has been destroyed */ - return 0; -} - -/* ...audio codec destructor - first stage (ports unrouting) */ -static int xa_audio_codec_cleanup(xf_component_t *component, xf_message_t *m) -{ - XAAudioCodec *codec = (XAAudioCodec *) component; - - /* ...complete message with error response */ - xf_response_err(m); - - /* ...cancel internal scheduling message if needed */ - xa_base_cancel(&codec->base); - - /* ...purge input port (returns OK? pretty strange at this point - tbd) */ - xf_input_port_purge(&codec->input); - - /* ...propagate unregister command to connected component */ - if (xf_output_port_flush(&codec->output, XF_FLUSH)) - { - /* ...flushing sequence is not needed; destroy audio codec */ - return xa_audio_codec_destroy(component, NULL); - } - else - { - /* ...wait until output port is cleaned; adjust component hooks */ - component->entry = xa_audio_codec_terminate; - component->exit = xa_audio_codec_destroy; - - TRACE(INIT, _b("codec[%p] cleanup sequence started"), codec); - - /* ...indicate that second stage is required */ - return 1; - } -} - -/******************************************************************************* - * Audio codec component factory - ******************************************************************************/ - -xf_component_t * xa_audio_codec_factory(u32 core, xa_codec_func_t process) -{ - XAAudioCodec *codec; - - /* ...allocate local memory for codec structure */ - XF_CHK_ERR(codec = (XAAudioCodec *) xa_base_factory(core, XF_MM(sizeof(*codec)), process), NULL); - - /* ...set base codec API methods */ - codec->base.memtab = xa_codec_memtab; - codec->base.preprocess = xa_codec_preprocess; - codec->base.postprocess = xa_codec_postprocess; - codec->base.getparam = xa_codec_getparam; - - /* ...set message commands processing table */ - codec->base.command = xa_codec_cmd; - codec->base.command_num = XA_CODEC_CMD_NUM; - - /* ...set component destructor hook */ - codec->base.component.exit = xa_audio_codec_cleanup; - - TRACE(INIT, _b("Codec[%p] initialized"), codec); - - return (xf_component_t *) codec; -} diff --git a/hifi/xaf/hifi-dpf/audio/xa-class-base.c b/hifi/xaf/hifi-dpf/audio/xa-class-base.c deleted file mode 100644 index 0b672553..00000000 --- a/hifi/xaf/hifi-dpf/audio/xa-class-base.c +++ /dev/null @@ -1,537 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2018 Cadence Design Systems, Inc. -* -* Permission is hereby granted, free of charge, to any person obtaining -* a copy of this software and associated documentation files (the -* "Software"), to use this Software with Cadence processor cores only and -* not with any other processors and platforms, subject to -* the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -******************************************************************************/ - -/******************************************************************************* - * xa-class-base.c - * - * Generic audio codec task implementation - * - ******************************************************************************/ - -#define MODULE_TAG BASE - -/******************************************************************************* - * Includes - ******************************************************************************/ - -#include "xf.h" -#include "xa-class-base.h" - -/******************************************************************************* - * Tracing configuration - ******************************************************************************/ - -TRACE_TAG(INIT, 1); -TRACE_TAG(WARNING, 1); -TRACE_TAG(SETUP, 1); -TRACE_TAG(EXEC, 1); - -/******************************************************************************* - * Internal functions definitions - ******************************************************************************/ - -/* ...codec pre-initialization */ -static XA_ERRORCODE xa_base_preinit(XACodecBase *base, u32 core) -{ - WORD32 n; - - /* ...codec must be empty */ - XF_CHK_ERR(base->state == 0, XA_API_FATAL_INVALID_CMD); - - /* ...get API structure size */ - XA_API(base, XA_API_CMD_GET_API_SIZE, 0, &n); - - /* ...allocate memory for codec API structure (4-bytes aligned) */ - XMALLOC(&base->api, n, 4, core); - - /* ...set default config parameters */ - XA_API(base, XA_API_CMD_INIT, XA_CMD_TYPE_INIT_API_PRE_CONFIG_PARAMS, NULL); - - /* ...get memory info tables size */ - if (XA_API(base, XA_API_CMD_GET_MEMTABS_SIZE, 0, &n), n != 0) - { - /* ...allocate memory for tables (4-bytes aligned) */ - XMALLOC(&base->mem_tabs, n, 4, core); - - /* ...set pointer for process memory tables */ - XA_API(base, XA_API_CMD_SET_MEMTABS_PTR, 0, base->mem_tabs.addr); - } - - TRACE(INIT, _b("Codec[%p] pre-initialization completed"), base); - - return XA_NO_ERROR; -} - -/* ...post-initialization setup */ -static XA_ERRORCODE xa_base_postinit(XACodecBase *base, u32 core) -{ - WORD32 n, i; - - /* ...issue post-config command and determine the buffer requirements */ - XA_API(base, XA_API_CMD_INIT, XA_CMD_TYPE_INIT_API_POST_CONFIG_PARAMS, NULL); - - /* ...get number of memory tables required */ - XA_API(base, XA_API_CMD_GET_N_MEMTABS, 0, &n); - - /* ...set scratch buffer in advance (as codec not necessarily exposes it) */ - base->scratch = XF_CORE_DATA(core)->scratch; - - /* ...allocate memory buffers */ - for (i = 0; i < n; i++) - { - WORD32 size, align, type; - - TRACE(1, _b("i = %u (of %u)"), (u32)i, (u32)n); - - /* ...get memory type */ - XA_API(base, XA_API_CMD_GET_MEM_INFO_TYPE, i, &type); - - /* ...get memory size of i-th buffer */ - XA_API(base, XA_API_CMD_GET_MEM_INFO_SIZE, i, &size); - - /* ...get alignment */ - XA_API(base, XA_API_CMD_GET_MEM_INFO_ALIGNMENT, i, &align); - - /* ...process individual buffer */ - switch (type) - { - case XA_MEMTYPE_SCRATCH: - /* ...scratch memory is shared among all codecs; check its validity */ - XF_CHK_ERR(size <= XF_CFG_CODEC_SCRATCHMEM_SIZE, XA_API_FATAL_MEM_ALLOC); - - /* ...make sure alignment is sane */ - XF_CHK_ERR((XF_CFG_CODEC_SCRATCHMEM_ALIGN & (align - 1)) == 0, XA_API_FATAL_MEM_ALIGN); - - /* ...set the scratch memory pointer */ - XA_API(base, XA_API_CMD_SET_MEM_PTR, i, base->scratch); - - TRACE(INIT, _b("Mem tab %d: sz=%d al=%d ty=%d Scratch memory (%p)"), i, size, align, type, base->scratch); - - break; - - case XA_MEMTYPE_PERSIST: - /* ...allocate persistent memory */ - XMALLOC(&base->persist, size, align, core); - - /* ...and set the pointer instantly */ - XA_API(base, XA_API_CMD_SET_MEM_PTR, i, base->persist.addr); - - TRACE(INIT, _b("Mem tab %d: sz=%d al=%d ty=%d Persistent memory (%p)"), i, size, align, type, base->persist.addr); - - break; - - case XA_MEMTYPE_INPUT: - case XA_MEMTYPE_OUTPUT: - /* ...input/output buffer specification; pass to codec function */ - CODEC_API(base, memtab, i, type, size, align, core); - - break; - - default: - /* ...unrecognized memory type */ - TRACE(ERROR, _x("Invalid memory type: [%d]=(%u, %u, %u)"), i, type, size, align); - return XA_API_FATAL_INVALID_CMD_TYPE; - } - } - - TRACE(INIT, _b("Codec[%p] post-initialization completed (api:%p[%u])"), base, base->api.addr, base->api.size); - - return XA_NO_ERROR; -} - -/******************************************************************************* - * Commands processing - ******************************************************************************/ - -/* ...SET-PARAM processing (enabled in all states) */ -XA_ERRORCODE xa_base_set_param(XACodecBase *base, xf_message_t *m) -{ - xf_set_param_msg_t *cmd = m->buffer; - xf_set_param_item_t *param = &cmd->item[0]; - WORD32 n, i; - - /* ...calculate total amount of parameters */ - n = m->length / sizeof(*param); - - /* ...check the message length is sane */ - XF_CHK_ERR(m->length == XF_SET_PARAM_CMD_LEN(n), XA_API_FATAL_INVALID_CMD_TYPE); - - /* ...apply all parameters; pass to codec-specific function */ - for (i = 0; i < n; i++) - { - TRACE(SETUP, _b("set-param[%p]: [%u]=%u"), base, param[i].id, param[i].value); - - if (base->setparam) - { - CODEC_API(base, setparam, param[i].id, ¶m[i].value); - } - else - { - XA_API(base, XA_API_CMD_SET_CONFIG_PARAM, param[i].id, ¶m[i].value); - } - } - - /* ...check if we need to do post-initialization */ - if ((base->state & XA_BASE_FLAG_POSTINIT) == 0) - { - /* ...do post-initialization step */ - XA_CHK(xa_base_postinit(base, XF_MSG_DST_CORE(m->id))); - - /* ...mark the codec static configuration is set */ - base->state ^= XA_BASE_FLAG_POSTINIT | XA_BASE_FLAG_RUNTIME_INIT; - } - - /* ...complete message processing; output buffer is empty */ - xf_response_ok(m); - - return XA_NO_ERROR; -} - -/* ...GET-PARAM message processing (enabled in all states) */ -XA_ERRORCODE xa_base_get_param(XACodecBase *base, xf_message_t *m) -{ - xf_get_param_msg_t *cmd = m->buffer; - u32 *id = &cmd->c.id[0]; - u32 *value = &cmd->r.value[0]; - u32 n, i; - - /* ...calculate amount of parameters */ - n = m->length / sizeof(*id); - - /* ...check input parameter length */ - XF_CHK_ERR(XF_GET_PARAM_CMD_LEN(n) == m->length, XA_API_FATAL_INVALID_CMD_TYPE); - - /* ...retrieve the collection of codec parameters */ - for (i = 0; i < n; i++) - { - /* ...place the result into same location */ - if (base->getparam) - { - CODEC_API(base, getparam, id[i], &value[i]); - } - else - { - XA_API(base, XA_API_CMD_GET_CONFIG_PARAM, id[i], &value[i]); - } - } - - /* ...complete message specifying output buffer size */ - xf_response_data(m, XF_GET_PARAM_RSP_LEN(n)); - - return XA_NO_ERROR; -} - -/* ...SET-PARAM-EXT processing (enabled in all states) */ -XA_ERRORCODE xa_base_set_param_ext(XACodecBase *base, xf_message_t *m) -{ - xf_ext_param_msg_t *cmd = m->buffer; - u16 length = m->length; - u16 remaining = (length + 3) & ~3; - u16 i; - - for (i = 0; TRACE_CFG(SETUP) && i < remaining; i += 16) - { - TRACE(SETUP, _b("[%03x]: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X"), - i, - ((u8 *)m->buffer)[i + 0], ((u8 *)m->buffer)[i + 1], - ((u8 *)m->buffer)[i + 2], ((u8 *)m->buffer)[i + 3], - ((u8 *)m->buffer)[i + 4], ((u8 *)m->buffer)[i + 5], - ((u8 *)m->buffer)[i + 6], ((u8 *)m->buffer)[i + 7], - ((u8 *)m->buffer)[i + 8], ((u8 *)m->buffer)[i + 9], - ((u8 *)m->buffer)[i + 10], ((u8 *)m->buffer)[i + 11], - ((u8 *)m->buffer)[i + 12], ((u8 *)m->buffer)[i + 13], - ((u8 *)m->buffer)[i + 14], ((u8 *)m->buffer)[i + 15]); - } - - /* ...process all parameters encapsulated in buffer */ - while (remaining >= sizeof(*cmd)) - { - u16 id = cmd->desc.id; - u16 dlen = cmd->desc.length; - u16 dsize = (dlen + 3) & ~3; - u16 pad = dlen & 3; - - /* ...cut-off descriptor header */ - remaining -= sizeof(*cmd); - - TRACE(SETUP, _b("remaining:%u, desc_size:%u"), (u32)remaining, (u32)dsize); - - /* ...make sure length is sufficient */ - XF_CHK_ERR(remaining >= dsize, XA_API_FATAL_INVALID_CMD_TYPE); - - /* ...pad remaining bytes with zeroes */ - (pad ? memset(cmd->data + dlen, 0, 4 - pad) : 0); - - TRACE(SETUP, _b("set-ext-param[%p]: [%u]:%u - [%02X:%02X:%02X:%02X:...]"), base, id, dsize, cmd->data[0], cmd->data[1], cmd->data[2], cmd->data[3]); - - /* ...apply parameter */ - XA_API(base, XA_API_CMD_SET_CONFIG_PARAM, id, cmd->data); - - /* ...move to next item (keep 4-bytes alignment for descriptor) */ - cmd = (xf_ext_param_msg_t *)(&cmd->data[0] + dsize), remaining -= dsize; - } - - /* ...check the message is fully processed */ - XF_CHK_ERR(remaining == 0, XA_API_FATAL_INVALID_CMD_TYPE); - - /* ...complete message processing; output buffer is empty */ - //xf_response_ok(m); - - /* ...unfortunately, it looks like a bug of the library that updates the memory - * and leaves it in a dirty state causing subsequent cache inconsistency - tbd - */ - xf_response_data(m, length); - - return XA_NO_ERROR; -} - -/* ...GET-PARAM-EXT message processing (enabled in all states) */ -XA_ERRORCODE xa_base_get_param_ext(XACodecBase *base, xf_message_t *m) -{ - xf_ext_param_msg_t *cmd = m->buffer; - u32 length = m->length; - u32 remaining = (length + 3) & ~3; - int i; - - for (i = 0; TRACE_CFG(SETUP) && i < remaining; i += 16) - { - TRACE(SETUP, _b("[%03x]: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X"), - i, - ((u8 *)m->buffer)[i + 0], ((u8 *)m->buffer)[i + 1], - ((u8 *)m->buffer)[i + 2], ((u8 *)m->buffer)[i + 3], - ((u8 *)m->buffer)[i + 4], ((u8 *)m->buffer)[i + 5], - ((u8 *)m->buffer)[i + 6], ((u8 *)m->buffer)[i + 7], - ((u8 *)m->buffer)[i + 8], ((u8 *)m->buffer)[i + 9], - ((u8 *)m->buffer)[i + 10], ((u8 *)m->buffer)[i + 11], - ((u8 *)m->buffer)[i + 12], ((u8 *)m->buffer)[i + 13], - ((u8 *)m->buffer)[i + 14], ((u8 *)m->buffer)[i + 15]); - } - - /* ...process all parameters encapsulated in buffer */ - while (remaining >= sizeof(*cmd)) - { - u16 id = cmd->desc.id; - u16 len = cmd->desc.length; - u16 size = (len + 3) & ~3; - u8 pad = len & 3; - - /* ...cut-off command header */ - remaining -= sizeof(*cmd); - - /* ...make sure data buffer has sufficient length */ - XF_CHK_ERR(remaining >= size, XA_API_FATAL_INVALID_CMD_TYPE); - - /* ...retrieve parameter from buffer (care about alignment? - tbd) */ - XA_API(base, XA_API_CMD_GET_CONFIG_PARAM, id, cmd->data); - - /* ...pad remaininig bytes with zeroes */ - (pad ? memset(cmd->data + len, 0, 4 - pad) : 0); - - TRACE(SETUP, _b("get-ext-param[%p]: [%u]:%u - [%02X:%02X:%02X:%02X:...]"), base, id, size, cmd->data[0], cmd->data[1], cmd->data[2], cmd->data[3]); - - /* ...move to next item (alignment issues? - tbd) */ - cmd = (xf_ext_param_msg_t *)(&cmd->data[0] + size), remaining -= size; - } - - /* ...check the message is fully processed */ - XF_CHK_ERR(remaining == 0, XA_API_FATAL_INVALID_CMD_TYPE); - - /* ...complete message processing; output buffer has the same length */ - xf_response_data(m, length); - - return XA_NO_ERROR; -} - -/******************************************************************************* - * Command/data processing functions - ******************************************************************************/ - -/* ...generic codec data processing */ -static XA_ERRORCODE xa_base_process(XACodecBase *base) -{ - XA_ERRORCODE error; - WORD32 done; - - /* ...clear internal scheduling flag */ - base->state &= ~XA_BASE_FLAG_SCHEDULE; - - /* ...codec-specific preprocessing (buffer maintenance) */ - if ((error = CODEC_API(base, preprocess)) != XA_NO_ERROR) - { - /* ...return non-fatal codec error */ - return error; - } - - /* ...execution step */ - if (base->state & XA_BASE_FLAG_RUNTIME_INIT) - { - /* ...kick initialization process */ - XA_API(base, XA_API_CMD_INIT, XA_CMD_TYPE_INIT_PROCESS, NULL); - - /* ...check if initialization is completed */ - XA_API(base, XA_API_CMD_INIT, XA_CMD_TYPE_INIT_DONE_QUERY, &done); - - TRACE(EXEC, _b("Initialization result: %d"), done); - - /* ...switch to execution state if required */ - (done ? base->state ^= XA_BASE_FLAG_RUNTIME_INIT | XA_BASE_FLAG_EXECUTION : 0); - } - else if (base->state & XA_BASE_FLAG_EXECUTION) - { - TRACE(1, _b("do exec")); - - /* ...execute decoding process */ - XA_API(base, XA_API_CMD_EXECUTE, XA_CMD_TYPE_DO_EXECUTE, NULL); - - /* ...check for end-of-stream condition */ - XA_API(base, XA_API_CMD_EXECUTE, XA_CMD_TYPE_DONE_QUERY, &done); - - TRACE(EXEC, _b("Execution result: %d"), done); - - /* ...mark the output path is done to release all queued buffers */ - (done ? base->state ^= XA_BASE_FLAG_EXECUTION | XA_BASE_FLAG_COMPLETED : 0); - } - - /* ...codec-specific buffer post-processing */ - return CODEC_API(base, postprocess, done); -} - -/* ...message-processing function (component entry point) */ -static int xa_base_command(xf_component_t *component, xf_message_t *m) -{ - XACodecBase *base = (XACodecBase *) component; - u32 cmd; - - /* ...invoke data-processing function if message is null */ - if (m == NULL) - { - XF_CHK_ERR(!XA_ERROR_SEVERITY(xa_base_process(base)), -EPIPE); - return 0; - } - - /* ...process the command */ - TRACE(EXEC, _b("[%p]:state[%X]:(%X, %d, %p)"), base, base->state, m->opcode, m->length, m->buffer); - - /* ...bail out if this is forced termination command (I do have a map; maybe I'd better have a hook? - tbd) */ - if ((cmd = XF_OPCODE_TYPE(m->opcode)) == XF_OPCODE_TYPE(XF_UNREGISTER)) - { - TRACE(INIT, _b("force component[%p] termination"), base); - return -1; - } - - /* ...check opcode is valid */ - XF_CHK_ERR(cmd < base->command_num, -EINVAL); - - /* ...and has a hook */ - XF_CHK_ERR(base->command[cmd] != NULL, -EINVAL); - - /* ...pass control to specific command */ - XF_CHK_ERR(!XA_ERROR_SEVERITY(base->command[cmd](base, m)), -EPIPE); - - /* ...execution completed successfully */ - return 0; -} - -/******************************************************************************* - * Base codec API - ******************************************************************************/ - -/* ...data processing scheduling */ -void xa_base_schedule(XACodecBase *base, u32 dts) -{ - if ((base->state & XA_BASE_FLAG_SCHEDULE) == 0) - { - /* ...schedule component task execution */ - xf_component_schedule(&base->component, dts); - - /* ...and put scheduling flag */ - base->state ^= XA_BASE_FLAG_SCHEDULE; - } - else - { - TRACE(EXEC, _b("codec[%p] processing pending"), base); - } -} - -/* ...cancel data processing */ -void xa_base_cancel(XACodecBase *base) -{ - if (base->state & XA_BASE_FLAG_SCHEDULE) - { - /* ...cancel scheduled codec task */ - xf_component_cancel(&base->component); - - /* ...and clear scheduling flag */ - base->state ^= XA_BASE_FLAG_SCHEDULE; - - TRACE(EXEC, _b("codec[%p] processing cancelled"), base); - } -} - -/* ...base codec destructor */ -void xa_base_destroy(XACodecBase *base, u32 size, u32 core) -{ - /* ...deallocate all resources */ - xf_mm_free_buffer(&base->persist, core); - xf_mm_free_buffer(&base->mem_tabs, core); - xf_mm_free_buffer(&base->api, core); - - /* ...destroy codec structure (and task) itself */ - xf_mem_free(base, size, core, 0); - - TRACE(INIT, _b("codec[%p]:%u destroyed"), base, core); -} - -/* ...generic codec initialization routine */ -XACodecBase * xa_base_factory(u32 core, u32 size, xa_codec_func_t process) -{ - XACodecBase *base; - - /* ...make sure the size is sane */ - XF_CHK_ERR(size >= sizeof(XACodecBase), NULL); - - /* ...allocate local memory for codec structure */ - XF_CHK_ERR(base = xf_mem_alloc(size, 0, core, 0), NULL); - - /* ...reset codec memory */ - memset(base, 0, size); - - /* ...set low-level codec API function */ - base->process = process; - - /* ...set message processing function */ - base->component.entry = xa_base_command; - - /* ...do basic initialization */ - if (xa_base_preinit(base, core) != XA_NO_ERROR) - { - /* ...initialization failed for some reason; do cleanup */ - xa_base_destroy(base, size, core); - - return NULL; - } - - /* ...initialization completed successfully */ - TRACE(INIT, _b("Codec[%p]:%u initialized"), base, core); - - return base; -} diff --git a/hifi/xaf/hifi-dpf/audio/xa-class-base.h b/hifi/xaf/hifi-dpf/audio/xa-class-base.h deleted file mode 100644 index 252044d4..00000000 --- a/hifi/xaf/hifi-dpf/audio/xa-class-base.h +++ /dev/null @@ -1,263 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2018 Cadence Design Systems, Inc. -* -* Permission is hereby granted, free of charge, to any person obtaining -* a copy of this software and associated documentation files (the -* "Software"), to use this Software with Cadence processor cores only and -* not with any other processors and platforms, subject to -* the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -******************************************************************************/ - -/******************************************************************************* - * xa-class-base.h - * - * Generic Xtensa Audio codecs interfaces - * - ******************************************************************************/ - -#ifndef __XA_CLASS_BASE_H -#define __XA_CLASS_BASE_H - -/******************************************************************************* - * Includes - ******************************************************************************/ - -/* ...audio-specific API */ -#include "audio/xa_type_def.h" -#include "audio/xa_error_standards.h" -#include "audio/xa_apicmd_standards.h" -#include "audio/xa_memory_standards.h" - -/******************************************************************************* - * Generic codec structure - ******************************************************************************/ - -typedef struct XACodecBase XACodecBase; - -/* ...memory buffer initialization */ -typedef XA_ERRORCODE (*xa_codec_memtab_f)(XACodecBase *codec, WORD32 i, WORD32 type, WORD32 size, WORD32 align, u32 core); - -/* ...preprocessing operation */ -typedef XA_ERRORCODE (*xa_codec_preprocess_f)(XACodecBase *); - -/* ...postprocessing operation */ -typedef XA_ERRORCODE (*xa_codec_postprocess_f)(XACodecBase *, int); - -/* ...parameter setting function */ -typedef XA_ERRORCODE (*xa_codec_setparam_f)(XACodecBase *, WORD32, pVOID p); - -/* ...parameter retrival function */ -typedef XA_ERRORCODE (*xa_codec_getparam_f)(XACodecBase *, WORD32, pVOID p); - -/******************************************************************************* - * Codec instance structure - ******************************************************************************/ - -struct XACodecBase -{ - /*************************************************************************** - * Control data - **************************************************************************/ - - /* ...generic component handle */ - xf_component_t component; - - /* ...codec API entry point (function) */ - xa_codec_func_t *process; - - /* ...codec API handle, passed to *process */ - xf_mm_buffer_t api; - - /* ...memory table buffer */ - xf_mm_buffer_t mem_tabs; - - /* ...persistent memory buffer */ - xf_mm_buffer_t persist; - - /* ...scratch memory pointer */ - void *scratch; - - /* ...codec control state */ - u32 state; - - /*************************************************************************** - * Codec-specific methods - **************************************************************************/ - - /* ...memory buffer initialization */ - xa_codec_memtab_f memtab; - - /* ...preprocessing function */ - xa_codec_preprocess_f preprocess; - - /* ...postprocessing function */ - xa_codec_postprocess_f postprocess; - - /* ...configuration parameter setting function */ - xa_codec_setparam_f setparam; - - /* ...configuration parameter retrieval function */ - xa_codec_getparam_f getparam; - - /* ...command-processing table */ - XA_ERRORCODE (* const * command)(XACodecBase *, xf_message_t *); - - /* ...command-processing table size */ - u32 command_num; -}; - -/******************************************************************************* - * Base codec execution flags - ******************************************************************************/ - -/* ...codec static initialization completed */ -#define XA_BASE_FLAG_POSTINIT (1 << 0) - -/* ...codec runtime initialization sequence */ -#define XA_BASE_FLAG_RUNTIME_INIT (1 << 1) - -/* ...codec steady execution state */ -#define XA_BASE_FLAG_EXECUTION (1 << 2) - -/* ...execution stage completed */ -#define XA_BASE_FLAG_COMPLETED (1 << 3) - -/* ...data processing scheduling flag */ -#define XA_BASE_FLAG_SCHEDULE (1 << 4) - -/* ...base codec flags accessor */ -#define __XA_BASE_FLAGS(flags) ((flags) & ((1 << 5) - 1)) - -/* ...custom execution flag */ -#define __XA_BASE_FLAG(f) ((f) << 5) - -/******************************************************************************* - * Local macros definitions - ******************************************************************************/ - -/* ...audio-framework API function execution */ -#define XA_CHK(cond) \ -({ \ - XA_ERRORCODE __e = (cond); \ - if (__e != XA_NO_ERROR) \ - { \ - if (XA_ERROR_SEVERITY(__e)) \ - { \ - TRACE(ERROR, _x("error: %X"), __e); \ - return __e; \ - } \ - TRACE(WARNING, _x("warning: %X"), __e); \ - } \ - __e; \ -}) - -/* ...low-level codec API function execution */ -#define XA_API(codec, cmd, idx, pv) \ -({ \ - XA_ERRORCODE __e; \ - __e = (codec)->process((xa_codec_handle_t)(codec)->api.addr, (cmd), (idx), (pv)); \ - if (__e != XA_NO_ERROR) \ - { \ - if (XA_ERROR_SEVERITY(__e)) \ - { \ - TRACE(ERROR, _x("[%p]:(%d, %d, %p): %X"), (codec), (cmd), (idx), (pv), __e); \ - return __e; \ - } \ - TRACE(WARNING, _x("%X"), __e); \ - } \ - __e; \ -}) - -#define XA_API_NORET(codec, cmd, idx, pv) \ -({ \ - XA_ERRORCODE __e; \ - __e = (codec)->process((xa_codec_handle_t)(codec)->api.addr, (cmd), (idx), (pv)); \ - if (__e != XA_NO_ERROR) \ - { \ - if (XA_ERROR_SEVERITY(__e)) \ - { \ - TRACE(ERROR, _x("[%p]:(%d, %d, %p): %X"), (codec), (cmd), (idx), (pv), __e); \ - } \ - TRACE(WARNING, _x("%X"), __e); \ - } \ - __e; \ -}) - -/* ...codec hook invocation */ -#define CODEC_API(codec, func, ...) \ -({ \ - XA_ERRORCODE __e = (codec)->func((codec), ##__VA_ARGS__); \ - \ - if (__e != XA_NO_ERROR) \ - { \ - if (XA_ERROR_SEVERITY(__e)) \ - { \ - /* ...actual error is reported by the codec */ \ - TRACE(ERROR, _x("[%p]: " #func ": %X"), (codec), __e); \ - return __e; \ - } \ - \ - TRACE(WARNING, _x("warning: %X"), __e); \ - } \ - __e; \ -}) - -/* ...allocate local memory on specific core */ -#define XMALLOC(p, size, align, core) \ -do \ -{ \ - if (xf_mm_alloc_buffer((size), (align), (core), (p)) != 0) \ - { \ - TRACE(ERROR, _x("Failed to allocate %d bytes of memory"), (size)); \ - return XA_API_FATAL_MEM_ALLOC; \ - } \ - \ - if (((u32)((p)->addr) & ((align) - 1)) != 0) \ - { \ - TRACE(ERROR, _x("Invalid %d-algnment: %p"), (align), (p)->addr); \ - return XA_API_FATAL_MEM_ALIGN; \ - } \ -} \ -while (0) - -/******************************************************************************* - * Public API - ******************************************************************************/ - -/* ...SET-PARAM processing */ -extern XA_ERRORCODE xa_base_set_param(XACodecBase *base, xf_message_t *m); - -/* ...GET-PARAM-EXT message processing */ -extern XA_ERRORCODE xa_base_set_param_ext(XACodecBase *base, xf_message_t *m); - -/* ...GET-PARAM message processing */ -extern XA_ERRORCODE xa_base_get_param(XACodecBase *base, xf_message_t *m); - -/* ...GET-PARAM-EXT message processing */ -extern XA_ERRORCODE xa_base_get_param_ext(XACodecBase *base, xf_message_t *m); - -/* ...data processing scheduling */ -extern void xa_base_schedule(XACodecBase *base, u32 dts); - -/* ...cancel internal scheduling message */ -extern void xa_base_cancel(XACodecBase *base); - -/* ...base codec factory */ -extern XACodecBase * xa_base_factory(u32 core, u32 size, xa_codec_func_t process); - -/* ...base codec destructor */ -extern void xa_base_destroy(XACodecBase *base, u32 size, u32 core); - -#endif /* __XA_CLASS_BASE_H */ diff --git a/hifi/xaf/hifi-dpf/audio/xa-class-mixer.c b/hifi/xaf/hifi-dpf/audio/xa-class-mixer.c deleted file mode 100644 index ac2ff9ad..00000000 --- a/hifi/xaf/hifi-dpf/audio/xa-class-mixer.c +++ /dev/null @@ -1,870 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2018 Cadence Design Systems, Inc. -* -* Permission is hereby granted, free of charge, to any person obtaining -* a copy of this software and associated documentation files (the -* "Software"), to use this Software with Cadence processor cores only and -* not with any other processors and platforms, subject to -* the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -******************************************************************************/ - -/******************************************************************************* - * xa-class-mixer.c - * - * Generic mixer component class - * - ******************************************************************************/ - -#define MODULE_TAG MIXER - -/******************************************************************************* - * Includes - ******************************************************************************/ - -#include "xf.h" -#include "xa-class-base.h" -#include "audio/xa-mixer-api.h" - -/******************************************************************************* - * Tracing tags - ******************************************************************************/ - -TRACE_TAG(INIT, 1); -TRACE_TAG(WARNING, 1); -TRACE_TAG(INFO, 1); -TRACE_TAG(INPUT, 1); -TRACE_TAG(OUTPUT, 1); - -/******************************************************************************* - * Data structures - ******************************************************************************/ - -/* ...mixed source - input data */ -typedef struct XATrack -{ - /* ...input port data */ - xf_input_port_t input; - - /* ...current presentation timestamp (in samples; local to a mixer state) */ - u32 pts; - - /* ...total amount of decoded frames since last synchronization point */ - u32 decoded; - - /* ...total amount of rendered frames (consumed) since last synchronization point */ - u32 rendered; - -} XATrack; - -/******************************************************************************* - * Helpers - ******************************************************************************/ - -static inline u32 xa_track_test_flags(XATrack *track, u32 flags) -{ - return (track->input.flags & flags); -} - -static inline u32 xa_track_set_flags(XATrack *track, u32 flags) -{ - return (track->input.flags |= flags); -} - -static inline u32 xa_track_clear_flags(XATrack *track, u32 flags) -{ - return (track->input.flags &= ~flags); -} - -static inline u32 xa_track_toggle_flags(XATrack *track, u32 flags) -{ - return (track->input.flags ^= flags); -} - -/******************************************************************************* - * Mixer data definitions - ******************************************************************************/ - -/* ...mixer data */ -typedef struct XAMixer -{ - /*************************************************************************** - * Control data - **************************************************************************/ - - /* ...generic audio codec data */ - XACodecBase base; - - /* ...input tracks */ - XATrack track[XA_MIXER_MAX_TRACK_NUMBER]; - - /* ...output port */ - xf_output_port_t output; - - /*************************************************************************** - * Run-time configuration parameters - **************************************************************************/ - - /* ...audio frame size in samples */ - u32 frame_size; - - /* ...audio frame duration */ - u32 frame_duration; - - /* ...presentation timestamp (in samples; local mixer scope) */ - u32 pts; - -} XAMixer; - -/******************************************************************************* - * Mixer flags - ******************************************************************************/ - -/* ...output port setup completed */ -#define XA_MIXER_FLAG_OUTPUT_SETUP __XA_BASE_FLAG(1 << 0) - -/******************************************************************************* - * Track state flags - ******************************************************************************/ - -/* ...track is idle (will autostart as soon as input data received) */ -#define XA_TRACK_FLAG_IDLE __XF_INPUT_FLAG(1 << 0) - -/* ...track is rendered */ -#define XA_TRACK_FLAG_ACTIVE __XF_INPUT_FLAG(1 << 1) - -/* ...track is paused */ -#define XA_TRACK_FLAG_PAUSED __XF_INPUT_FLAG(1 << 2) - -/* ...track input port is setup */ -#define XA_TRACK_FLAG_INPUT_SETUP __XF_INPUT_FLAG(1 << 3) - -/* ...track has received data */ -#define XA_TRACK_FLAG_RECVD_DATA __XF_INPUT_FLAG(1 << 4) - -/******************************************************************************* - * Helper functions - ******************************************************************************/ -/* ...Count the tracks that have received data or are active*/ -static inline UWORD32 xa_mixer_check_active(XAMixer *mixer) -{ - XATrack *track; - UWORD32 i; - UWORD32 cnt = 0; - - for (track = &mixer->track[i = 0]; i < XA_MIXER_MAX_TRACK_NUMBER; i++, track++) - { - if (xa_track_test_flags(track, XA_TRACK_FLAG_RECVD_DATA | XA_TRACK_FLAG_ACTIVE)) - cnt++; - } - return cnt; -} - -/* ...prepare mixer for steady operation */ -static inline XA_ERRORCODE xa_mixer_prepare_runtime(XAMixer *mixer) -{ - XACodecBase *base = (XACodecBase *) mixer; - xf_message_t *m = xf_msg_dequeue(&mixer->output.queue); - xf_start_msg_t *msg = m->buffer; - u32 frame_size; - u32 factor; - - /* ...query mixer parameters */ - XA_API(base, XA_API_CMD_GET_CONFIG_PARAM, XA_MIXER_CONFIG_PARAM_SAMPLE_RATE, &msg->sample_rate); - XA_API(base, XA_API_CMD_GET_CONFIG_PARAM, XA_MIXER_CONFIG_PARAM_CHANNELS, &msg->channels); - XA_API(base, XA_API_CMD_GET_CONFIG_PARAM, XA_MIXER_CONFIG_PARAM_PCM_WIDTH, &msg->pcm_width); - XA_API(base, XA_API_CMD_GET_MEM_INFO_SIZE, 0, &msg->input_length); - XA_API(base, XA_API_CMD_GET_MEM_INFO_SIZE, XA_MIXER_MAX_TRACK_NUMBER, &msg->output_length); - XA_API(base, XA_API_CMD_GET_CONFIG_PARAM, XA_MIXER_CONFIG_PARAM_FRAME_SIZE, &frame_size); - - /* ...calculate mixer frame duration; get upsample factor */ - XF_CHK_ERR(factor = xf_timebase_factor(msg->sample_rate), XA_MIXER_CONFIG_FATAL_RANGE); - - /* ...set mixer frame duration */ - mixer->frame_duration = frame_size * factor; - - /* ...pass response to caller */ - xf_response_data(m, sizeof(*msg)); - - return XA_NO_ERROR; -} - -/******************************************************************************* - * Commands handlers - ******************************************************************************/ - -/* ...EMPTY-THIS-BUFFER command processing */ -static XA_ERRORCODE xa_mixer_empty_this_buffer(XACodecBase *base, xf_message_t *m) -{ - XAMixer *mixer = (XAMixer *) base; - u32 i = XF_MSG_DST_PORT(m->id); - XATrack *track = &mixer->track[i]; - - /* ...make sure the port is valid */ - XF_CHK_ERR(i < XA_MIXER_MAX_TRACK_NUMBER, XA_API_FATAL_INVALID_CMD_TYPE); - - /* ...command is allowed only in "postinit" state */ - XF_CHK_ERR(base->state & XA_BASE_FLAG_POSTINIT, XA_API_FATAL_INVALID_CMD); - - TRACE(INPUT, _b("track-%u: received buffer [%p]:%u"), i, m->buffer, m->length); - - /* ...update received data for the track */ - if (m->length) - xa_track_set_flags(track, XA_TRACK_FLAG_RECVD_DATA); - else - xa_track_clear_flags(track, XA_TRACK_FLAG_RECVD_DATA); - - /* ...place received message into track input port */ - if (xf_input_port_put(&track->input, m)) - { - /* ...process track autostart if needed */ - if (xa_track_test_flags(track, XA_TRACK_FLAG_IDLE)) - { - /* ...put track into active state */ - xa_track_toggle_flags(track, XA_TRACK_FLAG_IDLE | XA_TRACK_FLAG_ACTIVE); - - /* ...save track presentation timestamp */ - track->pts = mixer->pts; - - TRACE(INFO, _b("track-%u started (pts=%x)"), i, track->pts); - } - - /* ...schedule data processing if there is output port available */ - if (xf_output_port_ready(&mixer->output)) - { - /* ...force data processing */ - xa_base_schedule(base, 0); - } - } - - return XA_NO_ERROR; -} - -/* ...FILL-THIS-BUFFER command processing */ -static XA_ERRORCODE xa_mixer_fill_this_buffer(XACodecBase *base, xf_message_t *m) -{ - XAMixer *mixer = (XAMixer *) base; - u32 i = XF_MSG_DST_PORT(m->id); - - /* ...make sure the port is valid */ - XF_CHK_ERR(i == XA_MIXER_MAX_TRACK_NUMBER, XA_API_FATAL_INVALID_CMD_TYPE); - - /* ...command is allowed only in "postinit" state */ - XF_CHK_ERR(base->state & XA_BASE_FLAG_POSTINIT, XA_API_FATAL_INVALID_CMD); - - /* ...process runtime initialization explicitly */ - if (base->state & XA_BASE_FLAG_RUNTIME_INIT) - { - /* ...message must be zero-length */ - XF_CHK_ERR(m->length == 0, XA_MIXER_EXEC_FATAL_STATE); - } - else if (m->length != 0) /* ...EOS response */ - { - /* ...message must have exactly expected size (there is no ordered abortion) */ - XF_CHK_ERR(m->length == mixer->output.length, XA_MIXER_EXEC_FATAL_STATE); - } - - TRACE(OUTPUT, _b("received output buffer [%p]:%u"), m->buffer, m->length); - - /* ...put message into output port */ - if (xf_output_port_put(&mixer->output, m)) - { - /* ...force data processing */ - xa_base_schedule(base, 0); - } - - return XA_NO_ERROR; -} - -/* ...output port routing */ -static XA_ERRORCODE xa_mixer_port_route(XACodecBase *base, xf_message_t *m) -{ - XAMixer *mixer = (XAMixer *) base; - xf_route_port_msg_t *cmd = m->buffer; - xf_output_port_t *port = &mixer->output; - u32 src = XF_MSG_DST(m->id); - u32 dst = cmd->dst; - - /* ...command is allowed only in "postinit" state */ - XF_CHK_ERR(base->state & XA_BASE_FLAG_POSTINIT, XA_API_FATAL_INVALID_CMD); - - /* ...make sure output port is addressed */ - XF_CHK_ERR(XF_MSG_DST_PORT(m->id) == XA_MIXER_MAX_TRACK_NUMBER, XA_API_FATAL_INVALID_CMD_TYPE); - - /* ...make sure port is not routed yet */ - XF_CHK_ERR(!xf_output_port_routed(port), XA_API_FATAL_INVALID_CMD_TYPE); - - /* ...route output port - allocate queue */ - XF_CHK_ERR(xf_output_port_route(port, __XF_MSG_ID(dst, src), cmd->alloc_number, cmd->alloc_size, cmd->alloc_align) == 0, XA_API_FATAL_MEM_ALLOC); - - /* ...schedule processing instantly - tbd - check if we have anything pending on input */ - xa_base_schedule(base, 0); - - /* ...pass success result to caller */ - xf_response_ok(m); - - return XA_NO_ERROR; -} - -/* ...port unroute command */ -static XA_ERRORCODE xa_mixer_port_unroute(XACodecBase *base, xf_message_t *m) -{ - XAMixer *mixer = (XAMixer *) base; - xf_output_port_t *port = &mixer->output; - - /* ...command is allowed only in "postinit" state */ - XF_CHK_ERR(base->state & XA_BASE_FLAG_POSTINIT, XA_API_FATAL_INVALID_CMD); - - /* ...make sure output port is addressed */ - XF_CHK_ERR(XF_MSG_DST_PORT(m->id) == XA_MIXER_MAX_TRACK_NUMBER, XA_API_FATAL_INVALID_CMD_TYPE); - - /* ...cancel any pending processing */ - xa_base_cancel(base); - - /* ...clear output-port-setup condition */ - base->state &= ~XA_MIXER_FLAG_OUTPUT_SETUP; - - /* ...pass flush command down the graph */ - if (xf_output_port_flush(port, XF_FLUSH)) - { - TRACE(INFO, _b("port is idle; instantly unroute")); - - /* ...flushing sequence is not needed; command may be satisfied instantly */ - xf_output_port_unroute(port); - - /* ...pass response to the proxy */ - xf_response_ok(m); - } - else - { - TRACE(INFO, _b("port is busy; propagate unroute command")); - - /* ...flushing sequence is started; save flow-control message */ - xf_output_port_unroute_start(port, m); - } - - return XA_NO_ERROR; -} - -/* ...PAUSE message processing */ -static XA_ERRORCODE xa_mixer_pause(XACodecBase *base, xf_message_t *m) -{ - XAMixer *mixer = (XAMixer *) base; - u32 i = XF_MSG_DST_PORT(m->id); - XATrack *track = &mixer->track[i]; - - /* ...make sure the buffer is empty */ - XF_CHK_ERR(m->length == 0, XA_API_FATAL_INVALID_CMD_TYPE); - - /* ...check destination port is valid */ - XF_CHK_ERR(i < XA_MIXER_MAX_TRACK_NUMBER, XA_API_FATAL_INVALID_CMD_TYPE); - - /* ...check for actual track flags */ - if (xa_track_test_flags(track, XA_TRACK_FLAG_ACTIVE)) - { - /* ...switch to paused state */ - xa_track_toggle_flags(track, XA_TRACK_FLAG_ACTIVE | XA_TRACK_FLAG_PAUSED); - - /* ...other tracks may be waiting for this one, so force data processing */ - if (xf_output_port_ready(&mixer->output)) - { - xa_base_schedule(base, 0); - } - - TRACE(INFO, _b("mixer[%p]::track[%u] paused"), mixer, i); - } - else - { - /* ...track is in idle state and pausing here means suspending */ - TRACE(INFO, _b("mixer[%p]::track[%u] is not active"), mixer, i); - } - - /* ...complete message immediately */ - xf_response(m); - - return XA_NO_ERROR; -} - -/* ...RESUME command processing */ -static XA_ERRORCODE xa_mixer_resume(XACodecBase *base, xf_message_t *m) -{ - XAMixer *mixer = (XAMixer *) base; - u32 i = XF_MSG_DST_PORT(m->id); - XATrack *track = &mixer->track[i]; - - /* ...make sure the buffer is empty */ - XF_CHK_ERR(m->length == 0, XA_API_FATAL_INVALID_CMD_TYPE); - - /* ...check destination port is valid */ - XF_CHK_ERR(i < XA_MIXER_MAX_TRACK_NUMBER, XA_API_FATAL_INVALID_CMD_TYPE); - - /* ...check for actual track state */ - if (xa_track_test_flags(track, XA_TRACK_FLAG_PAUSED)) - { - /* ...switch track to active state */ - xa_track_toggle_flags(track, XA_TRACK_FLAG_ACTIVE | XA_TRACK_FLAG_PAUSED); - - /* ...reset track presentation timestamp - tbd */ - track->pts = mixer->pts; - - /* ...force data processing if there is an output buffer */ - if (xf_output_port_ready(&mixer->output)) - { - xa_base_schedule(base, 0); - } - - TRACE(INFO, _b("mixer[%p]::track[%u] resumed"), mixer, i); - } - else - { - /* ...track is in idle state; do nothing */ - TRACE(INFO, _b("mixer[%p]::track[%u] is not paused"), mixer, i); - } - - /* ...complete message */ - xf_response(m); - - return XA_NO_ERROR; -} - -/* ...FLUSH command processing */ -static XA_ERRORCODE xa_mixer_flush(XACodecBase *base, xf_message_t *m) -{ - XAMixer *mixer = (XAMixer *) base; - u32 i = XF_MSG_DST_PORT(m->id); - XATrack *track = &mixer->track[i]; - - /* ...make sure the buffer is empty */ - XF_CHK_ERR(m->length == 0, XA_API_FATAL_INVALID_CMD_TYPE); - - /* ...check destination port index */ - if (i == XA_MIXER_MAX_TRACK_NUMBER) - { - /* ...flushing response received; that is a port unrouting sequence */ - XF_CHK_ERR(xf_output_port_unrouting(&mixer->output), XA_API_FATAL_INVALID_CMD_TYPE); - - /* ...complete unroute sequence */ - xf_output_port_unroute_done(&mixer->output); - - TRACE(INFO, _b("port is unrouted")); - - return XA_NO_ERROR; - } - - /* ...check destination port index is valid */ - XF_CHK_ERR(i < XA_MIXER_MAX_TRACK_NUMBER, XA_API_FATAL_INVALID_CMD_TYPE); - - /* ...input port flushing; check the track state is valid */ - if (xa_track_test_flags(track, XA_TRACK_FLAG_ACTIVE | XA_TRACK_FLAG_PAUSED)) - { - /* ...purge input port */ - xf_input_port_purge(&track->input); - - /* ...force clearing of ACTIVE and INPUT_SETUP condition */ - xa_track_clear_flags(track, XA_TRACK_FLAG_ACTIVE | XA_TRACK_FLAG_PAUSED | XA_TRACK_FLAG_INPUT_SETUP); - - /* ...and enter into idle state */ - xa_track_set_flags(track, XA_TRACK_FLAG_IDLE); - - /* ...other tracks may be waiting for this track, so force data processing */ - if (xf_output_port_ready(&mixer->output)) - { - xa_base_schedule(base, 0); - } - - TRACE(INFO, _b("mixer[%p]::track[%u] flushed"), mixer, i); - } - - /* ...complete message instantly (no propagation to output port) */ - xf_response(m); - - return XA_NO_ERROR; -} - -/******************************************************************************* - * Codec API implementation - ******************************************************************************/ - -/* ...buffers handling */ -static XA_ERRORCODE xa_mixer_memtab(XACodecBase *base, WORD32 idx, WORD32 type, WORD32 size, WORD32 align, u32 core) -{ - XAMixer *mixer = (XAMixer *)base; - - if (type == XA_MEMTYPE_INPUT) - { - XATrack *track = &mixer->track[idx]; - - /* ...input buffer allocation; check track number is sane */ - XF_CHK_ERR(idx < XA_MIXER_MAX_TRACK_NUMBER, XA_API_FATAL_INVALID_CMD_TYPE); - - /* ...create input port for a track */ - XF_CHK_ERR(xf_input_port_init(&track->input, size, align, core) == 0, XA_API_FATAL_MEM_ALLOC); - - /* ...set input port buffer */ - XA_API(base, XA_API_CMD_SET_MEM_PTR, idx, track->input.buffer); - - /* ...put track into idle state (will start as soon as we receive data) */ - xa_track_set_flags(track, XA_TRACK_FLAG_IDLE); - - TRACE(INIT, _b("mixer[%p]::track[%u] input port created - size=%u"), mixer, idx, size); - } - else - { - /* ...output buffer allocation */ - XF_CHK_ERR(type == XA_MEMTYPE_OUTPUT, XA_API_FATAL_INVALID_CMD_TYPE); - - /* ...check port number is what we expect */ - XF_CHK_ERR(idx == XA_MIXER_MAX_TRACK_NUMBER, XA_API_FATAL_INVALID_CMD_TYPE); - - /* ...set mixer frame-size (in samples - for timestamp tracking) */ - XA_API(base, XA_API_CMD_GET_CONFIG_PARAM, XA_MIXER_CONFIG_PARAM_FRAME_SIZE, &mixer->frame_size); - - /* ...create output port for a track */ - XF_CHK_ERR(xf_output_port_init(&mixer->output, size) == 0, XA_API_FATAL_MEM_ALLOC); - - TRACE(INIT, _b("mixer[%p] output port created; size=%u"), mixer, size); - } - - return XA_NO_ERROR; -} - -/* ...preprocessing function */ -static XA_ERRORCODE xa_mixer_preprocess(XACodecBase *base) -{ - XAMixer *mixer = (XAMixer *) base; - XATrack *track; - u8 i; - XA_ERRORCODE e = XA_MIXER_EXEC_NONFATAL_NO_DATA; - - /* ...prepare output buffer */ - if (!(base->state & XA_MIXER_FLAG_OUTPUT_SETUP)) - { - void *output; - - /* ...set output buffer pointer */ - if (base->state & XA_BASE_FLAG_RUNTIME_INIT) - { - /* ...no actual data processing during initialization */ - return XA_NO_ERROR; - } - else if ((output = xf_output_port_data(&mixer->output)) == NULL) - { - /* ...no output buffer available */ - return e; - } - - /* ...set output buffer pointer */ - XA_API(base, XA_API_CMD_SET_MEM_PTR, XA_MIXER_MAX_TRACK_NUMBER, output); - - /* ...mark output port is setup */ - base->state ^= XA_MIXER_FLAG_OUTPUT_SETUP; - } - - /* ...check EOS */ - if (!xa_mixer_check_active(mixer)) - { - /* ...push EOS to output port */ - xf_output_port_produce(&mixer->output, 0); - TRACE(INFO, _b("mixer[%p]::EOS generated"), mixer); - } - - /* ...setup input buffer pointers and length */ - for (track = &mixer->track[i = 0]; i < XA_MIXER_MAX_TRACK_NUMBER; i++, track++) - { - /* ...skip tracks that are not played */ - if (!xa_track_test_flags(track, XA_TRACK_FLAG_ACTIVE)) continue; - - /* ...set temporary mixing request */ - e = XA_NO_ERROR; - - /* ...skip the tracks that has been setup already */ - if (xa_track_test_flags(track, XA_TRACK_FLAG_INPUT_SETUP)) continue; - - /* ...found active track that hasn't been setup yet */ - TRACE(INPUT, _b("track-%u: ts=%x vs mts=%x"), i, track->pts, mixer->pts); - - /* ...if track presentation timestamp is in the future, do nothing yet really */ - if (!xf_time_after(track->pts, mixer->pts)) - { - u32 filled; - - /* ...take actual data from input port (mixer is always using internal buffer) */ - if (!xf_input_port_fill(&track->input)) - { - /* ...failed to prefill input buffer - no sufficient data yet */ - return XA_MIXER_EXEC_NONFATAL_NO_DATA; - } - else - { - /* ...retrieve number of bytes available */ - filled = xf_input_port_level(&track->input); - } - - /* ...set total number of bytes we have in buffer */ - XA_API(base, XA_API_CMD_SET_INPUT_BYTES, i, &filled); - - /* ...actual data is to be played */ - TRACE(INPUT, _b("track-%u: filled %u bytes"), i, filled); - } - - /* ...mark the track input is setup (emit silence or actual data) */ - xa_track_set_flags(track, XA_TRACK_FLAG_INPUT_SETUP); - } - - /* ...do mixing operation only when all active tracks are setup */ - return e; -} - -/* ...postprocessing function */ -static XA_ERRORCODE xa_mixer_postprocess(XACodecBase *base, int done) -{ - XAMixer *mixer = (XAMixer *) base; - XATrack *track; - u32 produced; - u32 consumed; - u8 i; - - /* ...process execution stage transitions */ - if (done) - { - if (base->state & XA_BASE_FLAG_RUNTIME_INIT) - { - /* ...failed to initialize runtime (can't be? - tbd)*/ - BUG(1, _x("breakpoint")); - } - else if (base->state & XA_BASE_FLAG_EXECUTION) - { - /* ...enter into execution state; initialize runtime */ - return XA_CHK(xa_mixer_prepare_runtime(mixer)); - } - else - { - /* ...mixer operation is over (can't be? - tbd) */ - BUG(1, _x("breakpoint")); - } - } - - /* ...input ports maintenance; process all tracks */ - for (track = &mixer->track[i = 0]; i < XA_MIXER_MAX_TRACK_NUMBER; i++, track++) - { - /* ...skip the tracks that are not runing */ - if (!xa_track_test_flags(track, XA_TRACK_FLAG_ACTIVE)) continue; - - /* ...clear input setup flag */ - xa_track_clear_flags(track, XA_TRACK_FLAG_INPUT_SETUP); - - /* ...advance track presentation timestamp */ - track->pts += mixer->frame_size; - - /* ...get total amount of consumed bytes */ - XA_API(base, XA_API_CMD_GET_CURIDX_INPUT_BUF, i, &consumed); - - TRACE(INPUT, _b("track-%u::postprocess(c=%u, ts=%x)"), i, consumed, track->pts); - - /* ...consume that amount from input port (may be zero) */ - xf_input_port_consume(&track->input, consumed); - - /* ...check if input port is done */ - if (xf_input_port_done(&track->input)) - { - /* ...input stream is over; return zero-length input back to caller */ - xf_input_port_purge(&track->input); - - /* ...switch to idle state */ - xa_track_toggle_flags(track, XA_TRACK_FLAG_ACTIVE | XA_TRACK_FLAG_IDLE); - - TRACE(INFO, _b("mixer[%p]::track[%u] completed"), mixer, i); - } - } - - /* ...check if we have produced anything */ - XA_API(base, XA_API_CMD_GET_OUTPUT_BYTES, XA_MIXER_MAX_TRACK_NUMBER, &produced); - - TRACE(OUTPUT, _b("mixer[%p]::postprocess(p=%u, ts=%x, done=%u)"), mixer, produced, mixer->pts, done); - - /* ...output port maintenance */ - if (produced) - { - /* ...make sure we have produced exactly single frame */ - BUG(produced != mixer->output.length, _x("Invalid length: %u != %u"), produced, mixer->output.length); - - /* ...steady mixing process; advance mixer presentation timestamp */ - mixer->pts += mixer->frame_size; - - /* ...push data from output port */ - xf_output_port_produce(&mixer->output, produced); - - /* ...clear output-setup condition */ - base->state &= ~XA_MIXER_FLAG_OUTPUT_SETUP; - } - - /* ...reschedule data processing if there is a pending output message */ - if (xf_output_port_ready(&mixer->output)) - { - /* ...schedule execution with respect to urgency */ - xa_base_schedule(base, (produced ? mixer->frame_duration : 0)); - } - - return XA_NO_ERROR; -} - -/******************************************************************************* - * Command-processing function - ******************************************************************************/ - -/* ...command hooks */ -static XA_ERRORCODE (* const xa_mixer_cmd[])(XACodecBase *, xf_message_t *) = -{ - /* ...set-parameter - actually, same as in generic case */ - [XF_OPCODE_TYPE(XF_SET_PARAM)] = xa_base_set_param, - [XF_OPCODE_TYPE(XF_GET_PARAM)] = xa_base_get_param, - - /* ...output port routing/unrouting */ - [XF_OPCODE_TYPE(XF_ROUTE)] = xa_mixer_port_route, - [XF_OPCODE_TYPE(XF_UNROUTE)] = xa_mixer_port_unroute, - - /* ...input/output buffers processing */ - [XF_OPCODE_TYPE(XF_EMPTY_THIS_BUFFER)] = xa_mixer_empty_this_buffer, - [XF_OPCODE_TYPE(XF_FILL_THIS_BUFFER)] = xa_mixer_fill_this_buffer, - [XF_OPCODE_TYPE(XF_FLUSH)] = xa_mixer_flush, - - /* ...track control */ - [XF_OPCODE_TYPE(XF_PAUSE)] = xa_mixer_pause, - [XF_OPCODE_TYPE(XF_RESUME)] = xa_mixer_resume, -}; - -/* ...total number of commands supported */ -#define XA_MIXER_CMD_NUM (sizeof(xa_mixer_cmd) / sizeof(xa_mixer_cmd[0])) - -/******************************************************************************* - * Entry points - ******************************************************************************/ - -/* ...mixer termination-state command processor */ -static int xa_mixer_terminate(xf_component_t *component, xf_message_t *m) -{ - XAMixer *mixer = (XAMixer *) component; - u32 opcode = m->opcode; - - if (m == xf_output_port_control_msg(&mixer->output)) - { - /* ...output port flushing complete; mark port is idle and terminate */ - xf_output_port_flush_done(&mixer->output); - return -1; - } - else if (opcode == XF_FILL_THIS_BUFFER && xf_output_port_routed(&mixer->output)) - { - /* ...output buffer returned by the sink component; ignore and keep waiting */ - TRACE(OUTPUT, _b("collect output buffer")); - return 0; - } - else if (opcode == XF_UNREGISTER) - { - /* ...ignore subsequent unregister command/response */ - return 0; - } - else - { - /* ...everything else is responded with generic failure */ - xf_response_err(m); - return 0; - } -} - -/* ...mixer class destructor */ -static int xa_mixer_destroy(xf_component_t *component, xf_message_t *m) -{ - XAMixer *mixer = (XAMixer *) component; - u32 core = xf_component_core(component); - u32 i; - - /* ...destroy all inputs */ - for (i = 0; i < XA_MIXER_MAX_TRACK_NUMBER; i++) - { - xf_input_port_destroy(&mixer->track[i].input, core); - } - - /* ...destroy output port */ - xf_output_port_destroy(&mixer->output, core); - - /* ...destroy base object */ - xa_base_destroy(&mixer->base, XF_MM(sizeof(*mixer)), core); - - TRACE(INIT, _b("mixer[%p] destroyed"), mixer); - - return 0; -} - -/* ...mixer class first-stage destructor */ -static int xa_mixer_cleanup(xf_component_t *component, xf_message_t *m) -{ - XAMixer *mixer = (XAMixer *) component; - u32 i; - - /* ...complete message with error result code */ - xf_response_err(m); - - /* ...cancel internal scheduling message if needed */ - xa_base_cancel(&mixer->base); - - /* ...purge all input ports (specify "unregister"? - don't know yet - tbd) */ - for (i = 0; i < XA_MIXER_MAX_TRACK_NUMBER; i++) - { - xf_input_port_purge(&mixer->track[i].input); - } - - /* ...flush output port */ - if (xf_output_port_flush(&mixer->output, XF_FLUSH)) - { - /* ...flushing sequence is not needed; destroy mixer */ - return xa_mixer_destroy(component, NULL); - } - else - { - /* ...wait until output port is cleaned; adjust component hooks */ - component->entry = xa_mixer_terminate; - component->exit = xa_mixer_destroy; - - TRACE(INIT, _b("mixer[%p] cleanup sequence started"), mixer); - - /* ...indicate that second stage is required */ - return 1; - } -} - -/* ...mixer class factory */ -xf_component_t * xa_mixer_factory(u32 core, xa_codec_func_t process) -{ - XAMixer *mixer; - - /* ...construct generic audio component */ - XF_CHK_ERR(mixer = (XAMixer *)xa_base_factory(core, XF_MM(sizeof(*mixer)), process), NULL); - - /* ...set generic codec API */ - mixer->base.memtab = xa_mixer_memtab; - mixer->base.preprocess = xa_mixer_preprocess; - mixer->base.postprocess = xa_mixer_postprocess; - - /* ...set message-processing table */ - mixer->base.command = xa_mixer_cmd; - mixer->base.command_num = XA_MIXER_CMD_NUM; - - /* ...set component destructor hook */ - mixer->base.component.exit = xa_mixer_cleanup; - - TRACE(INIT, _b("Mixer[%p] created"), mixer); - - /* ...return handle to component */ - return (xf_component_t *) mixer; -} |