1、摄像头添加SD卡录满处理;

2、修复摄像头、科大讯飞等相关问题;
This commit is contained in:
huxi
2026-01-08 11:29:46 +08:00
parent dc11ee3fc4
commit 36e62db3a4
65 changed files with 3092 additions and 2904 deletions
+19 -1
View File
@@ -30,7 +30,7 @@
//创建另外的文件存储AVI索引, 节约ram内存。在结束录像时合并索引到AVI文件中
#define AVI_INDXE_FILE_ENABLE 1
#define AVI_INDXE_FILE_SAME_NAME 1//使用相同文件名
//#include <time.h>
#if TCFG_PSRAM_DEV_ENABLE
#define malloc(size) malloc_psram(size)
@@ -78,6 +78,9 @@ static size_t avi_read(void *fd, char *buf, size_t len)
static size_t avi_write(void *fd, char *buf, size_t len)
{
/* u32 rets; */
/* __asm__ volatile("%0 = rets":"=r"(rets)); */
/* printf("[avi_w]len:%d rets:%x", (u32)len, rets); */
size_t n = 0;
size_t r = 0;
@@ -353,10 +356,25 @@ avi_t *AVI_open_output_file(char *filename)
strcpy(index_filename, filename);
if (dir_path) {
dir_path++;
#if AVI_INDXE_FILE_SAME_NAME
sprintf(index_filename + (dir_path - filename), "IDX.idx");
#else
sprintf(index_filename + (dir_path - filename), "IDX_****.idx");
#endif
} else {
#if AVI_INDXE_FILE_SAME_NAME
sprintf(index_filename, "IDX.idx");
#else
sprintf(index_filename, "%s.idx", filename);
#endif
}
#if AVI_INDXE_FILE_SAME_NAME
FILE *fp_tmp = fopen(index_filename, "r");
if (fp_tmp) {
fdelete(fp_tmp);
fp_tmp = NULL;
}
#endif
/* printf("index :%s \n", index_filename); */
AVI->index_fdes = fopen(index_filename, "w+");
if (AVI->index_fdes == NULL) {
+18 -15
View File
@@ -123,9 +123,9 @@ u16 app_video_task_switch_flag_set(u16 flag)
#define AVI_FILE_COUNT (sizeof(avi_files) / sizeof(avi_files[0]))
static void parse_list_chunk(FILE *file, long list_end, ChunkCallback callback,
void *user_param, long file_size, const char **parent_hierarchy,
int parent_level);
static int parse_list_chunk(FILE *file, long list_end, ChunkCallback callback,
void *user_param, long file_size, const char **parent_hierarchy,
int parent_level);
typedef void (*DisplayMJpegFunc)(void *player, FILE *file, int data, int chunk_size, int width, int height);
typedef void (*PlayPCMFunc)(void *player, FILE *file, int data, int chunk_size);
@@ -479,6 +479,7 @@ char parse_riff_file(FILE *file, ChunkCallback callback, void *user_param, int
log_info("\n\n\n\n\nRIFF chunk_size: %d\n\n\n\n\n", chunk_size);
/* 校验块大小合法性 */
long current_pos = ftell(file) - __this->file_offset;
/* printf("%s 111 chunk:%s current_pos: %d, chunk_size: %d, file_size: %d", __func__, chunk_id, (int)current_pos, chunk_size, (int)file_size); */
log_info("\n\n\n\n[%s]current_pos: %d, chunk_size: %d, file_size: %d\n\n\n\n", __func__, (int)current_pos, chunk_size, (int)file_size);
if (current_pos + chunk_size > file_size) {
log_info("校验块大小合法性 %d %d %d", (int)current_pos, chunk_size, (int)file_size);
@@ -507,9 +508,9 @@ char parse_riff_file(FILE *file, ChunkCallback callback, void *user_param, int
log_error("Failed to read sub chunk size");
return -AVI_READ_SUB_CHUNK_ID_FAIL;
}
/* 校验子块大小 */
current_pos = ftell(file) - __this->file_offset;
/* printf("%s 222 chunk:%s current_pos: %d, chunk_size: %d, file_size: %d", __func__, sub_chunk_id, (int)current_pos, sub_chunk_size, (int)file_size); */
if (current_pos + sub_chunk_size > file_size) {
log_info("校验子块大小 %d %d %d", (int)current_pos, sub_chunk_size, (int)file_size);
log_error("Sub chunk exceeds file size");
@@ -541,9 +542,9 @@ char parse_riff_file(FILE *file, ChunkCallback callback, void *user_param, int
fseek(file, current_pos + sub_chunk_size, SEEK_SET);
} else {
long list_end = ftell(file) - __this->file_offset + sub_chunk_size - 4;
parse_list_chunk(file, list_end, callback, user_param, file_size,
list_hierarchy, 4);
int ret = parse_list_chunk(file, list_end, callback, user_param, file_size,
list_hierarchy, 4);
return ret;
fseek(file, current_pos + sub_chunk_size, SEEK_SET); // add
}
} else {
@@ -567,9 +568,9 @@ char parse_riff_file(FILE *file, ChunkCallback callback, void *user_param, int
return 0;
}
/* LIST块解析实现 */
static void parse_list_chunk(FILE *file, long list_end, ChunkCallback callback,
void *user_param, long file_size, const char **parent_hierarchy,
int parent_level)
static int parse_list_chunk(FILE *file, long list_end, ChunkCallback callback,
void *user_param, long file_size, const char **parent_hierarchy,
int parent_level)
{
while (ftell(file) - __this->file_offset < list_end) {
wdt_clear();
@@ -580,20 +581,21 @@ static void parse_list_chunk(FILE *file, long list_end, ChunkCallback callback,
/* 读取子块头 */
if (avi_fread(sub_chunk_id, 1, 4, file) != 4) {
log_error("Failed to read sub chunk ID");
return;
return -AVI_READ_SUB_CHUNK_ID_FAIL;
}
sub_chunk_id[4] = '\0';
if (avi_fread(&sub_chunk_size, 4, 1, file) != 1) {
log_error("Failed to read sub chunk size");
return;
return -AVI_READ_SUB_CHUNK_SIZE_FAIL;
}
/* 校验子块大小 */
long current_pos = ftell(file) - __this->file_offset;
/* printf("%s 333 chunk:%s current_pos: %d, chunk_size: %d, file_size: %d", __func__, sub_chunk_id, (int)current_pos, sub_chunk_size, (int)file_size); */
if (current_pos + sub_chunk_size > file_size) {
log_error("Sub chunk exceeds file size");
return;
return -AVI_SUB_CHUNK_LEN_ERR;
}
/* 构建层级信息 */
@@ -608,7 +610,7 @@ static void parse_list_chunk(FILE *file, long list_end, ChunkCallback callback,
if (avi_fread(list_type, 1, 4, file) != 4) {
log_error("Failed to read nested LIST type");
avi_free(current_hierarchy);
return;
return -AVI_LIST_TYPE_ERR;
}
list_type[4] = '\0';
@@ -654,6 +656,7 @@ static void parse_list_chunk(FILE *file, long list_end, ChunkCallback callback,
avi_free(current_hierarchy);
}
return 0;
}
// 打印流头信息(增强版)
+87 -10
View File
@@ -28,7 +28,10 @@ extern u16 app_video_task_switch_flag_get();
#define MIC_FREMA_SIZE (4*1024)
#define MIC_BUFFER_SIZE (MIC_FREMA_SIZE*2+512)
#define MIC_SIMPLE_RATE (8000)
#define VIDEO_REC_START_MIN_SIZE (100)//单位是k
#define VIDEO_REC_FILE_MIN_SIZE (20)//单位是k
#define AVI_IDX_LEN (16)
#define AVI_FRAME_HEAD (8)
enum {
Q_AVI_TASK_KILL = (Q_USER + 100),
Q_AVI_TASK_REC_START,
@@ -53,11 +56,13 @@ struct video_rec_handle {
void *mic;
u8 *mic_frame;
char avi_task_name[32];
u8 write_error; //写文件异常
s8 write_error; //写文件异常 :-1 avilib返回异常,-2 空间不足
u8 busy;
int aframe_size;
int video_rate;
int sample_rate;
int avi_file_size; //预估文件大小
/* int real_file_size; //真实文件大小 */
void (*ui_refresh_cb)(int status);
int bytes_per_sample;
struct fill_frame fill;
@@ -228,13 +233,18 @@ static void jljpeg_frame_fill_judge(avi_t *out_fd, u32 frame_cnt)
/* printf("avi dup video fps :%d act fps:%d ,ext fps: %d %d\n", __this->fill.cnt_fnum / __this->fill.secs, __this->fill.one_sec_fps, __this->fill.fps,__this->fill.fnum); */
__this->fill.one_sec_fps = 0;
}
__again:
if (__this->fill.fnum && __this->fill.fill_frame_en) {
int ret = AVI_dup_frame(out_fd);
if (!ret) {
__this->avi_file_size += AVI_IDX_LEN * 2;
/* __this->real_file_size += AVI_IDX_LEN; */
/* printf("real1 dt:%d", AVI_IDX_LEN); */
__this->fill.cnt_fnum++;
__this->fill.fnum--;
if (__this->fill.fnum > __this->fill.fps / 3) {
goto __again;
}
}
}
}
@@ -254,7 +264,7 @@ static int jljpeg_frame_dropping_judge()
u32 msecs = jiffies_msec2offset(__this->fill.msecs, jiffies_msec());
/* printf("%d %d %d\n",(__this->fill.one_sec_fps+1) , (msecs*__this->fill.fps/1000),msecs); */
if ((__this->fill.one_sec_fps) > (msecs * __this->fill.fps / 1000) + 1) {
/* printf("fps > %d ,need droping\n",__this->fill.fps); */
printf("fps > %d ,need droping\n", __this->fill.fps);
if (__this->fill.fnum) {
__this->fill.fnum--;
return 0;
@@ -283,7 +293,7 @@ static void video_show_task(void *priv)
char *filename = NULL;
avi_t *out_fd = NULL;
u32 free_space = 0;
camera_manager_get_dev_width_height(&frame_width, &frame_height);
log_info("%s frame[%d x %d] \n", __func__, frame_width, frame_height);
@@ -325,8 +335,19 @@ static void video_show_task(void *priv)
break;
} else if (msg[0] == Q_AVI_TASK_REC_START) {
filename = (char *)msg[1];
fget_free_space(filename, &free_space);
printf("[VDO_DEBUG]free_space:%d \n", free_space);
if (free_space <= VIDEO_REC_START_MIN_SIZE) {
log_error("avi task rec start not enough space:%dk\n", free_space);
__this->write_error = -2;
continue;
}
cyc_time = msg[2];
__this->write_error = 0;
__this-> avi_file_size = 0;
/* __this->real_file_size = 0; */
log_debug("avi task rec start <%s> cyc_time:%d !\n", filename, cyc_time);
#if MIC_DATA_FORM_PCM_TASK_ENABLE
__this->pcm_hdl = pcm_data_init(__this->sample_rate, __this->aframe_size, __this->aframe_size * 10);
@@ -373,10 +394,11 @@ static void video_show_task(void *priv)
ret = AVI_close(out_fd);
if (ret) {
log_error("camera devide avi close err :%d \n", ret);
__this->write_error = 1;
__this->write_error = -1;
/* ASSERT(0); */
} else {
log_debug("avi write success \n");
/* printf("real_file_size:%d", __this->real_file_size); */
}
out_fd = NULL;
}
@@ -408,14 +430,29 @@ static void video_show_task(void *priv)
#if MIC_DATA_FORM_PCM_TASK_ENABLE
if (pcm_data_read(__this->pcm_hdl, &pcm_data, &pcm_data_len) == 0) {
read_data = 1;
__this->write_error = AVI_write_audio(out_fd, (char *)pcm_data, pcm_data_len);
ret = AVI_write_audio(out_fd, (char *)pcm_data, pcm_data_len);
if (!ret) {
__this->avi_file_size += (AVI_IDX_LEN * 2 + AVI_FRAME_HEAD + pcm_data_len);
/* __this->real_file_size += (AVI_IDX_LEN + AVI_FRAME_HEAD + pcm_data_len); */
/* printf("real2 dt:%d", (AVI_IDX_LEN + AVI_FRAME_HEAD + pcm_data_len)); */
} else {
__this->write_error = -1;
}
pcm_data_read_done(__this->pcm_hdl, pcm_data);
}
#else
if (__this->mic && __this->mic_frame) {
if (mic_data_read(__this->mic, __this->mic_frame, MIC_FREMA_SIZE)) {
read_data = 1;
__this->write_error = AVI_write_audio(out_fd, (char *)__this->mic_frame, MIC_FREMA_SIZE);
ret = AVI_write_audio(out_fd, (char *)__this->mic_frame, MIC_FREMA_SIZE);
if (!ret) {
__this->avi_file_size += (AVI_IDX_LEN * 2 + AVI_FRAME_HEAD + MIC_FREMA_SIZE);
/* __this->real_file_size += (AVI_IDX_LEN + AVI_FRAME_HEAD + MIC_FREMA_SIZE); */
/* printf("real3 dt:%d", (AVI_IDX_LEN + AVI_FRAME_HEAD + MIC_FREMA_SIZE)); */
} else {
__this->write_error = -1;
}
}
}
#endif
@@ -456,7 +493,15 @@ static void video_show_task(void *priv)
#endif
if (out_fd) { //录像输出
if (!jljpeg_frame_dropping_judge()) {
__this->write_error = AVI_write_frame(out_fd, (char *)jpeg_data, jpeg_data_len, 1);
ret = AVI_write_frame(out_fd, (char *)jpeg_data, jpeg_data_len, 1);
if (!ret) {
__this->avi_file_size += (AVI_IDX_LEN * 2 + AVI_FRAME_HEAD + (jpeg_data_len + 1) / 2 * 2);
/* __this->real_file_size += (AVI_IDX_LEN + AVI_FRAME_HEAD + (jpeg_data_len + 1) / 2 * 2); */
/* printf("real4 dt:%d", (AVI_IDX_LEN + AVI_FRAME_HEAD + jpeg_data_len)); */
} else {
__this->write_error = -1;
}
jljpeg_frame_fill_judge(out_fd, 1); //补帧计算
} else {
jljpeg_frame_fill_judge(out_fd, 0); //补帧计算
@@ -506,6 +551,38 @@ static void video_show_task(void *priv)
frame_cnt = 0;
}
}
if (out_fd) {
/* printf("[video_rec]fsize:%d left:%d dt:%d \n",__this->avi_file_size,free_space*1024,free_space*1024 -__this->avi_file_size); */
if ((__this->avi_file_size + VIDEO_REC_FILE_MIN_SIZE * 1024) >= (free_space * 1024)) {
ret = AVI_close(out_fd);
if (ret) {
log_error("camera devide avi close err :%d \n", ret);
__this->write_error = -1;
/* ASSERT(0); */
} else {
log_debug("avi write success \n");
/* printf(">>>real_file_size:%d", __this->real_file_size); */
}
out_fd = NULL;
#if MIC_DATA_FORM_PCM_TASK_ENABLE
if (__this->pcm_hdl) {
pcm_data_exit(__this->pcm_hdl);
__this->pcm_hdl = NULL;
}
#else
if (__this->mic) {
mic_data_close(__this->mic);
__this->mic = NULL;
}
if (__this->mic_frame) {
free(__this->mic_frame);
__this->mic_frame = NULL;
}
#endif
__this->write_error = -2;
/* break; */
}
}
//没有读到数据
if (!read_data) {