Initial commit: TXW82x FPV v2.7.0.7-42229 SDK + project sources
This commit is contained in:
822
sdk/app/decode/h264_decode_msi.c
Normal file
822
sdk/app/decode/h264_decode_msi.c
Normal file
@@ -0,0 +1,822 @@
|
||||
#include "basic_include.h"
|
||||
#include "dev.h"
|
||||
#include "dev/jpg/hgjpg.h"
|
||||
#include "dev/scale/hgscale.h"
|
||||
#include "devid.h"
|
||||
#include "lib/lcd/lcd.h"
|
||||
#include "osal/work.h"
|
||||
#include "stream_frame.h"
|
||||
#include "sys_config.h"
|
||||
#include "typesdef.h"
|
||||
#include "utlist.h"
|
||||
|
||||
#include "basic_include.h"
|
||||
#include "lib/heap/av_heap.h"
|
||||
#include "lib/heap/av_psram_heap.h"
|
||||
#include "lib/multimedia/msi.h"
|
||||
#include "lib/video/dvp/jpeg/jpg_common.h"
|
||||
#include "osal/event.h"
|
||||
#include "user_work/user_work.h"
|
||||
#include "lib/video/h264/h264_drv.h"
|
||||
#include "dev/h264/hg264.h"
|
||||
#include "lib/scale/scale_common.h"
|
||||
#include "scale/scale_dev.h"
|
||||
|
||||
#ifndef DECODE_MAX_W
|
||||
#define DECODE_MAX_W (320)
|
||||
#endif
|
||||
|
||||
#ifndef DECODE_MAX_H
|
||||
#define DECODE_MAX_H (180)
|
||||
#endif
|
||||
#define DECODE_MAX_SIZE (DECODE_MAX_W * DECODE_MAX_H * 3 / 2)
|
||||
|
||||
#define H264_ROM_MIN_SIZE (100 * 1024 + 4096)
|
||||
|
||||
extern void scale2_from_jpeg_config_for_msi(struct scale_device *scale_dev, uint32_t yinsram, uint32_t uinsram, uint32_t vinsram, uint32_t yuvoutbuf, uint32 in_w, uint32 in_h, uint32 out_w,
|
||||
uint32 out_h, uint8_t larger);
|
||||
// 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
|
||||
|
||||
#define MAX_DECODE_NUM (8)
|
||||
|
||||
#ifndef MAX_DECODE_YUV_TX
|
||||
#define MAX_DECODE_YUV_TX (1)
|
||||
#endif
|
||||
|
||||
struct h264_msi_s
|
||||
{
|
||||
struct os_work work;
|
||||
struct msi *msi;
|
||||
struct fbpool tx_pool;
|
||||
uint8_t *scaler2buf_y;
|
||||
uint8_t *scaler2buf_u;
|
||||
uint8_t *scaler2buf_v;
|
||||
struct h264_device *h264_dev;
|
||||
struct scale_device *scale_dev;
|
||||
uint32_t last_decode_time; // 记录上一次解码的时间,预防有异常的时候可以计算超时
|
||||
uint32_t dec_y_offset;
|
||||
uint32_t dec_uv_offset;
|
||||
uint16_t now_decode_pw;
|
||||
uint16_t scale_p1_w;
|
||||
uint16_t p1_w;
|
||||
uint16_t p1_h;
|
||||
struct framebuff *parent_fb;
|
||||
struct framebuff *current_fb;
|
||||
uint32_t max_data_size;
|
||||
|
||||
struct str_info h264_str;
|
||||
struct h264_header h264_head;
|
||||
struct h264_cfg_t dec_cfg;
|
||||
struct h264_ctl_t dec_ctl;
|
||||
|
||||
uint32_t rom_max_size;
|
||||
uint8_t *rom;
|
||||
uint8_t *ref_mem;
|
||||
uint32_t ref_max_size;
|
||||
|
||||
uint16_t w, h;
|
||||
// 硬件模块是否准备好
|
||||
// 是否自动释放空间(可能会导致碎片化严重,但是可以充分利用空间)
|
||||
uint8_t hardware_ready : 1, auto_free_space : 1, hardware_err : 1, is_register_isr : 1, sps_flag : 1, only_I_H264 : 1, unlock : 1, rev : 1;
|
||||
};
|
||||
|
||||
static void stream_jpg_decode_scale2_done(uint32 irq_flag, uint32 irq_data, uint32 param1)
|
||||
{
|
||||
}
|
||||
|
||||
static void stream_jpg_decode_scale2_ov_isr(uint32 irq_flag, uint32 irq_data, uint32 param1)
|
||||
{
|
||||
// struct scale_device *scale_dev = (struct scale_device *)irq_data;
|
||||
}
|
||||
|
||||
static int32_t h264_dec_done(uint32 irq_flags, uint32 irq_data, uint32 param)
|
||||
{
|
||||
struct h264_msi_s *decode = (struct h264_msi_s *) irq_data;
|
||||
decode->hardware_ready = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32 h264_decode_work(struct os_work *work)
|
||||
{
|
||||
int ret;
|
||||
uint8_t unlock = 0;
|
||||
struct h264_msi_s *decode = (struct h264_msi_s *) work;
|
||||
struct framebuff *fb;
|
||||
// static int count = 0;
|
||||
// 检测解码模块是否完成或者超时代表解码失败
|
||||
// 能进去,模块需要reset或者已经解码完毕,可以重新去解码,否则只能慢慢等超时或者硬件解码完成
|
||||
if (decode->hardware_err || decode->hardware_ready || os_jiffies() - decode->last_decode_time > 1000)
|
||||
{
|
||||
if (decode->current_fb && (os_jiffies() - decode->last_decode_time > 1000))
|
||||
{
|
||||
// 解码可能失败了
|
||||
os_printf(KERN_ERR "decode failed1:%d\n", decode->hardware_ready);
|
||||
os_printf(KERN_ERR "decode->hardware_err:%d\n", decode->hardware_err);
|
||||
|
||||
decode->sps_flag = 0;
|
||||
decode->hardware_ready = 1;
|
||||
// 无论是完成还是失败,都要释放这张图片了
|
||||
msi_delete_fb(NULL, decode->parent_fb);
|
||||
decode->parent_fb = NULL;
|
||||
|
||||
// 不再解码了
|
||||
msi_delete_fb(NULL, decode->current_fb);
|
||||
decode->current_fb = NULL;
|
||||
|
||||
// 这里最好将硬件模块停止
|
||||
// 解锁
|
||||
unlock = 1;
|
||||
}
|
||||
// 解码异常
|
||||
else if (decode->hardware_err)
|
||||
{
|
||||
h264_dec_intr_status(decode->h264_dev, &decode->dec_ctl);
|
||||
//-- clear the frm end flag
|
||||
h264_clr_intr(decode->h264_dev);
|
||||
h264_dec_flag_chk(decode->dec_ctl.enc_end_flags);
|
||||
_os_printf(KERN_ERR "decode failed2\n");
|
||||
decode->hardware_err = 0;
|
||||
decode->hardware_ready = 1;
|
||||
if (decode->current_fb)
|
||||
{
|
||||
// 无论是完成还是失败,都要释放这张图片了
|
||||
msi_delete_fb(NULL, decode->parent_fb);
|
||||
decode->parent_fb = NULL;
|
||||
|
||||
// 不再解码了
|
||||
msi_delete_fb(NULL, decode->current_fb);
|
||||
decode->current_fb = NULL;
|
||||
}
|
||||
|
||||
// 解锁
|
||||
unlock = 1;
|
||||
}
|
||||
// 解码完成,检查有解码完的数据需要发送
|
||||
else if (decode->current_fb)
|
||||
{
|
||||
h264_dec_intr_status(decode->h264_dev, &decode->dec_ctl);
|
||||
//-- clear the frm end flag
|
||||
h264_clr_intr(decode->h264_dev);
|
||||
h264_dec_flag_chk(decode->dec_ctl.enc_end_flags);
|
||||
// os_printf("%s:%d\tbuf:%X\n",__FUNCTION__,__LINE__,get_stream_real_data(decode->current_fb));
|
||||
fb = decode->current_fb;
|
||||
fb->time = decode->parent_fb->time;
|
||||
fb->mtype = F_YUV;
|
||||
fb->stype = decode->parent_fb->stype;
|
||||
fb->datatag = decode->parent_fb->datatag;
|
||||
fb->srcID = decode->parent_fb->srcID;
|
||||
_os_printf("&");
|
||||
|
||||
msi_output_fb(decode->msi, fb);
|
||||
// 无论是完成还是失败,都要释放这张图片了
|
||||
msi_delete_fb(NULL, decode->parent_fb);
|
||||
decode->parent_fb = NULL;
|
||||
decode->current_fb = NULL;
|
||||
decode->is_register_isr = 0;
|
||||
// 解锁
|
||||
unlock = 1;
|
||||
}
|
||||
// 硬件可用,但是current_fb不存在
|
||||
// 有两种可能
|
||||
// 一、没有需要解码的图片
|
||||
// 二、有需要解码的图片,但是fb没有申请成功或者内存空间不足以去解码图片数据
|
||||
else
|
||||
{
|
||||
}
|
||||
|
||||
if (unlock)
|
||||
{
|
||||
scale_mutex_unlock(2, SCALE_LOCK_H264_DECODE1);
|
||||
unlock = 0;
|
||||
decode->unlock = 0;
|
||||
}
|
||||
|
||||
// 这里没有解码的图片,尝试去看看有没有需要解码图片
|
||||
if (!decode->parent_fb)
|
||||
{
|
||||
// 接收图片,尝试看看是否要解码
|
||||
decode->parent_fb = msi_get_fb(decode->msi, 0);
|
||||
|
||||
// 需要解码,然后申请空间
|
||||
if (decode->parent_fb)
|
||||
{
|
||||
goto start_decode;
|
||||
}
|
||||
// 不需要解码
|
||||
else
|
||||
{
|
||||
// 为了腾出空间,释放空间
|
||||
if (decode->auto_free_space)
|
||||
{
|
||||
if (decode->scaler2buf_y)
|
||||
{
|
||||
STREAM_LIBC_FREE(decode->scaler2buf_y);
|
||||
decode->scaler2buf_y = NULL;
|
||||
}
|
||||
|
||||
if (decode->scaler2buf_u)
|
||||
{
|
||||
STREAM_LIBC_FREE(decode->scaler2buf_u);
|
||||
decode->scaler2buf_u = NULL;
|
||||
}
|
||||
|
||||
if (decode->scaler2buf_v)
|
||||
{
|
||||
STREAM_LIBC_FREE(decode->scaler2buf_v);
|
||||
decode->scaler2buf_v = NULL;
|
||||
}
|
||||
decode->now_decode_pw = 0;
|
||||
}
|
||||
goto not_decode;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
goto start_decode;
|
||||
}
|
||||
|
||||
// 开始尝试解码
|
||||
start_decode:
|
||||
// 检查是否需要解码(检查绑定msi的模块是否需要接收)
|
||||
{
|
||||
uint32_t send_count = msi_output_fb(decode->msi, NULL);
|
||||
// os_printf("send_count:%X\n",send_count);
|
||||
if (!send_count)
|
||||
{
|
||||
msi_delete_fb(NULL, decode->parent_fb);
|
||||
decode->parent_fb = NULL;
|
||||
goto not_decode;
|
||||
}
|
||||
}
|
||||
|
||||
struct framebuff *rfb = decode->parent_fb->next;
|
||||
struct fb_h264_s *h264_priv = (struct fb_h264_s *) rfb->priv;
|
||||
// w变化,就需要等待I帧
|
||||
if (decode->w != h264_priv->w || decode->h != h264_priv->h)
|
||||
{
|
||||
decode->sps_flag = 0;
|
||||
if (decode->ref_mem && (uint32_t) decode->ref_mem != 0x40000000)
|
||||
{
|
||||
uint32_t r_w = ((h264_priv->w + 15) >> 4) << 4;
|
||||
uint32_t r_h = ((h264_priv->h + 15) >> 4) << 4;
|
||||
uint32_t ref_max_size = (r_w * (r_h + 48)) + (r_w * (r_h + 48)) / 2 + 3 * 4096;
|
||||
if (decode->ref_max_size < ref_max_size)
|
||||
{
|
||||
STREAM_FREE(decode->ref_mem);
|
||||
decode->ref_mem = NULL;
|
||||
decode->ref_max_size = 0;
|
||||
decode->w = 0;
|
||||
decode->h = 0;
|
||||
}
|
||||
// 如果空间足够,修改frm_width与frm_height
|
||||
else
|
||||
{
|
||||
decode->w = h264_priv->w;
|
||||
decode->h = h264_priv->h;
|
||||
decode->dec_cfg.frm_width = r_w;
|
||||
decode->dec_cfg.frm_height = r_h;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 如果不是I帧,并且sps_flag没有解析过,就删除编码,等待到I帧
|
||||
if (h264_priv->type != 1 && !decode->sps_flag)
|
||||
{
|
||||
msi_delete_fb(NULL, decode->parent_fb);
|
||||
decode->parent_fb = NULL;
|
||||
os_printf("type:%d\n", h264_priv->type);
|
||||
os_printf("sps_flag:%d\n", decode->sps_flag);
|
||||
goto not_decode;
|
||||
}
|
||||
|
||||
// 如果空间不够,那么就重新申请空间
|
||||
if (decode->rom_max_size < rfb->len)
|
||||
{
|
||||
STREAM_FREE(decode->rom);
|
||||
decode->rom = NULL;
|
||||
decode->rom_max_size = 0;
|
||||
}
|
||||
if (!decode->rom)
|
||||
{
|
||||
uint32_t rom_max_size = rfb->len > H264_ROM_MIN_SIZE ? rfb->len : H264_ROM_MIN_SIZE;
|
||||
decode->rom = STREAM_MALLOC(rom_max_size + 4096);
|
||||
if (decode->rom)
|
||||
{
|
||||
decode->rom_max_size = rom_max_size;
|
||||
}
|
||||
}
|
||||
if (h264_priv->type == 1)
|
||||
{
|
||||
if (decode->only_I_H264)
|
||||
{
|
||||
uint32_t w = h264_priv->w;
|
||||
uint32_t h = h264_priv->h;
|
||||
uint32_t r_w = ((w + 15) >> 4) << 4;
|
||||
uint32_t r_h = ((h + 15) >> 4) << 4;
|
||||
|
||||
decode->dec_cfg.frm_width = r_w;
|
||||
decode->dec_cfg.frm_height = r_h;
|
||||
|
||||
decode->w = w;
|
||||
decode->h = h;
|
||||
|
||||
decode->ref_mem = (uint8_t *) 0x40000000;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!decode->ref_mem)
|
||||
{
|
||||
uint32_t w = h264_priv->w;
|
||||
uint32_t h = h264_priv->h;
|
||||
uint32_t r_w = ((w + 15) >> 4) << 4;
|
||||
uint32_t r_h = ((h + 15) >> 4) << 4;
|
||||
|
||||
decode->ref_mem = STREAM_MALLOC((r_w * (r_h + 48)) + (r_w * (r_h + 48)) / 2 + 3 * 4096);
|
||||
if (decode->ref_mem)
|
||||
{
|
||||
decode->ref_max_size = (r_w * (r_h + 48)) + (r_w * (r_h + 48)) / 2 + 3 * 4096;
|
||||
sys_dcache_clean_range((uint32_t *) decode->ref_mem, decode->ref_max_size);
|
||||
|
||||
decode->dec_cfg.frm_width = r_w;
|
||||
decode->dec_cfg.frm_height = r_h;
|
||||
|
||||
decode->w = w;
|
||||
decode->h = h;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 如果是P帧,如果是I帧only就不需要解码P帧
|
||||
else if (h264_priv->type == 2 && decode->only_I_H264)
|
||||
{
|
||||
msi_delete_fb(NULL, decode->parent_fb);
|
||||
decode->parent_fb = NULL;
|
||||
goto not_decode;
|
||||
}
|
||||
|
||||
if (!decode->only_I_H264 && !decode->ref_mem)
|
||||
{
|
||||
os_printf("malloc fail ref_mem:%X\n", decode->ref_mem);
|
||||
goto not_decode;
|
||||
}
|
||||
// 申请空间失败
|
||||
if (!decode->rom)
|
||||
{
|
||||
os_printf("malloc fail rom:%X\tref_mem:%X\n", decode->rom, decode->ref_mem);
|
||||
goto not_decode;
|
||||
}
|
||||
|
||||
if (decode->w != h264_priv->w || decode->h != h264_priv->h)
|
||||
{
|
||||
os_printf(KERN_ERR "h264_decode_msi: w[%d] or h[%d] not match dw[%d],dh[%d]\n", h264_priv->w, h264_priv->h, decode->w, decode->h);
|
||||
// 移除,不符合要求,不解码
|
||||
msi_delete_fb(NULL, decode->parent_fb);
|
||||
decode->parent_fb = NULL;
|
||||
goto not_decode;
|
||||
}
|
||||
// 获取锁
|
||||
ret = scale_mutex_lock(2, SCALE_LOCK_H264_DECODE1, NULL);
|
||||
if (ret)
|
||||
{
|
||||
goto not_decode;
|
||||
}
|
||||
decode->unlock = 1;
|
||||
// 申请到fb,申请解码空间
|
||||
fb = fbpool_get(&decode->tx_pool, 0, decode->msi);
|
||||
if (fb)
|
||||
{
|
||||
// 因为这个是解码的数据,所以默认parent_fb的data是一个参数内容,而不是真实的data,真实jpg的data应该是附在parent_fb后面其他节点
|
||||
struct jpg_decode_arg_s *msg = (struct jpg_decode_arg_s *) decode->parent_fb->data;
|
||||
// 没有找到,代表发送过来的不是jpg或者说对应参数没有配置,不解码
|
||||
if (msg)
|
||||
{
|
||||
// 为fb申请解码空间,申请不到下次申请
|
||||
fb->len = msg->yuv_arg.out_w * msg->yuv_arg.out_h * 3 / 2;
|
||||
if (fb->len <= decode->max_data_size)
|
||||
{
|
||||
struct jpg_decode_arg_s *cfg;
|
||||
cfg = (struct jpg_decode_arg_s *) fb->priv;
|
||||
memset(cfg, 0, sizeof(struct jpg_decode_arg_s));
|
||||
// 提前配置好data的长度
|
||||
memcpy(fb->priv, msg, sizeof(struct jpg_decode_arg_s));
|
||||
msi_do_cmd(decode->msi, MSI_CMD_DECODE, MSI_DECODE_SET_W_H, (uint32_t) fb);
|
||||
|
||||
// fb->type = SET_DATA_TYPE(YUV, GET_DATA_TYPE2(decode->parent_fb->type));
|
||||
|
||||
// msi_do_cmd(decode->msi, MSI_CMD_DECODE, MSI_DECODE_SET_STEP, (uint32_t) cfg);
|
||||
msi_do_cmd(decode->msi, MSI_CMD_DECODE, MSI_DECODE_READY, (uint32_t) fb);
|
||||
if (!decode->hardware_err)
|
||||
{
|
||||
msi_do_cmd(decode->msi, MSI_CMD_DECODE, MSI_DECOE_START, (uint32_t) decode->parent_fb);
|
||||
}
|
||||
|
||||
decode->current_fb = fb;
|
||||
decode->last_decode_time = os_jiffies();
|
||||
}
|
||||
else
|
||||
{
|
||||
os_printf(KERN_ERR "config err,max size w:%d\th:%d\tmax_mem:%d\n", DECODE_MAX_W, DECODE_MAX_H, decode->max_data_size);
|
||||
// 不符合,需要删除,不去解码
|
||||
msi_delete_fb(NULL, decode->parent_fb);
|
||||
decode->parent_fb = NULL;
|
||||
|
||||
msi_delete_fb(NULL, fb);
|
||||
fb = NULL;
|
||||
|
||||
// 解锁
|
||||
unlock = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
os_printf("%s:%d\tdecode msg isn't normal\tmsg:%X\tname:%s\n", __FUNCTION__, __LINE__, msg, decode->parent_fb->msi->name);
|
||||
|
||||
// 不符合,需要删除,不去编码
|
||||
msi_delete_fb(NULL, decode->parent_fb);
|
||||
decode->parent_fb = NULL;
|
||||
|
||||
msi_delete_fb(NULL, fb);
|
||||
fb = NULL;
|
||||
// 解锁
|
||||
unlock = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 解锁
|
||||
unlock = 1;
|
||||
}
|
||||
}
|
||||
not_decode:
|
||||
if (unlock)
|
||||
{
|
||||
scale_mutex_unlock(2, SCALE_LOCK_H264_DECODE1);
|
||||
decode->unlock = 0;
|
||||
}
|
||||
os_run_work_delay(work, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int decode_msi_action(struct msi *msi, uint32 cmd_id, uint32 param1, uint32 param2)
|
||||
{
|
||||
int ret = RET_OK;
|
||||
struct h264_msi_s *decode = (struct h264_msi_s *) msi->priv;
|
||||
switch (cmd_id)
|
||||
{
|
||||
case MSI_CMD_POST_DESTROY:
|
||||
{
|
||||
struct framebuff *fb;
|
||||
if (decode->unlock)
|
||||
{
|
||||
scale_mutex_unlock(2, SCALE_LOCK_H264_DECODE1);
|
||||
decode->unlock = 0;
|
||||
}
|
||||
|
||||
if (decode->rom)
|
||||
{
|
||||
STREAM_FREE(decode->rom);
|
||||
decode->rom = NULL;
|
||||
}
|
||||
|
||||
if (decode->ref_mem && (uint32_t) decode->ref_mem != 0x40000000)
|
||||
{
|
||||
STREAM_FREE(decode->ref_mem);
|
||||
decode->ref_mem = NULL;
|
||||
decode->ref_max_size = 0;
|
||||
}
|
||||
// 释放资源fb资源文件,priv是独立申请的
|
||||
while (1)
|
||||
{
|
||||
fb = fbpool_get(&decode->tx_pool, 0, NULL);
|
||||
if (!fb)
|
||||
{
|
||||
break;
|
||||
}
|
||||
// 预分配空间释放
|
||||
if (fb->priv)
|
||||
{
|
||||
STREAM_LIBC_FREE(fb->priv);
|
||||
}
|
||||
|
||||
// 预分配空间释放
|
||||
if (fb->data)
|
||||
{
|
||||
STREAM_FREE(fb->data);
|
||||
fb->data = NULL;
|
||||
}
|
||||
}
|
||||
fbpool_destroy(&decode->tx_pool);
|
||||
if (decode->scaler2buf_y)
|
||||
{
|
||||
STREAM_LIBC_FREE(decode->scaler2buf_y);
|
||||
decode->scaler2buf_y = NULL;
|
||||
}
|
||||
|
||||
if (decode->scaler2buf_u)
|
||||
{
|
||||
STREAM_LIBC_FREE(decode->scaler2buf_u);
|
||||
decode->scaler2buf_u = NULL;
|
||||
}
|
||||
|
||||
if (decode->scaler2buf_v)
|
||||
{
|
||||
STREAM_LIBC_FREE(decode->scaler2buf_v);
|
||||
decode->scaler2buf_v = NULL;
|
||||
}
|
||||
STREAM_LIBC_FREE(decode);
|
||||
}
|
||||
break;
|
||||
|
||||
// 停止硬件
|
||||
case MSI_CMD_PRE_DESTROY:
|
||||
{
|
||||
os_work_cancle2(&decode->work, 1);
|
||||
// 关闭硬件
|
||||
scale_close(decode->scale_dev);
|
||||
|
||||
if (decode->current_fb)
|
||||
{
|
||||
msi_delete_fb(NULL, decode->current_fb);
|
||||
decode->current_fb = NULL;
|
||||
}
|
||||
if (decode->parent_fb)
|
||||
{
|
||||
msi_delete_fb(NULL, decode->parent_fb);
|
||||
decode->parent_fb = NULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MSI_CMD_FREE_FB:
|
||||
{
|
||||
struct framebuff *fb = (struct framebuff *) param1;
|
||||
fbpool_put(&decode->tx_pool, fb);
|
||||
// 不需要内核去释放fb
|
||||
ret = RET_OK + 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case MSI_CMD_DECODE:
|
||||
{
|
||||
uint32_t cmd_self = (uint32_t) param1;
|
||||
uint32_t arg = param2;
|
||||
switch (cmd_self)
|
||||
{
|
||||
case MSI_DECODE_SET_W_H:
|
||||
{
|
||||
struct framebuff *fb = (struct framebuff *) arg;
|
||||
struct jpg_decode_arg_s *cfg = (struct jpg_decode_arg_s *) fb->priv;
|
||||
struct h264_msi_s *decode = (struct h264_msi_s *) msi->priv;
|
||||
decode->p1_w = cfg->yuv_arg.out_w;
|
||||
decode->p1_h = cfg->yuv_arg.out_h;
|
||||
decode->scale_p1_w = ((decode->p1_w + 3) / 4) * 4;
|
||||
if (cfg->rotate)
|
||||
{
|
||||
decode->dec_y_offset = decode->p1_w * (decode->p1_h - 1);
|
||||
decode->dec_uv_offset = ((decode->scale_p1_w / 2 + 3) / 4) * 4 * (decode->p1_h / 2 - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
decode->dec_y_offset = 0;
|
||||
decode->dec_uv_offset = 0;
|
||||
}
|
||||
|
||||
cfg->yuv_arg.y_off = decode->dec_y_offset;
|
||||
cfg->yuv_arg.uv_off = decode->dec_uv_offset;
|
||||
cfg->yuv_arg.y_size = decode->scale_p1_w * decode->p1_h;
|
||||
}
|
||||
break;
|
||||
|
||||
case MSI_DECODE_SET_IN_OUT_SIZE:
|
||||
{
|
||||
}
|
||||
break;
|
||||
|
||||
case MSI_DECODE_SET_STEP:
|
||||
{
|
||||
}
|
||||
break;
|
||||
|
||||
case MSI_DECODE_READY:
|
||||
{
|
||||
|
||||
struct h264_msi_s *decode = (struct h264_msi_s *) msi->priv;
|
||||
struct framebuff *fb = (struct framebuff *) arg;
|
||||
uint32 dst = (uint32_t) fb->data;
|
||||
struct jpg_decode_arg_s *cfg = (struct jpg_decode_arg_s *) fb->priv;
|
||||
uint8_t err = 0;
|
||||
|
||||
#if 0
|
||||
h264_request_irq(decode->h264_dev, H264_FRAME_DONE, h264_dec_done, (uint32) decode);
|
||||
#else
|
||||
// 如果空间不够,就重新申请把
|
||||
if (decode->p1_w > decode->now_decode_pw)
|
||||
{
|
||||
if (decode->scaler2buf_y)
|
||||
{
|
||||
STREAM_LIBC_FREE(decode->scaler2buf_y);
|
||||
decode->scaler2buf_y = NULL;
|
||||
}
|
||||
|
||||
if (decode->scaler2buf_u)
|
||||
{
|
||||
STREAM_LIBC_FREE(decode->scaler2buf_u);
|
||||
decode->scaler2buf_u = NULL;
|
||||
}
|
||||
|
||||
if (decode->scaler2buf_v)
|
||||
{
|
||||
STREAM_LIBC_FREE(decode->scaler2buf_v);
|
||||
decode->scaler2buf_v = NULL;
|
||||
}
|
||||
uint8_t scale_coeff = 0;
|
||||
uint32_t iw = cfg->decode_w;
|
||||
// uint32_t ih = cfg->decode_h;
|
||||
uint32_t ow = decode->p1_w;
|
||||
// uint32_t oh = decode->p1_h;
|
||||
if(iw >= ow)
|
||||
{
|
||||
scale_coeff = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
scale_coeff = 2;
|
||||
}
|
||||
|
||||
// 默认一定申请到,没有做申请失败的处理
|
||||
decode->scaler2buf_y = STREAM_LIBC_MALLOC(0x20+ow+scale_coeff*20*SRAMBUF_WLEN*4+256);
|
||||
decode->scaler2buf_u = STREAM_LIBC_MALLOC(((0x12+ow/2+scale_coeff*11*SRAMBUF_WLEN*2+128 + 3)/4)*4);
|
||||
decode->scaler2buf_v = STREAM_LIBC_MALLOC(((0x12+ow/2+scale_coeff*11*SRAMBUF_WLEN*2+128 + 3)/4)*4);
|
||||
if (!decode->scaler2buf_y || !decode->scaler2buf_u || !decode->scaler2buf_v)
|
||||
{
|
||||
os_printf(KERN_ERR "%s:%d err\tpw:%X\tnow_pw:%X\n", __FUNCTION__, __LINE__, decode->p1_w, decode->now_decode_pw);
|
||||
os_printf(KERN_ERR "fail y:%X\tu:%X\tv:%X\n", decode->scaler2buf_y, decode->scaler2buf_u, decode->scaler2buf_v);
|
||||
decode->now_decode_pw = 0;
|
||||
err = 1;
|
||||
if (decode->scaler2buf_y)
|
||||
{
|
||||
STREAM_LIBC_FREE(decode->scaler2buf_y);
|
||||
decode->scaler2buf_y = NULL;
|
||||
}
|
||||
|
||||
if (decode->scaler2buf_u)
|
||||
{
|
||||
STREAM_LIBC_FREE(decode->scaler2buf_u);
|
||||
decode->scaler2buf_u = NULL;
|
||||
}
|
||||
|
||||
if (decode->scaler2buf_v)
|
||||
{
|
||||
STREAM_LIBC_FREE(decode->scaler2buf_v);
|
||||
decode->scaler2buf_v = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
decode->now_decode_pw = decode->p1_w;
|
||||
}
|
||||
}
|
||||
if (!err)
|
||||
{
|
||||
|
||||
scale2_from_h264_config_for_msi(decode->scale_dev, (uint32_t) decode->scaler2buf_y, (uint32_t) decode->scaler2buf_u, (uint32_t) decode->scaler2buf_v, dst, cfg->decode_w,
|
||||
cfg->decode_h, cfg->yuv_arg.out_w, cfg->yuv_arg.out_h, 10);
|
||||
|
||||
if (!decode->is_register_isr)
|
||||
{
|
||||
scale_request_irq(decode->scale_dev, FRAME_END, (scale_irq_hdl) &stream_jpg_decode_scale2_done, (uint32) decode);
|
||||
scale_request_irq(decode->scale_dev, INBUF_OV, (scale_irq_hdl) &stream_jpg_decode_scale2_ov_isr, (uint32) decode);
|
||||
h264_request_irq(decode->h264_dev, H264_FRAME_DONE, h264_dec_done, (uint32) decode);
|
||||
// decode->is_register_isr = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
decode->hardware_err = 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
case MSI_DECOE_START:
|
||||
{
|
||||
struct framebuff *fb = (struct framebuff *) arg;
|
||||
struct framebuff *rfb = fb->next;
|
||||
struct h264_msi_s *decode = (struct h264_msi_s *) msi->priv;
|
||||
struct fb_h264_s *h264_priv = (struct fb_h264_s *) rfb->priv;
|
||||
uint32_t dst = (uint32_t) rfb->data;
|
||||
uint32_t dst_len = rfb->len;
|
||||
uint8_t *rom_ptr = (uint8_t *) (((uint32_t) decode->rom + 0xfff) & (~0xfff));
|
||||
|
||||
decode->hardware_ready = 0;
|
||||
decode->last_decode_time = os_jiffies();
|
||||
// 这里开启对应的h264解码
|
||||
// 如果是I帧,就去处理sps和pps
|
||||
if (h264_priv->type == 1 && !decode->sps_flag)
|
||||
{
|
||||
sps_setting(&decode->h264_str, &decode->h264_head, decode->w, decode->h);
|
||||
cfg_setting(decode->h264_dev, &decode->h264_head, &decode->dec_cfg, &decode->dec_ctl);
|
||||
h264_dec_refbuf_set(decode->h264_dev, ((uint32_t) decode->ref_mem + 0xfff) & (~0xfff), (struct h264_cfg_t *) &decode->dec_cfg, (struct h264_ctl_t *) &decode->dec_ctl);
|
||||
pps_setting(&decode->h264_str, &decode->h264_head, h264_priv->pps, h264_priv->pps_len);
|
||||
decode->sps_flag = 1;
|
||||
}
|
||||
h264_rom_memcpy(rom_ptr, (uint8_t *) dst, dst_len);
|
||||
h264_decode_I_P_setting(&decode->h264_str, &decode->h264_head, rom_ptr);
|
||||
|
||||
if (h264_priv->type == 1)
|
||||
{
|
||||
decode->dec_ctl.frm_type = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
decode->dec_ctl.frm_type = 0;
|
||||
}
|
||||
|
||||
h264_dec_src_room_set(decode->h264_dev, ((uint32_t) decode->ref_mem + 0xfff) & (~0xfff), (struct h264_cfg_t *) &decode->dec_cfg, (struct h264_ctl_t *) &decode->dec_ctl);
|
||||
h264_dec_a_frame(decode->h264_dev, dst_len + 4, &decode->dec_ctl, &decode->h264_head, &decode->h264_str, (uint32_t) rom_ptr);
|
||||
h264_decode_start(decode->h264_dev);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MSI_CMD_TRANS_FB:
|
||||
{
|
||||
struct framebuff *fb = (struct framebuff *) param1;
|
||||
if (fb->mtype != F_JPG_DECODE_MSG)
|
||||
{
|
||||
ret = RET_OK + 1;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
// 解码是要先获取jpg,然后申请解码后size的空间,然后启动解码
|
||||
// 不再支持传入msi的name(因为硬件解码模块只有一个,所以不支持这个msi的名称命名)
|
||||
struct msi *h264_decode_msi(const char *name, uint8_t only_I_H264)
|
||||
{
|
||||
(void) name; // 不再支持修改名字
|
||||
uint8_t is_new;
|
||||
struct msi *msi = msi_new(name, MAX_DECODE_NUM, &is_new);
|
||||
struct h264_msi_s *decode = (struct h264_msi_s *) msi->priv;
|
||||
if (is_new)
|
||||
{
|
||||
decode = (struct h264_msi_s *) STREAM_LIBC_ZALLOC(sizeof(struct h264_msi_s));
|
||||
decode->msi = msi;
|
||||
msi->priv = (void *) decode;
|
||||
msi->action = decode_msi_action;
|
||||
|
||||
uint32_t init_count = 0;
|
||||
void *priv;
|
||||
fbpool_init(&decode->tx_pool, 2);
|
||||
while (init_count < 2)
|
||||
{
|
||||
uint8_t *data = (uint8_t *) STREAM_MALLOC(DECODE_MAX_SIZE);
|
||||
ASSERT(data);
|
||||
sys_dcache_invalid_range((uint32_t *) data, DECODE_MAX_SIZE);
|
||||
priv = (void *) STREAM_LIBC_ZALLOC(sizeof(struct jpg_decode_arg_s));
|
||||
FBPOOL_SET_INFO(&decode->tx_pool, init_count, data, 0, priv);
|
||||
init_count++;
|
||||
}
|
||||
|
||||
decode->h264_dev = (struct h264_device *) dev_get(HG_H264_DEVID);
|
||||
decode->scale_dev = (struct scale_device *) dev_get(HG_SCALE2_DEVID);
|
||||
decode->scaler2buf_y = NULL;
|
||||
decode->scaler2buf_u = NULL;
|
||||
decode->scaler2buf_v = NULL;
|
||||
decode->now_decode_pw = 0;
|
||||
decode->hardware_ready = 1;
|
||||
decode->auto_free_space = 1;
|
||||
decode->only_I_H264 = only_I_H264;
|
||||
// decode->w = w;
|
||||
// decode->h = h;
|
||||
decode->max_data_size = DECODE_MAX_SIZE;
|
||||
// decode->rom = os_malloc_psram(100 * 1024 + 4096);
|
||||
// decode->ref_mem = os_malloc_psram((w * (h + 48)) + (w * (h + 48)) / 2 + 3 * 4096);
|
||||
// sys_dcache_clean_range((uint32_t *) decode->ref_mem, (w * (h + 48)) + (w * (h + 48)) / 2 + 3 * 4096);
|
||||
|
||||
decode->dec_cfg.enc_mode = 0;
|
||||
// decode->dec_cfg.frm_width = w;
|
||||
// decode->dec_cfg.frm_height = h;
|
||||
msi->enable = 1;
|
||||
OS_WORK_INIT(&decode->work, h264_decode_work, 0);
|
||||
os_run_work_delay(&decode->work, 1);
|
||||
}
|
||||
|
||||
return msi;
|
||||
}
|
||||
344
sdk/app/decode/jpg_decode_msg_msi.c
Normal file
344
sdk/app/decode/jpg_decode_msg_msi.c
Normal file
@@ -0,0 +1,344 @@
|
||||
/*******************************************************************************************************
|
||||
* 该文件主要是为了给jpeg配置需要解码的信息,然后传递给到硬件解码
|
||||
******************************************************************************************************/
|
||||
#include "sys_config.h"
|
||||
#include "typesdef.h"
|
||||
#include "dev.h"
|
||||
#include "devid.h"
|
||||
#include "stream_frame.h"
|
||||
#include "utlist.h"
|
||||
#include "osal/task.h"
|
||||
#include "osal/string.h"
|
||||
#include "osal/work.h"
|
||||
#include "osal_file.h"
|
||||
#include "jpgdef.h"
|
||||
#include "utlist.h"
|
||||
#include "basic_include.h"
|
||||
#include "lib/multimedia/msi.h"
|
||||
#include "stream_define.h"
|
||||
#include "lib/heap/av_heap.h"
|
||||
#include "lib/heap/av_psram_heap.h"
|
||||
#include "user_work/user_work.h"
|
||||
|
||||
// 获取jpeg的w和h,没有做太多容错,所以尽量给的是正确的jpeg,否则可能异常
|
||||
#define GET_16(p) (((p)[0] << 8) | (p)[1])
|
||||
|
||||
static int parse_SOF(uint8_t *d, uint32_t *w, uint32_t *h)
|
||||
{
|
||||
if (d[0] != 8)
|
||||
{
|
||||
printf("Invalid precision %d in SOF0\n", d[0]);
|
||||
return -1;
|
||||
}
|
||||
*h = GET_16(d + 1);
|
||||
*w = GET_16(d + 3);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_jpg(uint8_t *jpg_buf, uint32_t maxsize, uint32_t *w, uint32_t *h)
|
||||
{
|
||||
uint8_t *buf = jpg_buf;
|
||||
uint8_t EOI_flag = 0;
|
||||
uint32_t i = 0;
|
||||
int res = 1;
|
||||
int blen = 0;
|
||||
for (i = 0; i < maxsize; i += blen + 2)
|
||||
{
|
||||
if (buf[i] != 0xFF)
|
||||
{
|
||||
printf("Found %02X at %d, expecting FF\n", buf[i], i);
|
||||
goto parse_jpg_end;
|
||||
}
|
||||
while (buf[i + 1] == 0xFF)
|
||||
{
|
||||
++i;
|
||||
}
|
||||
if (buf[i + 1] == 0xD8)
|
||||
{
|
||||
blen = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
blen = GET_16(buf + i + 2);
|
||||
}
|
||||
|
||||
switch (buf[i + 1])
|
||||
{
|
||||
case 0xDB: /* Quantization Table */
|
||||
break;
|
||||
case 0xC0: /* Start of Frame */
|
||||
parse_SOF(buf + i + 4, w, h);
|
||||
res = 0;
|
||||
// printf("w:%d\th:%d\n",*w,*h);
|
||||
break;
|
||||
case 0xC4: /* Huffman Table */
|
||||
|
||||
break;
|
||||
case 0xDD: /* DRI */
|
||||
break;
|
||||
case 0xDA: /* Start of Scan */
|
||||
goto parse_jpg_end;
|
||||
}
|
||||
}
|
||||
|
||||
parse_jpg_end:
|
||||
|
||||
if (!res)
|
||||
{
|
||||
for (i = maxsize - 1; i >= maxsize - 16; i--)
|
||||
{
|
||||
if (buf[i] != 0xFF)
|
||||
{
|
||||
// os_printf("EOI Found %02X at %d, expecting FF\n", buf[i], i);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((i < maxsize - 1) && (buf[i + 1] == 0xD9))
|
||||
{
|
||||
EOI_flag = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((!res) && (!EOI_flag))
|
||||
{
|
||||
res = 1;
|
||||
os_printf("EOI No found FF D9\n");
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int ex_parse_jpg(uint8_t *jpg_buf, uint32_t maxsize, uint32_t *w, uint32_t *h)
|
||||
{
|
||||
return parse_jpg(jpg_buf, maxsize, w, 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 jpg_decode_msg_s
|
||||
{
|
||||
struct os_work work;
|
||||
struct msi *msi;
|
||||
struct framebuff *rfb;
|
||||
uint32_t magic; // 会赋值到对应参数,用于后续msi的识别,如果为0,就是没有任何处理
|
||||
uint16_t out_w;
|
||||
uint16_t out_h;
|
||||
uint16_t step_w;
|
||||
uint16_t step_h;
|
||||
uint16_t x, y; // 解码配置的x和y,如果没有可以不配置
|
||||
uint16_t force_type; // 强转类型(统一将解码的类型修改,不按照filter,0是无效)
|
||||
uint8_t filter; // 过滤解码的类型
|
||||
uint8_t ish264;
|
||||
};
|
||||
|
||||
static int32 jpg_decode_msg_work(struct os_work *work)
|
||||
{
|
||||
struct jpg_decode_msg_s *decode_msg = (struct jpg_decode_msg_s *) work;
|
||||
struct framebuff *rfb;
|
||||
struct framebuff *fb;
|
||||
int res;
|
||||
if (decode_msg->rfb)
|
||||
{
|
||||
rfb = decode_msg->rfb;
|
||||
// 这里可以考虑用自己的内存管理,后续看情况修改接口
|
||||
fb = fb_alloc(NULL, sizeof(struct jpg_decode_arg_s), 0, decode_msg->msi);
|
||||
// 申请不到就等下次进来再去尝试解码吧
|
||||
if (fb)
|
||||
{
|
||||
fb_ref(fb, rfb);
|
||||
fb->datatag = rfb->datatag;
|
||||
fb->stype = rfb->stype;
|
||||
fb->srcID = rfb->srcID;
|
||||
struct jpg_decode_arg_s *msg = (struct jpg_decode_arg_s *) fb->data;
|
||||
struct yuv_arg_s *yuv_msg = &msg->yuv_arg;
|
||||
memset(msg, 0, sizeof(struct jpg_decode_arg_s));
|
||||
yuv_msg->out_w = decode_msg->out_w;
|
||||
yuv_msg->out_h = decode_msg->out_h;
|
||||
yuv_msg->x = decode_msg->x;
|
||||
yuv_msg->y = decode_msg->y;
|
||||
yuv_msg->magic = decode_msg->magic;
|
||||
yuv_msg->dispcnt = fb->datatag;
|
||||
// os_printf("yuv_msg->dispcnt:%d\n",yuv_msg->dispcnt);
|
||||
msg->step_w = decode_msg->step_w;
|
||||
msg->step_h = decode_msg->step_h;
|
||||
|
||||
if (rfb->mtype == F_H264)
|
||||
{
|
||||
struct fb_h264_s *h264_priv = (struct fb_h264_s *) rfb->priv;
|
||||
res = 0;
|
||||
msg->decode_w = h264_priv->w;
|
||||
msg->decode_h = h264_priv->h;
|
||||
}
|
||||
else if (rfb->mtype == F_JPG)
|
||||
{
|
||||
res = parse_jpg(rfb->data, rfb->len, &msg->decode_w, &msg->decode_h);
|
||||
}
|
||||
else
|
||||
{
|
||||
res = 1;
|
||||
}
|
||||
if (!res)
|
||||
{
|
||||
fb->mtype = F_JPG_DECODE_MSG;
|
||||
fb->stype = decode_msg->force_type ? decode_msg->force_type : rfb->stype;
|
||||
fb->time = rfb->time;
|
||||
msi_output_fb(decode_msg->msi, fb);
|
||||
msi_delete_fb(NULL, rfb);
|
||||
decode_msg->rfb = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
msi_delete_fb(NULL, fb);
|
||||
msi_delete_fb(NULL, rfb);
|
||||
decode_msg->rfb = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
decode_msg->rfb = msi_get_fb(decode_msg->msi, 0);
|
||||
}
|
||||
os_run_work_delay(work, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t decode_msg_msi_action(struct msi *msi, uint32 cmd_id, uint32 param1, uint32 param2)
|
||||
{
|
||||
int32_t ret = RET_OK;
|
||||
struct jpg_decode_msg_s *decode_msg = (struct jpg_decode_msg_s *) msi->priv;
|
||||
switch (cmd_id)
|
||||
{
|
||||
|
||||
// 这里msi已经被删除,那么就要考虑tx_pool的资源释放了
|
||||
// 能进来这里,就是代表所有fb都已经用完了
|
||||
case MSI_CMD_POST_DESTROY:
|
||||
{
|
||||
os_work_cancle2(&decode_msg->work, 1);
|
||||
STREAM_LIBC_FREE(decode_msg);
|
||||
}
|
||||
break;
|
||||
|
||||
case MSI_CMD_PRE_DESTROY:
|
||||
{
|
||||
os_work_cancle2(&decode_msg->work, 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case MSI_CMD_DECODE_JPEG_MSG:
|
||||
{
|
||||
uint32_t cmd_self = (uint32_t) param1;
|
||||
uint32_t arg = param2;
|
||||
switch (cmd_self)
|
||||
{
|
||||
case MSI_JPEG_DECODE_X_Y:
|
||||
{
|
||||
decode_msg->x = arg >> 16;
|
||||
decode_msg->y = arg & 0xffff;
|
||||
}
|
||||
break;
|
||||
|
||||
// 配置强转类型
|
||||
case MSI_JPEG_DECODE_FORCE_TYPE:
|
||||
{
|
||||
decode_msg->force_type = arg;
|
||||
}
|
||||
break;
|
||||
|
||||
case MSI_JPEG_DECODE_MAGIC:
|
||||
{
|
||||
decode_msg->magic = arg;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MSI_CMD_TRANS_FB:
|
||||
{
|
||||
struct framebuff *fb = (struct framebuff *) param1;
|
||||
|
||||
if (decode_msg->ish264)
|
||||
{
|
||||
if (fb->mtype != F_H264)
|
||||
{
|
||||
ret = RET_OK + 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fb->mtype != F_JPG)
|
||||
{
|
||||
ret = RET_OK + 1;
|
||||
}
|
||||
}
|
||||
if (decode_msg->filter && !(decode_msg->filter == fb->stype))
|
||||
{
|
||||
ret = RET_OK + 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct msi *jpg_decode_msg_msi(const char *name, uint16_t out_w, uint16_t out_h, uint16_t step_w, uint16_t step_h, uint32_t filter)
|
||||
{
|
||||
struct msi *msi = msi_new(name, 8, NULL);
|
||||
struct jpg_decode_msg_s *decode_msg = (struct jpg_decode_msg_s *) msi->priv;
|
||||
if (!decode_msg)
|
||||
{
|
||||
decode_msg = (struct jpg_decode_msg_s *) STREAM_LIBC_ZALLOC(sizeof(struct jpg_decode_msg_s));
|
||||
msi->priv = (void *) decode_msg;
|
||||
msi->action = decode_msg_msi_action;
|
||||
decode_msg->msi = msi;
|
||||
decode_msg->out_w = out_w;
|
||||
decode_msg->out_h = out_h;
|
||||
decode_msg->step_w = step_w;
|
||||
decode_msg->step_h = step_h;
|
||||
decode_msg->filter = filter;
|
||||
decode_msg->rfb = NULL;
|
||||
decode_msg->ish264 = 0;
|
||||
msi->enable = 1;
|
||||
// 启动workqueue
|
||||
OS_WORK_INIT(&decode_msg->work, jpg_decode_msg_work, 0);
|
||||
os_run_work_delay(&decode_msg->work, 1);
|
||||
}
|
||||
|
||||
return msi;
|
||||
}
|
||||
|
||||
struct msi *h264_decode_msg_msi(const char *name, uint16_t out_w, uint16_t out_h, uint16_t step_w, uint16_t step_h, uint32_t filter)
|
||||
{
|
||||
struct msi *msi = msi_new(name, 8, NULL);
|
||||
struct jpg_decode_msg_s *decode_msg = (struct jpg_decode_msg_s *) msi->priv;
|
||||
if (!decode_msg)
|
||||
{
|
||||
decode_msg = (struct jpg_decode_msg_s *) STREAM_LIBC_ZALLOC(sizeof(struct jpg_decode_msg_s));
|
||||
msi->priv = (void *) decode_msg;
|
||||
msi->action = decode_msg_msi_action;
|
||||
decode_msg->msi = msi;
|
||||
decode_msg->out_w = out_w;
|
||||
decode_msg->out_h = out_h;
|
||||
decode_msg->step_w = step_w;
|
||||
decode_msg->step_h = step_h;
|
||||
decode_msg->filter = filter;
|
||||
decode_msg->rfb = NULL;
|
||||
decode_msg->ish264 = 0;
|
||||
decode_msg->ish264 = 1;
|
||||
msi->enable = 1;
|
||||
// 启动workqueue
|
||||
OS_WORK_INIT(&decode_msg->work, jpg_decode_msg_work, 0);
|
||||
os_run_work_delay(&decode_msg->work, 1);
|
||||
}
|
||||
|
||||
return msi;
|
||||
}
|
||||
616
sdk/app/decode/jpg_decode_msi.c
Normal file
616
sdk/app/decode/jpg_decode_msi.c
Normal file
@@ -0,0 +1,616 @@
|
||||
#include "basic_include.h"
|
||||
#include "dev.h"
|
||||
#include "dev/jpg/hgjpg.h"
|
||||
#include "dev/scale/hgscale.h"
|
||||
#include "devid.h"
|
||||
#include "lib/lcd/lcd.h"
|
||||
#include "osal/work.h"
|
||||
#include "stream_frame.h"
|
||||
#include "sys_config.h"
|
||||
#include "typesdef.h"
|
||||
#include "utlist.h"
|
||||
|
||||
#include "basic_include.h"
|
||||
#include "lib/heap/av_heap.h"
|
||||
#include "lib/heap/av_psram_heap.h"
|
||||
#include "lib/multimedia/msi.h"
|
||||
#include "lib/video/dvp/jpeg/jpg_common.h"
|
||||
#include "osal/event.h"
|
||||
#include "user_work/user_work.h"
|
||||
|
||||
#ifndef DECODE_MAX_W
|
||||
#define DECODE_MAX_W (320)
|
||||
#endif
|
||||
|
||||
#ifndef DECODE_MAX_H
|
||||
#define DECODE_MAX_H (180)
|
||||
#endif
|
||||
#define DECODE_MAX_SIZE (DECODE_MAX_W * DECODE_MAX_H * 3 / 2)
|
||||
|
||||
extern void scale2_from_jpeg_config_for_msi(struct scale_device *scale_dev, uint32_t yinsram, uint32_t uinsram, uint32_t vinsram, uint32_t yuvoutbuf, uint32 in_w, uint32 in_h, uint32 out_w,
|
||||
uint32 out_h, uint8_t larger);
|
||||
// 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
|
||||
|
||||
#define MAX_DECODE_NUM (8)
|
||||
|
||||
#ifndef MAX_DECODE_YUV_TX
|
||||
#define MAX_DECODE_YUV_TX (1)
|
||||
#endif
|
||||
|
||||
struct jpg_msi_s
|
||||
{
|
||||
struct os_work work;
|
||||
struct msi *msi;
|
||||
struct fbpool tx_pool;
|
||||
uint8_t *scaler2buf_y;
|
||||
uint8_t *scaler2buf_u;
|
||||
uint8_t *scaler2buf_v;
|
||||
struct jpg_device *jpg_dev;
|
||||
struct scale_device *scale_dev;
|
||||
uint32_t last_decode_time; // 记录上一次解码的时间,预防有异常的时候可以计算超时
|
||||
uint32_t dec_y_offset;
|
||||
uint32_t dec_uv_offset;
|
||||
uint16_t now_decode_pw;
|
||||
uint16_t scale_p1_w;
|
||||
uint16_t p1_w;
|
||||
uint16_t p1_h;
|
||||
struct framebuff *parent_fb;
|
||||
struct framebuff *current_fb;
|
||||
|
||||
uint32_t max_data_size;
|
||||
|
||||
// 硬件模块是否准备好
|
||||
uint8_t hardware_ready;
|
||||
uint8_t hardware_err;
|
||||
uint8_t is_register_isr;
|
||||
// 是否自动释放空间(可能会导致碎片化严重,但是可以充分利用空间)
|
||||
uint8_t auto_free_space;
|
||||
};
|
||||
|
||||
static void stream_jpg_decode_scale2_done(uint32 irq_flag, uint32 irq_data, uint32 param1)
|
||||
{
|
||||
}
|
||||
|
||||
static void stream_jpg_decode_scale2_ov_isr(uint32 irq_flag, uint32 irq_data, uint32 param1)
|
||||
{
|
||||
// struct scale_device *scale_dev = (struct scale_device *)irq_data;
|
||||
os_printf("sor2");
|
||||
}
|
||||
|
||||
static void stream_jpg_decode_done(uint32 irq_flag, uint32 irq_data, uint32 param1, uint32 param2)
|
||||
{
|
||||
_os_printf("*");
|
||||
struct jpg_msi_s *decode = (struct jpg_msi_s *) irq_data;
|
||||
decode->hardware_ready = 1;
|
||||
}
|
||||
|
||||
// 这里解码失败,暂时代表硬件完成,后面应该有错误标志位,主要为了解码失败移除当前frame
|
||||
static void stream_jpg_decode_err(uint32 irq_flag, uint32 irq_data, uint32 param1, uint32 param2)
|
||||
{
|
||||
struct jpg_msi_s *decode = (struct jpg_msi_s *) irq_data;
|
||||
os_printf("decode err\r\n");
|
||||
// decode->hardware_ready = 1;
|
||||
decode->hardware_err = 1;
|
||||
}
|
||||
|
||||
static int32 jpg_decode_work(struct os_work *work)
|
||||
{
|
||||
|
||||
int ret;
|
||||
uint8_t unlock = 0;
|
||||
struct jpg_msi_s *decode = (struct jpg_msi_s *) work;
|
||||
struct framebuff *fb;
|
||||
// static int count = 0;
|
||||
// 检测解码模块是否完成或者超时代表解码失败
|
||||
// 能进去,模块需要reset或者已经解码完毕,可以重新去解码,否则只能慢慢等超时或者硬件解码完成
|
||||
if (decode->hardware_err || decode->hardware_ready || os_jiffies() - decode->last_decode_time > 1000)
|
||||
{
|
||||
if (decode->current_fb && (os_jiffies() - decode->last_decode_time > 1000))
|
||||
{
|
||||
// 解码可能失败了
|
||||
os_printf(KERN_ERR"decode failed1:%d\n", decode->hardware_ready);
|
||||
os_printf(KERN_ERR"decode->hardware_err:%d\n", decode->hardware_err);
|
||||
decode->hardware_ready = 1;
|
||||
// 无论是完成还是失败,都要释放这张图片了
|
||||
msi_delete_fb(NULL, decode->parent_fb);
|
||||
decode->parent_fb = NULL;
|
||||
|
||||
// 不再解码了
|
||||
msi_delete_fb(NULL, decode->current_fb);
|
||||
decode->current_fb = NULL;
|
||||
|
||||
// 这里最好将硬件模块停止
|
||||
|
||||
// 解锁
|
||||
unlock = 1;
|
||||
}
|
||||
// 解码异常
|
||||
else if (decode->hardware_err)
|
||||
{
|
||||
_os_printf(KERN_ERR"decode failed2\n");
|
||||
decode->hardware_err = 0;
|
||||
decode->hardware_ready = 1;
|
||||
if (decode->current_fb)
|
||||
{
|
||||
// 无论是完成还是失败,都要释放这张图片了
|
||||
msi_delete_fb(NULL, decode->parent_fb);
|
||||
decode->parent_fb = NULL;
|
||||
|
||||
// 不再解码了
|
||||
msi_delete_fb(NULL, decode->current_fb);
|
||||
decode->current_fb = NULL;
|
||||
}
|
||||
// 解锁
|
||||
unlock = 1;
|
||||
}
|
||||
// 解码完成,检查有解码完的数据需要发送
|
||||
else if (decode->current_fb)
|
||||
{
|
||||
// os_printf("%s:%d\tbuf:%X\n",__FUNCTION__,__LINE__,get_stream_real_data(decode->current_fb));
|
||||
fb = decode->current_fb;
|
||||
fb->time = decode->parent_fb->time;
|
||||
fb->mtype = F_YUV;
|
||||
fb->stype = decode->parent_fb->stype;
|
||||
fb->datatag = decode->parent_fb->datatag;
|
||||
fb->srcID = decode->parent_fb->srcID;
|
||||
_os_printf("&");
|
||||
|
||||
msi_output_fb(decode->msi, fb);
|
||||
// 无论是完成还是失败,都要释放这张图片了
|
||||
msi_delete_fb(NULL, decode->parent_fb);
|
||||
decode->parent_fb = NULL;
|
||||
decode->current_fb = NULL;
|
||||
decode->is_register_isr = 0;
|
||||
// 解锁
|
||||
unlock = 1;
|
||||
}
|
||||
// 硬件可用,但是current_fb不存在
|
||||
// 有两种可能
|
||||
// 一、没有需要解码的图片
|
||||
// 二、有需要解码的图片,但是fb没有申请成功或者内存空间不足以去解码图片数据
|
||||
else
|
||||
{
|
||||
}
|
||||
|
||||
if (unlock)
|
||||
{
|
||||
jpg_close(decode->jpg_dev);
|
||||
jpg_mutex_unlock(JPGID1, JPG_LOCK_DECODE);
|
||||
unlock = 0;
|
||||
}
|
||||
|
||||
// 这里没有解码的图片,尝试去看看有没有需要解码图片
|
||||
if (!decode->parent_fb)
|
||||
{
|
||||
// 接收图片,尝试看看是否要解码
|
||||
decode->parent_fb = msi_get_fb(decode->msi, 0);
|
||||
|
||||
// 需要解码,然后申请空间
|
||||
if (decode->parent_fb)
|
||||
{
|
||||
// os_printf("parent_fb:%X\n",decode->parent_fb);
|
||||
goto start_decode;
|
||||
}
|
||||
// 不需要解码
|
||||
else
|
||||
{
|
||||
// 为了腾出空间,释放空间
|
||||
if (decode->auto_free_space)
|
||||
{
|
||||
if (decode->scaler2buf_y)
|
||||
{
|
||||
STREAM_LIBC_FREE(decode->scaler2buf_y);
|
||||
decode->scaler2buf_y = NULL;
|
||||
}
|
||||
|
||||
if (decode->scaler2buf_u)
|
||||
{
|
||||
STREAM_LIBC_FREE(decode->scaler2buf_u);
|
||||
decode->scaler2buf_u = NULL;
|
||||
}
|
||||
|
||||
if (decode->scaler2buf_v)
|
||||
{
|
||||
STREAM_LIBC_FREE(decode->scaler2buf_v);
|
||||
decode->scaler2buf_v = NULL;
|
||||
}
|
||||
decode->now_decode_pw = 0;
|
||||
}
|
||||
goto not_decode;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
goto start_decode;
|
||||
}
|
||||
|
||||
// 开始尝试解码
|
||||
start_decode:
|
||||
// 检查是否需要解码(检查绑定msi的模块是否需要接收)
|
||||
{
|
||||
uint32_t send_count = msi_output_fb(decode->msi, NULL);
|
||||
if (!send_count)
|
||||
{
|
||||
msi_delete_fb(NULL, decode->parent_fb);
|
||||
decode->parent_fb = NULL;
|
||||
goto not_decode;
|
||||
}
|
||||
}
|
||||
// 先去申请jpg1的锁,确保只有一个模块在使用jpg1
|
||||
ret = jpg_mutex_lock(JPGID1, JPG_LOCK_DECODE, NULL);
|
||||
if (ret)
|
||||
{
|
||||
goto not_decode;
|
||||
}
|
||||
// jpg_open(decode->jpg_dev);
|
||||
// 申请到fb,申请解码空间
|
||||
fb = fbpool_get(&decode->tx_pool, 0, decode->msi);
|
||||
if (fb)
|
||||
{
|
||||
// 因为这个是解码的数据,所以默认parent_fb的data是一个参数内容,而不是真实的data,真实jpg的data应该是附在parent_fb后面其他节点
|
||||
struct jpg_decode_arg_s *msg = (struct jpg_decode_arg_s *) decode->parent_fb->data;
|
||||
// 没有找到,代表发送过来的不是jpg或者说对应参数没有配置,不解码
|
||||
if (msg)
|
||||
{
|
||||
// 为fb申请解码空间,申请不到下次申请
|
||||
fb->len = msg->yuv_arg.out_w * msg->yuv_arg.out_h * 3 / 2;
|
||||
if (fb->len <= decode->max_data_size)
|
||||
{
|
||||
struct jpg_decode_arg_s *cfg;
|
||||
cfg = (struct jpg_decode_arg_s *) fb->priv;
|
||||
memset(cfg, 0, sizeof(struct jpg_decode_arg_s));
|
||||
// 提前配置好data的长度
|
||||
memcpy(fb->priv, msg, sizeof(struct jpg_decode_arg_s));
|
||||
|
||||
msi_do_cmd(decode->msi, MSI_CMD_DECODE, MSI_DECODE_SET_W_H, (uint32_t) fb);
|
||||
|
||||
// fb->type = SET_DATA_TYPE(YUV, GET_DATA_TYPE2(decode->parent_fb->type));
|
||||
|
||||
// msi_do_cmd(decode->msi, MSI_CMD_DECODE, MSI_DECODE_SET_STEP, (uint32_t) cfg);
|
||||
msi_do_cmd(decode->msi, MSI_CMD_DECODE, MSI_DECODE_READY, (uint32_t) fb);
|
||||
if (!decode->hardware_err)
|
||||
{
|
||||
msi_do_cmd(decode->msi, MSI_CMD_DECODE, MSI_DECOE_START, (uint32_t) decode->parent_fb);
|
||||
}
|
||||
|
||||
decode->current_fb = fb;
|
||||
decode->last_decode_time = os_jiffies();
|
||||
}
|
||||
else
|
||||
{
|
||||
os_printf(KERN_ERR"config err,max size w:%d\th:%d\tmax_mem:%d\n",DECODE_MAX_W,DECODE_MAX_H,decode->max_data_size);
|
||||
// 不符合,需要删除,不去编码
|
||||
msi_delete_fb(NULL, decode->parent_fb);
|
||||
decode->parent_fb = NULL;
|
||||
|
||||
msi_delete_fb(NULL, fb);
|
||||
fb = NULL;
|
||||
// 解锁
|
||||
unlock = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
os_printf("%s:%d\tdecode msg isn't normal\tmsg:%X\tname:%s\n", __FUNCTION__, __LINE__, msg, decode->parent_fb->msi->name);
|
||||
|
||||
// 不符合,需要删除,不去编码
|
||||
msi_delete_fb(NULL, decode->parent_fb);
|
||||
decode->parent_fb = NULL;
|
||||
|
||||
msi_delete_fb(NULL, fb);
|
||||
fb = NULL;
|
||||
// 解锁
|
||||
unlock = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 解锁
|
||||
unlock = 1;
|
||||
}
|
||||
}
|
||||
not_decode:
|
||||
if (unlock)
|
||||
{
|
||||
jpg_mutex_unlock(JPGID1, JPG_LOCK_DECODE);
|
||||
}
|
||||
os_run_work_delay(work, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int decode_msi_action(struct msi *msi, uint32 cmd_id, uint32 param1, uint32 param2)
|
||||
{
|
||||
int ret = RET_OK;
|
||||
struct jpg_msi_s *decode = (struct jpg_msi_s *) msi->priv;
|
||||
switch (cmd_id)
|
||||
{
|
||||
case MSI_CMD_POST_DESTROY:
|
||||
{
|
||||
struct framebuff *fb;
|
||||
// 释放资源fb资源文件,priv是独立申请的
|
||||
while (1)
|
||||
{
|
||||
fb = fbpool_get(&decode->tx_pool, 0, NULL);
|
||||
if (!fb)
|
||||
{
|
||||
break;
|
||||
}
|
||||
// 预分配空间释放
|
||||
if (fb->priv)
|
||||
{
|
||||
STREAM_LIBC_FREE(fb->priv);
|
||||
}
|
||||
|
||||
// 预分配空间释放
|
||||
if (fb->data)
|
||||
{
|
||||
STREAM_FREE(fb->data);
|
||||
fb->data = NULL;
|
||||
}
|
||||
}
|
||||
fbpool_destroy(&decode->tx_pool);
|
||||
if (decode->scaler2buf_y)
|
||||
{
|
||||
STREAM_LIBC_FREE(decode->scaler2buf_y);
|
||||
decode->scaler2buf_y = NULL;
|
||||
}
|
||||
|
||||
if (decode->scaler2buf_u)
|
||||
{
|
||||
STREAM_LIBC_FREE(decode->scaler2buf_u);
|
||||
decode->scaler2buf_u = NULL;
|
||||
}
|
||||
|
||||
if (decode->scaler2buf_v)
|
||||
{
|
||||
STREAM_LIBC_FREE(decode->scaler2buf_v);
|
||||
decode->scaler2buf_v = NULL;
|
||||
}
|
||||
jpg_close(decode->jpg_dev);
|
||||
STREAM_LIBC_FREE(decode);
|
||||
jpg_mutex_unlock(JPGID1, JPG_LOCK_DECODE);
|
||||
}
|
||||
break;
|
||||
|
||||
// 停止硬件
|
||||
case MSI_CMD_PRE_DESTROY:
|
||||
{
|
||||
os_work_cancle2(&decode->work, 1);
|
||||
// 关闭硬件
|
||||
scale_close(decode->scale_dev);
|
||||
jpg_close(decode->jpg_dev);
|
||||
|
||||
if (decode->current_fb)
|
||||
{
|
||||
msi_delete_fb(NULL, decode->current_fb);
|
||||
decode->current_fb = NULL;
|
||||
}
|
||||
if (decode->parent_fb)
|
||||
{
|
||||
msi_delete_fb(NULL, decode->parent_fb);
|
||||
decode->parent_fb = NULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MSI_CMD_FREE_FB:
|
||||
{
|
||||
struct framebuff *fb = (struct framebuff *) param1;
|
||||
fbpool_put(&decode->tx_pool, fb);
|
||||
// 不需要内核去释放fb
|
||||
ret = RET_OK + 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case MSI_CMD_DECODE:
|
||||
{
|
||||
uint32_t cmd_self = (uint32_t) param1;
|
||||
uint32_t arg = param2;
|
||||
switch (cmd_self)
|
||||
{
|
||||
case MSI_DECODE_SET_W_H:
|
||||
{
|
||||
struct framebuff *fb = (struct framebuff *) arg;
|
||||
struct jpg_decode_arg_s *cfg = (struct jpg_decode_arg_s *) fb->priv;
|
||||
struct jpg_msi_s *decode = (struct jpg_msi_s *) msi->priv;
|
||||
decode->p1_w = cfg->yuv_arg.out_w;
|
||||
decode->p1_h = cfg->yuv_arg.out_h;
|
||||
decode->scale_p1_w = ((decode->p1_w + 3) / 4) * 4;
|
||||
if (cfg->rotate)
|
||||
{
|
||||
decode->dec_y_offset = decode->p1_w * (decode->p1_h - 1);
|
||||
decode->dec_uv_offset = ((decode->scale_p1_w / 2 + 3) / 4) * 4 * (decode->p1_h / 2 - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
decode->dec_y_offset = 0;
|
||||
decode->dec_uv_offset = 0;
|
||||
}
|
||||
|
||||
cfg->yuv_arg.y_off = decode->dec_y_offset;
|
||||
cfg->yuv_arg.uv_off = decode->dec_uv_offset;
|
||||
cfg->yuv_arg.y_size = decode->scale_p1_w * decode->p1_h;
|
||||
}
|
||||
break;
|
||||
|
||||
case MSI_DECODE_SET_IN_OUT_SIZE:
|
||||
{
|
||||
}
|
||||
break;
|
||||
|
||||
case MSI_DECODE_SET_STEP:
|
||||
{
|
||||
}
|
||||
break;
|
||||
|
||||
case MSI_DECODE_READY:
|
||||
{
|
||||
|
||||
struct jpg_msi_s *decode = (struct jpg_msi_s *) msi->priv;
|
||||
struct framebuff *fb = (struct framebuff *) arg;
|
||||
uint32 dst = (uint32_t) fb->data;
|
||||
struct jpg_decode_arg_s *cfg = (struct jpg_decode_arg_s *) fb->priv;
|
||||
uint8_t err = 0;
|
||||
// 如果空间不够,就重新申请把
|
||||
if (decode->p1_w > decode->now_decode_pw)
|
||||
{
|
||||
if (decode->scaler2buf_y)
|
||||
{
|
||||
STREAM_LIBC_FREE(decode->scaler2buf_y);
|
||||
decode->scaler2buf_y = NULL;
|
||||
}
|
||||
|
||||
if (decode->scaler2buf_u)
|
||||
{
|
||||
STREAM_LIBC_FREE(decode->scaler2buf_u);
|
||||
decode->scaler2buf_u = NULL;
|
||||
}
|
||||
|
||||
if (decode->scaler2buf_v)
|
||||
{
|
||||
STREAM_LIBC_FREE(decode->scaler2buf_v);
|
||||
decode->scaler2buf_v = NULL;
|
||||
}
|
||||
// 默认一定申请到,没有做申请失败的处理
|
||||
decode->scaler2buf_y = STREAM_LIBC_MALLOC(0x20 + decode->p1_w + 17 * 4 * SRAMBUF_WLEN);
|
||||
decode->scaler2buf_u = STREAM_LIBC_MALLOC(0x12 + decode->p1_w / 2 + 9 * 4 * SRAMBUF_WLEN);
|
||||
decode->scaler2buf_v = STREAM_LIBC_MALLOC(0x12 + decode->p1_w / 2 + 9 * 4 * SRAMBUF_WLEN);
|
||||
if (!decode->scaler2buf_y || !decode->scaler2buf_u || !decode->scaler2buf_v)
|
||||
{
|
||||
os_printf(KERN_ERR "%s:%d err\tpw:%X\tnow_pw:%X\n", __FUNCTION__, __LINE__, decode->p1_w, decode->now_decode_pw);
|
||||
os_printf(KERN_ERR "fail y:%X\tu:%X\tv:%X\n", decode->scaler2buf_y, decode->scaler2buf_u, decode->scaler2buf_v);
|
||||
decode->now_decode_pw = 0;
|
||||
err = 1;
|
||||
if (decode->scaler2buf_y)
|
||||
{
|
||||
STREAM_LIBC_FREE(decode->scaler2buf_y);
|
||||
decode->scaler2buf_y = NULL;
|
||||
}
|
||||
|
||||
if (decode->scaler2buf_u)
|
||||
{
|
||||
STREAM_LIBC_FREE(decode->scaler2buf_u);
|
||||
decode->scaler2buf_u = NULL;
|
||||
}
|
||||
|
||||
if (decode->scaler2buf_v)
|
||||
{
|
||||
STREAM_LIBC_FREE(decode->scaler2buf_v);
|
||||
decode->scaler2buf_v = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
decode->now_decode_pw = decode->p1_w;
|
||||
}
|
||||
}
|
||||
if (!err)
|
||||
{
|
||||
//jpg_open(decode->jpg_dev);
|
||||
scale2_from_jpeg_config_for_msi(decode->scale_dev, (uint32_t)decode->scaler2buf_y, (uint32_t)decode->scaler2buf_u, (uint32_t)decode->scaler2buf_v, dst, cfg->decode_w, cfg->decode_h, cfg->yuv_arg.out_w,
|
||||
cfg->yuv_arg.out_h, 10);
|
||||
|
||||
if (!decode->is_register_isr)
|
||||
{
|
||||
scale_request_irq(decode->scale_dev, FRAME_END, (scale_irq_hdl) &stream_jpg_decode_scale2_done, (uint32) decode);
|
||||
scale_request_irq(decode->scale_dev, INBUF_OV, (scale_irq_hdl) &stream_jpg_decode_scale2_ov_isr, (uint32) decode);
|
||||
jpg_request_irq(decode->jpg_dev, (jpg_irq_hdl) &stream_jpg_decode_done, JPG_IRQ_FLAG_JPG_DONE, (void *) decode);
|
||||
jpg_request_irq(decode->jpg_dev, (jpg_irq_hdl) &stream_jpg_decode_err, JPG_IRQ_FLAG_ERROR, (void *) decode);
|
||||
// decode->is_register_isr = 1;
|
||||
}
|
||||
jpg_decode_target(decode->jpg_dev, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
decode->hardware_err = 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MSI_DECOE_START:
|
||||
{
|
||||
struct framebuff *fb = (struct framebuff *) arg;
|
||||
struct framebuff *rfb = fb->next;
|
||||
struct jpg_msi_s *decode = (struct jpg_msi_s *) msi->priv;
|
||||
uint32_t dst = (uint32_t) rfb->data;
|
||||
decode->hardware_ready = 0;
|
||||
decode->last_decode_time = os_jiffies();
|
||||
// scale_open(decode->scale_dev);
|
||||
sys_dcache_clean_range((uint32_t*)dst,rfb->len);
|
||||
jpg_decode_photo(decode->jpg_dev, dst, rfb->len);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MSI_CMD_TRANS_FB:
|
||||
{
|
||||
struct framebuff *fb = (struct framebuff *) param1;
|
||||
if (fb->mtype != F_JPG_DECODE_MSG)
|
||||
{
|
||||
ret = RET_OK + 1;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
// 解码是要先获取jpg,然后申请解码后size的空间,然后启动解码
|
||||
// 不再支持传入msi的name(因为硬件解码模块只有一个,所以不支持这个msi的名称命名)
|
||||
struct msi *jpg_decode_msi(const char *name)
|
||||
{
|
||||
(void) name; // 不再支持修改名字
|
||||
uint8_t is_new;
|
||||
struct msi *msi = msi_new(S_JPG_DECODE, MAX_DECODE_NUM, &is_new);
|
||||
struct jpg_msi_s *decode = (struct jpg_msi_s *) msi->priv;
|
||||
if (is_new)
|
||||
{
|
||||
decode = (struct jpg_msi_s *) STREAM_LIBC_ZALLOC(sizeof(struct jpg_msi_s));
|
||||
decode->msi = msi;
|
||||
msi->priv = (void *) decode;
|
||||
msi->action = decode_msi_action;
|
||||
|
||||
uint32_t init_count = 0;
|
||||
void *priv;
|
||||
fbpool_init(&decode->tx_pool, MAX_DECODE_YUV_TX);
|
||||
while (init_count < MAX_DECODE_YUV_TX)
|
||||
{
|
||||
uint8_t *data = (uint8_t *) STREAM_MALLOC(DECODE_MAX_SIZE);
|
||||
ASSERT(data);
|
||||
sys_dcache_invalid_range((uint32_t*)data, DECODE_MAX_SIZE);
|
||||
priv = (void *) STREAM_LIBC_ZALLOC(sizeof(struct jpg_decode_arg_s));
|
||||
FBPOOL_SET_INFO(&decode->tx_pool, init_count, data, 0, priv);
|
||||
init_count++;
|
||||
}
|
||||
|
||||
decode->jpg_dev = (struct jpg_device *) dev_get(HG_JPG1_DEVID);
|
||||
decode->scale_dev = (struct scale_device *) dev_get(HG_SCALE2_DEVID);
|
||||
decode->scaler2buf_y = NULL;
|
||||
decode->scaler2buf_u = NULL;
|
||||
decode->scaler2buf_v = NULL;
|
||||
decode->now_decode_pw = 0;
|
||||
decode->hardware_ready = 1;
|
||||
decode->auto_free_space = 1;
|
||||
decode->max_data_size = DECODE_MAX_SIZE;
|
||||
|
||||
msi->enable = 1;
|
||||
OS_WORK_INIT(&decode->work, jpg_decode_work, 0);
|
||||
os_run_work_delay(&decode->work, 1);
|
||||
}
|
||||
|
||||
return msi;
|
||||
}
|
||||
54
sdk/app/decode/route_msi.c
Normal file
54
sdk/app/decode/route_msi.c
Normal file
@@ -0,0 +1,54 @@
|
||||
/***********************************************************************
|
||||
* 这个文件仅仅是中转数据,主要为了一些硬件模块是插入才有数据,所以外部希望
|
||||
* 绑定的时候,可能硬件没有准备好,所以创建一个中转msi,硬件准备好就发送到
|
||||
* 中转msi,然后中转msi帮忙转发出去,外部调用就是用中转msi帮定就可以了,
|
||||
* 这样硬件准备好会自动通过中转msi去转发
|
||||
***********************************************************************/
|
||||
#include "basic_include.h"
|
||||
#include "lib/multimedia/msi.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
|
||||
|
||||
static int32_t route_msi_action(struct msi *msi, uint32_t cmd_id, uint32_t param1, uint32_t param2)
|
||||
{
|
||||
int32_t ret = RET_OK;
|
||||
switch (cmd_id)
|
||||
{
|
||||
// 帮忙转发,但是永远不需要放在队列中
|
||||
case MSI_CMD_TRANS_FB:
|
||||
{
|
||||
struct framebuff *fb = (struct framebuff *)param1;
|
||||
fb_get(fb);
|
||||
msi_output_fb(msi, fb);
|
||||
ret = RET_OK + 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
// 中转(路由)msi,不需要接收,仅仅发送就可以了
|
||||
struct msi *route_msi(const char *name)
|
||||
{
|
||||
// 设置1个接收,只是为了可以output_fb给到这个msi
|
||||
struct msi *msi = msi_new(name, 0, NULL);
|
||||
if (msi)
|
||||
{
|
||||
msi->action = route_msi_action;
|
||||
msi->enable = 1;
|
||||
}
|
||||
return msi;
|
||||
}
|
||||
Reference in New Issue
Block a user