Steve Muckle | 0a9c087 | 2022-02-16 05:58:07 +0000 | [diff] [blame] | 1 | /******************************************************************************* |
| 2 | * Copyright (C) 2018 Cadence Design Systems, Inc. |
| 3 | * |
| 4 | * Permission is hereby granted, free of charge, to any person obtaining |
| 5 | * a copy of this software and associated documentation files (the |
| 6 | * "Software"), to use this Software with Cadence processor cores only and |
| 7 | * not with any other processors and platforms, subject to |
| 8 | * the following conditions: |
| 9 | * |
| 10 | * The above copyright notice and this permission notice shall be included |
| 11 | * in all copies or substantial portions of the Software. |
| 12 | * |
| 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
| 14 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| 15 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
| 16 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY |
| 17 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, |
| 18 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |
| 19 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| 20 | |
| 21 | ******************************************************************************/ |
| 22 | |
| 23 | /******************************************************************************* |
| 24 | * xa-class-base.c |
| 25 | * |
| 26 | * Generic audio codec task implementation |
| 27 | * |
| 28 | ******************************************************************************/ |
| 29 | |
| 30 | #define MODULE_TAG BASE |
| 31 | |
| 32 | /******************************************************************************* |
| 33 | * Includes |
| 34 | ******************************************************************************/ |
| 35 | |
| 36 | #include "xf.h" |
| 37 | #include "xa-class-base.h" |
| 38 | |
| 39 | /******************************************************************************* |
| 40 | * Tracing configuration |
| 41 | ******************************************************************************/ |
| 42 | |
| 43 | TRACE_TAG(INIT, 1); |
| 44 | TRACE_TAG(WARNING, 1); |
| 45 | TRACE_TAG(SETUP, 1); |
| 46 | TRACE_TAG(EXEC, 1); |
| 47 | |
| 48 | /******************************************************************************* |
| 49 | * Internal functions definitions |
| 50 | ******************************************************************************/ |
| 51 | |
| 52 | /* ...codec pre-initialization */ |
| 53 | static XA_ERRORCODE xa_base_preinit(XACodecBase *base, u32 core) |
| 54 | { |
| 55 | WORD32 n; |
| 56 | |
| 57 | /* ...codec must be empty */ |
| 58 | XF_CHK_ERR(base->state == 0, XA_API_FATAL_INVALID_CMD); |
| 59 | |
| 60 | /* ...get API structure size */ |
| 61 | XA_API(base, XA_API_CMD_GET_API_SIZE, 0, &n); |
| 62 | |
| 63 | /* ...allocate memory for codec API structure (4-bytes aligned) */ |
| 64 | XMALLOC(&base->api, n, 4, core); |
| 65 | |
| 66 | /* ...set default config parameters */ |
| 67 | XA_API(base, XA_API_CMD_INIT, XA_CMD_TYPE_INIT_API_PRE_CONFIG_PARAMS, NULL); |
| 68 | |
| 69 | /* ...get memory info tables size */ |
| 70 | if (XA_API(base, XA_API_CMD_GET_MEMTABS_SIZE, 0, &n), n != 0) |
| 71 | { |
| 72 | /* ...allocate memory for tables (4-bytes aligned) */ |
| 73 | XMALLOC(&base->mem_tabs, n, 4, core); |
| 74 | |
| 75 | /* ...set pointer for process memory tables */ |
| 76 | XA_API(base, XA_API_CMD_SET_MEMTABS_PTR, 0, base->mem_tabs.addr); |
| 77 | } |
| 78 | |
| 79 | TRACE(INIT, _b("Codec[%p] pre-initialization completed"), base); |
| 80 | |
| 81 | return XA_NO_ERROR; |
| 82 | } |
| 83 | |
| 84 | /* ...post-initialization setup */ |
| 85 | static XA_ERRORCODE xa_base_postinit(XACodecBase *base, u32 core) |
| 86 | { |
| 87 | WORD32 n, i; |
| 88 | |
| 89 | /* ...issue post-config command and determine the buffer requirements */ |
| 90 | XA_API(base, XA_API_CMD_INIT, XA_CMD_TYPE_INIT_API_POST_CONFIG_PARAMS, NULL); |
| 91 | |
| 92 | /* ...get number of memory tables required */ |
| 93 | XA_API(base, XA_API_CMD_GET_N_MEMTABS, 0, &n); |
| 94 | |
| 95 | /* ...set scratch buffer in advance (as codec not necessarily exposes it) */ |
| 96 | base->scratch = XF_CORE_DATA(core)->scratch; |
| 97 | |
| 98 | /* ...allocate memory buffers */ |
| 99 | for (i = 0; i < n; i++) |
| 100 | { |
| 101 | WORD32 size, align, type; |
| 102 | |
| 103 | TRACE(1, _b("i = %u (of %u)"), (u32)i, (u32)n); |
| 104 | |
| 105 | /* ...get memory type */ |
| 106 | XA_API(base, XA_API_CMD_GET_MEM_INFO_TYPE, i, &type); |
| 107 | |
| 108 | /* ...get memory size of i-th buffer */ |
| 109 | XA_API(base, XA_API_CMD_GET_MEM_INFO_SIZE, i, &size); |
| 110 | |
| 111 | /* ...get alignment */ |
| 112 | XA_API(base, XA_API_CMD_GET_MEM_INFO_ALIGNMENT, i, &align); |
| 113 | |
| 114 | /* ...process individual buffer */ |
| 115 | switch (type) |
| 116 | { |
| 117 | case XA_MEMTYPE_SCRATCH: |
| 118 | /* ...scratch memory is shared among all codecs; check its validity */ |
| 119 | XF_CHK_ERR(size <= XF_CFG_CODEC_SCRATCHMEM_SIZE, XA_API_FATAL_MEM_ALLOC); |
| 120 | |
| 121 | /* ...make sure alignment is valid */ |
| 122 | XF_CHK_ERR((XF_CFG_CODEC_SCRATCHMEM_ALIGN & (align - 1)) == 0, XA_API_FATAL_MEM_ALIGN); |
| 123 | |
| 124 | /* ...set the scratch memory pointer */ |
| 125 | XA_API(base, XA_API_CMD_SET_MEM_PTR, i, base->scratch); |
| 126 | |
| 127 | TRACE(INIT, _b("Mem tab %d: sz=%d al=%d ty=%d Scratch memory (%p)"), i, size, align, type, base->scratch); |
| 128 | |
| 129 | break; |
| 130 | |
| 131 | case XA_MEMTYPE_PERSIST: |
| 132 | /* ...allocate persistent memory */ |
| 133 | XMALLOC(&base->persist, size, align, core); |
| 134 | |
| 135 | /* ...and set the pointer instantly */ |
| 136 | XA_API(base, XA_API_CMD_SET_MEM_PTR, i, base->persist.addr); |
| 137 | |
| 138 | TRACE(INIT, _b("Mem tab %d: sz=%d al=%d ty=%d Persistent memory (%p)"), i, size, align, type, base->persist.addr); |
| 139 | |
| 140 | break; |
| 141 | |
| 142 | case XA_MEMTYPE_INPUT: |
| 143 | case XA_MEMTYPE_OUTPUT: |
| 144 | /* ...input/output buffer specification; pass to codec function */ |
| 145 | CODEC_API(base, memtab, i, type, size, align, core); |
| 146 | |
| 147 | break; |
| 148 | |
| 149 | default: |
| 150 | /* ...unrecognized memory type */ |
| 151 | TRACE(ERROR, _x("Invalid memory type: [%d]=(%u, %u, %u)"), i, type, size, align); |
| 152 | return XA_API_FATAL_INVALID_CMD_TYPE; |
| 153 | } |
| 154 | } |
| 155 | |
| 156 | TRACE(INIT, _b("Codec[%p] post-initialization completed (api:%p[%u])"), base, base->api.addr, base->api.size); |
| 157 | |
| 158 | return XA_NO_ERROR; |
| 159 | } |
| 160 | |
| 161 | /******************************************************************************* |
| 162 | * Commands processing |
| 163 | ******************************************************************************/ |
| 164 | |
| 165 | /* ...SET-PARAM processing (enabled in all states) */ |
| 166 | XA_ERRORCODE xa_base_set_param(XACodecBase *base, xf_message_t *m) |
| 167 | { |
| 168 | xf_set_param_msg_t *cmd = m->buffer; |
| 169 | xf_set_param_item_t *param = &cmd->item[0]; |
| 170 | WORD32 n, i; |
| 171 | |
| 172 | /* ...calculate total amount of parameters */ |
| 173 | n = m->length / sizeof(*param); |
| 174 | |
| 175 | /* ...check the message length is valid */ |
| 176 | XF_CHK_ERR(m->length == XF_SET_PARAM_CMD_LEN(n), XA_API_FATAL_INVALID_CMD_TYPE); |
| 177 | |
| 178 | /* ...apply all parameters; pass to codec-specific function */ |
| 179 | for (i = 0; i < n; i++) |
| 180 | { |
| 181 | TRACE(SETUP, _b("set-param[%p]: [%u]=%u"), base, param[i].id, param[i].value); |
| 182 | |
| 183 | if (base->setparam) |
| 184 | { |
| 185 | CODEC_API(base, setparam, param[i].id, ¶m[i].value); |
| 186 | } |
| 187 | else |
| 188 | { |
| 189 | XA_API(base, XA_API_CMD_SET_CONFIG_PARAM, param[i].id, ¶m[i].value); |
| 190 | } |
| 191 | } |
| 192 | |
| 193 | /* ...check if we need to do post-initialization */ |
| 194 | if ((base->state & XA_BASE_FLAG_POSTINIT) == 0) |
| 195 | { |
| 196 | /* ...do post-initialization step */ |
| 197 | XA_CHK(xa_base_postinit(base, XF_MSG_DST_CORE(m->id))); |
| 198 | |
| 199 | /* ...mark the codec static configuration is set */ |
| 200 | base->state ^= XA_BASE_FLAG_POSTINIT | XA_BASE_FLAG_RUNTIME_INIT; |
| 201 | } |
| 202 | |
| 203 | /* ...complete message processing; output buffer is empty */ |
| 204 | xf_response_ok(m); |
| 205 | |
| 206 | return XA_NO_ERROR; |
| 207 | } |
| 208 | |
| 209 | /* ...GET-PARAM message processing (enabled in all states) */ |
| 210 | XA_ERRORCODE xa_base_get_param(XACodecBase *base, xf_message_t *m) |
| 211 | { |
| 212 | xf_get_param_msg_t *cmd = m->buffer; |
| 213 | u32 *id = &cmd->c.id[0]; |
| 214 | u32 *value = &cmd->r.value[0]; |
| 215 | u32 n, i; |
| 216 | |
| 217 | /* ...calculate amount of parameters */ |
| 218 | n = m->length / sizeof(*id); |
| 219 | |
| 220 | /* ...check input parameter length */ |
| 221 | XF_CHK_ERR(XF_GET_PARAM_CMD_LEN(n) == m->length, XA_API_FATAL_INVALID_CMD_TYPE); |
| 222 | |
| 223 | /* ...retrieve the collection of codec parameters */ |
| 224 | for (i = 0; i < n; i++) |
| 225 | { |
| 226 | /* ...place the result into same location */ |
| 227 | if (base->getparam) |
| 228 | { |
| 229 | CODEC_API(base, getparam, id[i], &value[i]); |
| 230 | } |
| 231 | else |
| 232 | { |
| 233 | XA_API(base, XA_API_CMD_GET_CONFIG_PARAM, id[i], &value[i]); |
| 234 | } |
| 235 | } |
| 236 | |
| 237 | /* ...complete message specifying output buffer size */ |
| 238 | xf_response_data(m, XF_GET_PARAM_RSP_LEN(n)); |
| 239 | |
| 240 | return XA_NO_ERROR; |
| 241 | } |
| 242 | |
| 243 | /* ...SET-PARAM-EXT processing (enabled in all states) */ |
| 244 | XA_ERRORCODE xa_base_set_param_ext(XACodecBase *base, xf_message_t *m) |
| 245 | { |
| 246 | xf_ext_param_msg_t *cmd = m->buffer; |
| 247 | u16 length = m->length; |
| 248 | u16 remaining = (length + 3) & ~3; |
| 249 | u16 i; |
| 250 | |
| 251 | for (i = 0; TRACE_CFG(SETUP) && i < remaining; i += 16) |
| 252 | { |
| 253 | TRACE(SETUP, _b("[%03x]: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X"), |
| 254 | i, |
| 255 | ((u8 *)m->buffer)[i + 0], ((u8 *)m->buffer)[i + 1], |
| 256 | ((u8 *)m->buffer)[i + 2], ((u8 *)m->buffer)[i + 3], |
| 257 | ((u8 *)m->buffer)[i + 4], ((u8 *)m->buffer)[i + 5], |
| 258 | ((u8 *)m->buffer)[i + 6], ((u8 *)m->buffer)[i + 7], |
| 259 | ((u8 *)m->buffer)[i + 8], ((u8 *)m->buffer)[i + 9], |
| 260 | ((u8 *)m->buffer)[i + 10], ((u8 *)m->buffer)[i + 11], |
| 261 | ((u8 *)m->buffer)[i + 12], ((u8 *)m->buffer)[i + 13], |
| 262 | ((u8 *)m->buffer)[i + 14], ((u8 *)m->buffer)[i + 15]); |
| 263 | } |
| 264 | |
| 265 | /* ...process all parameters encapsulated in buffer */ |
| 266 | while (remaining >= sizeof(*cmd)) |
| 267 | { |
| 268 | u16 id = cmd->desc.id; |
| 269 | u16 dlen = cmd->desc.length; |
| 270 | u16 dsize = (dlen + 3) & ~3; |
| 271 | u16 pad = dlen & 3; |
| 272 | |
| 273 | /* ...cut-off descriptor header */ |
| 274 | remaining -= sizeof(*cmd); |
| 275 | |
| 276 | TRACE(SETUP, _b("remaining:%u, desc_size:%u"), (u32)remaining, (u32)dsize); |
| 277 | |
| 278 | /* ...make sure length is sufficient */ |
| 279 | XF_CHK_ERR(remaining >= dsize, XA_API_FATAL_INVALID_CMD_TYPE); |
| 280 | |
| 281 | /* ...pad remaining bytes with zeroes */ |
| 282 | (pad ? memset(cmd->data + dlen, 0, 4 - pad) : 0); |
| 283 | |
| 284 | 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]); |
| 285 | |
| 286 | /* ...apply parameter */ |
| 287 | XA_API(base, XA_API_CMD_SET_CONFIG_PARAM, id, cmd->data); |
| 288 | |
| 289 | /* ...move to next item (keep 4-bytes alignment for descriptor) */ |
| 290 | cmd = (xf_ext_param_msg_t *)(&cmd->data[0] + dsize), remaining -= dsize; |
| 291 | } |
| 292 | |
| 293 | /* ...check the message is fully processed */ |
| 294 | XF_CHK_ERR(remaining == 0, XA_API_FATAL_INVALID_CMD_TYPE); |
| 295 | |
| 296 | /* ...complete message processing; output buffer is empty */ |
| 297 | //xf_response_ok(m); |
| 298 | |
| 299 | /* ...unfortunately, it looks like a bug of the library that updates the memory |
| 300 | * and leaves it in a dirty state causing subsequent cache inconsistency - tbd |
| 301 | */ |
| 302 | xf_response_data(m, length); |
| 303 | |
| 304 | return XA_NO_ERROR; |
| 305 | } |
| 306 | |
| 307 | /* ...GET-PARAM-EXT message processing (enabled in all states) */ |
| 308 | XA_ERRORCODE xa_base_get_param_ext(XACodecBase *base, xf_message_t *m) |
| 309 | { |
| 310 | xf_ext_param_msg_t *cmd = m->buffer; |
| 311 | u32 length = m->length; |
| 312 | u32 remaining = (length + 3) & ~3; |
| 313 | int i; |
| 314 | |
| 315 | for (i = 0; TRACE_CFG(SETUP) && i < remaining; i += 16) |
| 316 | { |
| 317 | TRACE(SETUP, _b("[%03x]: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X"), |
| 318 | i, |
| 319 | ((u8 *)m->buffer)[i + 0], ((u8 *)m->buffer)[i + 1], |
| 320 | ((u8 *)m->buffer)[i + 2], ((u8 *)m->buffer)[i + 3], |
| 321 | ((u8 *)m->buffer)[i + 4], ((u8 *)m->buffer)[i + 5], |
| 322 | ((u8 *)m->buffer)[i + 6], ((u8 *)m->buffer)[i + 7], |
| 323 | ((u8 *)m->buffer)[i + 8], ((u8 *)m->buffer)[i + 9], |
| 324 | ((u8 *)m->buffer)[i + 10], ((u8 *)m->buffer)[i + 11], |
| 325 | ((u8 *)m->buffer)[i + 12], ((u8 *)m->buffer)[i + 13], |
| 326 | ((u8 *)m->buffer)[i + 14], ((u8 *)m->buffer)[i + 15]); |
| 327 | } |
| 328 | |
| 329 | /* ...process all parameters encapsulated in buffer */ |
| 330 | while (remaining >= sizeof(*cmd)) |
| 331 | { |
| 332 | u16 id = cmd->desc.id; |
| 333 | u16 len = cmd->desc.length; |
| 334 | u16 size = (len + 3) & ~3; |
| 335 | u8 pad = len & 3; |
| 336 | |
| 337 | /* ...cut-off command header */ |
| 338 | remaining -= sizeof(*cmd); |
| 339 | |
| 340 | /* ...make sure data buffer has sufficient length */ |
| 341 | XF_CHK_ERR(remaining >= size, XA_API_FATAL_INVALID_CMD_TYPE); |
| 342 | |
| 343 | /* ...retrieve parameter from buffer (care about alignment? - tbd) */ |
| 344 | XA_API(base, XA_API_CMD_GET_CONFIG_PARAM, id, cmd->data); |
| 345 | |
| 346 | /* ...pad remaininig bytes with zeroes */ |
| 347 | (pad ? memset(cmd->data + len, 0, 4 - pad) : 0); |
| 348 | |
| 349 | 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]); |
| 350 | |
| 351 | /* ...move to next item (alignment issues? - tbd) */ |
| 352 | cmd = (xf_ext_param_msg_t *)(&cmd->data[0] + size), remaining -= size; |
| 353 | } |
| 354 | |
| 355 | /* ...check the message is fully processed */ |
| 356 | XF_CHK_ERR(remaining == 0, XA_API_FATAL_INVALID_CMD_TYPE); |
| 357 | |
| 358 | /* ...complete message processing; output buffer has the same length */ |
| 359 | xf_response_data(m, length); |
| 360 | |
| 361 | return XA_NO_ERROR; |
| 362 | } |
| 363 | |
| 364 | /******************************************************************************* |
| 365 | * Command/data processing functions |
| 366 | ******************************************************************************/ |
| 367 | |
| 368 | /* ...generic codec data processing */ |
| 369 | static XA_ERRORCODE xa_base_process(XACodecBase *base) |
| 370 | { |
| 371 | XA_ERRORCODE error; |
| 372 | WORD32 done; |
| 373 | |
| 374 | /* ...clear internal scheduling flag */ |
| 375 | base->state &= ~XA_BASE_FLAG_SCHEDULE; |
| 376 | |
| 377 | /* ...codec-specific preprocessing (buffer maintenance) */ |
| 378 | if ((error = CODEC_API(base, preprocess)) != XA_NO_ERROR) |
| 379 | { |
| 380 | /* ...return non-fatal codec error */ |
| 381 | return error; |
| 382 | } |
| 383 | |
| 384 | /* ...execution step */ |
| 385 | if (base->state & XA_BASE_FLAG_RUNTIME_INIT) |
| 386 | { |
| 387 | /* ...kick initialization process */ |
| 388 | XA_API(base, XA_API_CMD_INIT, XA_CMD_TYPE_INIT_PROCESS, NULL); |
| 389 | |
| 390 | /* ...check if initialization is completed */ |
| 391 | XA_API(base, XA_API_CMD_INIT, XA_CMD_TYPE_INIT_DONE_QUERY, &done); |
| 392 | |
| 393 | TRACE(EXEC, _b("Initialization result: %d"), done); |
| 394 | |
| 395 | /* ...switch to execution state if required */ |
| 396 | (done ? base->state ^= XA_BASE_FLAG_RUNTIME_INIT | XA_BASE_FLAG_EXECUTION : 0); |
| 397 | } |
| 398 | else if (base->state & XA_BASE_FLAG_EXECUTION) |
| 399 | { |
| 400 | TRACE(1, _b("do exec")); |
| 401 | |
| 402 | /* ...execute decoding process */ |
| 403 | XA_API(base, XA_API_CMD_EXECUTE, XA_CMD_TYPE_DO_EXECUTE, NULL); |
| 404 | |
| 405 | /* ...check for end-of-stream condition */ |
| 406 | XA_API(base, XA_API_CMD_EXECUTE, XA_CMD_TYPE_DONE_QUERY, &done); |
| 407 | |
| 408 | TRACE(EXEC, _b("Execution result: %d"), done); |
| 409 | |
| 410 | /* ...mark the output path is done to release all queued buffers */ |
| 411 | (done ? base->state ^= XA_BASE_FLAG_EXECUTION | XA_BASE_FLAG_COMPLETED : 0); |
| 412 | } |
| 413 | |
| 414 | /* ...codec-specific buffer post-processing */ |
| 415 | return CODEC_API(base, postprocess, done); |
| 416 | } |
| 417 | |
| 418 | /* ...message-processing function (component entry point) */ |
| 419 | static int xa_base_command(xf_component_t *component, xf_message_t *m) |
| 420 | { |
| 421 | XACodecBase *base = (XACodecBase *) component; |
| 422 | u32 cmd; |
| 423 | |
| 424 | /* ...invoke data-processing function if message is null */ |
| 425 | if (m == NULL) |
| 426 | { |
| 427 | XF_CHK_ERR(!XA_ERROR_SEVERITY(xa_base_process(base)), -EPIPE); |
| 428 | return 0; |
| 429 | } |
| 430 | |
| 431 | /* ...process the command */ |
| 432 | TRACE(EXEC, _b("[%p]:state[%X]:(%X, %d, %p)"), base, base->state, m->opcode, m->length, m->buffer); |
| 433 | |
| 434 | /* ...bail out if this is forced termination command (I do have a map; maybe I'd better have a hook? - tbd) */ |
| 435 | if ((cmd = XF_OPCODE_TYPE(m->opcode)) == XF_OPCODE_TYPE(XF_UNREGISTER)) |
| 436 | { |
| 437 | TRACE(INIT, _b("force component[%p] termination"), base); |
| 438 | return -1; |
| 439 | } |
| 440 | |
| 441 | /* ...check opcode is valid */ |
| 442 | XF_CHK_ERR(cmd < base->command_num, -EINVAL); |
| 443 | |
| 444 | /* ...and has a hook */ |
| 445 | XF_CHK_ERR(base->command[cmd] != NULL, -EINVAL); |
| 446 | |
| 447 | /* ...pass control to specific command */ |
| 448 | XF_CHK_ERR(!XA_ERROR_SEVERITY(base->command[cmd](base, m)), -EPIPE); |
| 449 | |
| 450 | /* ...execution completed successfully */ |
| 451 | return 0; |
| 452 | } |
| 453 | |
| 454 | /******************************************************************************* |
| 455 | * Base codec API |
| 456 | ******************************************************************************/ |
| 457 | |
| 458 | /* ...data processing scheduling */ |
| 459 | void xa_base_schedule(XACodecBase *base, u32 dts) |
| 460 | { |
| 461 | if ((base->state & XA_BASE_FLAG_SCHEDULE) == 0) |
| 462 | { |
| 463 | /* ...schedule component task execution */ |
| 464 | xf_component_schedule(&base->component, dts); |
| 465 | |
| 466 | /* ...and put scheduling flag */ |
| 467 | base->state ^= XA_BASE_FLAG_SCHEDULE; |
| 468 | } |
| 469 | else |
| 470 | { |
| 471 | TRACE(EXEC, _b("codec[%p] processing pending"), base); |
| 472 | } |
| 473 | } |
| 474 | |
| 475 | /* ...cancel data processing */ |
| 476 | void xa_base_cancel(XACodecBase *base) |
| 477 | { |
| 478 | if (base->state & XA_BASE_FLAG_SCHEDULE) |
| 479 | { |
| 480 | /* ...cancel scheduled codec task */ |
| 481 | xf_component_cancel(&base->component); |
| 482 | |
| 483 | /* ...and clear scheduling flag */ |
| 484 | base->state ^= XA_BASE_FLAG_SCHEDULE; |
| 485 | |
| 486 | TRACE(EXEC, _b("codec[%p] processing cancelled"), base); |
| 487 | } |
| 488 | } |
| 489 | |
| 490 | /* ...base codec destructor */ |
| 491 | void xa_base_destroy(XACodecBase *base, u32 size, u32 core) |
| 492 | { |
| 493 | /* ...deallocate all resources */ |
| 494 | xf_mm_free_buffer(&base->persist, core); |
| 495 | xf_mm_free_buffer(&base->mem_tabs, core); |
| 496 | xf_mm_free_buffer(&base->api, core); |
| 497 | |
| 498 | /* ...destroy codec structure (and task) itself */ |
| 499 | xf_mem_free(base, size, core, 0); |
| 500 | |
| 501 | TRACE(INIT, _b("codec[%p]:%u destroyed"), base, core); |
| 502 | } |
| 503 | |
| 504 | /* ...generic codec initialization routine */ |
| 505 | XACodecBase * xa_base_factory(u32 core, u32 size, xa_codec_func_t process) |
| 506 | { |
| 507 | XACodecBase *base; |
| 508 | |
| 509 | /* ...make sure the size is valid */ |
| 510 | XF_CHK_ERR(size >= sizeof(XACodecBase), NULL); |
| 511 | |
| 512 | /* ...allocate local memory for codec structure */ |
| 513 | XF_CHK_ERR(base = xf_mem_alloc(size, 0, core, 0), NULL); |
| 514 | |
| 515 | /* ...reset codec memory */ |
| 516 | memset(base, 0, size); |
| 517 | |
| 518 | /* ...set low-level codec API function */ |
| 519 | base->process = process; |
| 520 | |
| 521 | /* ...set message processing function */ |
| 522 | base->component.entry = xa_base_command; |
| 523 | |
| 524 | /* ...do basic initialization */ |
| 525 | if (xa_base_preinit(base, core) != XA_NO_ERROR) |
| 526 | { |
| 527 | /* ...initialization failed for some reason; do cleanup */ |
| 528 | xa_base_destroy(base, size, core); |
| 529 | |
| 530 | return NULL; |
| 531 | } |
| 532 | |
| 533 | /* ...initialization completed successfully */ |
| 534 | TRACE(INIT, _b("Codec[%p]:%u initialized"), base, core); |
| 535 | |
| 536 | return base; |
| 537 | } |