1、摄像头添加SD卡录满处理;
2、修复摄像头、科大讯飞等相关问题;
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
// 打印流头信息(增强版)
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user