You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
538 lines
18 KiB
538 lines
18 KiB
/*******************************************************************************
|
|
* 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 valid */
|
|
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 valid */
|
|
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 valid */
|
|
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;
|
|
}
|