Files
TAIXIN/sdk/app/video_app/thumb_over_dpi_msi.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