Initial commit: TXW82x FPV v2.7.0.7-42229 SDK + project sources
This commit is contained in:
232
sdk/app/video_app/auto_jpg_msi.c
Normal file
232
sdk/app/video_app/auto_jpg_msi.c
Normal file
@@ -0,0 +1,232 @@
|
||||
#include "basic_include.h"
|
||||
#include "lib/multimedia/msi.h"
|
||||
#include "jpg_concat_msi.h"
|
||||
#include "lib/heap/av_heap.h"
|
||||
#include "lib/heap/av_psram_heap.h"
|
||||
#include "lib/video/dvp/jpeg/jpg.h"
|
||||
#include "stream_define.h"
|
||||
#include "user_work/user_work.h"
|
||||
#include "lib/video/dvp/jpeg/jpg_common.h"
|
||||
#include "lib/video/vpp/vpp_dev.h"
|
||||
|
||||
// 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
|
||||
|
||||
#ifdef JPG_NODE_COUNT
|
||||
#define AUTO_JPG_COUNT JPG_NODE_COUNT
|
||||
#else
|
||||
#define AUTO_JPG_COUNT 10
|
||||
#endif
|
||||
extern uint8_t get_vpp_scale_w_h(uint16_t *w, uint16_t *h);
|
||||
|
||||
struct auto_jpg_msi_s
|
||||
{
|
||||
struct os_work work;
|
||||
struct msi *msi;
|
||||
struct msi *register_jpg_msi; // 注册的jpg的msi
|
||||
uint16_t w, h;
|
||||
uint8_t src_from : 3, stop : 1, which_jpg : 1, rev : 3;
|
||||
};
|
||||
|
||||
static int32 auto_jpg_work(struct os_work *work)
|
||||
{
|
||||
uint8_t last_value;
|
||||
int32_t ret;
|
||||
uint8_t delay_time = 40;
|
||||
uint8_t stop = 0;
|
||||
struct auto_jpg_msi_s *auto_jpg = (struct auto_jpg_msi_s *) work;
|
||||
// 这里尝试发送数据?检查一下是否有接收的msi,如果有接收的msi,则启动mjpeg,如果没有,则将硬件停下来?
|
||||
uint32_t send_count = msi_output_fb(auto_jpg->msi, NULL);
|
||||
// 代表有需要接收的数据流,那么就要启动硬件,尝试获取锁,然后启动mjpg,如果上一次锁是mjpg,就不需要重新启动
|
||||
if (send_count)
|
||||
{
|
||||
// 尝试查看是否已经停止过
|
||||
ret = jpg_mutex_lock(auto_jpg->which_jpg, JPG_LOCK_ENCODE, &last_value);
|
||||
// 获取到锁,并且锁的值不一致,则要重新去启动mjpeg
|
||||
if (ret == 0)
|
||||
{
|
||||
// 如果锁的值不一致,代表该mjpg被其他地方使用过了,需要重新启动
|
||||
// 如果锁的值一致,但是stop == 1,代表已经停止过了,也需要重新启动
|
||||
if (last_value != JPG_LOCK_ENCODE || auto_jpg->stop == 1)
|
||||
{
|
||||
// 关闭mjpeg
|
||||
|
||||
if (auto_jpg->src_from == SCALER_DATA)
|
||||
{
|
||||
|
||||
ret = get_vpp_scale_w_h(&auto_jpg->w, &auto_jpg->h);
|
||||
if (!ret)
|
||||
{
|
||||
msi_do_cmd(auto_jpg->register_jpg_msi, MSI_CMD_JPEG_CONCAT, MSI_JPEG_START, 0);
|
||||
msi_do_cmd(auto_jpg->register_jpg_msi, MSI_CMD_JPEG_CONCAT, MSI_JPEG_NODE_COUNT, AUTO_JPG_COUNT);
|
||||
set_vpp_scale_w_h(1, auto_jpg->w, auto_jpg->h);
|
||||
msi_do_cmd(auto_jpg->register_jpg_msi, MSI_CMD_JPEG_CONCAT, MSI_SET_SCALE1_TYPE, 0);
|
||||
msi_do_cmd(auto_jpg->register_jpg_msi, MSI_CMD_JPEG_CONCAT, MSI_SET_SCALE1_AUTO_FLAG, 1);
|
||||
msi_do_cmd(auto_jpg->register_jpg_msi, MSI_CMD_JPEG_CONCAT, MSI_JPEG_MSG, auto_jpg->w << 16 | auto_jpg->h);
|
||||
}
|
||||
else
|
||||
{
|
||||
stop = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
msi_do_cmd(auto_jpg->register_jpg_msi, MSI_CMD_JPEG_CONCAT, MSI_JPEG_START, 0);
|
||||
msi_do_cmd(auto_jpg->register_jpg_msi, MSI_CMD_JPEG_CONCAT, MSI_JPEG_NODE_COUNT, AUTO_JPG_COUNT);
|
||||
}
|
||||
if (!stop)
|
||||
{
|
||||
// 切回到默认源头
|
||||
msi_do_cmd(auto_jpg->register_jpg_msi, MSI_CMD_JPEG_CONCAT, MSI_JPEG_FROM, auto_jpg->src_from);
|
||||
// 重新启动mjpg
|
||||
msi_do_cmd(auto_jpg->register_jpg_msi, MSI_CMD_JPEG_CONCAT, MSI_JPEG_START, 1);
|
||||
auto_jpg->stop = 0;
|
||||
}
|
||||
}
|
||||
// 解锁,可以被其他线程打断使用,因为这个是从VPP_DATA0,可以被其他线程打断使用完再恢复,
|
||||
// 这样只是丢部分帧,但是可以复用mjpg
|
||||
jpg_mutex_unlock(auto_jpg->which_jpg, JPG_LOCK_ENCODE);
|
||||
}
|
||||
// 没有获取到锁,就延时一点时间后,继续获取
|
||||
else
|
||||
{
|
||||
delay_time = 5;
|
||||
}
|
||||
}
|
||||
else if (send_count == 0)
|
||||
{
|
||||
if (auto_jpg->stop == 0)
|
||||
{
|
||||
ret = jpg_mutex_lock(auto_jpg->which_jpg, JPG_LOCK_ENCODE, &last_value);
|
||||
if (ret == 0)
|
||||
{
|
||||
// 如果锁的值一致,那么就要主动停止,因为已经在启动了
|
||||
if (last_value == JPG_LOCK_ENCODE)
|
||||
{
|
||||
msi_do_cmd(auto_jpg->register_jpg_msi, MSI_CMD_JPEG_CONCAT, MSI_JPEG_START, 0);
|
||||
}
|
||||
|
||||
jpg_mutex_unlock_check(auto_jpg->which_jpg, JPG_LOCK_ENCODE);
|
||||
}
|
||||
auto_jpg->stop = 1;
|
||||
}
|
||||
}
|
||||
os_run_work_delay(work, delay_time);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t auto_jpg_msi_action(struct msi *msi, uint32_t cmd_id, uint32_t param1, uint32_t param2)
|
||||
{
|
||||
int32_t ret = RET_OK;
|
||||
struct auto_jpg_msi_s *auto_jpg = (struct auto_jpg_msi_s *) msi->priv;
|
||||
switch (cmd_id)
|
||||
{
|
||||
case MSI_CMD_POST_DESTROY:
|
||||
{
|
||||
os_work_cancle2(&auto_jpg->work, 1);
|
||||
STREAM_LIBC_FREE(auto_jpg);
|
||||
}
|
||||
break;
|
||||
case MSI_CMD_PRE_DESTROY:
|
||||
{
|
||||
os_work_cancle2(&auto_jpg->work, 1);
|
||||
if (auto_jpg->register_jpg_msi)
|
||||
{
|
||||
msi_destroy(auto_jpg->register_jpg_msi);
|
||||
auto_jpg->register_jpg_msi = NULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MSI_CMD_AUTO_JPG:
|
||||
{
|
||||
uint32_t cmd_self = (uint32_t) param1;
|
||||
uint32_t arg = param2;
|
||||
switch (cmd_self)
|
||||
{
|
||||
// 切换数据源
|
||||
case MSI_AUTO_JPG_SWITCH_ENCODE_SRC:
|
||||
{
|
||||
auto_jpg->src_from = arg;
|
||||
auto_jpg->stop = 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MSI_CMD_TRANS_FB:
|
||||
{
|
||||
struct framebuff *fb = (struct framebuff *) param1;
|
||||
// 如果是mjpeg,帮忙转发到其他数据流
|
||||
// 如果需要支持264,也要帮忙转发
|
||||
if (fb->mtype == F_JPG)
|
||||
{
|
||||
// 类型匹配才可以转发
|
||||
if (fb->stype == FSTYPE_VIDEO_VPP_DATA0 + auto_jpg->src_from)
|
||||
{
|
||||
_os_printf("+");
|
||||
struct framebuff *fb = (struct framebuff *) param1;
|
||||
fb_get(fb);
|
||||
msi_output_fb(msi, fb);
|
||||
}
|
||||
ret = RET_OK + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct msi *auto_jpg_msi_init(const char *auto_jpg_name, uint8_t which_jpg, uint8_t src_from)
|
||||
{
|
||||
uint8_t isnew;
|
||||
struct msi *msi = NULL;
|
||||
msi = msi_new(auto_jpg_name, 0, &isnew);
|
||||
struct auto_jpg_msi_s *auto_jpg = (struct auto_jpg_msi_s *) msi->priv;
|
||||
if (isnew)
|
||||
{
|
||||
auto_jpg = (struct auto_jpg_msi_s *) STREAM_LIBC_ZALLOC(sizeof(struct auto_jpg_msi_s));
|
||||
msi->priv = (void *) auto_jpg;
|
||||
msi->action = auto_jpg_msi_action;
|
||||
auto_jpg->msi = msi;
|
||||
auto_jpg->src_from = src_from;
|
||||
auto_jpg->stop = 1;
|
||||
auto_jpg->which_jpg = which_jpg;
|
||||
auto_jpg->w = 0;
|
||||
auto_jpg->h = 0;
|
||||
// w和h在vpp_data0和vpp_data1的时候是没有作用的
|
||||
auto_jpg->register_jpg_msi = jpg_concat_msi_init_start(auto_jpg->which_jpg, 0, 0, NULL, auto_jpg->src_from, 0);
|
||||
if (auto_jpg->register_jpg_msi)
|
||||
{
|
||||
msi_add_output(auto_jpg->register_jpg_msi, NULL, msi->name);
|
||||
}
|
||||
else
|
||||
{
|
||||
msi_destroy(msi);
|
||||
msi = NULL;
|
||||
goto auto_jpg_msi_init_end;
|
||||
}
|
||||
|
||||
msi->enable = 1;
|
||||
// 启动workqueue
|
||||
OS_WORK_INIT(&auto_jpg->work, auto_jpg_work, 0);
|
||||
os_run_work(&auto_jpg->work);
|
||||
}
|
||||
|
||||
auto_jpg_msi_init_end:
|
||||
return msi;
|
||||
}
|
||||
Reference in New Issue
Block a user