嵌入式linux相機(2)

??本人從0開始學習linux,使用的是韋東山的教程,在跟著課程學習的情況下的所遇到的問題的總結,理論雖枯燥但是是基礎。本人將前幾章的內容大致學完之后,考慮到后續驅動方面得更多的開始實操,后續的內容將以韋東山教程Linux項目的內容為主,學習其中的代碼并手敲。做到鍛煉動手能力的同時鉆研其中的理論知識點。
摘要:相機部分代碼的理解
摘要關鍵詞:相機驅動、照片亮度調節、開發板ip配置

問題匯總
1.為什么int變量給枚舉不會報錯?  int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2.void *bufs[32] 是什么?
3.為什么需要配置和檢查捕獲能力?
4.申請緩沖區是向誰申請?
5.緩沖區位于哪里?
6.明明要傳入函數指針,為什么可以傳入結構體?
7.是將數據都放到了bufs[i]里面了對吧,是這段代碼實現的數據存放嗎? 
8.嘗試了adb拉取所有圖片發現拉取不了,只能從頭開始設置IP地址。 

第一個項目相關使用的命令行,得記錄使用的數據分辨率大小

在這里插入圖片描述

arm-buildroot-linux-gnueabihf-gcc -o video_get_data video_get_data.c
adb push video_get_data root
./video_get_data /dev/video1
adb pull root/video_raw_data_0010.jpg  home

代碼程序

代碼實現輸出支持的圖像大小以及格式,并截取圖片。


#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <linux/videodev2.h>
#include <stdio.h>
#include <string.h>
#include <poll.h> 
#include <sys/mman.h>
#include <unistd.h>/* ./video_test </dev/video0>  */int main(int argc, char **argv)
{int fd;struct v4l2_fmtdesc fmtdesc;              // 參數結構體初始化int fmt_index = 0;int frame_index = 0;struct v4l2_frmsizeenum fsenum;void *bufs[32];                          int buf_cnt;int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;struct pollfd fds[1];char filename[32];int file_cnt = 0;if (argc != 2){printf("Usage: %s </dev/videoX>,print detail for video device\n",argv[0]);return -1;}/* open */fd = open(argv[1],O_RDWR);if (fd < 0){printf("can not open %s \n",argv[1]);return -1;}// 查詢能力struct v4l2_capability capability;memset(&capability, 0, sizeof(struct v4l2_capability));if (0 == ioctl(fd, VIDIOC_QUERYCAP, &capability)){if((capability.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0) {printf("Error opening device %s: video capture not supported.\n",argv[1]);return -1;}if(!(capability.capabilities & V4L2_CAP_STREAMING)) {printf("%s does not support streaming i/o\n", argv[1]);return -1;}}else {printf("can not get capability\n");return -1;}/* */while(1){/* 枚舉格式 *//* 枚舉這種格式所支持的幀大小*/fmtdesc.index = fmt_index;  // 比如從0開始fmtdesc.type  = V4L2_BUF_TYPE_VIDEO_CAPTURE;  // 指定type為"捕獲"if(ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc) != 0) break;frame_index = 0;while(1){//枚舉所支持的幀大小memset(&fsenum,0,sizeof(struct v4l2_frmsizeenum));fsenum.pixel_format = fmtdesc.pixelformat;fsenum.index = frame_index;if(ioctl(fd,VIDIOC_ENUM_FRAMESIZES,&fsenum) == 0){printf("format %s %d ,framesize %d x %d \n",fmtdesc.description,fmtdesc.pixelformat,fsenum.discrete.width,fsenum.discrete.height);}else break;frame_index++;}fmt_index++;}// 設置攝像頭分辨率struct v4l2_format fmt;memset(&fmt, 0, sizeof(struct v4l2_format));fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;fmt.fmt.pix.width = 800;fmt.fmt.pix.height = 480;fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;fmt.fmt.pix.field = V4L2_FIELD_ANY;if (0 == ioctl(fd, VIDIOC_S_FMT, &fmt)){printf("set format ok :%d x %d\n",fmt.fmt.pix.width,fmt.fmt.pix.height);}else {printf("can not set format\n");return -1;}/** 申請 buffers*/struct v4l2_requestbuffers rb;memset(&rb, 0, sizeof(struct v4l2_requestbuffers));rb.count = 32;rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;rb.memory = V4L2_MEMORY_MMAP;if ( 0 == ioctl(fd, VIDIOC_REQBUFS, &rb)){/** 申請成功后,map the buffers*/buf_cnt = rb.count;for(int i = 0; i < rb.count; i++) {struct v4l2_buffer buf;memset(&buf, 0, sizeof(struct v4l2_buffer));buf.index = i;buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;buf.memory = V4L2_MEMORY_MMAP;if(0 == ioctl(fd, VIDIOC_QUERYBUF, &buf)){// mmapbufs[i] = mmap(0 /* start anywhere */ ,buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd,buf.m.offset);if(bufs[i] == MAP_FAILED) {printf("Unable to map buffer");return -1;}}else{printf("can not query buffer");return -1 ;}}printf("map %d bufders ok \n ",buf_cnt);}else {printf("can not request buffers\n");return -1;}// 把所有buffer放入"空閑鏈表"/** Queue the buffers.*/for(int i = 0; i < buf_cnt; ++i) {struct v4l2_buffer buf;memset(&buf, 0, sizeof(struct v4l2_buffer));buf.index = i;buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;buf.memory = V4L2_MEMORY_MMAP;if ( 0 != ioctl(fd, VIDIOC_QBUF, &buf)){printf("Unable to queue buffer");return -1;}}printf("queue buffers ok \n");// ioctl VIDIOC_STREAMON:啟動攝像頭if( 0 == ioctl(fd, VIDIOC_STREAMON, &type)){printf("start capture ok");}else {printf("Unable to start capture");return -1;}//就是這段代碼的問題查原因  while(1)     {/* poll */memset(fds,0,sizeof(fds));fds[0].fd = fd;fds[0].events = POLLIN;/* 把buffer取出隊列 */if (1 == poll(fds,1,-1)){struct v4l2_buffer buf;memset(&buf, 0, sizeof(struct v4l2_buffer));buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;buf.memory = V4L2_MEMORY_MMAP;if (0 == ioctl(fd, VIDIOC_DQBUF, &buf));else{printf("Unable to dequeue buffer");return -1;}/* 把buffer的數據存儲為文件 */sprintf(filename,"video_raw_data_%04d.jpg",file_cnt++);int fd_file = open(filename,O_RDWR | O_CREAT, 0666);if (fd_file < 0){printf("can not create file: %s \n",filename);}printf("capture to %s\n",filename);write(fd_file,bufs[buf.index], buf.bytesused);close(fd_file);/* 把buffer放入隊列 */if (0 == ioctl(fd, VIDIOC_DQBUF, &buf));else{printf("Unable to dequeue buffer");return -1;}}}if (0 == ioctl(fd, VIDIOC_STREAMOFF, &type)){printf("stop capture");}else {printf("Unable to stop capture");return -1;}close(fd);return 0;}

代碼不詳細解釋,只有本人不熟的問題。

1.為什么int變量給枚舉不會報錯? int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
在C++中,枚舉類型本質上就是整數類型。每個枚舉值在編譯時會被替換為對應的整數值。因此,將枚舉值賦給int變量是完全合法的,編譯器不會報錯。

2.void bufs[32] 是什么?
這是一個包含32個void指針的數組:void
是一種通用指針類型,可以指向任何類型的數據
[32] 表示這是一個包含32個元素的數組,每個元素都是一個指針,可以存儲任何數據類型的地址這種結構在系統編程中很常見,特別是在需要管理多種類型數據或需要通用數據存儲的場景中。

3.為什么需要配置和檢查捕獲能力?
1. 設備多樣性
不是所有視頻設備都支持視頻捕獲功能。有些設備可能是:
視頻輸出設備(如HDMI輸出)
音頻設備
無線電接收設備
其他特殊用途設備

2. 功能支持差異
不同設備支持不同的I/O方法:
V4L2_CAP_STREAMING: 支持流式I/O(內存映射或用戶指針)
V4L2_CAP_READWRITE: 支持傳統的read()/write() I/O
V4L2_CAP_VIDEO_CAPTURE: 支持視頻捕獲
V4L2_CAP_VIDEO_OUTPUT: 支持視頻輸出

4.申請緩沖區是向誰申請?
不是直接向攝像頭硬件申請,而是向內核中的V4L2驅動程序申請
驅動程序負責管理視頻捕獲所需的內存區域
這些內存區域用于存儲攝像頭捕獲的幀數據

5.緩沖區位于哪里?
緩沖區位于內核空間,通過mmap系統調用映射到用戶空間,攝像頭硬件通過DMA(直接內存訪問) 直接將數據寫入這些緩沖區

void *memset(void *s, int c, size_t count)
{char *xs = s;while (count--)*xs++ = c;return s;
}   memset

6.明明要傳入函數指針,為什么可以傳入結構體? `

struct v4l2_requestbuffers rb;
memset(&rb, 0, sizeof(struct v4l2_requestbuffers));

void* 的通用性??:
void* 是“無類型指針”,可接受任何類型的數據指針(如 int*、char*、結構體指針等)。編譯器會自動將具體指針類型轉換為 void*。
??結構體的內存本質??:
結構體在內存中是連續的字節塊。memset 按字節操作內存,與數據類型無關。傳入 &rb 時,函數會從該地址開始,將 sizeof(struct v4l2_requestbuffers) 個字節全部設為 0

7.是將數據都放到了bufs[i]里面了對吧,是這段代碼實現的數據存放嗎? 是的,你的理解非常準確!這段代碼確實是實現數據存放的關鍵步驟之一。它通過 mmap 系統調用,??將驅動在內核空間申請的內存映射到你的用戶空間應用程序中??,這樣你就可以直接讀取或處理采集到的視頻幀數據了。
為了讓這個過程更清晰,我們來分解一下:
內存映射 (mmap) 的作用 直接訪問??:mmap 讓你無需在用戶態和內核態之間拷貝數據(避免了 read/write 之類的系統調用開銷),就能直接訪問驅動中申請的幀緩沖區。這對于需要高效處理大量視頻數據的應用至關重要。

8.嘗試了adb拉取所有圖片發現拉取不了,只能從頭開始設置IP地址。

在這里插入圖片描述
直接輸入ifconfig eth0 192.168.5.9設置IP地址。
在這里插入圖片描述
方案2:更改永久保存如圖所示輸入 vi/etc/network/interfaces 命令行,更改設置,設置內容如圖所示。
在這里插入圖片描述
重啟之后可以看到。
在這里插入圖片描述
電腦之間實現相互應答。

在這里插入圖片描述

在這里插入圖片描述

arm-buildroot-linux-gnueabihf-gcc -o video_brightness video_brightness.c
adb push video_brightness root
./video_brightness /dev/video1
shift+鼠標左鍵指定選擇區域
d+回車要慢一點按

實現攝像機亮度調節如圖所示。
在這里插入圖片描述
pthread_create(&thread, NULL, thread_brightness_control, (void )fd);
void 的通用性
:void* 是C語言中的通用指針類型,可以指向任何數據類型,類型轉換:C語言允許在整數類型和指針類型之間進行顯式,轉換大小兼容:在大多數系統上,指針的大小足以存儲一個int值

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/97788.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/97788.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/97788.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

云計算學習100天-第34天 -zabbix監控2

SourceURL:file:///home/student/Documents/zabbix.doczabbix服務器配置1. 拷貝zabbix軟件包到pubserver#在此之前先從真機拷貝安裝包[rootserver1 ~]# scp /linux-soft/s2/zzg/zabbix_soft/*.rpm 192.168.88.5:/root/#然后拷貝到pubserver[rootzabbixserver ~]# scp /linux-so…

貓頭虎AI分享:無需OCR,基于ColQwen2、Qwen2.5和Weaviate對PDF進行多模態RAG的解決方案

無需OCR&#xff0c;基于ColQwen2、Qwen2.5和Weaviate對PDF進行多模態RAG的解決方案 關鍵詞&#xff1a;多模態RAG、ColQwen2、Qwen2.5-VL、Weaviate 向量數據庫、PDF 檢索問答、無需 OCR、ColBERT 多向量、跨模態檢索、MaxSim 相似度、知識庫構建、AI 文檔處理、視覺語言模型、…

HTML第三課:特殊元素

HTML第三課&#xff1a;特殊元素特殊元素代碼展示特殊元素 不在行級元素和塊級元素概念里面的元素無法控制沒有寬高的元素 代碼展示 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewpo…

藍橋杯算法之基礎知識(5)

目錄 Ⅰ.in方法的使用 Ⅱ.字典的使用 Ⅲ.1MB 、KB、 B、 b(即bit)的轉換&#xff08;必學&#xff09; Ⅳ.閏年or平年 Ⅴ.count和counter方法 1. count() 方法的使用場景 2. Counter 類的介紹 3. count() 與 Counter 的區別 4. Counter 的高級應用 5.Counter的另一種使用 Ⅵ.ma…

lesson52:CSS進階指南:雪碧圖與邊框技術的創新應用

目錄 一、CSS雪碧圖&#xff1a;從性能優化到交互革命 1.1 技術原理與現代價值 1.2 2025年實現工具與自動化流程 1.2.1 構建工具集成方案 1.2.2 在線生成工具推薦 1.3 高級應用案例與代碼實現 1.3.1 多狀態按鈕系統 1.3.2 響應式雪碧圖實現 1.4 最佳實踐與性能優化 二…

案例——從零開始搭建 ASP.NET Core 健康檢查實例

1. 項目創建與基礎設置 創建新項目 首先&#xff0c;創建一個新的 ASP.NET Core Web API 項目&#xff1a; dotnet new webapi -n HealthCheckDemo cd HealthCheckDemo添加必要的 NuGet 包 添加健康檢查相關的 NuGet 包&#xff1a; dotnet add package Microsoft.AspNetCore.D…

【Java生產級避坑指南】8. Tomcat線程池下的內存地雷:ThreadLocal泄漏檢測與實戰解決

摘要:某金融交易系統(Spring Boot 2.7 + Tomcat 9)在線上運行時出現嚴重內存泄漏:堆內存(4GB)72小時內耗盡并觸發OOM,日均200萬請求場景下,Full GC頻率從正常1次/天飆升至6次/小時。排查發現,根源是ThreadLocal未清理——Tomcat線程池復用線程時,UserInfo等大對象被T…

云端職達:你的AI求職專屬獵頭,顛覆傳統招聘模式

在求職的“金三銀四”或“金九銀十”&#xff0c;每一分每一秒都彌足珍貴。面對浩如煙海的招聘信息&#xff0c;你是否還在花費大量時間一條條篩選、重復投遞簡歷&#xff0c;最終卻常常石沉大海&#xff1f;傳統求職方式的低效和“已讀不回”的窘境&#xff0c;讓許多求職者感…

Parasoft C/C++test如何實現開發環境內嵌的安全檢測

Parasoft 作為嵌入式質量與安全領域的全球領先供應商&#xff0c;其 C/Ctest 平臺依托 IDE 級原生集成、實時合規檢測引擎與缺陷閉環治理框架&#xff0c;將傳統靜態應用安全測試由項目末期集中執行前移至編碼階段&#xff0c;顯著降低缺陷修復成本并縮短認證周期&#xff0c;為…

leetcode-每日一題-人員站位的方案數-C語言

3025. 人員站位的方案數 I 輸入&#xff1a; 2 < n < 50 points[i].length 2 0 < points[i][0], points[i][1] < 50 points[i] 點對兩兩不同。 // 按x降序&#xff0c;按y升序 int cmp(const void *a, const void *b) {int *p *(int **)a;int *q *(int **)b;if(…

ClickHouse中的ON CLUSTER關鍵字

目錄 ClickHouse中的ON CLUSTER關鍵字 前置基礎 ClickHouse 中的 MergeTree 與 ReplicatedMergeTree ON CLUSTER 查詢在集群上的正確用法(為什么 查詢/寫入數據 不用 ON CLUSTER) 與不使用 ON CLUSTER 的區別 注意事項與坑 常用配套命令 ClickHouse中的ON CLUSTER關鍵字 前置…

Python繪圖動態可視化:實時音頻流

在數據可視化中&#xff0c;動畫是一種非常有效的方式&#xff0c;可以幫助我們更好地理解數據的變化和動態過程。Python 的 matplotlib.animation 模塊提供了強大的功能來創建動畫。本文將介紹如何使用 matplotlib.animation 創建簡單的動畫&#xff0c;并展示一個更復雜的實時…

【Vue2 ?】Vue2 入門之旅(七):事件處理

在前幾篇文章中&#xff0c;我們學習了指令與過濾器。本篇將介紹 事件處理&#xff0c;重點包括 v-on、事件修飾符以及鍵盤事件。 目錄 事件綁定 v-on事件修飾符鍵盤事件小結 事件綁定 v-on Vue 使用 v-on&#xff08;縮寫 &#xff09;來監聽事件。 <div id"app&qu…

高效數據傳輸的秘密武器:Protobuf

當涉及到網絡通信和數據存儲時&#xff0c;數據序列化一直都是一個重要的話題&#xff1b;特別是現在很多公司都在推行微服務&#xff0c;數據序列化更是重中之重&#xff0c;通常會選擇使用 JSON 作為數據交換格式&#xff0c;且 JSON 已經成為業界的主流。但是 Google 這么大…

騰訊混元翻譯大模型Hunyuan-MT-7B:重塑跨語言溝通的技術革命

騰訊混元翻譯大模型Hunyuan-MT-7B&#xff1a;重塑跨語言溝通的技術革命 騰訊混元Hunyuan-MT-7B大模型的發布標志著機器翻譯領域進入全新時代&#xff0c;本文將深入解析這一突破性技術如何實現30種語言翻譯冠軍的卓越表現 一、Hunyuan-MT-7B核心架構解析 1.1 基于Transformer的…

End-To-End 之于推薦-kuaishou OneRec2 筆記

End_To_End 之于推薦onerec里&#xff0c;快手利用大模型做了推薦架構的革命&#xff0c;幾個月后&#xff0c;v2之于v1是一些技術細節進行了進一步迭代&#xff0c;主要是以下兩個方面&#xff1a; 1. 架構層面的突破&#xff1a;Lazy Decoder-Only 背景問題&#xff1a;V1 的…

【LeetCode】3670. 沒有公共位的整數最大乘積 (SOSDP)

3670. 沒有公共位的整數最大乘積 - 力扣&#xff08;LeetCode&#xff09; 題目&#xff1a; 思路&#xff1a; SOSDP 本題我們顯然不能枚舉每一個數對&#xff0c;n 的復雜度顯然超時&#xff0c;所以考慮優化 我們考慮一個二進制數 mask&#xff0c;因為我們必須要選沒有任…

Sping Web MVC入門

1.什么是Sping Web MVC1.1MVC定義2.什么是Spring MVC

LLM面試50問:NLP/RAG/部署/對齊/安全/多模態全覆蓋

太好了!下面按你點名的 6 大主題(NLP、檢索/RAG、部署、對齊、 安全、多模態)給出深度版答案 + 關鍵公式/推導 + 最小可跑示例代碼 + 常見坑。都盡量精煉到“拿來即用/面試可白板推導”的粒度。 NLP(架構、位置編碼、指令跟隨) 1) RoPE 長上下文與縮放 要點:RoPE 將位置…

計算機網絡技術(四)完結

七&#xff0c;虛擬局域網VLAN1&#xff0c;VLAN概述通過設置虛擬局域網來實現&#xff0c;pc之間實現快速安全通信。對比說明&#xff1a;之前交換機的廣播來實現通信&#xff0c;但同意也帶來了幾個問題&#xff0c;過大的廣播域&#xff0c;造成了帶寬的浪費&#xff0c;過大…