C語言調(diào)用攝像頭實現(xiàn)生成yuv未壓縮圖片
播發(fā)yuv格式圖片:ffplay -f rawvideo -video_size 1920X1080 -pixel_format yuyv422 my.yuv
此圖片是沒有進(jìn)行過任何壓縮處理的圖片,是攝像頭最高分辨率的圖片。
實現(xiàn)代碼
#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdlib.h> #include <unistd.h> #include <sys/ioctl.h> #include <linux/videodev2.h> //v4l2 頭文件 #include <string.h> #include <sys/mman.h> int main(void) { //1.打開設(shè)備 int fd = open("/dev/video0", O_RDWR); if(fd < 0) { perror("打開設(shè)備失敗"); return -1; } //設(shè)置采集格式 struct v4l2_format { enum v4l2_buf_type { V4L2_BUF_TYPE_VIDEO_CAPTURE = 1, V4L2_BUF_TYPE_VIDEO_OUTPUT = 2, V4L2_BUF_TYPE_VIDEO_OVERLAY = 3, }type; union { // struct v4l2_pix_format pix; /* V4L2_BUF_TYPE_VIDEO_CAPTURE */ struct v4l2_window win; /* V4L2_BUF_TYPE_VIDEO_OVERLAY */ struct v4l2_vbi_format vbi; /* V4L2_BUF_TYPE_VBI_CAPTURE */ struct v4l2_sliced_vbi_format sliced; /* V4L2_BUF_TYPE_SLICED_VBI_CAPTURE */ __u8 raw_data[200]; /* user-defined */ struct v4l2_pix_format { __u32 width; __u32 height; __u32 pixelformat; __u32 field; /* enum v4l2_field */ __u32 bytesperline; /* for padding, zero if unused */ __u32 sizeimage; __u32 colorspace; /* enum v4l2_colorspace */ __u32 priv; /* private data, depends on pixelformat */ __u32 flags; /* format flags (V4L2_PIX_FMT_FLAG_*) */ union { /* enum v4l2_ycbcr_encoding */ __u32 ycbcr_enc; /* enum v4l2_hsv_encoding */ __u32 hsv_enc; }; __u32 quantization; /* enum v4l2_quantization */ __u32 xfer_func; /* enum v4l2_xfer_func */ }pix; } fmt; }vfmt; vfmt.type=1; vfmt.fmt.pix.width=1920; //720p=1280*720 1080p=1920*1080 vfmt.fmt.pix.pixelformat=v4l2_fourcc('Y','U','Y','V'); //生成不壓縮的圖片 //播發(fā)yuv格式圖片:ffplay -f rawvideo -video_size 1920X1080 -pixel_format yuyv422 my.yuv int ret = ioctl(fd, VIDIOC_S_FMT, &vfmt); if(ret < 0) { perror("設(shè)置格式失敗"); } //4.申請內(nèi)核緩沖區(qū)個數(shù) struct v4l2_requestbuffers { __u32 count; //申請個數(shù) __u32 type; /* enum v4l2_buf_type */ __u32 memory; /* enum v4l2_memory */ __u32 capabilities; __u32 reserved[1]; }reqbuffer; reqbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; reqbuffer.count = 1; //申請4個緩沖區(qū) reqbuffer.memory=V4L2_BUF_CAP_SUPPORTS_MMAP; //映射方式 ret = ioctl(fd, VIDIOC_REQBUFS, &reqbuffer); if(ret < 0) { perror("申請隊列空間失敗"); } //設(shè)置 設(shè)備映射到內(nèi)存的選項 struct v4l2_buffer { __u32 index; __u32 type; __u32 bytesused; __u32 flags; __u32 field; struct timeval timestamp; struct v4l2_timecode timecode; __u32 sequence; /* memory location */ __u32 memory; union { __u32 offset; unsigned long userptr; struct v4l2_plane *planes; __s32 fd; } m; __u32 length; __u32 reserved2; union { __s32 request_fd; __u32 reserved; }; }mapbuffer; unsigned char *mptr; unsigned int size; mapbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; mapbuffer.index = 0; ret = ioctl(fd, VIDIOC_QUERYBUF, &mapbuffer);//查詢緩沖區(qū)狀態(tài) if(ret < 0) { perror("查詢內(nèi)核空間隊列失敗"); } int type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ret = ioctl(fd, VIDIOC_STREAMON, &type); //啟動流 if(ret < 0) { perror("開啟失敗"); } mptr= (unsigned char *)mmap(NULL, mapbuffer.length, PROT_READ|PROT_WRITE, MAP_SHARED, fd, mapbuffer.m.offset); //設(shè)備映射到緩沖區(qū)內(nèi)存 size=mapbuffer.length; ret = ioctl(fd, VIDIOC_QBUF, &mapbuffer); //把緩沖區(qū)數(shù)據(jù)放入讀隊列中 if(ret < 0) { perror("放回失敗"); } ret = ioctl(fd, VIDIOC_DQBUF, &mapbuffer); //讀當(dāng)前隊列緩沖區(qū)的數(shù)據(jù) if(ret < 0) { perror("提取數(shù)據(jù)失敗"); } FILE *file=fopen("my.yuv", "w+"); fwrite(mptr,mapbuffer.length, 1, file); fclose(file); munmap(mptr, size); close(fd); return 0; }
到此這篇關(guān)于C語言調(diào)用攝像頭實現(xiàn)生成yuv未壓縮圖片的文章就介紹到這了,更多相關(guān)C語言生成yuv圖片內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
VS2022實現(xiàn)VC++打包生成安裝文件圖文詳細(xì)歷程
本文主要介紹了VS2022實現(xiàn)VC++打包生成安裝文件圖文詳細(xì)歷程,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-02-02剖析C++編程當(dāng)中指針作為函數(shù)參數(shù)的用法
這篇文章主要介紹了剖析C++編程當(dāng)中指針作為函數(shù)參數(shù)的用法,是C++入門學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下2015-09-09C++中::SHCreateDirectoryEx函數(shù)使用方法
::SHCreateDirectoryEx用于創(chuàng)建多級目錄,類似于mkdir -p命令,本文主要介紹了C++中::SHCreateDirectoryEx函數(shù)使用方法,具有一定的參考價值,感興趣的可以了解一下2025-03-03C++實現(xiàn)LeetCode(200.島嶼的數(shù)量)
這篇文章主要介紹了C++實現(xiàn)LeetCode(200.島嶼的數(shù)量),本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07solaris操作系統(tǒng)做c應(yīng)用程序開發(fā)步驟
solaris操作系統(tǒng)做c應(yīng)用程序開發(fā)步驟,大家參考使用吧2013-12-12C++內(nèi)存四區(qū)之代碼區(qū)、全局區(qū)、棧區(qū)和堆區(qū)
C++編譯器會把代碼直接分為四個小區(qū),弄懂這四小區(qū)對我們理解內(nèi)存有所幫助,所以下面這篇文章主要給大家介紹了關(guān)于C++內(nèi)存四區(qū)之代碼區(qū)、全局區(qū)、棧區(qū)和堆區(qū)的相關(guān)資料,需要的朋友可以參考下2021-07-07