最近在做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摄像头录制视频相关推荐

  1. 微信小程序web-view 外部引用h5页面调用摄像头录制视频 配有提示音

    微信小程序web-view 外部引用h5页面调用摄像头录制视频 配有提示音 1.目前的需求是什么 2.都踩了那些坑 1.小程序 2.h5语音提示 3.语音合成声音录制不进去,ios有时候是麦克风,有时 ...

  2. php微信调用摄像头拍视频,公众号调用摄像头录制视频

    公众号微信网页调用摄像头录制视频,不想用input方法.  找了很久找到了腾讯优图.活体检测示例(http://open.youtu.qq.com/h5_ctl/living_detect),这里面采 ...

  3. 教你用Python控制摄像头录制视频~

    导语 ​Python如何下载网页上的图片呢? 哈喽哈喽铁汁萌~今天小编给大家分享另一个Python应用小程序,就是:用Python控制摄像头录制视频! 感兴趣的小伙伴耐心往下看哦

  4. 如何使用usb_cam和image_transport_plugins插件进行usb摄像头的视频获取和实时图像传输

    如何使用usb_cam和image_transport_plugins插件进行usb摄像头的视频获取和实时图像传输 前言 一.使用usb_cam驱动进行usb摄像头的图像获取 二.使用image_tr ...

  5. HTML5调用摄像头录制视频

    HTML5调用摄像头录制视频 不支持ie,ie下不支持webrtc,无法使用navigator.getUserMedia调用摄像头 <!DOCTYPE html> <html> ...

  6. openwrt实现挂载usb摄像头及视频保存

    路由器要实现挂载usb摄像头功能首先就需要路由器带USB接口,理论上带USB接口.支持openwrt刷机应该就能实现挂载usb摄像头的功能. 一.路由器配置 1.路由器刷好openwrt后,PC通过网 ...

  7. Ubuntu系统下安装opencv3.x并打开图片和视频文件以及打开摄像头录制视频

    目录 一.安装opencv 1.前置安装条件 2.安装环境 3.下载opencv3.4.11 4.解压安装包 5.开始安装 6.检查是否安装成功 二.显示图片和播放视频 1.显示图片 2.播放视频 三 ...

  8. opencv 利用快捷键来实现USB摄像头录制和抓拍

    设想一下现在我们有这样一个需求,需要通过键盘来实现usb摄像头的录制和抓图,并且最终保存的名称用当前的时间来命名. 解决思路: 由于之前自己的很多操作都是在QT上进行的,因此本次的需求也可以借助QT这 ...

  9. python调用摄像头录制视频_Python OpenCV使用摄像头捕获视频

    我们知道,OpenCV是一款强大的跨平台的计算机视觉库,使用它能完成我们对于图像和视频处理的很多功能,今天,我们使用OpenCV来捕获计算机摄像头的视频. 使用OpenCV捕获摄像头视频 我们知道,视 ...

  10. Android前置后置摄像头录制视频综合版

    公司有个项目,有一个需求是录制视频上传到网上,原本准备使用系统的录制功能,发现界面的跳转不能满足需求.于是就只能用自己写的,然后我也不会,就找了很多网上的例子,发现总是有些问题,然后我总结了一下写成了 ...

最新文章

  1. swift 语言评价
  2. 十分钟搞懂什么是CGI
  3. Maven入门极简使用教程
  4. HTML5之webSocket使用
  5. 源码安装zabbix遇到的报错集锦
  6. 浅谈云网融合与SD-WAN
  7. scrapy Crawl_spider
  8. 好用java库(二) : lambdaj (集合操作)
  9. python繁体中文到简体中文的转换
  10. 通过ROS控制真实机械臂(17) --- 视觉抓取之ORK实现三维物体识别
  11. MATLAB 如何使用pascal函数创建Pascal(帕斯卡)矩阵
  12. SAN:存储区域网络及其协议
  13. 小米10pro手机电路图 主板元件位号图
  14. 数据结构与算法之迷宫回溯
  15. php guzzle,php – 如何使用Guzzle 6记录所有API调用
  16. Springboot整合Shiro之授权
  17. uni-app 动态添加style 动态绑定背景图片无效
  18. python异常-TypeError: ‘tuple‘ object is not callable.当不同的环境下同一个语句运行结果不同时,不如重启程序、更改不相关变量试试
  19. oracle之concat()函数
  20. Electron常见问题 60 - 报错:Could not start audio source

热门文章

  1. Readyboost功能
  2. 微信小程序 实现点击收藏功能
  3. 智慧屏如何连接电视盒子
  4. wps启用编辑按钮在哪里_wps页面设置在哪里?wps页面设置使用教程
  5. 苹果笔记本没有计算机管理员,Mac管理员账户丢失怎么办
  6. java 坐标反算_Java实现坐标反算方位角
  7. 2021大学网课答案搜题公众号
  8. C语言pow函数返回值一直是0
  9. 电影《邪不压正》打动我的
  10. echarts实现组织结构图