537 lines
19 KiB
C
537 lines
19 KiB
C
// #include "thumb_msi.h"
|
|
#include "basic_include.h"
|
|
#include "lib/multimedia/msi.h"
|
|
#include "lib/fs/fatfs/osal_file.h"
|
|
#include "stream_define.h"
|
|
#include "video_app/file_thumb.h"
|
|
#include "user_work/user_work.h"
|
|
#include "lib/heap/av_heap.h"
|
|
#include "lib/heap/av_psram_heap.h"
|
|
#include "video_msi.h"
|
|
#include "video_app/file_common_api.h"
|
|
|
|
#define USER_WORK 1
|
|
#define MAX_THUMB_MSI 16
|
|
#define MAX_RECV_MAX 16
|
|
|
|
// data申请空间函数
|
|
#define STREAM_MALLOC av_psram_malloc
|
|
#define STREAM_FREE av_psram_free
|
|
#define STREAM_ZALLOC av_psram_zalloc
|
|
|
|
// 结构体申请空间函数
|
|
#ifdef MORE_SRAM
|
|
#define STREAM_LIBC_MALLOC av_psram_malloc
|
|
#define STREAM_LIBC_FREE av_psram_free
|
|
#define STREAM_LIBC_ZALLOC av_psram_zalloc
|
|
#else
|
|
#define STREAM_LIBC_MALLOC av_malloc
|
|
#define STREAM_LIBC_FREE av_free
|
|
#define STREAM_LIBC_ZALLOC av_zalloc
|
|
#endif
|
|
|
|
enum thumb_thread_enum
|
|
{
|
|
THUMB_THREAD_RUNNING = BIT(0),
|
|
THUMB_THREAD_EXIT = BIT(1),
|
|
THUMB_THREAD_DEADTH = BIT(2),
|
|
};
|
|
|
|
struct thumb_queue_fb
|
|
{
|
|
uint8_t datatag; // 对应的stype,按照顺序递增,只有stype匹配才可以
|
|
uint16_t time16; // 记录时间戳,只有16位,仅仅简单作为超时使用
|
|
uint8_t path[64]; // 记录缩略图的路径
|
|
};
|
|
|
|
#if USER_WORK == 0
|
|
struct thumb_msi_s
|
|
{
|
|
os_task_t task;
|
|
struct msi *msi;
|
|
struct os_event evt;
|
|
const char *normal_base_dir; // 设置如果是原图,则有个基础文件夹地址
|
|
uint32_t magic;
|
|
uint8_t ramdom_id; // 随机ID,实际最后与stype匹配用
|
|
uint8_t jpg_type; // 0:是缩略图 1:原图
|
|
uint8_t stype; // 设置自己的专有类型
|
|
RBUFFER_DEF(rb, struct thumb_queue_fb, MAX_THUMB_MSI);
|
|
};
|
|
|
|
static void thumb_msi_thread(void *d)
|
|
{
|
|
struct thumb_msi_s *thumb_msi = (struct thumb_msi_s *) d;
|
|
struct msi *msi = thumb_msi->msi;
|
|
struct framebuff *fb;
|
|
struct thumb_queue_fb t_fb;
|
|
uint8_t ret;
|
|
uint8_t path[80];
|
|
int32_t res;
|
|
uint32_t rflags;
|
|
msi_get(msi);
|
|
while (1)
|
|
{
|
|
rflags = 0;
|
|
res = os_event_wait(&thumb_msi->evt, THUMB_THREAD_RUNNING | THUMB_THREAD_EXIT, &rflags, OS_EVENT_WMODE_OR | OS_EVENT_WMODE_CLEAR, -1);
|
|
if (rflags & THUMB_THREAD_EXIT)
|
|
{
|
|
os_event_set(&thumb_msi->evt, THUMB_THREAD_DEADTH, NULL);
|
|
break;
|
|
}
|
|
|
|
thumb_msi_thread_get_fb_again:
|
|
fb = msi_get_fb(msi, 0);
|
|
// 获取到图片,判断stype与rb中的stype是否匹配
|
|
if (fb)
|
|
{
|
|
thumb_msi_thread_again:
|
|
ret = RB_INT_GET(&thumb_msi->rb, t_fb);
|
|
if (ret)
|
|
{
|
|
if (fb->datatag == t_fb.datatag)
|
|
{
|
|
// 生成缩略图
|
|
if (thumb_msi->jpg_type == 0)
|
|
{
|
|
gen_thumb_path((char *) t_fb.path, path, sizeof(path));
|
|
}
|
|
else
|
|
{
|
|
takephoto_name_add_dir(path, sizeof(path), (char *) t_fb.path, thumb_msi->normal_base_dir);
|
|
}
|
|
// 保存地址,转发出去
|
|
struct framebuff *send_fb = fb_clone(fb, F_FILE_T << 8 | fb->stype, msi);
|
|
ASSERT(send_fb);
|
|
struct file_msg_s *file_msg = (struct file_msg_s *) STREAM_LIBC_ZALLOC(sizeof(struct file_msg_s));
|
|
ASSERT(file_msg);
|
|
os_memcpy(file_msg->path, path, strlen(path) + 1);
|
|
if (thumb_msi->jpg_type == 0)
|
|
{
|
|
file_msg->ishid = 1;
|
|
}
|
|
send_fb->priv = (void *) file_msg;
|
|
msi_output_fb(msi, send_fb);
|
|
}
|
|
else
|
|
{
|
|
// 如果fb->stype > t_fb.stype?代表可能已经有漏数据,则忽略,继续寻找洗一张图
|
|
if (fb->datatag > t_fb.datatag)
|
|
{
|
|
goto thumb_msi_thread_again;
|
|
}
|
|
else
|
|
{
|
|
os_printf("thumb_msi_thread: no match fb->datatag:%X\tt_fb.datatag:%X\n", fb->datatag, t_fb.datatag);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
os_printf("thumb_msi_thread: no match fb,datatag:%X\tfb:%X\tret:%d\n", fb->datatag, fb, ret);
|
|
}
|
|
msi_delete_fb(NULL, fb);
|
|
// 去缓冲区继续查找是否有图片需要保存
|
|
goto thumb_msi_thread_get_fb_again;
|
|
}
|
|
}
|
|
msi_put(msi);
|
|
}
|
|
|
|
static int32_t thumb_msi_action(struct msi *msi, uint32_t cmd_id, uint32_t param1, uint32_t param2)
|
|
{
|
|
int32_t ret = RET_OK;
|
|
struct thumb_msi_s *thumb_msi = (struct thumb_msi_s *) msi->priv;
|
|
switch (cmd_id)
|
|
{
|
|
case MSI_CMD_POST_DESTROY:
|
|
{
|
|
os_event_wait(&thumb_msi->evt, THUMB_THREAD_DEADTH, NULL, OS_EVENT_WMODE_OR, -1);
|
|
os_event_del(&thumb_msi->evt);
|
|
STREAM_LIBC_FREE(thumb_msi);
|
|
}
|
|
break;
|
|
case MSI_CMD_PRE_DESTROY:
|
|
{
|
|
os_event_set(&thumb_msi->evt, THUMB_THREAD_EXIT, NULL);
|
|
}
|
|
break;
|
|
|
|
case MSI_CMD_FREE_FB:
|
|
{
|
|
struct framebuff *fb = (struct framebuff *) param1;
|
|
// fb由内部管理,仅仅删除私有结构
|
|
if (fb && fb->mtype == F_FILE_T)
|
|
{
|
|
if (fb->priv)
|
|
{
|
|
STREAM_LIBC_FREE(fb->priv);
|
|
fb->priv = NULL;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case MSI_CMD_TRANS_FB:
|
|
{
|
|
struct framebuff *fb = (struct framebuff *) param1;
|
|
// 通过YUV去生成缩略图
|
|
if (fb->mtype == F_YUV)
|
|
{
|
|
struct takephoto_yuv_arg_s *arg = (struct takephoto_yuv_arg_s *) fb->priv;
|
|
if (!thumb_msi->magic || arg->yuv_arg.magic == thumb_msi->magic)
|
|
{
|
|
// 记录path以及转发去生成真的缩略图
|
|
// 这里采用clone方式,将类型修改
|
|
thumb_msi->ramdom_id = (thumb_msi->ramdom_id + 1);
|
|
struct thumb_queue_fb t_fb;
|
|
t_fb.datatag = thumb_msi->ramdom_id;
|
|
t_fb.time16 = (uint16_t) (os_jiffies() & 0xffff);
|
|
|
|
// 配置参数,转发
|
|
if (arg && arg->yuv_arg.type == YUV_ARG_TAKEPHOTO)
|
|
{
|
|
os_memcpy(t_fb.path, arg->name, strlen(arg->name) + 1);
|
|
if (RB_INT_SET(&thumb_msi->rb, t_fb))
|
|
{
|
|
// 转发出去
|
|
struct framebuff *c_fb = fb_clone(fb, fb->mtype << 8 | thumb_msi->stype, msi);
|
|
if (c_fb)
|
|
{
|
|
c_fb->datatag = thumb_msi->ramdom_id;
|
|
msi_output_fb(msi, c_fb);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
msi_delete_fb(NULL, fb);
|
|
}
|
|
}
|
|
// 不需要接收到队列
|
|
ret = RET_ERR;
|
|
}
|
|
// 通过mjpeg去生成缩略图(需要转发到解码器去实现)
|
|
else if (fb->mtype == F_THUMB_JPG)
|
|
{
|
|
// 记录path以及转发去生成真的缩略图
|
|
// 这里采用clone方式,将类型修改
|
|
thumb_msi->ramdom_id = (thumb_msi->ramdom_id + 1);
|
|
struct thumb_queue_fb t_fb;
|
|
t_fb.datatag = thumb_msi->ramdom_id;
|
|
t_fb.time16 = (uint16_t) (os_jiffies() & 0xffff);
|
|
|
|
if (fb->priv)
|
|
{
|
|
os_memcpy(t_fb.path, fb->priv, strlen(fb->priv) + 1);
|
|
}
|
|
else
|
|
{
|
|
os_memset(t_fb.path, 0, sizeof(t_fb.path));
|
|
}
|
|
if (RB_INT_SET(&thumb_msi->rb, t_fb))
|
|
{
|
|
// 转发出去
|
|
struct framebuff *c_fb = fb_clone(fb, F_JPG << 8 | thumb_msi->stype, msi);
|
|
if (c_fb)
|
|
{
|
|
c_fb->datatag = thumb_msi->ramdom_id;
|
|
msi_output_fb(msi, c_fb);
|
|
}
|
|
}
|
|
ret = RET_ERR;
|
|
}
|
|
// 接收stype匹配才去保存图片,datatag作为id
|
|
else if ((fb->mtype == F_JPG || fb->mtype == F_JPG_NODE) && (fb->stype == thumb_msi->stype))
|
|
{
|
|
// 唤醒线程
|
|
os_event_set(&thumb_msi->evt, THUMB_THREAD_RUNNING, NULL);
|
|
}
|
|
else
|
|
{
|
|
ret = RET_ERR;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
struct msi *thumb_over_dpi_msi_init(const char *msi_name, uint8_t jpg_type, uint8_t stype, uint32_t magic)
|
|
{
|
|
uint8_t is_new;
|
|
struct msi *msi = msi_new(msi_name, MAX_RECV_MAX, &is_new);
|
|
struct thumb_msi_s *thumb_msi = NULL;
|
|
if (is_new)
|
|
{
|
|
thumb_msi = (struct thumb_msi_s *) STREAM_LIBC_ZALLOC(sizeof(struct thumb_msi_s));
|
|
msi->priv = thumb_msi;
|
|
thumb_msi->msi = msi;
|
|
thumb_msi->jpg_type = jpg_type;
|
|
thumb_msi->magic = magic;
|
|
thumb_msi->stype = stype;
|
|
thumb_msi->normal_base_dir = IMG_PATH;
|
|
RB_INIT(&thumb_msi->rb, MAX_THUMB_MSI);
|
|
msi->action = thumb_msi_action;
|
|
os_event_init(&thumb_msi->evt);
|
|
msi->enable = 1;
|
|
OS_TASK_INIT("thumb_msi_over_dpi", &thumb_msi->task, thumb_msi_thread, thumb_msi, OS_TASK_PRIORITY_NORMAL, NULL, 1500);
|
|
}
|
|
|
|
return msi;
|
|
}
|
|
#else
|
|
struct thumb_msi_s
|
|
{
|
|
struct os_work work;
|
|
struct msi *msi;
|
|
struct os_event evt;
|
|
const char *normal_base_dir; // 设置如果是原图,则有个基础文件夹地址
|
|
uint32_t magic;
|
|
uint8_t ramdom_id; // 随机ID,实际最后与stype匹配用
|
|
uint8_t jpg_type; // 0:是缩略图 1:原图
|
|
uint8_t stype; // 设置自己的专有类型
|
|
RBUFFER_DEF(rb, struct thumb_queue_fb, MAX_THUMB_MSI);
|
|
};
|
|
|
|
static int32_t thumb_msi_work(struct os_work *work)
|
|
{
|
|
struct thumb_msi_s *thumb_msi = (struct thumb_msi_s *) work;
|
|
struct msi *msi = thumb_msi->msi;
|
|
struct framebuff *fb;
|
|
struct thumb_queue_fb t_fb;
|
|
uint8_t ret;
|
|
char path[80];
|
|
int32_t res;
|
|
uint32_t rflags;
|
|
|
|
rflags = 0;
|
|
res = os_event_wait(&thumb_msi->evt, THUMB_THREAD_RUNNING | THUMB_THREAD_EXIT, &rflags, OS_EVENT_WMODE_OR | OS_EVENT_WMODE_CLEAR, -1);
|
|
if (rflags & THUMB_THREAD_EXIT)
|
|
{
|
|
os_event_set(&thumb_msi->evt, THUMB_THREAD_DEADTH, NULL);
|
|
goto thumb_msi_exit;
|
|
}
|
|
|
|
thumb_msi_thread_get_fb_again:
|
|
fb = msi_get_fb(msi, 0);
|
|
// 获取到图片,判断stype与rb中的stype是否匹配
|
|
if (fb)
|
|
{
|
|
thumb_msi_thread_again:
|
|
ret = RB_INT_GET(&thumb_msi->rb, t_fb);
|
|
if (ret)
|
|
{
|
|
if (fb->datatag == t_fb.datatag)
|
|
{
|
|
// 生成缩略图
|
|
if (thumb_msi->jpg_type == 0)
|
|
{
|
|
gen_thumb_path((char *) t_fb.path, path, sizeof(path));
|
|
}
|
|
else
|
|
{
|
|
takephoto_name_add_dir(path, sizeof(path), (char *) t_fb.path, thumb_msi->normal_base_dir);
|
|
}
|
|
// 保存地址,转发出去
|
|
struct framebuff *send_fb = fb_clone(fb, F_FILE_T << 8 | fb->stype, msi);
|
|
ASSERT(send_fb);
|
|
struct file_msg_s *file_msg = (struct file_msg_s *) STREAM_LIBC_ZALLOC(sizeof(struct file_msg_s));
|
|
ASSERT(file_msg);
|
|
os_memcpy(file_msg->path, path, strlen(path) + 1);
|
|
if (thumb_msi->jpg_type == 0)
|
|
{
|
|
file_msg->ishid = 1;
|
|
}
|
|
send_fb->priv = (void *) file_msg;
|
|
msi_output_fb(msi, send_fb);
|
|
}
|
|
else
|
|
{
|
|
// 如果fb->stype > t_fb.stype?代表可能已经有漏数据,则忽略,继续寻找洗一张图
|
|
if (fb->datatag > t_fb.datatag)
|
|
{
|
|
goto thumb_msi_thread_again;
|
|
}
|
|
else
|
|
{
|
|
os_printf("thumb_msi_thread: no match fb->datatag:%X\tt_fb.datatag:%X\n", fb->datatag, t_fb.datatag);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
os_printf("thumb_msi_thread: no match fb,datatag:%X\tfb:%X\tret:%d\n", fb->datatag, fb, ret);
|
|
}
|
|
msi_delete_fb(NULL, fb);
|
|
// 去缓冲区继续查找是否有图片需要保存
|
|
goto thumb_msi_thread_get_fb_again;
|
|
}
|
|
|
|
thumb_msi_exit:
|
|
return 0;
|
|
}
|
|
|
|
static int32_t thumb_msi_action(struct msi *msi, uint32_t cmd_id, uint32_t param1, uint32_t param2)
|
|
{
|
|
int32_t ret = RET_OK;
|
|
struct thumb_msi_s *thumb_msi = (struct thumb_msi_s *) msi->priv;
|
|
switch (cmd_id)
|
|
{
|
|
case MSI_CMD_POST_DESTROY:
|
|
{
|
|
// os_event_wait(&thumb_msi->evt, THUMB_THREAD_DEADTH, NULL, OS_EVENT_WMODE_OR, -1);
|
|
os_event_del(&thumb_msi->evt);
|
|
STREAM_LIBC_FREE(thumb_msi);
|
|
}
|
|
break;
|
|
case MSI_CMD_PRE_DESTROY:
|
|
{
|
|
os_event_set(&thumb_msi->evt, THUMB_THREAD_EXIT, NULL);
|
|
os_work_cancle2(&thumb_msi->work, 1);
|
|
}
|
|
break;
|
|
|
|
case MSI_CMD_FREE_FB:
|
|
{
|
|
struct framebuff *fb = (struct framebuff *) param1;
|
|
// fb由内部管理,仅仅删除私有结构
|
|
if (fb && fb->mtype == F_FILE_T)
|
|
{
|
|
if (fb->priv)
|
|
{
|
|
STREAM_LIBC_FREE(fb->priv);
|
|
fb->priv = NULL;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case MSI_CMD_TRANS_FB:
|
|
{
|
|
struct framebuff *fb = (struct framebuff *) param1;
|
|
// 通过YUV去生成缩略图
|
|
if (fb->mtype == F_YUV)
|
|
{
|
|
struct takephoto_yuv_arg_s *arg = (struct takephoto_yuv_arg_s *) fb->priv;
|
|
if (!thumb_msi->magic || arg->yuv_arg.magic == thumb_msi->magic)
|
|
{
|
|
// 记录path以及转发去生成真的缩略图
|
|
// 这里采用clone方式,将类型修改
|
|
thumb_msi->ramdom_id = (thumb_msi->ramdom_id + 1);
|
|
struct thumb_queue_fb t_fb;
|
|
t_fb.datatag = thumb_msi->ramdom_id;
|
|
t_fb.time16 = (uint16_t) (os_jiffies() & 0xffff);
|
|
|
|
// 配置参数,转发
|
|
if (arg && arg->yuv_arg.type == YUV_ARG_TAKEPHOTO)
|
|
{
|
|
os_memcpy(t_fb.path, arg->name, os_strlen(arg->name) + 1);
|
|
if (RB_INT_SET(&thumb_msi->rb, t_fb))
|
|
{
|
|
// 转发出去
|
|
struct framebuff *c_fb = fb_clone(fb, fb->mtype << 8 | thumb_msi->stype, msi);
|
|
if (c_fb)
|
|
{
|
|
c_fb->datatag = thumb_msi->ramdom_id;
|
|
msi_output_fb(msi, c_fb);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
msi_delete_fb(NULL, fb);
|
|
}
|
|
}
|
|
// 不需要接收到队列
|
|
ret = RET_ERR;
|
|
}
|
|
// 通过mjpeg去生成缩略图(需要转发到解码器去实现)
|
|
else if (fb->mtype == F_THUMB_JPG)
|
|
{
|
|
// 记录path以及转发去生成真的缩略图
|
|
// 这里采用clone方式,将类型修改
|
|
thumb_msi->ramdom_id = (thumb_msi->ramdom_id + 1);
|
|
struct thumb_queue_fb t_fb;
|
|
t_fb.datatag = thumb_msi->ramdom_id;
|
|
t_fb.time16 = (uint16_t) (os_jiffies() & 0xffff);
|
|
|
|
if (fb->priv)
|
|
{
|
|
os_memcpy(t_fb.path, fb->priv, strlen(fb->priv) + 1);
|
|
}
|
|
else
|
|
{
|
|
os_memset(t_fb.path, 0, sizeof(t_fb.path));
|
|
}
|
|
if (RB_INT_SET(&thumb_msi->rb, t_fb))
|
|
{
|
|
// 转发出去
|
|
struct framebuff *c_fb = fb_clone(fb, F_JPG << 8 | thumb_msi->stype, msi);
|
|
if (c_fb)
|
|
{
|
|
c_fb->datatag = thumb_msi->ramdom_id;
|
|
msi_output_fb(msi, c_fb);
|
|
}
|
|
}
|
|
ret = RET_ERR;
|
|
}
|
|
// 接收stype匹配才去保存图片,datatag作为id
|
|
else if ((fb->mtype == F_JPG || fb->mtype == F_JPG_NODE) && (fb->stype == thumb_msi->stype))
|
|
{
|
|
// 唤醒线程
|
|
// os_event_set(&thumb_msi->evt, THUMB_THREAD_RUNNING, NULL);
|
|
}
|
|
else
|
|
{
|
|
ret = RET_ERR;
|
|
}
|
|
}
|
|
break;
|
|
case MSI_CMD_TRANS_FB_END:
|
|
{
|
|
// 唤醒线程
|
|
os_event_set(&thumb_msi->evt, THUMB_THREAD_RUNNING, NULL);
|
|
os_run_work(&thumb_msi->work);
|
|
}
|
|
break;
|
|
case MSI_CMD_JPG_THUMB:
|
|
{
|
|
uint32_t cmd_self = (uint32_t) param1;
|
|
uint32_t arg = param2;
|
|
switch (cmd_self)
|
|
{
|
|
case MSI_JPG_THUMB_TAKEPHOTO_SETPATH:
|
|
{
|
|
thumb_msi->normal_base_dir = (char *) arg;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
struct msi *thumb_over_dpi_msi_init(const char *msi_name, uint8_t jpg_type, uint8_t stype, uint32_t magic)
|
|
{
|
|
uint8_t is_new;
|
|
struct msi *msi = msi_new(msi_name, MAX_RECV_MAX, &is_new);
|
|
struct thumb_msi_s *thumb_msi = NULL;
|
|
if (is_new)
|
|
{
|
|
thumb_msi = (struct thumb_msi_s *) STREAM_LIBC_ZALLOC(sizeof(struct thumb_msi_s));
|
|
msi->priv = thumb_msi;
|
|
thumb_msi->msi = msi;
|
|
thumb_msi->jpg_type = jpg_type;
|
|
thumb_msi->magic = magic;
|
|
thumb_msi->stype = stype;
|
|
thumb_msi->normal_base_dir = IMG_PATH;
|
|
RB_INIT(&thumb_msi->rb, MAX_THUMB_MSI);
|
|
msi->action = thumb_msi_action;
|
|
os_event_init(&thumb_msi->evt);
|
|
msi->enable = 1;
|
|
OS_WORK_INIT(&thumb_msi->work, thumb_msi_work, 0);
|
|
// OS_TASK_INIT("thumb_msi_over_dpi", &thumb_msi->task, thumb_msi_thread, thumb_msi, OS_TASK_PRIORITY_NORMAL, NULL, 1500);
|
|
}
|
|
|
|
return msi;
|
|
}
|
|
#endif |