Android用MediaRecorder实现MPEG4视频监控
来源:互联网 发布:windows优化软件知乎 编辑:程序博客网 时间:2024/05/16 15:32
主要需要实现的功能是在Android手机上实时采集视频,并在远程比如PC机上实时显示出来,也就是以android手机作为监控摄像头。
一开始查到的是smartcam的一个开源项目,看了下源代码,发现其实现原理是利用Android 的camera图像的预采集,通过实现PreviewCallback类的回调函数onPreviewFrame,获得camera采集的原始图像数据之后,压成jpeg格式传到pc端。pc端对接收到的jpeg图像序列进行实时解压和显示,就达到了预想的效果。
虽然这种方式稍微显得比较笨拙,这个方式还可以接受。但是不可接受的是jpeg只是帧内压缩,320x280的图片序列,FPS大概是10上下,网络流量就到达了100kb/s以上。这个几乎是无法实际应用的。
于是必须直接传视频流,MPEG4或者H.264格式。貌似我的开发机上(HTC G8)只支持到MPEG4,所以还是选取MPEG4。但是如何实时采集视频流是一个大问题,毕竟在video方面,Android并没有提供一个类似于OnPreviewFrame的回调函数。
想到用opencore或者更为新一点的stagefright,大概看看了其sdk的框架后,马上泄气了,这个太庞大了。在http://www.linuxidc.com/Linux/2011-04/34468.htm的帖子中提到一个很好的解决方案,就是利用MediaRecorder:MediaRecorder的输出路径(其实叫file descriptor)除了是本地文件路径之外,还可以绑定socket端口。也就是说,通过一个socket端口,就可以实时获得MediaRecorder的视频流数据。
(其实上面博客的内容可以在开源项目sipdroid 的 videocamera文件中找到,但是非常感谢博客主人zhangzhenj对网友提问的回答,赞一个。)
通过socket接收的视频流与直接写在本地文件的视频流数据有点不一样,因为是通过socket传输,就无法对视频文件的回写,通常MediaRecorder结束录像的时候都会对视频文件进行回写处理,这样才可以被播放器播放。所以通过socket接受到的数据,保存下来是无法播放的。16进制方式查看了一下其输出文件,发现其前32byte都是00,紧接着就是mdat。问题就出现在这了:缺少了一个ftyp box 的描述(28 bytes)以及mdat的长度描述(4 bytes).网上已经有人顺利解决这样的问题,在数据中查找moov的起始位置,发现前面会有ftyp的描述,长度刚刚好28bytes。你可以copy这28bytes到文件开始的28byte中。这ftyp的描述是从moov的起始位置 的前32byte开始一直到前4byte(后面4byte是moov的长度描述)。然后mdat的长度就是 moov的起始位置 减去 0x20,道理就不解释了。然后把这个值写到mdat的前面4byte。刚刚好填满32byte,之后就能顺利播放了。
保存好的文件能播放之后,最后一个问题,如何在实时显示这个视频流呢?查看一下mpeg4的文件格式,很快就会知道答案,答案就在mdat中。mdat之后紧跟的就是视频媒体数据,每一帧以 00 00 01 b6 为开始标志,貌似没有结束标志,分帧的话估计要用这个。开始标志后紧接着的两bit就是I、P、B帧的标志了,分别对应值为00,01,10,记住是两bit不是两byte
好了,把mdat的一帧数据取出来,可以用ffmpeg解码,然后显示,这样的路子是可行的,不过细节还是有点麻烦,关键是ffmpeg在解码mpeg4的时候一定要先指定width和height,否则解码失败。
一开始查到的是smartcam的一个开源项目,看了下源代码,发现其实现原理是利用Android 的camera图像的预采集,通过实现PreviewCallback类的回调函数onPreviewFrame,获得camera采集的原始图像数据之后,压成jpeg格式传到pc端。pc端对接收到的jpeg图像序列进行实时解压和显示,就达到了预想的效果。
虽然这种方式稍微显得比较笨拙,这个方式还可以接受。但是不可接受的是jpeg只是帧内压缩,320x280的图片序列,FPS大概是10上下,网络流量就到达了100kb/s以上。这个几乎是无法实际应用的。
于是必须直接传视频流,MPEG4或者H.264格式。貌似我的开发机上(HTC G8)只支持到MPEG4,所以还是选取MPEG4。但是如何实时采集视频流是一个大问题,毕竟在video方面,Android并没有提供一个类似于OnPreviewFrame的回调函数。
想到用opencore或者更为新一点的stagefright,大概看看了其sdk的框架后,马上泄气了,这个太庞大了。在http://www.linuxidc.com/Linux/2011-04/34468.htm的帖子中提到一个很好的解决方案,就是利用MediaRecorder:MediaRecorder的输出路径(其实叫file descriptor)除了是本地文件路径之外,还可以绑定socket端口。也就是说,通过一个socket端口,就可以实时获得MediaRecorder的视频流数据。
(其实上面博客的内容可以在开源项目sipdroid 的 videocamera文件中找到,但是非常感谢博客主人zhangzhenj对网友提问的回答,赞一个。)
通过socket接收的视频流与直接写在本地文件的视频流数据有点不一样,因为是通过socket传输,就无法对视频文件的回写,通常MediaRecorder结束录像的时候都会对视频文件进行回写处理,这样才可以被播放器播放。所以通过socket接受到的数据,保存下来是无法播放的。16进制方式查看了一下其输出文件,发现其前32byte都是00,紧接着就是mdat。问题就出现在这了:缺少了一个ftyp box 的描述(28 bytes)以及mdat的长度描述(4 bytes).网上已经有人顺利解决这样的问题,在数据中查找moov的起始位置,发现前面会有ftyp的描述,长度刚刚好28bytes。你可以copy这28bytes到文件开始的28byte中。这ftyp的描述是从moov的起始位置 的前32byte开始一直到前4byte(后面4byte是moov的长度描述)。然后mdat的长度就是 moov的起始位置 减去 0x20,道理就不解释了。然后把这个值写到mdat的前面4byte。刚刚好填满32byte,之后就能顺利播放了。
保存好的文件能播放之后,最后一个问题,如何在实时显示这个视频流呢?查看一下mpeg4的文件格式,很快就会知道答案,答案就在mdat中。mdat之后紧跟的就是视频媒体数据,每一帧以 00 00 01 b6 为开始标志,貌似没有结束标志,分帧的话估计要用这个。开始标志后紧接着的两bit就是I、P、B帧的标志了,分别对应值为00,01,10,记住是两bit不是两byte
好了,把mdat的一帧数据取出来,可以用ffmpeg解码,然后显示,这样的路子是可行的,不过细节还是有点麻烦,关键是ffmpeg在解码mpeg4的时候一定要先指定width和height,否则解码失败。
大概思路就是这样了,完整的代码还没出来。
转载自:http://blog.sina.com.cn/s/blog_6568e7880100ttcd.html
阅读全文
0 0
- Android用MediaRecorder实现MPEG4视频监控
- Android用MediaRecorder实现MPEG4视频监控
- Android用MediaRecorder实现MPEG4视频监控
- Android用MediaRecorder实现MPEG4视频监控(转)
- Android用MediaRecorder实现MPEG4视频监控【转】
- Android基础--MediaRecorder类实现视频录制
- Android 拍照和视频录制实现mediaRecorder
- Android 用MediaRecorder实时视频采集
- Android MediaRecorder视频录制
- Android MediaRecorder录制视频
- 视频采集---MPEG4压缩实现
- Android中MediaRecorder类实现视频的录制
- android MediaRecorder录制音视频实现直播的基础
- Android MediaRecorder 实现录制无声视频 禁止录入声音
- Android视频监控实现(一)
- Android视频监控实现(二)
- Android视频监控实现(三)
- Android视频监控实现(四)
- C# 编辑器怎么配置最好
- 数据结构---二叉树的基本运算
- JEECMS——过滤器和拦截器
- 最近常用的几个命令 记录一下
- 顶象加固分析和一点还原
- Android用MediaRecorder实现MPEG4视频监控
- bzoj 4568: [Scoi2016]幸运数字(树上倍增+线性基)
- 在windows下安装windows+Ubuntu16.04双系统(下)
- C++获取文件版本信息
- UE4_C++使Actor属性出现在编辑器中
- cloudera cdh 5.11 编译 启动spark thrift server spark sql
- jQuery扩展插件封装
- “戏”说Spark-Spark核心-RDD 持久化机制详解
- 素数(质数)判断方法