ffmpeg源码分析及mp4文件解析
?
一.mp4文件的組織
1. mp4文件的box(ffmpeg中叫atom)
mp4是由一系列的box組成的,每個box的header是8個字節(4字節的長度,4字節的type)
第一個box比較特殊,其type類型為ftyp,還包含一個sub-type
0000 0020 6674 7970??--> 第1個box的長度為0x20, type=ftyp
6973 6f6d ?-->其sub-type=isom
0000 0008 6672 6565??--> 第2個box的長度為0x08, type=free
0609 6f8e 6d64 6174 ? --> 第3個box的長度為0x06096F8E, type=mdat
由此可以看出第4個box:
0x06096F8E+0x08+0x20=0x06096FB6處是第4個box
000c ca81 6d6f 6f76 ? ?--> 第4個box的長度是0x0cca81, type=moov
?
1.2 計算文件的大小
所以整個文件的大小為?0x20+0x08+0x0x06096F8E+0x0cca81=0x6163A37=102119991
cong@msi:/work/ffmpeg/ffmpeg-3.0.1$ ls -l ../san.mp4
-rw-rw-r-- 1 cong cong 102119991 Sep 10 ?2015 ../san.mp4
1.3?關于box-type:
box-type可以是如下一個:
"ftyp",?"mdat",?"moov",?"pnot",?"udta",?"uuid",?"moof",?"free",?"skip",?"jP2 ",?"wide",?"load",?"ctab",?"imap",?"matt",?"kmat",?"clip",?"crgn",?"sync",?"chap",?"tmcd",?"scpt",?"ssrc",?"PICT".
sub-type可以取如下一個:
sub-type which must be one of values:?"avc1",?"iso2",?"isom",?"mmp4",?"mp41",?"mp42",?"mp71",?"msnv",?"ndas",?"ndsc",?"ndsh",?"ndsm",?"ndsp",?"ndss",?"ndxc","ndxh",?"ndxm",?"ndxp",?"ndxs".
?
1.4總結
一個mov文件就是由ftyp free mdat moov這四個部分組成
ftyp --> 格式
free --> 不關心
mdat --> 音視頻數據
moov --> 包含一系列次級box:一個mvhd及多個trak
?
1.5 如下圖所示:
清楚了
?
二. BOX的具體解析
2.1FileTypeBox--> ftype解析
0000000:?0000 0020 6674 7970 6973 6f6d 0000 0200?...?ftypisom....
0000010:?6973 6f6d 6973 6f32 6176 6331 6d70 3431 isomiso2avc1mp41
0000 0020 6674 7970??--> 第1個box的長度為0x20, type=ftyp
6973 6f6d ? ? ? ? ? ? ? ? ? ? --> major_brand: isom
0000 0200 ? ? ? ? ? ? ? ? ? ?--> minor_verion: isom的版本號
6973 6f6d 6973 6f32 6176 6331 6d70 3431--> 兼容isom iso2 avc1 mp41這四個協議
沒有ftyp后面就不知道用什么去解析這個媒體文件
2.2?Free Space Box -->free解析
沒啥作用
2.3?Media Data Box -->mdat解析
這個box里面全部都是數據
2.4?Movie Box ?-->moov解析 (很復雜)
6096fb0:?9002 1900 2380?000c ca81 6d6f 6f76?0000?....#.....moov.. 6096fc0:?006c 6d76 6864 0000 0000 7c25 b080 7c25?.lmvhd....|%..|% 6096fd0:?b080 0000 03e8 0014 6995 0001 0000 0100?........i....... 6096fe0:?0000 0000 0000 0000 0000 0001 0000 0000?................ 6096ff0:?0000 0000 0000 0000 0000 0001 0000 0000?................ 6097000:?0000 0000 0000 0000 0000 4000 0000 0000?..........@..... 6097010:?0000 0000 0000 0000 0000 0000 0000 0000?................ 6097020:?0000 0000 0000 0000 0003?0005 bf9d 7472?..............tr 6097030:?616b?0000 005c 746b 6864 0000 000f 7c25 ak...\tkhd....|% 6097040:?b080 7c25 b080 0000 0001 0000 0000 0014?..|%............ 6097050:?6595 0000 0000 0000 0000 0000 0000 0000?e............... 6097060: 0000 0001 0000 0000 0000 0000 0000 0000 ?................ 6097070: 0000 0001 0000 0000 0000 0000 0000 0000 ?................ 6097080: 0000 4000 0000 01d6 0000 0160 0000?0000??..@........`.... 6097090: 0024?6564 7473 0000 001c 656c 7374 0000 ?.$edts....elst.. 60970a0: 0000?0000?0001 0014 6595 0000 03e9 0001 ?........e....... 60970b0: 0000?0005 bf15 6d64 6961 0000 0020 6d64 ?......mdia... md000c ca81 6d6f 6f76 ? ?--> moov的長度是0x0cca81, type=moov
0000?006c 6d76 6864 ?-->?mvhd的長度是0x6c ? ?,type=mvhd
0000 0000 ? ? ? ? ? ? ? ? ? ?--> version=0x0
7c25 b080?7c25 b080 ?--> create_time=modify_time=0x7c25b080
0000 03e8????????????????? ? --> timescale=0x3e8=1000 ?
0014 6995 ?????????????? ? ? --> duration=0x146995(單位是time_units)
0001 0000 ? ? ? ? ? ? ? ? ? ?--> rate=0x00010000
0100 ? ? ? ? ? ? ? ? ? ? ? ? ? ? --> volume=0x0100
0005 bf9d 7472 616b? ?--> track的長度是0x5bf9d,type=trak
0000 005c 746b?6864 ?--> tkhd的長度是0x5c, type=tkhd
0000 ? ? ? ? ? ? ? ? ? ? ? ? ? ? -->version
000F ? ? ? ? ? ? ? ? ? ? ? ? ? ? --> flag
7c25 b080 7c25 b080 ?-->create_time=modify_time=0x7c25b080
0000 0001?????????????? ? ? ?--> trackID=1
0000 0000 ? ? ? ? ? ? ? ? ? ?--> reserve
0014 6595 ? ? ? ? ? ? ? ? ? ?--> duration=0x146595
0000 0000 ?????????????? ? ? -->?reserved
0000 0000 ?????????????? ? ??-->?reserved
0000 0000 ?????????????? ? ??-->?layer+group
0000?0000 ?????????????? ? ??-->?volum+resever
0001 0000 0000 0000 0000 0000 ? matrix
0000?0000 0001 0000 0000 0000?
0000 0000 0000 ?0000 4000 0000?
01d6 0000 0160 0000 ? -->??width=0x1d6?height=0x160(這兒都需要向右移16位)
0000?0024 6564 7473 ? -->edts的長度是0x24,type=edts
注意:?
a.媒體文件在播放過程中用的時間單位,是由timescale計算出來的
一個time units=1s/timescale=1ms,這兒1 time_unts=1ms
b.通過duration可計算媒體的播放時間 0x146995*1ms=1337749ms=1337.749s,對上了
附1.mvhd
ISO14496-12 的8.3.2 Syntax?
aligned(8)?class?MovieHeaderBox extends FullBox(‘mvhd’,?version,?0)?{?
if?(version==1)?{?unsigned?int(64)?creation_time;?unsigned?int(64)?modification_time;?unsigned?int(32)?timescale;?unsigned?int(64)?duration;?
}?else?{?//?version==0?unsigned?int(32)?creation_time;?unsigned?int(32)?modification_time;?unsigned?int(32)?timescale;?unsigned?int(32)?duration;?
}?
template?int(32)?rate?=?0x00010000;?//?typically 1.0?
template?int(16)?volume?=?0x0100;?//?typically,?full volume?
const?bit(16)?reserved?=?0;?
const?unsigned?int(32)[2]?reserved?=?0;?
template?int(32)[9]?matrix?=?{?0x00010000,0,0,0,0x00010000,0,0,0,0x40000000?};?
//?Unity matrix?
bit(32)[6]?pre_defined?=?0;?
unsigned?int(32)?next_track_ID;?
}
附2.trak
?
8.5.2 Syntax aligned(8)?class?TrackHeaderBox? extends FullBox(‘tkhd’,?version,?flags){?if?(version==1)?{?unsigned?int(64)?creation_time;?unsigned?int(64)?modification_time;?unsigned?int(32)?track_ID;?const?unsigned?int(32)?reserved?=?0;?unsigned?int(64)?duration;?}?else?{?//?version==0?unsigned?int(32)?creation_time;?unsigned?int(32)?modification_time;?unsigned?int(32)?track_ID;?const?unsigned?int(32)?reserved?=?0;?unsigned?int(32)?duration;?}?const?unsigned?int(32)[2]?reserved?=?0;?template?int(16)?layer?=?0;?template?int(16)?alternate_group?=?0;?template?int(16)?volume?=?{if?track_is_audio 0x0100?else?0};?const?unsigned?int(16)?reserved?=?0;?template?int(32)[9]?matrix=?{?0x00010000,0,0,0,0x00010000,0,0,0,0x40000000?};?//?unity matrix?unsigned?int(32)?width;?unsigned?int(32)?height;? }?
三.ffmpeg中對mp4的處理
3.1 對mp4文件的probe -->?在libavformat/mov.c中
有兩個宏需要關注一下:
這兩個宏都是把4個char組成一個int
3.2 mov_probe
static?int?mov_probe(AVProbeData?*p) {int64_t offset;uint32_t tag;int?score?=?0;int?moov_offset?=?-1;dbmsg();/*?check file header?*/offset?=?0;for?(;;)?{tag?=?AV_RL32(p->buf?+?offset?+?4); ? ?//將p->buf+4即‘f’ ‘t’ 'y' 'p'組成一個intswitch(tag)?{ ? ? ? ? ? ? ? ? ? ? ? ? ?//判斷這個int是不是ftypcase?MKTAG('f','t','y','p'):score?=?AVPROBE_SCORE_MAX; ? ??//如果是的話score=100,說明就是mov格式的文件break;}}return score; }精簡一下mov_probe,其實就是判斷第一個box是不是ftyp,若是則就是mov格式的了。
3.3.1 對ftype的讀取
static?int?mov_read_ftyp(MOVContext?*c,?AVIOContext?*pb,?MOVAtom atom)
{//讀4個字節的major_brand,并存到dict中ffio_read_size(pb,?type,?4);av_dict_set(&c->fc->metadata,?"major_brand",?type,?0);//讀4個字節的minor_ver,并存到dict中minor_ver?=?avio_rb32(pb);av_dict_set_int(&c->fc->metadata,?"minor_version",?minor_ver,?0);//讀剩余的字節,即comp_brands_str,并存到dict中comp_brand_size?=?atom.size?-?8;? ??//atom.size己經是去除8字節頭,余下的sizeffio_read_size(pb,?comp_brands_str,?comp_brand_size);comp_brands_str[comp_brand_size]?=?0;av_dict_set(&c->fc->metadata,?"compatible_brands",?comp_brands_str,?0);return 0;
}
3.3.2 對free的讀取
static?int?mov_read_free(MOVContext?*c,?AVIOContext?*pb,?MOVAtom atom) {//沒什么作用,只是讀取出來,把文件指針指向下一下box而己avio_read(pb,?content,?FFMIN(sizeof(content),?atom.size));return 0; }3.3.3對mdat的讀取
static?int?mov_read_mdat(MOVContext?*c,?AVIOContext?*pb,?MOVAtom atom) {//mdat更簡單,只把標志設置了一下c->found_mdat=1;return 0;?/*?now?go?for?moov?*/ }3.3.4對moov的讀取
?
三.附錄: ISO/IEC 14496 MPEG的協議標準
轉自:?http://blog.csdn.net/yu_yuan_1314/article/details/9406587
總結
以上是生活随笔為你收集整理的ffmpeg源码分析及mp4文件解析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [转]浅析Tomcat、JBOSS、We
- 下一篇: [转]【JAVA各版本特性】JAVA 1