最近遇到这样一个问题,一个媒体文件扩展名为.mpg,但是它的封装格式确实mpegts的。所以通过扩展名来判断文件的封装格式,是有点不太靠谱。每种封装格式都有自己的判断方法,没事总结了一下。
1、MP3
MP3文件是一种流媒体文件格式,所以没有文件头,要判断是不是MP3文件只能分析帧头数据。MP3文件还可能存在TAG,有两种TAG,ID3V1和ID3V2。ID3V1存放在MP3文件的末尾,占据128个字节;ID3V2在MP3文件的头部,大小不固定。因此要获得MP3文件的信息,不但要判断文件时候含有TAG并对TAG进行解析,还要解析帧头数据。
因此,在判断一个文件是否是MP3文件,还是比较复杂的。
2、ASF、WMA与WMV
对于这三种文件格式,它们的头16个字节都是固定的,为十六进制的“30 26 B2 75 8E 66 CF 11 A6 D9 00 AA 00 62 CE 6C”,用来标识这个文件是否为ASF、WMA或者WMV文件。虽然有音频文件格式,也有视频文件格式,但是这三种文件格式可以共享同一个解析器,因为他们的封装格式是一样的。
3、APE
每个APE文件的开头有四个固定的字节,十六进制为“4D 41 43 20”,是ASCII值,对应的四个字符为“MAC ”。判断一个文件是否为APE文件,可以通过解析文件的开始四个字节是否为“4D 41 43 20”。
其中“MAC ”应该是Monkey Audio Compression的缩写。
4、AVI与WAV
AVI与WAV都是RIFF文件格式。要判断一个文件是否是AVI文件或者WAV文件,要首先了解一下RIFF文件格式。RIFF文件使用四字符码FOURCC来标识数据类型。RIFF文件的格式如下:
首先,文件最开始的四个字符码是“RIFF”,表示这是一个RIFF文件;
其次,紧跟着的四个字节表示此RIFF文件的大小,对于AVI这样的媒体文件,四个字节无法表示文件的大小,因此没什么意义;
然后,四个字符表示文件的具体类型,如AVI,WAVE等;
最后,实际的数据。
因此,我们就可以通过RIFF的结构特点来判断一个媒体文件是否为AVI文件或者WAV文件。比如判断AVI文件,
char tmp[12];//获得文件开始的12字节的数据
if (!memcmp(tmp, "RIFF", 4) && !memcmp(&tmp[8], "AVI ", 4)) {
该媒体文件为AVI文件;
} else {
该媒体文件不是AVI文件;
}
5、FLAC
FLAC文件的开头的有8个固定的字节,十六进制为“66 4C 61 43 00 00 00 22”,这一点可以通过ffmpeg的flac编码器看出来。因此来判断一个文件是否为FLAC文件时,就可以通过这八个字节来判断,对应的字符为“fLaC\0\0\0\042”。
6、OGG
OGG格式是以page为单位进行封装的,每个page之间都是相互独立的。OGG文件没有单独的文件头作为OGG文件的标识,即文件的一开始就是page的开始。要想判断一个媒体文件是否为OGG文件,就需要解析它的第一个page。
OGG文件每个page的开头有4个固定的字节,十六进制为“4F 67 67 53”,对应的字符为“OggS”,表示page的开始。利用这个标识就可以判断文件是否为OGG文件。
ffmpeg在判断OGG文件时,不仅仅判断了这四个字节,还判断了第五个字节,该字节的值是否满足buf[5] <= 0x7,这个字节是page的flag,表示页的具体类型。
7、FLV
FLV文件格式比较好判断,在文件的开始有固定的三个字节,0X46 4C 56,对应的字符为FLV。通过这三个字节就可以判断是否是FLV文件。
8、MKV与WEBM
MKV格式仅仅包含两种Top Level Elements,即EBML Header和Segment。EBML Header包含了对MKV文件类型的描述信息,比如:EBML version、文件类型名、文件类型版本等。因此,可以通过解析EBML Header来判断是否为MKV文件。
此外,WEBM其实是以MKV文件格式为基础开发的一种新文件格式,因此它的判断方式和MKV的一样,而且两者可以共用解析器,在ffmpeg中就是采用这样的方式。
在EBML Header中有这样一个elememt:DocType,用来描述文件的类型。如果是MKV文件,它的内容为“matroska”,如果是WEBM文件,它的内容为“webm”。因此,通过EBML Header中的DocType,就可以准确的判断是MKV文件还是WEBM文件。
9、RM/RMVB
每个RM文件都以一个RM文件头开始,RM文件头用来标识文件是RMF类型。在RM文件中只有一个RM文件头,在文件头中包含一个object_id,这是RM文件的唯一标识符。这个标识符为“.RMF”,对应的ASCII为:0X2E 52 4D 46,这也是文件的最开始的四个字节。因此,可以通过这四个字节来判断是否为RM/RMVB文件。
10、MPEG2TS
MPEG2TS是一种流媒体文件格式,没有文件头,文件的一开始就是ts包数据。可以通过解析ts包来判断文件的格式。TS包的第一个字节为同步字节,是一个固定值0X47,表示后面是TS分组。因此,在判断TS文件时,就可以通过这个字节来判断。当然,如果,只判断一次,可能会出现错误的判断,因此,就需要多判断几次。
11、MPG/MPEG
MPG/MPEG文件有两种header:(1)0x000001B3 (2)0x000001BA
(1)说明文件只包含视频数据;(2)说明文件既有音频数据也有视频数据。判断MPG/MPEG文件,就可以通过这两种header来判断。
之前说到了MPEG2TS,那MPEG2PS呢?MPG/MPEG就是PS流文件。
12、MOV、MP4与3GP
这三中container采用了相同的封装格式,因此,无论是sniff方式,还是对数据流的解析方式,都是可以通用的,因此也就可以使用同一个解析器。在这些文件的开始位置,都会包含“ftyp”这样一个标记。这个标记不是从文件的第一个字节开始的,而是从第5个字节开始的,对应的十六进制码是0X66 74 79 70。简单的,就可以通过这个标记来sniff文件类型。
“ftyp”根据不同的Developer、不同的Release等,因此,存在各种类型。要想了解各种“ftyp”类型,可以参考下面的地址:
http://www.ftyps.com/
“ftyp”的类型会紧跟在“ftyp”这几个字符的后面,也是用四个字节来描述。因此,可以通过这八个字节更精确的来sniff文件的类型。