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.

813 lines
21 KiB

/*
* Copyright (c) Hisilicon Technologies Co., Ltd. 2019-2019. All rights reserved.
* Description: adec channel function
* Author: audio
* Create: 2019-12-30
*/
#include "adec_chan.h"
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <pthread.h>
#include "securec.h"
#include "mpi_memory_ext.h"
#include "mpi_adec_debug.h"
#include "mpi_adec_imple.h"
#include "drv_ioctl_adec.h"
#include "adec_common.h"
#include "adec_thread.h"
#include "adec_fault_check.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
static inline td_s32 adec_open_device(adec_chan *adec)
{
adec->adec_dev_fd = open(ADEC_DEVICE_NAME, O_RDWR, 0);
if (adec->adec_dev_fd < 0) {
soc_log_fatal("cannot open '%s'!\n", ADEC_DEVICE_NAME);
return SOC_ERR_ADEC_DEV_NOT_OPEN;
}
return TD_SUCCESS;
}
static td_s32 adec_close_device(adec_chan *adec)
{
td_s32 ret;
if (adec->adec_dev_fd < 0) {
return TD_SUCCESS;
}
ret = close(adec->adec_dev_fd);
if (ret != TD_SUCCESS) {
soc_log_warn("adec device close failed(0x%x)\n", ret);
}
adec->adec_dev_fd = -1;
return ret;
}
td_u32 adec_get_max_out_buf_size(adec_chan *adec)
{
uapi_acodec_decode *codec = adec->dec_attr.codec_dev;
td_void *decoder = adec->dec_attr.decoder;
return adec_get_max_pcm_out_size(codec, decoder) * 2 + /* 2 pcm buffer size to store object pcm */
adec_get_max_bits_out_size(codec, decoder);
}
static inline td_s32 adec_find_decoder(adec_chan *adec)
{
uapi_acodec_decode *codec = adec_find_ha_decoder_imple(adec->codec_id);
if (codec == TD_NULL) {
soc_err_print_h32(adec->codec_id);
soc_err_print_str(adec_get_decoder_lib_name_imple(adec->codec_id));
return SOC_ERR_ADEC_NOT_SUPPORT;
}
adec->dec_attr.codec_dev = codec;
return TD_SUCCESS;
}
static td_s32 adec_init_decoder(adec_chan *adec)
{
td_s32 ret;
ret = adec_find_decoder(adec);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(adec_find_decoder, ret);
return ret;
}
ret = adec_init_decoder_imple(&adec->dec_attr);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(adec_init_decoder_imple, ret);
return ret;
}
return TD_SUCCESS;
}
static inline td_void adec_deinit_decoder(adec_chan *adec)
{
return adec_deinit_decoder_imple(&adec->dec_attr);
}
static td_s32 adec_init_out_buf(adec_chan_output_buf *out_buf,
td_u32 max_frame_size)
{
td_u32 i;
td_u8 *buf = TD_NULL;
if ((max_frame_size == 0) ||
(out_buf->buf_num <= 0x1) ||
(out_buf->buf_num >= ADEC_MAX_WORK_BUFFER_NUMBER)) {
return SOC_ERR_ADEC_INVALID_PARA;
}
/* allocate out_buffer */
buf = (td_u8 *)malloc(out_buf->buf_num * max_frame_size);
if (buf == TD_NULL) {
soc_log_fatal("call malloc( failed\n");
return SOC_ERR_ADEC_ALLOC_MEM_FAILED;
}
/* assigning buffer */
for (i = 0; i < out_buf->buf_num; i++) {
out_buf->out_buf[i].buf = buf + i * max_frame_size;
out_buf->out_buf[i].flag = TD_FALSE;
out_buf->out_buf[i].buf_status = ADEC_OUTPUT_FILL_THIS_BUF;
}
/* reset output buffer pointer */
out_buf->base_addr = buf;
out_buf->read = 0;
out_buf->write = 0;
return TD_SUCCESS;
}
static td_void adec_deinit_out_buf(adec_chan_output_buf *out_buf)
{
td_u32 i;
if (out_buf->base_addr != TD_NULL) {
free(out_buf->base_addr);
out_buf->base_addr = TD_NULL;
}
for (i = 0; i < out_buf->buf_num; i++) {
out_buf->out_buf[i].buf = TD_NULL;
out_buf->out_buf[i].flag = TD_FALSE;
out_buf->out_buf[i].buf_status = ADEC_OUTPUT_FILL_THIS_BUF;
}
out_buf->read = 0;
out_buf->write = 0;
}
static td_void adec_deinit_in_buf(adec_chan_input_buf *in_buf)
{
if (in_buf->data != TD_NULL) {
free(in_buf->data - in_buf->buf_padding_size);
in_buf->data = TD_NULL;
}
in_buf->buf_free = 0;
in_buf->buf_read_pos = 0;
in_buf->buf_write_pos = 0;
in_buf->stream_write_pos = 0;
in_buf->buf_padding_size = 0;
}
static td_s32 adec_init_in_buf(adec_chan_input_buf *in_buf, td_u32 padding_size)
{
if ((in_buf->buf_size < ADEC_MIN_INPUT_BUFFER_SIZE) ||
(in_buf->buf_size > ADEC_MAX_INPUT_BUFFER_SIZE)) {
soc_log_err(" invalid input buffer size(%d) minsize(%d) maxsize(%d)!\n",
in_buf->buf_size, ADEC_MIN_INPUT_BUFFER_SIZE, ADEC_MAX_INPUT_BUFFER_SIZE);
return SOC_ERR_ADEC_INVALID_PARA;
}
in_buf->buf_free = in_buf->buf_size;
in_buf->buf_read_pos = 0;
in_buf->buf_write_pos = 0;
in_buf->stream_write_pos = 0;
in_buf->boundary = in_buf->buf_size;
while ((in_buf->boundary << 1) <= (ADEC_PTS_BOUNDARY_SIZE - in_buf->buf_size)) {
in_buf->boundary <<= 1;
}
in_buf->buf_padding_size = padding_size;
in_buf->data = (td_u8 *)malloc(in_buf->buf_size + padding_size);
if (in_buf->data == TD_NULL) {
soc_log_fatal("call malloc( failed\n");
return SOC_ERR_ADEC_ALLOC_MEM_FAILED;
}
in_buf->data += padding_size;
return TD_SUCCESS;
}
static td_void adec_free_buffer(adec_chan *adec)
{
adec_deinit_out_buf(&adec->out_stream_buf);
adec_deinit_in_buf(&adec->in_stream_buf);
}
static td_s32 adec_alloc_buffer(adec_chan *adec)
{
td_s32 ret;
td_u32 padding_size;
if (adec->packet_decoder == TD_TRUE) {
padding_size = PACKET_ADEC_INPUTBUF_PADDING_SIZE;
} else {
padding_size = ADEC_INPUTBUF_PADDING_SIZE;
}
ret = adec_init_in_buf(&adec->in_stream_buf, padding_size);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(adec_init_in_buf, ret);
return ret;
}
ret = adec_init_out_buf(&adec->out_stream_buf, adec_get_max_out_buf_size(adec));
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(adec_init_out_buf, ret);
adec_deinit_in_buf(&adec->in_stream_buf);
return ret;
}
return TD_SUCCESS;
}
static td_void adec_free_packet_queue(adec_chan *adec)
{
if (adec->packet_que == TD_NULL) {
return;
}
adec_free(adec->packet_que);
adec->packet_que = TD_NULL;
}
static td_s32 adec_alloc_packet_queue(adec_chan *adec)
{
/* only sw decoder support packet audio */
adec->packet_que = (adec_packet_que *)adec_malloc(sizeof(adec_packet_que));
if (adec->packet_que == TD_NULL) {
soc_log_err("adec_malloc adec_packet_que failed\n");
return SOC_ERR_ADEC_ALLOC_MEM_FAILED;
}
return TD_SUCCESS;
}
static td_void adec_reset_chan(adec_chan *adec)
{
td_s32 ret;
adec->sw_decoder_bytes_left = 0;
adec->output_delay = 0;
adec->ie_samples = 0;
adec->mid_state.continue_err_num = 0;
adec->mid_state.last_frame_channels = EXT_AUDIO_CH_STEREO;
adec->mid_state.last_frame_sample_rate = EXT_SAMPLE_RATE_48K;
/* reset PTS */
ret = memset_s(&adec->pts_que, sizeof(adec->pts_que), 0, sizeof(adec_pts_que));
if (ret != EOK) {
soc_err_print_call_fun_err(memset_s, ret);
return;
}
adec->pts_que.last_pts_ms = ADEC_INVALID_PTS;
adec->pts_que.last_store_pts_ms = ADEC_INVALID_PTS;
adec->pts_que.dfx.first_valid_pts = ADEC_INVALID_PTS;
adec->pts_que.dfx.expect_pts = ADEC_INVALID_PTS;
ret = memset_s(&adec->dfx, sizeof(adec->dfx), 0, sizeof(adec_chan_dfx));
if (ret != EOK) {
soc_err_print_call_fun_err(memset_s, ret);
return;
}
adec->dfx.speed.speed_integer = 1;
}
static td_s32 adec_init_channel(adec_chan *adec)
{
td_s32 ret;
ret = adec_init_decoder(adec);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(adec_init_decoder, ret);
return ret;
}
ret = adec_alloc_packet_queue(adec);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(adec_alloc_packet_queue, ret);
goto out0;
}
ret = adec_alloc_buffer(adec);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(adec_alloc_buffer, ret);
goto out1;
}
ret = adec_event_init(&adec->event);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(adec_event_init, ret);
goto out2;
}
adec_reset_chan(adec);
adec_chan_dfx_create_ud(adec);
return TD_SUCCESS;
out2:
adec_free_buffer(adec);
out1:
adec_free_packet_queue(adec);
out0:
adec_deinit_decoder(adec);
return ret;
}
static td_s32 adec_deinit_channel(adec_chan *adec)
{
adec_chan_dfx_destroy_ud(adec);
adec_event_deinit(&adec->event);
adec_free_buffer(adec);
adec_free_packet_queue(adec);
adec_deinit_decoder(adec);
return TD_SUCCESS;
}
static td_void adec_get_decoder_name(adec_chan *adec)
{
td_s32 ret;
adec_proc_item *adec_proc = adec->adec_info;
uapi_acodec_decode *codec = adec->dec_attr.codec_dev;
if (codec == TD_NULL) {
return;
}
ret = snprintf_s(adec_proc->codec_type, sizeof(adec_proc->codec_type),
sizeof(adec_proc->codec_type) - 1, "%s",
(codec->name != TD_NULL) ? codec->name : "UNKNOWN");
if (ret < 0) {
soc_err_print_call_fun_err(snprintf_s, ret);
return;
}
ret = snprintf_s(adec_proc->codec_description, sizeof(adec_proc->codec_description),
sizeof(adec_proc->codec_description) - 1, "%s",
(codec->description != TD_NULL) ? codec->description : "UNKNOWN");
if (ret < 0) {
soc_err_print_call_fun_err(snprintf_s, ret);
return;
}
}
static td_void adec_reset_proc_info(adec_chan *adec)
{
adec_proc_item *adec_proc = adec->adec_info;
if (adec_proc == TD_NULL) {
return;
}
adec_proc->codec_id = adec->codec_id;
adec_proc->fmt = adec->packet_decoder;
adec_proc->adec_work_enable = adec_be_work(adec->state);
adec_proc->frame_size = adec->out_stream_buf.buf_num;
adec_proc->buf_size = adec->in_stream_buf.buf_size;
adec_proc->frame_read = 0;
adec_proc->frame_write = 0;
adec_proc->frame_read_wrap = 0;
adec_proc->frame_write_wrap = 0;
adec_proc->out_channels = 0;
adec_proc->bits_out_bytes_per_frame = 0;
adec_proc->pcm_samples_per_frame = 0;
adec_proc->buf_read = 0;
adec_proc->buf_write = 0;
adec_proc->pts_lost = 0;
adec_proc->framn_nm = 0;
adec_proc->err_frame_num = 0;
adec_proc->frame_consumed_bytes = 0;
adec_proc->last_correct_frame_num = 0;
adec_proc->codec_unsupport_num = 0;
adec_proc->stream_corrupt_num = 0;
adec->total_dec_duration_ms = 0.0f;
adec_get_decoder_name(adec);
}
static td_void adec_init_proc_info(adec_proc_item *adec_info)
{
td_s32 ret;
ret = memset_s(adec_info, sizeof(*adec_info), 0, sizeof(adec_proc_item));
if (ret != EOK) {
soc_err_print_call_fun_err(memset_s, ret);
return;
}
adec_info->sample_rate = EXT_SAMPLE_RATE_UNKNOWN;
adec_info->bit_width = EXT_BIT_DEPTH_UNKNOWN;
adec_info->pcm_ctrl_state = ADEC_CMD_CTRL_STOP;
adec_info->es_ctrl_state = ADEC_CMD_CTRL_STOP;
adec_info->volume = ADEC_MAX_VOLUME;
}
static td_s32 adec_proc_init(adec_chan *adec)
{
td_s32 ret;
adec_proc_param adec_proc = {0, -1, 0};
ret = adec_open_device(adec);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(adec_open_device, ret);
return ret;
}
ret = ioctl(adec->adec_dev_fd, DRV_ADEC_PROC_INIT, &adec_proc);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl DRV_ADEC_PROC_INIT failed(0x%x)\n", ret);
goto out1;
}
adec->adec_info = (adec_proc_item *)mmap((td_void *)0, sizeof(adec_proc_item),
PROT_READ | PROT_WRITE, MAP_SHARED, adec_proc.map_fd, 0);
if (adec->adec_info == MAP_FAILED) {
soc_log_err("mmap adec_proc_item failed\n");
goto out2;
}
adec->adec_proc_map_fd = adec_proc.map_fd;
adec_init_proc_info(adec->adec_info);
return TD_SUCCESS;
out2:
ret = ioctl(adec->adec_dev_fd, DRV_ADEC_PROC_EXIT);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl DRV_ADEC_PROC_EXIT failed(0x%x)\n", ret);
}
out1:
ret = adec_close_device(adec);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(adec_close_device, ret);
}
return TD_FAILURE;
}
static td_void adec_free_private_data(adec_chan *adec)
{
if (adec->dec_attr.private_data != TD_NULL) {
free(adec->dec_attr.private_data);
adec->dec_attr.private_data = TD_NULL;
adec->dec_attr.private_data_size = 0;
}
}
static td_void adec_proc_deinit(adec_chan *adec)
{
td_s32 ret;
if (adec->adec_info != TD_NULL) {
ret = munmap(adec->adec_info, sizeof(adec_proc_item));
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(munmap, ret);
return;
}
adec->adec_proc_map_fd = TD_INVALID_HANDLE;
adec->adec_info = TD_NULL;
}
if (adec->adec_dev_fd >= 0) {
ret = ioctl(adec->adec_dev_fd, DRV_ADEC_PROC_EXIT);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl DRV_ADEC_PROC_EXIT failed(0x%x)\n", ret);
return;
}
ret = adec_close_device(adec);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(adec_close_device, ret);
return;
}
}
adec_free_private_data(adec);
}
td_s32 adec_chan_stop_dec_thread(adec_chan *adec)
{
td_s32 ret;
if (adec == TD_NULL) {
return TD_SUCCESS;
}
adec->adec_thread_run = TD_FALSE;
ret = pthread_join(adec->adec_thread_inst, TD_NULL);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(pthread_join, ret);
return ret;
}
return TD_SUCCESS;
}
td_s32 adec_chan_close(adec_chan *adec)
{
td_s32 ret;
if (adec == TD_NULL) {
return TD_SUCCESS;
}
if (adec_be_work(adec->state) == TD_TRUE) {
ret = adec_deinit_channel(adec);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(adec_deinit_channel, ret);
return ret;
}
adec->state = ADEC_STATE_STOP;
}
adec_proc_deinit(adec);
return TD_SUCCESS;
}
td_s32 adec_chan_open(adec_chan *adec)
{
td_s32 ret;
check_adec_null_ptr(adec);
ret = adec_proc_init(adec);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(adec_proc_init, ret);
return ret;
}
adec->adec_thread_run = TD_TRUE;
ret = pthread_create(&adec->adec_thread_inst, TD_NULL,
adec_dec_thread, (td_void *)adec);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(pthread_create, ret);
adec_proc_deinit(adec);
return ret;
}
adec->start_time = 0;
return TD_SUCCESS;
}
td_s32 adec_chan_start(adec_chan *adec)
{
td_s32 ret;
check_adec_null_ptr(adec);
if (adec_be_work(adec->state) == TD_TRUE) {
return TD_SUCCESS;
}
ret = adec_init_channel(adec);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(adec_init_channel, ret);
return ret;
}
adec->state = ADEC_STATE_START;
adec_reset_proc_info(adec);
adec->start_time = 0;
soc_log_info("adec%02u start\n", adec->ch_id);
return TD_SUCCESS;
}
td_s32 adec_chan_stop(adec_chan *adec)
{
td_s32 ret;
check_adec_null_ptr(adec);
if (adec_be_work(adec->state) == TD_FALSE) {
return TD_SUCCESS;
}
ret = adec_deinit_channel(adec);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(adec_deinit_channel, ret);
return ret;
}
adec->state = ADEC_STATE_STOP;
adec->eos_flag = TD_FALSE;
adec->report_decode_event = TD_FALSE;
adec_reset_proc_info(adec);
soc_log_info("adec%02u stop\n", adec->ch_id);
return TD_SUCCESS;
}
td_s32 adec_chan_pause(adec_chan *adec)
{
check_adec_null_ptr(adec);
if (adec_be_work(adec->state) == TD_FALSE) {
return SOC_ERR_ADEC_NOT_SUPPORT;
}
if (adec->state == ADEC_STATE_PAUSE) {
return TD_SUCCESS;
}
adec_chan_dfx_pause(adec);
adec->state = ADEC_STATE_PAUSE;
return TD_SUCCESS;
}
td_s32 adec_chan_resume(adec_chan *adec)
{
check_adec_null_ptr(adec);
if (adec_be_work(adec->state) == TD_FALSE) {
return SOC_ERR_ADEC_NOT_SUPPORT;
}
if (adec->state != ADEC_STATE_PAUSE) {
return TD_SUCCESS;
}
adec_chan_dfx_resume(adec);
adec->state = ADEC_STATE_START;
return TD_SUCCESS;
}
td_s32 adec_chan_set_speed(adec_chan *adec, const ext_adec_speed *speed)
{
td_s32 ret;
check_adec_null_ptr(adec);
check_adec_null_ptr(speed);
if (adec_be_work(adec->state) == TD_FALSE ||
(speed->speed_integer == 0 && speed->speed_decimal == 0)) {
return SOC_ERR_ADEC_NOT_SUPPORT;
}
if (adec->state == ADEC_STATE_PAUSE) {
adec_chan_dfx_resume(adec);
adec->state = ADEC_STATE_START;
}
ret = adec_chan_dfx_set_speed(adec, speed);
return ret;
}
td_s32 adec_chan_get_speed(adec_chan *adec, ext_adec_speed *speed)
{
check_adec_null_ptr(adec);
check_adec_null_ptr(speed);
if (adec_be_work(adec->state) == TD_FALSE) {
return SOC_ERR_ADEC_DECODE_MODE;
}
return adec_chan_dfx_get_speed(adec, speed);
}
static td_s32 adec_store_decode_private_data(adec_chan *adec, const ext_adec_attr *adec_attr)
{
td_s32 ret;
td_void *private = TD_NULL;
td_u32 size = adec_attr->open_param.private_data_size;
ret = memcpy_s(&adec->dec_attr.dec_param, sizeof(adec->dec_attr.dec_param),
&adec_attr->open_param, sizeof(uapi_acodec_dec_param));
if (ret != EOK) {
soc_err_print_call_fun_err(memcpy_s, ret);
return ret;
}
if ((adec_attr->open_param.private_data == TD_NULL) || (size == 0)) {
return TD_SUCCESS;
}
if ((adec->dec_attr.private_data_size >= size) &&
(adec->dec_attr.private_data != TD_NULL)) {
private = adec->dec_attr.private_data;
} else {
adec_free_private_data(adec);
private = malloc(size);
if (private == TD_NULL) {
soc_log_err("call malloc( fail\n");
return SOC_ERR_ADEC_ALLOC_MEM_FAILED;
}
}
ret = memcpy_s(private, size,
adec_attr->open_param.private_data,
adec_attr->open_param.private_data_size);
if (ret != EOK) {
soc_err_print_call_fun_err(memcpy_s, ret);
if (adec->dec_attr.private_data == TD_NULL) {
free(private);
} else {
adec_free_private_data(adec);
}
return ret;
}
adec->dec_attr.dec_param.private_data = private;
adec->dec_attr.dec_param.private_data_size = size;
adec->dec_attr.private_data = private;
adec->dec_attr.private_data_size = size;
return TD_SUCCESS;
}
static td_void adec_check_packet_decode(adec_chan *adec)
{
td_s32 ret;
uapi_acodec_packet_decoder_query_param packet_decode = {
.cmd = UAPI_ACODEC_PACKET_DECODER_QUERY_CMD,
.packet_decoder = TD_FALSE,
};
if (adec->codec_id == 0xFFFFFFFF) {
return;
}
ret = adec_set_config_decoder(adec->codec_id, &packet_decode);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(adec_set_config_decoder, ret);
adec->packet_decoder = TD_FALSE;
return;
}
adec->packet_decoder = packet_decode.packet_decoder;
}
td_s32 adec_chan_get_attr(adec_chan *adec, ext_adec_attr *adec_attr)
{
td_s32 ret;
ret = memcpy_s(&adec_attr->open_param, sizeof(adec_attr->open_param),
&adec->dec_attr.dec_param, sizeof(uapi_acodec_dec_param));
if (ret != EOK) {
soc_err_print_call_fun_err(memcpy_s, ret);
return ret;
}
adec_attr->codec_id = adec->codec_id;
adec_attr->in_buf_size = adec->in_stream_buf.buf_size;
adec_attr->out_buf_num = adec->out_stream_buf.buf_num;
adec_attr->enable = adec_be_work(adec->state);
adec_attr->eos = adec->eos_flag;
if ((adec_attr->codec_id == UAPI_ACODEC_ID_DOLBY_PLUS) || (adec_attr->codec_id == UAPI_ACODEC_ID_DTSM6)) {
adec->output_channel_num = adec_attr->open_param.pcm_attr.desired_out_channels;
soc_log_notice("set adec_channel->output_channel_num:%d\n", adec->output_channel_num);
}
return TD_SUCCESS;
}
td_s32 adec_chan_set_attr(adec_chan *adec, const ext_adec_attr *adec_attr)
{
td_s32 ret;
ret = adec_chan_stop(adec);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(adec_chan_stop, ret);
return ret;
}
ret = adec_store_decode_private_data(adec, adec_attr);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(adec_store_decode_private_data, ret);
return ret;
}
adec->in_stream_buf.buf_size = adec_attr->in_buf_size;
adec->out_stream_buf.buf_num = adec_attr->out_buf_num;
adec->codec_id = adec_attr->codec_id;
adec->eos_flag = adec_attr->eos;
if (adec_attr->enable == TD_TRUE) {
ret = adec_chan_start(adec);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(adec_chan_start, ret);
return ret;
}
}
adec_check_packet_decode(adec);
return TD_SUCCESS;
}
#ifdef __cplusplus
}
#endif /* __cplusplus */