`
prowl
  • 浏览: 79316 次
  • 性别: Icon_minigender_1
  • 来自: 艾泽拉斯
社区版块
存档分类
最新评论

JAVA做音视频解析(MP4)

阅读更多
java用来做音视频解析的还是挺少的,刚巧领导给分派了这个工作,就硬着头皮干了4个月。基本上算能解决mp4的音视频解析了。share一下,希望能对有这方面需求的人提供帮助,也希望能有更好的建议和解决方案。

此文不涉及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方面的。


分享到:
评论
19 楼 yhh 2013-05-25  
我现在也在做视频,音频这快,请问那个解析涉及哪些东西,网页中嵌套的视频文件能解析吗?谢谢
18 楼 tapestry1122 2011-08-30  
有mp4parser干嘛不用呢?
mp4文件格式就是n个container组成的
17 楼 hnzhangshi 2010-06-09  
能不能提供一些jave的资料,最近我也是为了工作,要用java解析视频音频文件,我的邮箱是hnzhangshi@163.com,谢谢了
16 楼 dizdev 2010-03-01  
Good Point~~~

我一直在做这方面的事情~~

使用你这样的方法只能针对 文件格式的 进行编解码~~  right?

那么在传输上就存在瓶颈,because所有的工序都要经过文件方式编解码!

我一直在写关于mpg4的软编码包,这样可以提供流支持从而达到同步,但是目前进展太慢

1:严重缺乏资料
2:没有任何借鉴

有兴趣大家可以一起研究,造福java群体
15 楼 jeeper 2009-12-26  
请问楼主c/c++有从视频(如rm等)文件中提取音频信息的么?
14 楼 xiaobao0501 2009-12-25  
还是有点意思的.只不过领域不同罢了.
任何文件都有其组成规律.读协议很痛苦的.
以前曾经曾经被逼验证一个bmp图片是否是黑白的方法,就是缺少类似楼主这种资料.
谢谢分享.没准以后有用呢.
13 楼 rocwon 2009-12-23  
我在2004年之前做这个玩意儿,MPEG2/4的解码/传输/播放,RTP/RTCP协议栈是自己实现的。当初我硬着头皮研究了两个东西:FFMPEG和MPEG4IP
12 楼 ctfzh 2009-12-22  
我看了老半天还是没有看懂
11 楼 cw1011 2009-12-22  
看不懂 不过楼主的共享精神值得学习
10 楼 prowl 2009-12-21  
回楼上,我这代码上面写了几十行注释,您都没看吧
9 楼 tian-84 2009-12-21  
请问,有人能知道楼主在写些啥不。。。。反正我是看不懂。。。。代码也没注释啊,尤其是那段解析的代码,更是云里雾里!
8 楼 prowl 2009-12-21  
mp4=h264+aac

分别解析h264,aac,在根据特定的协议进行组装。

如果你在工作用遇到这样的问题,很快就会明白的
7 楼 prowl 2009-12-21  
回jd2bs:

c,c++确实有很好的库,甚至封装了RTP,RTCP协议!!其实我做这个本身也是硬着头皮来,本身有好的solution,何必要在java上浪费时间,可这是工作。我记录下这些也就为能给予一些同样“为了工作”需要用java来分析多媒体文件的童鞋们一些帮助,同时也希望在这方面有好的经验,或者正在做这方面开发的童鞋也多多给予我一些建议。
6 楼 andy54321 2009-12-21  
不是很明白
现在对流媒体有些兴趣
5 楼 jd2bs 2009-12-21  
java做audio,vedio 编解码 视频发送,并发性能是个大问题 ;何况你这里用在win主机下 更不靠谱了 ;这件事情 应该由c来做 我想这方面c,c++都有完整的库
4 楼 aoliwen521 2009-12-21  
非常好。。很有帮助
3 楼 wslfh2008 2009-12-21  
看不懂,能不能说一下原理啊?
2 楼 fengsky491 2009-12-21  
完全看不懂
1 楼 frankiehuang 2009-12-20  
看起来是用来JNI?

相关推荐

    音视频时长解析软件,附javad代码解析类

    音视频时长解析软件,附javad代码解析类 音视频时长解析软件,附javad代码解析类

    java语音视频功能

    java项目,下载导入即可运行。通过监听获取声音并解析成中文

    java中使用FFMpeg获取视频时长

    在java中上传视频时根据需求,使用FFMpeg获取视频的时长

    1078解析推流源代码(netty+javacv+spring+maven+rtp+rtmp)

    解析1078部标终端推流,并转发至rtmp流服务器.代码有点乱但是本人保证可用. 1078分了2014和2016.该版本是否都支持我已近刚忘记了.但是大同小异对不对~~就是解析的时候注意下就行了

    java多种读取(文件,视音频)信息方式

    包含了常用到的几种二进制或文件读取方式,很齐全,可直接使用

    MediaInfo音视频信息解析类

    有源码和说明,包括一些简单的实例,适合自己二次封装并使用。

    java源码包---java 源码 大量 实例

    util实现Java图片水印添加功能,有添加图片水印和文字水印,可以设置水印位置,透明度、设置对线段锯齿状边缘处理、水印图片的路径,水印一般格式是gif,png,这种图片可以设置透明度、水印旋转等,可以参考代码加以...

    Android使用FFmeg进行音视频解码,实时回调H264流到java接口中 已经实现JNA的调用代码,可以直接调用

    Android使用FFmeg进行音视频解码,实时回调H264流到java接口中。已经实现JNA的调用代码,可以直接调用。使用时可以直接通过一个方法就可以实时的获取到从rtsp或rtmp视频流中解析出的H264视频流数据。简单、方便。

    JAVA上百实例源码以及开源项目源代码

    util实现Java图片水印添加功能,有添加图片水印和文字水印,可以设置水印位置,透明度、设置对线段锯齿状边缘处理、水印图片的路径,水印一般格式是gif,png,这种图片可以设置透明度、水印旋转等,可以参考代码加以...

    java源码包4

    util实现Java图片水印添加功能,有添加图片水印和文字水印,可以设置水印位置,透明度、设置对线段锯齿状边缘处理、水印图片的路径,水印一般格式是gif,png,这种图片可以设置透明度、水印旋转等,可以参考代码加以...

    java源码包3

    util实现Java图片水印添加功能,有添加图片水印和文字水印,可以设置水印位置,透明度、设置对线段锯齿状边缘处理、水印图片的路径,水印一般格式是gif,png,这种图片可以设置透明度、水印旋转等,可以参考代码加以...

    JAVA上百实例源码以及开源项目

    util实现Java图片水印添加功能,有添加图片水印和文字水印,可以设置水印位置,透明度、设置对线段锯齿状边缘处理、水印图片的路径,水印一般格式是gif,png,这种图片可以设置透明度、水印旋转等,可以参考代码加以...

    java源码包2

    util实现Java图片水印添加功能,有添加图片水印和文字水印,可以设置水印位置,透明度、设置对线段锯齿状边缘处理、水印图片的路径,水印一般格式是gif,png,这种图片可以设置透明度、水印旋转等,可以参考代码加以...

    成百上千个Java 源码DEMO 4(1-4是独立压缩包)

    util实现Java图片水印添加功能,有添加图片水印和文字水印,可以设置水印位置,透明度、设置对线段锯齿状边缘处理、水印图片的路径,水印一般格式是gif,png,这种图片可以设置透明度、水印旋转等,可以参考代码加以...

    Java在线答题系统(在线考试,问卷调查,在线练题).zip

    支持题型:单选题、多选题、填空题、问答题、判断题、附件题、材料题、视频题、音频题支持答题类型:手工配置 试卷答题、随机抽题练习社交功能:试题收藏、试题评论、试题解析、试题点赞权限控制:题库权限、考场...

    java jdk实列宝典 光盘源代码

    读写Blob数据,blob数据常以二进制形式存储比较大的文件数据,如图片、视频文件等,本文介绍如何往数据库中读写blob数据,BlobData.java; 使用ResultSet更新数据库,UpdateWithResultSet.java; 使用RowSet,....

    CameraClient_大华java_大华android_jni_android_poetoj9_

    利用大华摄像头提供的java层的NetSDK.jar和JNI层相关的音视频编解码库实现在Android平台上对大华摄像头拉流功能

    音频解码,分贝计算 适用 wav/mp3/aac 16/24/32bit的音频类型

    音频解码,分贝计算 适用 wav/mp3/aac 16/24/32bit的音频类型 音频可视化

    基于Java的808协议网关设计源码

    808协议网关:基于Java开发,包含202个文件,其中176个Java源文件,用于实现协议...此外,系统还支持JT/T1078音视频协议、T/JSATL12苏标主动安全协议、T/GDRTA002粤标主动安全协议,并提供Android客户端编解码支持。

Global site tag (gtag.js) - Google Analytics