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.
614 lines
19 KiB
614 lines
19 KiB
/*
|
|
* Copyright (c) Hisilicon Technologies Co., Ltd. 2019-2019. All rights reserved.
|
|
* Description: MPI function file for Huanglong low latency
|
|
* Author: audio
|
|
* Create: 2019-05-30
|
|
*/
|
|
|
|
#include <sys/ioctl.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <pthread.h>
|
|
#include <stdint.h>
|
|
#include <sys/mman.h>
|
|
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
#include <dlfcn.h>
|
|
|
|
#include "mpi_ao_plugin.h"
|
|
#include "mpi_ao_debug.h"
|
|
|
|
#include "securec.h"
|
|
#include "list.h"
|
|
#include "mpi_memory_ext.h"
|
|
#include "mpi_ao_ext.h"
|
|
#include "soc_errno.h"
|
|
|
|
#include "drv_ioctl_ao.h"
|
|
#include "mpi_ao_circ_buf.h"
|
|
#include "mpi_ao.h"
|
|
|
|
#ifdef __cplusplus
|
|
#if __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
#endif /* __cplusplus */
|
|
|
|
#define MAX_BUFFER_MS 500
|
|
#define PAGE_SIZE_MASK 0xfffff000
|
|
#define WRITE_REG_OFFSET 0x10
|
|
#define READ_REG_OFFSET 0x14
|
|
#define OFFSET 0x08
|
|
#define FRAME_SAMPLES_MIN 256
|
|
#define FRAME_SAMPLES_MASK 0x1F00 /* support 256/512/1024/2048/4096 samples */
|
|
#define FRONTOUT_EXTRA_FRAME_SIZE (6 * sizeof(td_u16) * 2048)
|
|
|
|
#define FRONTOUT_WPTR_OFFSET 0x00000088
|
|
#define FRONTOUT_RPTR_OFFSET 0x00000090
|
|
#define BACKIN_WPTR_OFFSET 0x000000a4
|
|
#define BACKIN_RPTR_OFFSET 0x000000ac
|
|
#define AOE_REG_PLUGIN_ATTR_OFFSET 0x000000b4
|
|
#define FRONTOUT_FRAME_CHANNELS 6
|
|
|
|
typedef enum {
|
|
FRONT_OUT,
|
|
BACK_IN,
|
|
} frame_direction;
|
|
|
|
typedef struct {
|
|
td_bool used;
|
|
td_bool enable;
|
|
ao_snd_id snd;
|
|
pthread_mutex_t mutex;
|
|
|
|
td_s32 bit_depth;
|
|
td_u32 sample_rate;
|
|
td_u32 channels;
|
|
ext_audio_buffer aoe_reg;
|
|
ext_audio_buffer frontout_buf;
|
|
ext_audio_buffer backin_buf;
|
|
circ_buf frontout_cb;
|
|
circ_buf backin_cb;
|
|
td_u32 frontout_buf_used_size;
|
|
td_u32 frontout_buf_extra_frame_size;
|
|
td_u32 frame_samples_diff;
|
|
} snd_engine_plugin_source;
|
|
|
|
static snd_engine_plugin_source g_engine_state = {
|
|
.used = TD_FALSE,
|
|
.enable = TD_FALSE,
|
|
.snd = AO_SND_0,
|
|
.bit_depth = EXT_BIT_DEPTH_16,
|
|
.channels = FRONTOUT_FRAME_CHANNELS,
|
|
.sample_rate = EXT_SAMPLE_RATE_48K,
|
|
};
|
|
|
|
static pthread_mutex_t g_engine_plugin_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
|
|
static inline td_void engine_plugin_mutex_lock(td_void)
|
|
{
|
|
if (pthread_mutex_lock(&g_engine_plugin_mutex) != 0) {
|
|
soc_log_err("Lock mutex failed\n");
|
|
}
|
|
}
|
|
|
|
static inline td_void engine_plugin_mutex_unlock(td_void)
|
|
{
|
|
if (pthread_mutex_unlock(&g_engine_plugin_mutex) != 0) {
|
|
soc_log_err("Unlock mutex failed\n");
|
|
}
|
|
}
|
|
|
|
static td_void audio_munmap(td_void *buffer, td_u32 size)
|
|
{
|
|
td_s32 ret;
|
|
|
|
if (buffer == TD_NULL) {
|
|
return;
|
|
}
|
|
|
|
ret = munmap(buffer, size);
|
|
if (ret != TD_SUCCESS) {
|
|
soc_err_print_call_fun_err(munmap, ret);
|
|
return;
|
|
}
|
|
}
|
|
|
|
static td_void *audio_mmap(td_s32 fd, td_u32 size, td_u64 phys_addr)
|
|
{
|
|
td_void *buffer = TD_NULL;
|
|
|
|
if (fd < 0) {
|
|
return TD_NULL;
|
|
}
|
|
buffer = (td_void *)mmap64((td_void *)0, size,
|
|
PROT_READ | PROT_WRITE, MAP_SHARED, fd, (off64_t)phys_addr);
|
|
if (buffer == MAP_FAILED) {
|
|
soc_log_err("mmap failed, fd = %d, size = %d\n", fd, size);
|
|
return TD_NULL;
|
|
}
|
|
return buffer;
|
|
}
|
|
|
|
static td_void audio_munmap_ion(td_void *buf, td_u32 size)
|
|
{
|
|
audio_munmap(buf, size);
|
|
}
|
|
|
|
static td_s32 buf_mmap(ext_audio_buffer *map_buf)
|
|
{
|
|
map_buf->virt_addr = audio_mmap(map_buf->fd, map_buf->size, 0);
|
|
if (map_buf->virt_addr == TD_NULL) {
|
|
return SOC_ERR_AO_MALLOC_FAILED;
|
|
}
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
static td_void buf_munmap(ext_audio_buffer *map_buf)
|
|
{
|
|
audio_munmap_ion(map_buf->virt_addr, map_buf->size);
|
|
map_buf->fd = -1;
|
|
map_buf->virt_addr = TD_NULL;
|
|
}
|
|
|
|
static inline td_void munmap_hw_aoe_reg(td_void)
|
|
{
|
|
audio_munmap(g_engine_state.aoe_reg.virt_addr, g_engine_state.aoe_reg.size);
|
|
}
|
|
|
|
static td_s32 mmap_hw_aoe_reg(td_void)
|
|
{
|
|
td_s32 fd;
|
|
ext_audio_buffer *buf = TD_NULL;
|
|
|
|
/* hw aoe use dsp dram or cpu sram as aoe reg
|
|
* we use ao fd to mmap
|
|
*/
|
|
fd = mpi_ao_get_fd();
|
|
if (fd < 0) {
|
|
soc_log_err("mpi_ao_get_fd failed\n");
|
|
return SOC_ERR_AO_DEV_NOT_OPEN;
|
|
}
|
|
|
|
buf = &g_engine_state.aoe_reg;
|
|
buf->fd = fd;
|
|
buf->virt_addr = (td_u8 *)audio_mmap(fd, buf->size, buf->phys_addr);
|
|
if (buf->virt_addr == TD_NULL) {
|
|
soc_log_err("call audio_mmap failed\n");
|
|
return SOC_ERR_AO_MALLOC_FAILED;
|
|
}
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
static td_void snd_engine_plugin_munmap_buffer(td_void)
|
|
{
|
|
snd_engine_plugin_source *engine_state = &g_engine_state;
|
|
buf_munmap(&engine_state->backin_buf);
|
|
buf_munmap(&engine_state->frontout_buf);
|
|
munmap_hw_aoe_reg();
|
|
}
|
|
|
|
static td_void get_mmap_buffer_info(const mixer_plugin_attr *attr)
|
|
{
|
|
snd_engine_plugin_source *engine_state = &g_engine_state;
|
|
|
|
engine_state->aoe_reg.phys_addr = attr->aoe_reg.phys_addr;
|
|
engine_state->aoe_reg.size = attr->aoe_reg.size;
|
|
engine_state->aoe_reg.fd = attr->aoe_reg.fd;
|
|
|
|
engine_state->frontout_buf.phys_addr = attr->frontout_buffer.phys_addr;
|
|
engine_state->frontout_buf.size = attr->frontout_buffer.size + FRONTOUT_EXTRA_FRAME_SIZE;
|
|
engine_state->frontout_buf_used_size = attr->frontout_buffer.size;
|
|
engine_state->frontout_buf_extra_frame_size = FRONTOUT_EXTRA_FRAME_SIZE;
|
|
engine_state->frontout_buf.fd = attr->frontout_buffer.fd;
|
|
|
|
engine_state->backin_buf.phys_addr = attr->backin_buffer.phys_addr;
|
|
engine_state->backin_buf.size = attr->backin_buffer.size;
|
|
engine_state->backin_buf.fd = attr->backin_buffer.fd;
|
|
}
|
|
|
|
static td_s32 snd_engine_plugin_mmap_buffer(td_void)
|
|
{
|
|
td_s32 ret;
|
|
td_u32 *write_ptr = TD_NULL;
|
|
td_u32 *read_ptr = TD_NULL;
|
|
snd_engine_plugin_source *engine_state = &g_engine_state;
|
|
|
|
ret = mmap_hw_aoe_reg();
|
|
if (ret != TD_SUCCESS) {
|
|
soc_err_print_call_fun_err(mmap_hw_aoe_reg, ret);
|
|
return ret;
|
|
}
|
|
|
|
ret = buf_mmap(&engine_state->frontout_buf);
|
|
if (ret != TD_SUCCESS) {
|
|
soc_err_print_call_fun_err(buf_mmap, ret);
|
|
munmap_hw_aoe_reg();
|
|
return ret;
|
|
}
|
|
|
|
ret = buf_mmap(&engine_state->backin_buf);
|
|
if (ret != TD_SUCCESS) {
|
|
soc_err_print_call_fun_err(buf_mmap, ret);
|
|
buf_munmap(&engine_state->frontout_buf);
|
|
munmap_hw_aoe_reg();
|
|
return ret;
|
|
}
|
|
|
|
write_ptr = (td_u32 *)(engine_state->aoe_reg.virt_addr + FRONTOUT_WPTR_OFFSET);
|
|
read_ptr = (td_u32 *)(engine_state->aoe_reg.virt_addr + FRONTOUT_RPTR_OFFSET);
|
|
soc_log_dbg("frontout v %p s %d w %p r %p\n",
|
|
engine_state->frontout_buf.virt_addr, engine_state->frontout_buf_used_size, write_ptr, read_ptr);
|
|
circ_buf_init(&engine_state->frontout_cb,
|
|
(td_u32 *)(write_ptr),
|
|
(td_u32 *)(read_ptr),
|
|
engine_state->frontout_buf.virt_addr,
|
|
engine_state->frontout_buf_used_size);
|
|
|
|
write_ptr = (td_u32 *)(engine_state->aoe_reg.virt_addr + BACKIN_WPTR_OFFSET);
|
|
read_ptr = (td_u32 *)(engine_state->aoe_reg.virt_addr + BACKIN_RPTR_OFFSET);
|
|
soc_log_dbg("backin v %p s %d w %p r %p\n",
|
|
engine_state->backin_buf.virt_addr, engine_state->backin_buf.size, write_ptr, read_ptr);
|
|
circ_buf_init(&engine_state->backin_cb,
|
|
(td_u32 *)(write_ptr),
|
|
(td_u32 *)(read_ptr),
|
|
engine_state->backin_buf.virt_addr,
|
|
engine_state->backin_buf.size);
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
static td_u32 aoe_reg_read_frontout_channel(const snd_engine_plugin_source *engine_state)
|
|
{
|
|
td_u32 ch = 0;
|
|
td_u32 engine_plugin_attr = 0;
|
|
td_u32 *engine_plugin_attr_reg = TD_NULL;
|
|
const td_u32 frontout_ch_map[] = { 0, EXT_AUDIO_CH_STEREO, EXT_AUDIO_CH_6, 0};
|
|
|
|
if (engine_state->aoe_reg.virt_addr == TD_NULL) {
|
|
soc_log_err("engine_state->aoe_reg.virt_addr null pointer!\n");
|
|
return 0;
|
|
}
|
|
|
|
engine_plugin_attr_reg = (td_u32 *)(engine_state->aoe_reg.virt_addr + AOE_REG_PLUGIN_ATTR_OFFSET);
|
|
engine_plugin_attr = *engine_plugin_attr_reg;
|
|
ch = engine_plugin_attr & 0x0003; /* aoe reg: engine_plugin_attr.bits.ch */
|
|
if (ch >= sizeof(frontout_ch_map) / sizeof(td_u32)) {
|
|
soc_log_warn("channels is error %d\n", ch);
|
|
return 0;
|
|
}
|
|
|
|
return frontout_ch_map[ch];
|
|
}
|
|
|
|
static td_s32 check_get_buffer_params_valid(td_u32 require_size, td_u32 timeout_ms)
|
|
{
|
|
if (require_size == 0) {
|
|
return SOC_ERR_AO_INVALID_PARA;
|
|
}
|
|
if (timeout_ms > MAX_BUFFER_MS) {
|
|
return SOC_ERR_AO_INVALID_PARA;
|
|
}
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
static td_s32 get_engine_plugin_frame_info(ext_audio_mixer_plugin_frame *frame, frame_direction dir)
|
|
{
|
|
snd_engine_plugin_source *engine_state = &g_engine_state;
|
|
if (dir == FRONT_OUT) {
|
|
frame->frame_addr.frame_fd.mem_handle = engine_state->frontout_buf.fd;
|
|
frame->frame_addr.frame_size = engine_state->frontout_buf_used_size;
|
|
} else if (dir == BACK_IN) {
|
|
frame->frame_addr.frame_fd.mem_handle = engine_state->backin_buf.fd;
|
|
frame->frame_addr.frame_size = engine_state->backin_buf.size;
|
|
}
|
|
|
|
frame->frame_info.bit_depth = engine_state->bit_depth;
|
|
frame->frame_info.channels = aoe_reg_read_frontout_channel(engine_state);
|
|
engine_state->channels = frame->frame_info.channels;
|
|
frame->frame_info.sample_rate = engine_state->sample_rate;
|
|
frame->frame_info.interleaved = TD_TRUE;
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
static td_s32 snd_engine_plugin_enable(ao_snd_id sound)
|
|
{
|
|
td_s32 ret, ao_fd;
|
|
engine_plugin_mutex_lock();
|
|
ao_snd_mixer_plugin_buffer_param param;
|
|
ao_snd_mixer_plugin_enable_param enable;
|
|
|
|
if (g_engine_state.used == TD_TRUE) {
|
|
soc_log_err("SND engine plugin is busy!\n");
|
|
engine_plugin_mutex_unlock();
|
|
return SOC_ERR_AO_NOTSUPPORT;
|
|
}
|
|
|
|
ao_fd = mpi_ao_get_fd();
|
|
if (ao_fd < 0) {
|
|
soc_log_err("mpi_ao_get_fd failed\n");
|
|
engine_plugin_mutex_unlock();
|
|
return SOC_ERR_AO_DEV_NOT_OPEN;
|
|
}
|
|
|
|
ret = memset_s(¶m, sizeof(param), 0, sizeof(ao_snd_mixer_plugin_buffer_param));
|
|
if (ret != EOK) {
|
|
soc_err_print_call_fun_err(memset_s, ret);
|
|
engine_plugin_mutex_unlock();
|
|
return ret;
|
|
}
|
|
|
|
enable.sound = sound;
|
|
enable.plugin_enable = TD_TRUE;
|
|
ret = ioctl(ao_fd, CMD_AO_MIXER_PLUGIN_SET_ENABLE, &enable);
|
|
if (ret != TD_SUCCESS) {
|
|
soc_log_err("ioctl CMD_AO_MIXER_PLUGIN_SET_ENABLE TRUE failed(0x%x)\n", ret);
|
|
engine_plugin_mutex_unlock();
|
|
return ret;
|
|
}
|
|
|
|
param.sound = sound;
|
|
ret = ioctl(ao_fd, CMD_AO_MIXER_PLUGIN_GET_BUFFER_INFO, ¶m);
|
|
if (ret != TD_SUCCESS) {
|
|
soc_log_err("ioctl CMD_AO_MIXER_PLUGIN_GET_BUFFER_INFO failed(0x%x)\n", ret);
|
|
engine_plugin_mutex_unlock();
|
|
return ret;
|
|
}
|
|
|
|
get_mmap_buffer_info(¶m.buffer_attr);
|
|
|
|
ret = snd_engine_plugin_mmap_buffer();
|
|
if (ret != TD_SUCCESS) {
|
|
soc_err_print_call_fun_err(snd_engine_plugin_mmap_buffer, ret);
|
|
engine_plugin_mutex_unlock();
|
|
return ret;
|
|
}
|
|
g_engine_state.enable = TD_TRUE;
|
|
g_engine_state.used = TD_TRUE;
|
|
soc_log_notice("set engine plugin enable\n");
|
|
engine_plugin_mutex_unlock();
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
static td_s32 snd_engine_plugin_disable(ao_snd_id sound)
|
|
{
|
|
td_s32 ret;
|
|
td_s32 ao_fd;
|
|
ao_snd_mixer_plugin_enable_param enable;
|
|
ao_snd_mixer_plugin_buffer_param param;
|
|
|
|
engine_plugin_mutex_lock();
|
|
|
|
ao_fd = mpi_ao_get_fd();
|
|
if (ao_fd < 0) {
|
|
soc_log_err("mpi_ao_get_fd failed\n");
|
|
engine_plugin_mutex_unlock();
|
|
return SOC_ERR_AO_DEV_NOT_OPEN;
|
|
}
|
|
|
|
param.sound = sound;
|
|
ret = ioctl(ao_fd, CMD_AO_MIXER_PLUGIN_GET_BUFFER_INFO, ¶m);
|
|
if (ret != TD_SUCCESS) {
|
|
soc_log_err("ioctl CMD_AO_MIXER_PLUGIN_GET_BUFFER_INFO failed(0x%x)\n", ret);
|
|
engine_plugin_mutex_unlock();
|
|
return ret;
|
|
}
|
|
|
|
g_engine_state.enable = TD_FALSE;
|
|
g_engine_state.used = TD_FALSE;
|
|
get_mmap_buffer_info(¶m.buffer_attr);
|
|
snd_engine_plugin_munmap_buffer();
|
|
|
|
enable.sound = sound;
|
|
enable.plugin_enable = TD_FALSE;
|
|
ret = ioctl(ao_fd, CMD_AO_MIXER_PLUGIN_SET_ENABLE, &enable);
|
|
if (ret != TD_SUCCESS) {
|
|
soc_log_err("ioctl CMD_AO_MIXER_PLUGIN_SET_ENABLE FALSE failed(0x%x)\n", ret);
|
|
engine_plugin_mutex_unlock();
|
|
return ret;
|
|
}
|
|
|
|
soc_log_notice("set engine plugin disable\n");
|
|
engine_plugin_mutex_unlock();
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
td_s32 snd_mixer_set_engine_plugin_enable(ao_snd_id sound, td_bool enable)
|
|
{
|
|
if (enable == TD_TRUE) {
|
|
return snd_engine_plugin_enable(sound);
|
|
} else {
|
|
return snd_engine_plugin_disable(sound);
|
|
}
|
|
}
|
|
|
|
td_s32 snd_mixer_get_engine_plugin_enable(ao_snd_id sound, td_bool *enable)
|
|
{
|
|
td_s32 ret;
|
|
td_s32 ao_fd;
|
|
ao_snd_mixer_plugin_enable_param params;
|
|
|
|
if (sound != AO_SND_0) {
|
|
return SOC_ERR_AO_INVALID_ID;
|
|
}
|
|
if (enable == TD_NULL) {
|
|
return SOC_ERR_AO_NULL_PTR;
|
|
}
|
|
|
|
ao_fd = mpi_ao_get_fd();
|
|
if (ao_fd < 0) {
|
|
soc_log_err("mpi_ao_get_fd failed\n");
|
|
return SOC_ERR_AO_DEV_NOT_OPEN;
|
|
}
|
|
|
|
params.sound = sound;
|
|
ret = ioctl(ao_fd, CMD_AO_MIXER_PLUGIN_GET_ENABLE, ¶ms);
|
|
if (ret != TD_SUCCESS) {
|
|
soc_log_err("ioctl CMD_AO_MIXER_PLUGIN_GET_ENABLE failed(0x%x)\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
g_engine_state.enable = params.plugin_enable;
|
|
g_engine_state.used = params.plugin_enable;
|
|
*enable = params.plugin_enable;
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
td_s32 snd_mixer_acquire_engine_plugin_frontout_stream(ao_snd_id sound, td_u32 require_samples,
|
|
ext_audio_mixer_plugin_frame *frontout_frame, td_u32 timeout_ms)
|
|
{
|
|
td_s32 ret;
|
|
circ_buf_info info;
|
|
td_u32 wait_ms = 0;
|
|
td_u32 busy_size, dest_size, require_size, realtime_temp;
|
|
ext_audio_mixer_plugin_frame out_frame;
|
|
snd_engine_plugin_source *engine_state = &g_engine_state;
|
|
|
|
if (engine_state->enable == TD_FALSE) {
|
|
return SOC_ERR_AO_DEV_NOT_OPEN;
|
|
}
|
|
|
|
TD_UNUSED(sound);
|
|
ret = check_get_buffer_params_valid(require_samples, timeout_ms);
|
|
if (ret != TD_SUCCESS) {
|
|
soc_err_print_call_fun_err(check_get_buffer_params_valid, ret);
|
|
return ret;
|
|
}
|
|
|
|
circ_buf_query_info(&engine_state->frontout_cb, &info);
|
|
soc_log_dbg("out w %d r %d b %d f %d\n", info.write_pos, info.read_pos, info.total_data_size,
|
|
info.total_free_size);
|
|
|
|
realtime_temp = (require_samples & FRAME_SAMPLES_MASK) * sizeof(td_s16);
|
|
if (realtime_temp == 0) {
|
|
soc_log_err("query buffer samples invalid %d\n", require_samples);
|
|
return SOC_ERR_AO_INVALID_PARA;
|
|
}
|
|
require_size = realtime_temp * FRONTOUT_FRAME_CHANNELS;
|
|
do {
|
|
busy_size = circ_buf_query_busy(&engine_state->frontout_cb);
|
|
if ((require_size != 0) && (busy_size >= require_size)) {
|
|
break;
|
|
} else if (wait_ms++ >= timeout_ms) {
|
|
break;
|
|
}
|
|
usleep(1000); /* 1000 is sleep time */
|
|
} while (wait_ms <= timeout_ms);
|
|
|
|
if ((wait_ms >= timeout_ms) && (busy_size < require_size)) {
|
|
soc_log_warn("query buf_data time out! need_bytes(0x%x), avail_bytes(0x%x)\n", require_size, busy_size);
|
|
return SOC_ERR_AO_INBUF_EMPTY;
|
|
}
|
|
|
|
get_engine_plugin_frame_info(&out_frame, FRONT_OUT);
|
|
dest_size = require_size < busy_size ? require_size : busy_size;
|
|
out_frame.frame_addr.frame_size = dest_size;
|
|
out_frame.frame_addr.frame_fd.addr_offset = *(engine_state->frontout_cb.read);
|
|
out_frame.frame_info.pcm_samples = require_samples;
|
|
ret = memcpy_s(frontout_frame, sizeof(ext_audio_mixer_plugin_frame), &out_frame, sizeof(out_frame));
|
|
if (ret != EOK) {
|
|
soc_err_print_call_fun_err(memcpy_s, ret);
|
|
return ret;
|
|
}
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
td_s32 snd_mixer_release_engine_plugin_frontout_stream(ao_snd_id sound,
|
|
const ext_audio_mixer_plugin_frame *frontout_frame)
|
|
{
|
|
snd_engine_plugin_source *engine_state = &g_engine_state;
|
|
|
|
if (engine_state->enable == TD_FALSE) {
|
|
return SOC_ERR_AO_DEV_NOT_OPEN;
|
|
}
|
|
|
|
if (frontout_frame == TD_NULL) {
|
|
return SOC_ERR_AO_NULL_PTR;
|
|
}
|
|
|
|
TD_UNUSED(sound);
|
|
circ_buf_update_read_pos(&engine_state->frontout_cb, frontout_frame->frame_addr.frame_size);
|
|
engine_state->frame_samples_diff += frontout_frame->frame_info.pcm_samples;
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
td_s32 snd_mixer_get_engine_plugin_backin_buffer(ao_snd_id sound, td_u32 require_size,
|
|
ext_audio_mixer_plugin_frame *backin_frame, td_u32 timeout_ms)
|
|
{
|
|
td_s32 ret;
|
|
circ_buf_info info;
|
|
td_u32 free_size;
|
|
td_u32 dest_size;
|
|
td_u32 wait_ms = 0;
|
|
ext_audio_mixer_plugin_frame in_frame;
|
|
snd_engine_plugin_source *engine_state = &g_engine_state;
|
|
|
|
if (engine_state->enable == TD_FALSE) {
|
|
return SOC_ERR_AO_DEV_NOT_OPEN;
|
|
}
|
|
|
|
TD_UNUSED(sound);
|
|
ret = check_get_buffer_params_valid(require_size, timeout_ms);
|
|
if (ret != TD_SUCCESS) {
|
|
soc_err_print_call_fun_err(check_get_buffer_params_valid, ret);
|
|
return ret;
|
|
}
|
|
get_engine_plugin_frame_info(&in_frame, BACK_IN);
|
|
|
|
circ_buf_query_info(&engine_state->backin_cb, &info);
|
|
soc_log_dbg("in w %d r %d b %d f %d req %d\n", info.write_pos, info.read_pos,
|
|
info.total_data_size, info.total_free_size, require_size);
|
|
do {
|
|
free_size = circ_buf_query_free(&engine_state->backin_cb);
|
|
if (free_size > require_size) {
|
|
break;
|
|
} else if (wait_ms++ >= timeout_ms) {
|
|
break;
|
|
}
|
|
usleep(1000); /* 1000 is sleep time */
|
|
} while (wait_ms <= timeout_ms);
|
|
|
|
if ((wait_ms >= timeout_ms) && (free_size <= require_size)) {
|
|
soc_log_warn("query buf_data time out! need_bytes(0x%x), avail_bytes(0x%x)\n", require_size, free_size);
|
|
return SOC_ERR_AO_OUT_BUF_FULL;
|
|
}
|
|
dest_size = require_size < free_size ? require_size : free_size;
|
|
in_frame.frame_addr.frame_size = dest_size;
|
|
in_frame.frame_addr.frame_fd.addr_offset = *(engine_state->backin_cb.write);
|
|
in_frame.frame_info.pcm_samples = FRAME_SAMPLES_MIN;
|
|
ret = memcpy_s(backin_frame, sizeof(ext_audio_mixer_plugin_frame), &in_frame, sizeof(in_frame));
|
|
if (ret != EOK) {
|
|
soc_err_print_call_fun_err(memcpy_s, ret);
|
|
return ret;
|
|
}
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
td_s32 snd_mixer_put_engine_plugin_backin_buffer(ao_snd_id sound,
|
|
const ext_audio_mixer_plugin_frame *backin_frame)
|
|
{
|
|
snd_engine_plugin_source *engine_state = &g_engine_state;
|
|
|
|
if (engine_state->enable == TD_FALSE) {
|
|
return SOC_ERR_AO_DEV_NOT_OPEN;
|
|
}
|
|
|
|
if (backin_frame == TD_NULL) {
|
|
return SOC_ERR_AO_NULL_PTR;
|
|
}
|
|
|
|
TD_UNUSED(sound);
|
|
circ_buf_update_write_pos(&engine_state->backin_cb, backin_frame->frame_addr.frame_size);
|
|
engine_state->frame_samples_diff -= backin_frame->frame_info.pcm_samples;
|
|
soc_log_info("samples frame store %d \n", engine_state->frame_samples_diff);
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
#ifdef __cplusplus
|
|
#if __cplusplus
|
|
}
|
|
#endif
|
|
#endif /* __cplusplus */
|