程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> uvc攝像頭代碼解析6

uvc攝像頭代碼解析6

編輯:C++入門知識

10.掃描視頻設備鏈和注冊視頻設備 10.1 uvc視頻鏈 [cpp]   struct uvc_video_chain {    //uvc視頻鏈       struct uvc_device *dev;         //uvc設備       struct list_head list;          //uvc視頻鏈鏈表頭       struct list_head entities;      //uvc實體鏈表頭       struct uvc_entity *processing;  //處理Unit實體       struct uvc_entity *selector;    //選擇器Unit實體       struct mutex ctrl_mutex;        /* Protects ctrl.info */   };   10.2 uvc掃描設備 [cpp]   static int uvc_scan_device(struct uvc_device *dev)   {       struct uvc_video_chain *chain;  //uvc視頻鏈       struct uvc_entity *term;    //uvc實體          list_for_each_entry(term, &dev->entities, list) {    //遍歷全局實體鏈表           if (!UVC_ENTITY_IS_OTERM(term)) //獲取實體鏈表中的輸出Terminal實體               continue;           if (term->chain.next || term->chain.prev) //已經添加到uvc視頻鏈中了               continue;           chain = kzalloc(sizeof(*chain), GFP_KERNEL);    //分配uvc視頻鏈內存(有多少個輸入Terminal就有多少個uvc_video_chain)           if (chain == NULL)               return -ENOMEM;           INIT_LIST_HEAD(&chain->entities);    //初始化視頻鏈entities(實體)鏈表           mutex_init(&chain->ctrl_mutex);           chain->dev = dev;    //捆綁uvc視頻鏈和uvc設備           if (uvc_scan_chain(chain, term) < 0) {   //掃描uvc視頻鏈(處理所有相關的輸入pin)               kfree(chain);               continue;           }           uvc_trace(UVC_TRACE_PROBE, "Found a valid video chain (%s).\n",uvc_print_chain(chain));           list_add_tail(&chain->list, &dev->chains);    //添加到uvc設備的uvc視頻鏈鏈表       }       if (list_empty(&dev->chains)) {           uvc_printk(KERN_INFO, "No valid video chain found.\n");           return -1;       }       return 0;   }   10.3 uvc掃描視頻鏈 [cpp]   static int uvc_scan_chain(struct uvc_video_chain *chain,struct uvc_entity *term)   {       struct uvc_entity *entity, *prev;       uvc_trace(UVC_TRACE_PROBE, "Scanning UVC chain:");       entity = term;  //獲取實體       prev = NULL;    //前一個實體       while (entity != NULL) {           /* Entity must not be part of an existing chain */           if (entity->chain.next || entity->chain.prev) {   //已經添加到uvc視頻鏈中了               uvc_trace(UVC_TRACE_DESCR, "Found reference to entity %d already in chain.\n", entity->id);               return -EINVAL;           }           /* Process entity */           if (uvc_scan_chain_entity(chain, entity) < 0)    //掃描當前實體               return -EINVAL;           /* Forward scan */           if (uvc_scan_chain_forward(chain, entity, prev) < 0) //向前掃描實體               return -EINVAL;           /* Backward scan */           prev = entity;      //當前實體作為下一次while循環的前一個實體           if (uvc_scan_chain_backward(chain, &entity) < 0) //向後掃描實體               return -EINVAL;       }       return 0;   }   將uvc視頻鏈的輸入實體添加到uvc視頻鏈的entities鏈表中 將uvc視頻鏈添加到uvc設備的chains鏈表中 10.3.1 掃描當前實體 [cpp]   static int uvc_scan_chain_entity(struct uvc_video_chain *chain,struct uvc_entity *entity)   {       switch (UVC_ENTITY_TYPE(entity)) {       case UVC_VC_EXTENSION_UNIT: //擴展Unit           if (uvc_trace_param & UVC_TRACE_PROBE)               printk(" <- XU %d", entity->id);           if (entity->bNrInPins != 1) {               uvc_trace(UVC_TRACE_DESCR, "Extension unit %d has more than 1 input pin.\n", entity->id);               return -1;           }           break;       case UVC_VC_PROCESSING_UNIT:    //處理Unit           if (uvc_trace_param & UVC_TRACE_PROBE)               printk(" <- PU %d", entity->id);           if (chain->processing != NULL) {               uvc_trace(UVC_TRACE_DESCR, "Found multiple Processing Units in chain.\n");               return -1;           }           chain->processing = entity;  //如果是處理Unit則設置其為uvc視頻鏈的processing對象           break;       case UVC_VC_SELECTOR_UNIT:  //選擇器Unit           if (uvc_trace_param & UVC_TRACE_PROBE)               printk(" <- SU %d", entity->id);           /* Single-input selector units are ignored. */           if (entity->bNrInPins == 1)               break;           if (chain->selector != NULL) {               uvc_trace(UVC_TRACE_DESCR, "Found multiple Selector Units in chain.\n");               return -1;           }           chain->selector = entity;    //如果是選擇器Unit則設置其為uvc視頻鏈的selector對象           break;       case UVC_ITT_VENDOR_SPECIFIC:   //廠商特殊       case UVC_ITT_CAMERA:    //輸入Terminal camera       case UVC_ITT_MEDIA_TRANSPORT_INPUT: //輸入Terminal Media transport           if (uvc_trace_param & UVC_TRACE_PROBE)               printk(" <- IT %d\n", entity->id);           break;       case UVC_TT_STREAMING:  //輸入Terminal stream           if (UVC_ENTITY_IS_ITERM(entity)) {               if (uvc_trace_param & UVC_TRACE_PROBE)                   printk(" <- IT %d\n", entity->id);           }            else {               if (uvc_trace_param & UVC_TRACE_PROBE)                   printk(" OT %d", entity->id);           }           break;       default:           uvc_trace(UVC_TRACE_DESCR, "Unsupported entity type 0x%04x found in chain.\n", UVC_ENTITY_TYPE(entity));           return -1;       }       list_add_tail(&entity->chain, &chain->entities);  //添加到uvc視頻鏈的實體鏈表       return 0;   }   10.3.2 向前掃描實體 [cpp]   static int uvc_scan_chain_forward(struct uvc_video_chain *chain,struct uvc_entity *entity, struct uvc_entity *prev)   {       struct uvc_entity *forward;       int found;       /* Forward scan */       forward = NULL;       found = 0;       while (1) { //獲取實體前面的所以實體處理直到前面的實體forward=NULL為止跳出死循環           forward = uvc_entity_by_reference(chain->dev, entity->id,forward);    //獲取前一個實體           if (forward == NULL)               break;           if (forward == prev)               continue;           switch (UVC_ENTITY_TYPE(forward)) {           case UVC_VC_EXTENSION_UNIT: //擴展Unit               if (forward->bNrInPins != 1) {                   uvc_trace(UVC_TRACE_DESCR, "Extension unit %d has more than 1 input pin.\n",entity->id);                   return -EINVAL;               }               list_add_tail(&forward->chain, &chain->entities); //添加uvc實體到uvc視頻鏈的entities中               if (uvc_trace_param & UVC_TRACE_PROBE) {                   if (!found)                       printk(" (->");                   printk(" XU %d", forward->id);                   found = 1;               }               break;           case UVC_OTT_VENDOR_SPECIFIC:   //廠商特殊           case UVC_OTT_DISPLAY:   //輸出Termianl display           case UVC_OTT_MEDIA_TRANSPORT_OUTPUT:    //輸出Terminal media transport           case UVC_TT_STREAMING: //輸出Terminal stream               if (UVC_ENTITY_IS_ITERM(forward)) {                   uvc_trace(UVC_TRACE_DESCR, "Unsupported input terminal %u.\n", forward->id);                   return -EINVAL;               }               list_add_tail(&forward->chain, &chain->entities); //添加uvc實體到uvc視頻鏈的entities中               if (uvc_trace_param & UVC_TRACE_PROBE) {                   if (!found)                       printk(" (->");                   printk(" OT %d", forward->id);                   found = 1;               }               break;           }       }       if (found)           printk(")");       return 0;   }   10.3.3 向後掃描實體 [cpp]   static int uvc_scan_chain_backward(struct uvc_video_chain *chain,struct uvc_entity **_entity)   {       struct uvc_entity *entity = *_entity;       struct uvc_entity *term;       int id = -EINVAL, i;       switch (UVC_ENTITY_TYPE(entity)) {       case UVC_VC_EXTENSION_UNIT: //擴展Unit       case UVC_VC_PROCESSING_UNIT:    //處理Unit處理Unit的輸入Terminal個數只能為1           id = entity->baSourceID[0];  //獲取輸入pin(Unit/Terminal)的ID           break;       case UVC_VC_SELECTOR_UNIT:  //選擇器實體           /* Single-input selector units are ignored. */           if (entity->bNrInPins == 1) {    //若輸入pin個數為1               id = entity->baSourceID[0];  //獲取輸入in(Unit/Terminal)的ID               break;           }           if (uvc_trace_param & UVC_TRACE_PROBE)               printk(" <- IT");           chain->selector = entity;    //uvc視頻鏈的selector對象指向uvc實體           for (i = 0; i < entity->bNrInPins; ++i) { //總共有多少個輸入pin               id = entity->baSourceID[i];  //獲取輸入in(Unit/Terminal)的ID               term = uvc_entity_by_id(chain->dev, id); //獲取對應的輸入pin實體               if (term == NULL || !UVC_ENTITY_IS_ITERM(term)) {                   uvc_trace(UVC_TRACE_DESCR, "Selector unit %d input %d isn't connected to an input terminal\n", entity->id, i);                   return -1;               }               if (uvc_trace_param & UVC_TRACE_PROBE)                   printk(" %d", term->id);               list_add_tail(&term->chain, &chain->entities);    //添加uvc實體到uvc視頻鏈的entities鏈表               uvc_scan_chain_forward(chain, term, entity);    //向前掃描實體           }           if (uvc_trace_param & UVC_TRACE_PROBE)               printk("\n");           id = 0;           break;       case UVC_ITT_VENDOR_SPECIFIC:       case UVC_ITT_CAMERA:       case UVC_ITT_MEDIA_TRANSPORT_INPUT:       case UVC_OTT_VENDOR_SPECIFIC:       case UVC_OTT_DISPLAY:       case UVC_OTT_MEDIA_TRANSPORT_OUTPUT:       case UVC_TT_STREAMING:           id = UVC_ENTITY_IS_OTERM(entity) ? entity->baSourceID[0] : 0;           break;       }       if (id <= 0) {           *_entity = NULL;           return id;       }       entity = uvc_entity_by_id(chain->dev, id);       if (entity == NULL) {           uvc_trace(UVC_TRACE_DESCR, "Found reference to unknown entity %d.\n", id);           return -EINVAL;       }       *_entity = entity;       return 0;   }   注意到trace打印的語句會發現有一條 [cpp]   uvcvideo: Scanning UVC chain: OT 2 <- XU 5 <- XU 4 <- PU 3 <- IT 1   可以看到這些Unit和Terminal是如何組建起來的

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved