上一篇我说了如何使用JNI进行h264编码,但是由于效率的问题 感觉并不太实用。
经过几天的折腾,并参照http://www.javaeye.com/problems/27244 大体实现的Android 的实时编码问题,但是只是思路,还没有进入代码实现的阶段。
比较重要的2个类 MediaRecorder ParcelFileDescriptor
MediaRecorder 是Android提供的进行采集编码的类,而 ParcelFileDescriptor是个用Socket实现 setOutputFile的一个类
在测试liuzongan 的程序的过程中,发现其他这位仁兄已经实现了我们需要的大部分的功能,唯一要处理的就是在服务器端的程序。
在这里我先猜测一下MediaRecorder写文件的过程
1 , MediaRecorder写入一个固定的头,估计是占位用的 都是00H( 占位的长度好像和使用的编码器有关系)
再插入 00 00 00 08 6D 64 61 74 (mdat box)
2,开始编码,并把编码后的没一个帧都添加到文件中,看到00 00 80了没, 了解h263的同志一定很熟悉,根本就是263视频的标志吗!
(如果有音频数据的话,很定会和视频数据交错在一起,但是我们的目标只是实时编码视频流,不需要处理音频,所以在初始化 MediaRecorder的时候我不不要 MediaRecorder.setAudioSource,这样就没有音频数据了。)
3 结束捕获。 MediaRecorder应该会返回到文件的头部填充文件头。但由于不是真正文件的关系,不能返回到头部,于是就把文件头附加到文件的后面了,感觉也就是 liuzongan 这仁兄提出的问题的答案了。
这个是,文件开头mdat box的长度,用于替换 00 00 00 08.
这个是3gp文件的头, 用于替换开头的占位。
4最后, MediaRecorder补充3gp文件的moov box ,这一部分已经属于3gp的媒体索引部分了,具体的内容对于我们来说已经不太关心了。大家可以参照http://www.cnitblog.com/zouzheng/archive/2007/04/04/25155.html 研究。
下开始说我们要是实现的内容了
其实有了上面的描述,大家应该能想到我们要实现的其实就是视频的分帧就可以了。。
server 端处理h263的方法
1一步 找到 mdat这个串, 后面的数据就是我们要的视频数据了,
2在流中查找 00 00 80 这个标志,每一个都是一帧数据的开始
对于 h264和mpeg4的,要预采集一次数据,这是因为mp4v的相关解码参数,在esds box中的, 而esds box 是在采集结束后才写入的,所以对于我们的程序来说需要先编码一次 获取 mp4v的相关解码参数,然后在用相同的参数进行采集, 呵呵 这样我们就能获得原始的mp4v流了
h264一样 不过是存在了 avcC box 里