Files
TAIXIN/sdk/app/decode/jpg_decode_msg_msi.c

344 lines
10 KiB
C

/*******************************************************************************************************
* 该文件主要是为了给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;
}