1. 程式人生 > >uvc攝像頭程式碼解析7

uvc攝像頭程式碼解析7

13.uvc視訊初始化 13.1 uvc資料流控制 [cpp  struct uvc_streaming_control {       __u16 bmHint;       __u8  bFormatIndex; //視訊格式索引       __u8  bFrameIndex;  //視訊幀索引       __u32 dwFrameInterval;  //視訊幀間隔       __u16 wKeyFrameRate;    //       __u16 wPFrameRate;       __u16 wCompQuality;       __u16 wCompWindowSize;       __u16 wDelay;   //延時       __u32 dwMaxVideoFrameSize;  //最大視訊幀大小       __u32 dwMaxPayloadTransferSize;       __u32 dwClockFrequency; //時鐘頻率       __u8  bmFramingInfo;       __u8  bPreferedVersion;       __u8  bMinVersion;  //版本       __u8  bMaxVersion;  //版本   } __attribute__((__packed__));   13.2 uvc_video_init [cpp]   int uvc_video_init(struct uvc_streaming *stream)   {       struct uvc_streaming_control *probe = &stream->ctrl; //獲取uvc資料流的uvs資料流控制物件       struct uvc_format *format = NULL;       struct uvc_frame *frame = NULL;       unsigned int i;       int ret;       if (stream->nformats == 0) {           uvc_printk(KERN_INFO, "No supported video formats found.\n");           return -EINVAL;       }       atomic_set(&stream->active, 0);       uvc_queue_init(&stream->queue, stream->type, !uvc_no_drop_param); //初始化視訊緩衝區佇列       usb_set_interface(stream->dev->udev, stream->intfnum, 0);  //選擇Alt.Setting 0       if (uvc_get_video_ctrl(stream, probe, 1, UVC_GET_DEF) == 0) //VS_PROBE_CONTROL(GET_DEF)           uvc_set_video_ctrl(stream, probe, 1);                   //VS_PROBE_CONTROL(SET_DEF)       ret = uvc_get_video_ctrl(stream, probe, 1, UVC_GET_CUR);    //VS_PROBE_CONTROL(GET_CUR)       if (ret < 0)           return ret;       for (i = stream->nformats; i > 0; --i) {  //獲取對應的uvc格式           format = &stream->format[i-1];              if (format->index == probe->bFormatIndex) //匹配uvc格式索引值               break;       }       if (format->nframes == 0) {           uvc_printk(KERN_INFO, "No frame descriptor found for the default format.\n");           return -EINVAL;       }       for (i = format->nframes; i > 0; --i) {           frame = &format->frame[i-1]; //獲取對應的uvc幀           if (frame->bFrameIndex == probe->bFrameIndex) //匹配uvc幀索引值               break;       }       probe->bFormatIndex = format->index;      //設定uvc視訊流控制的格式索引為uvc格式的索引       probe->bFrameIndex = frame->bFrameIndex;  //設定uvc視訊流控制的幀索引為uvc幀的索引       stream->cur_format = format;             //設定uvc格式為uvc資料流的cur_format成員       stream->cur_frame = frame;                   //設定uvc幀未uvc資料流的cur_frame成員       /* Select the video decoding function 選擇視訊解碼函式*/       if (stream->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {   //視訊採集           if (stream->dev->quirks & UVC_QUIRK_BUILTIN_ISIGHT)               stream->decode = uvc_video_decode_isight;           else if (stream->intf->num_altsetting > 1)               stream->decode = uvc_video_decode_isoc;  //同步方式           else               stream->decode = uvc_video_decode_bulk;  //bluk方式       }        else {  //視訊播放           if (stream->intf->num_altsetting == 1)               stream->decode = uvc_video_encode_bulk;           else {               uvc_printk(KERN_INFO, "Isochronous endpoints are not supported for video output devices.\n");               return -EINVAL;           }       }       return 0;   }   13.2.1 初始化uvc佇列 [cpp]   void uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type,int drop_corrupted)   {       mutex_init(&queue->mutex);       spin_lock_init(&queue->irqlock);       INIT_LIST_HEAD(&queue->mainqueue);   //初始化uvc視訊佇列mainqueue連結串列       INIT_LIST_HEAD(&queue->irqqueue);    //初始化uvc視訊佇列irqqueue連結串列       queue->flags = drop_corrupted ? UVC_QUEUE_DROP_CORRUPTED : 0;       queue->type = type;   }   14.uvc V4L2裝置 14.1 V4L2操作函式集 [cpp]  const struct v4l2_file_operations uvc_fops = {       .owner      = THIS_MODULE,       .open       = uvc_v4l2_open,    //開啟方法       .release             = uvc_v4l2_release,    //釋放方法       .unlocked_ioctl = uvc_v4l2_ioctl,   //控制方法       .read       = uvc_v4l2_read,    //讀方法       .mmap       = uvc_v4l2_mmap,    //對映方法       .poll       = uvc_v4l2_poll,    //輪詢方法   };   14.2 開啟方法 14.2.1 相關結構體 [cpp]   struct uvc_fh {//uvc控制代碼       struct uvc_video_chain *chain;  //uvc視訊鏈       struct uvc_streaming *stream;   //uvc視訊流       enum uvc_handle_state state;   };   14.2.2 open [cpp]   static int uvc_v4l2_open(struct file *file)   {       struct uvc_streaming *stream;       struct uvc_fh *handle;       int ret = 0;       uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_open\n");       stream = video_drvdata(file);   //獲取uvc視訊流       if (stream->dev->state & UVC_DEV_DISCONNECTED)    //裝置沒連線           return -ENODEV;       ret = usb_autopm_get_interface(stream->dev->intf);    //喚醒裝置       if (ret < 0)           return ret;       /* Create the device handle. */       handle = kzalloc(sizeof *handle, GFP_KERNEL);   //建立uvc控制代碼       if (handle == NULL) {           usb_autopm_put_interface(stream->dev->intf);           return -ENOMEM;       }       if (atomic_inc_return(&stream->dev->users) == 1) {           ret = uvc_status_start(stream->dev); //uvc狀態開始           if (ret < 0) {               usb_autopm_put_interface(stream->dev->intf);               atomic_dec(&stream->dev->users);               kfree(handle);               return ret;           }       }       handle->chain = stream->chain;    //捆綁uvc控制代碼和uvc視訊鏈       handle->stream = stream; //捆綁uvc控制代碼和uvc視訊流       handle->state = UVC_HANDLE_PASSIVE;  //設定uvc狀態為未啟用       file->private_data = handle; //將uvc控制代碼作為檔案的私有資料       return 0;   }   14.2.2.1 uvc_status_start啟動狀態 [cpp]   int uvc_status_start(struct uvc_device *dev)   {       if (dev->int_urb == NULL)           return 0;       return usb_submit_urb(dev->int_urb, GFP_KERNEL); //提交urb   }   參看 12.uvc狀態初始化 14.3 控制方法 14.3.1 V4L2的控制方式可以參考下面的資料 linux媒體介面API 常用的命令 [cpp]   VIDIOC_REQBUFS:分配記憶體    VIDIOC_QUERYBUF:把VIDIOC_REQBUFS中分配的資料快取轉換成實體地址    VIDIOC_QUERYCAP:查詢驅動功能    VIDIOC_ENUM_FMT:獲取當前驅動支援的視訊格式    VIDIOC_S_FMT:設定當前驅動的頻捕獲格式    VIDIOC_G_FMT:讀取當前驅動的頻捕獲格式    VIDIOC_TRY_FMT:驗證當前驅動的顯示格式    VIDIOC_CROPCAP:查詢驅動的修剪能力    VIDIOC_S_CROP:設定視訊訊號的邊框    VIDIOC_G_CROP:讀取視訊訊號的邊框    VIDIOC_QBUF:把資料從快取中讀取出來    VIDIOC_DQBUF:把資料放回快取佇列    VIDIOC_STREAMON:開始視訊顯示函式    VIDIOC_STREAMOFF:結束視訊顯示函式    VIDIOC_QUERYSTD:檢查當前視訊裝置支援的標準,例如PAL或NTSC。    14.3.2 uvc裝置V4L2控制方法uvc_v4l2_do_ioctl [cpp]   static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)   {       struct video_device *vdev = video_devdata(file);//獲取V4L2裝置       struct uvc_fh *handle = file->private_data;//獲取uvc控制代碼       struct uvc_video_chain *chain = handle->chain;//獲取uvc視訊鏈       struct uvc_streaming *stream = handle->stream;//獲取uvc視訊流       long ret = 0;       switch (cmd) {       ...       case ...:       {           ...           break;       }       return ret;   }   a.VIDIOC_STREAMON 開始視訊顯示函式 [cpp]   <pre class="cpp" name="code">   case VIDIOC_STREAMON:       {           int *type = arg;           if (*type != stream->type)               return -EINVAL;           if (!uvc_has_privileges(handle))               return -EBUSY;           mutex_lock(&stream->mutex);           ret = uvc_video_enable(stream, 1);  //uvc視訊流使能           mutex_unlock(&stream->mutex);           if (ret < 0)               return ret;           break;       }</pre>a.1 uvc視訊流使能<br>   <pre class="cpp" name="code">int uvc_video_enable(struct uvc_streaming *stream, int enable)   {       int ret;       if (!enable) {           uvc_uninit_video(stream, 1);//逆初始化視訊           usb_set_interface(stream->dev->udev, stream->intfnum, 0);           uvc_queue_enable(&stream->queue, 0);//uvc禁用佇列           return 0;       }       ret = uvc_queue_enable(&stream->queue, 1);   //uvc使能佇列       if (ret < 0)           return ret;       /* Commit the streaming parameters. */       ret = uvc_commit_video(stream, &stream->ctrl);   //uvc提交視訊引數       if (ret < 0)           return ret;       return uvc_init_video(stream, GFP_KERNEL);  //uvc初始化視訊   }</pre>a.1.1 uvc使能佇列   <pre></pre>   <pre class="cpp" name="code"><pre class="cpp" name="code">static int uvc_queue_enable(struct uvc_video_queue *queue, int enable)   {       unsigned int i;       int ret = 0;       mutex_lock(&queue->mutex);       if (enable) {   //使能uvc佇列           if (uvc_queue_streaming(queue)) {   //判斷佇列標誌是否為UVC_QUEUE_STREAMING               ret = -EBUSY;               goto done;           }           queue->sequence = 0;           queue->flags |= UVC_QUEUE_STREAMING; //設定佇列標誌           queue->buf_used = 0; //設定緩衝區使用標誌       }        else {           uvc_queue_cancel(queue, 0); //取消uvc佇列           INIT_LIST_HEAD(&queue->mainqueue);   //重新初始化uvc佇列mainqueue佇列頭           for (i = 0; i < queue->count; ++i)               queue->buffer[i].state = UVC_BUF_STATE_IDLE; //設定緩衝區狀態為閒置態           queue->flags &= ~UVC_QUEUE_STREAMING;    //設定佇列標誌       }   done:       mutex_unlock(&queue->mutex);       return ret;   }</pre>a.1.2 uvc提交視訊引數   <pre></pre>   <pre class="cpp" name="code"><pre class="cpp" name="code">int uvc_commit_video(struct uvc_streaming *stream,struct uvc_streaming_control *probe)   {       return uvc_set_video_ctrl(stream, probe, 0);    //uvc設定視訊控制   }</pre><span style="font-family:Arial,Helvetica,sans-serif">a.1.3 uvc初始化視訊</span>   <pre></pre>   <pre class="cpp" name="code"><pre class="cpp" name="code">static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags)   {       struct usb_interface *intf = stream->intf;       struct usb_host_endpoint *ep;       unsigned int i;       int ret;       stream->sequence = -1;       stream->last_fid = -1;       stream->bulk.header_size = 0;       stream->bulk.skip_payload = 0;       stream->bulk.payload_size = 0;       if (intf->num_altsetting > 1) {   //同步方式           struct usb_host_endpoint *best_ep = NULL;           unsigned int best_psize = 3 * 1024;           unsigned int bandwidth;           unsigned int uninitialized_var(altsetting);           int intfnum = stream->intfnum;           /* Isochronous endpoint, select the alternate setting. */           bandwidth = stream->ctrl.dwMaxPayloadTransferSize;           if (bandwidth == 0) {               uvc_trace(UVC_TRACE_VIDEO, "Device requested null bandwidth, defaulting to lowest.\n");               bandwidth = 1;           }            else {               uvc_trace(UVC_TRACE_VIDEO, "Device requested %u B/frame bandwidth.\n", bandwidth);           }           for (i = 0; i < intf->num_altsetting; ++i) {               struct usb_host_interface *alts;               unsigned int psize;               alts = &intf->altsetting[i];               ep = uvc_find_endpoint(alts,stream->header.bEndpointAddress);               if (ep == NULL)                   continue;               /* Check if the bandwidth is high enough. */               psize = le16_to_cpu(ep->desc.wMaxPacketSize);               psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3));               if (psize >= bandwidth && psize <= best_psize) {                   altsetting = i;                   best_psize = psize;                   best_ep = ep;               }           }           if (best_ep == NULL) {               uvc_trace(UVC_TRACE_VIDEO, "No fast enough alt setting for requested bandwidth.\n");               return -EIO;           }           uvc_trace(UVC_TRACE_VIDEO, "Selecting alternate setting %u (%u B/frame bandwidth).\n", altsetting, best_psize);           ret = usb_set_interface(stream->dev->udev, intfnum, altsetting);           if (ret < 0)               return ret;           ret = uvc_init_video_isoc(stream, best_ep, gfp_flags);  //uvc初始化視訊(同步方法)       }        else {  //Bulk方式           /* Bulk endpoint, proceed to URB initialization. */           ep = uvc_find_endpoint(&intf->altsetting[0],stream->header.bEndpointAddress);           if (ep == NULL)               return -EIO;           ret = uvc_init_video_bulk(stream, ep, gfp_flags);   //uvc初始化視訊(bulk方法)       }       if (ret < 0)           return ret;       /* Submit the URBs. */       for (i = 0; i < UVC_URBS; ++i) {           ret = usb_submit_urb(stream->urb[i], gfp_flags); //提交urb           if (ret < 0) {               uvc_printk(KERN_ERR, "Failed to submit URB %u (%d).\n", i, ret);               uvc_uninit_video(stream, 1);               return ret;           }       }       return 0;   }</pre>a.1.3.1 同步方式   <pre></pre>   <pre class="cpp" name="code"><pre class="cpp" name="code">static int uvc_init_video_isoc(struct uvc_streaming *stream,struct usb_host_endpoint *ep, gfp_t gfp_flags)   {       struct urb *urb;       unsigned int npackets, i, j;       u16 psize;       u32 size;       psize = le16_to_cpu(ep->desc.wMaxPacketSize);       psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3));       size = stream->ctrl.dwMaxVideoFrameSize;       npackets = uvc_alloc_urb_buffers(stream, size, psize, gfp_flags);   //分配urb緩衝區       if (npackets == 0)           return -ENOMEM;       size = npackets * psize;       for (i = 0; i < UVC_URBS; ++i) {           urb = usb_alloc_urb(npackets, gfp_flags);   //分配urb           if (urb == NULL) {               uvc_uninit_video(stream, 1);               return -ENOMEM;           }           urb->dev = stream->dev->udev;  //設定urb           urb->context = stream;           urb->pipe = usb_rcvisocpipe(stream->dev->udev,ep->desc.bEndpointAddress);           urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;           urb->interval = ep->desc.bInterval;           urb->transfer_buffer = stream->urb_buffer[i];           urb->transfer_dma = stream->urb_dma[i];           urb->complete = uvc_video_complete;           urb->number_of_packets = npackets;           urb->transfer_buffer_length = size;           for (j = 0; j < npackets; ++j) {               urb->iso_frame_desc[j].offset = j * psize;               urb->iso_frame_desc[j].length = psize;           }           stream->urb[i] = urb;       }       return 0;   }</pre><span style="font-family:Arial,Helvetica,sans-serif">a.1.3.2 Bluk方式</span>   <pre></pre>   <pre class="cpp" name="code"><pre class="cpp" name="code">static int uvc_init_video_bulk(struct uvc_streaming *stream,struct usb_host_endpoint *ep, gfp_t gfp_flags)   {       struct urb *urb;       unsigned int npackets, pipe, i;       u16 psize;  

相關推薦

uvc攝像頭程式碼解析7

13.uvc視訊初始化 13.1 uvc資料流控制 [cpp  struct uvc_streaming_control {       __u16 bmHint;       __u8  bFormatIndex; //視訊格式索引       __u8  b

uvc攝像頭程式碼解析5

8.初始化uvc控制 8.1 重要結構體 struct uvc_control { //uvc控制 struct uvc_entity *entity; //uvc實體 struct uvc_control_info info; //uvc控制資訊 __u8 ind

uvc攝像頭程式碼解析6

10.掃描視訊裝置鏈和註冊視訊裝置 10.1 uvc視訊鏈 struct uvc_video_chain { //uvc視訊鏈 struct uvc_device *dev; //uvc裝置 struct list_head list; //uvc視訊鏈連結串列

uvc攝像頭程式碼解析之描述符

module_init(uvc_init); //1.模組入口 2.初始化函式 static int __init uvc_init(void) // 2.初始化函式 { int result; result = usb_register(&uvc_driver.driver); // 3

iTOP-4412開發板-QtE4.7-UVC攝像頭使用例程

只有一個 tftp 命令 文件拷貝 用例 qmake 添加 攝像頭 更新 本文檔主要介紹 迅為iTOP-4412 開發板 QtE4.7 系統下 UVC 攝像頭的使用過程。 工程文件是:“iTOP-4412-QtE4.7-UVC_V1.0”(註意版本更新)。用戶可以直接運行

專題一經典問題解析-7

ons 需要 可執行 const 不同 結果 width 進行 什麽是 一。const和引用的疑惑 #include <stdio.h> int main() { const int x = 1; const int& rx = x;

wordcount 程式碼解析

MapRuduce map表示對映 reduce表示化簡。它的思想就是‘分而治之’,具體思想就不用說了 這裡主要解析wordcount原始碼。程式碼裡的思想是一直是K,V對(鍵值對)傳輸的重要的是map ()、reduce()兩個函式。 main方法裡主要job作業的配置、啟動

GraphSAGE 程式碼解析 - minibatch.py

class EdgeMinibatchIterator """ This minibatch iterator iterates over batches of sampled edges or random pairs of co-occuring edges.

Faster RCNN演算法訓練程式碼解析(2)

接著上篇的部落格,我們獲取imdb和roidb的資料後,就可以搭建網路進行訓練了。 我們回到trian_rpn()函式裡面,此時執行完了roidb, imdb = get_roidb(imdb_name),取得了imdb和roidb資料。 先進入第一階段的訓練:   print

Faster RCNN演算法訓練程式碼解析(3)

四個層的forward函式分析: RoIDataLayer:讀資料,隨機打亂等 AnchorTargetLayer:輸出所有anchors(這裡分析這個) ProposalLayer:用產生的anchors平移整圖,裁剪出界、移除低於閾值的的anchors,排序後使用nms,返回頂部排名的anchors

Matlab程式設計之——卷積神經網路CNN程式碼解析

卷積神經網路CNN程式碼解析 deepLearnToolbox-master是一個深度學習matlab包,裡面含有很多機器學習演算法,如卷積神經網路CNN,深度信念網路DBN,自動編碼AutoE ncoder(堆疊SAE,卷積CAE)的作者是 RasmusBerg Palm 今天給介紹d

GraphSAGE 程式碼解析(四) - models.py

1. 類及其繼承關係 Model / \ / \ MLP GeneralizedModel / \ / \ Node2VecModel SampleAndAggregate 首先看Model, Ge

GraphSAGE 程式碼解析(三) - aggregators.py

1. class MeanAggregator(Layer): 該類主要用於實現 1. __init__()  __init_() 用於獲取並初始化成員變數 dropout, bias(False), act(ReLu), concat(False), input_dim, output_

載入本地攝像頭完全解析opencv

#QQ群:476842922(歡迎加群討論學習) import cv2 import numpy as np #表示開啟筆記本的內建攝像頭,引數是視訊檔案路徑則開啟視訊 cv2.VideoCapture("../test.avi") cap = cv2.VideoCapture(0) whi

opencv實現螢幕錄製程式碼解析

# -*- coding: utf-8 -*- """ Created on Thu Nov 15 22:37:02 2018 #QQ群:476842922(歡迎加群討論學習) @author: Administrator """ """python + opencv 實現螢幕錄製""" f

C語言程式設計狼追兔子問題程式碼解析

問題描述 一隻兔子躲進了10個環形分佈的洞中的一個。狼在第一個洞中沒有找到兔子,就隔一個洞,到第3個洞去找;也沒有找到,就隔2個洞,到第6個洞去找;以後每次多一個洞去找兔子……這樣下去,如果一直找不到兔子,請問兔子可能在哪個洞中? 問題分析 首先定義一個數組a[11],其陣列元素為a[1],a[2],a

C語言解決常勝將軍問題程式碼解析

問題描述 有21根火柴,兩人依次取,每次每人只可取走1〜4根,不能多取,也不能不取,誰取到最後一根火柴誰輸。請編寫一個人機對弈程式,要求人先取,計算機後取;計算機為“常勝將軍”。 問題分析 可以這樣思考這個問題:要想讓計算機是“常勝將軍”,也就是要讓人取到最後一根火柴。這樣只有一種可能,那就是讓計算機只

筆記-爬蟲-js程式碼解析

筆記-爬蟲-js程式碼解析   1.      js程式碼解析 1.1.    前言 在爬取網站時經常會有js生成關鍵資訊,而且js程式碼是混淆過的。 以瓜子二手車為例,直接請求https://www.guaz

keras/examples/mnist_acgan.py ACGAN程式碼解析

  # -*- coding: utf-8 -*- """ Train an Auxiliary Classifier Generative Adversarial Network (ACGAN) on the MNIST dataset. See https://arxiv.org/

經典裝飾器程式碼解析

程式碼: def A(funC): def B(funE): def C(*args, **kwargs): out = funC(funE)(*args,**kwargs) return out + "...111