主頁 > 軟體工程 > Hi3559AV100外接UVC/MJPEG相機實時采圖設計(一):Linux USB攝像頭驅動分析

Hi3559AV100外接UVC/MJPEG相機實時采圖設計(一):Linux USB攝像頭驅動分析

2021-02-13 06:19:30 軟體工程

  下面將給出Hi3559AV100外接UVC/MJPEG相機實時采圖設計的整體流程,主要實作是通過V4L2介面將UVC/MJPEG相機采集的資料送入至MPP平臺,經過VDEC、VPSS、VO最后通過HDMI的輸出,首先給出(一)Linux USB攝像頭驅動加載與分析,

板載平臺:BOXER-8410AI

芯片型號:Hi3559AV100

相機型號:Logitch c270

開發環境:VM15.5+ubuntu16.04+Hilinux

1、確定USB攝像頭支持UVC

  首先,可以把USB攝像頭插在PC端,然后通過設備管理器找到相機,右鍵選擇屬性,選擇詳細資訊,更改屬性一欄,選擇硬體ID,從中可以看到USB攝像頭的VID和PID,比如Logitech c270的ID號為:046d:0825,之后通過這個網頁 http://www.ideasonboard.org/uvc/ 來查看是否支持 UVC,這個網站是 USB Video Class Linux device driver 的主頁,里面有 UVC 的詳細的介紹,根據前面的列印資訊,根據自己的 ID 號, 這里是搜索 USB 攝像頭的 VID 號:046d 和 PID 號:0825,主頁如下所示:

  通過攝像頭的 ID,可以看到該攝像頭是否支持 UVC 和其他資訊,綠勾代表支持,

2、配置與相機型號匹配的USB host驅動

  目前Hilinux系統自帶了部分型號的usb攝像頭驅動,但并不是支持所有市面上usb攝像頭,像Logitch c270這一款usb攝像頭就不支持,如果說linux kernel驅動中不支持,需要我們重新配置該驅動,或者需要進行裁剪等操作,而這個程序需要我們進行手動配置,配置程序如下:在內核目錄下,輸入如下命令(以emmc啟動為例):

 1         待進入內核源代碼目錄后,執行以下操作
 2 
 3         cp arch/arm64/configs/hi3559av100_arm64_big_little_emmc_defconfig .config
 4 
 5 
 6         make ARCH=arm64 CROSS_COMPILE=aarch64-himix100-linux- menuconfig
 7 
 8 
 9         cp .config arch/arm64/configs/hi3559av100_arm64_big_little_emmc_defconfig
10 
11 
12         osdrv頂層目錄下執行:make BOOT_MEDIA=emmc AMP_TYPE=linux atf

 

執行 make ARCH=arm64 CROSS_COMPILE=aarch64-himix100-linux- menuconfig 后,彈出如下視窗:

之后進行驅動配置,打開UVC驅動等等,

  在配置好之后,彈出menuconfig視窗后,記得保存,保存完之后在手動修改usb驅動代碼:修改位置如下:

linux-xxx\drivers\media\usb\uvc\uvc_driver.c

  設備插入時呼叫probe將會按默認的id_table來加載驅動,也就是這個uvc_ids末尾說的Generic USB Video Class,具體如下所示:

1     /* Generic USB Video Class */
2     { USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, UVC_PC_PROTOCOL_UNDEFINED) },
3     { USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, UVC_PC_PROTOCOL_15) },
4     {}

  struct usb_device_id uvc_ids[]中模仿之前的加上自己的USB設備資訊:

1     { .match_flags        = USB_DEVICE_ID_MATCH_DEVICE
2                 | USB_DEVICE_ID_MATCH_INT_INFO,
3       .idVendor        = 0x046d,
4       .idProduct        = 0x0825,
5       .bInterfaceClass    = USB_CLASS_VIDEO,
6       .bInterfaceSubClass    = 1,
7       .bInterfaceProtocol    = 0,
8       .driver_info        = UVC_QUIRK_RESTORE_CTRLS_ON_INIT },

  注意一下這個driver_info的賦值,可以用來限制幀率,UVC_QUIRK_RESTORE_CTRLS_ON_INIT的值是0x400,這個設定好像是跟帶寬有關系,沒有深入了解,如果設的過小,將導致無法出圖,而且USB2.0的帶寬上限也只有480Mbit/s,連一個攝像頭都夠嗆了,修改完之后,還需要重新編譯內核,

  之后將攝像頭插在板載上,終端出現如下:

   也可以通過命令ls /dev/video*查看video設備,如下所示, 到此驅動部分添加完成,

 1 /dev/video0                                                      

 3、UVC driver的研究

  上述終端顯示的資訊是由uvc_probe()函式輸出,對應函式位置為linux-xxx\drivers\media\usb\uvc\uvc_driver.c,函式具體內容如下:

  1 static int uvc_probe(struct usb_interface *intf,
  2              const struct usb_device_id *id)
  3 {
  4     struct usb_device *udev = interface_to_usbdev(intf);
  5     struct uvc_device *dev;
  6     int ret;
  7 
  8     if (id->idVendor && id->idProduct)
  9         uvc_trace(UVC_TRACE_PROBE, "Probing known UVC device %s "
 10                 "(%04x:%04x)\n", udev->devpath, id->idVendor,
 11                 id->idProduct);
 12     else
 13         uvc_trace(UVC_TRACE_PROBE, "Probing generic UVC device %s\n",
 14                 udev->devpath);
 15 
 16     /* Allocate memory for the device and initialize it. */
 17     if ((dev = kzalloc(sizeof *dev, GFP_KERNEL)) == NULL)
 18         return -ENOMEM;
 19 
 20     INIT_LIST_HEAD(&dev->entities);
 21     INIT_LIST_HEAD(&dev->chains);
 22     INIT_LIST_HEAD(&dev->streams);
 23     atomic_set(&dev->nstreams, 0);
 24     atomic_set(&dev->nmappings, 0);
 25     mutex_init(&dev->lock);
 26 
 27     dev->udev = usb_get_dev(udev);
 28     dev->intf = usb_get_intf(intf);
 29     dev->intfnum = intf->cur_altsetting->desc.bInterfaceNumber;
 30     dev->quirks = (uvc_quirks_param == -1)
 31             ? id->driver_info : uvc_quirks_param;
 32 
 33     if (udev->product != NULL)
 34         strlcpy(dev->name, udev->product, sizeof dev->name);
 35     else
 36         snprintf(dev->name, sizeof dev->name,
 37             "UVC Camera (%04x:%04x)",
 38             le16_to_cpu(udev->descriptor.idVendor),
 39             le16_to_cpu(udev->descriptor.idProduct));
 40 
 41     /* Parse the Video Class control descriptor. */
 42     if (uvc_parse_control(dev) < 0) {
 43         uvc_trace(UVC_TRACE_PROBE, "Unable to parse UVC "
 44             "descriptors.\n");
 45         goto error;
 46     }
 47 
 48     uvc_printk(KERN_INFO, "Found UVC %u.%02x device %s (%04x:%04x)\n",
 49         dev->uvc_version >> 8, dev->uvc_version & 0xff,
 50         udev->product ? udev->product : "<unnamed>",
 51         le16_to_cpu(udev->descriptor.idVendor),
 52         le16_to_cpu(udev->descriptor.idProduct));
 53 
 54     if (dev->quirks != id->driver_info) {
 55         uvc_printk(KERN_INFO, "Forcing device quirks to 0x%x by module "
 56             "parameter for testing purpose.\n", dev->quirks);
 57         uvc_printk(KERN_INFO, "Please report required quirks to the "
 58             "linux-uvc-devel mailing list.\n");
 59     }
 60 
 61     /* Initialize the media device and register the V4L2 device. */
 62 #ifdef CONFIG_MEDIA_CONTROLLER
 63     dev->mdev.dev = &intf->dev;
 64     strlcpy(dev->mdev.model, dev->name, sizeof(dev->mdev.model));
 65     if (udev->serial)
 66         strlcpy(dev->mdev.serial, udev->serial,
 67             sizeof(dev->mdev.serial));
 68     strcpy(dev->mdev.bus_info, udev->devpath);
 69     dev->mdev.hw_revision = le16_to_cpu(udev->descriptor.bcdDevice);
 70     dev->mdev.driver_version = LINUX_VERSION_CODE;
 71     media_device_init(&dev->mdev);
 72 
 73     dev->vdev.mdev = &dev->mdev;
 74 #endif
 75     if (v4l2_device_register(&intf->dev, &dev->vdev) < 0)
 76         goto error;
 77 
 78     /* Initialize controls. */
 79     if (uvc_ctrl_init_device(dev) < 0)
 80         goto error;
 81 
 82     /* Scan the device for video chains. */
 83     if (uvc_scan_device(dev) < 0)
 84         goto error;
 85 
 86     /* Register video device nodes. */
 87     if (uvc_register_chains(dev) < 0)
 88         goto error;
 89 
 90 #ifdef CONFIG_MEDIA_CONTROLLER
 91     /* Register the media device node */
 92     if (media_device_register(&dev->mdev) < 0)
 93         goto error;
 94 #endif
 95     /* Save our data pointer in the interface data. */
 96     usb_set_intfdata(intf, dev);
 97 
 98     /* Initialize the interrupt URB. */
 99     if ((ret = uvc_status_init(dev)) < 0) {
100         uvc_printk(KERN_INFO, "Unable to initialize the status "
101             "endpoint (%d), status interrupt will not be "
102             "supported.\n", ret);
103     }
104 
105     uvc_trace(UVC_TRACE_PROBE, "UVC device initialized.\n");
106     usb_enable_autosuspend(udev);
107     return 0;
108 
109 error:
110     uvc_unregister_video(dev);
111     return -ENODEV;
112 }
  對于初始kernel內核USB驅動應該是加載了一部分支持 UVC 攝像頭的驅動,在默認的uvc_driver 下,是沒有我們攝像頭 046d 0825 ID 號的,需要我們手動添加,當內核發現與 uvc_ids 匹配的 USB 攝像頭就會呼叫 uvc_probe 函式,一旦內核發現插入的 USB 攝像頭被匹配后,最終就會呼叫 uvc_probe 函式,   USB攝像頭驅動其實就是一個字符設備驅動,重點關注v4l2_fops結構體,如下所示:
 1 static const struct file_operations v4l2_fops = {
 2     .owner = THIS_MODULE,
 3     .read = v4l2_read,
 4     .write = v4l2_write,
 5     .open = v4l2_open,
 6     .get_unmapped_area = v4l2_get_unmapped_area,
 7     .mmap = v4l2_mmap,
 8     .unlocked_ioctl = v4l2_ioctl,
 9 #ifdef CONFIG_COMPAT
10     .compat_ioctl = v4l2_compat_ioctl32,
11 #endif
12     .release = v4l2_release,
13     .poll = v4l2_poll,
14     .llseek = no_llseek,
15 };
  而USB攝像頭結合V4L2介面時,當應用程式呼叫 open 函式,例如: open("/dev/video0",....),首先就會呼叫到 v4l2 核心里的 open 函式,也就是 v4l2_open 函式(v4l2-dev.c),而在v4l2-open 函式中呼叫了 vdev->fops->open(filp),相當于呼叫 uvc_v4l2_open()函式,這個函式的實作在\drivers\media\usb\uvc\uvc_v4l2.c 里,同樣地,vdev->fops->unlocked_ioctl(filp,cmd,arg)(v4l2-dev.c);最后相當于呼叫 uvc_v4l2_ioctl()函式,它又呼叫 video_usercopy(file,cmd,arg,uvc_v4l2_do_ioctl);函式,video_usercopy()函式的作用從名字上可以猜測,它是根據用戶空間傳遞過來的 cmd 命令,呼叫 uvc_v4l2_do_ioctl()函式來決議 arg 引數,   ctrl 屬性的函式呼叫流程   uvc_probe     uvc_register_chains       uvc_register_terms         uvc_register_video           video_register_device__video_register_device             determine_valid_ioctls   這些 ctrl 屬性就是 USB 攝像頭的各種屬性,比如亮度的調節,打開、關閉STREAM 等等操作,這些是 v4l2 核心最最復雜的作業了,沒有之一, 參考: \drivers\media\v4l2-core\v4l2-dev.c

轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/259126.html

標籤:其他

上一篇:Hi3559AV100外接UVC/MJPEG相機實時采圖設計(一):Linux USB攝像頭驅動分析

下一篇:為什么我的程式占CPU資源35% 這么多

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • Git本地庫既關聯GitHub又關聯Gitee

    創建代碼倉庫 使用gitee舉例(github和gitee差不多) 1.在gitee右上角點擊+,選擇新建倉庫 ? 2.選擇填寫倉庫資訊,然后進行創建 ? 3.服務端已經準備好了,本地開始作準備 (1)Git 全域設定 git config --global user.name "成鈺" git c ......

    uj5u.com 2020-09-10 05:04:14 more
  • CODING DevOps 代碼質量實戰系列第二課,相約周三

    隨著 ToB(企業服務)的興起和 ToC(消費互聯網)產品進入成熟期,線上故障帶來的損失越來越大,代碼質量越來越重要,而「質量內建」正是 DevOps 核心理念之一。**《DevOps 代碼質量實戰(PHP 版)》**為 CODING DevOps 代碼質量實戰系列的第二課,同時也是本系列的 PHP ......

    uj5u.com 2020-09-10 05:07:43 more
  • 推薦Scrum書籍

    推薦Scrum書籍 直接上干貨,推薦書籍清單如下(推薦有順序的哦) Scrum指南 Scrum精髓 Scrum敏捷軟體開發 Scrum捷徑 硝煙中的Scrum和XP : 我們如何實施Scrum 敏捷軟體開發:Scrum實戰指南 Scrum要素 大規模Scrum:大規模敏捷組織的設計 用戶故事地圖 用 ......

    uj5u.com 2020-09-10 05:07:45 more
  • CODING DevOps 代碼質量實戰系列最后一課,周四發車

    隨著 ToB(企業服務)的興起和 ToC(消費互聯網)產品進入成熟期,線上故障帶來的損失越來越大,代碼質量越來越重要,而「質量內建」正是 DevOps 核心理念之一。 **《DevOps 代碼質量實戰(Java 版)》**為 CODING DevOps 代碼質量實戰系列的最后一課,同時也是本系列的 ......

    uj5u.com 2020-09-10 05:07:52 more
  • 敏捷軟體工程實踐書籍

    Scrum轉型想要做好,第一步先了解并真正落實Scrum,那么我推薦的Scrum書籍是要看懂并實踐的。第二步是團隊的工程實踐要做扎實。 下面推薦工程實踐書單: 重構:改善既有代碼的設計 決議極限編程 : 擁抱變化 代碼整潔代碼 程式員的職業素養 修改代碼的藝術 撰寫可讀代碼的藝術 測驗驅動開發 : ......

    uj5u.com 2020-09-10 05:07:55 more
  • Jenkins+svn+nginx實作windows環境自動部署vue前端專案

    前面文章介紹了Jenkins+svn+tomcat實作自動化部署,現在終于有空抽時間出來寫下Jenkins+svn+nginx實作自動部署vue前端專案。 jenkins的安裝和配置已經在前面文章進行介紹,下面介紹實作vue前端專案需要進行的哪些額外的步驟。 注意:在安裝jenkins和nginx的 ......

    uj5u.com 2020-09-10 05:08:49 more
  • CODING DevOps 微服務專案實戰系列第一課,明天等你

    CODING DevOps 微服務專案實戰系列第一課**《DevOps 微服務專案實戰:DevOps 初體驗》**將由 CODING DevOps 開發工程師 王寬老師 向大家介紹 DevOps 的基本理念,并探討為什么現代開發活動需要 DevOps,同時將以 eShopOnContainers 項 ......

    uj5u.com 2020-09-10 05:09:14 more
  • CODING DevOps 微服務專案實戰系列第二課來啦!

    近年來,工程專案的結構越來越復雜,需要接入合適的持續集成流水線形式,才能滿足更多變的需求,那么如何優雅地使用 CI 能力提升生產效率呢?CODING DevOps 微服務專案實戰系列第二課 《DevOps 微服務專案實戰:CI 進階用法》 將由 CODING DevOps 全堆疊工程師 何晨哲老師 向 ......

    uj5u.com 2020-09-10 05:09:33 more
  • CODING DevOps 微服務專案實戰系列最后一課,周四開講!

    隨著軟體工程越來越復雜化,如何在 Kubernetes 集群進行灰度發布成為了生產部署的”必修課“,而如何實作安全可控、自動化的灰度發布也成為了持續部署重點關注的問題。CODING DevOps 微服務專案實戰系列最后一課:**《DevOps 微服務專案實戰:基于 Nginx-ingress 的自動 ......

    uj5u.com 2020-09-10 05:10:00 more
  • CODING 儀表盤功能正式推出,實作作業資料可視化!

    CODING 儀表盤功能現已正式推出!該功能旨在用一張張統計卡片的形式,統計并展示使用 CODING 中所產生的資料。這意味著無需額外的設定,就可以收集歸納寶貴的作業資料并予之量化分析。這些海量的資料皆會以圖表或串列的方式躍然紙上,方便團隊成員隨時查看各專案的進度、狀態和指標,云端協作迎來真正意義上 ......

    uj5u.com 2020-09-10 05:11:01 more
最新发布
  • windows系統git使用ssh方式和gitee/github進行同步

    使用git來clone專案有兩種方式:HTTPS和SSH:
    HTTPS:不管是誰,拿到url隨便clone,但是在push的時候需要驗證用戶名和密碼;
    SSH:clone的專案你必須是擁有者或者管理員,而且需要在clone前添加SSH Key。SSH 在push的時候,是不需要輸入用戶名的,如果配置... ......

    uj5u.com 2023-04-19 08:41:12 more
  • windows系統git使用ssh方式和gitee/github進行同步

    使用git來clone專案有兩種方式:HTTPS和SSH:
    HTTPS:不管是誰,拿到url隨便clone,但是在push的時候需要驗證用戶名和密碼;
    SSH:clone的專案你必須是擁有者或者管理員,而且需要在clone前添加SSH Key。SSH 在push的時候,是不需要輸入用戶名的,如果配置... ......

    uj5u.com 2023-04-19 08:35:34 more
  • 2023年農牧行業6大CRM系統、5大場景盤點

    在物聯網、大資料、云計算、人工智能、自動化技術等現代資訊技術蓬勃發展與逐步成熟的背景下,數字化正成為農牧行業供給側結構性變革與高質量發展的核心驅動因素。因此,改造和提升傳統農牧業、開拓創新現代智慧農牧業,加快推進農牧業的現代化、資訊化、數字化建設已成為農牧業發展的重要方向。 當下,企業數字化轉型已經 ......

    uj5u.com 2023-04-18 08:05:44 more
  • 2023年農牧行業6大CRM系統、5大場景盤點

    在物聯網、大資料、云計算、人工智能、自動化技術等現代資訊技術蓬勃發展與逐步成熟的背景下,數字化正成為農牧行業供給側結構性變革與高質量發展的核心驅動因素。因此,改造和提升傳統農牧業、開拓創新現代智慧農牧業,加快推進農牧業的現代化、資訊化、數字化建設已成為農牧業發展的重要方向。 當下,企業數字化轉型已經 ......

    uj5u.com 2023-04-18 08:00:18 more
  • 計算機組成原理—存盤器

    計算機組成原理—硬體結構 二、存盤器 1.概述 存盤器是計算機系統中的記憶設備,用來存放程式和資料 1.1存盤器的層次結構 快取-主存層次主要解決CPU和主存速度不匹配的問題,速度接近快取 主存-輔存層次主要解決存盤系統的容量問題,容量接近與價位接近于主存 2.主存盤器 2.1概述 主存與CPU的聯 ......

    uj5u.com 2023-04-17 08:20:31 more
  • 談一談我對協同開發的一些認識

    如今各互聯網公司普通都使用敏捷開發,采用小步快跑的形式來進行專案開發。如果是小專案或者小需求,那一個開發可能就搞定了。但對于電商等復雜的系統,其功能多,結構復雜,一個人肯定是搞不定的,所以都是很多人來共同開發維護。以我曾經待過的商城團隊為例,光是后端開發就有七十多人。 為了更好地開發這類大型系統,往 ......

    uj5u.com 2023-04-17 08:18:55 more
  • 專案管理PRINCE2核心知識點整理

    PRINCE2,即 PRoject IN Controlled Environment(受控環境中的專案)是一種結構化的專案管理方法論,由英國政府內閣商務部(OGC)推出,是英國專案管理標準。
    PRINCE2 作為一種開放的方法論,是一套結構化的專案管理流程,描述了如何以一種邏輯性的、有組織的方法,... ......

    uj5u.com 2023-04-17 08:18:51 more
  • 談一談我對協同開發的一些認識

    如今各互聯網公司普通都使用敏捷開發,采用小步快跑的形式來進行專案開發。如果是小專案或者小需求,那一個開發可能就搞定了。但對于電商等復雜的系統,其功能多,結構復雜,一個人肯定是搞不定的,所以都是很多人來共同開發維護。以我曾經待過的商城團隊為例,光是后端開發就有七十多人。 為了更好地開發這類大型系統,往 ......

    uj5u.com 2023-04-17 08:18:00 more
  • 專案管理PRINCE2核心知識點整理

    PRINCE2,即 PRoject IN Controlled Environment(受控環境中的專案)是一種結構化的專案管理方法論,由英國政府內閣商務部(OGC)推出,是英國專案管理標準。
    PRINCE2 作為一種開放的方法論,是一套結構化的專案管理流程,描述了如何以一種邏輯性的、有組織的方法,... ......

    uj5u.com 2023-04-17 08:17:55 more
  • 計算機組成原理—存盤器

    計算機組成原理—硬體結構 二、存盤器 1.概述 存盤器是計算機系統中的記憶設備,用來存放程式和資料 1.1存盤器的層次結構 快取-主存層次主要解決CPU和主存速度不匹配的問題,速度接近快取 主存-輔存層次主要解決存盤系統的容量問題,容量接近與價位接近于主存 2.主存盤器 2.1概述 主存與CPU的聯 ......

    uj5u.com 2023-04-17 08:12:06 more