ZigZag Sin
登 陆
上一篇:前期准备 下一篇:ftyp Box

Box 概述

Time
2022-2-21 11:39 阅读 336

Box 分析

主题简述:

  • 首先我们要对一个 MP4 文件进行分析,先准备好一个 MP4 文件,然后跟着文章步骤和思路一步一步来把 MP4 文件的封装进行解析。
  • 借助一个实例去分析核心Box的语法结构和字段含义,总结下H264码流的打包。
  • 本系列参考对应的官方文档 ISO/IEC 14496-12 地址: https://sce.umkc.edu/faculty-sites/lizhu/teaching/2020.spring.video/ref/mp4.pdf
  • 由于 MP4 里面封装的 Box 众多,本文会进行分篇,对每一个核心和常见的 Box 进行分析,大家在复习或者学习也有很好的针对观看,有些特殊和不太用的Box就一笔带过了,如果你万一项目用到直接查ISO标准文档即可。
  • Box里面字段不是所有都是重点,我们只需要关注核心和有用的,对于一些不太用的就可以忽略不计了,实际解封装我们也是提取我们想要的信息或者打包时对于不关注的字段直接赋默认值即可。
  • 接下来我会前面提到的工具对 MP4 文件进行分析,并编写对应的代码进行解析操作。

基础 Box 定义

  • 根据上文介绍的 Box 我们知道 Box 里面的结构是 Header + Data

Box

Box Header

  • size:指定了这个 Box 的大小,从 Header 到 Data 部分,一般 Header 的大小为8字节,但是如果 Box 很大,超过了 uint32 的最大数值,那么 size 则为 1,并拓展出8字节 uint64 来表示该Box的大小,这样 Header 大小就变成16字节了。

  • type:指定了这个 Box 是什么 Box,例如常见的 ftyp Box,mdat Box,moov Box 等等。这里是存对应 Box 属性的 ASCII 码。

工具分析
  • 首先我们知道 Box 有很多种类型,那么我们便可以定义一个枚举来表示我们对应的 Box type。
  • 详情参考:MP4 文档 P11 页,这里我就不放截图了,大家可以去看看 Box 的种类。
  • 首先我们先用之前准备好的工具 MP4 info 打开一个 MP4文件
    • image-20211216205201073
    • 我们可以先看到 Root 下面有很多子 Box,在 moov Box 进行展开里面又有很多子 Box,根据我们上面画的这个 Box 的结构图,很清晰的看到了 Box 的具体结构。那么我们就可以先定义一个基类的 Box。
代码定义:
  1. 首先我们先定义一个枚举用来表示 Box 的类型
// BaseBox.h

enum BOX_TYPE{
    FTYP,
    MOOV,
    UUID,
    MDAT,
    ERROR // 实际上没有这个 Box,只是为了当在错误时,要返回的值
};
  1. 接下来我们定义一个 Box Header
// BaseBox.h

typedef unsigned char Timebyte;

struct BoxHeader{
    Timebyte _h_size[4] = {0};
    Timebyte _h_type[5] = {0}; // 这里定义5个字节是为了后面 to_string 的打印操作读取到最后一个0结束
							  // 这里可以定义一个是否有拓展长度字节的,还没遇到对应的情况,这里我就还没写
    
    // 获取当前 Box 的大小
    unsigned int GetSize() {
        return _h_size[0] << 24 | _h_size[1] << 16 | _h_size[2] << 8 | _h_size[3];
    }
    
	// 获取当前 Box Data 的大小
    unsigned int GetDataSize() {
        return GetSize() - 8;
    }
    
	// 对当前这个 Header 进行打印操作
    void to_string() {
        printf("box_size: %ud\n", GetSize());
        printf("box_type: %s\n", _h_type);
    }
    
	// 这个返回当前 Box 的类型
    BOX_TYPE GetType() {
   		// ... 这里暂时先不写,后面具体定义的时候再加再加
    }
};
  1. 定义最基本的 Box
// BaseBox.h

class BaseBox{
protected:
    Timebyte *data = nullptr;

public:
    BoxHeader h;
    BaseBox(BoxHeader h);
    BaseBox(BoxHeader h, Timebyte * d);
    ~BaseBox();
    
    Timebyte * GetData() const {return data;};

};
// BaseBox.cpp

BaseBox::BaseBox(BoxHeader h)
        : h(h) {

}

BaseBox::BaseBox(BoxHeader h, Timebyte *d)
        : h(h), data(d){

}

BaseBox::~BaseBox() {
    if (data) {
        delete[] data;
        data = nullptr;
    }
}

BaseBox::BaseBox(BaseBox &baseBox) {
    data = baseBox.data;
    h = baseBox.h;
}

总结

以上便是我定义的基本的 Box Type,Box Header,BaseBox 后面会解析对应的 Box 还会对这些进行重构和改写。

上一篇:前期准备 下一篇:ftyp Box
给我买个键盘吧。。。求打赏。。。
欢迎加群,一起交流~~~