本文來源電子發燒友社區,作者:ALSET, 帖子地址:https://bbs.elecfans.com/jishu_2303429_1_1.html
測試攝像頭采集視頻數據
飛凌RZ/G2L的開發板試用測評報告二 — 視頻采集開發
大信(QQ:8125036)
一、硬件音視頻能力了解
OK-G2LD-C開發板擁有豐富的多媒體資源,支持多種顯示、攝像頭、音頻接口,滿足多場景下的人機交互和圖像采集需求;核心板同時配備500MHz 3D GPU Mali-G31,支持Vulkan、OpenGL、OpenCL,同時VPU支持1080P高清顯示,可進行H.264 1080P分辨率的硬件編解碼。
同時板子帶有2個有線網口和wifi無線網絡,這也給音視頻實時傳輸提供了硬件基礎。
因此基于RZG2l應該能夠開發出多種音視頻應用,比如視頻的采集編碼,視頻直播,電視電話會議,視頻實時處理等。
圖1
二、配置開發網絡環境在前面的測試中已經建立基本的串口調試環境。為了后面更方便的在主機與開發板間傳送文件,還需要建立開發板和主機的網絡通訊,以便通過主機對開發板下載和上傳文件。這里主機的開發環境是基于Windows 10操作系統的Ubuntu虛機系統,在Win10上安裝vmware 虛機和串口超級終端,vmware里安裝了 uBuntu18.4版本的linux環境。
在啟動開發板之后,使用ifconfig 命令查看網絡配置,可見網卡都不通,因此需要進行網絡配置。
首先把一條有線網絡插入到開發板的網口中,其中下圖左邊的網口對應的是系統里的eth0, 右側的網口對應的是 eth1
圖2
插好網線后,進入系統網口配置文件所在目錄:cd /etc/systemd/network
打開10-eth.network 文件
vim 10-eth.network
根據自己網絡段,配置好開發板的地址,這里使用的靜態地址,在與主機相同網段內找一個空閑的IP地址,配置上即可,這樣避免動態地址分配,導致每次重啟可能會造成地址改變,帶來不必要的麻煩。
[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
配置完后,重啟開發板,再使用ifconfig查看網絡設備,eth0設備已經有IP地址,并且檢查ping是否能連通通外部主機。同時通過SecureCRT建立SSH登錄,也能夠順利登錄開發板了。
圖4
三、連接檢查網絡攝像頭 因為手邊暫時沒有MIPI CSI的攝像頭器件。因此查看開發板文檔,開發板系統是一個標準的ARMLinux 4.19系統,那么它就可以支持uvcamera, 因此找了一款通用型的網絡攝像頭Logitech Webcam C270 USB網絡攝像頭作為視頻采集的設備,把攝像頭插入開發板的USB口,檢測開發板是否能夠支持該攝像頭,。連接好攝像頭后,進入系統查看驅動加載信息。
圖5查看系統的版本
圖6 連接USB攝像頭
SecureCRT工具里進入開發板環境里,查看USB總線信息以及開發板USB設備信息如下圖:
圖7
圖8
從系統設備驅動加載信息上看,開發板已經為這個攝像頭識別出 audio 和 uvcvideo 設備,并成功加載驅動。使用查看USB設備詳細驅動參數命令,可查看到連入開發板的所有USB設備,以及連接位置,USB總線結構等信息。進一步查看攝像頭所對應的USB設備號和相關參數,如下圖紅色圈設備即為該攝像頭設備,記下這些參數,后面軟件開發時需要,否則程序將不能正確的采集到視頻畫面。
usb-devices
圖9
四、檢測攝像頭支持的采集視頻規格 連接好開發板和USB攝像頭后,還需要獲得開發板支持這款攝像頭對視頻采集的規格,不同攝像頭采集的規則并不相同,不同開發板支持采集的規格也不同,因此需要對當前的硬件連接做一下攝像頭視頻支持規則檢測。
可采集視頻規格檢測代碼在網上就有,在github上搜索Vv4l2_apture c++ 開源工程,即可以到該原始工程,git下載到主機環境中,然后根據板子的SDK,開始修改…(此處省去代碼修改的一萬字),主要是修改相關參數和函數。
https://github.com/soramimi/v4l2capture
圖10
圖11
經過修改調試代碼后,最后在板上成功的運行,并輸出開發板對攝像頭支持的格式列表,如下: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
五、采集程序開發測試 獲得攝像頭的設備參數以及能夠采集的視頻規格參數以后,就可以開發視頻采集程序,在開發采集程序前,還需要查看一下攝像頭的用戶層抽象操作設備,一般在/dev/下,使用以下命令查看抽象出的設備文件:
ls –ls /dev/video*
可以看到抽象的視頻采集設備,后面將試用設備控制代碼來打開操作它。
另外在看一下采集設備對 v4l2 系統的驅動,命令如下:
ls -l/sys/class/video4linux/video*
這兩個命令是在攝像頭底層驅動加載工作正常后才會出現,如果底層驅動有任何問題,這兩個命令將不會有相應信息顯示。
采集視頻采用的是V4L2視頻框架。V4L2是Video for linux2的簡稱,為linux中關于視頻設備的內核驅動。在Linux中視頻設備是設備文件,可以像訪問普通文件一樣對其進行讀寫,攝像頭在/dev/video*下,如果只有一個視頻設備,通常為/dev/video0。V4L2在設計時,是能支持很多廣泛的設備,但它們之中只有一部分是真正的視頻設備:
可以支持多種設備,它可以有以下幾種接口:
1. 視頻采集接口(video capture interface):這種應用的設備可以是高頻頭或者攝像頭.V4L2的最初設計就是應用于這種功能的.
2. 視頻輸出接口(video output interface):可以驅動計算機的外圍視頻圖像設備--像可以輸出電視信號格式的設備.
3. 直接傳輸視頻接口(video overlay interface):它的主要工作是把從視頻采集設備采集過來的信號直接輸出到輸出設備之上,而不用經過系統的CPU.
4. 視頻間隔消隱信號接口(VBI interface):它可以使應用可以訪問傳輸消隱期的視頻信號.
5. 收音機接口(radio interface):可用來處理從AM或FM高頻頭設備接收來的音頻流.
圖12
圖13
代碼比較長,這里放出修改的部分關鍵代碼如下:- #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文件,編寫編譯腳本,進入GL2編譯環境下,進行編譯調試(省去調試修改代碼xxx字)最后把編譯好的程序上傳到開發板上,啟動運行如下;
v4l2capture-m save -d /dev/video0 -t usb -F YUYV -w 640 -h 480 -f 15 -o/home/root/test.yuv -n 300
參數含義如下:
-d 選擇采集設備
-t usb采集
-F 采集視頻色彩數據組織格式,YUYV對應的ffmpeg里就是 YUV422格式
-w 采集視頻畫面長度,這個寬度必須是采集設備支持的規格表里的參數
-h 采集視頻畫面高度,同上需要滿足視頻規格標準
-f 采集幀率,必須是視頻采集支持的規格
-o 輸出文件
-n 采集幀數
圖14
采集完成后,將yuv數據上傳到windows下,使用GL2工具包下的tools目錄下的YUV Player.exe,播放,因為yuv文件不記錄視頻的長寬,以及格式信息,所以需要在yuv播放器中需要配置正確的尺寸,和視頻格式信息,才能正確的播出。
圖15
文末放了兩段視頻,一段是是手機拍攝,拍攝啟動采集程序和移動攝像頭的過程。另外一段視頻為采集到的yuv數據上傳到Ubuntu主機后,經過轉換和編碼生成mp4,可以看攝像頭到實際采集到的畫面效果。六、視頻采集開發測評總結 通過對Logitech C270 攝像頭的視頻采集開發測試來看,RZGL2開發板支持視頻采集功能很完善,支持V4L2,FFMPEG這樣常用的音視頻處理框架,使得很多音視頻應用移植起來成為可能,也比較簡單。
從采集到的視頻看,采集速率較高,支持視頻的規格也很廣。這為后面開發提供很好的基礎,在后面較長時間(>60分鐘)的視頻采集測試中,采集程序和系統運行非常穩定,沒有出現異常中斷等現象,并且在持續視頻采集中,觸摸CPU感覺升溫不明顯,這也可以看該處理優良的功耗表現。
攝像頭采集到的視頻回放,開發板體驗視頻詳見作者原帖子
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。
舉報投訴
-
飛凌
+關注
關注
0文章
134瀏覽量
16171 -
開發板試用
+關注
關注
3文章
301瀏覽量
2147
發布評論請先 登錄
相關推薦
瑞薩電子RZ MPU家族精品RZ/N2L產品介紹
瑞薩生態合作伙伴RT-Thread推出了一款高性能、多功能以太網MPU開發板EtherKit,搭載瑞薩電子RZ/N2L,并攜手瑞薩電子舉辦了產品發布會和產品研討。瑞薩電子在本次活動中介紹了瑞薩明星
瑞薩RZ/G2L微處理器的SD卡GPIO控制功能介紹
RZ/G2L微處理器配備Cortex-A55(1.2 GHz) CPU、16位DDR3L/DDR4接口、帶Arm Mali-G31的3D圖形加速引擎以及
RZ/G2L高速虛擬串口方案 基于瑞薩RZ/G2L SMARC開發板的虛擬(Virtual UART)實現方案
RZ/G2L具有豐富的外設,比如千兆以太網,CANFD以及豐富的UART接口,可以滿足工業數據收集處理相關的應用。本文主要介紹基于瑞薩RZ/G2L SMARC
發表于 11-20 14:41
?572次閱讀
飛凌全志T527開發板buildroot系統下擴大rootfs分區
一、實驗環境介紹
硬件:飛凌T527開發板(2G+16G)
軟件:全志Tina sdk
二、查看當前存儲分布
登入
發表于 07-18 14:45
【米爾-瑞米派兼容樹莓派擴展模塊-試用體驗】值得擁有的米爾-瑞米派兼容樹莓派生態板
今天為大家介紹一塊米爾出的精致生態開發板-米爾-瑞米派兼容樹莓派擴展模塊。
超高性價比的RZ/G2L工業級處理器
RZ/G2L是瑞薩在智
發表于 05-13 11:28
RZ/G2L Demo調試經驗流程分享(1)
r01us0553ej0107-rz-g(Release Note).pdf,r01us0556ej0102-rz-g(Board_StartUp_Guide_smarcEVK).pdf,對SMARC EVK of RZ/
【米爾-瑞米派兼容樹莓派擴展模塊-試用體驗】初始開發板_米爾-瑞米派兼容樹莓派擴展模塊
的開發板,他兼顧了嚴肅產品開發和愛好者創意實現兩種需要。告訴你,選擇它的五大理由:
1.工業芯片:采用瑞薩RZ/G2L雙核A55芯片,芯片是工業級,結溫可達-40到+125度,滿足10
發表于 04-29 11:42
RZ/G2L微處理器DDR ECC功能和機制概要
RZ/G2L微處理器配備Cortex?-A55 (1.2 GHz) CPU、16位DDR3L/DDR4接口、帶Arm Mali-G31的3D圖形加速引擎以及
評論