本文來源電子發(fā)燒友社區(qū),作者:ALSET, 帖子地址:https://bbs.elecfans.com/jishu_2303429_1_1.html
測試攝像頭采集視頻數(shù)據(jù)
飛凌RZ/G2L的開發(fā)板試用測評報告二 — 視頻采集開發(fā)
大信(QQ:8125036)
一、硬件音視頻能力了解
OK-G2LD-C開發(fā)板擁有豐富的多媒體資源,支持多種顯示、攝像頭、音頻接口,滿足多場景下的人機(jī)交互和圖像采集需求;核心板同時配備500MHz 3D GPU Mali-G31,支持Vulkan、OpenGL、OpenCL,同時VPU支持1080P高清顯示,可進(jìn)行H.264 1080P分辨率的硬件編解碼。
同時板子帶有2個有線網(wǎng)口和wifi無線網(wǎng)絡(luò),這也給音視頻實(shí)時傳輸提供了硬件基礎(chǔ)。
因此基于RZG2l應(yīng)該能夠開發(fā)出多種音視頻應(yīng)用,比如視頻的采集編碼,視頻直播,電視電話會議,視頻實(shí)時處理等。
圖1
二、配置開發(fā)網(wǎng)絡(luò)環(huán)境在前面的測試中已經(jīng)建立基本的串口調(diào)試環(huán)境。為了后面更方便的在主機(jī)與開發(fā)板間傳送文件,還需要建立開發(fā)板和主機(jī)的網(wǎng)絡(luò)通訊,以便通過主機(jī)對開發(fā)板下載和上傳文件。這里主機(jī)的開發(fā)環(huán)境是基于Windows 10操作系統(tǒng)的Ubuntu虛機(jī)系統(tǒng),在Win10上安裝vmware 虛機(jī)和串口超級終端,vmware里安裝了 uBuntu18.4版本的linux環(huán)境。
在啟動開發(fā)板之后,使用ifconfig 命令查看網(wǎng)絡(luò)配置,可見網(wǎng)卡都不通,因此需要進(jìn)行網(wǎng)絡(luò)配置。
首先把一條有線網(wǎng)絡(luò)插入到開發(fā)板的網(wǎng)口中,其中下圖左邊的網(wǎng)口對應(yīng)的是系統(tǒng)里的eth0, 右側(cè)的網(wǎng)口對應(yīng)的是 eth1
圖2
插好網(wǎng)線后,進(jìn)入系統(tǒng)網(wǎng)口配置文件所在目錄:cd /etc/systemd/network
打開10-eth.network 文件
vim 10-eth.network
根據(jù)自己網(wǎng)絡(luò)段,配置好開發(fā)板的地址,這里使用的靜態(tài)地址,在與主機(jī)相同網(wǎng)段內(nèi)找一個空閑的IP地址,配置上即可,這樣避免動態(tài)地址分配,導(dǎo)致每次重啟可能會造成地址改變,帶來不必要的麻煩。
[Match]
Name=eth0
KernelCommandLine=!root=/dev/nfs
[Network]
Address=192.168.3.232
Gateway=192.168.3.1
DNS=192.168.3.1
ConfigureWithoutCarrier=true
IgnoreCarrierLoss=true
圖3
配置完后,重啟開發(fā)板,再使用ifconfig查看網(wǎng)絡(luò)設(shè)備,eth0設(shè)備已經(jīng)有IP地址,并且檢查ping是否能連通通外部主機(jī)。同時通過SecureCRT建立SSH登錄,也能夠順利登錄開發(fā)板了。
圖4
三、連接檢查網(wǎng)絡(luò)攝像頭 因?yàn)槭诌厱簳r沒有MIPI CSI的攝像頭器件。因此查看開發(fā)板文檔,開發(fā)板系統(tǒng)是一個標(biāo)準(zhǔn)的ARMLinux 4.19系統(tǒng),那么它就可以支持uvcamera, 因此找了一款通用型的網(wǎng)絡(luò)攝像頭Logitech Webcam C270 USB網(wǎng)絡(luò)攝像頭作為視頻采集的設(shè)備,把攝像頭插入開發(fā)板的USB口,檢測開發(fā)板是否能夠支持該攝像頭,。連接好攝像頭后,進(jìn)入系統(tǒng)查看驅(qū)動加載信息。
圖5查看系統(tǒng)的版本
圖6 連接USB攝像頭
SecureCRT工具里進(jìn)入開發(fā)板環(huán)境里,查看USB總線信息以及開發(fā)板USB設(shè)備信息如下圖:
圖7
圖8
從系統(tǒng)設(shè)備驅(qū)動加載信息上看,開發(fā)板已經(jīng)為這個攝像頭識別出 audio 和 uvcvideo 設(shè)備,并成功加載驅(qū)動。使用查看USB設(shè)備詳細(xì)驅(qū)動參數(shù)命令,可查看到連入開發(fā)板的所有USB設(shè)備,以及連接位置,USB總線結(jié)構(gòu)等信息。進(jìn)一步查看攝像頭所對應(yīng)的USB設(shè)備號和相關(guān)參數(shù),如下圖紅色圈設(shè)備即為該攝像頭設(shè)備,記下這些參數(shù),后面軟件開發(fā)時需要,否則程序?qū)⒉荒苷_的采集到視頻畫面。
usb-devices
圖9
四、檢測攝像頭支持的采集視頻規(guī)格 連接好開發(fā)板和USB攝像頭后,還需要獲得開發(fā)板支持這款攝像頭對視頻采集的規(guī)格,不同攝像頭采集的規(guī)則并不相同,不同開發(fā)板支持采集的規(guī)格也不同,因此需要對當(dāng)前的硬件連接做一下攝像頭視頻支持規(guī)則檢測。
可采集視頻規(guī)格檢測代碼在網(wǎng)上就有,在github上搜索Vv4l2_apture c++ 開源工程,即可以到該原始工程,git下載到主機(jī)環(huán)境中,然后根據(jù)板子的SDK,開始修改…(此處省去代碼修改的一萬字),主要是修改相關(guān)參數(shù)和函數(shù)。
https://github.com/soramimi/v4l2capture
圖10
圖11
經(jīng)過修改調(diào)試代碼后,最后在板上成功的運(yùn)行,并輸出開發(fā)板對攝像頭支持的格式列表,如下:Supported Formats:
V4L2_CAP_VIDEO_CAPTURE: pixelformat = YUYV, description = 'YUYV 4:2:2'
resolution:640x480 fps: 30, 25, 20, 15, 10, 5
resolution:160x120 fps: 30, 25, 20, 15, 10, 5
resolution:176x144 fps: 30, 25, 20, 15, 10, 5
resolution:320x176 fps: 30, 25, 20, 15, 10, 5
resolution:320x240 fps: 30, 25, 20, 15, 10, 5
resolution:352x288 fps: 30, 25, 20, 15, 10, 5
resolution:432x240 fps: 30, 25, 20, 15, 10, 5
resolution:544x288 fps: 30, 25, 20, 15, 10, 5
resolution:640x360 fps: 30, 25, 20, 15, 10, 5
resolution:752x416 fps: 25, 20, 15, 10, 5
resolution:800x448 fps: 25, 20, 15, 10, 5
resolution:800x600 fps: 20, 15, 10, 5
resolution:864x480 fps: 20, 15, 10, 5
resolution:960x544 fps: 15, 10, 5
resolution:960x720 fps: 10, 5
resolution:1024x576 fps: 10, 5
resolution:1184x656 fps: 10, 5
resolution:1280x720 fps: 10, 5
resolution:1280x960 fps: 7, 5
V4L2_CAP_VIDEO_CAPTURE: pixelformat = MJPG, description = 'Motion-JPEG'
resolution:640x480 fps: 30, 25, 20, 15, 10, 5
resolution:160x120 fps: 30, 25, 20, 15, 10, 5
resolution:176x144 fps: 30, 25, 20, 15, 10, 5
resolution:320x176 fps: 30, 25, 20, 15, 10, 5
resolution:320x240 fps: 30, 25, 20, 15, 10, 5
resolution:352x288 fps: 30, 25, 20, 15, 10, 5
resolution:432x240 fps: 30, 25, 20, 15, 10, 5
resolution:544x288 fps: 30, 25, 20, 15, 10, 5
resolution:640x360 fps: 30, 25, 20, 15, 10, 5
resolution:752x416 fps: 30, 25, 20, 15, 10, 5
resolution:800x448 fps: 30, 25, 20, 15, 10, 5
resolution:800x600 fps: 30, 25, 20, 15, 10, 5
resolution:864x480 fps: 30, 25, 20, 15, 10, 5
resolution:960x544 fps: 30, 25, 20, 15, 10, 5
resolution:960x720 fps: 30, 25, 20, 15, 10, 5
resolution:1024x576 fps: 30, 25, 20, 15, 10, 5
resolution:1184x656 fps: 30, 25, 20, 15, 10, 5
resolution:1280x720 fps: 30, 25, 20, 15, 10, 5
resolution:1280x960 fps: 30, 25, 20, 15, 10, 5
五、采集程序開發(fā)測試 獲得攝像頭的設(shè)備參數(shù)以及能夠采集的視頻規(guī)格參數(shù)以后,就可以開發(fā)視頻采集程序,在開發(fā)采集程序前,還需要查看一下攝像頭的用戶層抽象操作設(shè)備,一般在/dev/下,使用以下命令查看抽象出的設(shè)備文件:
ls –ls /dev/video*
可以看到抽象的視頻采集設(shè)備,后面將試用設(shè)備控制代碼來打開操作它。
另外在看一下采集設(shè)備對 v4l2 系統(tǒng)的驅(qū)動,命令如下:
ls -l/sys/class/video4linux/video*
這兩個命令是在攝像頭底層驅(qū)動加載工作正常后才會出現(xiàn),如果底層驅(qū)動有任何問題,這兩個命令將不會有相應(yīng)信息顯示。
采集視頻采用的是V4L2視頻框架。V4L2是Video for linux2的簡稱,為linux中關(guān)于視頻設(shè)備的內(nèi)核驅(qū)動。在Linux中視頻設(shè)備是設(shè)備文件,可以像訪問普通文件一樣對其進(jìn)行讀寫,攝像頭在/dev/video*下,如果只有一個視頻設(shè)備,通常為/dev/video0。V4L2在設(shè)計時,是能支持很多廣泛的設(shè)備,但它們之中只有一部分是真正的視頻設(shè)備:
可以支持多種設(shè)備,它可以有以下幾種接口:
1. 視頻采集接口(video capture interface):這種應(yīng)用的設(shè)備可以是高頻頭或者攝像頭.V4L2的最初設(shè)計就是應(yīng)用于這種功能的.
2. 視頻輸出接口(video output interface):可以驅(qū)動計算機(jī)的外圍視頻圖像設(shè)備--像可以輸出電視信號格式的設(shè)備.
3. 直接傳輸視頻接口(video overlay interface):它的主要工作是把從視頻采集設(shè)備采集過來的信號直接輸出到輸出設(shè)備之上,而不用經(jīng)過系統(tǒng)的CPU.
4. 視頻間隔消隱信號接口(VBI interface):它可以使應(yīng)用可以訪問傳輸消隱期的視頻信號.
5. 收音機(jī)接口(radio interface):可用來處理從AM或FM高頻頭設(shè)備接收來的音頻流.
圖12
圖13
代碼比較長,這里放出修改的部分關(guān)鍵代碼如下:- #include
- #include
- #include
- #include
- #include /* getopt_long() */
- #include /* low-level i/o */
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #define CLEAR(x) memset(&(x), 0, sizeof(x))
- #ifndef V4L2_PIX_FMT_H264
- #define V4L2_PIX_FMT_H264 v4l2_fourcc('H', '2', '6', '4') /* H264 with start codes */
- #endif
- enum io_method {
- IO_METHOD_READ,
- IO_METHOD_MMAP,
- IO_METHOD_USERPTR,
- };
- struct buffer {
- void *start;
- size_t length;
- };
- static char *dev_name;
- static enum io_method io = IO_METHOD_MMAP;
- static int fd = -1;
- struct buffer *buffers;
- static unsigned int n_buffers;
- static int out_buf;
- static int force_format = 0;
- static int frame_count = 200;
- static int frame_number = 0;
- static void errno_exit(const char *s)
- {
- fprintf(stderr, "%s error %d, %sn", s, errno, strerror(errno));
- exit(EXIT_FAILURE);
- }
- static int xioctl(int fh, int request, void *arg)
- {
- int r;
- do {
- r = ioctl(fh, request, arg);
- } while (-1 == r && EINTR == errno);
- return r;
- }
- static void process_image(const void *p, int size)
- {
- int status;
- frame_number++;
- if (out_buf==0)
- {
- /* write to file */
- FILE *fp=fopen("video.raw","ab");
- fwrite(p, size, 1, fp);
- fflush(fp);
- fclose(fp);
- }
- else
- {
- /* write to stdout */
- status = write(1, p, size);
- if(status == -1)
- perror("write");
- }
- }
- static int read_frame(void)
- {
- struct v4l2_buffer buf;
- unsigned int i;
- switch (io) {
- case IO_METHOD_READ:
- if (-1 == read(fd, buffers[0].start, buffers[0].length)) {
- switch (errno) {
- case EAGAIN:
- return 0;
- case EIO:
- /* Could ignore EIO, see spec. */
- /* fall through */
- default:
- errno_exit("read");
- }
- }
- process_image(buffers[0].start, buffers[0].length);
- break;
- case IO_METHOD_MMAP:
- 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");
- break;
- case IO_METHOD_USERPTR:
- CLEAR(buf);
- buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- buf.memory = V4L2_MEMORY_USERPTR;
- 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");
- }
- }
- for (i = 0; i < n_buffers; ++i)
- if (buf.m.userptr == (unsigned long)buffers[i].start
- && buf.length == buffers[i].length)
- break;
- assert(i < n_buffers);
- process_image((void *)buf.m.userptr, buf.bytesused);
- if (-1 == xioctl(fd, VIDIOC_QBUF, &buf))
- errno_exit("VIDIOC_QBUF");
- break;
- }
- return 1;
- }
- static void mainloop(void)
- {
- unsigned int count;
- unsigned int loopIsInfinite = 0;
- if (frame_count == 0) loopIsInfinite = 1; //infinite loop
- count = frame_count;
- while ((count-- > 0) || loopIsInfinite) {
- for (;; ) {
- fd_set fds;
- struct timeval tv;
- int r;
- FD_ZERO(&fds);
- FD_SET(fd, &fds);
- /* Timeout. */
- tv.tv_sec = 2;
- tv.tv_usec = 0;
- r = select(fd + 1, &fds, NULL, NULL, &tv);
- if (-1 == r) {
- if (EINTR == errno)
- continue;
- errno_exit("select");
- }
- if (0 == r) {
- fprintf(stderr, "select timeoutn");
- exit(EXIT_FAILURE);
- }
- if (read_frame())
- break;
- /* EAGAIN - continue select loop. */
- }
- }
- }
- 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;
- }
- }
- static void start_capturing(void)
- {
- unsigned int i;
- enum v4l2_buf_type type;
- switch (io) {
- case IO_METHOD_READ:
- /* Nothing to do. */
- break;
- case IO_METHOD_MMAP:
- 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");
- break;
- case IO_METHOD_USERPTR:
- for (i = 0; i < n_buffers; ++i) {
- struct v4l2_buffer buf;
- CLEAR(buf);
- buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- buf.memory = V4L2_MEMORY_USERPTR;
- buf.index = i;
- buf.m.userptr = (unsigned long)buffers[i].start;
- buf.length = buffers[i].length;
- 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");
- break;
- }
- }
- 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);
- }
- static void init_read(unsigned int buffer_size)
- {
- buffers = calloc(1, sizeof(*buffers));
- if (!buffers) {
- fprintf(stderr, "Out of memoryn");
- exit(EXIT_FAILURE);
- }
- buffers[0].length = buffer_size;
- buffers[0].start = malloc(buffer_size);
- if (!buffers[0].start) {
- fprintf(stderr, "Out of memoryn");
- exit(EXIT_FAILURE);
- }
- }
- static void init_mmap(void)
- {
- struct v4l2_requestbuffers req;
- CLEAR(req);
- req.count = 4;
- req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- req.memory = V4L2_MEMORY_MMAP;
- if (-1 == xioctl(fd, VIDIOC_REQBUFS, &req)) {
- if (EINVAL == errno) {
- fprintf(stderr, "%s does not support "
- "memory mappingn", dev_name);
- exit(EXIT_FAILURE);
- } else {
- errno_exit("VIDIOC_REQBUFS");
- }
- }
- if (req.count < 2) {
- fprintf(stderr, "Insufficient buffer memory on %sn",
- dev_name);
- exit(EXIT_FAILURE);
- }
- buffers = calloc(req.count, sizeof(*buffers));
- if (!buffers) {
- fprintf(stderr, "Out of memoryn");
- exit(EXIT_FAILURE);
- }
- for (n_buffers = 0; n_buffers < req.count; ++n_buffers) {
- struct v4l2_buffer buf;
- CLEAR(buf);
- buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- buf.memory = V4L2_MEMORY_MMAP;
- buf.index = n_buffers;
- if (-1 == xioctl(fd, VIDIOC_QUERYBUF, &buf))
- errno_exit("VIDIOC_QUERYBUF");
- buffers[n_buffers].length = buf.length;
- buffers[n_buffers].start =
- mmap(NULL /* start anywhere */,
- buf.length,
- PROT_READ | PROT_WRITE /* required */,
- MAP_SHARED /* recommended */,
- fd, buf.m.offset);
- if (MAP_FAILED == buffers[n_buffers].start)
- errno_exit("mmap");
- }
- }
- static void init_userp(unsigned int buffer_size)
- {
- struct v4l2_requestbuffers req;
- CLEAR(req);
- req.count= 4;
- req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- req.memory = V4L2_MEMORY_USERPTR;
- if (-1 == xioctl(fd, VIDIOC_REQBUFS, &req)) {
- if (EINVAL == errno) {
- fprintf(stderr, "%s does not support "
- "user pointer i/on", dev_name);
- exit(EXIT_FAILURE);
- } else {
- errno_exit("VIDIOC_REQBUFS");
- }
- }
- buffers = calloc(4, sizeof(*buffers));
- if (!buffers) {
- fprintf(stderr, "Out of memoryn");
- exit(EXIT_FAILURE);
- }
- for (n_buffers = 0; n_buffers < 4; ++n_buffers) {
- buffers[n_buffers].length = buffer_size;
- buffers[n_buffers].start = malloc(buffer_size);
- if (!buffers[n_buffers].start) {
- fprintf(stderr, "Out of memoryn");
- exit(EXIT_FAILURE);
- }
- }
- }
- static void init_device(void)
- {
- struct v4l2_capability cap;
- struct v4l2_cropcap cropcap;
- struct v4l2_crop crop;
- struct v4l2_format fmt;
- unsigned int min;
- if (-1 == xioctl(fd, VIDIOC_QUERYCAP, &cap)) {
- if (EINVAL == errno) {
- fprintf(stderr, "%s is no V4L2 devicen",
- dev_name);
- exit(EXIT_FAILURE);
- } else {
- errno_exit("VIDIOC_QUERYCAP");
- }
- }
- if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
- fprintf(stderr, "%s is no video capture devicen",
- dev_name);
- exit(EXIT_FAILURE);
- }
- switch (io) {
- case IO_METHOD_READ:
- if (!(cap.capabilities & V4L2_CAP_READWRITE)) {
- fprintf(stderr, "%s does not support read i/on",
- dev_name);
- exit(EXIT_FAILURE);
- }
- break;
- case IO_METHOD_MMAP:
- case IO_METHOD_USERPTR:
- if (!(cap.capabilities & V4L2_CAP_STREAMING)) {
- fprintf(stderr, "%s does not support streaming i/on",
- dev_name);
- exit(EXIT_FAILURE);
- }
- break;
- }
- /* Select video input, video standard and tune here. */
- CLEAR(cropcap);
- cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- if (0 == xioctl(fd, VIDIOC_CROPCAP, &cropcap)) {
- crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- crop.c = cropcap.defrect; /* reset to default */
- if (-1 == xioctl(fd, VIDIOC_S_CROP, &crop)) {
- switch (errno) {
- case EINVAL:
- /* Cropping not supported. */
- break;
- default:
- /* Errors ignored. */
- break;
- }
- }
- } else {
- /* Errors ignored. */
- }
- CLEAR(fmt);
- fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- fprintf(stderr, "Force Format %dn", force_format);
- if (force_format) {
- if (force_format==2){
- fmt.fmt.pix.width = 1920;
- fmt.fmt.pix.height = 1080;
- fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_H264;
- fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
- }
- else if(force_format==1){
- fmt.fmt.pix.width = 640;
- fmt.fmt.pix.height = 480;
- fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
- fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
- }
- if (-1 == xioctl(fd, VIDIOC_S_FMT, &fmt))
- errno_exit("VIDIOC_S_FMT");
- /* Note VIDIOC_S_FMT may change width and height. */
- } else {
- /* Preserve original settings as set by v4l2-ctl for example */
- if (-1 == xioctl(fd, VIDIOC_G_FMT, &fmt))
- errno_exit("VIDIOC_G_FMT");
- }
- /* Buggy driver paranoia. */
- min = fmt.fmt.pix.width * 2;
- if (fmt.fmt.pix.bytesperline < min)
- fmt.fmt.pix.bytesperline = min;
- min = fmt.fmt.pix.bytesperline * fmt.fmt.pix.height;
- if (fmt.fmt.pix.sizeimage < min)
- fmt.fmt.pix.sizeimage = min;
- switch (io) {
- case IO_METHOD_READ:
- init_read(fmt.fmt.pix.sizeimage);
- break;
- case IO_METHOD_MMAP:
- init_mmap();
- break;
- case IO_METHOD_USERPTR:
- init_userp(fmt.fmt.pix.sizeimage);
- break;
- }
- }
- static void close_device(void)
- {
- if (-1 == close(fd))
- errno_exit("close");
- fd = -1;
- }
- static void open_device(void)
- {
- struct stat st;
- if (-1 == stat(dev_name, &st)) {
- fprintf(stderr, "Cannot identify '%s': %d, %sn",
- dev_name, errno, strerror(errno));
- exit(EXIT_FAILURE);
- }
- if (!S_ISCHR(st.st_mode)) {
- fprintf(stderr, "%s is no devicen", dev_name);
- exit(EXIT_FAILURE);
- }
- fd = open(dev_name, O_RDWR /* required */ | O_NONBLOCK, 0);
- if (-1 == fd) {
- fprintf(stderr, "Cannot open '%s': %d, %sn",
- dev_name, errno, strerror(errno));
- exit(EXIT_FAILURE);
- }
- }
編寫好的代碼,可以參照例程工程里的Makefile文件,編寫編譯腳本,進(jìn)入GL2編譯環(huán)境下,進(jìn)行編譯調(diào)試(省去調(diào)試修改代碼xxx字)最后把編譯好的程序上傳到開發(fā)板上,啟動運(yùn)行如下;
v4l2capture-m save -d /dev/video0 -t usb -F YUYV -w 640 -h 480 -f 15 -o/home/root/test.yuv -n 300
參數(shù)含義如下:
-d 選擇采集設(shè)備
-t usb采集
-F 采集視頻色彩數(shù)據(jù)組織格式,YUYV對應(yīng)的ffmpeg里就是 YUV422格式
-w 采集視頻畫面長度,這個寬度必須是采集設(shè)備支持的規(guī)格表里的參數(shù)
-h 采集視頻畫面高度,同上需要滿足視頻規(guī)格標(biāo)準(zhǔn)
-f 采集幀率,必須是視頻采集支持的規(guī)格
-o 輸出文件
-n 采集幀數(shù)
圖14
采集完成后,將yuv數(shù)據(jù)上傳到windows下,使用GL2工具包下的tools目錄下的YUV Player.exe,播放,因?yàn)閥uv文件不記錄視頻的長寬,以及格式信息,所以需要在yuv播放器中需要配置正確的尺寸,和視頻格式信息,才能正確的播出。
圖15
文末放了兩段視頻,一段是是手機(jī)拍攝,拍攝啟動采集程序和移動攝像頭的過程。另外一段視頻為采集到的yuv數(shù)據(jù)上傳到Ubuntu主機(jī)后,經(jīng)過轉(zhuǎn)換和編碼生成mp4,可以看攝像頭到實(shí)際采集到的畫面效果。六、視頻采集開發(fā)測評總結(jié) 通過對Logitech C270 攝像頭的視頻采集開發(fā)測試來看,RZGL2開發(fā)板支持視頻采集功能很完善,支持V4L2,F(xiàn)FMPEG這樣常用的音視頻處理框架,使得很多音視頻應(yīng)用移植起來成為可能,也比較簡單。
從采集到的視頻看,采集速率較高,支持視頻的規(guī)格也很廣。這為后面開發(fā)提供很好的基礎(chǔ),在后面較長時間(>60分鐘)的視頻采集測試中,采集程序和系統(tǒng)運(yùn)行非常穩(wěn)定,沒有出現(xiàn)異常中斷等現(xiàn)象,并且在持續(xù)視頻采集中,觸摸CPU感覺升溫不明顯,這也可以看該處理優(yōu)良的功耗表現(xiàn)。
攝像頭采集到的視頻回放,開發(fā)板體驗(yàn)視頻詳見作者原帖子
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。
舉報投訴
-
飛凌
+關(guān)注
關(guān)注
0文章
132瀏覽量
16073 -
開發(fā)板試用
+關(guān)注
關(guān)注
3文章
300瀏覽量
2024
發(fā)布評論請先 登錄
相關(guān)推薦
RZ/G2L Demo調(diào)試經(jīng)驗(yàn)流程分享(1)
r01us0553ej0107-rz-g(Release Note).pdf,r01us0556ej0102-rz-g(Board_StartUp_Guide_smarcEVK).pdf,對SMARC EVK of RZ/
RZ/G2L微處理器DDR ECC功能和機(jī)制概要
RZ/G2L微處理器配備Cortex?-A55 (1.2 GHz) CPU、16位DDR3L/DDR4接口、帶Arm Mali-G31的3D圖形加速引擎以及
【米爾-瑞薩RZ/G2UL開發(fā)板】1.開箱
【米爾-瑞薩RZ/G2UL開發(fā)板】1.開箱
開箱視頻
開箱也許會遲到,但是絕對不會缺席。今天開箱的是米爾-瑞薩 RZ/
發(fā)表于 02-04 23:38
RZ/G2L、RZ/G2LC和RZ/G2UL的SMARC EVK啟動指南Rev.1.01
電子發(fā)燒友網(wǎng)站提供《RZ/G2L、RZ/G2LC和RZ/G2UL的SMARC EVK啟動指南Re
發(fā)表于 02-02 09:45
?1次下載
米爾RZ/G2L開發(fā)板瑞米派雙核A55Remi Pi學(xué)習(xí)板兼容樹莓派擴(kuò)展模塊
RemiPi瑞薩第一款MPU生態(tài)板卡兼容樹莓派擴(kuò)展模塊瑞薩RZ/G2L工業(yè)級處理器,便于企業(yè)客戶產(chǎn)品開發(fā);RemiPi兼容樹莓派所有配件,方便產(chǎn)品原型搭建和創(chuàng)新應(yīng)用;更多的工業(yè)接口,兼顧開發(fā)
發(fā)表于 01-29 17:05
?4次下載
【米爾-瑞薩RZ/G2UL開發(fā)板】開發(fā)板開箱與接口介紹
開發(fā)板簡介 MYC-YG2UL核心板及開發(fā)板基于RZ/G2UL處理器,通用64位工業(yè)MPU
發(fā)表于 01-14 13:25
RZ/G2L RZ/G2LC RZ/G2UL用靈活的軟件包設(shè)置GPIO
電子發(fā)燒友網(wǎng)站提供《RZ/G2L RZ/G2LC RZ/G2UL用靈活的軟件包設(shè)置GPIO.pd
發(fā)表于 01-14 10:53
?0次下載
RZ/G2L RZ/G2LC RZ/G2UL RZ/G3S靈活軟件包應(yīng)用說明
電子發(fā)燒友網(wǎng)站提供《RZ/G2L RZ/G2LC RZ/G2UL
發(fā)表于 01-14 10:46
?1次下載
【飛凌OK113i-S開發(fā)板試用】開機(jī)測評--硬件篇
【飛凌OK113i-S開發(fā)板試用】開機(jī)測評--硬件篇
一,開箱見圖 包裝精致
注意:上面紅黃的先是本人接上的
配了電源線和一根usb線一根天
發(fā)表于 12-24 20:51
評論