锁定老帖子 主题:JAVA做音视频解析(MP4)
精华帖 (11) :: 良好帖 (15) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2009-12-18
最后修改:2010-03-02
此文不涉及RTP,RTCP协议,H264解码,因为本人的专业知识实在有限,不过我还是特别希望有此方面开发经验的兄弟指点一二(c/c++ 方向的也可以) Lib:这里用到了jave(一个日本的framework封装了ffmpeg),spring2.5.6,依赖于jdk1.6和ffmpeg SDK3.2。 MP4利用ffmpeg分割为aac和h264文件分别解析,可将如下代码封装到java.lang.ProcessBuilder,多线程调用进行MP4分离。 ffmpeg.exe -i **.mp4 **.h264 -vstats_file **.log ffmpeg.exe -i **.mp4 **.aac 特别说明下,分离**.h264文件后面跟了一个 -vstats_file **.log ,这是视频分隔输出流日志,后面解析h264文件时要用到的,目前这个日志只试用于win主机,*nix经测试打印日志不全,暂时没找到好的解决方法. 一 aac格式文件的解析: aac文件格式很简单,header(7个字节)-content-header-content...,其中header分为fixed和variable两种,这里采用标准音频(援引标准文档): adts_fixed_header() { syncword; 12 bslbf ID; 1 bslbf layer; 2 uimsbf protection_absent; 1 bslbf profile; 2 uimsbf sampling_frequency_index; 4 uimsbf private_bit; 1 bslbf channel_configuration; 3 uimsbf original/copy; 1 bslbf home; 1 bslbf } adts_variable_header() { copyright_identification_bit; 1 bslbf copyright_identification_start; 1 bslbf frame_length; 13 bslbf adts_buffer_fullness; 11 bslbf number_of_raw_data_blocks_in_frame; 2 uimsfb } 可以看到,两部分各28比特位,共56比特位,7字节. 首两个字节一般都是1111 1111 1111 0001,如果音频数据包含crc校验信息,最后一位就是0(看文档是这样的,但没有实作). 对应关系如下: syncword 1111 1111 1111 ID 0 layer 00 protection_absent 1 然后接下来的一个半字节, 如下: profile 两位,见下表 sampling_frequency_index 四位,见下表 private_bit 0 channel_configuration 三位,见下表,立体声为2,即010 original_copy 0 home 0 这部分标志位需要解释一下,援引标准文档 profile Table 31 – Profiles 0 Main profile 1 Low Complexity profile (LC) 2 Scalable Sampling Rate profile (SSR) 3 (reserved) 再看Variable部分 前两位,一般都是00 copyright_identification_bit 0 copyright_identification_start 0 数值,等于数据包大小加上7--header的大小.其实就是第二个adts chunck的起始地址. frame_length 00 0001 1000 000 全是1,即0x7FF adts_buffer_fullness 1 1111 1111 11 一般为00 number_of_raw_data_blocks_in_frame 00 比特位映像: 1111 1111 1111 0 00 1 xx xx- xx 0 x- x x 0 0 0 0 xx- xxxx xxxx xxx 1- 1111 1111- 11 00 这里附一些我解析aac文件的代码: private long parse(long offset) throws CannotParseException { int fl = 0; try { is.skip(offset); byte[] syncword = new byte[2]; int i = is.read(syncword); if (i != -1) { if (syncword[0] == -1 && (syncword[1] & -15) == -15) { is.skip(1); byte[] framelength = new byte[3]; int k = is.read(framelength); if (k != -1) { byte front = (byte) (framelength[0] & 3); byte middle = framelength[1]; byte end = (byte) (((framelength[2] & -32) >> 5) & 7); fl |= front; fl <<= 8; fl |= middle; fl <<= 3; fl |= end; AudioBean bean = new AudioBean(); bean.setFramenum(++blocks); bean.setOffset(fl); bean.setPosition(position); list.add(bean); position += fl; } else { return -1; } } else { return -1; } } else { logger.info("aac file that length's : " + position + " parse done!"); return 0; } } catch (IOException ex) { logger.error("during parse aac file occur unexpected exception", ex); throw new CannotParseException(ex); } return fl - 7 + 1; } 递归上面这个方法,记录一些关键的字段,保存到list里,这里我定义了一个对象AudioBean,他继承于MediaBean,没有子类字段。因为标准aac文件时线性的,所以记录了以下字段,以便分析。 public class MediaBean implements Serializable { /** * 起始位置 */ private long position; /** * 每帧偏移量 */ private int offset; /** * 帧位置 */ private int framenum; /** * 起始时间 */ private float time; //setter getter 方法 } 由于是标准线性aac,那么总时间与总帧数的比大概就是每帧的时间(必须注明下,没有decode aac文件的内部数据,需要精确数据的请不要采取此方法)。经过处理的list<MeadiaBean>是一个完成的aac信息,我们可以用他来处理aac文件的截取和传输。 二 H264文件的解析 刚才的命令行产生的**.log文件现在用到了。贴一小段log信息 frame= 1 q= 31.0 f_size= 6927 s_size= 7kB time= 0.083 br= 665.0kbits/s avg_br= 665.0kbits/s type= I frame= 2 q= 31.0 f_size= 17 s_size= 7kB time= 0.167 br= 1.6kbits/s avg_br= 333.3kbits/s type= P frame= 3 q= 31.0 f_size= 11 s_size= 7kB time= 0.250 br= 1.1kbits/s avg_br= 222.6kbits/s type= P frame= 4 q= 31.0 f_size= 11 s_size= 7kB time= 0.333 br= 1.1kbits/s avg_br= 167.2kbits/s type= P frame= 5 q= 31.0 f_size= 11 s_size= 7kB time= 0.417 br= 1.1kbits/s avg_br= 134.0kbits/s type= P 其中 frame 为帧数,f_size为此帧大小,s_size是一个不是特别精确的累积帧大小,time为结束时间。 这些字段已经足够分析h264文件了。 项目还包括缓存,池,等概念,是一个完成的视频发送服务器,涉及到公司内部的视频协议就不公开了。希望能结识有视频研发经验的朋友,交流经验,其实我想把他再完善一下做成一个开源的视频分析框架,无奈专业知识有限,尤其是aac和h264方面的。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2009-12-20
看起来是用来JNI?
|
|
返回顶楼 | |
发表时间:2009-12-21
完全看不懂
|
|
返回顶楼 | |
发表时间:2009-12-21
看不懂,能不能说一下原理啊?
|
|
返回顶楼 | |
发表时间:2009-12-21
非常好。。很有帮助
|
|
返回顶楼 | |
发表时间:2009-12-21
java做audio,vedio 编解码 视频发送,并发性能是个大问题 ;何况你这里用在win主机下 更不靠谱了 ;这件事情 应该由c来做 我想这方面c,c++都有完整的库
|
|
返回顶楼 | |
发表时间:2009-12-21
不是很明白
现在对流媒体有些兴趣 |
|
返回顶楼 | |
发表时间:2009-12-21
最后修改:2009-12-21
回jd2bs:
c,c++确实有很好的库,甚至封装了RTP,RTCP协议!!其实我做这个本身也是硬着头皮来,本身有好的solution,何必要在java上浪费时间,可这是工作。我记录下这些也就为能给予一些同样“为了工作”需要用java来分析多媒体文件的童鞋们一些帮助,同时也希望在这方面有好的经验,或者正在做这方面开发的童鞋也多多给予我一些建议。 |
|
返回顶楼 | |
发表时间:2009-12-21
mp4=h264+aac
分别解析h264,aac,在根据特定的协议进行组装。 如果你在工作用遇到这样的问题,很快就会明白的 |
|
返回顶楼 | |
发表时间:2009-12-21
请问,有人能知道楼主在写些啥不。。。。反正我是看不懂。。。。代码也没注释啊,尤其是那段解析的代码,更是云里雾里!
|
|
返回顶楼 | |