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.
729 lines
22 KiB
729 lines
22 KiB
/*
|
|
* Copyright (c) Hisilicon Technologies Co., Ltd. 2012-2019. All rights reserved.
|
|
* Description: IEC61937 data parser function
|
|
* Author: audio
|
|
* Create: 2012-05-30
|
|
*/
|
|
|
|
#include <string.h>
|
|
|
|
#include "mpi_ai_debug.h"
|
|
|
|
#include "iec61937_parser.h"
|
|
|
|
#include "soc_math.h"
|
|
#include "mpi_memory_ext.h"
|
|
#include "mpi_system_ext.h"
|
|
#include "securec.h"
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif /* __cplusplus */
|
|
|
|
static td_void ai_free(td_void *buf)
|
|
{
|
|
if (buf == TD_NULL) {
|
|
return;
|
|
}
|
|
|
|
free(buf);
|
|
}
|
|
|
|
static td_void *ai_malloc(td_u32 size)
|
|
{
|
|
td_s32 ret;
|
|
td_void *buf = TD_NULL;
|
|
|
|
if (size == 0) {
|
|
soc_log_err("invalid size\n");
|
|
return TD_NULL;
|
|
}
|
|
|
|
buf = malloc(size);
|
|
if (buf == TD_NULL) {
|
|
soc_log_err("call malloc( failed\n");
|
|
return TD_NULL;
|
|
}
|
|
|
|
ret = memset_s(buf, size, 0, size);
|
|
if (ret != EOK) {
|
|
soc_err_print_call_fun_err(memset_s, ret);
|
|
free(buf);
|
|
return TD_NULL;
|
|
}
|
|
|
|
return buf;
|
|
}
|
|
|
|
/* when sync not found, return pos = (bytes - 3) */
|
|
static td_bool iec61937_parser_find_sync_word(const td_u8 *buf, td_u32 bytes, td_u32 *pos, td_bool *dtscd)
|
|
{
|
|
td_u32 state;
|
|
td_u32 i;
|
|
td_bool big_endian = TD_FALSE;
|
|
|
|
/* find IEC SYNC */
|
|
for (i = 0; i < (bytes - 3); i++) { /* 3 is a number */
|
|
state = (buf[i] << 24) | (buf[i + 1] << 16) | /* 24 and 16 is shift number */
|
|
(buf[i + 2] << 8) | buf[i + 3]; /* 8 is a shift number, 2 and 3 is serial number */
|
|
if ((state == IEC61937_SYNCWORD_LE) || (state == IEC61937_SYNCWORD_BE)) {
|
|
big_endian = (state == IEC61937_SYNCWORD_BE) ? TD_TRUE : TD_FALSE;
|
|
*dtscd = TD_FALSE;
|
|
*pos = i;
|
|
return big_endian;
|
|
}
|
|
}
|
|
|
|
/* find DTSCD */
|
|
for (i = 0; i < (bytes - 3); i++) { /* 3 is a number */
|
|
state = (buf[i] << 24) | (buf[i + 1] << 16) | /* 24 and 16 is shift number */
|
|
(buf[i + 2] << 8) | buf[i + 3]; /* 8 is a shift number, 2 and 3 is serial number */
|
|
if ((state == DCA_MARKER_RAW_BE) || (state == DCA_MARKER_RAW_LE) ||
|
|
(state == DCA_MARKER_14B_BE) || (state == DCA_MARKER_14B_LE)) {
|
|
*dtscd = TD_TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
*pos = i;
|
|
|
|
return big_endian;
|
|
}
|
|
|
|
static td_void iec61937_parser_get_frame_len(iec61937_parser_stream_type stream_type,
|
|
const td_u16 *buf, td_u32 *bytes)
|
|
{
|
|
td_u32 frame_len = 0;
|
|
|
|
switch (stream_type) {
|
|
case IEC61937_PARSER_STREAM_DD:
|
|
frame_len = buf[3] >> 3; /* 3 is a shift number */
|
|
break;
|
|
case IEC61937_PARSER_STREAM_DDP:
|
|
frame_len = buf[3]; /* 3 is a number */
|
|
break;
|
|
case IEC61937_PARSER_STREAM_DTS:
|
|
frame_len = buf[3] >> 3; /* 3 is a shift number */
|
|
frame_len = ((frame_len + 3) >> 2) << 2; /* 2 is a shift number, 3 is a number */
|
|
break;
|
|
case IEC61937_PARSER_STREAM_DTSHD:
|
|
frame_len = buf[9]; /* 9 is a number */
|
|
frame_len = ((frame_len + 3) >> 2) << 2; /* 2 is a shift number, 3 is a number */
|
|
break;
|
|
case IEC61937_PARSER_STREAM_MAT:
|
|
frame_len = buf[3]; /* 3 is a number */
|
|
break;
|
|
default:
|
|
soc_log_err("invalid iec61937 stream type!\n");
|
|
break;
|
|
}
|
|
|
|
*bytes = frame_len;
|
|
}
|
|
|
|
static td_void iec61937_parser_move_buf_to_head(iec61937_parser_state *state, const td_u8 *src_buf)
|
|
{
|
|
td_s32 ret;
|
|
ret = memmove_s(state->buffer, IEC61937_PARSER_LENGTH_MAX, src_buf, state->filled_len);
|
|
if (ret != EOK) {
|
|
soc_log_err("memmove_s failed,err = 0x%x\n", ret);
|
|
return;
|
|
}
|
|
|
|
state->free_len = state->alloc_len - state->filled_len;
|
|
}
|
|
|
|
static td_s32 iec61937_parser_build_burst_info_default(iec61937_parser_state *state, const td_u8 *src_buf,
|
|
td_u32 data_type)
|
|
{
|
|
state->filled_len -= LENGTH_OF_PA_AND_PB;
|
|
|
|
iec61937_parser_move_buf_to_head(state, src_buf + LENGTH_OF_PA_AND_PB);
|
|
soc_log_err("invalid IEC61937 data type!\n");
|
|
soc_err_print_u32(data_type);
|
|
if (data_type == IEC61937_DATATYPE_NULL) {
|
|
return SOC_ERR_AI_BITS_INVALID_DATA;
|
|
} else if (data_type == IEC61937_DATATYPE_PAUSE) {
|
|
return SOC_ERR_AI_BITS_PAUSE_DATA;
|
|
}
|
|
|
|
return SOC_ERR_AI_PARSERBUF_EMPTY;
|
|
}
|
|
|
|
static const struct {
|
|
td_u32 data_type;
|
|
const td_char *str;
|
|
td_u32 stream_type;
|
|
td_u32 len;
|
|
} g_iec61937_parser[] = {
|
|
{ IEC61937_DATATYPE_AC3, "IEC61937_DATATYPE_AC3", IEC61937_PARSER_STREAM_DD, BITS_BURSTLENGTH_AC3 },
|
|
{ IEC61937_DATATYPE_EAC3, "IEC61937_DATATYPE_EAC3", IEC61937_PARSER_STREAM_DDP, BITS_BURSTLENGTH_EAC3 },
|
|
{ IEC61937_DATATYPE_DTS_TYPE_I, "IEC61937_DATATYPE_DTS_TYPE_I",
|
|
IEC61937_PARSER_STREAM_DTS, BITS_BURSTLENGTH_DTS_TYPE_I },
|
|
{ IEC61937_DATATYPE_DTS_TYPE_II, "IEC61937_DATATYPE_DTS_TYPE_II",
|
|
IEC61937_PARSER_STREAM_DTS, BITS_BURSTLENGTH_DTS_TYPE_II },
|
|
{ IEC61937_DATATYPE_DTS_TYPE_III, "IEC61937_DATATYPE_DTS_TYPE_III",
|
|
IEC61937_PARSER_STREAM_DTS, BITS_BURSTLENGTH_DTS_TYPE_III },
|
|
{ IEC61937_DATATYPE_MAT, "IEC61937_DATATYPE_MAT", IEC61937_PARSER_STREAM_MAT, BITS_BURSTLENGTH_MAT },
|
|
};
|
|
|
|
static td_s32 iec61937_parser_build_burst_info(iec61937_parser_state *state, td_u8 *src_buf)
|
|
{
|
|
/* data type: value of PC bit 0-4 */
|
|
td_u32 data_type = (td_u16)src_buf[4] & 0x1f; /* 4 is a serial number */
|
|
td_u32 i;
|
|
|
|
for (i = 0; i < (sizeof(g_iec61937_parser) / sizeof(g_iec61937_parser[0])); i++) {
|
|
if (data_type == g_iec61937_parser[i].data_type) {
|
|
soc_log_dbg("g_iec61937_parser[%d].data_type %s!\n", i, g_iec61937_parser[i].str);
|
|
state->stream_type = g_iec61937_parser[i].stream_type;
|
|
state->burst_len = g_iec61937_parser[i].len;
|
|
return TD_SUCCESS;
|
|
}
|
|
}
|
|
|
|
if (data_type == IEC61937_DATATYPE_DTS_TYPE_IV) {
|
|
soc_log_dbg("IEC61937_DATATYPE_DTS_TYPE_IV\n");
|
|
state->stream_type = IEC61937_PARSER_STREAM_DTSHD;
|
|
state->burst_len = (BITS_BURSTLENGTH_DTS_TYPE_I << ((td_u16)src_buf[5] & 0x7)); /* 5 is a serial number */
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
return iec61937_parser_build_burst_info_default(state, src_buf, data_type);
|
|
}
|
|
|
|
static td_s32 iec61937_parser_continual_dtscd(iec61937_parser_state *state)
|
|
{
|
|
td_bool dtscd = TD_FALSE;
|
|
td_u32 sync_skip = 0;
|
|
|
|
if (state->stream_type != IEC61937_PARSER_STREAM_DTS) {
|
|
if (state->filled_len < BITS_BURSTLENGTH_DTSCD + IEC61937_PARSER_LENGTH_MIN) {
|
|
return SOC_ERR_AI_PARSERBUF_EMPTY;
|
|
}
|
|
|
|
(td_void)iec61937_parser_find_sync_word(state->buffer + BITS_BURSTLENGTH_DTSCD,
|
|
state->filled_len - BITS_BURSTLENGTH_DTSCD, &sync_skip, &dtscd);
|
|
if ((sync_skip != 0) || (dtscd != TD_TRUE)) {
|
|
state->filled_len -= (BITS_BURSTLENGTH_DTSCD + sync_skip);
|
|
state->total_discard_len += (BITS_BURSTLENGTH_DTSCD + sync_skip);
|
|
iec61937_parser_move_buf_to_head(state, state->buffer + BITS_BURSTLENGTH_DTSCD + sync_skip);
|
|
return SOC_ERR_AI_PARSERBUF_EMPTY;
|
|
}
|
|
}
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
static td_bool iec61937_check_is_empty_frame(const td_u8 *buffer, td_u32 size)
|
|
{
|
|
td_u32 i;
|
|
for (i = 0; i < size; i++) {
|
|
if (*(buffer + i) != 0) {
|
|
return TD_FALSE;
|
|
}
|
|
}
|
|
return TD_TRUE;
|
|
}
|
|
|
|
static td_s32 iec61937_parser_handup_dtscd(iec61937_parser_state *state)
|
|
{
|
|
td_s32 ret;
|
|
|
|
soc_log_dbg("IEC61937_DATATYPE_DTSCD\n");
|
|
ret = iec61937_parser_continual_dtscd(state);
|
|
if (ret != TD_SUCCESS) {
|
|
soc_log_warn("iec61937_parser_continual_dtscd failed\n");
|
|
soc_err_print_err_code(ret);
|
|
return ret;
|
|
}
|
|
|
|
state->burst_len = BITS_BURSTLENGTH_DTSCD;
|
|
state->stream_type = IEC61937_PARSER_STREAM_DTS;
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
static td_s32 iec61937_parser_avoid_handup_dtscd(iec61937_parser_state *state)
|
|
{
|
|
td_s32 ret;
|
|
td_u32 cur_sys_time_ms;
|
|
|
|
/* avoid handup when getframelen */
|
|
if (state->filled_len < LENGTH_OF_PREAMBLE + DTSHD_HEADER_SIZE) {
|
|
ext_mpi_sys_get_time_stamp_ms(&cur_sys_time_ms);
|
|
if (state->first_empty_time == 0) {
|
|
state->first_empty_time = cur_sys_time_ms;
|
|
}
|
|
|
|
if (state->total_discard_len >= IEC61937_PARSER_LENGTH_MAX * 2) { /* 2 is a number */
|
|
return SOC_ERR_AI_FIND_SYNC_FAILED;
|
|
} else if (cur_sys_time_ms > state->first_empty_time + 1000) { /* 1000 means 1 second */
|
|
return SOC_ERR_AI_BITS_INVALID_DATA;
|
|
} else {
|
|
return SOC_ERR_AI_PARSERBUF_EMPTY;
|
|
}
|
|
}
|
|
|
|
ret = iec61937_parser_build_burst_info(state, state->buffer);
|
|
if (ret != TD_SUCCESS) {
|
|
soc_log_err("iec61937_parser_build_burst_info failed\n");
|
|
soc_err_print_err_code(ret);
|
|
return ret;
|
|
}
|
|
|
|
if (state->stream_type != IEC61937_PARSER_STREAM_MAT) {
|
|
state->big_endian = TD_FALSE; /* only for turehd or mat */
|
|
}
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
static td_s32 iec61937_parser_build_burst_data(iec61937_parser_state *state, td_bool *dtscd)
|
|
{
|
|
td_s32 ret;
|
|
td_u32 sync_skip = 0;
|
|
|
|
state->big_endian = iec61937_parser_find_sync_word(state->buffer, state->filled_len, &sync_skip, dtscd);
|
|
|
|
if (sync_skip != 0) {
|
|
state->filled_len -= sync_skip;
|
|
state->total_discard_len += sync_skip;
|
|
iec61937_parser_move_buf_to_head(state, state->buffer + sync_skip);
|
|
}
|
|
|
|
if (*dtscd == TD_TRUE) {
|
|
ret = iec61937_parser_handup_dtscd(state);
|
|
if (ret != TD_SUCCESS) {
|
|
return ret;
|
|
}
|
|
} else {
|
|
/* avoid handup when getframelen */
|
|
ret = iec61937_parser_avoid_handup_dtscd(state);
|
|
if (ret != TD_SUCCESS) {
|
|
soc_log_warn("iec61937_parser_handup_dtscd failed\n");
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
/* if successfully find sync, reset first_empty_time */
|
|
state->first_empty_time = 0;
|
|
state->total_discard_len = 0;
|
|
|
|
/* ensure release frame including the stuffing */
|
|
if (state->filled_len < state->burst_len) {
|
|
soc_log_warn("state->filled_len < state->burst_len\n");
|
|
soc_warn_print_u32(state->filled_len);
|
|
soc_warn_print_u32(state->burst_len);
|
|
return SOC_ERR_AI_PARSERBUF_EMPTY;
|
|
}
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
#define IEC61937_PARSER_MAX_TIMES 150
|
|
|
|
static td_s32 iec61937_parser_build_burst_data_inner(iec61937_parser_state *state, td_bool *dtscd)
|
|
{
|
|
td_s32 ret;
|
|
td_u32 i;
|
|
|
|
ret = iec61937_parser_build_burst_data(state, dtscd);
|
|
/* PAUSE data should be consumed timely. */
|
|
if (ret == SOC_ERR_AI_BITS_PAUSE_DATA) {
|
|
for (i = 0; i < IEC61937_PARSER_MAX_TIMES; i++) {
|
|
ret = iec61937_parser_build_burst_data(state, dtscd);
|
|
if ((ret == TD_SUCCESS) || (ret == SOC_ERR_AI_PARSERBUF_EMPTY)) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (ret != TD_SUCCESS) {
|
|
soc_warn_print_call_fun_err(iec61937_parser_build_burst_data, ret);
|
|
return ret;
|
|
}
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
static td_u32 iec61937_calc_frame_size(td_u32 ch, td_u32 bit_depth)
|
|
{
|
|
switch (bit_depth) {
|
|
case EXT_BIT_DEPTH_16:
|
|
return ch * sizeof(td_u16);
|
|
case EXT_BIT_DEPTH_24:
|
|
return ch * sizeof(td_u32);
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
td_s32 iec61937_parser_create(ext_parser_handle *parser)
|
|
{
|
|
iec61937_parser_state *state = TD_NULL;
|
|
|
|
check_ai_null_ptr(parser);
|
|
|
|
state = (iec61937_parser_state *)ai_malloc(sizeof(iec61937_parser_state));
|
|
if (state == TD_NULL) {
|
|
soc_log_err("malloc parser instance failed\n");
|
|
return SOC_ERR_AI_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
state->buffer = (td_u8 *)ai_malloc(IEC61937_PARSER_LENGTH_MAX);
|
|
if (state->buffer == TD_NULL) {
|
|
soc_log_err("malloc parser inner buffer failed\n");
|
|
ai_free(state);
|
|
return SOC_ERR_AI_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
state->free_len = IEC61937_PARSER_LENGTH_MAX;
|
|
state->alloc_len = IEC61937_PARSER_LENGTH_MAX;
|
|
state->stream_type = IEC61937_PARSER_STREAM_TYPE_MAX;
|
|
|
|
*parser = (ext_parser_handle)state;
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
td_void iec61937_parser_destroy(ext_parser_handle parser)
|
|
{
|
|
iec61937_parser_state *state = (iec61937_parser_state *)parser;
|
|
|
|
if (state == TD_NULL) {
|
|
return;
|
|
}
|
|
|
|
if (state->buffer != TD_NULL) {
|
|
/* no need to set state->buffer to NULL, because state is going to be free next */
|
|
ai_free(state->buffer);
|
|
}
|
|
|
|
ai_free(state);
|
|
}
|
|
|
|
td_s32 iec61937_parser_get_buf(ext_parser_handle parser, td_u32 request_size, iec61937_parser_stream_buf *stream)
|
|
{
|
|
iec61937_parser_state *state = TD_NULL_PTR;
|
|
td_u32 actual_req_size;
|
|
td_u32 frame_size;
|
|
|
|
check_ai_null_ptr(parser);
|
|
check_ai_null_ptr(stream);
|
|
|
|
state = (iec61937_parser_state *)parser;
|
|
|
|
stream->size = 0;
|
|
|
|
if (request_size == 0) {
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
frame_size = iec61937_calc_frame_size(state->channel, state->bit_depth);
|
|
if (frame_size == 0) {
|
|
soc_log_err("invalid parameter!\n");
|
|
soc_err_print_u32(state->channel);
|
|
soc_err_print_u32(state->bit_depth);
|
|
return SOC_ERR_AI_INVALID_PARA;
|
|
}
|
|
|
|
/* ensure actual_req_size - filled_len is aligned with frame_size */
|
|
actual_req_size = request_size;
|
|
if ((state->stream_type == IEC61937_PARSER_STREAM_PCM) ||
|
|
(state->stream_type == IEC61937_PARSER_STREAM_UNKNOWN) ||
|
|
(state->stream_type == IEC61937_PARSER_STREAM_TYPE_MAX)) {
|
|
actual_req_size += (state->filled_len % frame_size);
|
|
}
|
|
|
|
if (actual_req_size > IEC61937_PARSER_LENGTH_MAX) {
|
|
soc_log_err("request_size is too big!\n");
|
|
soc_err_print_u32(request_size);
|
|
soc_err_print_u32(actual_req_size);
|
|
return SOC_ERR_AI_INVALID_PARA;
|
|
}
|
|
|
|
if (request_size > state->filled_len) {
|
|
stream->data = state->buffer + state->filled_len;
|
|
stream->size = actual_req_size - state->filled_len;
|
|
}
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
td_s32 iec61937_parser_put_buf(ext_parser_handle parser, iec61937_parser_stream_buf *stream)
|
|
{
|
|
iec61937_parser_state *state = TD_NULL_PTR;
|
|
|
|
check_ai_null_ptr(parser);
|
|
check_ai_null_ptr(stream);
|
|
check_ai_null_ptr(stream->data);
|
|
|
|
if (stream->size == 0) {
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
state = (iec61937_parser_state *)parser;
|
|
|
|
if (stream->size > state->free_len) {
|
|
soc_log_err("size is bigger then free_len\n");
|
|
soc_err_print_u32(stream->size);
|
|
soc_err_print_u32(state->free_len);
|
|
return SOC_ERR_AI_INVALID_PARA;
|
|
}
|
|
|
|
state->free_len -= stream->size;
|
|
state->filled_len += stream->size;
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
static inline td_u16 swapbit_16(td_u16 x)
|
|
{
|
|
td_u16 res = (x >> 8) | (x << 8); /* shift right 8 bits, shift left 8 bits */
|
|
return res;
|
|
}
|
|
|
|
static td_void big_endian2_little_endian(td_u8 *io, td_s32 bytes)
|
|
{
|
|
td_s32 i;
|
|
td_u16 *data = (td_u16 *)io;
|
|
td_u16 pcm_data;
|
|
|
|
for (i = 0; i < bytes / 2; i++) { /* 2 is a number */
|
|
pcm_data = *data;
|
|
*data++ = swapbit_16(pcm_data);
|
|
}
|
|
}
|
|
|
|
static td_void iec61937_parser_acquire_dtscd_frame(iec61937_parser_state *state)
|
|
{
|
|
state->frame_buf = state->buffer;
|
|
state->frame_len = BITS_BURSTLENGTH_DTSCD;
|
|
}
|
|
|
|
static td_s32 iec61937_parser_acquire_mat_frame(iec61937_parser_state *state)
|
|
{
|
|
state->frame_buf = state->buffer;
|
|
state->frame_len = BITS_BURSTLENGTH_MAT;
|
|
|
|
if (state->filled_len < state->frame_len) {
|
|
soc_log_warn("frame_len < filled_len");
|
|
soc_warn_print_u32(state->frame_len);
|
|
soc_warn_print_u32(state->filled_len);
|
|
return SOC_ERR_AI_PARSERBUF_EMPTY;
|
|
}
|
|
|
|
if (state->big_endian == TD_TRUE) {
|
|
big_endian2_little_endian(state->buffer, BITS_BURSTLENGTH_MAT);
|
|
}
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
static td_s32 iec61937_parser_acquire_other_frame(iec61937_parser_state *state)
|
|
{
|
|
iec61937_parser_get_frame_len(state->stream_type, (td_u16 *)state->buffer, &state->frame_len);
|
|
|
|
if ((state->frame_len == 0) || (state->frame_len > BITS_BURSTLENGTH_MAT)) {
|
|
state->filled_len -= LENGTH_OF_PA_AND_PB;
|
|
iec61937_parser_move_buf_to_head(state, state->buffer + LENGTH_OF_PA_AND_PB);
|
|
soc_log_err("invalid frame_len!\n");
|
|
soc_err_print_u32(state->frame_len);
|
|
return SOC_ERR_AI_BITS_INVALID_DATA;
|
|
}
|
|
|
|
if (state->filled_len < state->frame_len) {
|
|
soc_log_warn("frame_len < filled_len\n");
|
|
soc_warn_print_u32(state->frame_len);
|
|
soc_warn_print_u32(state->filled_len);
|
|
return SOC_ERR_AI_PARSERBUF_EMPTY;
|
|
}
|
|
|
|
if ((state->stream_type == IEC61937_PARSER_STREAM_DTSHD) || (state->stream_type == IEC61937_PARSER_STREAM_MAT)) {
|
|
state->frame_buf = state->buffer + LENGTH_OF_PREAMBLE + DTSHD_HEADER_SIZE;
|
|
} else {
|
|
state->frame_buf = state->buffer + LENGTH_OF_PREAMBLE;
|
|
}
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
td_s32 iec61937_parser_acquire_frame(ext_parser_handle parser, td_void *dst_buf, td_u32 *frame_len)
|
|
{
|
|
td_s32 ret;
|
|
td_bool dtscd = TD_FALSE;
|
|
td_u8 **pp_dst_buf = TD_NULL_PTR;
|
|
iec61937_parser_state *state = TD_NULL_PTR;
|
|
|
|
check_ai_null_ptr(parser);
|
|
check_ai_null_ptr(dst_buf);
|
|
check_ai_null_ptr(frame_len);
|
|
|
|
state = (iec61937_parser_state *)parser;
|
|
|
|
pp_dst_buf = (td_u8 **)dst_buf;
|
|
|
|
/* avoid acquire frame much times without release frame */
|
|
if (state->frame_is_ready == TD_TRUE) {
|
|
soc_log_warn("call iec61937_parser_acquire_frame continuously many times!\n");
|
|
*pp_dst_buf = state->frame_buf;
|
|
*frame_len = state->frame_len;
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
*frame_len = 0; /* avoid acquire fail and do release */
|
|
|
|
if ((state->filled_len < IEC61937_PARSER_LENGTH_MIN) || (state->filled_len > IEC61937_PARSER_LENGTH_MAX)) {
|
|
soc_log_warn("state->filled_len is not fit!\n");
|
|
soc_warn_print_u32(state->filled_len);
|
|
return SOC_ERR_AI_PARSERBUF_EMPTY;
|
|
}
|
|
|
|
ret = iec61937_parser_build_burst_data_inner(state, &dtscd);
|
|
if (ret != TD_SUCCESS) {
|
|
soc_log_warn("iec61937_parser_build_burst_data_inner failed\n");
|
|
soc_warn_print_h32(ret);
|
|
return ret;
|
|
}
|
|
|
|
check_ai_null_ptr(state->buffer);
|
|
|
|
if (dtscd == TD_TRUE) {
|
|
iec61937_parser_acquire_dtscd_frame(state);
|
|
} else if (state->stream_type == IEC61937_PARSER_STREAM_MAT) {
|
|
ret = iec61937_parser_acquire_mat_frame(state);
|
|
if (ret != TD_SUCCESS) {
|
|
return ret;
|
|
}
|
|
} else {
|
|
ret = iec61937_parser_acquire_other_frame(state);
|
|
if (ret != TD_SUCCESS) {
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
*pp_dst_buf = state->frame_buf;
|
|
*frame_len = state->frame_len;
|
|
state->frame_is_ready = TD_TRUE;
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
td_s32 iec61937_parser_release_frame(ext_parser_handle parser, td_u32 frame_len)
|
|
{
|
|
iec61937_parser_state *state = TD_NULL_PTR;
|
|
|
|
check_ai_null_ptr(parser);
|
|
|
|
if (frame_len == 0) {
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
state = (iec61937_parser_state *)parser;
|
|
|
|
/* avoid release frame much times without acquire frame */
|
|
if (state->frame_is_ready == TD_FALSE) {
|
|
soc_log_warn("call iec61937_parser_release_frame continuously many times!");
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
if (state->filled_len < state->burst_len) {
|
|
soc_log_err("filled_len < burst_len, release failed!");
|
|
soc_err_print_u32(state->filled_len);
|
|
soc_err_print_u32(state->burst_len);
|
|
return SOC_ERR_AI_INVALID_PARA;
|
|
}
|
|
|
|
state->frame_is_ready = TD_FALSE;
|
|
state->filled_len -= state->burst_len;
|
|
|
|
iec61937_parser_move_buf_to_head(state, state->buffer + state->burst_len);
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
td_s32 iec61937_parser_get_stream_type(ext_parser_handle parser, iec61937_parser_stream_type *stream_type)
|
|
{
|
|
td_s32 ret;
|
|
td_bool dtscd = TD_FALSE;
|
|
iec61937_parser_state *state = TD_NULL_PTR;
|
|
|
|
check_ai_null_ptr(parser);
|
|
check_ai_null_ptr(stream_type);
|
|
|
|
state = (iec61937_parser_state *)parser;
|
|
|
|
*stream_type = state->stream_type;
|
|
|
|
if ((state->stream_type != IEC61937_PARSER_STREAM_UNKNOWN) &&
|
|
(state->stream_type != IEC61937_PARSER_STREAM_TYPE_MAX)) {
|
|
*stream_type = state->stream_type;
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
if ((state->filled_len < IEC61937_PARSER_LENGTH_MIN) ||
|
|
(state->filled_len > IEC61937_PARSER_LENGTH_MAX)) {
|
|
soc_log_warn("state->filled_len is not fit!\n");
|
|
soc_warn_print_u32(state->filled_len);
|
|
return SOC_ERR_AI_PARSERBUF_EMPTY;
|
|
}
|
|
|
|
ret = iec61937_parser_build_burst_data_inner(state, &dtscd);
|
|
if (ret != TD_SUCCESS) {
|
|
soc_log_warn("iec61937_parser_build_burst_data_inner failed\n");
|
|
soc_err_print_err_code(ret);
|
|
return ret;
|
|
}
|
|
|
|
*stream_type = state->stream_type;
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
td_s32 iec61937_parser_get_burst_len(ext_parser_handle parser, td_u32 *burst_len)
|
|
{
|
|
iec61937_parser_state *state = TD_NULL_PTR;
|
|
|
|
check_ai_null_ptr(parser);
|
|
check_ai_null_ptr(burst_len);
|
|
|
|
state = (iec61937_parser_state *)parser;
|
|
|
|
if ((state->stream_type == IEC61937_PARSER_STREAM_UNKNOWN) ||
|
|
(state->stream_type == IEC61937_PARSER_STREAM_TYPE_MAX)) {
|
|
/* A proper value enough to parse all stream type and to synchronize. */
|
|
*burst_len = BITS_BURSTLENGTH_DTS_TYPE_III;
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
if ((state->burst_len) > BITS_BURSTLENGTH_MAT) {
|
|
soc_log_err("burst length is too big!");
|
|
soc_err_print_u32(state->burst_len);
|
|
return SOC_ERR_AI_BITS_INVALID_DATA;
|
|
} else {
|
|
*burst_len = state->burst_len;
|
|
return TD_SUCCESS;
|
|
}
|
|
}
|
|
|
|
td_bool iec61937_check_is_empty(ext_parser_handle parser)
|
|
{
|
|
iec61937_parser_state *state = (iec61937_parser_state *)parser;
|
|
if ((state == TD_NULL) || (state->buffer == TD_NULL)) {
|
|
return TD_FALSE;
|
|
}
|
|
|
|
if (iec61937_check_is_empty_frame(state->buffer, state->filled_len) == TD_TRUE) {
|
|
state->filled_len = 0;
|
|
state->free_len = state->alloc_len;
|
|
return TD_TRUE;
|
|
}
|
|
|
|
return TD_FALSE;
|
|
}
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif /* __cplusplus */
|