ok,經過昨天對v4l2工作流程的學習,現在已經大體了解了v4l2的工作原理,現在開始對v4l2的api的學習,目標:1、開啟攝像頭 2、儲存影象 3、關閉攝像頭,api**:linux media infrastructure userspace api — the linux kernel documentation
具體流程如下:
1、開啟裝置:
static void open_device()
dev_name = "/dev/video0";
fd = open(dev_name, o_rdwr /* required */ | o_nonblock, 0);
2、初始化裝置:
static void init_device()
3、捕獲影象:
static void start_capturing(void)
unsigned int i;
enum v4l2_buf_type type;
for (i = 0; i < n_buffers; ++i) {
struct v4l2_buffer buf;
clear(buf);
buf.type = v4l2_buf_type_video_capture;
buf.memory = v4l2_memory_mmap;
buf.index = i;
if (-1 == xioctl(fd, vidioc_qbuf, &buf))
errno_exit("vidioc_qbuf");
type = v4l2_buf_type_video_capture;
if (-1 == xioctl(fd, vidioc_streamon, &type))
errno_exit("vidioc_streamon");
4、主迴圈
static void mainloop(void)
unsigned int count;
count = frame_count;//幀數70
while (count-- > 0) {
for (;;) {/*select()機制中提供一fd_set的資料結構,實際上是一long型別的陣列,
每乙個陣列元素都能與一開啟的檔案控制代碼(不管是socket控制代碼,還是其他檔案或命名管道或裝置控制代碼)建立聯絡,
當呼叫select()時,由核心根據io狀態修改fd_set的內容,由此來通知執行了select()的程序哪一socket或檔案可讀*/
fd_set fds;
struct timeval tv;//時間值
int r;
fd_zero(&fds); /*將set清零使集合中不含任何fd*/
fd_set(fd, &fds);/*將fd加入set集合*/
/* timeout. */
tv.tv_sec = 2; //2s
tv.tv_usec = 0;//0微妙
r = select(fd + 1, &fds, null, null, &tv);//select操作,用於確定乙個或多個套介面的狀態,返回滿足條件的套介面的數目,最多隻等待兩秒,
if (-1 == r) { //所有描述符集清零
if (eintr == errno)//如果錯誤型別為4(中斷系統呼叫)
continue;
errno_exit("select");
if (0 == r) { //超時
fprintf(stderr, "select timeout\\n");
exit(exit_failure);
if (read_frame())//讀取幀
break;
/* eagain - continue select loop. */
5、在主迴圈的過程中讀取幀
static int read_frame(void)
struct v4l2_buffer buf;//v4l2中臨時緩衝器
unsigned int i;
clear(buf);
buf.type = v4l2_buf_type_video_capture;
buf.memory = v4l2_memory_mmap;
if (-1 == xioctl(fd, vidioc_dqbuf, &buf)) {
switch (errno) {
case eagain:
return 0;
case eio:
/* could ignore eio, see spec. */
/* fall through */
default:
errno_exit("vidioc_dqbuf");
assert(buf.index < n_buffers);//斷言,索引小於緩衝區個數
process_image(buffers[buf.index].start, buf.bytesused);//程序對映
if (-1 == xioctl(fd, vidioc_qbuf, &buf))
errno_exit("vidioc_qbuf");
6、讀取幀時開始儲存影象
7、停止捕獲
static void stop_capturing(void)
enum v4l2_buf_type type;
switch (io) {
case io_method_read:
/* nothing to do. */
break;
case io_method_mmap:
case io_method_userptr:
type = v4l2_buf_type_video_capture;
if (-1 == xioctl(fd, vidioc_streamoff, &type))
errno_exit("vidioc_streamoff");
break;
8、釋放記憶體
static void uninit_device(void)
unsigned int i;
switch (io) {
case io_method_read:
free(buffers[0].start);
break;
case io_method_mmap:
for (i = 0; i < n_buffers; ++i)
if (-1 == munmap(buffers[i].start, buffers[i].length))
errno_exit("munmap");
break;
case io_method_userptr:
for (i = 0; i < n_buffers; ++i)
free(buffers[i].start);
break;
free(buffers);
9、關閉裝置
static void close_device(void)
if (-1 == close(fd))
errno_exit("close");
fd = -1;
10、輸出異常
fprintf(stderr, "\\n");
使用v4l2開啟攝像頭獲取影象的流程就是這樣,下一步就是使用python呼叫這個程式,取代cv2.imwrite。
2023年12月12日總結
今天用plsql進行pde檔案匯入時,提示表空間不存在,有兩個伺服器,從a伺服器匯出的pde檔案在b伺服器匯入表,在plsql選擇工具 匯入表,在pl sql developer標籤下的在建立表前打鉤,然後匯入檔案那選擇剛才匯出生成的pde檔案,按匯入,結果出錯,日誌如下 import starte...
2023年12月2日Linux開發手記
知識準備 2.獲得裝置資訊。3.根據需要更改裝置的相關設定。4.獲得採集到的影象資料 在這裡v4l提供了兩種方式,直接通過開啟的裝置讀取資料,使用mmap記憶體對映的方式獲取資料 5.對採集到的資料進行操作 如顯示到螢幕,影象處理,儲存成檔案 知道了流程之後,我們就需要根據流程完成相應的函式。第一步...
2023年12月1日Linux開發手記
配置ubuntu攝像頭 1 設定 新增 usb控制器 相容usb3.0 2 虛擬機器 可移動裝置 web camera 連線 斷開主機 3 檢視是否配置成功,開啟終端,輸入 susb ls dev video 輸出 dev video0 配置成功 4 開啟ubuntu自帶的chesse軟體 茄子 執...