Initial commit: TXW82x FPV v2.7.0.7-42229 SDK + project sources

This commit is contained in:
2026-07-06 11:30:13 +08:00
commit e76462eeb7
3451 changed files with 1415300 additions and 0 deletions

View File

@@ -0,0 +1,226 @@
#include "basic_include.h"
#include "lib/multimedia/msi.h"
#include "lib/heap/av_heap.h"
#include "lib/heap/av_psram_heap.h"
#include "stream_define.h"
#include "user_work/user_work.h"
/***************************************************************************************
* 这个模块主要是添加水印,比较特殊,会涉及修改源数据,所以从软件逻辑一定要明确,只有它可以接收
* 这个yuv数据,然后重新输出,这样才能保证其他msi接收到的yuv是有水印的
* 水印简单添加水印,没有进行运算
**************************************************************************************/
// data申请空间函数
#define STREAM_MALLOC av_psram_malloc
#define STREAM_FREE av_psram_free
#define STREAM_ZALLOC av_psram_zalloc
// 结构体申请空间函数
#define STREAM_LIBC_MALLOC av_malloc
#define STREAM_LIBC_FREE av_free
#define STREAM_LIBC_ZALLOC av_zalloc
struct watermark_msi_s
{
struct os_work work;
struct msi *msi;
uint8_t filter;
uint8_t output_en;
};
#define WATERMARK_X (50)
#define WATERMARK_Y (50)
#define WATERMARK_COLOR (0x0) // 设置水印亮度
#define FONT_W 16
#define FONT_H 32
// clang-format off
const uint8_t font_data[][64] = {
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xC0, 0x06, 0x20, 0x0C, 0x30, 0x18, 0x18, 0x18, 0x18, 0x18, 0x08, 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x18, 0x08, 0x18, 0x18, 0x18, 0x18, 0x0C, 0x30, 0x06, 0x20, 0x03, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x80, 0x1F, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x03, 0xC0, 0x1F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xE0, 0x08, 0x38, 0x10, 0x18, 0x20, 0x0C, 0x20, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x00, 0x0C, 0x00, 0x18, 0x00, 0x18, 0x00, 0x30, 0x00, 0x60, 0x00, 0xC0, 0x01, 0x80, 0x03, 0x00, 0x02, 0x00, 0x04, 0x04, 0x08, 0x04, 0x10, 0x04, 0x20, 0x0C, 0x3F, 0xF8, 0x3F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xC0, 0x18, 0x60, 0x30, 0x30, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x30, 0x00, 0x60, 0x03, 0xC0, 0x00, 0x70, 0x00, 0x18, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x08, 0x30, 0x18, 0x18, 0x30, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x00, 0xE0, 0x00, 0xE0, 0x01, 0x60, 0x01, 0x60, 0x02, 0x60, 0x04, 0x60, 0x04, 0x60, 0x08, 0x60, 0x08, 0x60, 0x10, 0x60, 0x30, 0x60, 0x20, 0x60, 0x40, 0x60, 0x7F, 0xFC, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x03, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFC, 0x0F, 0xFC, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x13, 0xE0, 0x14, 0x30, 0x18, 0x18, 0x10, 0x08, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x20, 0x18, 0x20, 0x18, 0x18, 0x30, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xE0, 0x06, 0x18, 0x0C, 0x18, 0x08, 0x18, 0x18, 0x00, 0x10, 0x00, 0x10, 0x00, 0x30, 0x00, 0x33, 0xE0, 0x36, 0x30, 0x38, 0x18, 0x38, 0x08, 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x18, 0x0C, 0x18, 0x08, 0x0C, 0x18, 0x0E, 0x30, 0x03, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFC, 0x1F, 0xFC, 0x10, 0x08, 0x30, 0x10, 0x20, 0x10, 0x20, 0x20, 0x00, 0x20, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x80, 0x00, 0x80, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xE0, 0x0C, 0x30, 0x18, 0x18, 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x38, 0x0C, 0x38, 0x08, 0x1E, 0x18, 0x0F, 0x20, 0x07, 0xC0, 0x18, 0xF0, 0x30, 0x78, 0x30, 0x38, 0x60, 0x1C, 0x60, 0x0C, 0x60, 0x0C, 0x60, 0x0C, 0x60, 0x0C, 0x30, 0x18, 0x18, 0x30, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xC0, 0x18, 0x20, 0x30, 0x10, 0x30, 0x18, 0x60, 0x08, 0x60, 0x0C, 0x60, 0x0C, 0x60, 0x0C, 0x60, 0x0C, 0x60, 0x0C, 0x70, 0x1C, 0x30, 0x2C, 0x18, 0x6C, 0x0F, 0x8C, 0x00, 0x0C, 0x00, 0x18, 0x00, 0x18, 0x00, 0x10, 0x30, 0x30, 0x30, 0x60, 0x30, 0xC0, 0x0F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x03, 0xC0, 0x03, 0xC0, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x03, 0xC0, 0x03, 0xC0, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
};
// clang-format on
static void draw_char(char *yuv_buf, char ch, int w, int h, int x, int y)
{
int i, j;
int8_t num = ch - 0x30;
if (ch == ':')
{
num = 10;
}
else if (ch == '-')
{
num = 11;
}
else if (num < 0 || num > 10)
{
return;
}
const uint8_t *num_font = (const uint8_t*)font_data[num];
int size = sizeof(font_data[0]);
for (i = 0; i < size; i++)
{
for (j = 0; j < 8; j++)
{
if (num_font[i] & (0x80 >> j))
{
// 越界就不再绘制
if (x + j + i % (FONT_W / 8) * 8 >= w)
{
break;
}
yuv_buf[(y + i / (FONT_W / 8)) * w + x + j + i % (FONT_W / 8) * 8] = WATERMARK_COLOR;
}
else
{
// yuv_buf[(y+i)*WIDTH,+x+j] = 0;
}
}
}
}
static char draw_str(char *yuv_buf, char *str, int w, int h, int x, int y)
{
while (*str)
{
draw_char(yuv_buf, *str, w, h, x, y);
x += FONT_W;
str++;
}
return 0;
}
static int32_t watermark_work(struct os_work *work)
{
struct yuv_arg_s *arg;
struct watermark_msi_s *watermark = (struct watermark_msi_s *) work;
struct framebuff *fb;
uint32_t send_count;
fb = msi_get_fb(watermark->msi, 0);
// 检查是否需要发送到下一级
if (fb && !watermark->output_en)
{
send_count = msi_output_fb(watermark->msi, NULL);
if (!send_count)
{
msi_delete_fb(NULL, fb);
fb = NULL;
}
else
{
watermark->output_en = 1;
}
}
if (fb)
{
char path[64];
struct tm *time_info;
struct timeval ptimeval;
gettimeofday(&ptimeval, NULL);
time_t time_val = (time_t)ptimeval.tv_sec;
time_info = gmtime(&time_val);
uint32_t year = time_info->tm_year + 1900;
uint32_t mon = time_info->tm_mon + 1;
uint32_t day = time_info->tm_mday;
uint32_t hour = time_info->tm_hour;
uint32_t min = time_info->tm_min;
uint32_t sec = time_info->tm_sec;
os_sprintf(path, "%04d %02d %02d %02d:%02d:%02d", year,mon,day,hour, min, sec);
arg = (struct yuv_arg_s *) fb->priv;
// 增加水印后,发出去
draw_str((char*)fb->data, path, arg->out_w, arg->out_h, WATERMARK_X, WATERMARK_Y);
sys_dcache_clean_invalid_range((uint32_t *) (fb->data + WATERMARK_Y * arg->out_w), arg->out_w * 32);
send_count = msi_output_fb(watermark->msi, fb);
if (!send_count)
{
watermark->output_en = 0;
}
}
return 0;
}
static int32_t watermark_msi_action(struct msi *msi, uint32_t cmd_id, uint32_t param1, uint32_t param2)
{
int32_t ret = RET_OK;
struct watermark_msi_s *watermark = (struct watermark_msi_s *) msi->priv;
switch (cmd_id)
{
case MSI_CMD_POST_DESTROY:
{
os_work_cancle2(&watermark->work, 1);
STREAM_LIBC_FREE(watermark);
}
break;
case MSI_CMD_PRE_DESTROY:
{
os_work_cancle2(&watermark->work, 1);
}
break;
case MSI_CMD_TRANS_FB:
{
struct framebuff *fb = (struct framebuff *) param1;
// printf("mtype:%d\n",fb->mtype);
if (fb->mtype != F_YUV)
{
ret = RET_ERR;
}
// 如果需要过滤,并且过滤类型不匹配就不增加水印
else if (watermark->filter && watermark->filter != fb->stype)
{
ret = RET_ERR;
}
}
break;
case MSI_CMD_TRANS_FB_END:
{
os_run_work(&watermark->work);
}
break;
default:
{
}
break;
}
return ret;
}
// 中转(路由)msi,不需要接收,仅仅发送就可以了
struct msi *yuv_time_watermark(const char *name, uint8_t filter)
{
// 设置1个接收,只是为了可以output_fb给到这个msi
uint8_t isnew;
struct msi *msi = msi_new(name, 8, &isnew);
if (isnew)
{
struct watermark_msi_s *watermark = (struct watermark_msi_s *) STREAM_LIBC_ZALLOC(sizeof(struct watermark_msi_s));
ASSERT(watermark);
watermark->msi = msi;
watermark->filter = filter;
msi->priv = (void *) watermark;
msi->action = watermark_msi_action;
OS_WORK_INIT(&watermark->work, watermark_work, 0);
os_run_work_delay(&watermark->work, 1);
msi->enable = 1;
}
return msi;
}