1486 lines
37 KiB
C
1486 lines
37 KiB
C
#include "sys_config.h"
|
|
#include "tx_platform.h"
|
|
#include "list.h"
|
|
#include "dev.h"
|
|
#include "typesdef.h"
|
|
#include "lib/video/dvp/cmos_sensor/csi.h"
|
|
#include "devid.h"
|
|
#include "osal/irq.h"
|
|
#include "osal/string.h"
|
|
#include "lib/video/dvp/jpeg/jpg.h"
|
|
#include "hal/jpeg.h"
|
|
#include "dev/scale/hgscale.h"
|
|
#include "osal/semaphore.h"
|
|
#include "openDML.h"
|
|
#include "osal/mutex.h"
|
|
#include "custom_mem/custom_mem.h"
|
|
//#include "media.h"
|
|
//#include "lib/common/common.h"
|
|
#include "stream_frame.h"
|
|
#include "utlist.h"
|
|
#include "jpgdef.h"
|
|
#if PRC_EN
|
|
#include "hal/prc.h"
|
|
#endif
|
|
#include "osal/task.h"
|
|
extern struct os_mutex m2m1_mutex;
|
|
extern void soft_to_jpg_cfg(uint32 w,uint32 h);
|
|
|
|
|
|
|
|
/* soft to jpg run*/
|
|
static volatile uint8 stjr_itk=0;
|
|
#if PRC_EN
|
|
static uint32 sw_jpg_w, sw_jpg_h;
|
|
static uint32 stjr_linebuf;
|
|
static uint32 stjr_yuvbuf;
|
|
static volatile uint32 stjr_tick;
|
|
static struct prc_device *stjr_prc_dev;
|
|
static struct jpg_device *stjr_jpeg_dev;
|
|
#endif
|
|
extern volatile uint8_t vfx_open;
|
|
#if JPG_EN
|
|
|
|
|
|
static uint8_t *global_jpg0_buf = NULL;
|
|
static uint8_t *global_jpg1_buf = NULL;
|
|
|
|
|
|
|
|
extern struct dvp_device *dvp_test;
|
|
extern uint8_t qc_mode;
|
|
extern Vpp_stream photo_msg;
|
|
extern uint8 *yuvbuf;
|
|
extern FIL fp_jpg;
|
|
|
|
|
|
struct list_head* get_frame(uint8 jpgid);
|
|
|
|
|
|
uint8 *psram_jpg0_buf;
|
|
uint8 *psram_jpg1_buf;
|
|
|
|
struct os_semaphore *jpg_sema_pd = NULL;
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#define JPEG_FRAME_NUM 2
|
|
|
|
|
|
volatile struct list_head free_tab[JPG_NUM]; //空闲列表,存放空间节点
|
|
|
|
volatile struct list_head *jpg_p[JPG_NUM]; //jpg模块的节点指针
|
|
volatile struct list_head *usr_p[JPG_NUM]; //应用的节点指针
|
|
|
|
volatile jpeg_frame jpg_frame[JPG_NUM][JPEG_FRAME_NUM]; //最大frame数量
|
|
volatile struct list_head* jpg_f_p[JPG_NUM]; //当前jpg所使用的frame
|
|
|
|
volatile mjpeg_node jpg0_node_src[JPG0_NODE];
|
|
volatile mjpeg_node jpg1_node_src[JPG1_NODE];
|
|
|
|
volatile uint32 outbuff_isr[JPG_NUM] = {0x0,0x0};
|
|
volatile int8 default_qt[JPG_NUM] = {0xf, 0xf};
|
|
struct jpg_device *jpeg_dev_global[JPG_NUM];
|
|
|
|
volatile uint8 psram_example_buf[38548] __attribute__ ((aligned(4),section(".psram.src")));
|
|
extern uint8 psram_ybuf_src[IMAGE_H*IMAGE_W+IMAGE_H*IMAGE_W/2];
|
|
|
|
volatile int8_t g_dqtable_index = DQT_DEF;
|
|
|
|
/**@brief
|
|
* 将传入的frame根节点下的buf池都送回空间池(free_tab)中
|
|
*/
|
|
bool free_get_node_list(volatile struct list_head *head,volatile struct list_head *free){
|
|
if(list_empty((struct list_head *)head)){
|
|
return 0;
|
|
}
|
|
|
|
list_splice_init((struct list_head *)head,(struct list_head *)free);
|
|
return 1;
|
|
}
|
|
|
|
|
|
/**@brief
|
|
* 从初始化的frame根节点中抽取其中一个空闲的根节点进行使用,并标记frame的使用状态为正在使用
|
|
* @param 是否开启抢占模式,如果开启,则将上一帧已完成的帧节点删掉,并返回
|
|
*/
|
|
|
|
|
|
volatile struct list_head* get_new_frame_head(uint8 jpgnum,int grab){
|
|
uint8 frame_num = 0;
|
|
for(frame_num = 0;frame_num < JPEG_FRAME_NUM;frame_num++){
|
|
if(jpg_frame[jpgnum][frame_num].usable == 0){
|
|
jpg_frame[jpgnum][frame_num].usable = 1;
|
|
return &jpg_frame[jpgnum][frame_num].list;
|
|
}
|
|
|
|
}
|
|
|
|
if(grab) //是否开启抢占模式,开启抢占后,肯定有frame返回,上一帧没使用的frame肯定usable为2
|
|
{
|
|
|
|
for(frame_num = 0;frame_num < JPEG_FRAME_NUM;frame_num++){
|
|
if(jpg_frame[jpgnum][frame_num].usable == 2){
|
|
jpg_frame[jpgnum][frame_num].usable = 1;
|
|
free_get_node_list(&jpg_frame[jpgnum][frame_num].list,&free_tab[jpgnum]);
|
|
return &jpg_frame[jpgnum][frame_num].list;
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
/**@brief
|
|
* 获取当前frame根节点中保存成功的frame,返回根节点以供链表查询
|
|
*/
|
|
|
|
extern struct list_head *get_node(volatile struct list_head *head,volatile struct list_head *del);
|
|
extern uint32 get_addr(volatile struct list_head *list);
|
|
|
|
|
|
|
|
void set_frame_ready(jpeg_frame *jf){
|
|
jf->usable = 2;
|
|
}
|
|
|
|
|
|
/**@brief
|
|
* 将传入的frame根节点状态调整为空闲,以供下次重新获取
|
|
*/
|
|
void del_frame(uint8 jpg_num,volatile struct list_head* frame_list)
|
|
{
|
|
|
|
|
|
jpeg_frame* fl;
|
|
uint32_t flags;
|
|
if(list_empty((struct list_head *)frame_list) != TRUE){
|
|
//NVIC_DisableIRQ(MJPEG01_IRQn);
|
|
|
|
flags = disable_irq();
|
|
free_get_node_list(frame_list,&free_tab[jpg_num]);
|
|
fl = list_entry((struct list_head *)frame_list,jpeg_frame,list);
|
|
fl->usable = 0;
|
|
//NVIC_EnableIRQ(MJPEG01_IRQn);
|
|
enable_irq(flags);
|
|
return;
|
|
|
|
}else{
|
|
//NVIC_DisableIRQ(MJPEG01_IRQn);
|
|
flags = disable_irq();
|
|
fl = list_entry((struct list_head *)frame_list,jpeg_frame,list);
|
|
fl->usable = 0;
|
|
enable_irq(flags);
|
|
//NVIC_EnableIRQ(MJPEG01_IRQn);
|
|
return;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
/**@brief
|
|
* 初始化free_tab池,将mjpeg_node的节点都放到空闲池中,供frame后面提取使用
|
|
* @param ftb 空闲池头指针
|
|
* @param jpn mjpeg_node节点源
|
|
* @param use_num mjpeg_node的数量,即多少个mjpeg_node放到空闲池
|
|
* @param addr mjpeg_node的总buf起始地址
|
|
* @param buf_len 每个mjpeg_node所关联到的数据量
|
|
*/
|
|
void free_table_init(uint8 jpgnum,volatile struct list_head *ftb, volatile mjpeg_node* jpn,int use_num,uint32 addr,uint32 buf_len){
|
|
int itk;
|
|
for(itk = 0;itk < use_num;itk++){
|
|
if(jpgnum == 0)
|
|
jpn->buf_addr = (uint8*)(addr + itk*(buf_len+JPG0_TAIL_RESERVER)+JPG0_HEAD_RESERVER);
|
|
else
|
|
jpn->buf_addr = (uint8*)(addr + itk*(buf_len+JPG1_TAIL_RESERVER)+JPG1_HEAD_RESERVER);
|
|
|
|
list_add_tail((struct list_head *)&jpn->list,(struct list_head *)ftb);
|
|
jpn++;
|
|
}
|
|
}
|
|
|
|
|
|
/**@brief
|
|
* 从空间池中提取一个节点,放到队列中,并将此节点作为返回值返回
|
|
*/
|
|
struct list_head *get_node(volatile struct list_head *head,volatile struct list_head *del){
|
|
if(list_empty((struct list_head *)del)){
|
|
return 0;
|
|
}
|
|
|
|
list_move((struct list_head *)del->next,(struct list_head *)head);
|
|
|
|
return head->next; //返回最新的位置
|
|
}
|
|
|
|
|
|
int get_node_count(volatile struct list_head *head)
|
|
{
|
|
int count = 0;
|
|
struct list_head *first = (struct list_head *)head;
|
|
while(head->next != first)
|
|
{
|
|
head = head->next;
|
|
count++;
|
|
}
|
|
|
|
return count; //返回最新的位置
|
|
}
|
|
|
|
|
|
|
|
/**@brief
|
|
* 从当前使用的节点回放到消息池中
|
|
*/
|
|
bool put_node(volatile struct list_head *head,volatile struct list_head *del){
|
|
//portINIT_CRITICAL();
|
|
if(list_empty((struct list_head *)del)){
|
|
return 0;
|
|
}
|
|
uint32_t flags;
|
|
flags = disable_irq();
|
|
//NVIC_DisableIRQ(MJPEG01_IRQn);
|
|
list_move(del->next,(struct list_head *)head);
|
|
enable_irq(flags);
|
|
//NVIC_EnableIRQ(MJPEG01_IRQn);
|
|
|
|
return 1;
|
|
}
|
|
|
|
/**@brief
|
|
* 获取当前jpeg节点buf地址进行返回
|
|
*/
|
|
uint32 get_addr(volatile struct list_head *list){
|
|
mjpeg_node* mjn;
|
|
mjn = list_entry((struct list_head *)list,mjpeg_node,list);
|
|
return (uint32)mjn->buf_addr;
|
|
}
|
|
|
|
void jpg_DQT_updata(struct jpg_device *p_jpg, uint8 upOdown, uint8 diff)
|
|
{
|
|
uint32 *ptable;
|
|
static int8 pdqt_tab = DQT_DEF;
|
|
if (upOdown == 1)
|
|
{
|
|
pdqt_tab -= diff;
|
|
if (pdqt_tab < 0)
|
|
pdqt_tab = 0;
|
|
}
|
|
else
|
|
{
|
|
pdqt_tab += diff;
|
|
if (pdqt_tab > DQT_MAX_INDEX)
|
|
pdqt_tab = DQT_MAX_INDEX;
|
|
}
|
|
g_dqtable_index = pdqt_tab;
|
|
ptable = (uint32 *)quality_tab[pdqt_tab];
|
|
jpg_updata_dqt(p_jpg, ptable);
|
|
}
|
|
|
|
int jpg_quality_pidCtrl(int diff, int p, int i, int d)
|
|
{
|
|
static int diff_prev = 0;
|
|
static int diff_sum = 0;
|
|
int res = 0;
|
|
res = p * diff + i * diff_sum + d * (diff - diff_prev);
|
|
diff_sum += diff;
|
|
diff_prev = diff;
|
|
res = res>>16;
|
|
res = LIMITING(res, 120, -120);
|
|
diff_sum = LIMITING(diff_sum, 2000, -2000);
|
|
//_os_printf("diff_sum:%d\n",diff_sum);
|
|
return res;
|
|
}
|
|
|
|
extern volatile uint32 hs_isr;
|
|
volatile uint8 rtp_speed = 0; // 1:降低 2:提升
|
|
|
|
uint8 jpg_quality_tidy(uint8 jpgnum, uint32 len, uint8 *dqt_index_diff)
|
|
{
|
|
uint8 updata_dqt = 0;
|
|
if (qc_mode)
|
|
{
|
|
if (len >= 15 * 1024)
|
|
{
|
|
default_qt[jpgnum]++;
|
|
if (default_qt[jpgnum] == 0x10)
|
|
{
|
|
default_qt[jpgnum] = 0x8;
|
|
updata_dqt = 2;
|
|
}
|
|
}
|
|
else if (len <= 5 * 1024)
|
|
{
|
|
default_qt[jpgnum]--;
|
|
if (default_qt[jpgnum] == 0)
|
|
{
|
|
default_qt[jpgnum] = 8;
|
|
updata_dqt = 1;
|
|
}
|
|
}
|
|
return updata_dqt;
|
|
}
|
|
#if 0
|
|
if(len >= 25*1024){
|
|
default_qt[jpgnum]++;
|
|
if(default_qt[jpgnum] == 0x10){
|
|
if(g_dqtable_index < DQT_MAX_INDEX) {
|
|
default_qt[jpgnum] = 0x8;
|
|
updata_dqt = 2;
|
|
}
|
|
else
|
|
default_qt[jpgnum] = 0xf;
|
|
}
|
|
}else if(len <= 15*1024){
|
|
default_qt[jpgnum]--;
|
|
if(default_qt[jpgnum] == 0){
|
|
if(g_dqtable_index > 0) {
|
|
default_qt[jpgnum] = 8;
|
|
updata_dqt = 1;
|
|
}
|
|
else
|
|
default_qt[jpgnum] = 0x1;
|
|
}
|
|
}
|
|
*dqt_index_diff = 1;
|
|
#elif 1
|
|
int jpg_len_diff = len - TARGET_JPG_LEN;
|
|
int res = jpg_quality_pidCtrl(jpg_len_diff, QUALITY_CTRL_P, QUALITY_CTRL_I, QUALITY_CTRL_D);
|
|
uint8 qt_diff = os_abs(res) % 0x10;
|
|
uint8 qt_index_diff = os_abs(res) / 0x10;
|
|
*dqt_index_diff = qt_index_diff;
|
|
if (res > 0)
|
|
{
|
|
if (qt_diff + default_qt[jpgnum] > 0xf)
|
|
{
|
|
if ((g_dqtable_index + qt_index_diff + 1 + (qt_diff - (0xf - default_qt[jpgnum]))/8) > DQT_MAX_INDEX)
|
|
{
|
|
*dqt_index_diff = DQT_MAX_INDEX - g_dqtable_index;
|
|
default_qt[jpgnum] = 0xf;
|
|
}
|
|
else
|
|
{
|
|
default_qt[jpgnum] = 0x8 + (qt_diff - (0xf - default_qt[jpgnum]))%8;
|
|
*dqt_index_diff = qt_index_diff + 1 + (qt_diff - (0xf - default_qt[jpgnum]))/8;
|
|
}
|
|
}
|
|
else
|
|
default_qt[jpgnum] += qt_diff;
|
|
if ((*dqt_index_diff) >= 1 && g_dqtable_index < DQT_MAX_INDEX)
|
|
{
|
|
*dqt_index_diff = ((*dqt_index_diff) > (DQT_MAX_INDEX - g_dqtable_index)) ? (DQT_MAX_INDEX - g_dqtable_index) : (*dqt_index_diff);
|
|
updata_dqt = 2;
|
|
}
|
|
}
|
|
else if(res < 0)
|
|
{
|
|
if (default_qt[jpgnum] - qt_diff < 0)
|
|
{
|
|
if ((g_dqtable_index - (qt_index_diff + 1 + (qt_diff-default_qt[jpgnum])/8)) < 0)
|
|
{
|
|
*dqt_index_diff = g_dqtable_index;
|
|
default_qt[jpgnum] = 0;
|
|
}
|
|
else
|
|
{
|
|
default_qt[jpgnum] = 0x8 - (qt_diff - default_qt[jpgnum])%8; //(qt_diff-default_qt[jpgnum]) maybe > 0x8
|
|
*dqt_index_diff = qt_index_diff + 1 + (qt_diff-default_qt[jpgnum])/8;
|
|
}
|
|
}
|
|
else
|
|
default_qt[jpgnum] -= qt_diff;
|
|
if ((*dqt_index_diff) >= 1 && g_dqtable_index > 0)
|
|
{
|
|
*dqt_index_diff = ((*dqt_index_diff) > (g_dqtable_index)) ? g_dqtable_index : (*dqt_index_diff);
|
|
updata_dqt = 1;
|
|
}
|
|
}
|
|
if(updata_dqt == 0)
|
|
*dqt_index_diff = 0;
|
|
// _os_printf("pid res:%d %d %d %d %d %d\n", jpg_len_diff, res, qt_diff, qt_index_diff, *dqt_index_diff, updata_dqt);
|
|
#else
|
|
|
|
if (len >= 35 * 1024)
|
|
{
|
|
default_qt++;
|
|
if (default_qt == 0x10)
|
|
{
|
|
default_qt = 0x8;
|
|
updata_dqt = 2;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (rtp_speed == 1)
|
|
{
|
|
default_qt++;
|
|
if (default_qt == 0x10)
|
|
{
|
|
default_qt = 0x8;
|
|
updata_dqt = 2;
|
|
}
|
|
}
|
|
else if (rtp_speed == 2)
|
|
{
|
|
default_qt--;
|
|
if (default_qt == 0)
|
|
{
|
|
default_qt = 8;
|
|
updata_dqt = 1;
|
|
}
|
|
}
|
|
rtp_speed = 0;
|
|
}
|
|
#endif
|
|
return updata_dqt;
|
|
}
|
|
|
|
|
|
|
|
//获取实际内容buf的长度
|
|
int get_jpg_node_len(uint8 jpg_num)
|
|
{
|
|
if(jpg_num == 0)
|
|
{
|
|
return JPG0_BUF_LEN-JPG0_HEAD_RESERVER;
|
|
}
|
|
else
|
|
{
|
|
return JPG1_BUF_LEN-JPG1_HEAD_RESERVER;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
uint32 get_jpg_node_len_new(void *get_f)
|
|
{
|
|
jpeg_frame* jpg_frame = (jpeg_frame*)get_f;
|
|
if(jpg_frame->jpg_num == 0)
|
|
return JPG0_BUF_LEN-JPG0_HEAD_RESERVER;
|
|
else
|
|
return JPG1_BUF_LEN-JPG1_HEAD_RESERVER;
|
|
}
|
|
|
|
extern volatile uint8 scale_take_photo;
|
|
|
|
|
|
#if 0
|
|
extern uint8 video_psram_mem[616320];
|
|
extern uint8 video_psram_mem1[616320];
|
|
|
|
void location_reset(uint8_t *inbuf,uint8_t *outbuf,int x,int y,int w){
|
|
int xn,yn;
|
|
uint8_t yd,ud,vd;
|
|
//float angle;
|
|
//angle = (30*3.14)/180;
|
|
y = y*-1;
|
|
xn = (x * 866 - y * 499)/1000;
|
|
yn = (x * 499 + y * 866)/1000;
|
|
yn = yn*-1;
|
|
|
|
if(xn < 0){
|
|
return;
|
|
}
|
|
|
|
if(xn > 640){
|
|
return;
|
|
}
|
|
|
|
if(yn < 0){
|
|
return;
|
|
}
|
|
|
|
//yd = inbuf[x+y*w];
|
|
//ud = inbuf[307200+x/2+(y/2)*320];
|
|
//vd = inbuf[384000+x/2+(y/2)*320];
|
|
|
|
|
|
outbuf[xn+yn*w] = inbuf[x+y*w];
|
|
outbuf[307200+xn/2+(yn/2)*320]= inbuf[307200+x/2+(y/2)*320];
|
|
outbuf[384000+xn/2+(yn/2)*320]= inbuf[384000+x/2+(y/2)*320];
|
|
//if(xn+1 < 640)
|
|
{
|
|
if((unsigned char)outbuf[xn+1+yn*w] == 0x80){
|
|
outbuf[xn+1+(int)yn*w] = inbuf[x+y*w];
|
|
//if((xn+1)%2 == 0){
|
|
// outbuf[307200+xn/2+1+(yn/2)*320] = ud;
|
|
// outbuf[384000+xn/2+1+(yn/2)*320]= vd;
|
|
//}
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
#endif
|
|
|
|
#if 0
|
|
//认证或者用户学习使用
|
|
void jpeg_user(uint32* pixel_itp) //应用层
|
|
{
|
|
//#define TAKE_PHOTO_HIGH 1080//1080//2560//4320
|
|
//#define TAKE_PHOTO_WIDTH 1920//1920//3840//7680
|
|
uint16_t itp_w,itp_h;
|
|
uint8_t continous_spon;
|
|
struct scale_device *scale_dev;
|
|
struct lcdc_device *lcd_dev;
|
|
struct vpp_device *vpp_dev;
|
|
uint8 jpg_chose;
|
|
uint32 pingpang = 0;
|
|
uint32 count = 0;
|
|
uint32 flen;
|
|
uint32 itk;
|
|
struct list_head* get_f;
|
|
mjpeg_node* mjn;
|
|
jpeg_frame* jpf;
|
|
uint8 printf_dat = 0;
|
|
struct jpg_device *jpeg_dev;
|
|
jpeg_dev = (struct jpg_device *)dev_get(HG_JPG0_DEVID);
|
|
scale_dev = (struct scale_device *)dev_get(HG_SCALE1_DEVID);
|
|
lcd_dev = (struct lcdc_device *)dev_get(HG_LCDC_DEVID);
|
|
vpp_dev = (struct vpp_device *)dev_get(HG_VPP_DEVID);
|
|
itp_w = pixel_itp[0]&0xffff;
|
|
itp_h = (pixel_itp[0]>>16)&0xffff;
|
|
continous_spon = pixel_itp[1];
|
|
scale_close(scale_dev);
|
|
jpg_close(jpeg_dev);
|
|
os_sleep_ms(100);
|
|
jpg_cfg(HG_JPG0_DEVID,SCALER_DATA);
|
|
_os_printf("itp_w:%d itp_h:%d continous_spon:%d\r\n",itp_w,itp_h,continous_spon);
|
|
photo_msg.out0_w = itp_w;
|
|
photo_msg.out0_h = itp_h;
|
|
jpg_start(HG_JPG0_DEVID);
|
|
if(itp_h <= 720){
|
|
scale_from_vpp_to_jpg(scale_dev,yuvbuf,photo_msg.in_w,photo_msg.in_h,itp_w,itp_h);
|
|
}
|
|
|
|
while(1){
|
|
if(itp_h > 720){
|
|
if(m2m1_mutex.magic == 0xa8b4c2d5)
|
|
os_mutex_lock(&m2m1_mutex,osWaitForever);
|
|
|
|
lcdc_video_enable_auto_ks(lcd_dev,1);
|
|
scale_from_soft_to_jpg(scale_dev,psram_ybuf_src,photo_msg.in_w,photo_msg.in_h,itp_w,itp_h);
|
|
scale_take_photo = 0;
|
|
while(scale_take_photo == 0){
|
|
os_sleep_ms(2);
|
|
}
|
|
|
|
if(m2m1_mutex.magic == 0xa8b4c2d5)
|
|
os_mutex_unlock(&m2m1_mutex);
|
|
|
|
os_sleep_ms(10);
|
|
lcdc_video_enable_auto_ks(lcd_dev,0);
|
|
vpp_open(vpp_dev);
|
|
}
|
|
|
|
|
|
get_f = get_frame(HG_JPG0_DEVID);
|
|
jpg_chose = 0;
|
|
|
|
if(get_f){
|
|
fatfs_create_jpg();
|
|
_os_printf("usr(%d)====>get_f:%x\r\n",jpg_chose,(uint32)get_f);
|
|
count++;
|
|
usr_p[jpg_chose] = get_f;
|
|
|
|
jpf = list_entry(get_f,jpeg_frame,list);
|
|
flen = jpf->frame_len;
|
|
|
|
_os_printf("flen_write:%d\r\n",flen);
|
|
while(list_empty((struct list_head *)usr_p[jpg_chose]) != TRUE)
|
|
{
|
|
mjn = list_entry((struct list_head *)usr_p[jpg_chose]->next,mjpeg_node,list);
|
|
|
|
//_os_printf("mjn:%x\r\n",mjn);
|
|
/*
|
|
此处使用当前mjn,获取节点对应的buf数据位置,对数据进行处理
|
|
*/
|
|
if(jpg_chose){
|
|
if(flen > JPG1_BUF_LEN){
|
|
//fatfs_write_data(mjn->buf_addr,JPG1_BUF_LEN);
|
|
osal_fwrite(mjn->buf_addr,1,JPG1_BUF_LEN,&fp_jpg);
|
|
flen -= get_jpg_node_len(jpg_chose);
|
|
}
|
|
else{
|
|
//for(itk = 0;itk < flen+JPG1_HEAD_RESERVER;itk++){
|
|
// _os_printf("%02x ",mjn->buf_addr[itk-JPG1_HEAD_RESERVER]);
|
|
//}
|
|
//fatfs_write_data(mjn->buf_addr,flen);
|
|
osal_fwrite(mjn->buf_addr,1,flen,&fp_jpg);
|
|
flen = 0;
|
|
}
|
|
}else{
|
|
if(flen > JPG0_BUF_LEN){
|
|
//for(itk = 0;itk < JPG0_BUF_LEN;itk++){
|
|
// _os_printf("%02x ",mjn->buf_addr[itk-JPG0_HEAD_RESERVER]);
|
|
//}
|
|
//fatfs_write_data(mjn->buf_addr,JPG0_BUF_LEN);
|
|
osal_fwrite(mjn->buf_addr,1,JPG0_BUF_LEN,&fp_jpg);
|
|
flen -= get_jpg_node_len(jpg_chose);
|
|
}
|
|
else{
|
|
//for(itk = 0;itk < flen+JPG0_HEAD_RESERVER;itk++){
|
|
// _os_printf("%02x ",mjn->buf_addr[itk-JPG0_HEAD_RESERVER]);
|
|
//}
|
|
//fatfs_write_data(mjn->buf_addr,flen);
|
|
osal_fwrite(mjn->buf_addr,1,flen,&fp_jpg);
|
|
flen = 0;
|
|
}
|
|
}
|
|
put_node(&free_tab[jpg_chose],usr_p[jpg_chose]); //节点归还到free_tab,边处理边给下一帧释放空间
|
|
}
|
|
_os_printf("flen_write_end:%d\r\n",flen);
|
|
del_frame(jpg_chose,usr_p[jpg_chose]); //删除frame
|
|
fatfs_close_jpg();
|
|
if(count == continous_spon)
|
|
break;
|
|
}
|
|
}
|
|
csi_kernel_task_del(csi_kernel_task_get_cur());
|
|
}
|
|
#endif
|
|
extern void take_photo_thread(void *d);
|
|
uint32_t takephoto_arg[3] = {0};
|
|
void take_photo_thread_init(uint16_t w,uint16_t h,uint8_t continuous_spot){
|
|
takephoto_arg[0] = (w&0xffff) | ((h<<16)&0xffff0000);
|
|
takephoto_arg[1] = continuous_spot;
|
|
takephoto_arg[2] = 1;
|
|
os_task_create("take_photo_thread", take_photo_thread, (void*)&takephoto_arg, OS_TASK_PRIORITY_NORMAL, 0, NULL, 1024);
|
|
}
|
|
|
|
uint32_t get_takephoto_thread_status()
|
|
{
|
|
return takephoto_arg[2];
|
|
}
|
|
|
|
|
|
|
|
|
|
void jpg_room_init(uint8 jpgnum){
|
|
//INIT_LIST_HEAD(&jpg_node);
|
|
uint8 *buf;
|
|
|
|
if(jpgnum == 0)
|
|
{
|
|
|
|
if(global_jpg0_buf)
|
|
{
|
|
os_printf("0please custom_free jpg_buf when custom_malloc again\n");
|
|
return ;
|
|
}
|
|
|
|
#ifdef PSRAM_HEAP
|
|
buf = (uint8*)custom_malloc_psram(JPG0_NODE*(JPG0_BUF_LEN+JPG0_TAIL_RESERVER));
|
|
#else
|
|
buf = (uint8*)custom_malloc(JPG0_NODE*(JPG0_BUF_LEN+JPG0_TAIL_RESERVER));
|
|
#endif
|
|
global_jpg0_buf = buf;
|
|
//sys_dcache_clean_invalid_range((void *)buf, JPG0_NODE*(JPG0_BUF_LEN+JPG0_TAIL_RESERVER));
|
|
}
|
|
else
|
|
{
|
|
|
|
if(global_jpg1_buf)
|
|
{
|
|
os_printf("1please custom_free jpg_buf when custom_malloc again\n");
|
|
return ;
|
|
}
|
|
#ifdef PSRAM_HEAP
|
|
buf = (uint8*)custom_malloc_psram(JPG1_NODE*(JPG1_BUF_LEN+JPG1_TAIL_RESERVER));
|
|
#else
|
|
buf = (uint8*)custom_malloc(JPG1_NODE*(JPG1_BUF_LEN+JPG1_TAIL_RESERVER));
|
|
#endif
|
|
global_jpg1_buf = buf;
|
|
//sys_dcache_clean_invalid_range((void *)buf, JPG1_NODE*(JPG1_BUF_LEN+JPG1_TAIL_RESERVER));
|
|
}
|
|
|
|
while(!buf)
|
|
{
|
|
os_printf("%s:%d\n",__FUNCTION__,__LINE__);
|
|
os_sleep_ms(1000);
|
|
}
|
|
|
|
INIT_LIST_HEAD((struct list_head *)&jpg_frame[jpgnum][0].list);
|
|
INIT_LIST_HEAD((struct list_head *)&jpg_frame[jpgnum][1].list);
|
|
INIT_LIST_HEAD((struct list_head *)&free_tab[jpgnum]);
|
|
|
|
if(jpgnum == 0)
|
|
free_table_init(jpgnum,&free_tab[jpgnum],(mjpeg_node*)&jpg0_node_src,JPG0_NODE,(uint32)buf,JPG0_BUF_LEN);
|
|
else
|
|
free_table_init(jpgnum,&free_tab[jpgnum],(mjpeg_node*)&jpg1_node_src,JPG1_NODE,(uint32)buf,JPG1_BUF_LEN);
|
|
jpg_frame[jpgnum][0].usable = 0;
|
|
jpg_frame[jpgnum][1].usable = 0;
|
|
|
|
|
|
|
|
|
|
jpg_frame[jpgnum][0].jpg_num = jpgnum;
|
|
jpg_frame[jpgnum][1].jpg_num = jpgnum;
|
|
|
|
|
|
jpg_f_p[jpgnum] = get_new_frame_head(jpgnum,1); //预先分配第一frame,待帧结束的时候再分配下一frame
|
|
jpg_p[jpgnum] = jpg_f_p[jpgnum];
|
|
}
|
|
|
|
|
|
uint8_t jpg_room_deinit(uint8 jpgnum)
|
|
{
|
|
if(jpgnum == 0)
|
|
{
|
|
if(global_jpg0_buf)
|
|
{
|
|
#ifndef PSRAM_HEAP
|
|
custom_free(global_jpg0_buf);
|
|
#else
|
|
custom_free_psram(global_jpg0_buf);
|
|
#endif
|
|
global_jpg0_buf = NULL;
|
|
}
|
|
}
|
|
else if(jpgnum == 1)
|
|
{
|
|
if(global_jpg1_buf)
|
|
{
|
|
#ifndef PSRAM_HEAP
|
|
custom_free(global_jpg1_buf);
|
|
#else
|
|
custom_free_psram(global_jpg1_buf);
|
|
#endif
|
|
global_jpg1_buf = NULL;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*********************************
|
|
获取分辨率
|
|
0:无效
|
|
1:vga(640x480)
|
|
2:720p(1280x720)
|
|
*********************************/
|
|
uint8 get_camera_dpi()
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
|
|
void jpg_outbuff_full_isr(uint32 irq_flag,uint32 irq_data,uint32 param1,uint32 param2){
|
|
uint8 jpg_chose;
|
|
uint32 addr;
|
|
struct jpg_device *p_jpg = (struct jpg_device *)irq_data;
|
|
if(p_jpg == jpeg_dev_global[0]){
|
|
jpg_chose = 0;
|
|
}else{
|
|
jpg_chose = 1;
|
|
}
|
|
|
|
|
|
if(outbuff_isr[jpg_chose] != 0xff)
|
|
outbuff_isr[jpg_chose]++;
|
|
else
|
|
return;
|
|
|
|
|
|
|
|
jpg_p[jpg_chose] = get_node(jpg_p[jpg_chose],&free_tab[jpg_chose]);
|
|
if(jpg_p[jpg_chose] == NULL){
|
|
outbuff_isr[jpg_chose] = 0xff;
|
|
return;
|
|
}
|
|
|
|
// if((jpg_addr_num%2) == 0){
|
|
// data_cmp_u32(jpg_addr0,psram_example_buf+1284*jpg_addr_num,1284);
|
|
// }else{
|
|
// data_cmp_u32(jpg_addr1,psram_example_buf+1284*jpg_addr_num,1284);
|
|
// }
|
|
|
|
// jpg_addr_num++;
|
|
|
|
|
|
addr = get_addr(jpg_p[jpg_chose]);
|
|
jpg_set_addr(p_jpg,addr,get_jpg_node_len(jpg_chose));
|
|
sys_dcache_clean_invalid_range((uint32_t *)addr, get_jpg_node_len(jpg_chose));
|
|
//os_printf("OF-%x \r\n",addr);
|
|
// if((jpg_addr_num%2) == 1){
|
|
// jpg_addr0 = addr;
|
|
// }else{
|
|
// jpg_addr1 = addr;
|
|
// }
|
|
}
|
|
|
|
void jpg_buf_err(uint32 irq_flag,uint32 irq_data,uint32 param1,uint32 param2){
|
|
uint8 jpg_chose;
|
|
struct scale_device *scale_dev;
|
|
uint32 addr;
|
|
struct jpg_device *p_jpg = (struct jpg_device *)irq_data;
|
|
scale_dev = (struct scale_device *)dev_get(HG_SCALE1_DEVID);
|
|
if(p_jpg == jpeg_dev_global[0]){
|
|
jpg_chose = 0;
|
|
}else{
|
|
jpg_chose = 1;
|
|
}
|
|
jpg_close(p_jpg);
|
|
if(jpg_chose == 0)
|
|
scale_close(scale_dev);
|
|
// dvp_close(dvp_test);
|
|
_os_printf("(%d)?\r\n",jpg_chose);
|
|
del_frame(jpg_chose,jpg_f_p[jpg_chose]);
|
|
|
|
jpg_f_p[jpg_chose] = get_new_frame_head(jpg_chose,1);
|
|
jpg_p[jpg_chose] = jpg_f_p[jpg_chose];
|
|
outbuff_isr[jpg_chose] = 0;
|
|
|
|
jpg_p[jpg_chose] = get_node(jpg_p[jpg_chose],&free_tab[jpg_chose]); //预分配的两个buf地址,帧结束的时候要去掉一个预分配节点
|
|
if(jpg_p[jpg_chose] == NULL){
|
|
_os_printf("need more node for new frame start1\r\n");
|
|
while(1);
|
|
}
|
|
//p_jpg->DMA_TADR0 = get_addr(jpg_p);
|
|
addr = get_addr(jpg_p[jpg_chose]);
|
|
//jpg_set_addr0(p_jpg,addr);
|
|
jpg_set_addr(p_jpg,addr,get_jpg_node_len(jpg_chose));
|
|
sys_dcache_clean_invalid_range((uint32_t *)addr, get_jpg_node_len(jpg_chose));
|
|
jpg_p[jpg_chose] = get_node(jpg_p[jpg_chose],&free_tab[jpg_chose]);
|
|
if(jpg_p[jpg_chose] == NULL){
|
|
_os_printf("need more node for new frame start2\r\n");
|
|
while(1);
|
|
}
|
|
//p_jpg->DMA_TADR1 = get_addr(jpg_p);
|
|
addr = get_addr(jpg_p[jpg_chose]);
|
|
//jpg_set_addr1(p_jpg,addr);
|
|
jpg_set_addr(p_jpg,addr,get_jpg_node_len(jpg_chose));
|
|
sys_dcache_clean_invalid_range((uint32_t *)addr, get_jpg_node_len(jpg_chose));
|
|
jpg_open(p_jpg);
|
|
if(jpg_chose == 0)
|
|
scale_open(scale_dev);
|
|
|
|
|
|
|
|
|
|
// dvp_open(dvp_test);
|
|
|
|
|
|
}
|
|
|
|
void jpg_done_isr(uint32 irq_flag,uint32 irq_data,uint32 param1,uint32 param2){
|
|
uint8 jpg_chose;
|
|
struct jpg_device *p_jpg = (struct jpg_device *)irq_data;
|
|
|
|
uint32 addr;
|
|
jpeg_frame* jf;
|
|
uint8 out_buf_num_err = 0;
|
|
uint8 updata_dqt = 0;
|
|
uint8 default_qt_last;
|
|
uint32 jpg_len;
|
|
|
|
uint8 dqt_index_diff = 0;
|
|
|
|
if(p_jpg == jpeg_dev_global[0]){
|
|
jpg_chose = 0;
|
|
}else{
|
|
jpg_chose = 1;
|
|
}
|
|
|
|
|
|
jpg_len = param1;//jpg_get_len(p_jpg);
|
|
//os_printf("len(%d)=>:%d ",jpg_chose,jpg_len);
|
|
//if(outbuff_isr != jpg_get_outbuf_num(p_jpg))
|
|
if(param2||(outbuff_isr[jpg_chose] == 255)){
|
|
os_printf("jpg done len err:%d\r\n",outbuff_isr[jpg_chose]);
|
|
out_buf_num_err = 1;
|
|
}
|
|
default_qt_last = default_qt[jpg_chose];
|
|
// os_printf("jpglen:%d %d %d\n", jpg_len, default_qt[jpg_chose], g_dqtable_index);
|
|
updata_dqt = jpg_quality_tidy(jpg_chose, jpg_len, &dqt_index_diff);
|
|
if (default_qt_last != default_qt[jpg_chose])
|
|
{
|
|
jpg_set_qt(p_jpg, default_qt[jpg_chose]);
|
|
}
|
|
// os_printf("quality res:%d %s%d\n", default_qt[jpg_chose], ((updata_dqt>1)?"+":"-"),dqt_index_diff);
|
|
if (get_node_count(&free_tab[jpg_chose]) < 2)
|
|
{
|
|
outbuff_isr[jpg_chose] = 0xff;
|
|
}
|
|
/**/
|
|
if(jpg_len < outbuff_isr[jpg_chose] * get_jpg_node_len(jpg_chose)){
|
|
os_printf("BUF len err:%d %d\r\n",jpg_len,outbuff_isr[jpg_chose] * get_jpg_node_len(jpg_chose));
|
|
del_frame(jpg_chose,jpg_f_p[jpg_chose]);
|
|
}else if(outbuff_isr[jpg_chose] == 0xff){
|
|
os_printf("outbuff_isr err,no room\r\n");
|
|
del_frame(jpg_chose,jpg_f_p[jpg_chose]);
|
|
}else if(out_buf_num_err){
|
|
os_printf("out_buf_num_err happen\r\n");
|
|
del_frame(jpg_chose,jpg_f_p[jpg_chose]);
|
|
}
|
|
else{
|
|
//帧OK
|
|
|
|
jf = list_entry((struct list_head *)jpg_f_p[jpg_chose],jpeg_frame,list);
|
|
jf->frame_len = jpg_len;
|
|
|
|
//因为有预分配机制,所以要先去掉最后一个节点
|
|
put_node(&free_tab[jpg_chose],jpg_p[jpg_chose]->prev);
|
|
set_frame_ready(jf);
|
|
//os_printf("jf_ready:%x jpg_chose:%d\r\n",jf,jpg_chose);
|
|
}
|
|
|
|
jpg_f_p[jpg_chose] = get_new_frame_head(jpg_chose,1);
|
|
//os_printf("jpg_f_p[jpg_chose]:%X\n",jpg_f_p[jpg_chose]);
|
|
jpg_p[jpg_chose] = jpg_f_p[jpg_chose];
|
|
outbuff_isr[jpg_chose] = 0;
|
|
//再设置DMA地址
|
|
jpg_p[jpg_chose] = get_node(jpg_p[jpg_chose],&free_tab[jpg_chose]); //预分配的两个buf地址,帧结束的时候要去掉一个预分配节点
|
|
if(jpg_p[jpg_chose] == NULL){
|
|
_os_printf("need more node for new frame start1\r\n");
|
|
while(1);
|
|
}
|
|
//p_jpg->DMA_TADR0 = get_addr(jpg_p);
|
|
addr = get_addr(jpg_p[jpg_chose]);
|
|
jpg_set_addr(p_jpg,addr,get_jpg_node_len(jpg_chose));
|
|
sys_dcache_clean_invalid_range((uint32_t *)addr, get_jpg_node_len(jpg_chose));
|
|
jpg_p[jpg_chose] = get_node(jpg_p[jpg_chose],&free_tab[jpg_chose]);
|
|
if(jpg_p[jpg_chose] == NULL){
|
|
_os_printf("need more node for new frame start2\r\n");
|
|
while(1);
|
|
}
|
|
//os_printf("addr:%x \r\n",addr);
|
|
addr = get_addr(jpg_p[jpg_chose]);
|
|
jpg_set_addr(p_jpg,addr,get_jpg_node_len(jpg_chose));
|
|
sys_dcache_clean_invalid_range((uint32_t *)addr, get_jpg_node_len(jpg_chose));
|
|
if (updata_dqt)
|
|
jpg_DQT_updata(p_jpg, updata_dqt, dqt_index_diff);
|
|
}
|
|
|
|
volatile uint8_t pixel_done = 0;
|
|
#if PRC_EN
|
|
void jpg_pixel_done(uint32 irq_flag,uint32 irq_data,uint32 param1,uint32 param2){
|
|
pixel_done = 1;
|
|
//为了旧版本兼容,暂时用宏隔离
|
|
#if DVP_EN
|
|
if(!vfx_open) {
|
|
return;
|
|
}
|
|
#else
|
|
if(0)
|
|
{
|
|
|
|
}
|
|
#endif
|
|
else {
|
|
if(stjr_itk < 30) {
|
|
hw_memcpy((void*)stjr_linebuf,(void*)(stjr_yuvbuf+stjr_itk*16* sw_jpg_w), sw_jpg_w*16);
|
|
prc_set_yaddr(stjr_prc_dev,(uint32)stjr_linebuf);
|
|
hw_memcpy((void*)(stjr_linebuf+ sw_jpg_w*16),(void*)(stjr_yuvbuf+ sw_jpg_w*sw_jpg_h+stjr_itk*4* sw_jpg_w), sw_jpg_w*4);
|
|
prc_set_uaddr(stjr_prc_dev,(uint32)(stjr_linebuf+ sw_jpg_w*16));
|
|
hw_memcpy((void*)(stjr_linebuf+ sw_jpg_w*16+4*sw_jpg_w),(void*)(stjr_yuvbuf+ sw_jpg_w*sw_jpg_h+ sw_jpg_w*sw_jpg_h/4+stjr_itk*4* sw_jpg_w), sw_jpg_w*4);
|
|
prc_set_vaddr(stjr_prc_dev,(uint32)(stjr_linebuf+ sw_jpg_w*16+4* sw_jpg_w));
|
|
jpg_soft_kick(stjr_jpeg_dev,1);
|
|
stjr_itk++;
|
|
} else {
|
|
os_sema_up(jpg_sema_pd);
|
|
stjr_itk = 0;
|
|
}
|
|
}
|
|
|
|
}
|
|
#endif
|
|
|
|
void jpg_config_addr(struct jpg_device *p_jpg,uint8 jpgnum){
|
|
uint32 addr;
|
|
jpg_p[jpgnum] = get_node(jpg_p[jpgnum],&free_tab[jpgnum]); //预分配的两个buf地址,帧结束的时候要去掉一个预分配节点
|
|
addr = get_addr(jpg_p[jpgnum]);
|
|
jpg_set_addr(p_jpg,addr,get_jpg_node_len(jpgnum));
|
|
sys_dcache_clean_invalid_range((uint32_t *)addr, get_jpg_node_len(jpgnum));
|
|
jpg_p[jpgnum] = get_node(jpg_p[jpgnum],&free_tab[jpgnum]);
|
|
addr = get_addr(jpg_p[jpgnum]);
|
|
jpg_set_addr(p_jpg,addr,get_jpg_node_len(jpgnum));
|
|
sys_dcache_clean_invalid_range((uint32_t *)addr, get_jpg_node_len(jpgnum));
|
|
}
|
|
|
|
void jpg_isr_init(struct jpg_device *p_jpg){
|
|
jpg_request_irq(p_jpg,(jpg_irq_hdl )&jpg_outbuff_full_isr,JPG_IRQ_FLAG_JPG_BUF_FULL,p_jpg);
|
|
jpg_request_irq(p_jpg,(jpg_irq_hdl )&jpg_buf_err,JPG_IRQ_FLAG_ERROR,p_jpg);
|
|
jpg_request_irq(p_jpg,(jpg_irq_hdl )&jpg_done_isr,JPG_IRQ_FLAG_JPG_DONE,p_jpg);
|
|
#if PRC_EN
|
|
jpg_request_irq(p_jpg,(jpg_irq_hdl )&jpg_pixel_done,JPG_IRQ_FLAG_PIXEL_DONE,p_jpg);
|
|
#endif
|
|
NVIC_EnableIRQ(MJPEG01_IRQn);
|
|
}
|
|
|
|
|
|
//专门为从yuv在psram,然后编码成jpg的模式
|
|
//利用prc模块寄存器但不属于prc功能
|
|
//为了兼容,仅仅对JPG_IRQ_FLAG_PIXEL_DONE的done的参数修改,其他不变
|
|
typedef int32_t (*jpg_pixel_done_prc)(uint32 irq_flag,uint32 irq_data,uint32 param1,uint32 param2);
|
|
void jpg_isr_init_prc(struct jpg_device *p_jpg,jpg_pixel_done_prc done_prc,void *param){
|
|
jpg_request_irq(p_jpg,(jpg_irq_hdl )&jpg_outbuff_full_isr,JPG_IRQ_FLAG_JPG_BUF_FULL,p_jpg);
|
|
jpg_request_irq(p_jpg,(jpg_irq_hdl )&jpg_buf_err,JPG_IRQ_FLAG_ERROR,p_jpg);
|
|
jpg_request_irq(p_jpg,(jpg_irq_hdl )&jpg_done_isr,JPG_IRQ_FLAG_JPG_DONE,p_jpg);
|
|
jpg_request_irq(p_jpg,done_prc,JPG_IRQ_FLAG_PIXEL_DONE,param);
|
|
NVIC_EnableIRQ(MJPEG01_IRQn);
|
|
}
|
|
|
|
//不需要JPG_IRQ_FLAG_PIXEL_DONE中断
|
|
void jpg_isr_init_vpp(struct jpg_device *p_jpg){
|
|
jpg_request_irq(p_jpg,(jpg_irq_hdl )&jpg_outbuff_full_isr,JPG_IRQ_FLAG_JPG_BUF_FULL,p_jpg);
|
|
jpg_request_irq(p_jpg,(jpg_irq_hdl )&jpg_buf_err,JPG_IRQ_FLAG_ERROR,p_jpg);
|
|
jpg_request_irq(p_jpg,(jpg_irq_hdl )&jpg_done_isr,JPG_IRQ_FLAG_JPG_DONE,p_jpg);
|
|
jpg_request_irq(p_jpg,(jpg_irq_hdl)NULL,JPG_IRQ_FLAG_PIXEL_DONE,NULL);
|
|
NVIC_EnableIRQ(MJPEG01_IRQn);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void jpg_cfg_prc(uint8 jpgid,enum JPG_SRC_FROM src_from,jpg_pixel_done_prc done_prc,void *dev_id){
|
|
uint8 jpg_chose;
|
|
//uint32 itk,jtk;
|
|
_os_printf("JPG start:%d\r\n",src_from);
|
|
struct jpg_device *jpeg_dev;
|
|
if(jpgid == HG_JPG0_DEVID)
|
|
jpg_chose = 0;
|
|
else
|
|
jpg_chose = 1;
|
|
|
|
jpeg_dev = (struct jpg_device *)dev_get(jpgid);
|
|
jpeg_dev_global[jpg_chose] = jpeg_dev;
|
|
|
|
//jpg table init
|
|
jpg_init(jpeg_dev,DQT_DEF,default_qt[jpg_chose]);
|
|
|
|
jpg_set_data_from(jpeg_dev,src_from);
|
|
jpg_set_hw_check(jpeg_dev,1);
|
|
jpg_isr_init_prc(jpeg_dev,done_prc,dev_id);
|
|
jpg_set_init_finish(jpeg_dev,1);
|
|
}
|
|
|
|
void jpg_cfg(uint8 jpgid,enum JPG_SRC_FROM src_from){
|
|
uint8 jpg_chose;
|
|
//uint32 itk,jtk;
|
|
_os_printf("JPG start\r\n");
|
|
struct jpg_device *jpeg_dev;
|
|
if(jpgid == HG_JPG0_DEVID)
|
|
jpg_chose = 0;
|
|
else
|
|
jpg_chose = 1;
|
|
|
|
jpeg_dev = (struct jpg_device *)dev_get(jpgid);
|
|
jpeg_dev_global[jpg_chose] = jpeg_dev;
|
|
|
|
//jpg table init
|
|
jpg_init(jpeg_dev,DQT_DEF,default_qt[jpg_chose]);
|
|
|
|
jpg_set_data_from(jpeg_dev,src_from);
|
|
jpg_set_hw_check(jpeg_dev,1);
|
|
jpg_isr_init(jpeg_dev);
|
|
jpg_set_init_finish(jpeg_dev,1);
|
|
}
|
|
|
|
void jpg_cfg_vpp(uint8 jpgid,enum JPG_SRC_FROM src_from){
|
|
uint8 jpg_chose;
|
|
//uint32 itk,jtk;
|
|
_os_printf("JPG start\r\n");
|
|
struct jpg_device *jpeg_dev;
|
|
if(jpgid == HG_JPG0_DEVID)
|
|
jpg_chose = 0;
|
|
else
|
|
jpg_chose = 1;
|
|
|
|
jpeg_dev = (struct jpg_device *)dev_get(jpgid);
|
|
jpeg_dev_global[jpg_chose] = jpeg_dev;
|
|
|
|
//jpg table init
|
|
jpg_init(jpeg_dev,DQT_DEF,default_qt[jpg_chose]);
|
|
|
|
jpg_set_data_from(jpeg_dev,src_from);
|
|
jpg_set_hw_check(jpeg_dev,1);
|
|
jpg_isr_init_vpp(jpeg_dev);
|
|
jpg_set_init_finish(jpeg_dev,1);
|
|
}
|
|
|
|
|
|
static int opcode_func(stream *s,void *priv,int opcode)
|
|
{
|
|
int res = 0;
|
|
//_os_printf("%s:%d\topcode:%d\n",__FUNCTION__,__LINE__,opcode);
|
|
switch(opcode)
|
|
{
|
|
case STREAM_OPEN_ENTER:
|
|
break;
|
|
case STREAM_OPEN_EXIT:
|
|
{
|
|
enable_stream(s,1);
|
|
}
|
|
break;
|
|
case STREAM_OPEN_FAIL:
|
|
break;
|
|
default:
|
|
//默认都返回成功
|
|
break;
|
|
}
|
|
return res;
|
|
}
|
|
|
|
uint32_t get_jpg_default_dpi(uint8_t id)
|
|
{
|
|
if(id == 0)
|
|
{
|
|
return (photo_msg.out0_w<<16 | photo_msg.out0_h);
|
|
}
|
|
else
|
|
{
|
|
return (photo_msg.out1_w<<16 | photo_msg.out1_h);
|
|
}
|
|
}
|
|
|
|
extern uint8_t vga_room[2][640*480+640*480/2];
|
|
//uint8_t soft_linebuf[16*640+8*640]__attribute__ ((aligned(4)));
|
|
void soft_to_jpg_cfg(uint32 w,uint32 h){
|
|
photo_msg.out0_h = h;
|
|
photo_msg.out0_w = w;
|
|
jpg_cfg(HG_JPG0_DEVID,SOFT_DATA);
|
|
if(jpg_sema_pd == NULL)
|
|
{
|
|
jpg_sema_pd = os_malloc(sizeof(struct os_semaphore));
|
|
os_sema_init(jpg_sema_pd, 0);
|
|
}
|
|
else
|
|
{
|
|
os_sema_del(jpg_sema_pd);
|
|
os_sema_init(jpg_sema_pd, 0);
|
|
}
|
|
|
|
}
|
|
|
|
#if PRC_EN
|
|
void soft_to_jpg_run(uint32 yuvbuf,uint32 linebuf,uint32 w,uint32 h){
|
|
|
|
stjr_prc_dev = (struct prc_device*)dev_get(HG_PRC_DEVID);
|
|
stjr_jpeg_dev = (struct jpg_device *)dev_get(HG_JPG0_DEVID);
|
|
stjr_linebuf = linebuf;
|
|
stjr_yuvbuf = yuvbuf;
|
|
sw_jpg_w = w;
|
|
sw_jpg_h = h;
|
|
stjr_itk = 0;
|
|
stjr_tick = os_jiffies();
|
|
hw_memcpy((void*)(stjr_linebuf),(void*)(stjr_yuvbuf+stjr_itk*16* sw_jpg_w), sw_jpg_w*16);
|
|
prc_set_yaddr(stjr_prc_dev,(uint32)stjr_linebuf);
|
|
hw_memcpy((void*)(stjr_linebuf+ sw_jpg_w*16),(void*)(stjr_yuvbuf+ sw_jpg_w*sw_jpg_h+stjr_itk*4* sw_jpg_w), sw_jpg_w*4);
|
|
prc_set_uaddr(stjr_prc_dev,(uint32)(stjr_linebuf+ sw_jpg_w*16));
|
|
hw_memcpy((void*)(stjr_linebuf+ sw_jpg_w*16+4*sw_jpg_w),(void*)(stjr_yuvbuf+ sw_jpg_w*sw_jpg_h+ sw_jpg_w*sw_jpg_h/4+stjr_itk*4* sw_jpg_w), sw_jpg_w*4);
|
|
prc_set_vaddr(stjr_prc_dev,(uint32)(stjr_linebuf+ sw_jpg_w*16+4* sw_jpg_w));
|
|
stjr_itk++;
|
|
pixel_done = 0;
|
|
jpg_soft_kick(stjr_jpeg_dev,1);
|
|
os_sema_down(jpg_sema_pd, 50);
|
|
}
|
|
|
|
|
|
extern void yuv_add_time_watermark(uint8_t *src,uint32_t w,uint32_t h,uint8_t cw,uint8_t ch,uint32_t x_s,uint32_t y_s,uint32_t year,uint8_t month,uint8_t day,uint8_t hour,uint8_t min,uint8_t sec);
|
|
extern uint8_t *vfx_linebuf;
|
|
void start_jpeg();
|
|
void soft_to_jpg_thread(){
|
|
struct data_structure *get_f = NULL;
|
|
struct stream_jpeg_data_s *dest_list;
|
|
struct stream_jpeg_data_s *dest_list_tmp;
|
|
stream *s = NULL;
|
|
uint32_t node_len;
|
|
uint32_t flen;
|
|
uint8_t *jpeg_buf_addr = NULL;
|
|
os_sleep_ms(1000);
|
|
s = open_stream_available(R_RTP_JPEG,0,8,opcode_func,NULL);
|
|
|
|
soft_to_jpg_cfg(640,480);
|
|
|
|
if(vfx_linebuf == NULL)
|
|
vfx_linebuf = os_malloc(16*640+8*640);
|
|
if(vfx_linebuf == NULL){
|
|
os_printf("error....vfx malloc...\r\n");
|
|
}
|
|
vfx_open = 1;
|
|
start_jpeg();
|
|
while(1){
|
|
get_f = recv_real_data(s);
|
|
if(get_f){
|
|
dest_list = (struct stream_jpeg_data_s *)GET_DATA_BUF(get_f);
|
|
dest_list_tmp = dest_list;
|
|
flen = get_stream_real_data_len(get_f);
|
|
node_len = GET_NODE_LEN(get_f);
|
|
jpeg_buf_addr = (uint8_t *)GET_JPG_BUF(get_f);
|
|
free_data(get_f);
|
|
get_f = NULL;
|
|
|
|
}else{
|
|
os_sleep_ms(15);
|
|
yuv_add_time_watermark((uint8_t *)vga_room,640,480,12,32,400,440,2001,12,1,13,1,59);
|
|
soft_to_jpg_run((uint32)vga_room,(uint32)vfx_linebuf,640,480);
|
|
}
|
|
}
|
|
}
|
|
|
|
void softjpg_thread_init(){
|
|
os_task_create("handle_softjpg", soft_to_jpg_thread, (void*)NULL, OS_TASK_PRIORITY_NORMAL, 0, NULL, 1024);
|
|
}
|
|
#endif
|
|
|
|
#if 0
|
|
|
|
void jpg_soft_run_demo(){
|
|
struct data_structure *get_f = NULL;
|
|
struct stream_jpeg_data_s *dest_list;
|
|
struct stream_jpeg_data_s *dest_list_tmp;
|
|
struct stream_jpeg_data_s *el,*tmp;
|
|
stream *s = NULL;
|
|
uint32_t node_len;
|
|
uint32_t flen;
|
|
uint32_t num = 0;
|
|
uint8_t *jpeg_buf_addr = NULL;
|
|
void *fp;
|
|
os_sleep_ms(1000);
|
|
s = open_stream_available(R_RTP_JPEG,0,8,opcode_func,NULL);
|
|
soft_to_jpg_cfg(640,480);
|
|
start_jpeg();
|
|
while(1){
|
|
get_f = recv_real_data(s);
|
|
if(get_f){
|
|
os_printf("JPG gen\r\n");
|
|
dest_list = (struct stream_jpeg_data_s *)GET_DATA_BUF(get_f);
|
|
dest_list_tmp = dest_list;
|
|
flen = get_stream_real_data_len(get_f);
|
|
node_len = GET_NODE_LEN(get_f);
|
|
jpeg_buf_addr = (uint8_t *)GET_JPG_BUF(get_f);
|
|
|
|
os_printf("jpeg_buf_addr:%x len:%d\r\n",jpeg_buf_addr,node_len);
|
|
free_data(get_f);
|
|
get_f = NULL;
|
|
|
|
}else{
|
|
os_sleep_ms(15);
|
|
soft_to_jpg_run(decode_vga,640,480);
|
|
}
|
|
}
|
|
|
|
}
|
|
#endif
|
|
|
|
|
|
//jpg重新配置,如果设备处于休眠状态,则可能需要等待休眠结束才可以重新启动mjpeg
|
|
void jpg_recfg(uint8 jpg_num)
|
|
{
|
|
uint32_t jpg_id;
|
|
uint32_t count = 0;
|
|
jpg_id = jpg_num + HG_JPG0_DEVID;
|
|
struct jpg_device *jpeg_dev;
|
|
jpeg_dev = (struct jpg_device *)dev_get(jpg_id);
|
|
//第二bit代表jpg初始化完成
|
|
while(!(jpg_get_init_flag(jpeg_dev)) && count++<3000)
|
|
{
|
|
os_sleep_ms(1);
|
|
}
|
|
os_printf("jpg_is_online(jpeg_dev):%X\n",jpg_is_online(jpeg_dev));
|
|
jpg_room_init(jpg_num);
|
|
jpg_config_addr(jpeg_dev,jpg_num);
|
|
}
|
|
|
|
|
|
|
|
void jpg_start(uint8 jpg_num){
|
|
struct jpg_device *jpeg_dev;
|
|
uint32_t jpgid;
|
|
jpgid = jpg_num + HG_JPG0_DEVID;
|
|
jpeg_dev = (struct jpg_device *)dev_get(jpgid);
|
|
|
|
//jpg csr config
|
|
if(jpgid == HG_JPG0_DEVID){
|
|
#if BBM_DEMO
|
|
jpg_set_size(jpeg_dev,photo_msg.out1_h,photo_msg.out1_w);
|
|
#else
|
|
jpg_set_size(jpeg_dev,photo_msg.out0_h,photo_msg.out0_w);
|
|
#endif
|
|
}
|
|
else{
|
|
jpg_set_size(jpeg_dev,photo_msg.out0_h,photo_msg.out0_w);
|
|
}
|
|
jpg_open(jpeg_dev);
|
|
os_printf("mj1 open\r\n");
|
|
}
|
|
|
|
//w和h 设置0,代表和源头分辨率一致
|
|
void set_jpg_w_h(uint8 jpg_num,uint16_t w,uint16_t h)
|
|
{
|
|
if(jpg_num == 0)
|
|
{
|
|
if(w == 0 && h == 0)
|
|
{
|
|
photo_msg.out0_w = photo_msg.in_w;
|
|
photo_msg.out0_h = photo_msg.in_h;
|
|
}
|
|
else
|
|
{
|
|
photo_msg.out0_w = w;
|
|
photo_msg.out0_h = h;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
if(w == 0 && h == 0)
|
|
{
|
|
photo_msg.out1_w = photo_msg.in_w;
|
|
photo_msg.out1_h = photo_msg.in_h;
|
|
}
|
|
else
|
|
{
|
|
photo_msg.out1_w = w;
|
|
photo_msg.out1_h = h;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void jpg_start_dpi(uint8 jpg_num,uint16_t w,uint16_t h){
|
|
struct jpg_device *jpeg_dev;
|
|
uint32_t jpgid;
|
|
jpgid = jpg_num + HG_JPG0_DEVID;
|
|
jpeg_dev = (struct jpg_device *)dev_get(jpgid);
|
|
|
|
if(jpg_num == 0)
|
|
{
|
|
photo_msg.out0_w = w;
|
|
photo_msg.out0_h = h;
|
|
}
|
|
else
|
|
{
|
|
photo_msg.out1_w = w;
|
|
photo_msg.out1_h = h;
|
|
}
|
|
|
|
os_printf("w:%d\th:%d\n",w,h);
|
|
//jpg csr config
|
|
if(jpeg_dev)
|
|
{
|
|
jpg_set_size(jpeg_dev,h,w);
|
|
jpg_open(jpeg_dev);
|
|
}
|
|
|
|
os_printf("mj1 open\r\n");
|
|
}
|
|
|
|
void jpg_stop(uint32_t jpg_num)
|
|
{
|
|
uint32_t jpg_id;
|
|
jpg_id = jpg_num + HG_JPG0_DEVID;
|
|
struct jpg_device *jpeg_dev;
|
|
jpeg_dev = (struct jpg_device *)dev_get(jpg_id);
|
|
jpg_close(jpeg_dev);
|
|
jpg_room_deinit(jpg_num);
|
|
}
|
|
|
|
void jpg_clear_init_flag(uint32_t jpg_num)
|
|
{
|
|
uint32_t jpg_id;
|
|
struct jpg_device *jpeg_dev;
|
|
jpg_id = jpg_num + HG_JPG0_DEVID;
|
|
jpeg_dev = (struct jpg_device *)dev_get(jpg_id);
|
|
jpg_set_init_finish(jpeg_dev,0);
|
|
}
|
|
|
|
|
|
|
|
void del_jpeg_frame(void *d)
|
|
{
|
|
jpeg_frame* get_f = (jpeg_frame*)d;
|
|
del_frame(get_f->jpg_num,(struct list_head*)get_f);
|
|
|
|
}
|
|
|
|
struct list_head* get_frame(uint8 jpgid)
|
|
{
|
|
uint8 frame_num = 0;
|
|
uint8 jpg_chose;
|
|
if(jpgid == HG_JPG0_DEVID)
|
|
jpg_chose = 0;
|
|
else
|
|
jpg_chose = 1;
|
|
|
|
for(frame_num = 0;frame_num < JPEG_FRAME_NUM;frame_num++){
|
|
if(jpg_frame[jpg_chose][frame_num].usable == 2){
|
|
jpg_frame[jpg_chose][frame_num].usable = 1;
|
|
return (struct list_head *)&jpg_frame[jpg_chose][frame_num].list;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
uint32 get_jpeg_len(void *d)
|
|
{
|
|
uint32 flen;
|
|
struct list_head* get_f = (struct list_head*)d;
|
|
jpeg_frame* jpf;
|
|
jpf = list_entry(get_f,jpeg_frame,list);
|
|
flen = jpf->frame_len;
|
|
//_os_printf("%s:%d\tflen:%d\n",__FUNCTION__,__LINE__,flen);
|
|
|
|
return flen;
|
|
}
|
|
|
|
|
|
|
|
void *get_jpeg_first_buf(void *d)
|
|
{
|
|
struct list_head* get_f = (struct list_head*)d;
|
|
mjpeg_node* mjn;
|
|
mjn = list_entry(get_f->next,mjpeg_node,list);
|
|
if(mjn)
|
|
{
|
|
return mjn->buf_addr;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
int del_jpeg_first_node(void *d)
|
|
{
|
|
jpeg_frame* get_f = (jpeg_frame*)d;
|
|
put_node(&free_tab[get_f->jpg_num],(struct list_head*)get_f);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void *get_jpeg_node_buf(void *d)
|
|
{
|
|
struct list_head* get_f = (struct list_head*)d;
|
|
mjpeg_node* mjn;
|
|
mjn = list_entry(get_f,mjpeg_node,list);
|
|
if(mjn)
|
|
{
|
|
return mjn->buf_addr;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
|
|
//删除节点,是实际节点
|
|
void del_jpeg_node(void *d,uint32_t jpg_num)
|
|
{
|
|
uint32_t flags;
|
|
struct list_head* get_f = (struct list_head *)d;
|
|
flags = disable_irq();
|
|
list_add_tail(get_f,(struct list_head*)&free_tab[jpg_num]);
|
|
enable_irq(flags);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#endif
|