#include "sys_config.h" #include "tx_platform.h" #include "list.h" #include "dev.h" #include "typesdef.h" #include "devid.h" #include "osal/irq.h" #include "osal/string.h" #include "osal/semaphore.h" #include "osal/mutex.h" #include "osal/task.h" #include "osal/work.h" #include "osal/event.h" #include "hal/usb_device.h" #include "dev/usb/hgusb20_v1_dev_api.h" #include "dev/usb/uvc_host.h" #include "osal/semaphore.h" #include "jpgdef.h" #include "lib/lcd/lcd.h" #include "lib/common/common.h" #include "lib/heap/av_heap.h" #include "lib/heap/av_psram_heap.h" #include "stream_frame.h" #include "utlist.h" //兼容有psram和无psram的情况 #ifdef PSRAM_HEAP #define UVC_MALLOC av_psram_malloc #define UVC_FREE av_psram_free #else #define UVC_MALLOC av_malloc #define UVC_FREE av_free #endif #if USB_EN #define UVC_BLANK_LEN 16*1024 #ifdef PSRAM_HEAP #define UVC_BLANK_NUM 8 #else #define UVC_BLANK_NUM 8 #endif #define UVC_FRAME_NUM 2 UVC_BLANK uvc_blank[UVC_BLANK_NUM]; //uint8 blank_space[UVC_BLANK_NUM][UVC_BLANK_LEN+UVC_HEAD_RESERVER]__attribute__ ((aligned(4))); uint8 *blank_space[UVC_BLANK_NUM]; struct list_head free_uvc_tab[UVC_HOST_NUM]; struct list_head *uvc_p[UVC_HOST_NUM]; struct list_head *uvc_bnk[UVC_HOST_NUM]; UVC_MANAGE* uvc_msg[UVC_HOST_NUM]; UVC_MANAGE uvc_msg_frame[UVC_HOST_NUM][UVC_FRAME_NUM]; //2个frame就够了,一个中断处正在收,一个应用正在使用,带宽不足时一个frame的不同blank进行收发处理 #define NEXT_TGL ((uvc_msg[0]->uvc_head[1] & BIT(0)) ^ 1) #define CURT_TGL (uvc_msg[0]->uvc_head[1] & BIT(0)) #define NEXT_TGL2 ((uvc_msg[1]->uvc_head[1] & BIT(0)) ^ 1) #define CURT_TGL2 (uvc_msg[1]->uvc_head[1] & BIT(0)) uint32 frame_num[UVC_HOST_NUM]; volatile uint32 rx_packet_len; volatile uint32 rx_packet_len_2; volatile uint32 head_len; int get_node_uvc_len() { return UVC_BLANK_LEN; } void *get_usb_jpeg_node_buf(void *d) { UVC_BLANK* uvc_b = (UVC_BLANK*)d; return uvc_b->buf_ptr; } /**@brief * 将传入的frame根节点下的buf池都送回空间池(free_uvc_tab)中 */ bool free_get_uvc_node_list(struct list_head *head,struct list_head *free){ if(list_empty(head)){ return 0; } list_splice_init(head,free); return 1; } void del_usb_frame(void *get_f) { free_get_uvc_node_list(get_f,&free_uvc_tab[0]); } void del_usb_frame2(void *get_f) { free_get_uvc_node_list(get_f,&free_uvc_tab[1]); } int get_usb_node_count(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 * 从初始化的frame根节点中抽取其中一个空闲的根节点进行使用,并标记frame的使用状态为正在使用 * @param 是否开启抢占模式,如果开启,则将上一帧已完成的帧节点删掉,并返回 */ struct list_head* get_new_uvc_frame_head(int grab){ uint8 frame_num = 0; for(frame_num = 0;frame_num < UVC_FRAME_NUM;frame_num++){ if(uvc_msg_frame[0][frame_num].state == 0){ uvc_msg_frame[0][frame_num].state = 1; uvc_msg_frame[0][frame_num].frame_end = 0; return &uvc_msg_frame[0][frame_num].list; } } if(grab) //是否开启抢占模式,开启抢占后,肯定有frame返回,上一帧没使用的frame肯定usable为2 { for(frame_num = 0;frame_num < UVC_FRAME_NUM;frame_num++){ if(uvc_msg_frame[0][frame_num].state == 2){ uvc_msg_frame[0][frame_num].state = 1; uvc_msg_frame[0][frame_num].frame_end = 0; free_get_uvc_node_list(&uvc_msg_frame[0][frame_num].list,&free_uvc_tab[0]); return &uvc_msg_frame[0][frame_num].list; } } } return 0; } void set_uvc_frame_ready(UVC_MANAGE* uvc){ if(uvc->state != 3) //表示此frame正在被应用使用,可以使用的状态不用切了 uvc->state = 2; } void set_uvc_frame_using(UVC_MANAGE* uvc){ uvc->state = 3; } void del_uvc_frame(UVC_MANAGE* uvc) { uvc->state = 0; uvc->frame_len = 0; uvc->frame_end = 0; } /*reset所有的frame,包括正在填充的和正在使用的,在填充和获取的线程或中断都关闭后调用*/ void force_reset_uvc_frame() { uint8 frame_num = 0; for(frame_num = 0;frame_num < UVC_FRAME_NUM;frame_num++){ del_usb_frame(&uvc_msg_frame[0][frame_num].list); del_uvc_frame(&uvc_msg_frame[0][frame_num]); } } /**@brief * 从空间池中提取一个节点,放到队列中,并将此节点作为返回值返回 */ struct list_head *get_blank_node(struct list_head *head,struct list_head *del){ if(list_empty(del)){ return 0; } list_move(del->prev,head); return head->next; //返回最新的位置 } bool put_blank_node(struct list_head *head,struct list_head *del){ irq_disable(USB20DMA_IRQn); if(list_empty(del)){ irq_enable(USB20DMA_IRQn); return 0; } list_move(del->prev,head); irq_enable(USB20DMA_IRQn); return 1; } //新增加,将节点归还到节点池 bool free_usb_node(struct list_head *del){ irq_disable(USB20DMA_IRQn); list_move(del,&free_uvc_tab[0]); irq_enable(USB20DMA_IRQn); return 1; } //新增加,将节点归还到节点池 bool free_usb_node2(struct list_head *del){ irq_disable(USB20DMA_IRQn); list_move(del,&free_uvc_tab[1]); irq_enable(USB20DMA_IRQn); return 1; } bool free_node2tab(UVC_BLANK* ubk,struct list_head *head,struct list_head *del) { put_blank_node(head,del); return 0; } struct list_head* get_uvc_frame() { uint8 frame_num = 0; irq_disable(USB20DMA_IRQn); for(frame_num = 0;frame_num < UVC_FRAME_NUM;frame_num++){ if(uvc_msg_frame[0][frame_num].state == 2) //将当前使用frame或者完成frame返回出去,加以使用 { uvc_msg_frame[0][frame_num].state = 1; irq_enable(USB20DMA_IRQn); return &uvc_msg_frame[0][frame_num].list; } } #ifdef PSRAM_HEAP for(frame_num = 0;frame_num < UVC_FRAME_NUM;frame_num++){ if(uvc_msg_frame[0][frame_num].state == 1) //将当前使用frame或者完成frame返回出去,加以使用 { uvc_msg_frame[0][frame_num].state = 1; irq_enable(USB20DMA_IRQn); return &uvc_msg_frame[0][frame_num].list; } } #endif irq_enable(USB20DMA_IRQn); return 0; } struct list_head* get_uvc_frame2() { uint8 frame_num = 0; irq_disable(USB20DMA_IRQn); for(frame_num = 0;frame_num < UVC_FRAME_NUM;frame_num++){ if(uvc_msg_frame[1][frame_num].state == 2) //将当前使用frame或者完成frame返回出去,加以使用 { uvc_msg_frame[1][frame_num].state = 1; irq_enable(USB20DMA_IRQn); return &uvc_msg_frame[1][frame_num].list; } } #ifdef PSRAM_HEAP for(frame_num = 0;frame_num < UVC_FRAME_NUM;frame_num++){ if(uvc_msg_frame[1][frame_num].state == 1) //将当前使用frame或者完成frame返回出去,加以使用 { uvc_msg_frame[1][frame_num].state = 1; irq_enable(USB20DMA_IRQn); return &uvc_msg_frame[1][frame_num].list; } } #endif irq_enable(USB20DMA_IRQn); return 0; } void uvc_blank_init(uint8* buf, uint32 blank_len, uint8 blank_num) { uvc_blank[blank_num].blank_len = 0; uvc_blank[blank_num].re_space = blank_len; uvc_blank[blank_num].blank_loop = 0; uvc_blank[blank_num].buf_ptr = buf;//buf+blank_num*(blank_len+UVC_HEAD_RESERVER)+UVC_HEAD_RESERVER; uvc_blank[blank_num].busy = 0; uvc_blank[blank_num].frame_counter = 0; } void uvc_blank_list_init(struct list_head *ftb,uint8 blank_num) { uint8 bcnt = 0; INIT_LIST_HEAD(ftb); for(bcnt = 0;bcnt < blank_num;bcnt++){ INIT_LIST_HEAD(&uvc_blank[bcnt].list); list_add_tail(&uvc_blank[bcnt].list,ftb); } } void uvc_blank_list_init2(struct list_head *ftb,uint8 blank_num) { uint8 bcnt = 0; INIT_LIST_HEAD(ftb); for(bcnt = 0;bcnt < blank_num;bcnt++){ os_printf("uvc blank list init2:%d\r\n",bcnt+UVC_BLANK_NUM/2); INIT_LIST_HEAD(&uvc_blank[bcnt+UVC_BLANK_NUM/2].list); list_add_tail(&uvc_blank[bcnt+UVC_BLANK_NUM/2].list,ftb); } } void uvc_room_del(){ uint8 bcnt = 0; for(bcnt = 0;bcnt < UVC_BLANK_NUM;bcnt++){ if(blank_space[bcnt]){ os_printf("blank del[%d]\r\n",bcnt); UVC_FREE(blank_space[bcnt]); blank_space[bcnt] = NULL; } } } void uvc_room_del_mjpeg(){ uint8 bcnt = 0; for(bcnt = 0;bcnt < UVC_BLANK_NUM/2;bcnt++){ if(blank_space[bcnt]){ os_printf("h264 blank del[%d]\r\n",bcnt); UVC_FREE(blank_space[bcnt]); blank_space[bcnt] = NULL; } } } void uvc_room_del_h264(){ uint8 bcnt = 0; for(bcnt = UVC_BLANK_NUM/2;bcnt < UVC_BLANK_NUM;bcnt++){ if(blank_space[bcnt]){ os_printf("mjpeg blank del[%d]\r\n",bcnt); UVC_FREE(blank_space[bcnt]); blank_space[bcnt] = NULL; } } } uint8_t *check_uvc_room() { return blank_space[0]; } uint8_t *check_uvc_room2() { return blank_space[UVC_BLANK_NUM/2]; } void uvc_room_malloc(){ uint8 bcnt = 0; for(bcnt = 0;bcnt < UVC_BLANK_NUM;bcnt++){ if(blank_space[bcnt] == NULL){ blank_space[bcnt] = UVC_MALLOC(UVC_BLANK_LEN); if(blank_space[bcnt] == NULL){ os_printf("uvc malloc fail\r\n"); return; } os_printf("blank_space[%d]:%x\r\n",bcnt,(unsigned int)blank_space[bcnt]); } uvc_blank_init(blank_space[bcnt],UVC_BLANK_LEN,bcnt); } } void uvc_room_malloc_mjpeg(){ uint8 bcnt = 0; for(bcnt = 0;bcnt < UVC_BLANK_NUM/2;bcnt++){ if(blank_space[bcnt] == NULL){ blank_space[bcnt] = UVC_MALLOC(UVC_BLANK_LEN); if(blank_space[bcnt] == NULL){ os_printf("uvc malloc fail\r\n"); return; } os_printf("blank_space[%d]:%x\r\n",bcnt,(unsigned int)blank_space[bcnt]); } uvc_blank_init(blank_space[bcnt],UVC_BLANK_LEN,bcnt); } } void uvc_room_malloc_h264(){ uint8 bcnt = 0; for(bcnt = UVC_BLANK_NUM/2;bcnt < UVC_BLANK_NUM;bcnt++){ if(blank_space[bcnt] == NULL){ blank_space[bcnt] = UVC_MALLOC(UVC_BLANK_LEN); if(blank_space[bcnt] == NULL){ os_printf("uvc malloc fail\r\n"); return; } os_printf("blank_space[%d]:%x\r\n",bcnt,(unsigned int)blank_space[bcnt]); } uvc_blank_init(blank_space[bcnt],UVC_BLANK_LEN,bcnt); } } void uvc_reset_dev(uint8_t en){ if(en){ os_sleep_ms(5); uvc_room_malloc(); _os_printf("room set"); }else{ uvc_msg_frame[0][0].frame_end = 2; uvc_msg_frame[0][1].frame_end = 2; uvc_msg_frame[1][0].frame_end = 2; uvc_msg_frame[1][1].frame_end = 2; os_sleep_ms(5); uvc_room_del(); _os_printf("room del"); } } void uvc_reset_dev_mjpeg(uint8_t en){ if(en){ os_sleep_ms(5); uvc_room_malloc_mjpeg(); _os_printf("room mjpeg set"); }else{ uvc_msg_frame[0][0].frame_end = 2; uvc_msg_frame[0][1].frame_end = 2; uvc_room_del_mjpeg(); _os_printf("room mjpeg del"); } } void uvc_reset_dev_h264(uint8_t en){ if(en){ os_sleep_ms(5); uvc_room_malloc_h264(); _os_printf("room h264 set"); }else{ uvc_msg_frame[1][0].frame_end = 2; uvc_msg_frame[1][1].frame_end = 2; uvc_room_del_h264(); _os_printf("room h264 del"); } } extern void uvc_stream_open(struct hgusb20_dev *p_dev,uint8 enable); struct list_head* get_new_uvc_frame_head2(int grab); //初始化双数据流的节点空间 void uvc_room_init(void *p_dev) { os_printf("%s:%d\n",__FUNCTION__,__LINE__); //如果已经申请了空间,则不需要管,如果没有申请空间,则关闭 if(!check_uvc_room()) { uvc_reset_dev(1); } uvc_blank_list_init(&free_uvc_tab[0],UVC_BLANK_NUM/2); INIT_LIST_HEAD(&uvc_msg_frame[0][0].list); INIT_LIST_HEAD(&uvc_msg_frame[0][1].list); uvc_msg_frame[0][0].state = 0; uvc_msg_frame[0][1].state = 0; uvc_msg_frame[0][0].sta = 0; uvc_msg_frame[0][1].sta = 0; uvc_p[0] = get_new_uvc_frame_head(1); uvc_msg[0] = list_entry(uvc_p[0],UVC_MANAGE,list);//&uvc_msg_frame[0]; uvc_blank_list_init2(&free_uvc_tab[1],UVC_BLANK_NUM/2); INIT_LIST_HEAD(&uvc_msg_frame[1][0].list); INIT_LIST_HEAD(&uvc_msg_frame[1][1].list); uvc_msg_frame[1][0].state = 0; uvc_msg_frame[1][1].state = 0; uvc_msg_frame[1][0].sta = 0; uvc_msg_frame[1][1].sta = 0; uvc_p[1] = get_new_uvc_frame_head2(1); uvc_msg[1] = list_entry(uvc_p[1],UVC_MANAGE,list);//&uvc_msg_frame[0]; } //初始化mjpeg的节点空间 void uvc_room_init_mjpeg() { os_printf("%s:%d\n",__FUNCTION__,__LINE__); //如果已经申请了空间,则不需要管,如果没有申请空间,则关闭 if(!check_uvc_room()) { uvc_reset_dev_mjpeg(1); } uvc_blank_list_init(&free_uvc_tab[0],UVC_BLANK_NUM/2); INIT_LIST_HEAD(&uvc_msg_frame[0][0].list); INIT_LIST_HEAD(&uvc_msg_frame[0][1].list); uvc_msg_frame[0][0].state = 0; uvc_msg_frame[0][1].state = 0; uvc_msg_frame[0][0].sta = 0; uvc_msg_frame[0][1].sta = 0; uvc_p[0] = get_new_uvc_frame_head(1); uvc_msg[0] = list_entry(uvc_p[0],UVC_MANAGE,list);//&uvc_msg_frame[0]; } void uvc_room_deinit_mjpeg() { uvc_reset_dev_mjpeg(0); } //初始化h264的节点空间 void uvc_room_init_h264() { os_printf("%s:%d\n",__FUNCTION__,__LINE__); //如果已经申请了空间,则不需要管,如果没有申请空间,则关闭 if(!check_uvc_room2()) { uvc_reset_dev_h264(1); } uvc_blank_list_init2(&free_uvc_tab[1],UVC_BLANK_NUM/2); INIT_LIST_HEAD(&uvc_msg_frame[1][0].list); INIT_LIST_HEAD(&uvc_msg_frame[1][1].list); uvc_msg_frame[1][0].state = 0; uvc_msg_frame[1][1].state = 0; uvc_msg_frame[1][0].sta = 0; uvc_msg_frame[1][1].sta = 0; uvc_p[1] = get_new_uvc_frame_head2(1); uvc_msg[1] = list_entry(uvc_p[1],UVC_MANAGE,list);//&uvc_msg_frame[0]; } void uvc_room_deinit_h264(void) { uvc_reset_dev_h264(0); } static uint8 uvc_irq_redy(UVC_MANAGE *uvc) { UVC_BLANK *blank; uvc->tgl = NEXT_TGL; uvc->sta = 1; uvc->frame_end = 0; uvc_bnk[0] = get_blank_node(&uvc->list,&free_uvc_tab[0]); if(uvc_bnk[0] == NULL){ uvc->tgl = NEXT_TGL; uvc->sta = 0; } else { blank = list_entry(uvc_bnk[0],UVC_BLANK,list); blank->blank_loop = 0; blank->re_space = UVC_BLANK_LEN; blank->busy = 0; blank->blank_len = 0; } return 0; } static uint8 uvc_irq_wait_next_frame(UVC_MANAGE *uvc) { if(uvc->tgl == CURT_TGL) { uvc->sta = 2; } return 0; } /**************************************************** 0:立刻进行kcik(包含一些错误) 1:切换bank,不能立刻kick ******************************************************/ static uint8 uvc_data_handle(UVC_MANAGE *uvc,struct hgusb20_dev *p_dev,uint8_t* rx_buff,uint8 drop) { //static unsigned int uvc_time = 0; //static unsigned int in_times = 0; UVC_BLANK *blank; uint32 data_len; uint32 re_space; uint32 tgl_mark; uint8 blank_loop = 0; uint8 ret = 0; uint8 end_frame = 0; data_len = rx_packet_len-head_len; static uint8 last_frame_end = 0; if(drop == 2){ //printf("_E_"); end_frame = 1; drop = 0; } if(drop) //丢帧处理,帧异常的时候需要处理掉当前帧 { _os_printf("_D3_"); if(uvc->state != 3){ uvc->state = 0; free_get_uvc_node_list(&uvc->list,&free_uvc_tab[0]); } uvc_p[0] = get_new_uvc_frame_head(1); //获取新的frame,然后检测下这个frame是不是已有blank,有的话,要先清 uvc_msg[0] = list_entry(uvc_p[0],UVC_MANAGE,list);//&uvc_msg_frame[0]; uvc_msg[0]->sta = 0; if(uvc_msg[0] == uvc){ free_get_uvc_node_list(&uvc->list,&free_uvc_tab[0]); del_uvc_frame(uvc); uvc_msg[0]->state = 1; }else{ uvc->frame_end = 2; uvc->sta = 0; } return 0; } //in_times++; if((uvc->tgl != CURT_TGL) || (last_frame_end==1)){ last_frame_end = 0; uvc->sta = 2; uvc->tgl = CURT_TGL; tgl_mark = CURT_TGL; #ifdef PSRAM_HEAP set_uvc_frame_ready(uvc); //上一次frame已完成 //_os_printf("_1_"); blank = list_entry(uvc_bnk[0],UVC_BLANK,list); blank->busy = 2; //printf("t1:%d\n",in_times); uvc->frame_end = 1; // 无psram #else if(uvc->state == 1){ //防漏 set_uvc_frame_ready(uvc); blank = list_entry(uvc_bnk[0],UVC_BLANK,list); blank->busy = 2; uvc->frame_end = 1; } #endif // uvc_time = csi_kernel_get_ticks(); uvc_p[0] = get_new_uvc_frame_head(1); //获取新的frame,然后检测下这个frame是不是已有blank,有的话,要先清 uvc_msg[0] = list_entry(uvc_p[0],UVC_MANAGE,list);//&uvc_msg_frame[0]; uvc_msg[0]->frame_counter = frame_num[0]; uvc_msg[0]->sta = 2; uvc_msg[0]->tgl = tgl_mark; uvc_msg[0]->frame_len = 0; uvc_bnk[0] = get_blank_node(&uvc_msg[0]->list,&free_uvc_tab[0]); //提取新的可用blank,旧的blank虽然还有可用空间,但换帧后也直接抛出 // printf("GB"); uvc = uvc_msg[0]; if(uvc_bnk[0] != NULL) { blank = list_entry(uvc_bnk[0],UVC_BLANK,list); blank->blank_len = 0; blank->re_space = UVC_BLANK_LEN; blank->busy = 0; blank->blank_loop = blank_loop; //切换洗一个bank,要延时kick ret = 1; //printf("nblank:%x %x\r\n",blank,blank_loop); }else{ _os_printf("_D2_"); if(uvc->state != 3){ uvc->state = 0; free_get_uvc_node_list(&uvc->list,&free_uvc_tab[0]); } uvc_p[0] = get_new_uvc_frame_head(1); //获取新的frame,然后检测下这个frame是不是已有blank,有的话,要先清 uvc_msg[0] = list_entry(uvc_p[0],UVC_MANAGE,list);//&uvc_msg_frame[0]; uvc_msg[0]->sta = 0; if(uvc_msg[0] == uvc){ free_get_uvc_node_list(&uvc->list,&free_uvc_tab[0]); del_uvc_frame(uvc); uvc_msg[0]->state = 1; }else{ uvc->frame_end = 2; uvc->sta = 0; } return 0; } frame_num[0]++; } //当前frame的数据处理 //1:通过当前frame找到当前blank的结构体 //printf("uvc_bnk:%x\r\n",uvc_bnk); blank = list_entry(uvc_bnk[0],UVC_BLANK,list); blank->busy = 1; if(blank->re_space < data_len){ //当前blank剩余空间不足 //printf("a2:%x %d %d\r\n",blank->buf_ptr+blank->blank_len,blank->blank_len,blank->re_space); hw_memcpy(blank->buf_ptr+blank->blank_len,&rx_buff[head_len],blank->re_space); if((rx_buff[rx_packet_len-2] == 0xFF)&&(rx_buff[rx_packet_len-1] == 0xD9)) { last_frame_end = 1; } //printf("buf:%x\r\n",blank->buf_ptr+blank->blank_len); re_space = blank->re_space; blank->blank_len +=blank->re_space; blank->re_space = 0; blank->busy = 2; //printf("t2:%d\n",in_times); //uvc_time = csi_kernel_get_ticks(); blank_loop = blank->blank_loop; if(uvc == NULL) _os_printf("uvc hehe\r\n"); uvc_bnk[0] = get_blank_node(&uvc->list,&free_uvc_tab[0]); //重新获取一个新的blank,将剩余数据回填进去 // _os_printf("GB"); if(uvc_bnk[0] != 0) { blank = list_entry(uvc_bnk[0],UVC_BLANK,list); blank->blank_len = 0; blank->re_space = UVC_BLANK_LEN; blank->busy = 0; blank_loop++; blank->blank_loop = blank_loop; ret = 1; //_os_printf("blank:%x %x\r\n",blank,blank_loop); }else{ _os_printf("_D1_"); //一个frame就将所有的内存都占光了,没有新的内存可以存放此帧图像了 if(uvc->state != 3){ uvc->state = 0; free_get_uvc_node_list(&uvc->list,&free_uvc_tab[0]); } uvc_p[0] = get_new_uvc_frame_head(1); //获取新的frame,然后检测下这个frame是不是已有blank,有的话,要先清 uvc_msg[0] = list_entry(uvc_p[0],UVC_MANAGE,list);//&uvc_msg_frame[0]; uvc_msg[0]->sta = 0; if(uvc == NULL) _os_printf("hehe\r\n"); if(uvc_msg[0] == uvc){ free_get_uvc_node_list(&uvc->list,&free_uvc_tab[0]); del_uvc_frame(uvc); uvc_msg[0]->state = 1; }else{ uvc->frame_end = 2; uvc->sta = 0; } return 0; } hw_memcpy(blank->buf_ptr+blank->blank_len,&rx_buff[re_space+head_len],data_len - re_space); if((rx_buff[rx_packet_len-2] == 0xFF)&&(rx_buff[rx_packet_len-1] == 0xD9)) { last_frame_end = 1; } blank->re_space -=(data_len - re_space); blank->blank_len +=(data_len - re_space); blank->busy = 1; uvc->frame_len += data_len; }else{ //当前blank剩余空间足够 //printf("a1:%x %d %d\r\n",blank->buf_ptr+blank->blank_len,blank->blank_len,data_len); hw_memcpy(blank->buf_ptr+blank->blank_len,&rx_buff[head_len],data_len); if((rx_buff[rx_packet_len-2] == 0xFF)&&(rx_buff[rx_packet_len-1] == 0xD9)) { last_frame_end = 1; } uvc->frame_len += data_len; blank->re_space -=data_len; blank->blank_len +=data_len; //printf("."); } if(end_frame){ set_uvc_frame_ready(uvc); blank->busy = 2; uvc->frame_end = 1; } return ret; } bool uvc_data_deal(struct hgusb20_dev *p_dev) { uint32 hgusb20_ep_get_dma_rx_len(struct hgusb20_dev *p_dev, uint8 ep); uint32 rx_len = hgusb20_ep_get_dma_rx_len(p_dev, UVC_EP); if(rx_len == 0){ return 1; } rx_packet_len = rx_len; //printf("rx_len:%d ",rx_packet_len); return 0; } struct list_head* get_new_uvc_frame_head2(int grab){ uint8 frame_num = 0; for(frame_num = 0;frame_num < UVC_FRAME_NUM;frame_num++){ if(uvc_msg_frame[1][frame_num].state == 0){ uvc_msg_frame[1][frame_num].state = 1; uvc_msg_frame[1][frame_num].frame_end = 0; return &uvc_msg_frame[1][frame_num].list; } } if(grab) //是否开启抢占模式,开启抢占后,肯定有frame返回,上一帧没使用的frame肯定usable为2 { for(frame_num = 0;frame_num < UVC_FRAME_NUM;frame_num++){ if(uvc_msg_frame[1][frame_num].state == 2){ uvc_msg_frame[1][frame_num].state = 1; uvc_msg_frame[1][frame_num].frame_end = 0; free_get_uvc_node_list(&uvc_msg_frame[1][frame_num].list,&free_uvc_tab[1]); return &uvc_msg_frame[1][frame_num].list; } } } return 0; } bool uvc_data_deal2(struct hgusb20_dev *p_dev) { uint32 hgusb20_ep_get_dma_rx_len(struct hgusb20_dev *p_dev, uint8 ep); uint32 rx_len = hgusb20_ep_get_dma_rx_len(p_dev, UVC2_EP); if(rx_len == 0){ return 1; } rx_packet_len_2 = rx_len; //printf("rx_len:%d ",rx_packet_len_2); return 0; } static uint8 uvc_irq_redy2(UVC_MANAGE *uvc) { UVC_BLANK *blank; uvc->tgl = NEXT_TGL2; uvc->sta = 1; uvc->frame_end = 0; uvc_bnk[1] = get_blank_node(&uvc->list,&free_uvc_tab[1]); if(uvc_bnk[1] == NULL){ uvc->tgl = NEXT_TGL2; uvc->sta = 0; } else { blank = list_entry(uvc_bnk[1],UVC_BLANK,list); blank->blank_loop = 0; blank->re_space = UVC_BLANK_LEN; blank->busy = 0; blank->blank_len = 0; } return 0; } static uint8 uvc_irq_wait_next_frame2(UVC_MANAGE *uvc) { if(uvc->tgl == CURT_TGL2) { uvc->sta = 2; } return 0; } static uint8 uvc_data_handle2(UVC_MANAGE *uvc,struct hgusb20_dev *p_dev,uint8_t* rx_buff,uint8 drop) { //static unsigned int uvc_time = 0; static unsigned int in_times = 0; UVC_BLANK *blank; uint32 data_len; uint32 re_space; uint32 tgl_mark; uint8 blank_loop = 0; uint8 ret = 0; uint8 end_frame = 0; data_len = rx_packet_len_2-head_len; static uint8 last_frame_end = 0; if(drop == 2){ //printf("_E_"); end_frame = 1; drop = 0; } if(drop) //丢帧处理,帧异常的时候需要处理掉当前帧 { _os_printf("_D3_2"); if(uvc->state != 3){ uvc->state = 0; free_get_uvc_node_list(&uvc->list,&free_uvc_tab[1]); } uvc_p[1] = get_new_uvc_frame_head2(1); //获取新的frame,然后检测下这个frame是不是已有blank,有的话,要先清 uvc_msg[1] = list_entry(uvc_p[1],UVC_MANAGE,list);//&uvc_msg_frame[0]; uvc_msg[1]->sta = 0; if(uvc_msg[1] == uvc){ free_get_uvc_node_list(&uvc->list,&free_uvc_tab[1]); del_uvc_frame(uvc); uvc_msg[1]->state = 1; }else{ uvc->frame_end = 2; uvc->sta = 0; } return 0; } in_times++; if((uvc->tgl != CURT_TGL2) || (last_frame_end==1)){ last_frame_end = 0; uvc->sta = 2; uvc->tgl = CURT_TGL2; tgl_mark = CURT_TGL2; #ifdef PSRAM_HEAP set_uvc_frame_ready(uvc); //上一次frame已完成 //_os_printf("_O_"); blank = list_entry(uvc_bnk[1],UVC_BLANK,list); blank->busy = 2; //printf("t1:%d\n",in_times); uvc->frame_end = 1; // 无psram #else if(uvc->state == 1){ //防漏 set_uvc_frame_ready(uvc); blank = list_entry(uvc_bnk[1],UVC_BLANK,list); blank->busy = 2; uvc->frame_end = 1; } #endif //uvc_time = os_jiffies(); uvc_p[1] = get_new_uvc_frame_head2(1); //获取新的frame,然后检测下这个frame是不是已有blank,有的话,要先清 uvc_msg[1] = list_entry(uvc_p[1],UVC_MANAGE,list);//&uvc_msg_frame[0]; uvc_msg[1]->frame_counter = frame_num[1]; uvc_msg[1]->sta = 2; uvc_msg[1]->tgl = tgl_mark; uvc_msg[1]->frame_len = 0; uvc_bnk[1] = get_blank_node(&uvc_msg[1]->list,&free_uvc_tab[1]); //提取新的可用blank,旧的blank虽然还有可用空间,但换帧后也直接抛出 // printf("GB"); uvc = uvc_msg[1]; if(uvc_bnk[1] != NULL) { blank = list_entry(uvc_bnk[1],UVC_BLANK,list); blank->blank_len = 0; blank->re_space = UVC_BLANK_LEN; blank->busy = 0; blank->blank_loop = blank_loop; //切换洗一个bank,要延时kick ret = 1; //printf("nblank:%x %x\r\n",blank,blank_loop); }else{ _os_printf("_D2_2"); if(uvc->state != 3){ uvc->state = 0; free_get_uvc_node_list(&uvc->list,&free_uvc_tab[1]); } uvc_p[1] = get_new_uvc_frame_head2(1); //获取新的frame,然后检测下这个frame是不是已有blank,有的话,要先清 uvc_msg[1] = list_entry(uvc_p[1],UVC_MANAGE,list);//&uvc_msg_frame[0]; uvc_msg[1]->sta = 0; if(uvc_msg[1] == uvc){ free_get_uvc_node_list(&uvc->list,&free_uvc_tab[1]); del_uvc_frame(uvc); uvc_msg[1]->state = 1; }else{ uvc->frame_end = 2; uvc->sta = 0; } return 0; } frame_num[1]++; } //当前frame的数据处理 //1:通过当前frame找到当前blank的结构体 //printf("uvc_bnk:%x\r\n",uvc_bnk); blank = list_entry(uvc_bnk[1],UVC_BLANK,list); blank->busy = 1; if(blank->re_space < data_len){ //当前blank剩余空间不足 //printf("a2:%x %d %d\r\n",blank->buf_ptr+blank->blank_len,blank->blank_len,blank->re_space); hw_memcpy(blank->buf_ptr+blank->blank_len,&rx_buff[head_len],blank->re_space); if((rx_buff[rx_packet_len_2-2] == 0xFF)&&(rx_buff[rx_packet_len_2-1] == 0xD9)) { last_frame_end = 1; } //printf("buf:%x\r\n",blank->buf_ptr+blank->blank_len); re_space = blank->re_space; blank->blank_len +=blank->re_space; blank->re_space = 0; blank->busy = 2; //printf("t2:%d\n",in_times); //uvc_time = csi_kernel_get_ticks(); blank_loop = blank->blank_loop; if(uvc == NULL) _os_printf("uvc hehe\r\n"); uvc_bnk[1] = get_blank_node(&uvc->list,&free_uvc_tab[1]); //重新获取一个新的blank,将剩余数据回填进去 // _os_printf("GB"); if(uvc_bnk[1] != 0) { blank = list_entry(uvc_bnk[1],UVC_BLANK,list); blank->blank_len = 0; blank->re_space = UVC_BLANK_LEN; blank->busy = 0; blank_loop++; blank->blank_loop = blank_loop; ret = 1; //_os_printf("blank:%x %x\r\n",blank,blank_loop); //return 0; }else{ _os_printf("_D1_2"); //一个frame就将所有的内存都占光了,没有新的内存可以存放此帧图像了 if(uvc->state != 3){ uvc->state = 0; free_get_uvc_node_list(&uvc->list,&free_uvc_tab[1]); } uvc_p[1] = get_new_uvc_frame_head2(1); //获取新的frame,然后检测下这个frame是不是已有blank,有的话,要先清 uvc_msg[1] = list_entry(uvc_p[1],UVC_MANAGE,list);//&uvc_msg_frame[0]; uvc_msg[1]->sta = 0; if(uvc == NULL) _os_printf("hehe\r\n"); if(uvc_msg[1] == uvc){ free_get_uvc_node_list(&uvc->list,&free_uvc_tab[1]); del_uvc_frame(uvc); uvc_msg[1]->state = 1; }else{ uvc->frame_end = 2; uvc->sta = 0; } return 0; } hw_memcpy(blank->buf_ptr+blank->blank_len,&rx_buff[re_space+head_len],data_len - re_space); if((rx_buff[rx_packet_len_2-2] == 0xFF)&&(rx_buff[rx_packet_len_2-1] == 0xD9)) { last_frame_end = 1; } blank->re_space -=(data_len - re_space); blank->blank_len +=(data_len - re_space); blank->busy = 1; uvc->frame_len += data_len; //os_printf("1"); }else{ //当前blank剩余空间足够 //printf("a1:%x %d %d\r\n",blank->buf_ptr+blank->blank_len,blank->blank_len,data_len); hw_memcpy(blank->buf_ptr+blank->blank_len,&rx_buff[head_len],data_len); if((rx_buff[rx_packet_len_2-2] == 0xFF)&&(rx_buff[rx_packet_len_2-1] == 0xD9)) { last_frame_end = 1; } uvc->frame_len += data_len; blank->re_space -=data_len; blank->blank_len +=data_len; //printf("."); } if(end_frame){ set_uvc_frame_ready(uvc); blank->busy = 2; uvc->frame_end = 1; } return ret; } int uvc_deal_mjpeg(struct hgusb20_dev *p_dev, uint8_t* rx_buff, uint8_t ep, uint8_t ep_type) { uint8 drop = 0; int ret = 0; uint32 data_len; static uint8_t bulk_head[12]; static uint8_t recv_start = 0; uint8_t *uvc_cache = NULL; static uint32_t uvc_cache_buff[256+3]; if((ep_type & 0X03) == USB_ENDPOINT_XFER_BULK){ uvc_cache = (uint8_t *)&uvc_cache_buff; hw_memcpy(uvc_msg[0]->uvc_head,rx_buff+BULK_HEAD,16); if((uvc_msg[0]->uvc_head[0] == 0x02)&&((uvc_msg[0]->uvc_head[1]&0X80) == 0x80)&&(uvc_msg[0]->uvc_head[2] == 0xFF)&&(uvc_msg[0]->uvc_head[3] == 0xD8)){ _os_printf("P2"); hw_memcpy(bulk_head,rx_buff+BULK_HEAD,BULK_HEAD); hw_memcpy(uvc_cache,rx_buff+BULK_HEAD,rx_packet_len); hw_memcpy(rx_buff,uvc_cache,rx_packet_len); uvc_msg[0]->uvc_head[0] = 12; bulk_head[0] = 12; } else if((uvc_msg[0]->uvc_head[0] == 0x0c)&&((uvc_msg[0]->uvc_head[1]&0XFE) == 0x8c)&&(uvc_msg[0]->uvc_head[12] == 0xFF)&&(uvc_msg[0]->uvc_head[13] == 0xD8)){ _os_printf("P:%x ",uvc_msg[0]->uvc_head[2]); hw_memcpy(bulk_head,rx_buff+BULK_HEAD,BULK_HEAD); hw_memcpy(uvc_cache,rx_buff+BULK_HEAD,rx_packet_len); hw_memcpy(rx_buff,uvc_cache,rx_packet_len); recv_start = 1; }else if((uvc_msg[0]->uvc_head[0] == 0x0c)&&((uvc_msg[0]->uvc_head[1]&0XFE) == 0x82)&& (uvc_msg[0]->uvc_head[12] == 0x00)&&(uvc_msg[0]->uvc_head[13] == 0x00)&& (uvc_msg[0]->uvc_head[14] == 0x00)&&(uvc_msg[0]->uvc_head[15] == 0x01)){ hw_memcpy(bulk_head,rx_buff+BULK_HEAD,BULK_HEAD); hw_memcpy(uvc_cache,rx_buff+BULK_HEAD,rx_packet_len); hw_memcpy(rx_buff,uvc_cache,rx_packet_len); } else{ uint8 same_cnt = 0; if(recv_start==1) { for(uint8 i=0; i<6; i++) { if(uvc_msg[0]->uvc_head[i] == bulk_head[i]) same_cnt++; } } if(same_cnt < 6) { hw_memcpy(rx_buff,bulk_head,12); rx_packet_len+=12; } else { hw_memcpy(uvc_cache+BULK_HEAD,rx_buff+BULK_HEAD*2,rx_packet_len-BULK_HEAD); hw_memcpy(uvc_cache,bulk_head,BULK_HEAD); hw_memcpy(rx_buff, uvc_cache, rx_packet_len); } } } hw_memcpy(uvc_msg[0]->uvc_head,rx_buff,16); head_len = uvc_msg[0]->uvc_head[0]; if(head_len > rx_packet_len){ drop = 1; } data_len = rx_packet_len-head_len; if((data_len == 0) && (uvc_msg[0]->uvc_head[1] & (BIT(6)))) { drop = 1; } else if(data_len == 0) { return ret; } //无psram #ifndef PSRAM_HEAP if(uvc_msg[0]->uvc_head[1]&BIT(1)){ drop = 2; } #endif if (hgusb20_host_is_crc_err(p_dev, ep)) { drop = 1; } if((uvc_msg[0]->uvc_head[0] != 0x0c)&&(uvc_msg[0]->uvc_head[0] != 0x02)){//head[0] is head len drop = 1; } if(uvc_msg[0]->uvc_head[1] & (BIT(6) | BIT(5))){//error packe drop = 1; } switch(uvc_msg[0]->sta){ case 0: uvc_irq_redy(uvc_msg[0]); case 1: ret = uvc_irq_wait_next_frame(uvc_msg[0]); if(uvc_msg[0]->sta != 2) break; case 2: ret = uvc_data_handle(uvc_msg[0],p_dev,rx_buff,drop); break; } return ret; } int uvc_deal_h264(struct hgusb20_dev *p_dev, uint8_t* rx_buff, uint8_t ep, uint8 ep_type) { uint8 drop = 0; int ret = 0; uint32 data_len; static uint8_t bulk_head[12]; static uint8_t recv_start = 0; uint8_t *uvc_cache = NULL; static uint32_t uvc_cache_buff[256+3]; if((ep_type & 0X03) == USB_ENDPOINT_XFER_BULK){ uvc_cache = (uint8_t *)&uvc_cache_buff; hw_memcpy(uvc_msg[1]->uvc_head,rx_buff+BULK_HEAD,16); if((uvc_msg[1]->uvc_head[0] == 0x02)&&((uvc_msg[1]->uvc_head[1]&0X80) == 0x80)&&(uvc_msg[1]->uvc_head[2] == 0xFF)&&(uvc_msg[1]->uvc_head[3] == 0xD8)){ _os_printf("P2"); hw_memcpy(bulk_head,rx_buff+BULK_HEAD,BULK_HEAD); hw_memcpy(uvc_cache,rx_buff+BULK_HEAD,rx_packet_len_2); hw_memcpy(rx_buff,uvc_cache,rx_packet_len_2); uvc_msg[1]->uvc_head[0] = 12; bulk_head[0] = 12; } else if((uvc_msg[1]->uvc_head[0] == 0x0c)&&((uvc_msg[1]->uvc_head[1]&0XFE) == 0x8c)&&(uvc_msg[1]->uvc_head[12] == 0xFF)&&(uvc_msg[1]->uvc_head[13] == 0xD8)){ _os_printf("P:%x ",uvc_msg[1]->uvc_head[2]); hw_memcpy(bulk_head,rx_buff+BULK_HEAD,BULK_HEAD); hw_memcpy(uvc_cache,rx_buff+BULK_HEAD,rx_packet_len_2); hw_memcpy(rx_buff,uvc_cache,rx_packet_len_2); recv_start = 1; }else if((uvc_msg[1]->uvc_head[0] == 0x0c)&&((uvc_msg[1]->uvc_head[1]&0XFE) == 0x82)&& (uvc_msg[1]->uvc_head[12] == 0x00)&&(uvc_msg[1]->uvc_head[13] == 0x00)&& (uvc_msg[1]->uvc_head[14] == 0x00)&&(uvc_msg[1]->uvc_head[15] == 0x01)){ hw_memcpy(bulk_head,rx_buff+BULK_HEAD,BULK_HEAD); hw_memcpy(uvc_cache,rx_buff+BULK_HEAD,rx_packet_len_2); hw_memcpy(rx_buff,uvc_cache,rx_packet_len_2); } else{ uint8 same_cnt = 0; if(recv_start==1) { for(uint8 i=0; i<6; i++) { if(uvc_msg[1]->uvc_head[i] == bulk_head[i]) same_cnt++; } } if(same_cnt < 6) { hw_memcpy(rx_buff,bulk_head,12); rx_packet_len_2+=12; } else { hw_memcpy(uvc_cache+BULK_HEAD,rx_buff+BULK_HEAD*2,rx_packet_len_2-BULK_HEAD); hw_memcpy(uvc_cache,bulk_head,BULK_HEAD); hw_memcpy(rx_buff, uvc_cache, rx_packet_len_2); } } } hw_memcpy(uvc_msg[1]->uvc_head,rx_buff,16); head_len = uvc_msg[1]->uvc_head[0]; if(head_len > rx_packet_len_2){ drop = 1; } data_len = rx_packet_len_2-head_len; if((data_len == 0) && (uvc_msg[1]->uvc_head[1] & (BIT(6)))) { drop = 1; } else if(data_len == 0) { return ret; } //无psram #ifndef PSRAM_HEAP if(uvc_msg[1]->uvc_head[1]&BIT(1)){ drop = 2; } #endif if (hgusb20_host_is_crc_err(p_dev, ep)) { drop = 1; } if((uvc_msg[1]->uvc_head[0] != 0x0c)&&(uvc_msg[1]->uvc_head[0] != 0x02)){//head[0] is head len drop = 1; } if(uvc_msg[1]->uvc_head[1] & (BIT(6) | BIT(5))){//error packe drop = 1; } switch(uvc_msg[1]->sta){ case 0: uvc_irq_redy2(uvc_msg[1]); case 1: ret = uvc_irq_wait_next_frame2(uvc_msg[1]); if(uvc_msg[1]->sta != 2) break; case 2: ret = uvc_data_handle2(uvc_msg[1],p_dev,rx_buff,drop); break; } return ret; } int usb_dma_irq_times= 0; void usb_dma_irq(void * dev, uint8_t* uvc_rx_buff, uint8_t uvc_head_res, uint8_t ep_type) { uint32 ret; usb_dma_irq_times++; struct hgusb20_dev *p_dev = (struct hgusb20_dev *)dev; if (!p_dev) return; ret = uvc_data_deal(p_dev); if(ret == 0){ ret = uvc_deal_mjpeg(p_dev, (uint8_t*)uvc_rx_buff, UVC_EP, ep_type); } hgusb20_ep_rx_kick(p_dev, UVC_EP, (uint32)(uvc_rx_buff+uvc_head_res),0x400); } //暂时会比较简单去实现,定义都是比较随便,如果可以,jpeg与uvc能统一最好 //mjpeg信号量创建 static struct os_semaphore uvc_sem = {0}; static int uvc_sem_init = 0; void uvc_sema_init() { os_sema_init(&uvc_sem,0); uvc_sem_init = 1; } void uvc_sema_down(int32 tmo_ms) { if(!uvc_sem_init) { return; } os_sema_down(&uvc_sem,tmo_ms); //printf("$\n"); } void uvc_sema_up() { if(!uvc_sem_init) { return; } os_sema_up(&uvc_sem); } UVC_MANAGE* uvc_message_gloal; void set_uvc_message_gloal(UVC_MANAGE* uvc_message){ uvc_message_gloal = uvc_message; } UVC_MANAGE* get_uvc_message_gloal(){ return uvc_message_gloal; } void free_uvc_message_gloal(){ uvc_message_gloal = NULL; } uint32 get_uvc_frame_len(){ return uvc_message_gloal->frame_len; } UVC_BLANK* get_uvc_blank(){ UVC_BLANK* uvc_b; if((list_empty(&uvc_message_gloal->list) != TRUE )||(uvc_message_gloal->frame_end == 0)){ uvc_b = list_entry(uvc_message_gloal->list.prev,UVC_BLANK,list); return uvc_b; } return NULL; } uint8 free_uvc_blank(UVC_BLANK* uvc_b){ if(uvc_b == NULL) return 0; free_node2tab(uvc_b,(struct list_head*)&free_uvc_tab,&uvc_message_gloal->list); return 1; } uint8 free_uvc_blank_nopsram(UVC_MANAGE* uvc_message){ UVC_BLANK* uvc_b = NULL; if((list_empty(&uvc_message->list) != TRUE )||(uvc_message->frame_end == 0)){ uvc_b = list_entry(uvc_message->list.prev,UVC_BLANK,list); } if(uvc_b == NULL) return 0; free_node2tab(uvc_b,(struct list_head*)&free_uvc_tab,&uvc_message->list); return 1; } uint8* get_uvc_buf(){ UVC_BLANK* uvc_b; uvc_b = get_uvc_blank(); if(uvc_b == NULL) return NULL; return uvc_b->buf_ptr; } uint8_t uvc_open = 1; #if 0 UVC_BLANK* uvc_global = NULL; UVC_MANAGE*uvc_message_global = NULL; void uvc_stream_open(struct hgusb20_dev *p_dev,uint8 enable); extern volatile uint8 scale2_finish; #if DVP_EN uint8 *psram_uvc_buf[2]; extern uint8 psram_ybuf_src[480*640+480*640/2]; #else __psram_data uint8 psram_uvc_buf[2][200*1024] __aligned(4); #endif #if LCD_EN == 1 void jpg_decode_to_lcd(uint32 photo,uint32 jpg_w,uint32 jpg_h,uint32 video_w,uint32 video_h); void uvc_user4(void *d) { //uint8 msgbuf[10]; //u16* pt; uint8_t uvc_state = 2; os_sleep_ms(5); struct uvc_user_arg *arg = (struct uvc_user_arg*)d; uint32 tick_num = 0; UVC_MANAGE* uvc_message; UVC_BLANK* uvc_b; struct usb_device *dev = (struct usb_device *)dev_get(HG_USBDEV_DEVID); struct list_head* get_f; int del_times = 0; int err = 0; uint32 dnum = 0; uint8* buf = NULL; int irq_time = 0; //struct list_head* get_analy_node = NULL; uint8 pingpang = 0; #if DVP_EN psram_uvc_buf[0] = psram_ybuf_src; psram_uvc_buf[1] = psram_ybuf_src+200*1024; #endif //os_sleep_ms(6000); while(1){ get_f = get_uvc_frame(); if(get_f == 0) { //state=2,代表有通知需要删除任务 if(arg->state == 2) { err = 1; goto uvc_user4_exit; } if(uvc_open==1){ if(uvc_state != uvc_open){ uvc_stream_open((struct hgusb20_dev *)dev,1); uvc_state = uvc_open; } } //释放cpu os_sleep_ms(1); continue; } if(uvc_open==0){ if(uvc_state != uvc_open){ uvc_stream_open((struct hgusb20_dev *)dev,0); uvc_state = uvc_open; } } err = 0; irq_time = 0; tick_num++; uvc_message = list_entry(get_f,UVC_MANAGE,list); set_uvc_frame_using(uvc_message); uvc_message_global = uvc_message; while((list_empty(&uvc_message->list) != TRUE )||(uvc_message->frame_end == 0)){ if(uvc_open==0) break; irq_disable(USB20DMA_IRQn); uvc_b = list_entry(uvc_message->list.prev,UVC_BLANK,list); if(uvc_message->frame_end == 2){ break; } irq_enable(USB20DMA_IRQn); //if(arg->state == 2) //{ // err = 1; // goto uvc_user4_exit; //} if(uvc_message->state != 3) _os_printf("state_err\r\n"); uvc_global = uvc_b; if(uvc_b && uvc_b->busy == 2) { //数据头,所以要申请一帧数据 if(uvc_b->blank_loop == 0) { //正常不可能进来这里的 //获取下一帧 //u = f_get_uvc_frame_current_task(); //get_analy_node = get_app_analyze_node(&uvc_app_analyze); //if(get_analy_node) // buf = get_real_buf_adr(get_analy_node); //else // buf = NULL; if(pingpang == 0){ buf = psram_uvc_buf[0]; //pingpang = 1; }else{ buf = psram_uvc_buf[1]; //pingpang = 0; } } //没有帧,那么只能将bank删除,应该是rtsp处理速度不够 if(1)//(get_analy_node) { #if 0 if(uvc_b->buf_ptr[0] == 0xFF && uvc_b->buf_ptr[1] == 0xD8 && uvc_b->blank_loop != 0) { //printf("loop:%d\t%X\n",uvc_b->blank_loop,get_f); } #endif hw_memcpy0(buf,uvc_b->buf_ptr,uvc_b->blank_len); buf += uvc_b->blank_len; } else { _os_printf("="); } free_node2tab(uvc_b,(struct list_head*)&free_uvc_tab,&uvc_message->list); } else { //释放cpu os_sleep_ms(1); irq_time++; if(irq_time>200) { irq_time = 0; if(!usb_dma_irq_times) { //err = 1; _os_printf("%s usb maybe disconnect\n",__FUNCTION__); uvc_message->frame_end = 2; uvc_message->sta = 0; int32 usb_host_uvc_ioctl(struct usb_device *p_usb_d, uint32 cmd, uint32 param1, uint32 param2); usb_host_uvc_ioctl(dev, USB_HOST_IO_CMD_RESET,0,0); break; } usb_dma_irq_times = 0; } } //continue; } if(err) { #if 0 if(get_analy_node) { //f_del_uvc_frame(u); free_real_msg(get_analy_node,&uvc_app_analyze.free_list); get_analy_node = NULL; } continue; #endif goto uvc_user4_exit; } //异常退出,对应frame也del if(uvc_message->frame_end == 2) { //printf("get_F:%x\r\n",get_f); free_get_uvc_node_list(get_f,&free_uvc_tab[0]); del_uvc_frame(uvc_message); //if(get_analy_node) //{ //f_del_uvc_frame(u); // free_real_msg(get_analy_node,&uvc_app_analyze.free_list); // get_analy_node = NULL; //} } //正常退出 else { //设置状态,等于发送frame // if(get_analy_node) { //关闭usb中断,打印对应的数据出来 //u->frame_len = uvc_message->frame_len; // set_app_buf_len(get_analy_node,uvc_message->frame_len); #if 1 //f_set_uvc_frame_status(u); #else f_set_uvc_frame_status(u); f_del_uvc_frame(u); #endif //printf("frame_len:%d\n",uvc_message->frame_len); del_times++; // map_realnode_2_app_node_msg(&uvc_app_analyze,get_analy_node); if(uvc_open==1){ if(scale2_finish){ scale2_finish = 0; if(pingpang == 0){ jpg_decode_to_lcd((uint32)psram_uvc_buf[0],1280,720,160,120); pingpang = 1; }else{ jpg_decode_to_lcd((uint32)psram_uvc_buf[1],1280,720,160,120); pingpang = 0; } dnum = 0; }else{ dnum++; if(dnum > 8){ scale2_finish = 1; } } } _os_printf("M"); // wake_up_analyze_list_app(&uvc_app_analyze); // get_analy_node = NULL; // uvc_sema_up(); } //printf("del frame:%x %d %d\r\n",uvc_message,uvc_message->frame_len); //printf("="); //printf("?"); del_uvc_frame(uvc_message); } } uvc_user4_exit: if(err) { // if(get_analy_node) { //f_del_uvc_frame(u); // free_real_msg(get_analy_node,&uvc_app_analyze.free_list); // get_analy_node = NULL; } _os_printf("%s exit\n",__FUNCTION__); //代表任务已经被删除,可以重新启动 arg->state = 0; return; } } #endif #endif #if 0 void uvc_user() { UVC_MANAGE* uvc_message; UVC_BLANK* uvc_b; // uint32 len = 0; // uint32 itk = 0; // uint8 printf_uvc_jpg = 0; // struct list_head *uvc_bk; struct list_head* get_f; while(1){ get_f = get_uvc_frame(); if(get_f == 0) { //释放cpu os_sleep_ms(1); continue; } uvc_message = list_entry(get_f,UVC_MANAGE,list); set_uvc_frame_using(uvc_message); set_uvc_message_gloal(uvc_message); uvc_sema_down(-1); while((list_empty(&uvc_message->list) != TRUE )||(uvc_message->frame_end == 0)){ uvc_b = list_entry(uvc_message->list.prev,UVC_BLANK,list); if(uvc_b->busy == 2) { free_node2tab(uvc_b,(struct list_head*)&free_uvc_tab,&uvc_message->list); } } //printf("del frame:%x %d %d\r\n",uvc_message,uvc_message->frame_len,len); free_uvc_message_gloal(); del_uvc_frame(uvc_message); } } #endif #endif