• 媒体文件格式分析之FMP4


    媒体文件格式分析之FMP4 MP4 中最基本的单元就是Box,它内部是通过一个一个独立的Box拼接而成的。所以,这里,我们先从 Box 的讲解开始,每个 Box 是由 Header 和 Data 组成的,FullBox 是 Box 的扩展,Box 结构的基础上在 Header 中增加 8bits version 和 24bits flags

    1. 名词解释

    2. 最小单元Box

    2.1 常见的mp4文件结构(简化版)

    3. Mp4文件整体结构

    这里,我们按照 MP4 box 的划分来进行相关的阐述。先看一张 MP4 给出的结构图:

    一般来说,解析媒体文件,最关心的部分是视频文件的宽高、时长、码率、编码格式、帧列表、关键帧列表,以及所对应的时戳和在文件中的位置,这些信息,在mp4中,是以特定的算法分开存放在stbl box下属的几个box中的,需要解析stbl下面所有的box,来还原媒体信息。下表是对于以上几个重要的box存放信息的说明

     

    3.1 File Type Box (ftyp)

    通常放在MP4文件的开头,告诉解码器基本的解码版本和兼容格式。

    • 基本格式如下:
    1. aligned(8) class FileTypeBox
    2. extends Box(‘ftyp’) {
    3. unsigned int(32) major_brand;
    4. unsigned int(32) minor_version;
    5. unsigned int(32) compatible_brands[];
    6. }
    • 字段说明:

     

    • Nginx模块实现
    1. ngx_int_t
    2. ngx_rtmp_mp4_write_ftyp(ngx_buf_t *b)
    3. {
    4. u_char *pos;
    5. pos = ngx_rtmp_mp4_start_box(b, "ftyp");
    6. /* major brand */
    7. ngx_rtmp_mp4_box(b, "iso6");
    8. /* minor version */
    9. ngx_rtmp_mp4_field_32(b, 1);
    10. /* compatible brands */
    11. ngx_rtmp_mp4_box(b, "isom");
    12. ngx_rtmp_mp4_box(b, "iso6");
    13. ngx_rtmp_mp4_box(b, "dash");
    14. ngx_rtmp_mp4_update_box_size(b, pos);
    15. return NGX_OK;
    16. }

    3.2 Movie Box (moov)

    作为容器盒子,存放相关的trak及meta信息.

    • 基本格式如下:
    • aligned(8) class MovieExtendsBox extends Box(‘mvex’){ }
      
      文章最后扫码可领取音视频免费学习资料,资料包括(C/C++,Linux,FFmpeg webRTC rtmp hls rtsp ffplay srs 等等)

     

     

     3.2.1 Movie Header Box (mvhd)

    mvhd 是 moov 下的第一个 box,用来描述 media 的相关信息:

    • 基本格式如下:
      1. aligned(8) class MovieHeaderBox extends FullBox(‘mvhd’, version, 0) {
      2. if (version==1) {
      3. unsigned int(64) creation_time;
      4. unsigned int(64) modification_time;
      5. unsigned int(32) timescale;
      6. unsigned int(64) duration;
      7. } else { // version==0
      8. unsigned int(32) creation_time;
      9. unsigned int(32) modification_time;
      10. unsigned int(32) timescale;
      11. unsigned int(32) duration;
      12. }
      13. template int(32) rate = 0x00010000; // typically 1.0
      14. template int(16) volume = 0x0100; // typically, full volume
      15. const bit(16) reserved = 0;
      16. const unsigned int(32)[2] reserved = 0;
      17. template int(32)[9] matrix =
      18. { 0x00010000,0,0,0,0x00010000,0,0,0,0x40000000 };
      19. // Unity matrix
      20. bit(32)[6] pre_defined = 0;
      21. unsigned int(32) next_track_ID;
      22. }
    • 字段说明:
    • Nginx模块实现
    1. static ngx_int_t
    2. ngx_rtmp_mp4_write_mvhd(ngx_buf_t *b)
    3. {
    4. u_char *pos;
    5. pos = ngx_rtmp_mp4_start_box(b, "mvhd");
    6. /* version */
    7. ngx_rtmp_mp4_field_32(b, 0);
    8. /* creation time */
    9. ngx_rtmp_mp4_field_32(b, 0);
    10. /* modification time */
    11. ngx_rtmp_mp4_field_32(b, 0);
    12. /* timescale */
    13. ngx_rtmp_mp4_field_32(b, 1000);
    14. /* duration */
    15. ngx_rtmp_mp4_field_32(b, 0);
    16. /* reserved */
    17. ngx_rtmp_mp4_field_32(b, 0x00010000);
    18. ngx_rtmp_mp4_field_16(b, 0x0100);
    19. ngx_rtmp_mp4_field_16(b, 0);
    20. ngx_rtmp_mp4_field_32(b, 0);
    21. ngx_rtmp_mp4_field_32(b, 0);
    22. ngx_rtmp_mp4_write_matrix(b, 1, 0, 0, 1, 0, 0);
    23. /* reserved */
    24. ngx_rtmp_mp4_field_32(b, 0);
    25. ngx_rtmp_mp4_field_32(b, 0);
    26. ngx_rtmp_mp4_field_32(b, 0);
    27. ngx_rtmp_mp4_field_32(b, 0);
    28. ngx_rtmp_mp4_field_32(b, 0);
    29. ngx_rtmp_mp4_field_32(b, 0);
    30. /* next track id */
    31. ngx_rtmp_mp4_field_32(b, 1);
    32. ngx_rtmp_mp4_update_box_size(b, pos);
    33. return NGX_OK;
    34. }

    3.2.2 Movie Extends Box (mvex)(fMP4专有)

    mvex 是 fMP4 的标准盒子。它的作用是告诉解码器这是一个fMP4的文件,具体的 samples 信息内容不再放到 trak 里面,而是在每一个 moof 中。基本格式为:

    1. aligned(8) class MovieExtendsHeaderBox extends FullBox(‘mehd’, version, 0) { if (version==1) {
    2. unsigned int(64) fragment_duration;
    3. } else { // version==0
    4. unsigned int(32) fragment_duration;
    5. }
    6. }

     

    3.2.2.1 Track Extends Box (trex)(fMP4专有)

    trex 是 mvex 的子一级 box 用来给 fMP4 的 sample 设置默认值。基本内容为

    1. aligned(8) class TrackExtendsBox extends FullBox(‘trex’, 0, 0){
    2. unsigned int(32) track_ID;
    3. unsigned int(32) default_sample_description_index;
    4. unsigned int(32) default_sample_duration;
    5. unsigned int(32) default_sample_size;
    6. unsigned int(32) default_sample_flags
    7. }

    3.2.3 Track Box (trak)

    trak box 就是主要存放相关 media stream 的内容。

    3.2.3.1 Track Header Box (tkhd)

    tkhd 是 trak box 的子一级 box 的内容。主要是用来描述该特定 trak 的相关内容信息。其主要内容为:

    • 基本格式如下:
    1. aligned(8) class TrackHeaderBox
    2. extends FullBox(‘tkhd’, version, flags){
    3. if (version==1) {
    4. unsigned int(64) creation_time;
    5. unsigned int(64) modification_time;
    6. unsigned int(32) track_ID;
    7. const unsigned int(32) reserved = 0;
    8. unsigned int(64) duration;
    9. } else { // version==0
    10. unsigned int(32) creation_time;
    11. unsigned int(32) modification_time;
    12. unsigned int(32) track_ID;
    13. const unsigned int(32) reserved = 0;
    14. unsigned int(32) duration;
    15. }
    16. const unsigned int(32)[2] reserved = 0;
    17. template int(16) layer = 0;
    18. template int(16) alternate_group = 0;
    19. template int(16) volume = {if track_is_audio 0x0100 else 0}; const unsigned int(16) reserved = 0;
    20. template int(32)[9] matrix=
    21. { 0x00010000,0,0,0,0x00010000,0,0,0,0x40000000 };
    22. // unity matrix
    23. unsigned int(32) width;
    24. unsigned int(32) height;
    25. }

     

    • 字段说明:

    3.2.3.2 Media Box (media)

    mdia 主要用来包裹相关的 media 信息。

    (1) Media Header Box (mdhd)

    • 基本格式如下:
    1. aligned(8) class MediaHeaderBox extends FullBox(‘mdhd’, version, 0) { if (version==1) {
    2. unsigned int(64) creation_time;
    3. unsigned int(64) modification_time;
    4. unsigned int(32) timescale;
    5. unsigned int(64) duration;
    6. } else { // version==0
    7. unsigned int(32) creation_time;
    8. unsigned int(32) modification_time;
    9. unsigned int(32) timescale;
    10. unsigned int(32) duration;
    11. }
    12. bit(1) pad = 0;
    13. unsigned int(5)[3] language; // ISO-639-2/T language code unsigned int(16) pre_defined = 0;
    14. }

     

    • 字段说明:

    (2) Handler Reference Box(hdlr)

    • 基本格式如下:
    1. aligned(8) class HandlerBox extends FullBox(‘hdlr’, version = 0, 0) {
    2. unsigned int(32) pre_defined = 0;
    3. unsigned int(32) handler_type;
    4. const unsigned int(32)[3] reserved = 0;
    5. string name;
    6. }

     

    • 字段说明:

     

    • handler_type 类型如下:
      1. vide : Video track
      2. soun : Audio track
      3. hint : Hint track
      4. meta : Timed Metadata track
      5. auxv : Auxiliary Video track

      3.2.3.3 Media Information Box (minf)

      minf 是子属内容中,重要的容器 box,用来存放当前 track 的基本描述信息。

      (1) Video Media Header Box(vmhd)

    • 基本格式如下:
      1. aligned(8) class VideoMediaHeaderBox
      2. extends FullBox(‘vmhd’, version = 0, 1) {
      3. template unsigned int(16) graphicsmode = 0; // copy, see below
      4. template unsigned int(16)[3] opcolor = {0, 0, 0};
      5. }

      (2) Sound Media Header Box(smhd)

    • 基本格式如下:
      1. aligned(8) class SoundMediaHeaderBox
      2. extends FullBox(‘smhd’, version = 0, 0) {
      3. template int(16) balance = 0;
      4. const unsigned int(16) reserved = 0;
      5. }

      (3) Data Information Box(dinf)

      dinf 是用来说明在 trak 中,media 描述信息的位置。其实本身就是一个容器,没啥内容:

    • 基本格式如下:
      1. aligned(8) class SoundMediaHeaderBox
      2. extends FullBox(‘smhd’, version = 0, 0) {
      3. template int(16) balance = 0;
      4. const unsigned int(16) reserved = 0;
      5. }

      (4) Data Reference Box(dref)

      dref 是用来设置当前Box描述信息的 data_entry。

    • 基本格式如下:
    1. aligned(8) class DataReferenceBox
    2. extends FullBox(‘dref’, version = 0, 0) {
    3. unsigned int(32) entry_count;
    4. for (i=1; i <= entry_count; i++) {
    5. DataEntryBox(entry_version, entry_flags) data_entry; }
    6. }

     

    • 字段说明:

    3.3 Moof Box

    3.4 Sidxs Box

     

  • 相关阅读:
    C++基础与深度解析 | 输入与输出 | 文件与内存操作 | 流的状态、定位与同步
    将windows的显示器作为linux的扩展屏
    自然语言处理(NLP)—— Rasa中config.yml
    使用通义灵码插件提高开发效率
    Unity之ShaderGraph如何实现马赛克效果
    DolphinScheduler
    自定义qtquick 插件模块,支持qmldesigner
    【MYSQL】复合查询
    数据通信练习题
    Kotlin 操作集合的高阶函数
  • 原文地址:https://blog.csdn.net/yinshipin007/article/details/126651028