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,318 @@
#include "basic_include.h"
#include "lib/posix/stdio.h"
#include "lib/multimedia/msi.h"
#include "fatfs/osal_file.h"
#include "fatfs/ff.h"
#define MSI_URLFILE (0)
#if MSI_URLFILE
#include "lib/net/urlfile/urlfile.h"
#endif
enum MSI_FILE_CMD {
MSI_FILE_CMD_OPEN,
MSI_FILE_CMD_CLOSE,
};
enum MSI_FILE_STATE {
MSI_FILE_STATE_IDLE,
MSI_FILE_STATE_OPEN,
MSI_FILE_STATE_READ,
};
#define MSI_FILENAME_MAX (512)
#define MSI_FILE_CMD_MAX (8)
#define MSI_FILE_NUM_TRY (5)
#define MSIFILE_DBG(fmt, ...) os_printf("%s:%d::"fmt, __FUNCTION__, __LINE__, ##__VA_ARGS__)
#define MSIFILE_ERR(fmt, ...) os_printf(KERN_ERR"%s:%d::"fmt, __FUNCTION__, __LINE__, ##__VA_ARGS__)
#define URLFILE(file) (os_strstr(file, "://") != NULL)
struct msi_file {
struct os_task task;
struct msi *msi;
const char *name;
uint8 running: 1, eof: 1, filelist: 1, rev: 5;
uint8 state;
uint16 file_idx;
void *fp;
char file_name[MSI_FILENAME_MAX];
char *file_ext; //文件扩展名
atomic8_t fb_cnt; //未被释放的framebuff个数
uint8 fb_max; //允许使用的framebuff最大个数
uint8 speed; //读取速度,用于倍速播放控制
RBUFFER_DEF(cmd, uint8, MSI_FILE_CMD_MAX);
};
extern void *fopen(const char *filename, const char *mode);
extern size_t fread(void *ptr, size_t size, size_t nmemb, void *stream);
extern int fclose(void *stream);
static void *msi_filestream_fopen(struct msi_file *msifile)
{
#if MSI_URLFILE
if(URLFILE(msifile->file_name))
return uf_open(msifile->file_name, 0);
#endif
return fopen(msifile->file_name, "r");
}
static int msi_filestream_fclose(struct msi_file *msifile)
{
if(msifile->fp){
#if MSI_URLFILE
if(URLFILE(msifile->file_name))
return uf_close(msifile->fp);
#endif
return fclose(msifile->fp);
}
return 0;
}
static size_t msi_filestream_fread(void *ptr, size_t size, size_t nmemb, struct msi_file *msifile)
{
#if MSI_URLFILE
if(URLFILE(msifile->file_name))
return uf_read(ptr, size, nmemb, msifile->fp);
#endif
return fread(ptr, size, nmemb, msifile->fp);
}
static int msi_filestream_fseek(struct msi_file *msifile, off_t offset, int whence)
{
#if MSI_URLFILE
if(URLFILE(msifile->file_name))
return uf_seek(msifile->fp, offset, whence);
#endif
return fseek(msifile->fp, offset, whence);//
}
static int msi_filestream_feof(struct msi_file *msifile)
{
#if MSI_URLFILE
if(URLFILE(msifile->file_name))
return uf_eof(msifile->fp);
#endif
return feof(msifile->fp);
}
static int32 msi_filestream_action(struct msi *msi, uint32 cmd_id, uint32 param1, uint32 param2)
{
int32 ret = RET_OK;
struct msi_file *msifile = (struct msi_file *)msi->priv;
switch (cmd_id) {
case MSI_CMD_POST_DESTROY:
while (msifile->running) {
os_sleep_ms(10);
}
os_free(msifile);
break;
case MSI_CMD_FREE_FB:
break;
case MSI_CMD_SET_SPEED: //设置播放倍速,控制数据读取行为
break;
default:
break;
}
return ret;
}
static void msi_filestream_check_filename(struct msi_file *msifile)
{
msifile->filelist = 0;
msifile->file_idx = 0;
//检查是否存在文件列表支持自动切换文件格式要求xxxx_001.avi
if (msifile->file_ext) {
char *ptr = msifile->file_ext - 4;
if (ptr[0] == '_' && isdigit(ptr[1]) && isdigit(ptr[2]) && isdigit(ptr[3])) {
msifile->filelist = 1;
msifile->file_idx = os_atoi(ptr + 1);
MSIFILE_DBG("start index %d\r\n", msifile->file_idx);
}
}
}
static int32 msi_filestream_open_file(struct msi_file *msifile)
{
char *ptr;
int32 i = 0;
msi_filestream_fclose(msifile);
if (msifile->eof) {
if (!msifile->filelist) {
MSIFILE_ERR("read over!\r\n");
msifile->state = MSI_FILE_STATE_IDLE;
SYSEVT_NEW_MEDIA_EVT(SYSEVT_MEDIA_READ_EOF, (uint32)msifile);
return RET_ERR;
}
ptr = msifile->file_ext - 4;
for (i = 1; i <= MSI_FILE_NUM_TRY; i++) {
os_sprintf(ptr + 1, "%03d", msifile->file_idx + i);
msifile->fp = msi_filestream_fopen(msifile->file_name);
if (msifile->fp) {
MSIFILE_ERR("open %s success!\r\n", msifile->file_name);
msifile->file_idx += i;
msifile->state = MSI_FILE_STATE_READ;
msifile->eof = 0;
return RET_OK;
} else {
MSIFILE_ERR("open %s fail!\r\n", msifile->file_name);
}
}
os_sprintf(ptr + 1, "%03d", msifile->file_idx);
MSIFILE_ERR("read over! last file:%s\r\n", msifile->file_name);
SYSEVT_NEW_MEDIA_EVT(SYSEVT_MEDIA_READ_EOF, (uint32)msifile);
} else {
msifile->file_ext = os_strrchr(msifile->file_name, '.'); //文件扩展名
msifile->fp = msi_filestream_fopen(msifile->file_name);
if (msifile->fp) {
msi_filestream_check_filename(msifile);
} else {
SYSEVT_NEW_MEDIA_EVT(SYSEVT_MEDIA_OPEN_FAIL, (uint32)msifile);
MSIFILE_ERR("open %s fail!\r\n", msifile->file_name);
}
}
//根据扩展名,加载对应的插件
//////////////////////////////////////////////////////////////////////////////////
msifile->state = msifile->fp ? MSI_FILE_STATE_READ : MSI_FILE_STATE_IDLE;
return msifile->fp ? RET_OK : RET_ERR;
}
static int32 msi_filestream_read_file(struct msi_file *msifile, struct framebuff **fb)
{
if (atomic_read(&msifile->fb_cnt) >= msifile->fb_max + 1) {
return -ENOMEM;
}
//插件参与控制读取数据的行为: 比如 按帧读取数据,倍速跳帧
return RET_OK;
}
static void msi_filestream_proc_cmd(struct msi_file *msifile)
{
uint8 cmd;
while (!RB_EMPTY(&msifile->cmd)) {
RB_GET(&msifile->cmd, cmd);
switch (cmd) {
case MSI_FILE_CMD_OPEN:
msifile->eof = 0;
msifile->state = MSI_FILE_STATE_OPEN;
break;
case MSI_FILE_CMD_CLOSE:
msifile->state = MSI_FILE_STATE_IDLE;
break;
}
}
}
static void msi_filestream_task(void *arg)
{
int32 ret = 0;
struct framebuff *fb = NULL;
struct msi_file *msifile = (struct msi_file *)arg;
MSIFILE_DBG("msi_file running ...\r\n");
msifile->running = 1;
while (msifile->msi->enable) {
msi_filestream_proc_cmd(msifile);
switch (msifile->state) {
case MSI_FILE_STATE_IDLE:
os_sleep_ms(10);
break;
case MSI_FILE_STATE_OPEN:
msi_filestream_open_file(msifile);
break;
case MSI_FILE_STATE_READ:
fb = NULL;
ret = msi_filestream_read_file(msifile, &fb);
if (fb) {
atomic_inc(&msifile->fb_cnt);
msi_output_fb(msifile->msi, fb);
}
if (msifile->eof) { //当前文件读取结束
msifile->state = MSI_FILE_STATE_OPEN;
} else if (ret < 0 && msifile->msi->enable) {
os_sleep_ms(10);
}
break;
}
}
if (msifile->fp) {
msi_filestream_fclose(msifile);
msifile->fp = NULL;
}
MSIFILE_DBG("msi_file stopped!\r\n");
msifile->running = 0;
}
void *msi_filestream_init(const char *name, uint8 fb_max)
{
struct msi_file *msifile = os_zalloc(sizeof(struct msi_file));
if (msifile == NULL) {
MSIFILE_ERR("no memory!\r\n");
return NULL;
}
RB_INIT(&msifile->cmd, MSI_FILE_CMD_MAX);
msifile->fb_max = fb_max;
msifile->name = name;
msifile->msi = msi_new(name, 0, NULL);
if (msifile->msi == NULL) {
os_free(msifile);
MSIFILE_ERR("no memory!\r\n");
return NULL;
}
ASSERT(msifile->msi->priv == NULL);
msifile->msi->priv = msifile;
msifile->msi->action = msi_filestream_action;
msifile->msi->enable = 1;
OS_TASK_INIT(name, &msifile->task, msi_filestream_task, msifile, OS_TASK_PRIORITY_NORMAL, NULL,1024);
MSIFILE_DBG("msi_file %s init!\r\n", name);
return msifile;
}
int32 msi_filestream_destory(void *hdl)
{
if (hdl) {
struct msi_file *msifile = (struct msi_file *)hdl;
msi_destroy(msifile->msi); //msi被释放时会通过MSI_CMD_DESTORY通知msifile释放资源
return RET_OK;
} else {
return -EINVAL;
}
}
int32 msi_filestream_close(void *hdl)
{
if (hdl) {
struct msi_file *msifile = (struct msi_file *)hdl;
RB_SET(&msifile->cmd, MSI_FILE_CMD_CLOSE);
return RET_OK;
} else {
return -EINVAL;
}
}
int32 msi_filestream_open(void *hdl, char *file)
{
if (hdl) {
struct msi_file *msifile = (struct msi_file *)hdl;
if (os_strlen(file) >= MSI_FILENAME_MAX) {
return -ENAMETOOLONG;
}
os_strcpy(msifile->file_name, file);
RB_SET(&msifile->cmd, MSI_FILE_CMD_OPEN);
return RET_OK;
} else {
return -EINVAL;
}
}