USB摄像头录制视频
最近在做Android板上的USB摄像头录制视频的调试工作,在此记录一下开发历程和心得。
项目要求用USB摄像头录制视频,要求视频必须是720P+,25FPS+。
USB摄像头用的是海康威视摄像头,YUV只有10FPS,mjpeg可以达到30FPS。所以只能采用mjpeg方式。
开始找了网上开源的UVCCamera项目,先上连接 https://github.com/saki4510t/UVCCamera ,结果发现录制的视频帧率都达不到要求。
后面只能使用V4L2取摄像头的原始数据。参考这篇文章 安卓系统采用v4l2接口打开YUYV和MJPEG摄像头,支持热插拔。_alterli的博客-CSDN博客
取到的摄像头原始数据是一张张JPEG图片,将JPG图片编码为MP4就简单很多。先将JPEG解码为BMP数据,然后用Android自带编码器MediaMuxer,选择数据源格式为COLOR_Format32bitBGRA8888。但是有个问题,获取源数据,然后解码bmp,再然后编码到MP4,这个效率就很低了。
一方面受到摄像头制约(YUV只有10FPS),另一方面受到安卓板子性能制约,如何录制高帧率的MP4视频,真的是很头疼。
查了很多资料,走了很多弯路,也试过FFmpeg去将JPEG图片编码为MP4,结果效率实在不敢恭维。
没有办法,V4L2是目前唯一能走通的路。只能牺牲掉时效性,以空间换时间,多开线程,一边获取摄像头原始数据保存为JPEG文件,一边解码JPEG为bmp数据进行视频编码。这个方式可以达到30FPS,但是缺点也有,那就是视频文件需要在摄像头录制结束一段时间后才能做好。
后面换了一块性能更惨的板子,而且还不支持COLOR_Format32bitBGRA8888格式编码视频。
查看板子编码MP4所支持的数据源,发现只有YUV420p,所以关键问题就是把JPEG解码为YUV420P格式的数据。
查了一圈,看到网上bmp转YUV420p的算法很多,也很高效,JPEG解码为bmp本身就需要时间,再转码YUV420p,显然效率很难让人满意。以1280*720的JPEG图片为例,解码为bmp,再转YUV420P, 将近200~250ms。意思是一段10秒的视频,300帧图片,花费就是60~75秒。
不考虑bmp转YUV420P,有没有直接解码JPEG到YUV420P的办法呢。答案是肯定的。
利用libturbojpeg库可以实现,上关键代码
int tjpeg2yuv(unsigned char* jpeg_buffer, int jpeg_size, unsigned char** yuv_buffer, int* yuv_size, int* yuv_type) {tjhandle handle = NULL;int width, height, subsample, colorspace;int flags = 0;int padding = 1; // 1或4均可,但不能是0int ret = 0;handle = tjInitDecompress();tjDecompressHeader3(handle, jpeg_buffer, jpeg_size, &width, &height, &subsample, &colorspace);printf("w: %d h: %d subsample: %d color: %d\n", width, height, subsample, colorspace);flags |= 0;*yuv_type = subsample;*yuv_size = tjBufSizeYUV2(width, padding, height, subsample);*yuv_buffer =(unsigned char *)malloc(*yuv_size);if (*yuv_buffer == NULL){printf("malloc buffer for rgb failed.\n");return -1;}ret = tjDecompressToYUV2(handle, jpeg_buffer, jpeg_size, *yuv_buffer, width,padding, height, flags);if (ret < 0){printf("compress to jpeg failed: %s\n", tjGetErrorStr());}tjDestroy(handle);return ret; }
查看解码后的yuv_type,得到的是YUV422,我们需要的是YUV420P,所以貌似行不通。因为JPEG本身就是YUV编码的,所以得到的yuv_type就是JPEG用的,因此受制于摄像头,这里只能解出yuv422格式。那么只能将YUV422转为YUV420P了。
YUV422实际上有好几种,yuyv,yuv422p,yuv422sp。而YUV422转YUV420最简单有效的方式就是隔行抽取UV分量。这里不小心踩了一个坑,开始以为是隔一个取一个数据,怎么操作都不对,后来一想才反应过来应该是隔一行抽取一行。
最后验证发现果然效率提升了近一倍,编码一张JPEG图片100ms左右。一段10秒的视频,300帧图片,花费30秒左右,勉强只能这样了。
后面想到好的方式再继续优化。
USB摄像头录制视频相关推荐
- 微信小程序web-view 外部引用h5页面调用摄像头录制视频 配有提示音
微信小程序web-view 外部引用h5页面调用摄像头录制视频 配有提示音 1.目前的需求是什么 2.都踩了那些坑 1.小程序 2.h5语音提示 3.语音合成声音录制不进去,ios有时候是麦克风,有时 ...
- php微信调用摄像头拍视频,公众号调用摄像头录制视频
公众号微信网页调用摄像头录制视频,不想用input方法. 找了很久找到了腾讯优图.活体检测示例(http://open.youtu.qq.com/h5_ctl/living_detect),这里面采 ...
- 教你用Python控制摄像头录制视频~
导语 Python如何下载网页上的图片呢? 哈喽哈喽铁汁萌~今天小编给大家分享另一个Python应用小程序,就是:用Python控制摄像头录制视频! 感兴趣的小伙伴耐心往下看哦
- 如何使用usb_cam和image_transport_plugins插件进行usb摄像头的视频获取和实时图像传输
如何使用usb_cam和image_transport_plugins插件进行usb摄像头的视频获取和实时图像传输 前言 一.使用usb_cam驱动进行usb摄像头的图像获取 二.使用image_tr ...
- HTML5调用摄像头录制视频
HTML5调用摄像头录制视频 不支持ie,ie下不支持webrtc,无法使用navigator.getUserMedia调用摄像头 <!DOCTYPE html> <html> ...
- openwrt实现挂载usb摄像头及视频保存
路由器要实现挂载usb摄像头功能首先就需要路由器带USB接口,理论上带USB接口.支持openwrt刷机应该就能实现挂载usb摄像头的功能. 一.路由器配置 1.路由器刷好openwrt后,PC通过网 ...
- Ubuntu系统下安装opencv3.x并打开图片和视频文件以及打开摄像头录制视频
目录 一.安装opencv 1.前置安装条件 2.安装环境 3.下载opencv3.4.11 4.解压安装包 5.开始安装 6.检查是否安装成功 二.显示图片和播放视频 1.显示图片 2.播放视频 三 ...
- opencv 利用快捷键来实现USB摄像头录制和抓拍
设想一下现在我们有这样一个需求,需要通过键盘来实现usb摄像头的录制和抓图,并且最终保存的名称用当前的时间来命名. 解决思路: 由于之前自己的很多操作都是在QT上进行的,因此本次的需求也可以借助QT这 ...
- python调用摄像头录制视频_Python OpenCV使用摄像头捕获视频
我们知道,OpenCV是一款强大的跨平台的计算机视觉库,使用它能完成我们对于图像和视频处理的很多功能,今天,我们使用OpenCV来捕获计算机摄像头的视频. 使用OpenCV捕获摄像头视频 我们知道,视 ...
- Android前置后置摄像头录制视频综合版
公司有个项目,有一个需求是录制视频上传到网上,原本准备使用系统的录制功能,发现界面的跳转不能满足需求.于是就只能用自己写的,然后我也不会,就找了很多网上的例子,发现总是有些问题,然后我总结了一下写成了 ...
最新文章
- swift 语言评价
- 十分钟搞懂什么是CGI
- Maven入门极简使用教程
- HTML5之webSocket使用
- 源码安装zabbix遇到的报错集锦
- 浅谈云网融合与SD-WAN
- scrapy Crawl_spider
- 好用java库(二) : lambdaj (集合操作)
- python繁体中文到简体中文的转换
- 通过ROS控制真实机械臂(17) --- 视觉抓取之ORK实现三维物体识别
- MATLAB 如何使用pascal函数创建Pascal(帕斯卡)矩阵
- SAN:存储区域网络及其协议
- 小米10pro手机电路图 主板元件位号图
- 数据结构与算法之迷宫回溯
- php guzzle,php – 如何使用Guzzle 6记录所有API调用
- Springboot整合Shiro之授权
- uni-app 动态添加style 动态绑定背景图片无效
- python异常-TypeError: ‘tuple‘ object is not callable.当不同的环境下同一个语句运行结果不同时,不如重启程序、更改不相关变量试试
- oracle之concat()函数
- Electron常见问题 60 - 报错:Could not start audio source