561 lines
15 KiB
C
561 lines
15 KiB
C
#include "encode_write.h"
|
|
#include "file_operate/file_bs_deal.h"
|
|
#include "audio_enc.h"
|
|
#include "media/audio_base.h"
|
|
#include "dev_manager.h"
|
|
#include "app_config.h"
|
|
#include "spi/nor_fs.h"
|
|
#include "rec_nor/nor_interface.h"
|
|
|
|
#if TCFG_ENC_WRITE_FILE_ENABLE
|
|
|
|
extern FILE *file_api_auto_create_file(const char *path, const char *folder, const char *filename, u32 *file_index);
|
|
|
|
// *INDENT-OFF*
|
|
struct enc_write_file{
|
|
volatile u32 init_ok : 1;
|
|
volatile u32 wait_idle : 1;
|
|
volatile u32 start : 1;
|
|
volatile u32 wait_stop : 1;
|
|
u32 write_err : 1;
|
|
OS_SEM sem_task_run;
|
|
|
|
struct __dev *dev;
|
|
const char *folder;
|
|
const char *filename;
|
|
void *fmnt;
|
|
FILE *file;
|
|
u32 cut_size;
|
|
u32 limit_size;
|
|
int file_size;
|
|
u32 input_frame_len;
|
|
void *input_hdl;
|
|
struct audio_enc_write_input *input;
|
|
u32 write_err_no_check;
|
|
|
|
void *evt_hdl;
|
|
void (*evt_cb)(void *, int, int);
|
|
|
|
void *set_head_hdl;
|
|
int (*set_head)(void *, char **head);
|
|
};
|
|
|
|
static volatile u32 enc_file_index = (u32) - 1;
|
|
static volatile u32 enc_file_coding_type = 0;
|
|
extern u8 record_part;
|
|
void last_enc_file_codeing_type_save(u32 type)
|
|
{
|
|
enc_file_coding_type = type;
|
|
}
|
|
|
|
//获取最后录音文件的序号. 用于录音播放, -1表示无效
|
|
int last_enc_file_path_get(char path[64])
|
|
{
|
|
#if TCFG_NOR_REC || FLASH_INSIDE_REC_ENABLE
|
|
int index = 0;
|
|
char logo[20] = {0};
|
|
|
|
#if TCFG_NOR_REC
|
|
strcpy(logo, "rec_nor");
|
|
sprintf(path, "%s%s%s", dev_manager_get_root_path_by_logo(logo), REC_FOLDER_NAME"/AC69****",".WAV");
|
|
#elif FLASH_INSIDE_REC_ENABLE
|
|
char index_str[5] = {0};
|
|
index = flashinsize_rec_get_index();
|
|
memset(logo, 0, 20);
|
|
memset(path, 0, 64);
|
|
strcpy(logo, "rec_sdfile");
|
|
|
|
index_str[0] = index / 1000 + '0';
|
|
index_str[1] = index % 1000 / 100 + '0';
|
|
index_str[2] = index % 100 / 10 + '0';
|
|
index_str[3] = index % 10 + '0';
|
|
sprintf(path, "%s%s%s%s", dev_manager_get_root_path_by_logo(logo), REC_FOLDER_NAME"/AC69", index_str, ".WAV");
|
|
#endif
|
|
printf("rec file =%s\n", path);
|
|
return 0;
|
|
|
|
#else
|
|
|
|
char index_str[5] = {0};
|
|
char *logo = dev_manager_get_phy_logo(dev_manager_find_active(0));//最后活动设备
|
|
printf("enc file idex = %d, dev_path = %s\n", enc_file_index, dev_manager_get_root_path_by_logo(logo));
|
|
if (enc_file_index != (u32) - 1) {
|
|
index_str[0] = enc_file_index / 1000 + '0';
|
|
index_str[1] = enc_file_index % 1000 / 100 + '0';
|
|
index_str[2] = enc_file_index % 100 / 10 + '0';
|
|
index_str[3] = enc_file_index % 10 + '0';
|
|
if ((enc_file_coding_type == AUDIO_CODING_WAV) || (enc_file_coding_type == AUDIO_CODING_PCM)) {
|
|
sprintf(path, "%s%s%s%s", dev_manager_get_root_path_by_logo(logo), REC_FOLDER_NAME"/AC69", index_str, ".WAV");
|
|
} else if (enc_file_coding_type == AUDIO_CODING_G726) {
|
|
sprintf(path, "%s%s%s%s", dev_manager_get_root_path_by_logo(logo), REC_FOLDER_NAME"/AC69", index_str, ".wav");
|
|
} else if (enc_file_coding_type == AUDIO_CODING_MP3) {
|
|
sprintf(path, "%s%s%s%s", dev_manager_get_root_path_by_logo(logo), REC_FOLDER_NAME"/AC69", index_str, ".MP3");
|
|
} else {
|
|
return -1;
|
|
}
|
|
printf("rec file =%s\n", path);
|
|
return 0;
|
|
}
|
|
return -1;
|
|
#endif
|
|
}
|
|
|
|
static void enc_write_file_task(void *p)
|
|
{
|
|
int ret, len;
|
|
int pend_dly = -1;
|
|
struct enc_write_file *wfil = p;
|
|
s16 *frame;
|
|
|
|
while (1) {
|
|
if (pend_dly) {
|
|
os_sem_pend(&wfil->sem_task_run, pend_dly);
|
|
}
|
|
if (!wfil->init_ok) {
|
|
wfil->wait_idle = 0;
|
|
wfil->start = 0;
|
|
wfil->wait_stop = 0;
|
|
break;
|
|
}
|
|
pend_dly++;
|
|
if (!wfil->start) {
|
|
continue;
|
|
}
|
|
len = wfil->input->get(wfil->input_hdl, &frame, wfil->input_frame_len);
|
|
if (len) {
|
|
if (wfil->write_err == 0) {
|
|
ret = fwrite(wfil->file, frame, len);
|
|
wfil->file_size = fpos(wfil->file);
|
|
#if TCFG_NOR_REC || FLASH_INSIDE_REC_ENABLE
|
|
int max_capacity = 0;
|
|
#if TCFG_NOR_REC
|
|
max_capacity = get_rec_capacity(wfil->file);
|
|
#elif FLASH_INSIDE_REC_ENABLE
|
|
max_capacity = flashinsize_rec_get_capacity();
|
|
#endif
|
|
if (wfil->file_size + len > (max_capacity - 4096)) {
|
|
log_w("rec is overflow!!!!!!!!!!!!!");
|
|
wfil->write_err_no_check = 1;
|
|
wfil->write_err = 1;
|
|
} else {
|
|
wfil->write_err_no_check = 0;
|
|
}
|
|
#endif
|
|
} else {
|
|
ret = 0;
|
|
}
|
|
if (ret != len) {
|
|
if (wfil->write_err == 0) {
|
|
log_e("write file err ");
|
|
if (wfil->evt_cb) {
|
|
wfil->evt_cb(wfil->evt_hdl, ENC_WRITE_FILE_EVT_WRITE_ERR, 0);
|
|
}
|
|
}
|
|
wfil->write_err = 1;
|
|
} else {
|
|
pend_dly = 0;
|
|
}
|
|
if (wfil->input->put) {
|
|
wfil->input->put(wfil->input_hdl, frame);
|
|
}
|
|
} else {
|
|
wfil->wait_stop = 0;
|
|
}
|
|
}
|
|
while (1) {
|
|
os_time_dly(100);
|
|
}
|
|
}
|
|
|
|
int enc_write_file_resume(void *hdl)
|
|
{
|
|
struct enc_write_file *wfil = hdl;
|
|
if (wfil->start && (wfil->write_err == 0)) {
|
|
os_sem_set(&wfil->sem_task_run, 0);
|
|
os_sem_post(&wfil->sem_task_run);
|
|
return 0;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
void enc_write_file_close(void *hdl)
|
|
{
|
|
struct enc_write_file *wfil = hdl;
|
|
|
|
if (wfil->init_ok) {
|
|
wfil->wait_idle = 1;
|
|
wfil->init_ok = 0;
|
|
os_sem_set(&wfil->sem_task_run, 0);
|
|
os_sem_post(&wfil->sem_task_run);
|
|
while (wfil->wait_idle) {
|
|
os_time_dly(1);
|
|
}
|
|
task_kill("enc_write");
|
|
}
|
|
|
|
if (wfil->file) {
|
|
int f_len = fpos(wfil->file);
|
|
struct vfs_attr attr = {0};
|
|
do {
|
|
if (f_len <= wfil->cut_size) {
|
|
enc_file_index = (u32) - 1;
|
|
fdelete(wfil->file);
|
|
break;
|
|
}
|
|
f_len -= wfil->cut_size;
|
|
if (f_len <= wfil->limit_size) {
|
|
enc_file_index = (u32) - 1;
|
|
fdelete(wfil->file);
|
|
break;
|
|
}
|
|
|
|
if (wfil->set_head && (wfil->write_err_no_check || wfil->write_err == 0)) {
|
|
char *head;
|
|
int len = wfil->set_head(wfil->set_head_hdl, &head);
|
|
if (f_len <= len) {
|
|
enc_file_index = (u32) - 1;
|
|
fdelete(wfil->file);
|
|
break;
|
|
}
|
|
if (len) {
|
|
fseek(wfil->file, 0, SEEK_SET);
|
|
fwrite(wfil->file, head, len);
|
|
}
|
|
}
|
|
fseek(wfil->file, f_len, SEEK_SET);
|
|
fget_attrs(wfil->file, &attr);
|
|
fclose(wfil->file);
|
|
char *dev_logo = NULL;
|
|
#if (TCFG_RECORD_FOLDER_DEV_ENABLE)
|
|
dev_logo = dev_manager_get_rec_logo(wfil->dev);
|
|
#else
|
|
dev_logo = dev_manager_get_logo(wfil->dev);
|
|
#endif
|
|
dev_manager_set_valid_by_logo(dev_logo, 1);
|
|
} while (0);
|
|
if (wfil->evt_cb) {
|
|
wfil->evt_cb(wfil->evt_hdl, ENC_WRITE_FILE_EVT_FILE_CLOSE, attr.sclust);
|
|
}
|
|
wfil->file = NULL;
|
|
}
|
|
free(wfil);
|
|
}
|
|
|
|
static u32 get_creat_path_len(char *root_path, const char *folder, const char *filename)
|
|
{
|
|
return (strlen(root_path) + strlen(folder) + strlen(filename) + strlen("/") + 1);
|
|
}
|
|
|
|
static char *create_path(char *path, char *root_path, const char *folder, const char *filename)
|
|
{
|
|
strcat(path, root_path);
|
|
strcat(path, folder);
|
|
strcat(path, "/");
|
|
strcat(path, filename);
|
|
#if TCFG_NOR_REC
|
|
#elif FLASH_INSIDE_REC_ENABLE
|
|
int index = 0;
|
|
int last_num = -1;
|
|
char *file_num_str;
|
|
|
|
index = sdfile_rec_scan_ex();
|
|
last_num = index + 1;
|
|
file_num_str = strrchr(path, '.') - 4;
|
|
|
|
if (last_num > 9999) {
|
|
last_num = 0;
|
|
}
|
|
file_num_str[0] = last_num / 1000 + '0';
|
|
file_num_str[1] = last_num % 1000 / 100 + '0';
|
|
file_num_str[2] = last_num % 100 / 10 + '0';
|
|
file_num_str[3] = last_num % 10 + '0';
|
|
#endif
|
|
printf(">>>[test]:create path =%s\n", path);
|
|
return path;
|
|
}
|
|
|
|
void *enc_write_file_open(char *logo, const char *folder, const char *filename)
|
|
{
|
|
if (!logo || !folder || !filename) {
|
|
return NULL;
|
|
}
|
|
int err;
|
|
struct enc_write_file *wfil = zalloc(sizeof(struct enc_write_file));
|
|
if (!wfil) {
|
|
return NULL;
|
|
}
|
|
struct __dev *dev = dev_manager_find_spec(logo, 0);
|
|
if(!dev){
|
|
free(wfil);
|
|
return NULL;
|
|
}
|
|
|
|
char *root_path = dev_manager_get_root_path(dev);
|
|
wfil->dev = dev;
|
|
wfil->folder = folder;
|
|
wfil->filename = filename;
|
|
char *path = NULL;
|
|
u32 path_len = get_creat_path_len(root_path, folder, filename);
|
|
printf("path_len %d\n", path_len);
|
|
path = zalloc(path_len);
|
|
if(path == NULL){
|
|
goto _exit;
|
|
}
|
|
create_path(path, root_path, folder, filename);
|
|
wfil->file = fopen(path, "w+");
|
|
free(path);
|
|
path = NULL;
|
|
if (!wfil->file) {
|
|
log_e("file create err ");
|
|
goto _exit;
|
|
}
|
|
enc_file_index = get_last_num(); //获取最后的数字
|
|
|
|
/* r_printf(">>>[test]:enc_file_index = %d\n", enc_file_index); */
|
|
os_sem_create(&wfil->sem_task_run, 0);
|
|
err = task_create(enc_write_file_task, wfil, "enc_write");
|
|
if (err != OS_NO_ERR) {
|
|
log_e("task create err ");
|
|
goto _exit;
|
|
}
|
|
wfil->init_ok = 1;
|
|
|
|
return wfil;
|
|
|
|
_exit:
|
|
printf("\n--func=%s, line=%d\n", __FUNCTION__, __LINE__);
|
|
enc_write_file_close(wfil);
|
|
printf("\n--func=%s, line=%d\n", __FUNCTION__, __LINE__);
|
|
return NULL;
|
|
}
|
|
|
|
int enc_write_file_start(void *hdl)
|
|
{
|
|
struct enc_write_file *wfil = hdl;
|
|
|
|
if (wfil->init_ok) {
|
|
wfil->start = 1;
|
|
return 0;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
void enc_write_file_stop(void *hdl, u32 delay_ms)
|
|
{
|
|
struct enc_write_file *wfil = hdl;
|
|
|
|
if (wfil->start) {
|
|
wfil->wait_stop = 1;
|
|
u32 dly = 0;
|
|
do {
|
|
if (!wfil->wait_stop) {
|
|
break;
|
|
}
|
|
if (wfil->write_err) {
|
|
break;
|
|
}
|
|
os_time_dly(1);
|
|
dly += 10;
|
|
} while (dly < delay_ms);
|
|
wfil->start = 0;
|
|
}
|
|
}
|
|
|
|
void enc_write_file_set_head_handler(void *hdl, int (*set_head)(void *, char **head), void *set_head_hdl)
|
|
{
|
|
struct enc_write_file *wfil = hdl;
|
|
wfil->set_head = set_head;
|
|
wfil->set_head_hdl = set_head_hdl;
|
|
}
|
|
|
|
void enc_write_file_set_evt_handler(void *hdl, void (*evt_cb)(void *, int, int), void *evt_hdl)
|
|
{
|
|
struct enc_write_file *wfil = hdl;
|
|
wfil->evt_cb = evt_cb;
|
|
wfil->evt_hdl = evt_hdl;
|
|
}
|
|
|
|
void enc_write_file_set_input(void *hdl, struct audio_enc_write_input *input, void *input_hdl, u32 input_frame_len)
|
|
{
|
|
struct enc_write_file *wfil = hdl;
|
|
wfil->input = input;
|
|
wfil->input_hdl = input_hdl;
|
|
wfil->input_frame_len = input_frame_len;
|
|
}
|
|
|
|
void enc_write_file_set_limit(void *hdl, u32 cut_size, u32 limit_size)
|
|
{
|
|
struct enc_write_file *wfil = hdl;
|
|
wfil->cut_size = cut_size;
|
|
wfil->limit_size = limit_size;
|
|
}
|
|
|
|
int get_enc_file_len(void *hdl)
|
|
{
|
|
struct enc_write_file *wfil = hdl;
|
|
int filelen = 0;
|
|
if (!wfil) {
|
|
return -1;
|
|
}
|
|
if (wfil->file) {
|
|
filelen = wfil->file_size;
|
|
/* filelen = fpos(wfil->file); */
|
|
/* filelen = flen(wfil->file); */
|
|
}
|
|
return filelen;
|
|
}
|
|
|
|
|
|
void *get_wfil_head_hdl(void *enc_whdl)
|
|
{
|
|
struct enc_write_file *wfil = (struct enc_write_file *)enc_whdl;
|
|
return wfil->set_head_hdl;
|
|
}
|
|
|
|
FILE *get_wfil_file(void *enc_whdl)
|
|
{
|
|
struct enc_write_file *wfil = (struct enc_write_file *)enc_whdl;
|
|
return wfil->file;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
#if 0
|
|
|
|
#define W_OUTBUF_LEN (1 * 1024)
|
|
struct enc_write_test {
|
|
volatile u32 start : 1;
|
|
volatile u32 err : 1;
|
|
void *hdl;
|
|
OS_SEM sem_in;
|
|
OS_SEM sem_out;
|
|
u8 output_buf[W_OUTBUF_LEN];
|
|
cbuffer_t output_cbuf;
|
|
s16 output_frame[512 / 2]; //align 4Bytes
|
|
};
|
|
|
|
static void enc_w_evt(void *hdl, int err)
|
|
{
|
|
struct enc_write_test *tst = hdl;
|
|
printf("err: %d ", err);
|
|
if (err) {
|
|
tst->err = 1;
|
|
os_sem_set(&tst->sem_in, 0);
|
|
os_sem_post(&tst->sem_in);
|
|
os_sem_set(&tst->sem_out, 0);
|
|
os_sem_post(&tst->sem_out);
|
|
}
|
|
}
|
|
static int enc_w_set_head(void *hdl, char **head)
|
|
{
|
|
struct enc_write_test *tst = hdl;
|
|
u8 hdtab[] = "i'm head!!! ";
|
|
memcpy(tst->output_frame, hdtab, sizeof(hdtab));
|
|
*head = tst->output_frame;
|
|
return sizeof(hdtab);
|
|
}
|
|
|
|
static int enc_w_get(void *hdl, s16 **frame, u16 frame_len)
|
|
{
|
|
int rlen;
|
|
struct enc_write_test *tst = hdl;
|
|
do {
|
|
rlen = cbuf_read(&tst->output_cbuf, tst->output_frame, frame_len);
|
|
if (rlen == frame_len) {
|
|
break;
|
|
}
|
|
if (rlen == -EINVAL) {
|
|
return 0;
|
|
}
|
|
if (!tst->start) {
|
|
return 0;
|
|
}
|
|
if (tst->err) {
|
|
return 0;
|
|
}
|
|
os_sem_set(&tst->sem_in, 0);
|
|
os_sem_post(&tst->sem_in);
|
|
|
|
os_sem_pend(&tst->sem_out, 2);
|
|
} while (1);
|
|
|
|
*frame = tst->output_frame;
|
|
return rlen;
|
|
}
|
|
static void enc_w_put(void *hdl, s16 *frame)
|
|
{
|
|
}
|
|
|
|
const struct audio_enc_write_input enc_w_input = {
|
|
.get = enc_w_get,
|
|
.put = enc_w_put,
|
|
};
|
|
|
|
void enc_w_test(void)
|
|
{
|
|
struct enc_write_test *tst = zalloc(sizeof(struct enc_write_test));
|
|
printf("%s,%d ", __func__, __LINE__);
|
|
if (!tst) {
|
|
return ;
|
|
}
|
|
printf("%s,%d ", __func__, __LINE__);
|
|
os_sem_create(&tst->sem_in, 0);
|
|
os_sem_create(&tst->sem_out, 0);
|
|
cbuf_init(&tst->output_cbuf, tst->output_buf, W_OUTBUF_LEN);
|
|
|
|
printf("%s,%d ", __func__, __LINE__);
|
|
tst->hdl = enc_write_file_open("sd0", "/"REC_FOLDER_NAME, "AC690000.MP3");
|
|
printf("%s,%d ", __func__, __LINE__);
|
|
if (!tst->hdl) {
|
|
goto __exit;
|
|
}
|
|
|
|
printf("%s,%d ", __func__, __LINE__);
|
|
enc_write_file_set_evt_handler(tst->hdl, enc_w_evt, tst);
|
|
enc_write_file_set_input(tst->hdl, &enc_w_input, tst, sizeof(tst->output_frame));
|
|
enc_write_file_set_head_handler(tst->hdl, enc_w_set_head, tst);
|
|
enc_write_file_set_limit(tst->hdl, 123, 5000);
|
|
printf("%s,%d ", __func__, __LINE__);
|
|
|
|
tst->start = 1;
|
|
|
|
enc_write_file_start(tst->hdl);
|
|
|
|
int cnt = 0;
|
|
u8 str[] = "This is a test string.";
|
|
while (cnt < 1000) {
|
|
/* printf("%s,%d ", __func__, __LINE__); */
|
|
int len = cbuf_write(&tst->output_cbuf, str, sizeof(str));
|
|
os_sem_set(&tst->sem_out, 0);
|
|
os_sem_post(&tst->sem_out);
|
|
enc_write_file_resume(tst->hdl);
|
|
/* printf("%s,%d ", __func__, __LINE__); */
|
|
if (len != sizeof(str)) {
|
|
putchar('N');
|
|
os_sem_pend(&tst->sem_in, 2);
|
|
} else {
|
|
putchar('Y');
|
|
cnt++;
|
|
}
|
|
if (tst->err) {
|
|
os_sem_set(&tst->sem_out, 0);
|
|
os_sem_post(&tst->sem_out);
|
|
break;
|
|
}
|
|
}
|
|
|
|
__exit:
|
|
printf("%s,%d ", __func__, __LINE__);
|
|
tst->start = 0;
|
|
if (tst->hdl) {
|
|
enc_write_file_stop(tst->hdl, 1000);
|
|
enc_write_file_close(tst->hdl);
|
|
tst->hdl = 0;
|
|
}
|
|
printf("%s,%d ", __func__, __LINE__);
|
|
free(tst);
|
|
}
|
|
#endif
|
|
|
|
#endif
|
|
|