Files
TAIXIN/sdk/app/video_app/file_common_api.c

403 lines
12 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "file_common_api.h"
#include "lib/fs/fatfs/osal_file.h"
#include "app/video_app/file_thumb.h"
#include "osal/string.h"
#include "lwip/sockets.h"
static uint8_t get_rtc_time_str(char *timestr, uint8_t timestr_len, struct timeval *t)
{
struct tm *time_info;
struct timeval *time = t;
struct timeval ptimeval;
if(!time)
{
time = &ptimeval;
gettimeofday(time, NULL);
}
time_t time_val = (time_t)time->tv_sec;
int ms = time->tv_usec / 1000;
time_info = gmtime(&time_val);
if (time_info == NULL) {
_os_printf("gmtime error\r\n");
return 1;
}
os_snprintf(timestr, timestr_len, "%04d%02d%02d%02d%02d%02d%03d",
time_info->tm_year + 1900, time_info->tm_mon + 1, time_info->tm_mday,
time_info->tm_hour, time_info->tm_min, time_info->tm_sec, ms);
return 0;
}
/*
* 获取JPG文件路径不按天存储
* img_dir: 录像目录0:/IMG
* file_path: 文件名,格式: 0:/IMG/20250918010101000.JPG
* filepath_size: 文件名大小
*/
uint8_t takephoto_name(const char *img_dir, char *file_path, int filepath_size)
{
char timestr[FILE_NAME_LEN + 1];
if(get_rtc_time_str(timestr, FILE_NAME_LEN + 1, NULL))
return 1;
os_snprintf(file_path, filepath_size, "%s/%.*s.JPG", img_dir, FILE_NAME_LEN, timestr);
return 0;
}
/*
* 获取JPG文件路径按天存储
* img_dir: 录像目录0:/IMG
* file_path: 文件名,格式: 0:/IMG/20250918/20250918010101000.JPG
* filepath_size: 文件名大小
*/
uint8_t takephoto_name_day(const char *img_dir, char *file_path, int filepath_size)
{
char timestr[FILE_NAME_LEN + 1];
if(get_rtc_time_str(timestr, FILE_NAME_LEN + 1, NULL))
return 1;
os_snprintf(file_path, filepath_size, "%s/%.*s/%.*s.JPG", img_dir, FILE_SUB_PATH_LEN, timestr, FILE_NAME_LEN, timestr);
return 0;
}
/*
* 获取JPG文件名称
* filename: 文件名,格式: 20250918010101000.JPG
* filename_size: 文件名大小
*/
int32_t takephoto_name_no_dir(char *filename, int filename_size)
{
char timestr[FILE_NAME_LEN + 1];
if(get_rtc_time_str(timestr, FILE_NAME_LEN + 1, NULL))
return 1;
os_snprintf(filename, filename_size, "%.*s.JPG", FILE_NAME_LEN, timestr);
return 0;
}
/*
* 获取JPG文件名称
* filename: 文件名,格式: 20250918010101000.JPG
* filename_size: 文件名大小
* time: 时间
*/
int32_t takephoto_name_no_dir_time(char *filename, int filename_size, struct timeval *time)
{
char timestr[FILE_NAME_LEN + 1];
if(get_rtc_time_str(timestr, FILE_NAME_LEN + 1, time))
return 1;
os_snprintf(filename, filename_size, "%.*s.JPG", FILE_NAME_LEN, timestr);
return 0;
}
/*
* 为JPG文件添加目录
* path: 文件路径,格式: dir_name/filename
* path_size: 文件路径大小
*/
int32_t takephoto_name_add_dir(char *filename, int filename_size, char *path, const char *dir_name)
{
if(dir_name)
{
os_snprintf(filename, filename_size,"%s/%s", dir_name, path);
}
else
{
os_snprintf(filename, filename_size,"%s", path);
}
return 0;
}
/*
* 获取MP4文件名
* rec_dir: 录像目录0:/REC
* sub_path: 子目录,格式: 0:/REC/20250918
* file_name: 文件名,格式: 20250918010101000.MP4
*/
uint8_t get_mp4_file_name(const char *rec_dir, char *sub_path, char *file_name)
{
char timestr[FILE_NAME_LEN + 1];
if(get_rtc_time_str(timestr, FILE_NAME_LEN + 1, NULL))
return 1;
os_sprintf(sub_path, "%s/%.*s", rec_dir, FILE_SUB_PATH_LEN, timestr);
os_sprintf(file_name, "%.*s.MP4", FILE_NAME_LEN, timestr);
return 0;
}
/*
* 获取文件名
* rec_dir: 录像目录0:/RECA
* sub_path: 子目录,格式: 0:/RECA/20250918
* file_name: 文件名,格式: 20250918010101000.MP4
* extension_name: 文件扩展名,格式: .MP4/.AVI/...
*/
uint8_t get_extension_file_name(const char *rec_dir, char *sub_path, char *file_name, const char *extension_name)
{
char timestr[FILE_NAME_LEN + 1];
if(get_rtc_time_str(timestr, FILE_NAME_LEN + 1, NULL))
return 1;
os_sprintf(sub_path, "%s/%.*s", rec_dir, FILE_SUB_PATH_LEN, timestr);
os_sprintf(file_name, "%.*s%s", FILE_NAME_LEN, timestr, extension_name);
return 0;
}
/*
* 获取文件名
* rec_dir: 录像目录0:/RECA
* sub_path: 子目录,格式: 0:/RECA/20250918
* file_name: 文件名,格式: 20250918010101000.MP4
* extension_name: 文件扩展名,格式: .MP4/.AVI/...
* time: 时间
*/
uint8_t get_extension_file_name_time(const char *rec_dir, char *sub_path, char *file_name, const char *extension_name, struct timeval *time)
{
char timestr[FILE_NAME_LEN + 1];
if(get_rtc_time_str(timestr, FILE_NAME_LEN + 1, time))
return 1;
os_sprintf(sub_path, "%s/%.*s", rec_dir, FILE_SUB_PATH_LEN, timestr);
os_sprintf(file_name, "%.*s%s", FILE_NAME_LEN, timestr, extension_name);
return 0;
}
/*
* 根据文件类型获取照片文件路径
* filename: 文件名
* path: 文件路径
* pathsize: 文件路径大小
*/
void gen_photo_path(const char *filename, char *path, uint32_t pathsize)
{
const char *rec_path = NULL;
const char* file_dot = strrchr(filename, '.');
if(file_dot == NULL) {
os_printf("%s file_dot is NULL\n", __FUNCTION__);
return;
}
if(os_strstr(filename, FRONT_SUFFIX)) {
rec_path = IMGA_PATH;
} else if(os_strstr(filename, INTER_SUFFIX)) {
rec_path = IMGB_PATH;
} else if(os_strstr(filename, BACK_SUFFIX)) {
rec_path = IMGC_PATH;
} else {
rec_path = IMG_PATH;
}
os_snprintf(path, pathsize, "%s/%.*s%s", rec_path, FILE_NAME_LEN, filename, file_dot);
os_printf("%s path: %s\n", __FUNCTION__, path);
}
/*
* 根据文件类型获取视频文件路径
* filename: 文件名
* path: 文件路径
* pathsize: 文件路径大小
*/
void gen_video_path(const char *filename, char *path, uint32_t pathsize)
{
uint8_t prefix_len = 0;
const char *rec_path = NULL;
const char *file_name = os_strrchr(filename, '/');
if(file_name == NULL) {
file_name = filename;
}
const char* file_dot = strrchr(filename, '.');
if(file_dot == NULL) {
os_printf("%s file_dot is NULL\n", __FUNCTION__);
return;
}
if(os_strstr(file_name, SOS_PREFIX)) {
prefix_len = strlen(SOS_PREFIX);
} else if(os_strstr(file_name, PARKF_PREFIX)) {
prefix_len = strlen(PARKF_PREFIX);
}
if(os_strstr(file_name, FRONT_SUFFIX)) {
rec_path = RECA_PATH;
} else if(os_strstr(file_name, INTER_SUFFIX)) {
rec_path = RECB_PATH;
} else if(os_strstr(file_name, BACK_SUFFIX)) {
rec_path = RECC_PATH;
} else {
rec_path = REC_PATH;
}
os_snprintf(path, pathsize, "%s/%.*s/%.*s%s", rec_path, FILE_SUB_PATH_LEN, file_name + prefix_len, FILE_NAME_LEN + prefix_len, file_name, file_dot);
os_printf("%s path: %s\n", __FUNCTION__, path);
}
void gen_photo_video_path(const char *filename, char *path, uint32_t pathsize)
{
if(os_strstr(filename, JPG_EXTENSION_NAME))
{
gen_photo_path(filename, path, pathsize);
}
else if(os_strstr(filename, MP4_EXTENSION_NAME) || os_strstr(filename, AVI_EXTENSION_NAME))
{
gen_video_path(filename, path, pathsize);
}
else
{
_os_printf("filename %s format err!\n", filename);
}
}
/***************************************************************
* 获取文件列表接口 *
* *
****************************************************************/
typedef void (* conver_send_fn)(int fd, struct file_info *file_info);
void send_chunk(int fd, const char* data, uint16_t data_len)
{
char chunk_buffer[256]; // 或者使用动态分配
int chunk_len = os_snprintf(chunk_buffer, sizeof(chunk_buffer), "%x\r\n%s\r\n", data_len, data);
send(fd, chunk_buffer, chunk_len, 0);
}
void conver_send(int fd, struct file_info *file_info)
{
char send_buffer[256];
char timestr[15];
os_snprintf(timestr, sizeof(timestr), "%04d%02d%02d%02d%02d%02d",
((file_info->file_date & 0xFE00)>>9)+1980,
(file_info->file_date & 0x1E0)>>5,
(file_info->file_date & 0x1F),
(file_info->file_time & 0xF800)>>11,
(file_info->file_time & 0x7E0)>>5,
(file_info->file_time & 0x1F)*2);
os_snprintf(send_buffer, sizeof(send_buffer), "%s{\"name\":\"%s\",\"size\":%d,\"createtimestr\":\"%s\"}",
(file_info->file_count++ > 0) ? "," : "",
file_info->file_name,
file_info->file_size / 1024,
timestr);
// 发送数据
send_chunk(fd, send_buffer, strlen(send_buffer));
}
int get_fileinfo_send(int fd, const char *search_dir, const char *ext_name, conver_send_fn cs_fn)
{
struct file_info file_info;
FILINFO *fil = NULL;
void *dir = osal_opendir(search_dir);
if (dir)
{
do
{
fil = osal_readdir(dir);
if(!fil) break;
if(fil->fname[0] == 0) break;
if (fil->fname[0] == '.') continue;
if(!osal_dirent_isdir(fil))
{
char *filename = osal_dirent_name(fil);
uint32_t filesize = osal_dirent_size(fil);
uint32_t filedate = osal_dirent_date(fil);
uint32_t filetime = osal_dirent_time(fil);
uint8_t filename_len = os_strlen(filename);
// 检查后缀名是否匹配
if(ext_name)
{
uint8_t ext_filename[16];
uint8_t extname_len = os_strlen(ext_name);
// 进行全部转换成大写
if (filename_len - extname_len > 0)
{
for (uint8_t i = 0; i < os_strlen(ext_name); i++)
{
ext_filename[i] = toupper(filename[filename_len - extname_len + i]);
}
// 后缀名匹配
if (memcmp(ext_name, ext_filename, extname_len) != 0)
{
continue;
}
}
}
file_info.file_name = filename;
file_info.file_size = filesize;
file_info.file_date = filedate;
file_info.file_time = filetime;
file_info.file_count++;
cs_fn(fd, &file_info);
}
} while (fil);
osal_closedir(dir);
}
return file_info.file_count;
}
// 发送demo采用分块发送的方式
void send_stream_filelist(int fd)
{
int video_count = 0;
int photo_count = 0;
char send_buffer[256];
// 创建HTTP响应头
snprintf(send_buffer, sizeof(send_buffer),
"HTTP/1.0 200 OK\r\n"
"Connection: close\r\n"
"Content-Type: application/json\r\n"
"Transfer-Encoding: chunked\r\n"
"\r\n");
send(fd, send_buffer, strlen(send_buffer), 0);
// 获取视频
os_snprintf(send_buffer, sizeof(send_buffer), "{\"result\":0,\"info\":[{\"folder\":\"%s\",\"files\":[", LOOP_PREFIX);
send_chunk(fd, send_buffer, strlen(send_buffer));
void *dir = osal_opendir(REC_PATH);
FILINFO *fil = NULL;
char path[64];
if(dir)
{
do
{
fil = osal_readdir(dir);
if(!fil) break;
if(fil->fname[0] == 0) break;
if (fil->fname[0] == '.') continue;
if(osal_dirent_isdir(fil))
{
os_snprintf(path, sizeof(path), "%s/%s", REC_PATH, fil->fname);
video_count += get_fileinfo_send(fd, path, MP4_EXTENSION_NAME, conver_send);
send_chunk(fd, ",", strlen(","));
}
} while(fil);
}
// 获取照片
os_snprintf(send_buffer, sizeof(send_buffer), "],\"count\":%d},{\"folder\":\"%s\",\"files\":[", video_count, EVENT_PREFIX);
send_chunk(fd, send_buffer, strlen(send_buffer));
photo_count = get_fileinfo_send(fd, IMG_PATH, JPG_EXTENSION_NAME, conver_send);
os_snprintf(send_buffer, sizeof(send_buffer), "],\"count\":%d}]}", photo_count);
send_chunk(fd, send_buffer, strlen(send_buffer));
// 发送分块结束标记
send_chunk(fd, "", 0); // 0长度块表示结束
}