MP4文件中音视频时间戳的计算

MP4文件的组成

MP4文件的格式遵循ISO/IEC 14496-12标准,即ISO base media file format。所有数据都封装在被称为Box的数据结构中,一个MP4文件,是由多个Box组成的。
请添加图片描述
如上图所示,该MP4文件由ftype、free、mdat和moov四个Box组成。
其中moov Box属于container box,它又可以包含有其他的Box。它里面保存的数据如下图所示请添加图片描述

在这里moov box及其子box包含了该MP4文件的元数据,用于指定音视频数据的存储位置,数据类型,时间戳之类的信息。

mdat box为长度最大的box,该文件中的音视频数据都包含在该box中,可以通过解析moov box来获取每帧音视频数据具体保存的位置。

moov box包含有每帧音视频数据在文件中的偏移量信息,所以一般都是位于文件尾,用于方便保存文件时记录偏移量信息。但是也可以通过其他方式将其移动到文件前面的位置(MP4box和ffmpeg都可以做到),这样做的好处是播放器在播放网络上的MP4文件时,可以直接读取到文件的索引信息,使得开播更快。

Box结构的定义

size字段表示该Box的长度,如果size值为1,则表示box的长度超过了32位的表示范围,需要由type之后的64位用于表示实际的长度。

type字段表示该Box的类型,一般使用4个可打印的字符组合表示,也称为FOURCC,如ftyp、moov、meta、mdat等。

大部分box除了包含有size和type字段外,还包含有version和flag字段,用于处理在标准升级时产生的box内容定义不一致的问题。

除去以上数据后box剩余的数据为该box的实际数据,根据type不同,表示的含义也各不相同。

moov box

请添加图片描述
mvhd box中的duration和timescale字段用来指定该文件的播放时长,duration/timescale的值即为单位为秒的时长。如果文件中多个流的时长不一致,该位置为最大时长。如下图所示,该文件的播放时长为189167/1000=189.167秒。
在这里插入图片描述
trak box
每个trak box表示一路单独的流,可能是音频也可能是视频。
mdia box下的hdlr box用来指定该流是音频还是视频
stsd box的子box用于保存该流的编码类型
在这里插入图片描述

上图中avcC box指定了该流的编码类型为H264,且存储了解码所需的SPS、PPS信息。

stsc stsz stco三个box用于保存没帧视频或音频数据在文件中的保存位置。

stts stss ctts三个box用于保存媒体数据和时间戳的对应关系。

Sample(音视频帧)保存位置的计算

请添加图片描述

每个chunk可以有一个或多个sample,如果相邻的chunk含有相同的sample数量,则first_count字段用于指明第一个chunk的索引,sample_per_chunk指明该组chunk中每个chunk中sample的数量。
在这里插入图片描述
如上图
index为1的chunk含有3个sample;
index为2的chunk含有1个sample;
然后下一个first_chunk值为4,则表明index为3的chunk含有和2相同数量的sample,也是1个;
继续,index为4的chunk含有2个sample;
index为5和6的chunk含有1个sample;7有2个sample;8有1个sample;9含有2个sample;

请添加图片描述

entry_count指明了总的chunk的数量

chunk_offset指明了该chunk在文件中的偏移量

以上三个box结合起来,即可计算每个sample在文件中保存的位置和大小


void mp4Parser::GetSamplePosition(Stream* s)
{
    int sample_count = s->stsz_count;
    int chunk_count = s->stco_count;

    if(sample_count > 0)
    {
        s->sample_position = new uint64_t[sample_count];
    }

    int remain_chunk_count = chunk_count;
    int sample_index = 0;
    for(int i=0;i<s->stsc_count;i++)
    {
        int c_count = 0;
        if (i != s->stsc_count - 1)
        {
            c_count = s->stsc_data[i + 1].first_chunk - s->stsc_data[i].first_chunk;
            remain_chunk_count -= c_count;
        }
        else
        {
            c_count = remain_chunk_count;
        }
        for (int j = 0; j < c_count; j++)
        {
            int chunk_index = s->stsc_data[i].first_chunk + j;
            uint64_t offset = s->stco_data[chunk_index - 1];
            for (int k = 0; k < s->stsc_data[i].samples_per_chunk; k++)
            {
                s->sample_position[sample_index] = offset;
                offset += s->stsz_data[sample_index];
                sample_index++;
                if (sample_index > sample_count)
                    return;
            }
        }
    }
}

PTS和DTS的计算

I P B 帧的概念
在视频压缩中,为了提高压缩率,会将每帧画面压缩为不同类型的视频帧数据。
I帧表示关键帧,包含有一帧画面的完整信息,解码时只需要本帧数据就可以解码出完整的一帧画面。
P帧表示前向参考帧,它保存了本帧与上一帧的差异信息,它不能单独解码,需要根据上一帧的画面加上本帧保存的差值来获取本帧的完整画面。
B帧为双向参考帧,它解码时需要依赖它之前和之后的帧来获取最终的画面
因为B帧需要依赖它后面的帧来进行解码,所以它的解码顺序就必然和显示顺序不能保持一致,这是就需要解码时间戳(DTS)和显示时间戳(PTS)来共同决定一帧视频数据何时解码,然后何时显示了。
在这里插入图片描述
请添加图片描述
在这里插入图片描述
示例

stsz内容:
sample_count = 5
index = 1, size = 919
index = 2, size = 39
index = 3, size = 36
index = 4, size = 36
index = 5, size = 36

stsc内容:
entry_count = 2
first_chunk = 1, samples_per_chunk = 3, sample_description_index = 1
first_chunk = 2, samples_per_chunk = 1, sample_description_index = 1

stco内容
entry_count = 3
index = 1, chunk_offset = 48
index = 2, chunk_offset = 1051
index = 3, chunk_offset = 1096

index为1、2、3的三帧组成为chunk1
chunk1的起始地址为48,则sample1的起始地址为48,sample2的起始地址为48+919=967(919为sample1的大小),sample3的起始地址为967+39=1006(39为sample2的大小)。
chunk2和chunk3只包含有1个sample,分别为sample4和sample5
chunk2的起始地址为1051,则sample4的起始地址为1051
chunk3的起始地址为1096,则sample5的起始地址为1096

stts内容:
stts_count = 1
count:5, delte:512

ctts内容:
ctts_count = 5
count:1, offset:1024
count:1, offset:2560
count:1, offset:1024
count:1, offset:0
count:1, offset:512

在这里插入图片描述
在这里插入图片描述
参考:MP4文件中音视频时间戳的计算

MP4 解析工具

MP4 Inspector;

https://sourceforge.net/projects/mp4-inspector/files/

https://jaist.dl.sourceforge.net/project/mp4-inspector/MP4%20Inspector%20-%200.1.2.0.rar

在线解析

https://www.onlinemp4parser.com/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值