Initial commit: TXW82x FPV v2.7.0.7-42229 SDK + project sources
This commit is contained in:
553
sdk/app/scale_msi/scale2_msi.c
Normal file
553
sdk/app/scale_msi/scale2_msi.c
Normal file
@@ -0,0 +1,553 @@
|
||||
#include "scale_msi.h"
|
||||
#include "dev/vpp/hgvpp.h"
|
||||
#include "dev/scale/hgscale.h"
|
||||
#include "lib/heap/av_heap.h"
|
||||
#include "lib/heap/av_psram_heap.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
|
||||
|
||||
uint8 *scaler2buf;
|
||||
extern uint32 scale_p1_w;
|
||||
#define SCALE2_SRAMBUF_WLEN 64//64
|
||||
|
||||
//0:满屏保留所有的画面,不在意变形
|
||||
//1:保证画面不变型,再进行缩放
|
||||
#define SCALE2_MODE_SELECT 1
|
||||
|
||||
//SCALE2_MODE_SELECT为1有效,10为不放大,11为放大1.1倍,20为放大2.0倍,以此类推
|
||||
#define SCALE2_LARGER_SIZE 10
|
||||
struct scale2_yuv_arg_s
|
||||
{
|
||||
struct yuv_arg_s yuv_arg;
|
||||
uint8_t seq;
|
||||
};
|
||||
|
||||
struct scale2_msg_t scale2_msg[3] = {
|
||||
//ISP_VIDEO_0
|
||||
{
|
||||
.stype = FSTYPE_YUV_P1,
|
||||
.iw = 640,
|
||||
.ih = 480,
|
||||
.ow = 320,
|
||||
.oh = 240,
|
||||
.x = 0,
|
||||
.y = 0,
|
||||
.video_only = 0,
|
||||
.larger = 10,
|
||||
},
|
||||
//ISP_VIDEO_1
|
||||
{
|
||||
.stype = FSTYPE_YUV_P0,
|
||||
.iw = 640,
|
||||
.ih = 480,
|
||||
.ow = 320,
|
||||
.oh = 240,
|
||||
.x = 320,
|
||||
.y = 0,
|
||||
.video_only = 0,
|
||||
.larger = 10,
|
||||
},
|
||||
//ISP_VIDEO_2
|
||||
{
|
||||
.stype = FSTYPE_YUV_P2,
|
||||
.iw = 640,
|
||||
.ih = 480,
|
||||
.ow = 320,
|
||||
.oh = 240,
|
||||
.x = 0,
|
||||
.y = 180,
|
||||
.video_only = 0,
|
||||
.larger = 10,
|
||||
},
|
||||
};
|
||||
|
||||
volatile uint8_t scaler2_dev_id = 0;
|
||||
|
||||
// 这里可能采用信号量的形式,通知到线程去处理数据
|
||||
static int32_t scale2_stream_done(uint32 irq_flag, uint32 irq_data, uint32 param1)
|
||||
{
|
||||
struct scale2_msi_s *scale2 = (struct scale2_msi_s *)irq_data;
|
||||
//struct framebuff *fb;
|
||||
struct scale2_yuv_arg_s *arg;
|
||||
//判断序号,有可能双镜头
|
||||
scale2->seq++;
|
||||
|
||||
if (scale2->now_fb) {
|
||||
arg = (struct scale2_yuv_arg_s*)scale2->now_fb->priv;
|
||||
arg->seq = scale2->seq;
|
||||
|
||||
arg->yuv_arg.y_size = scale2->ow*scale2->oh;
|
||||
arg->yuv_arg.x = scale2->x;
|
||||
arg->yuv_arg.y = scale2->y;
|
||||
arg->yuv_arg.video_only = scale2_msg[scaler2_dev_id].video_only;
|
||||
arg->yuv_arg.out_w =scale2->ow;
|
||||
arg->yuv_arg.out_h =scale2->oh;
|
||||
|
||||
scale2->now_fb->stype = scale2_msg[scaler2_dev_id].stype;
|
||||
|
||||
|
||||
// 不再直接放now_fb,而是把now_fb放到预分配的槽(now_fb_msg)中,然后把槽地址放入消息队列
|
||||
uint8_t idx = scale2->now_fb_msg_idx;
|
||||
if (scale2->now_fb_msg[idx] == NULL) {
|
||||
scale2->now_fb_msg[idx] = scale2->now_fb;
|
||||
// advance index
|
||||
scale2->now_fb_msg_idx = (idx + 1) % MAX_SCALE2_TX;
|
||||
|
||||
if (os_msgq_put(&scale2->msgq, (uint32_t)&scale2->now_fb_msg[idx], 0)) {
|
||||
if (scale2->now_fb_msg[idx] == scale2->now_fb) {
|
||||
scale2->now_fb_msg[idx] = NULL;
|
||||
}
|
||||
msi_delete_fb(NULL, scale2->now_fb);
|
||||
}
|
||||
} else {
|
||||
msi_delete_fb(NULL, scale2->now_fb);
|
||||
}
|
||||
}
|
||||
|
||||
scale2->now_fb = NULL;
|
||||
scale2->mutex_count = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int32_t scale2_stream_ov(uint32 irq_flag, uint32 irq_data, uint32 param1)
|
||||
{
|
||||
os_printf("%s:%d\n", __FUNCTION__, __LINE__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int32 scale2_stream_work(struct os_work *work)
|
||||
{
|
||||
struct scale2_msi_s *scale2 = (struct scale2_msi_s *)work;
|
||||
struct framebuff *fb;
|
||||
struct scale2_yuv_arg_s *arg;
|
||||
int32_t err = -1;
|
||||
|
||||
struct framebuff **slot = (struct framebuff **)os_msgq_get2(&scale2->msgq, 0, &err);
|
||||
// 没有数据
|
||||
if (err)
|
||||
{
|
||||
goto scale2_stream_work_end;
|
||||
}
|
||||
fb = NULL;
|
||||
if (slot)
|
||||
{
|
||||
uint32 ie = disable_irq();
|
||||
fb = *slot;
|
||||
*slot = NULL;
|
||||
enable_irq(ie);
|
||||
}
|
||||
|
||||
arg = (struct scale2_yuv_arg_s*)fb->priv;
|
||||
arg->yuv_arg.dispcnt++;
|
||||
fb->mtype = F_YUV;
|
||||
//fb->stype = scale2->type;
|
||||
//_os_printf("scale2 fb:%X\ttype:%d\n",fb,fb->stype);
|
||||
if (scale2->filter_type != ~0 && scale2->filter_type != fb->srcID) {
|
||||
msi_delete_fb(scale2->msi, fb);
|
||||
} else {
|
||||
msi_output_fb(scale2->msi, fb);
|
||||
}
|
||||
|
||||
scale2_stream_work_end:
|
||||
// 过1ms就去轮询一遍,实际如果用信号量,可以改成任务形式,等待信号量,可以节约cpu(实际cache影响可能更大,cpu占用很少)
|
||||
// 由于workqueue没有支持等待信号量,只能通过1ms轮询一下
|
||||
os_run_work_delay(work, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t scale2_msi_action(struct msi *msi, uint32_t cmd_id, uint32_t param1, uint32_t param2)
|
||||
{
|
||||
int32_t ret = RET_OK;
|
||||
struct scale2_msi_s *scale2 = (struct scale2_msi_s *)msi->priv;
|
||||
//uint32_t ow_n,oh_n;
|
||||
//uint32_t iw_n,ih_n;
|
||||
uint8_t *yinaddr;
|
||||
uint8_t *uinaddr;
|
||||
uint8_t *vinaddr;
|
||||
switch (cmd_id)
|
||||
{
|
||||
|
||||
// 这里msi已经被删除,那么就要考虑tx_pool的资源释放了
|
||||
// 能进来这里,就是代表所有fb都已经用完了
|
||||
case MSI_CMD_POST_DESTROY:
|
||||
{
|
||||
|
||||
struct framebuff *fb;
|
||||
// 释放资源fb资源文件
|
||||
while (1)
|
||||
{
|
||||
fb = fbpool_get(&scale2->tx_pool, 0, NULL);
|
||||
if (!fb)
|
||||
{
|
||||
break;
|
||||
}
|
||||
// 预分配空间释放
|
||||
if (fb->priv)
|
||||
{
|
||||
STREAM_LIBC_FREE(fb->priv);
|
||||
}
|
||||
|
||||
if (fb->data)
|
||||
{
|
||||
STREAM_FREE(fb->data);
|
||||
}
|
||||
}
|
||||
STREAM_LIBC_FREE(scaler2buf);
|
||||
scaler2buf = NULL;
|
||||
fbpool_destroy(&scale2->tx_pool);
|
||||
STREAM_LIBC_FREE(scale2);
|
||||
}
|
||||
break;
|
||||
|
||||
// 停止硬件,移除没有必要的资源(但是fb的资源不能现在删除,这个时候fb可能外部还在调用)
|
||||
case MSI_CMD_PRE_DESTROY:
|
||||
{
|
||||
struct framebuff *fb = NULL;
|
||||
int32_t err = 0;
|
||||
|
||||
scale_close(scale2->scale_dev);
|
||||
os_work_cancle2(&scale2->work, 1);
|
||||
// os_printf("%s:%d MSI_CMD_PRE_DESTROY\n", __FUNCTION__, __LINE__);
|
||||
|
||||
// 移除信号量里面的数据
|
||||
|
||||
while (!err)
|
||||
{
|
||||
// 取出的是槽地址,首先获取槽,再释放其中的真实fb
|
||||
struct framebuff **slot = (struct framebuff **)os_msgq_get2(&scale2->msgq, 0, &err);
|
||||
if (slot)
|
||||
{
|
||||
uint32 ie = disable_irq();
|
||||
fb = *slot;
|
||||
*slot = NULL;
|
||||
enable_irq(ie);
|
||||
if (fb)
|
||||
{
|
||||
msi_delete_fb(NULL, fb);
|
||||
}
|
||||
}
|
||||
fb = NULL;
|
||||
}
|
||||
|
||||
os_msgq_del(&scale2->msgq);
|
||||
|
||||
|
||||
}
|
||||
break;
|
||||
// 接收,判断是类型是否可以支持压缩
|
||||
case MSI_CMD_TRANS_FB:
|
||||
{
|
||||
}
|
||||
break;
|
||||
// 预先分配的,默认不需要释放fb->data,除非是MSI_CMD_DESTROY后,就要释放
|
||||
case MSI_CMD_FREE_FB:
|
||||
{
|
||||
struct framebuff *fb = (struct framebuff *)param1;
|
||||
if (fb->data)
|
||||
{
|
||||
STREAM_FREE(fb->data);
|
||||
fb->data = NULL;
|
||||
}
|
||||
fbpool_put(&scale2->tx_pool, fb);
|
||||
// 不需要内核去释放fb
|
||||
ret = RET_OK + 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case MSI_CMD_SCALE2:
|
||||
{
|
||||
uint32_t cmd_self = (uint32_t)param1;
|
||||
uint32 scale2_p1_w;
|
||||
uint8_t *data;
|
||||
uint8_t decfrom = param2;
|
||||
// 自定义命令
|
||||
switch (cmd_self)
|
||||
{
|
||||
case MSI_SCALE2_SET_FILTER_TYPE:
|
||||
{
|
||||
scale2->filter_type = param2;
|
||||
}
|
||||
break;
|
||||
|
||||
case MSI_SCALE2_START:
|
||||
{
|
||||
//注意,这里需要根据vpp那边配置来决定用哪个
|
||||
//注意line buf的数量
|
||||
|
||||
// 暂时用同样的iw ih ow oh
|
||||
//scale_from_h264_config(scale2->scale_dev,scale2->iw,scale2->ih,scale2->ow,scale2->oh,10);
|
||||
//set_lcd_photo1_config(scale2->ow,scale2->oh,0);
|
||||
scale2_p1_w = ((scale2->ow+3)/4)*4;
|
||||
|
||||
scale_close(scale2->scale_dev);
|
||||
scale_set_input_stream(scale2->scale_dev,decfrom);
|
||||
scale_set_output_sram_or_frame(scale2->scale_dev,1);
|
||||
|
||||
scale_set_in_out_size(scale2->scale_dev,scale2->iw,scale2->ih,scale2->ow,scale2->oh);
|
||||
scale_set_step(scale2->scale_dev,scale2->iw,scale2->ih,scale2->stw,scale2->sth);
|
||||
scale_set_start_addr(scale2->scale_dev,scale2->sx,scale2->sy);
|
||||
|
||||
if(scaler2buf == NULL){
|
||||
if(scale2->ow <= scale2->iw){
|
||||
scaler2buf = STREAM_LIBC_MALLOC(0x20+scale2_p1_w+20*SCALE2_SRAMBUF_WLEN*4+256 + 0x12+scale2_p1_w/2+11*SCALE2_SRAMBUF_WLEN*2+128+0x12+scale2_p1_w/2+11*SCALE2_SRAMBUF_WLEN*2+128+12);
|
||||
memset(scaler2buf,0x55,0x20+scale2_p1_w+20*SCALE2_SRAMBUF_WLEN*4+256 + 0x12+scale2_p1_w/2+11*SCALE2_SRAMBUF_WLEN*2+128+0x12+scale2_p1_w/2+11*SCALE2_SRAMBUF_WLEN*2+128+12);
|
||||
}else{
|
||||
scaler2buf = STREAM_LIBC_MALLOC(0x20+scale2_p1_w+40*SCALE2_SRAMBUF_WLEN*4+256 + 0x12+scale2_p1_w/2+22*SCALE2_SRAMBUF_WLEN*2+128+0x12+scale2_p1_w/2+22*SCALE2_SRAMBUF_WLEN*2+128+12);
|
||||
memset(scaler2buf,0x55,0x20+scale2_p1_w+40*SCALE2_SRAMBUF_WLEN*4+256 + 0x12+scale2_p1_w/2+22*SCALE2_SRAMBUF_WLEN*2+128+0x12+scale2_p1_w/2+22*SCALE2_SRAMBUF_WLEN*2+128+12);
|
||||
}
|
||||
|
||||
if(scaler2buf == NULL){
|
||||
os_printf("malloc scaler2 fail.......\r\n");
|
||||
return RET_ERR;
|
||||
}else{
|
||||
os_printf("scaler 2 malloc finish\r\n");
|
||||
}
|
||||
|
||||
scale2->scaler2buf = scaler2buf;
|
||||
yinaddr = scaler2buf;
|
||||
if(scale2->ow <= scale2->iw){
|
||||
uinaddr = yinaddr+((0x20+scale2_p1_w+20*SCALE2_SRAMBUF_WLEN*4+256 + 3)/4)*4;
|
||||
vinaddr = uinaddr+((0x12+scale2_p1_w/2+11*SCALE2_SRAMBUF_WLEN*2+128 + 3)/4)*4;
|
||||
}else{
|
||||
uinaddr = yinaddr+((0x20+scale2_p1_w+40*SCALE2_SRAMBUF_WLEN*4+256 + 3)/4)*4;
|
||||
vinaddr = uinaddr+((0x12+scale2_p1_w/2+22*SCALE2_SRAMBUF_WLEN*2+128 + 3)/4)*4;
|
||||
}
|
||||
|
||||
scale_linebuf_yuv_addr(scale2->scale_dev,(uint32)yinaddr,(uint32)uinaddr,(uint32)vinaddr);
|
||||
}
|
||||
|
||||
|
||||
scale_set_srambuf_wlen(scale2->scale_dev,SCALE2_SRAMBUF_WLEN);
|
||||
scale_request_irq(scale2->scale_dev,FRAME_END,(scale_irq_hdl )&scale2_stream_done,(uint32)scale2);
|
||||
scale_request_irq(scale2->scale_dev,INBUF_OV,(scale_irq_hdl )&scale2_stream_ov,(uint32)scale2);
|
||||
|
||||
|
||||
// 这里分配一下scale2的空间,通过标准接口去分配吧,理论这里一定能获取到,这里就不判断异常情况了
|
||||
struct framebuff *fb;
|
||||
// 正常应该要获取到fb
|
||||
fb = fbpool_get(&scale2->tx_pool, 0, scale2->msi);
|
||||
uint8_t *p_buf;
|
||||
|
||||
if (!fb)
|
||||
{
|
||||
//os_printf("N scale2->now_fb:%X\r\n",scale2->now_fb);
|
||||
// 找不到新的空间,则返回,使用旧空间
|
||||
return 0;
|
||||
}
|
||||
fb->srcID = decfrom;
|
||||
data = (uint8_t *)STREAM_MALLOC(scale2->ow * scale2->oh * 3 / 2);
|
||||
if(data == NULL){
|
||||
_os_printf("no scaler room\r\n");
|
||||
return 0;
|
||||
}
|
||||
sys_dcache_invalid_range((uint32_t*)data, scale2->ow * scale2->oh * 3 / 2);
|
||||
fb->data = data;
|
||||
fb->len = (scale2->ow * scale2->oh * 3) / 2;
|
||||
p_buf = fb->data;
|
||||
scale2->now_fb = fb;
|
||||
scale_set_out_yaddr(scale2->scale_dev, (uint32)p_buf);
|
||||
scale_set_out_uaddr(scale2->scale_dev, (uint32)p_buf + scale2->ow * scale2->oh);
|
||||
scale_set_out_vaddr(scale2->scale_dev, (uint32)p_buf + scale2->ow * scale2->oh + scale2->ow * scale2->oh / 4);
|
||||
scale_open(scale2->scale_dev);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void scale2_output_size_local_change(uint8_t id,uint8_t show_only,uint16 x,uint16 y,uint16 w,uint16 h){
|
||||
uint32 ie;
|
||||
ie = disable_irq();
|
||||
scale2_msg[id].x = x;
|
||||
scale2_msg[id].y = y;
|
||||
scale2_msg[id].ow = w;
|
||||
scale2_msg[id].oh = h;
|
||||
scale2_msg[id].video_only = show_only;
|
||||
enable_irq(ie);
|
||||
}
|
||||
|
||||
void scale2_output_larger_local_change(uint8_t id, uint8_t larger)
|
||||
{
|
||||
uint32 ie;
|
||||
ie = disable_irq();
|
||||
scale2_msg[id].larger = larger;
|
||||
enable_irq(ie);
|
||||
}
|
||||
|
||||
// 参数分别是vpp的图像iw和ih,要scale的ow和oh,如果和屏有关,可以传入屏幕的宽高
|
||||
struct msi *scale2_msi(const char *name, uint16_t iw, uint16_t ih, uint16_t ow, uint16_t oh, uint16_t type,uint8_t larger)
|
||||
{
|
||||
uint8_t itk;
|
||||
struct msi *msi = msi_new(name, 0, NULL);
|
||||
struct scale2_msi_s *scale2 = (struct scale2_msi_s *)msi->priv;
|
||||
if(msi == NULL)
|
||||
return NULL;
|
||||
|
||||
if (!scale2)
|
||||
{
|
||||
// os_printf("%s:%d new success\n", __FUNCTION__, __LINE__);
|
||||
scale2 = (struct scale2_msi_s *)STREAM_LIBC_ZALLOC(sizeof(struct scale2_msi_s));
|
||||
msi->action = scale2_msi_action;
|
||||
msi->priv = (void *)scale2;
|
||||
scale2->msi = msi;
|
||||
scale2->scale_dev = (struct scale_device *)dev_get(HG_SCALE2_DEVID);
|
||||
|
||||
for(itk = 0;itk < 3;itk++){
|
||||
scale2_msg[itk].iw = iw;
|
||||
scale2_msg[itk].ih = ih;
|
||||
scale2_msg[itk].ow = ow;
|
||||
scale2_msg[itk].oh = oh;
|
||||
}
|
||||
|
||||
scale2->filter_type = ~0;
|
||||
scale2->ow = ow;
|
||||
scale2->oh = oh;
|
||||
scale2->iw = iw;
|
||||
scale2->ih = ih;
|
||||
scale2->stw = ow;
|
||||
scale2->sth = oh;
|
||||
scale2->x = 0;
|
||||
scale2->y = 0;
|
||||
scale2->type = type;
|
||||
scale2->larger = larger;
|
||||
// 初始化now_fb_msg槽位为NULL并重置索引
|
||||
scale2->now_fb_msg_idx = 0;
|
||||
for (itk = 0; itk < MAX_SCALE2_TX; itk++) {
|
||||
scale2->now_fb_msg[itk] = NULL;
|
||||
}
|
||||
fbpool_init(&scale2->tx_pool, MAX_SCALE2_TX);
|
||||
uint8_t init_count = 0;
|
||||
//uint8_t *data;
|
||||
// 初始化fb的一些默认信息
|
||||
while (init_count < MAX_SCALE2_TX)
|
||||
{
|
||||
// 预分配framebuff的空间给到scale
|
||||
//data = (uint8_t *)STREAM_MALLOC(ow * oh * 3 / 2);
|
||||
// 先配置参数信息
|
||||
//配置yuv信息,但是申请空间是申请scale3_yuv_arg_s,这里是特殊的,scale3_yuv_arg_s有自己的参数需要用到
|
||||
struct yuv_arg_s *yuv = (struct yuv_arg_s *)STREAM_LIBC_ZALLOC(sizeof(struct scale2_yuv_arg_s));
|
||||
// 由于创建流的时候,参数已经分配好了,所以这里可以确定参数
|
||||
yuv->y_size = scale2->ow * scale2->oh;
|
||||
yuv->uv_off = 0;
|
||||
yuv->y_off = 0;
|
||||
yuv->dispcnt = 0;
|
||||
yuv->out_w = scale2->ow;
|
||||
yuv->out_h = scale2->oh;
|
||||
yuv->del = &scale2->del;
|
||||
//os_printf("malloc data:%X\n",data);
|
||||
FBPOOL_SET_INFO(&scale2->tx_pool, init_count, NULL, ow * oh * 3 / 2, (void *)yuv);
|
||||
init_count++;
|
||||
}
|
||||
msi->enable = 1;
|
||||
// msi_add_output(msi,NULL,R_VIDEO_P1);
|
||||
// 发送自定义命令,启动scale3
|
||||
//msi_do_cmd(msi, MSI_CMD_SCALE2, MSI_SCALE2_START, 0);
|
||||
|
||||
os_msgq_init(&scale2->msgq, MAX_SCALE2_TX);
|
||||
|
||||
OS_WORK_INIT(&scale2->work, scale2_stream_work, 0);
|
||||
os_run_work_delay(&scale2->work, 1);
|
||||
}
|
||||
os_printf("%s:%d\tmsi:%X\n", __FUNCTION__, __LINE__, msi);
|
||||
return msi;
|
||||
}
|
||||
|
||||
int scale2_cfg_run(uint8_t streamfrom,uint8_t id){
|
||||
uint32 ow_n,oh_n;
|
||||
uint32_t w_start,h_start;
|
||||
uint32 larger;
|
||||
struct msi *scaler_msi = msi_find("scale2",0);
|
||||
struct scale2_msi_s *scale2 = (struct scale2_msi_s *)scaler_msi->priv;
|
||||
uint32 ie;
|
||||
int ret = 0;
|
||||
static uint32 last_cfg_time = 0;
|
||||
|
||||
if(scaler_msi) {
|
||||
msi_put(scaler_msi);
|
||||
}
|
||||
|
||||
#ifdef SYS_APP_WALKIE_TALKIE
|
||||
if(scale2->mutex_count) {
|
||||
if(os_jiffies() - last_cfg_time > 1000) {
|
||||
os_printf("scale2_cfg_run timeout\n");
|
||||
goto scale2_cfg_run_continue;
|
||||
}
|
||||
ret = 1;
|
||||
return ret;
|
||||
}
|
||||
scale2_cfg_run_continue:
|
||||
#endif
|
||||
scale2->mutex_count = 1;
|
||||
last_cfg_time = os_jiffies();
|
||||
ie = disable_irq();
|
||||
|
||||
// 满屏保留所有的画面,不在意变形
|
||||
#if SCALE2_MODE_SELECT == 0
|
||||
scale2->ow = scale2_msg[id].ow;
|
||||
scale2->oh = scale2_msg[id].oh;
|
||||
scale2->iw = scale2_msg[id].iw;
|
||||
scale2->ih = scale2_msg[id].ih;
|
||||
scale2->stw = scale2_msg[id].ow;
|
||||
scale2->sth = scale2_msg[id].oh;
|
||||
scale2->x = scale2_msg[id].x;
|
||||
scale2->y = scale2_msg[id].y;
|
||||
scale2->sx = 0;
|
||||
scale2->sy = 0;
|
||||
#endif
|
||||
//保证画面不变型,再进行缩放
|
||||
#if SCALE2_MODE_SELECT == 1
|
||||
scale2->ow = scale2_msg[id].ow;
|
||||
scale2->oh = scale2_msg[id].oh;
|
||||
scale2->iw = scale2_msg[id].iw;
|
||||
scale2->ih = scale2_msg[id].ih;
|
||||
scale2->x = scale2_msg[id].x;
|
||||
scale2->y = scale2_msg[id].y;
|
||||
scale2->larger = scale2_msg[id].larger;
|
||||
larger = scale2->larger;
|
||||
|
||||
if(((scale2->iw*1000)/scale2->ow) > ((scale2->ih*1000)/scale2->oh)){
|
||||
ow_n = (((scale2->iw*scale2->oh)/scale2->ih + 15)/16)*16 ;
|
||||
oh_n = scale2->oh;
|
||||
}else{
|
||||
ow_n = scale2->ow;
|
||||
oh_n = (((scale2->ih*scale2->ow)/scale2->iw + 15)/16)*16 ;
|
||||
}
|
||||
|
||||
w_start = ow_n*larger/10;
|
||||
h_start = oh_n*larger/10;
|
||||
scale2->stw = w_start;
|
||||
scale2->sth = h_start;
|
||||
scale2->sx = (w_start - ow_n)/2;
|
||||
scale2->sy = (h_start - oh_n)/2;
|
||||
#endif
|
||||
enable_irq(ie);
|
||||
|
||||
msi_do_cmd(scaler_msi, MSI_CMD_SCALE2, MSI_SCALE2_START, streamfrom);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void scale2_recfg_input_size(uint16_t w,uint16_t h,uint8_t id){
|
||||
uint32 ie;
|
||||
ie = disable_irq();
|
||||
scale2_msg[id].iw =w;
|
||||
scale2_msg[id].ih = h;
|
||||
enable_irq(ie);
|
||||
}
|
||||
767
sdk/app/scale_msi/scale3_msi.c
Normal file
767
sdk/app/scale_msi/scale3_msi.c
Normal file
@@ -0,0 +1,767 @@
|
||||
|
||||
#include "scale_msi.h"
|
||||
#include "dev/vpp/hgvpp.h"
|
||||
#include "lib/video/vpp/vpp_dev.h"
|
||||
#include "dev/scale/hgscale.h"
|
||||
#include "lib/heap/av_heap.h"
|
||||
#include "lib/heap/av_psram_heap.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
|
||||
struct scale3_yuv_arg_s
|
||||
{
|
||||
struct yuv_arg_s yuv_arg;
|
||||
uint16_t ow,oh;
|
||||
uint16_t ox,oy;
|
||||
uint8_t tx_type; //0~3 :video 4:error fb
|
||||
};
|
||||
|
||||
//暂时这里去控制scale3从哪个buf过来
|
||||
//请配合VPP那边配置
|
||||
#define SCALE3_YUVBUF_0_1 SCALE3_FROM_VPPBF
|
||||
|
||||
extern uint8 *yuvbuf;
|
||||
extern uint8 *yuvbuf1;
|
||||
#if SCALE3_YUVBUF_0_1 == 0
|
||||
#define SCALE3_LINE_BUF yuvbuf
|
||||
#define SCALE3_YUVBUF_Y_OFF_LINE ((VPP_BUF0_MODE == VPP_MODE_2N) ? (VPP_BUF0_LINEBUF_NUM * 2) : (VPP_BUF0_LINEBUF_NUM * 2 + 16))
|
||||
#elif SCALE3_YUVBUF_0_1 == 1
|
||||
#define SCALE3_LINE_BUF yuvbuf1
|
||||
#define SCALE3_YUVBUF_Y_OFF_LINE ((VPP_BUF1_MODE == VPP_MODE_2N) ? (VPP_BUF1_LINEBUF_NUM * 2) : (VPP_BUF1_LINEBUF_NUM * 2 + 16))
|
||||
#endif
|
||||
|
||||
|
||||
// 暂定这个scale3是在存在dvp的时候使用,所以用宏隔离
|
||||
// 实际scale3还有另一种模式不需要dvp那边启动的
|
||||
|
||||
|
||||
// 这里可能采用信号量的形式,通知到线程去处理数据
|
||||
|
||||
struct scale_msg_t scale3_msg[3] = {
|
||||
//ISP_VIDEO_0
|
||||
{
|
||||
.ow = 320,
|
||||
.oh = 180,
|
||||
.x = 0,
|
||||
.y = 0,
|
||||
.video_only = 0,
|
||||
},
|
||||
//ISP_VIDEO_1
|
||||
{
|
||||
.ow = 320,
|
||||
.oh = 180,
|
||||
.x = 320,
|
||||
.y = 0,
|
||||
.video_only = 0,
|
||||
},
|
||||
//ISP_VIDEO_2
|
||||
{
|
||||
.ow = 320,
|
||||
.oh = 180,
|
||||
.x = 0,
|
||||
.y = 180,
|
||||
.video_only = 0,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
static int32_t scale3_vpp_done_func(uint32 irq_data){
|
||||
struct scale3_msi_s *scale3 = (struct scale3_msi_s *)irq_data;
|
||||
struct framebuff *fb = NULL;
|
||||
uint8_t *p_buf;
|
||||
uint16_t xm,ym;
|
||||
uint16_t videow,videoh;
|
||||
uint8_t sennum = 0;
|
||||
struct scale3_yuv_arg_s *arg;
|
||||
uint8_t errfb;
|
||||
|
||||
if (SCALE3_YUVBUF_0_1 == 0)
|
||||
{
|
||||
extern uint8_t get_vpp_w_h(uint16_t *w, uint16_t *h);
|
||||
get_vpp_w_h(&videow, &videoh);
|
||||
}
|
||||
else if (SCALE3_YUVBUF_0_1 == 1)
|
||||
{
|
||||
extern uint8_t get_vpp1_w_h(uint16_t *w, uint16_t *h);
|
||||
get_vpp1_w_h(&videow, &videoh);
|
||||
}
|
||||
// static uint32_t scaler_cnt;
|
||||
//判断序号,有可能双镜头
|
||||
// scale3->seq++;
|
||||
if(scale3->txpool_type == 1){
|
||||
fb = fbpool_get(&scale3->tx_pool0, 0, scale3->msi);
|
||||
}else{
|
||||
if(video_msg.video_type_cur == ISP_VIDEO_0){
|
||||
if(video_msg.video_num == 2){
|
||||
fb = fbpool_get(&scale3->tx_pool1, 0, scale3->msi);
|
||||
}else{
|
||||
if(video_msg.video_type_last == ISP_VIDEO_1){
|
||||
fb = fbpool_get(&scale3->tx_pool2, 0, scale3->msi);
|
||||
}else{
|
||||
fb = fbpool_get(&scale3->tx_pool1, 0, scale3->msi);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(video_msg.video_type_cur == ISP_VIDEO_1){
|
||||
fb = fbpool_get(&scale3->tx_pool0, 0, scale3->msi);
|
||||
}
|
||||
|
||||
if(video_msg.video_type_cur == ISP_VIDEO_2){
|
||||
fb = fbpool_get(&scale3->tx_pool0, 0, scale3->msi);
|
||||
}
|
||||
}
|
||||
|
||||
errfb = 0;
|
||||
if(fb == NULL){
|
||||
fb = fbpool_get(&scale3->tx_poolerr, 0, scale3->msi);
|
||||
errfb = 1;
|
||||
}
|
||||
if(video_msg.video_num == 1){
|
||||
sennum = 0;
|
||||
}else if(video_msg.video_num == 2){
|
||||
if(video_msg.video_type_cur == ISP_VIDEO_0){
|
||||
sennum = 1;
|
||||
}else{
|
||||
sennum = 0;
|
||||
}
|
||||
}else{
|
||||
if((video_msg.video_type_cur == ISP_VIDEO_1)||(video_msg.video_type_cur == ISP_VIDEO_2)){
|
||||
sennum = 0;
|
||||
}else if(video_msg.video_type_last == ISP_VIDEO_1){
|
||||
sennum = 2;
|
||||
}else if(video_msg.video_type_last == ISP_VIDEO_2){
|
||||
sennum = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
arg = (struct scale3_yuv_arg_s*)fb->priv;
|
||||
if(errfb){
|
||||
scale3->ow = 128;//ow;
|
||||
scale3->oh = 96;//oh;
|
||||
xm = 0;
|
||||
ym = 0;
|
||||
}else{
|
||||
if(fb->len != (scale3_msg[sennum].ow * scale3_msg[sennum].oh * 3)/2 ){
|
||||
scale3->ow = arg->ow;
|
||||
scale3->oh = arg->oh;
|
||||
|
||||
xm = arg->ox;
|
||||
ym = arg->oy;
|
||||
}else{
|
||||
scale3->ow = scale3_msg[sennum].ow;//ow;
|
||||
scale3->oh = scale3_msg[sennum].oh;//oh;
|
||||
xm = scale3_msg[sennum].x;
|
||||
ym = scale3_msg[sennum].y;
|
||||
}
|
||||
}
|
||||
scale3->iw = videow;//scale3_msg[sennum].iw;//iw;
|
||||
scale3->ih = videoh;//scale3_msg[sennum].ih;//ih;
|
||||
arg->yuv_arg.x = xm;//scale3_msg[sennum].x;
|
||||
arg->yuv_arg.y = ym;//scale3_msg[sennum].y;
|
||||
arg->yuv_arg.video_only = scale3_msg[sennum].video_only;
|
||||
arg->yuv_arg.y_size = scale3->ow*scale3->oh;
|
||||
arg->yuv_arg.out_w = scale3->ow;
|
||||
arg->yuv_arg.out_h = scale3->oh;
|
||||
|
||||
// 暂时用同样的iw ih ow oh
|
||||
scale_set_in_out_size(scale3->scale_dev, scale3->iw, scale3->ih, scale3->ow, scale3->oh);
|
||||
scale_set_step(scale3->scale_dev, scale3->iw, scale3->ih, scale3->ow, scale3->oh);
|
||||
scale_set_in_yaddr(scale3->scale_dev, (uint32)scale3->scaler3buf);
|
||||
scale_set_in_uaddr(scale3->scale_dev, (uint32)scale3->scaler3buf + scale3->iw * SCALE3_YUVBUF_Y_OFF_LINE);
|
||||
scale_set_in_vaddr(scale3->scale_dev, (uint32)scale3->scaler3buf + scale3->iw * SCALE3_YUVBUF_Y_OFF_LINE + scale3->iw * SCALE3_YUVBUF_Y_OFF_LINE/4);
|
||||
|
||||
// _os_printf("M(%x %x)",fb,fb->data);
|
||||
fb->len = scale3->ow * scale3->oh * 3 / 2;
|
||||
// 配置新的空间地址
|
||||
p_buf = (uint8_t *)fb->data;
|
||||
scale_set_out_yaddr(scale3->scale_dev, (uint32)p_buf);
|
||||
scale_set_out_uaddr(scale3->scale_dev, (uint32)p_buf + scale3->ow * scale3->oh);
|
||||
scale_set_out_vaddr(scale3->scale_dev, (uint32)p_buf + scale3->ow * scale3->oh + scale3->ow * scale3->oh / 4);
|
||||
|
||||
if(errfb){
|
||||
msi_delete_fb(NULL, fb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
arg = (struct scale3_yuv_arg_s *)scale3->now_fb->priv;
|
||||
scale3->now_fb->stype = FSTYPE_YUV_P0+video_msg.video_type_cur;
|
||||
|
||||
// 发送now_data,发送失败也要返回
|
||||
|
||||
if(arg->tx_type == video_msg.video_type_cur){
|
||||
if (os_msgq_put(&scale3->msgq, (uint32_t)scale3->now_fb, 0))
|
||||
{
|
||||
// 正常不能中断del,但是这个模块是内部,只要del没有一些等待信号量操作,问题不大
|
||||
msi_delete_fb(NULL, scale3->now_fb);
|
||||
scale3->now_fb = NULL;
|
||||
//return 0;
|
||||
}
|
||||
}else{
|
||||
msi_delete_fb(NULL, scale3->now_fb);
|
||||
}
|
||||
|
||||
|
||||
scale3->now_fb = fb;
|
||||
// os_printf("%s:%d\n",__FUNCTION__,__LINE__);
|
||||
return 0;
|
||||
|
||||
|
||||
}
|
||||
|
||||
static int32_t scale3_stream_done(uint32 irq_flag, uint32 irq_data, uint32 param1)
|
||||
{
|
||||
//*(volatile uint32_t*)0x400e0124 |= (1<<14);
|
||||
//*(volatile uint32_t*)0x400e0124 &= ~(1<<14);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t scale3_stream_ov(uint32 irq_flag, uint32 irq_data, uint32 param1)
|
||||
{
|
||||
os_printf("%s:%d\n", __FUNCTION__, __LINE__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int32 scale3_stream_work(struct os_work *work)
|
||||
{
|
||||
int32_t ret;
|
||||
struct scale3_msi_s *scale3 = (struct scale3_msi_s *)work;
|
||||
struct framebuff *fb;
|
||||
struct scale3_yuv_arg_s *arg;
|
||||
int32_t err = -1;
|
||||
fb = (struct framebuff *)os_msgq_get2(&scale3->msgq, 0, &err);
|
||||
// 没有数据
|
||||
if (err)
|
||||
{
|
||||
goto scale3_stream_work_end;
|
||||
}
|
||||
|
||||
arg = (struct scale3_yuv_arg_s*)fb->priv;
|
||||
arg->yuv_arg.dispcnt++;
|
||||
fb->mtype = F_YUV;
|
||||
//_os_printf("P(%d x:%d y:%d)",fb->stype,arg->yuv_arg.x,arg->yuv_arg.y);
|
||||
//os_printf("scale3 fb:%X type:%d x:%d y:%d w:%d h:%d\r\n",fb,fb->stype,arg->yuv_arg.x,arg->yuv_arg.y,arg->yuv_arg.out_w,arg->yuv_arg.out_h);
|
||||
if(arg->tx_type == 4){
|
||||
fbpool_put(&scale3->tx_poolerr, fb);
|
||||
}else{
|
||||
//_os_printf("<S %08x>",fb->data);
|
||||
ret = msi_output_fb(scale3->msi, fb);
|
||||
}
|
||||
|
||||
scale3_stream_work_end:
|
||||
// 过1ms就去轮询一遍,实际如果用信号量,可以改成任务形式,等待信号量,可以节约cpu(实际cache影响可能更大,cpu占用很少)
|
||||
// 由于workqueue没有支持等待信号量,只能通过1ms轮询一下
|
||||
os_run_work_delay(work, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static int32_t scale3_msi_action(struct msi *msi, uint32_t cmd_id, uint32_t param1, uint32_t param2)
|
||||
{
|
||||
int32_t ret = RET_OK;
|
||||
uint32 ie;
|
||||
struct scale3_msi_s *scale3 = (struct scale3_msi_s *)msi->priv;
|
||||
struct scale3_yuv_arg_s *arg;
|
||||
switch (cmd_id)
|
||||
{
|
||||
|
||||
// 这里msi已经被删除,那么就要考虑tx_pool的资源释放了
|
||||
// 能进来这里,就是代表所有fb都已经用完了
|
||||
case MSI_CMD_POST_DESTROY:
|
||||
{
|
||||
|
||||
struct framebuff *fb;
|
||||
// 释放资源fb资源文件
|
||||
int temp_video_num = scale3->init_txpool_num;
|
||||
for(int init_txpool_num = 0; init_txpool_num < temp_video_num ; init_txpool_num++) {
|
||||
while (1)
|
||||
{
|
||||
fb = fbpool_get(&scale3->tx_pool0 + init_txpool_num, 0, NULL);
|
||||
if (!fb)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if(fb->data)
|
||||
{
|
||||
//os_printf("D(%x %x)\n",fb,fb->data);
|
||||
STREAM_FREE(fb->data);
|
||||
fb->data = NULL;
|
||||
}
|
||||
// 预分配空间释放
|
||||
if (fb->priv)
|
||||
{
|
||||
//os_printf("D(%x %x)\n",fb,fb->priv);
|
||||
STREAM_LIBC_FREE(fb->priv);
|
||||
fb->priv = NULL;
|
||||
}
|
||||
}
|
||||
fbpool_destroy(&scale3->tx_pool0 + init_txpool_num);
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
fb = fbpool_get(&scale3->tx_poolerr, 0, NULL);
|
||||
if (!fb)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if(fb->data)
|
||||
{
|
||||
//os_printf("E(%x %x)\n",fb,fb->data);
|
||||
STREAM_FREE(fb->data);
|
||||
fb->data = NULL;
|
||||
}
|
||||
// 预分配空间释放
|
||||
if (fb->priv)
|
||||
{
|
||||
//os_printf("E(%x %x)\n",fb,fb->priv);
|
||||
STREAM_LIBC_FREE(fb->priv);
|
||||
fb->priv = NULL;
|
||||
}
|
||||
}
|
||||
fbpool_destroy(&scale3->tx_poolerr);
|
||||
STREAM_LIBC_FREE(scale3);
|
||||
msi->priv = NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
// 停止硬件,移除没有必要的资源(但是fb的资源不能现在删除,这个时候fb可能外部还在调用)
|
||||
case MSI_CMD_PRE_DESTROY:
|
||||
{
|
||||
os_work_cancle2(&scale3->work, 1);
|
||||
scale_close(scale3->scale_dev);
|
||||
// os_printf("%s:%d MSI_CMD_PRE_DESTROY\n", __FUNCTION__, __LINE__);
|
||||
|
||||
// 移除信号量里面的数据
|
||||
struct framebuff *fb = NULL;
|
||||
int32_t err = 0;
|
||||
while (!err)
|
||||
{
|
||||
fb = (struct framebuff *)os_msgq_get2(&scale3->msgq, 0, &err);
|
||||
if (fb)
|
||||
{
|
||||
msi_delete_fb(NULL, fb);
|
||||
}
|
||||
fb = NULL;
|
||||
}
|
||||
|
||||
vppdone_func_unregister(SCALER3_DONE);
|
||||
|
||||
if (scale3->msgq.hdl) {
|
||||
os_msgq_del(&scale3->msgq);
|
||||
}
|
||||
|
||||
fb = scale3->now_fb;
|
||||
if (scale3->now_fb)
|
||||
{
|
||||
msi_delete_fb(NULL, scale3->now_fb);
|
||||
scale3->now_fb = NULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
// 接收,判断是类型是否可以支持压缩
|
||||
case MSI_CMD_TRANS_FB:
|
||||
{
|
||||
}
|
||||
break;
|
||||
// 预先分配的,默认不需要释放fb->data,除非是MSI_CMD_DESTROY后,就要释放
|
||||
case MSI_CMD_FREE_FB:
|
||||
{
|
||||
struct framebuff *fb = (struct framebuff *)param1;
|
||||
uint8_t type = 0;
|
||||
arg = (struct scale3_yuv_arg_s*)fb->priv;
|
||||
if(arg->tx_type == 0){
|
||||
type = 0;
|
||||
}else if(arg->tx_type == 1){
|
||||
type = 1;
|
||||
}else if(arg->tx_type == 2){
|
||||
type = 2;
|
||||
}else{
|
||||
type = 4;
|
||||
}
|
||||
|
||||
if (fb->data && (type < 4))
|
||||
{
|
||||
ie = disable_irq();
|
||||
if(fb->len != (scale3_msg[type].ow * scale3_msg[type].oh * 3) / 2){
|
||||
STREAM_FREE(fb->data); //释放之前的空间
|
||||
fb->data = (uint8_t *)STREAM_MALLOC((scale3_msg[type].ow * scale3_msg[type].oh * 3) / 2); //申请到新的大空间
|
||||
sys_dcache_invalid_range((void *)fb->data, (scale3_msg[type].ow * scale3_msg[type].oh * 3) / 2);
|
||||
fb->len = (scale3_msg[type].ow * scale3_msg[type].oh * 3) / 2;
|
||||
arg->ow = scale3_msg[type].ow;
|
||||
arg->oh = scale3_msg[type].oh;
|
||||
arg->ox = scale3_msg[type].x;
|
||||
arg->oy = scale3_msg[type].y;
|
||||
}
|
||||
enable_irq(ie);
|
||||
}
|
||||
//这里要更改一下,看put到哪里去
|
||||
if(type == 0){
|
||||
fbpool_put(&scale3->tx_pool0, fb);
|
||||
}else if(type == 1){
|
||||
fbpool_put(&scale3->tx_pool1, fb);
|
||||
}else if(type == 2){
|
||||
fbpool_put(&scale3->tx_pool2, fb);
|
||||
}else{
|
||||
fbpool_put(&scale3->tx_poolerr, fb);
|
||||
}
|
||||
// 不需要内核去释放fb
|
||||
ret = RET_OK + 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case MSI_CMD_SCALE3:
|
||||
{
|
||||
uint32_t cmd_self = (uint32_t)param1;
|
||||
//uint32_t arg = param2;
|
||||
// 自定义命令
|
||||
switch (cmd_self)
|
||||
{
|
||||
case MSI_SCALE3_START:
|
||||
{
|
||||
//注意,这里需要根据vpp那边配置来决定用哪个
|
||||
//注意line buf的数量
|
||||
uint8_t video_type = 0;
|
||||
uint8_t *p_buf;
|
||||
uint16_t videow,videoh;
|
||||
struct fbpool * tx_pool;
|
||||
struct framebuff *fb;
|
||||
|
||||
scale3->scaler3buf = SCALE3_LINE_BUF;
|
||||
os_msgq_init(&scale3->msgq, MAX_SCALE3_TX);
|
||||
|
||||
OS_WORK_INIT(&scale3->work, scale3_stream_work, 0);
|
||||
os_run_work_delay(&scale3->work, 1);
|
||||
|
||||
if(video_msg.video_num == 1){
|
||||
video_type = ISP_VIDEO_0;
|
||||
}else if(video_msg.video_num == 2){
|
||||
video_type = video_msg.video_type_last; //
|
||||
}else{
|
||||
if((video_msg.video_type_cur == ISP_VIDEO_1)||(video_msg.video_type_cur == ISP_VIDEO_2)){
|
||||
video_type = ISP_VIDEO_0;
|
||||
}else if(video_msg.video_type_last == ISP_VIDEO_1){
|
||||
video_type = ISP_VIDEO_2;
|
||||
}else if(video_msg.video_type_last == ISP_VIDEO_2){
|
||||
video_type = ISP_VIDEO_1;
|
||||
}
|
||||
}
|
||||
|
||||
if (SCALE3_YUVBUF_0_1 == 0)
|
||||
{
|
||||
extern uint8_t get_vpp_w_h(uint16_t *w, uint16_t *h);
|
||||
get_vpp_w_h(&videow, &videoh);
|
||||
}
|
||||
else if (SCALE3_YUVBUF_0_1 == 1)
|
||||
{
|
||||
extern uint8_t get_vpp1_w_h(uint16_t *w, uint16_t *h);
|
||||
get_vpp1_w_h(&videow, &videoh);
|
||||
}
|
||||
|
||||
scale_set_start_addr(scale3->scale_dev, 0, 0);
|
||||
// 暂时固定,如果遇到需要动态修改的,可以通过参数之类来切换
|
||||
scale_set_dma_to_memory(scale3->scale_dev, 1);
|
||||
scale_set_data_from_vpp(scale3->scale_dev, 1);
|
||||
scale_set_line_buf_num(scale3->scale_dev, SCALE3_YUVBUF_Y_OFF_LINE);
|
||||
|
||||
|
||||
scale3->ow = scale3_msg[video_type].ow;//ow;
|
||||
scale3->oh = scale3_msg[video_type].oh;//oh;
|
||||
scale3->iw = videow;//scale3_msg[video_type].iw;//iw;
|
||||
scale3->ih = videoh;//scale3_msg[video_type].ih;//ih;
|
||||
|
||||
|
||||
// 暂时用同样的iw ih ow oh
|
||||
scale_set_in_out_size(scale3->scale_dev, scale3->iw, scale3->ih, scale3->ow, scale3->oh);
|
||||
scale_set_step(scale3->scale_dev, scale3->iw, scale3->ih, scale3->ow, scale3->oh);
|
||||
scale_set_in_yaddr(scale3->scale_dev, (uint32)scale3->scaler3buf);
|
||||
scale_set_in_uaddr(scale3->scale_dev, (uint32)scale3->scaler3buf + scale3->iw * SCALE3_YUVBUF_Y_OFF_LINE);
|
||||
scale_set_in_vaddr(scale3->scale_dev, (uint32)scale3->scaler3buf + scale3->iw * SCALE3_YUVBUF_Y_OFF_LINE + scale3->iw * SCALE3_YUVBUF_Y_OFF_LINE/4);
|
||||
|
||||
// 这里分配一下scale3的空间,通过标准接口去分配吧,理论这里一定能获取到,这里就不判断异常情况了
|
||||
|
||||
// 正常应该要获取到fb
|
||||
if(scale3->txpool_type == 1){
|
||||
fb = fbpool_get(&scale3->tx_pool0, 0, scale3->msi);
|
||||
}else{
|
||||
if(video_type == ISP_VIDEO_0){
|
||||
tx_pool = &scale3->tx_pool0;
|
||||
}else if(video_type == ISP_VIDEO_1){
|
||||
tx_pool = &scale3->tx_pool1;
|
||||
}else{
|
||||
tx_pool = &scale3->tx_pool2;
|
||||
}
|
||||
fb = fbpool_get(tx_pool, 0, scale3->msi);
|
||||
}
|
||||
arg = (struct scale3_yuv_arg_s*)fb->priv;
|
||||
arg->yuv_arg.x = scale3_msg[video_type].x;
|
||||
arg->yuv_arg.y = scale3_msg[video_type].y;
|
||||
//os_printf("arg w:%d arg h:%d\r\n",arg->yuv_arg.out_w,arg->yuv_arg.out_h);
|
||||
|
||||
p_buf = fb->data;
|
||||
scale3->now_fb = fb;
|
||||
|
||||
scale_set_out_yaddr(scale3->scale_dev, (uint32)p_buf);
|
||||
scale_set_out_uaddr(scale3->scale_dev, (uint32)p_buf + scale3->ow * scale3->oh);
|
||||
scale_set_out_vaddr(scale3->scale_dev, (uint32)p_buf + scale3->ow * scale3->oh + scale3->ow * scale3->oh / 4);
|
||||
scale_request_irq(scale3->scale_dev, FRAME_END, scale3_stream_done, (uint32)scale3);
|
||||
scale_request_irq(scale3->scale_dev, INBUF_OV, scale3_stream_ov, (uint32)scale3);
|
||||
scale_open(scale3->scale_dev);
|
||||
// 由于硬件需要vpp参与,所以这里会耦合了其他硬件模块
|
||||
struct vpp_device *vpp_dev;
|
||||
vpp_dev = (struct vpp_device *)dev_get(HG_VPP_DEVID);
|
||||
vpp_open(vpp_dev);
|
||||
|
||||
vppdone_func_register(SCALER3_DONE,scale3_vpp_done_func,(uint32)scale3);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern scale3_kick_fn scale3_kick_func;
|
||||
int32_t scaler3_kick_start(){
|
||||
struct msi *msi = msi_find(S_PREVIEW_SCALE3, 0);
|
||||
msi_do_cmd(msi, MSI_CMD_SCALE3, MSI_SCALE3_START, 0);
|
||||
msi_put(msi);
|
||||
scale3_kick_func = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// 参数分别是vpp的图像iw和ih,要scale的ow和oh,如果和屏有关,可以传入屏幕的宽高
|
||||
struct msi *scale3_msi(const char *name)
|
||||
{
|
||||
struct msi *msi = msi_new(name, 0, NULL);
|
||||
|
||||
if(msi == NULL){
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct scale3_msi_s *scale3 = (struct scale3_msi_s *)msi->priv;
|
||||
struct scale_msg_t *scale_msg[3];
|
||||
uint8_t *fbuf;
|
||||
|
||||
scale_msg[0] = &scale3_msg[0];
|
||||
scale_msg[1] = &scale3_msg[1];
|
||||
scale_msg[2] = &scale3_msg[2];
|
||||
|
||||
if (!scale3)
|
||||
{
|
||||
// os_printf("%s:%d new success\n", __FUNCTION__, __LINE__);
|
||||
scale3 = (struct scale3_msi_s *)STREAM_LIBC_ZALLOC(sizeof(struct scale3_msi_s));
|
||||
msi->action = scale3_msi_action;
|
||||
msi->priv = (void *)scale3;
|
||||
scale3->msi = msi;
|
||||
scale3->scale_dev = (struct scale_device *)dev_get(HG_SCALE3_DEVID);
|
||||
scale3->txpool_type = 0;
|
||||
|
||||
int temp_video_num = video_msg.video_num;
|
||||
scale3->init_txpool_num = temp_video_num;
|
||||
|
||||
for(int init_txpool_num = 0; init_txpool_num < temp_video_num ; init_txpool_num++) {
|
||||
int fbpool_init_size = 0;
|
||||
|
||||
//if (SCALE3_YUVBUF_0_1 == 0)
|
||||
//{
|
||||
// extern uint8_t get_vpp_w_h(uint16_t *w, uint16_t *h);
|
||||
//get_vpp_w_h(&scale_msg[init_txpool_num]->iw, &scale_msg[init_txpool_num]->ih);
|
||||
//}
|
||||
//else if (SCALE3_YUVBUF_0_1 == 1)
|
||||
//{
|
||||
// extern uint8_t get_vpp1_w_h(uint16_t *w, uint16_t *h);
|
||||
//get_vpp1_w_h(&scale_msg[init_txpool_num]->iw, &scale_msg[init_txpool_num]->ih);
|
||||
//}
|
||||
|
||||
switch (init_txpool_num)
|
||||
{
|
||||
/* txpool0 */
|
||||
case 0:
|
||||
{
|
||||
fbpool_init_size = 2;
|
||||
if (temp_video_num == 1) {
|
||||
fbpool_init_size++;
|
||||
scale3->txpool_type = 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
/* txpool1 */
|
||||
case 1:
|
||||
{
|
||||
fbpool_init_size = 2;
|
||||
if(temp_video_num > 2)
|
||||
fbpool_init_size--;
|
||||
}
|
||||
break;
|
||||
|
||||
/* txpool2 */
|
||||
case 2:
|
||||
{
|
||||
fbpool_init_size = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
os_printf("scale3 init txpool num:%d size:%d txpool0:0x%x txpool1:0x%x txpool2:0x%x\r\n",init_txpool_num,fbpool_init_size, &scale3->tx_pool0 + 0, &scale3->tx_pool0 + 1, &scale3->tx_pool0 + 2);
|
||||
fbpool_init(&scale3->tx_pool0 + init_txpool_num, fbpool_init_size);
|
||||
for(int i = 0; i < fbpool_init_size; i++) {
|
||||
struct scale3_yuv_arg_s *yuv_priv = (struct scale3_yuv_arg_s *)STREAM_LIBC_ZALLOC(sizeof(struct scale3_yuv_arg_s));
|
||||
struct yuv_arg_s *yuv = (struct yuv_arg_s *)yuv_priv;
|
||||
scale3->ow = scale_msg[init_txpool_num]->ow;
|
||||
scale3->oh = scale_msg[init_txpool_num]->oh;
|
||||
yuv->y_size = scale3->ow * scale3->oh;
|
||||
yuv->uv_off = 0;
|
||||
yuv->y_off = 0;
|
||||
yuv->out_w = scale3->ow;
|
||||
yuv->out_h = scale3->oh;
|
||||
yuv->del = &scale3->del;
|
||||
|
||||
yuv_priv->tx_type = init_txpool_num;
|
||||
yuv_priv->ow = scale3->ow;
|
||||
yuv_priv->oh = scale3->oh;
|
||||
|
||||
fbuf = (uint8_t *)STREAM_MALLOC(scale3->ow * scale3->oh * 3 / 2);
|
||||
FBPOOL_SET_INFO(&scale3->tx_pool0 + init_txpool_num, i, fbuf, scale3->ow * scale3->oh * 3 / 2, (void *)yuv);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fbpool_init(&scale3->tx_poolerr, 1);
|
||||
struct scale3_yuv_arg_s * yuv_priv = (struct scale3_yuv_arg_s *)STREAM_LIBC_ZALLOC(sizeof(struct scale3_yuv_arg_s));
|
||||
struct yuv_arg_s *yuv = (struct yuv_arg_s *)yuv_priv;
|
||||
yuv->y_size = 128 * 96;
|
||||
yuv->uv_off = 0;
|
||||
yuv->y_off = 0;
|
||||
yuv->out_w = 128;
|
||||
yuv->out_h = 96;
|
||||
yuv->del = &scale3->del;
|
||||
scale3->ow = 128;
|
||||
scale3->oh = 96;
|
||||
yuv_priv->tx_type = 4;
|
||||
fbuf = (uint8_t *)STREAM_MALLOC(128 * 96 * 3 / 2);
|
||||
FBPOOL_SET_INFO(&scale3->tx_poolerr, 0, fbuf, 128 * 96 * 3 / 2, (void *)yuv);
|
||||
|
||||
msi->enable = 1;
|
||||
|
||||
scale3_kick_func = scaler3_kick_start;
|
||||
|
||||
}
|
||||
os_printf("%s:%d\tmsi:%X\n", __FUNCTION__, __LINE__, msi);
|
||||
return msi;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int32_t const_scale3_msi_action(struct msi *msi, uint32_t cmd_id, uint32_t param1, uint32_t param2)
|
||||
{
|
||||
int32_t ret = RET_OK;
|
||||
struct const_scale3_msi_s *scale3 = (struct const_scale3_msi_s *)msi->priv;
|
||||
switch (cmd_id)
|
||||
{
|
||||
|
||||
// 这里msi已经被删除,那么就要考虑tx_pool的资源释放了
|
||||
// 能进来这里,就是代表所有fb都已经用完了
|
||||
case MSI_CMD_POST_DESTROY:
|
||||
{
|
||||
STREAM_LIBC_FREE(scale3);
|
||||
}
|
||||
break;
|
||||
|
||||
// 停止硬件,移除没有必要的资源(但是fb的资源不能现在删除,这个时候fb可能外部还在调用)
|
||||
case MSI_CMD_PRE_DESTROY:
|
||||
{
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int32_t const_scale3_stream_done(uint32 irq_flag, uint32 irq_data, uint32 param1)
|
||||
{
|
||||
_os_printf("CO");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void scale3_output_size_local_change(uint8_t id,uint8_t show_only,uint16 x,uint16 y,uint16 w,uint16 h){
|
||||
uint32 ie;
|
||||
ie = disable_irq();
|
||||
scale3_msg[id].x = x;
|
||||
scale3_msg[id].y = y;
|
||||
scale3_msg[id].ow = w;
|
||||
scale3_msg[id].oh = h;
|
||||
scale3_msg[id].video_only = show_only;
|
||||
enable_irq(ie);
|
||||
}
|
||||
|
||||
//固定空间,由外部给空间,不再采用流的方式
|
||||
//buf需要给够空间,根据ow和oh来计算
|
||||
struct msi *scale3_msi_const_buf(const char *name, uint8_t *buf,uint16_t iw, uint16_t ih, uint16_t ow, uint16_t oh)
|
||||
{
|
||||
uint8_t isnew;
|
||||
struct msi *msi = msi_new(name, 0, &isnew);
|
||||
if (isnew)
|
||||
{
|
||||
struct scale_device *scale_dev = (struct scale_device *)dev_get(HG_SCALE3_DEVID);
|
||||
os_printf("%s:%d new success\n", __FUNCTION__, __LINE__);
|
||||
struct const_scale3_msi_s *scale3 = (struct const_scale3_msi_s *)STREAM_LIBC_ZALLOC(sizeof(struct const_scale3_msi_s));
|
||||
scale3->scale_dev = scale_dev;
|
||||
msi->priv = (void *)scale3;
|
||||
msi->action = const_scale3_msi_action;
|
||||
msi->enable = 0;
|
||||
|
||||
// 暂时用同样的iw ih ow oh
|
||||
scale_set_in_out_size(scale_dev, iw, ih, ow, oh);
|
||||
scale_set_step(scale_dev, iw, ih, ow, oh);
|
||||
scale_set_start_addr(scale_dev, 0, 0);
|
||||
// 暂时固定,如果遇到需要动态修改的,可以通过参数之类来切换
|
||||
scale_set_dma_to_memory(scale_dev, 1);
|
||||
scale_set_data_from_vpp(scale_dev, 1);
|
||||
scale_set_line_buf_num(scale_dev, 28);
|
||||
scale_set_in_yaddr(scale_dev, (uint32)yuvbuf);
|
||||
scale_set_in_uaddr(scale_dev, (uint32)yuvbuf + iw * 28);
|
||||
scale_set_in_vaddr(scale_dev, (uint32)yuvbuf + iw * 28 + iw * 28/4);
|
||||
|
||||
|
||||
|
||||
scale_set_out_yaddr(scale_dev, (uint32)buf);
|
||||
scale_set_out_uaddr(scale_dev, (uint32)buf + ow * oh);
|
||||
scale_set_out_vaddr(scale_dev, (uint32)buf + ow * oh + ow * oh / 4);
|
||||
scale_request_irq(scale_dev, FRAME_END, const_scale3_stream_done, (uint32)scale3);
|
||||
scale_request_irq(scale_dev, INBUF_OV, scale3_stream_ov, (uint32)scale3);
|
||||
scale_open(scale_dev);
|
||||
// 由于硬件需要vpp参与,所以这里会耦合了其他硬件模块
|
||||
struct vpp_device *vpp_dev;
|
||||
vpp_dev = (struct vpp_device *)dev_get(HG_VPP_DEVID);
|
||||
vpp_open(vpp_dev);
|
||||
|
||||
}
|
||||
os_printf("%s:%d\tmsi:%X\n", __FUNCTION__, __LINE__, msi);
|
||||
return msi;
|
||||
}
|
||||
518
sdk/app/scale_msi/scale3_normal_msi.c
Normal file
518
sdk/app/scale_msi/scale3_normal_msi.c
Normal file
@@ -0,0 +1,518 @@
|
||||
|
||||
#include "scale_msi.h"
|
||||
#include "dev/vpp/hgvpp.h"
|
||||
#include "lib/video/vpp/vpp_dev.h"
|
||||
#include "dev/scale/hgscale.h"
|
||||
#include "lib/heap/av_heap.h"
|
||||
#include "lib/heap/av_psram_heap.h"
|
||||
#include "user_work/user_work.h"
|
||||
#include "scale3_normal_msi.h"
|
||||
|
||||
extern int32_t takephoto_name_no_dir_time(char *filename, int filename_size,struct timeval *t);
|
||||
#define EXTERN_RB_COUNT 50
|
||||
|
||||
uint32_t yuv_buf_line(uint8_t which);
|
||||
|
||||
#define MAX_COUNT 3
|
||||
|
||||
/*********************************************************************
|
||||
* 这个模块是分别输出两种图片的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 scale3_normal_msi
|
||||
{
|
||||
struct os_work work;
|
||||
struct msi *msi;
|
||||
struct scale_device *scale_dev;
|
||||
struct fbpool pool;
|
||||
struct os_msgqueue msgq;
|
||||
uint8_t *buf;
|
||||
uint16_t iw, ih;
|
||||
uint16_t ow, oh;
|
||||
struct framebuff *fb;
|
||||
struct framebuff *extern_fb;
|
||||
struct scale3_normal_cmd_s *normal_cmd;
|
||||
uint32_t last_time;
|
||||
uint8_t force_stype;
|
||||
uint8_t ready : 1, extern_fb_ready : 1, start : 1,exit:1;
|
||||
RBUFFER_DEF(extern_rb, struct scale3_normal_cmd_s *, EXTERN_RB_COUNT);
|
||||
};
|
||||
|
||||
void *get_vpp_buf(uint8_t which);
|
||||
uint8_t get_vpp_w_h(uint16_t *w, uint16_t *h);
|
||||
|
||||
static int32_t const_scale3_msi_action(struct msi *msi, uint32_t cmd_id, uint32_t param1, uint32_t param2)
|
||||
{
|
||||
int32_t ret = RET_OK;
|
||||
struct scale3_normal_msi *scale3 = (struct scale3_normal_msi *) msi->priv;
|
||||
switch (cmd_id)
|
||||
{
|
||||
// 这里msi已经被删除,那么就要考虑tx_pool的资源释放了
|
||||
// 能进来这里,就是代表所有fb都已经用完了
|
||||
case MSI_CMD_POST_DESTROY:
|
||||
{
|
||||
struct framebuff *fb;
|
||||
// 释放资源fb资源文件
|
||||
while (1)
|
||||
{
|
||||
fb = fbpool_get(&scale3->pool, 0, NULL);
|
||||
if (!fb)
|
||||
{
|
||||
break;
|
||||
}
|
||||
// 预分配空间释放
|
||||
if (fb->priv)
|
||||
{
|
||||
STREAM_LIBC_FREE(fb->priv);
|
||||
}
|
||||
|
||||
if (fb->data)
|
||||
{
|
||||
STREAM_FREE(fb->data);
|
||||
}
|
||||
}
|
||||
os_msgq_del(&scale3->msgq);
|
||||
|
||||
struct scale3_normal_cmd_s *normal_cmd;
|
||||
if(scale3->normal_cmd)
|
||||
{
|
||||
STREAM_FREE(scale3->normal_cmd);
|
||||
scale3->normal_cmd = NULL;
|
||||
}
|
||||
while(RB_GET(&scale3->extern_rb, normal_cmd))
|
||||
{
|
||||
STREAM_FREE(normal_cmd);
|
||||
}
|
||||
STREAM_FREE(scale3);
|
||||
}
|
||||
break;
|
||||
|
||||
// 停止硬件,移除没有必要的资源(但是fb的资源不能现在删除,这个时候fb可能外部还在调用)
|
||||
case MSI_CMD_PRE_DESTROY:
|
||||
{
|
||||
scale_close(scale3->scale_dev);
|
||||
// 关闭work
|
||||
os_work_cancle2(&scale3->work, 1);
|
||||
|
||||
scale3->start = 0;
|
||||
scale3->exit = 1;
|
||||
|
||||
if (scale3->extern_fb)
|
||||
{
|
||||
msi_delete_fb(scale3->msi, scale3->fb);
|
||||
scale3->fb = NULL;
|
||||
}
|
||||
|
||||
if (scale3->fb)
|
||||
{
|
||||
msi_delete_fb(scale3->msi, scale3->fb);
|
||||
scale3->fb = NULL;
|
||||
}
|
||||
struct framebuff *fb = NULL;
|
||||
while (1)
|
||||
{
|
||||
fb = (struct framebuff *) os_msgq_get2(&scale3->msgq, 0, NULL);
|
||||
if (fb)
|
||||
{
|
||||
msi_delete_fb(NULL, fb);
|
||||
fb = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MSI_CMD_FREE_FB:
|
||||
{
|
||||
struct framebuff *fb = (struct framebuff *) param1;
|
||||
// sys_dcache_invalid_range(fb->data, scale3->ow * scale3->oh * 3 / 2);
|
||||
if (fb->datatag != 0xff)
|
||||
{
|
||||
fbpool_put(&scale3->pool, fb);
|
||||
ret = RET_OK + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
STREAM_FREE(fb->data);
|
||||
STREAM_LIBC_FREE(fb->priv);
|
||||
scale3->extern_fb_ready = 1;
|
||||
}
|
||||
if(!scale3->exit)
|
||||
{
|
||||
os_run_work(&scale3->work);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// 私有命令,特定结构体{w,h,time,stype}
|
||||
case MSI_CMD_SCALE3_NORMAL:
|
||||
{
|
||||
uint32_t cmd_self = (uint32_t) param1;
|
||||
// uint32_t arg = param2;
|
||||
switch (cmd_self)
|
||||
{
|
||||
case MSI_SCALE3_START:
|
||||
{
|
||||
scale3->start = param2 & 0x01;
|
||||
os_run_work(&scale3->work);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MSI_SCLAE3_NORMAL_ADD_DPI:
|
||||
{
|
||||
// 申请一个arg结构体给到ringbuf,等待workqueue去生成对应的fb
|
||||
struct scale3_normal_cmd_s *cmd = STREAM_MALLOC(sizeof(struct scale3_normal_cmd_s));
|
||||
if (cmd)
|
||||
{
|
||||
memcpy(cmd, (void *) param2, sizeof(struct scale3_normal_cmd_s));
|
||||
RB_SET(&scale3->extern_rb, cmd);
|
||||
os_run_work(&scale3->work);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int32_t scale3_stream_done(uint32 irq_flag, uint32 irq_data, uint32 param1)
|
||||
{
|
||||
struct scale3_normal_msi *scale3 = (struct scale3_normal_msi *) irq_data;
|
||||
struct framebuff *fb;
|
||||
struct takephoto_yuv_arg_s *arg;
|
||||
uint8_t *p_buf;
|
||||
uint32_t ow = 0, oh = 0;
|
||||
// 如果是需要额外抽一帧生成特定size的yuv
|
||||
if (scale3->extern_fb)
|
||||
{
|
||||
arg = scale3->extern_fb->priv;
|
||||
ow = arg->yuv_arg.out_w;
|
||||
oh = arg->yuv_arg.out_h;
|
||||
p_buf = (uint8_t *) scale3->extern_fb->data;
|
||||
fb = scale3->extern_fb;
|
||||
scale3->extern_fb = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (scale3->start)
|
||||
{
|
||||
ow = scale3->ow;
|
||||
oh = scale3->oh;
|
||||
fb = fbpool_get(&scale3->pool, 0, scale3->msi);
|
||||
}
|
||||
else
|
||||
{
|
||||
fb = NULL;
|
||||
}
|
||||
|
||||
// 空间不够,则使用原来的空间
|
||||
if (!fb)
|
||||
{
|
||||
scale_close(scale3->scale_dev);
|
||||
goto scale3_stream_done_end;
|
||||
}
|
||||
|
||||
// 配置新的空间地址
|
||||
p_buf = (uint8_t *) fb->data;
|
||||
}
|
||||
|
||||
scale_set_in_out_size(scale3->scale_dev, scale3->iw, scale3->ih, ow, oh);
|
||||
scale_set_step(scale3->scale_dev, scale3->iw, scale3->ih, ow, oh);
|
||||
scale_set_out_yaddr(scale3->scale_dev, (uint32) p_buf);
|
||||
scale_set_out_uaddr(scale3->scale_dev, (uint32) p_buf + ow * oh);
|
||||
scale_set_out_vaddr(scale3->scale_dev, (uint32) p_buf + ow * oh + ow * oh / 4);
|
||||
scale3_stream_done_end:
|
||||
// 发送now_data,发送失败也要返回
|
||||
if (os_msgq_put(&scale3->msgq, (uint32_t) scale3->fb, 0))
|
||||
{
|
||||
// 正常不能中断del,但是这个模块是内部,只要del没有一些等待信号量操作,问题不大
|
||||
msi_delete_fb(NULL, scale3->fb);
|
||||
scale3->fb = NULL;
|
||||
// return 0;
|
||||
}
|
||||
if (!fb)
|
||||
{
|
||||
scale3->ready = 1;
|
||||
}
|
||||
scale3->fb = fb;
|
||||
os_run_work(&scale3->work);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t scale3_stream_ov(uint32 irq_flag, uint32 irq_data, uint32 param1)
|
||||
{
|
||||
os_printf("%s:%d\n", __FUNCTION__, __LINE__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 如果空间申请不到,就延时去输出
|
||||
static int32 scale3_normal_msi_work(struct os_work *work)
|
||||
{
|
||||
struct scale3_normal_msi *scale3 = (struct scale3_normal_msi *) work;
|
||||
struct scale_device *scale_dev = scale3->scale_dev;
|
||||
uint8_t delay_time = 0;
|
||||
struct framebuff *fb = NULL;
|
||||
struct framebuff *e_fb = NULL;
|
||||
struct takephoto_yuv_arg_s *arg = NULL;
|
||||
uint16_t ow = 0;
|
||||
uint16_t oh = 0;
|
||||
uint32_t magic = 0;
|
||||
int32_t err = -1;
|
||||
// 先去检查是否有需要生成额外的yuv数据没
|
||||
// 检查如果没有extern_fb,并且有额外命令,则生成一个fb
|
||||
if (scale3->extern_fb_ready && !scale3->extern_fb)
|
||||
{
|
||||
if (!scale3->normal_cmd)
|
||||
{
|
||||
RB_GET(&scale3->extern_rb, scale3->normal_cmd);
|
||||
}
|
||||
|
||||
if (scale3->normal_cmd)
|
||||
{
|
||||
if (scale3->normal_cmd->w && scale3->normal_cmd->h)
|
||||
{
|
||||
ow = scale3->normal_cmd->w;
|
||||
oh = scale3->normal_cmd->h;
|
||||
}
|
||||
else
|
||||
{
|
||||
ow = scale3->iw;
|
||||
oh = scale3->ih;
|
||||
}
|
||||
|
||||
uint8_t *data = STREAM_MALLOC(ow * oh * 3 / 2);
|
||||
if (data)
|
||||
{
|
||||
|
||||
arg = (struct takephoto_yuv_arg_s *) STREAM_LIBC_ZALLOC(sizeof(struct takephoto_yuv_arg_s));
|
||||
e_fb = fb_alloc(data, ow * oh * 3 / 2, F_YUV << 8 | FSTYPE_NONE, scale3->msi);
|
||||
// 如果w和h其中一个为0,则使用iw和ih
|
||||
|
||||
e_fb->datatag = ~0; // 设置特殊标志,用于识别是否是额外生成的fb
|
||||
e_fb->priv = arg;
|
||||
arg->yuv_arg.y_size = ow * oh;
|
||||
arg->yuv_arg.y_off = 0;
|
||||
arg->yuv_arg.uv_off = 0;
|
||||
arg->yuv_arg.out_w = ow;
|
||||
arg->yuv_arg.out_h = oh;
|
||||
arg->yuv_arg.magic = scale3->normal_cmd->magic;
|
||||
arg->yuv_arg.type = scale3->normal_cmd->force_type;
|
||||
|
||||
takephoto_name_no_dir_time(arg->name, sizeof(arg->name), &scale3->normal_cmd->t);
|
||||
scale3->extern_fb_ready = 0;
|
||||
scale3->extern_fb = e_fb;
|
||||
|
||||
sys_dcache_invalid_range((uint32_t *) data, ow * oh * 3 / 2);
|
||||
STREAM_FREE(scale3->normal_cmd);
|
||||
|
||||
scale3->normal_cmd = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fb = (struct framebuff *) os_msgq_get2(&scale3->msgq, 0, &err);
|
||||
if (fb)
|
||||
{
|
||||
if (fb->datatag != (uint8_t) ~0)
|
||||
{
|
||||
_os_printf(KERN_INFO "S");
|
||||
fb->mtype = F_YUV;
|
||||
fb->stype = scale3->force_stype;
|
||||
arg = fb->priv;
|
||||
ow = scale3->ow;
|
||||
oh = scale3->oh;
|
||||
arg->yuv_arg.y_size = ow * oh;
|
||||
arg->yuv_arg.y_off = 0;
|
||||
arg->yuv_arg.uv_off = 0;
|
||||
arg->yuv_arg.out_w = ow;
|
||||
arg->yuv_arg.out_h = oh;
|
||||
arg->yuv_arg.magic = magic;
|
||||
arg->yuv_arg.type = YUV_ARG_NONE;
|
||||
msi_output_fb(scale3->msi, fb);
|
||||
}
|
||||
else
|
||||
{
|
||||
msi_output_fb(scale3->msi, fb);
|
||||
}
|
||||
|
||||
fb = NULL;
|
||||
}
|
||||
|
||||
// scale3可能空间不够关闭了中断,也可能是第一次启动
|
||||
if (scale3->ready)
|
||||
{
|
||||
|
||||
if (scale3->extern_fb)
|
||||
{
|
||||
arg = scale3->extern_fb->priv;
|
||||
ow = arg->yuv_arg.out_w;
|
||||
oh = arg->yuv_arg.out_h;
|
||||
scale3->fb = scale3->extern_fb;
|
||||
scale3->extern_fb = NULL;
|
||||
fb = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (scale3->start)
|
||||
{
|
||||
fb = fbpool_get(&scale3->pool, F_YUV << 8 | FSTYPE_YUV_P0, scale3->msi);
|
||||
if (fb)
|
||||
{
|
||||
ow = scale3->ow;
|
||||
oh = scale3->oh;
|
||||
scale3->fb = fb;
|
||||
fb = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!scale3->fb)
|
||||
{
|
||||
_os_printf(KERN_INFO "D");
|
||||
delay_time = 0;
|
||||
goto scale3_normal_msi_work_end;
|
||||
}
|
||||
|
||||
// 暂时用同样的iw ih ow oh
|
||||
scale_set_in_out_size(scale_dev, scale3->iw, scale3->ih, ow, oh);
|
||||
scale_set_step(scale_dev, scale3->iw, scale3->ih, ow, oh);
|
||||
scale_set_start_addr(scale_dev, 0, 0);
|
||||
// 暂时固定,如果遇到需要动态修改的,可以通过参数之类来切换
|
||||
scale_set_dma_to_memory(scale_dev, 1);
|
||||
scale_set_data_from_vpp(scale_dev, 1);
|
||||
scale_set_line_buf_num(scale_dev, yuv_buf_line(0));
|
||||
scale_set_in_yaddr(scale_dev, (uint32) get_vpp_buf(0));
|
||||
scale_set_in_uaddr(scale_dev, (uint32) get_vpp_buf(0) + scale3->iw * yuv_buf_line(0));
|
||||
scale_set_in_vaddr(scale_dev, (uint32) get_vpp_buf(0) + scale3->iw * yuv_buf_line(0) + scale3->iw * yuv_buf_line(0) / 4);
|
||||
|
||||
scale_set_out_yaddr(scale_dev, (uint32) scale3->fb->data);
|
||||
scale_set_out_uaddr(scale_dev, (uint32) scale3->fb->data + ow * oh);
|
||||
scale_set_out_vaddr(scale_dev, (uint32) scale3->fb->data + ow * oh + ow * oh / 4);
|
||||
scale_request_irq(scale_dev, FRAME_END, scale3_stream_done, (uint32) scale3);
|
||||
scale_request_irq(scale_dev, INBUF_OV, scale3_stream_ov, (uint32) scale3);
|
||||
scale3->ready = 0;
|
||||
scale_open(scale_dev);
|
||||
}
|
||||
|
||||
scale3_normal_msi_work_end:
|
||||
if (delay_time)
|
||||
{
|
||||
os_run_work_delay(work, delay_time);
|
||||
}
|
||||
|
||||
if (fb)
|
||||
{
|
||||
msi_delete_fb(NULL, fb);
|
||||
fb = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct msi *scale3_normal_msi(const char *name, uint16_t ow, uint16_t oh)
|
||||
{
|
||||
uint8_t isnew;
|
||||
struct msi *msi = msi_new(name, 0, &isnew);
|
||||
if (isnew)
|
||||
{
|
||||
struct scale_device *scale_dev = (struct scale_device *) dev_get(HG_SCALE3_DEVID);
|
||||
struct scale3_normal_msi *scale3 = (struct scale3_normal_msi *) STREAM_LIBC_ZALLOC(sizeof(struct scale3_normal_msi));
|
||||
scale3->scale_dev = scale_dev;
|
||||
scale3->ready = 1;
|
||||
scale3->ow = ow;
|
||||
scale3->oh = oh;
|
||||
scale3->msi = msi;
|
||||
scale3->force_stype = FSTYPE_NONE;
|
||||
scale3->extern_fb_ready = 1;
|
||||
scale3->start = 1;
|
||||
msi->priv = (void *) scale3;
|
||||
msi->action = const_scale3_msi_action;
|
||||
msi->enable = 1;
|
||||
os_msgq_init(&scale3->msgq, MAX_COUNT);
|
||||
fbpool_init(&scale3->pool, MAX_COUNT);
|
||||
|
||||
uint16_t init_count = 0;
|
||||
uint8_t *m_buff;
|
||||
struct takephoto_yuv_arg_s *arg;
|
||||
// 初始化framebuffer节点数量空间?最后由workqueue去从ringbuf去获取一个节点
|
||||
while (init_count < MAX_COUNT)
|
||||
{
|
||||
m_buff = STREAM_MALLOC(ow * oh * 3 / 2);
|
||||
arg = (struct takephoto_yuv_arg_s *) STREAM_LIBC_ZALLOC(sizeof(struct takephoto_yuv_arg_s));
|
||||
ASSERT(m_buff);
|
||||
ASSERT(arg);
|
||||
sys_dcache_invalid_range((uint32_t *) m_buff, ow * oh * 3 / 2);
|
||||
FBPOOL_SET_INFO(&scale3->pool, init_count, m_buff, ow * oh * 3 / 2, arg);
|
||||
init_count++;
|
||||
}
|
||||
get_vpp_w_h(&scale3->iw, &scale3->ih);
|
||||
OS_WORK_INIT(&scale3->work, scale3_normal_msi_work, 0);
|
||||
os_run_work(&scale3->work);
|
||||
}
|
||||
return msi;
|
||||
}
|
||||
|
||||
struct msi *scale3_normal_msi2(const char *name, uint8_t force_stype, uint16_t ow, uint16_t oh)
|
||||
{
|
||||
uint8_t isnew;
|
||||
struct msi *msi = msi_new(name, 0, &isnew);
|
||||
if (isnew)
|
||||
{
|
||||
struct scale_device *scale_dev = (struct scale_device *) dev_get(HG_SCALE3_DEVID);
|
||||
struct scale3_normal_msi *scale3 = (struct scale3_normal_msi *) STREAM_ZALLOC(sizeof(struct scale3_normal_msi));
|
||||
scale3->scale_dev = scale_dev;
|
||||
scale3->ready = 1;
|
||||
scale3->ow = ow;
|
||||
scale3->oh = oh;
|
||||
scale3->msi = msi;
|
||||
scale3->force_stype = force_stype;
|
||||
scale3->extern_fb_ready = 1;
|
||||
scale3->start = 0;
|
||||
msi->priv = (void *) scale3;
|
||||
msi->action = const_scale3_msi_action;
|
||||
msi->enable = 1;
|
||||
os_msgq_init(&scale3->msgq, MAX_COUNT);
|
||||
fbpool_init(&scale3->pool, MAX_COUNT);
|
||||
RB_INIT(&scale3->extern_rb, EXTERN_RB_COUNT);
|
||||
|
||||
uint16_t init_count = 0;
|
||||
uint8_t *m_buff;
|
||||
struct takephoto_yuv_arg_s *arg;
|
||||
// 初始化framebuffer节点数量空间?最后由workqueue去从ringbuf去获取一个节点
|
||||
while (init_count < MAX_COUNT)
|
||||
{
|
||||
m_buff = STREAM_MALLOC(ow * oh * 3 / 2);
|
||||
arg = (struct takephoto_yuv_arg_s *) STREAM_LIBC_ZALLOC(sizeof(struct takephoto_yuv_arg_s));
|
||||
ASSERT(m_buff);
|
||||
ASSERT(arg);
|
||||
sys_dcache_invalid_range((uint32_t *) m_buff, ow * oh * 3 / 2);
|
||||
FBPOOL_SET_INFO(&scale3->pool, init_count, m_buff, ow * oh * 3 / 2, arg);
|
||||
init_count++;
|
||||
}
|
||||
get_vpp_w_h(&scale3->iw, &scale3->ih);
|
||||
OS_WORK_INIT(&scale3->work, scale3_normal_msi_work, 0);
|
||||
os_run_work(&scale3->work);
|
||||
}
|
||||
return msi;
|
||||
}
|
||||
14
sdk/app/scale_msi/scale3_normal_msi.h
Normal file
14
sdk/app/scale_msi/scale3_normal_msi.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef __SCALE3_NORMAL_MSI_H__
|
||||
#define __SCALE3_NORMAL_MSI_H__
|
||||
#include "basic_include.h"
|
||||
struct scale3_normal_cmd_s
|
||||
{
|
||||
uint32_t w;
|
||||
uint32_t h;
|
||||
uint32_t magic;
|
||||
uint32_t force_type;
|
||||
struct timeval t;
|
||||
};
|
||||
|
||||
struct msi *scale3_normal_msi2(const char *name, uint8_t force_stype, uint16_t ow, uint16_t oh);
|
||||
#endif
|
||||
102
sdk/app/scale_msi/scale_msi.h
Normal file
102
sdk/app/scale_msi/scale_msi.h
Normal file
@@ -0,0 +1,102 @@
|
||||
#ifndef __SCALE_MSI_H
|
||||
#define __SCALE_MSI_H
|
||||
|
||||
#include "stream_frame.h"
|
||||
#include "basic_include.h"
|
||||
|
||||
#include "lib/multimedia/msi.h"
|
||||
|
||||
#include "osal/work.h"
|
||||
#define MAX_SCALE3_TX 3
|
||||
|
||||
|
||||
struct scale_msg_t {
|
||||
uint16_t iw,ih;
|
||||
uint16_t ow,oh;
|
||||
uint16_t x,y;
|
||||
uint8_t video_only; //多屏显示层专用,用于只显示当前层画面
|
||||
};
|
||||
|
||||
struct scale2_msg_t {
|
||||
uint16_t stype;
|
||||
uint16_t iw,ih;
|
||||
uint16_t ow,oh;
|
||||
uint16_t x,y;
|
||||
uint8_t video_only; //多屏显示层专用,用于只显示当前层画面
|
||||
uint8_t larger;
|
||||
};
|
||||
|
||||
struct scale3_msi_s
|
||||
{
|
||||
struct os_work work;
|
||||
struct scale_device *scale_dev;
|
||||
struct msi *msi;
|
||||
uint16_t iw,ih,ow,oh;
|
||||
struct framebuff *now_fb;
|
||||
uint8_t *scaler3buf; //scale的buf
|
||||
struct os_msgqueue msgq;
|
||||
uint8_t del;
|
||||
uint8_t txpool_type;
|
||||
uint8_t init_txpool_num;
|
||||
struct fbpool tx_pool0;
|
||||
struct fbpool tx_pool1;
|
||||
struct fbpool tx_pool2;
|
||||
struct fbpool tx_poolerr; //用于抛开错误长度或者fb不存在时的抛帧
|
||||
};
|
||||
|
||||
struct const_scale3_msi_s
|
||||
{
|
||||
struct msi *msi;
|
||||
struct scale_device *scale_dev;
|
||||
uint8_t *buf;
|
||||
};
|
||||
#define MAX_SCALE2_TX 4
|
||||
struct scale2_msi_s
|
||||
{
|
||||
struct os_work work;
|
||||
struct scale_device *scale_dev;
|
||||
struct msi *msi;
|
||||
uint16_t iw,ih,ow,oh;
|
||||
|
||||
uint16_t stw,sth,x,y; //step w和h,显示的video层位置
|
||||
uint16_t sx,sy; //模块scaler的图像操作启始位置,
|
||||
struct framebuff *now_fb;
|
||||
struct framebuff *now_fb_msg[MAX_SCALE2_TX]; //预分配的槽位数组,用于存放now_fb的指针(放入msgq的是槽的地址),以便循环复用
|
||||
uint8_t now_fb_msg_idx;
|
||||
uint8_t *scaler2buf; //scale的buf
|
||||
struct os_msgqueue msgq;
|
||||
uint8_t larger;
|
||||
uint8_t del;
|
||||
uint8_t seq;
|
||||
uint16_t type;
|
||||
//RBUFFER_DEF(tx_data, struct framebuff *, MAX_SCALE3_TX);
|
||||
struct fbpool tx_pool;
|
||||
int mutex_count;
|
||||
uint32_t filter_type;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct scale1_msi_s
|
||||
{
|
||||
struct os_work work;
|
||||
struct scale_device *scale_dev;
|
||||
struct dma_device *dma1;
|
||||
uint16_t iw,ih,ow,oh;
|
||||
struct msi *msi;
|
||||
uint8_t *scaler1buf; //scale的buf
|
||||
uint8_t dma1_lock;
|
||||
};
|
||||
|
||||
typedef int32_t (*scale3_done_fn)(uint32 irq_data);
|
||||
|
||||
struct msi *scale2_msi(const char *name, uint16_t iw, uint16_t ih, uint16_t ow, uint16_t oh, uint16_t type,uint8_t larger);
|
||||
void scale2_output_size_local_change(uint8_t id,uint8_t show_only,uint16 x,uint16 y,uint16 w,uint16 h);
|
||||
void scale2_output_larger_local_change(uint8_t id, uint8_t larger);
|
||||
struct msi *scale3_msi(const char *name);
|
||||
struct msi *scale3_msi_const_buf(const char *name, uint8_t *buf,uint16_t iw, uint16_t ih, uint16_t ow, uint16_t oh);
|
||||
void scale3_output_size_local_change(uint8_t id,uint8_t show_only,uint16 x,uint16 y,uint16 w,uint16 h);
|
||||
int scale2_cfg_run(uint8_t streamfrom,uint8_t id);
|
||||
void scale2_recfg_input_size(uint16_t w,uint16_t h,uint8_t id);
|
||||
|
||||
#endif
|
||||
340
sdk/app/scale_msi/takephoto_scale3_msi.c
Normal file
340
sdk/app/scale_msi/takephoto_scale3_msi.c
Normal file
@@ -0,0 +1,340 @@
|
||||
|
||||
#include "scale_msi.h"
|
||||
#include "dev/vpp/hgvpp.h"
|
||||
#include "lib/video/vpp/vpp_dev.h"
|
||||
#include "dev/scale/hgscale.h"
|
||||
#include "lib/heap/av_heap.h"
|
||||
#include "lib/heap/av_psram_heap.h"
|
||||
#include "user_work/user_work.h"
|
||||
#include "video_app/file_common_api.h"
|
||||
|
||||
uint32_t yuv_buf_line(uint8_t which);
|
||||
|
||||
/*********************************************************************
|
||||
* 这个模块是分别输出两种图片的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
|
||||
|
||||
uint8_t *test_buf = NULL;
|
||||
|
||||
#define THUMB_W 320
|
||||
#define THUMB_H 180
|
||||
|
||||
struct takephoto_scale3_msi_s
|
||||
{
|
||||
struct os_work work;
|
||||
struct msi *msi;
|
||||
struct scale_device *scale_dev;
|
||||
uint8_t *buf;
|
||||
uint32_t buf_max_size;
|
||||
uint32_t kick_times;
|
||||
uint16_t iw, ih;
|
||||
struct framebuff *fb;
|
||||
uint32_t thumb_magic;
|
||||
uint32_t normal_magic;
|
||||
char filename[64];
|
||||
uint8_t ready : 1, start : 1, only_one_buf : 1, rev : 5;
|
||||
};
|
||||
|
||||
void *get_vpp_buf(uint8_t which);
|
||||
uint8_t get_vpp_w_h(uint16_t *w, uint16_t *h);
|
||||
|
||||
static int32_t const_scale3_msi_action(struct msi *msi, uint32_t cmd_id, uint32_t param1, uint32_t param2)
|
||||
{
|
||||
int32_t ret = RET_OK;
|
||||
struct takephoto_scale3_msi_s *scale3 = (struct takephoto_scale3_msi_s *) msi->priv;
|
||||
switch (cmd_id)
|
||||
{
|
||||
|
||||
// 这里msi已经被删除,那么就要考虑tx_pool的资源释放了
|
||||
// 能进来这里,就是代表所有fb都已经用完了
|
||||
case MSI_CMD_POST_DESTROY:
|
||||
{
|
||||
if (scale3->only_one_buf && scale3->buf)
|
||||
{
|
||||
STREAM_FREE(scale3->buf);
|
||||
}
|
||||
STREAM_LIBC_FREE(scale3);
|
||||
}
|
||||
break;
|
||||
|
||||
// 停止硬件,移除没有必要的资源(但是fb的资源不能现在删除,这个时候fb可能外部还在调用)
|
||||
case MSI_CMD_PRE_DESTROY:
|
||||
{
|
||||
}
|
||||
break;
|
||||
case MSI_CMD_FREE_FB:
|
||||
{
|
||||
struct framebuff *fb = (struct framebuff *) param1;
|
||||
if (fb->data)
|
||||
{
|
||||
if (scale3->only_one_buf)
|
||||
{
|
||||
scale3->start = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
STREAM_FREE(fb->data);
|
||||
}
|
||||
}
|
||||
if (fb->priv)
|
||||
{
|
||||
STREAM_LIBC_FREE(fb->priv);
|
||||
}
|
||||
os_run_work(&scale3->work);
|
||||
}
|
||||
break;
|
||||
|
||||
case MSI_CMD_TAKEPHOTO_SCALE3:
|
||||
{
|
||||
uint32_t cmd_self = (uint32_t) param1;
|
||||
uint32_t arg = param2;
|
||||
switch (cmd_self)
|
||||
{
|
||||
case MSI_TAKEPHOTO_SCALE3_KICK:
|
||||
{
|
||||
if (scale3->thumb_magic)
|
||||
{
|
||||
scale3->kick_times += (arg * 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
scale3->kick_times += (arg);
|
||||
}
|
||||
|
||||
os_run_work(&scale3->work);
|
||||
break;
|
||||
}
|
||||
case MSI_TAKEPHOTO_SCALE3_STOP:
|
||||
{
|
||||
os_work_cancle2(&scale3->work, 1);
|
||||
scale3->kick_times = 0;
|
||||
os_run_work(&scale3->work);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int32_t takephoto_scale3_stream_done(uint32 irq_flag, uint32 irq_data, uint32 param1)
|
||||
{
|
||||
struct takephoto_scale3_msi_s *scale3 = (struct takephoto_scale3_msi_s *) irq_data;
|
||||
_os_printf("CO");
|
||||
scale_close(scale3->scale_dev);
|
||||
os_run_work(&scale3->work);
|
||||
scale3->ready = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t scale3_stream_ov(uint32 irq_flag, uint32 irq_data, uint32 param1)
|
||||
{
|
||||
os_printf("%s:%d\n", __FUNCTION__, __LINE__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 如果空间申请不到,就延时去输出
|
||||
static int32 takephoto_scale3_msi_work(struct os_work *work)
|
||||
{
|
||||
struct takephoto_scale3_msi_s *scale3 = (struct takephoto_scale3_msi_s *) work;
|
||||
struct scale_device *scale_dev = scale3->scale_dev;
|
||||
uint8_t delay_time = 0;
|
||||
uint8_t *buf = NULL;
|
||||
struct framebuff *fb = NULL;
|
||||
struct takephoto_yuv_arg_s *arg = NULL;
|
||||
uint32_t yuvsize;
|
||||
uint16_t ow, oh;
|
||||
uint32_t magic;
|
||||
if (scale3->ready)
|
||||
{
|
||||
if (scale3->fb)
|
||||
{
|
||||
// 还需要配置一些默认私有结构体参数
|
||||
msi_output_fb(scale3->msi, scale3->fb);
|
||||
scale3->fb = NULL;
|
||||
}
|
||||
if (!scale3->start)
|
||||
{
|
||||
goto takephoto_scale3_msi_work_end;
|
||||
}
|
||||
if (scale3->kick_times)
|
||||
{
|
||||
// os_printf("scale3->kick_times:%d\n", scale3->kick_times);
|
||||
// 原图?
|
||||
if (!scale3->thumb_magic || scale3->kick_times % 2 == 0)
|
||||
{
|
||||
ow = scale3->iw;
|
||||
oh = scale3->ih;
|
||||
magic = scale3->normal_magic;
|
||||
takephoto_name_no_dir(scale3->filename, sizeof(scale3->filename));
|
||||
}
|
||||
// 缩略图
|
||||
else
|
||||
{
|
||||
ow = THUMB_W;
|
||||
oh = THUMB_H;
|
||||
magic = scale3->thumb_magic;
|
||||
}
|
||||
yuvsize = ow * oh * 3 / 2;
|
||||
if (scale3->only_one_buf)
|
||||
{
|
||||
if (yuvsize > scale3->buf_max_size)
|
||||
{
|
||||
STREAM_FREE(scale3->buf);
|
||||
scale3->buf = STREAM_MALLOC(yuvsize);
|
||||
if (scale3->buf)
|
||||
{
|
||||
sys_dcache_clean_invalid_range((uint32_t *) scale3->buf, yuvsize);
|
||||
scale3->buf_max_size = yuvsize;
|
||||
}
|
||||
else
|
||||
{
|
||||
scale3->buf_max_size = 0;
|
||||
}
|
||||
}
|
||||
buf = scale3->buf;
|
||||
}
|
||||
else
|
||||
{
|
||||
buf = STREAM_MALLOC(yuvsize);
|
||||
if (buf)
|
||||
{
|
||||
sys_dcache_clean_invalid_range((uint32_t *) buf, yuvsize);
|
||||
}
|
||||
}
|
||||
|
||||
if (buf)
|
||||
{
|
||||
arg = STREAM_LIBC_ZALLOC(sizeof(struct takephoto_yuv_arg_s));
|
||||
if (!arg)
|
||||
{
|
||||
delay_time = 5;
|
||||
goto takephoto_scale3_msi_work_end;
|
||||
}
|
||||
fb = fb_alloc(buf, yuvsize, F_YUV << 8 | FSTYPE_YUV_TAKEPHOTO, scale3->msi);
|
||||
|
||||
if (!fb)
|
||||
{
|
||||
delay_time = 5;
|
||||
goto takephoto_scale3_msi_work_end;
|
||||
}
|
||||
fb->priv = (void *) arg;
|
||||
scale3->fb = fb;
|
||||
|
||||
arg->yuv_arg.y_size = ow * oh;
|
||||
arg->yuv_arg.y_off = 0;
|
||||
arg->yuv_arg.uv_off = 0;
|
||||
arg->yuv_arg.out_w = ow;
|
||||
arg->yuv_arg.out_h = oh;
|
||||
arg->yuv_arg.magic = magic;
|
||||
arg->yuv_arg.type = YUV_ARG_TAKEPHOTO;
|
||||
os_memcpy(arg->name, scale3->filename, os_strlen(scale3->filename) + 1);
|
||||
arg = NULL;
|
||||
buf = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
delay_time = 5;
|
||||
goto takephoto_scale3_msi_work_end;
|
||||
}
|
||||
// 暂时用同样的iw ih ow oh
|
||||
scale_set_in_out_size(scale_dev, scale3->iw, scale3->ih, ow, oh);
|
||||
scale_set_step(scale_dev, scale3->iw, scale3->ih, ow, oh);
|
||||
scale_set_start_addr(scale_dev, 0, 0);
|
||||
// 暂时固定,如果遇到需要动态修改的,可以通过参数之类来切换
|
||||
scale_set_dma_to_memory(scale_dev, 1);
|
||||
scale_set_data_from_vpp(scale_dev, 1);
|
||||
scale_set_line_buf_num(scale_dev, yuv_buf_line(0));
|
||||
scale_set_in_yaddr(scale_dev, (uint32) get_vpp_buf(0));
|
||||
scale_set_in_uaddr(scale_dev, (uint32) get_vpp_buf(0) + scale3->iw * yuv_buf_line(0));
|
||||
scale_set_in_vaddr(scale_dev, (uint32) get_vpp_buf(0) + scale3->iw * yuv_buf_line(0) + scale3->iw * yuv_buf_line(0) / 4);
|
||||
|
||||
scale_set_out_yaddr(scale_dev, (uint32) fb->data);
|
||||
scale_set_out_uaddr(scale_dev, (uint32) fb->data + ow * oh);
|
||||
scale_set_out_vaddr(scale_dev, (uint32) fb->data + ow * oh + ow * oh / 4);
|
||||
scale_request_irq(scale_dev, FRAME_END, takephoto_scale3_stream_done, (uint32) scale3);
|
||||
scale_request_irq(scale_dev, INBUF_OV, scale3_stream_ov, (uint32) scale3);
|
||||
scale3->ready = 0;
|
||||
if (scale3->only_one_buf)
|
||||
{
|
||||
scale3->start = 0;
|
||||
}
|
||||
|
||||
scale_open(scale_dev);
|
||||
|
||||
scale3->kick_times--;
|
||||
}
|
||||
// scale3的拍照模式完成,释放空间
|
||||
else
|
||||
{
|
||||
if (scale3->buf)
|
||||
{
|
||||
STREAM_FREE(scale3->buf);
|
||||
scale3->buf = NULL;
|
||||
scale3->buf_max_size = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
takephoto_scale3_msi_work_end:
|
||||
if (delay_time)
|
||||
{
|
||||
os_run_work_delay(work, delay_time);
|
||||
}
|
||||
|
||||
if (buf)
|
||||
{
|
||||
STREAM_FREE(buf);
|
||||
buf = NULL;
|
||||
}
|
||||
|
||||
if (arg)
|
||||
{
|
||||
STREAM_LIBC_FREE(arg);
|
||||
arg = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct msi *scale3_msi_pic_thumb(const char *name, uint8_t only,uint32_t normal_magic, uint32_t thumb_magic)
|
||||
{
|
||||
uint8_t isnew;
|
||||
struct msi *msi = msi_new(name, 0, &isnew);
|
||||
if (isnew)
|
||||
{
|
||||
struct scale_device *scale_dev = (struct scale_device *) dev_get(HG_SCALE3_DEVID);
|
||||
struct takephoto_scale3_msi_s *scale3 = (struct takephoto_scale3_msi_s *) STREAM_LIBC_ZALLOC(sizeof(struct takephoto_scale3_msi_s));
|
||||
scale3->scale_dev = scale_dev;
|
||||
scale3->ready = 1;
|
||||
scale3->msi = msi;
|
||||
msi->priv = (void *) scale3;
|
||||
msi->action = const_scale3_msi_action;
|
||||
scale3->kick_times = 0;
|
||||
scale3->normal_magic = normal_magic;
|
||||
scale3->thumb_magic = thumb_magic;
|
||||
scale3->start = 1;
|
||||
scale3->only_one_buf = only;
|
||||
msi->enable = 1;
|
||||
get_vpp_w_h(&scale3->iw, &scale3->ih);
|
||||
OS_WORK_INIT(&scale3->work, takephoto_scale3_msi_work, 0);
|
||||
}
|
||||
return msi;
|
||||
}
|
||||
Reference in New Issue
Block a user