欢迎来真孝善网,为您提供真孝善正能量书籍故事!

MP4文件格式深度解析:核心技术及细节解读

时间:11-18 现代故事 提交错误

历史[6]:

2001年,Apple推出QuickTime格式,后缀名为.qt和.mov。 2001 年,MPEG-4 第1 部分在MPEG-4 标准中添加了基于QuickTime 盒布局的容器格式。 2004 年,标准文档将编码和容器格式规范分开。 ISO-14496 第12 部分定义了容器格式的通用盒结构,即ISO媒体文件格式(ISO base media file format, ISO BMFF)。 ISO-14496 Part 14,基于Part12 进行了细化,定义了用于存储MPEG-4 内容的容器格式,即.mp4 格式。 ISO-14496 Part 15在Part 12的基础上,定义了如何封装AVC、HEVC和VVC的NALU。以下是每个标准文档的链接:

QuickTime:QuickTime/QTFFISO-14496 第12 部分:ISO/IEC 14496-12:2015ISO-14496 第14 部分:ISO/IEC 14496-14:2018。官网上这部分是付费的。 MP4文件由许多盒子组成,每个盒子包含不同的信息,并且这些盒子以树形结构组织。以下是主要框的简要说明:

图2 主框说明: 根节点下主要有ftyp、moov、mdat 三个节点。

ftyp:文件类型。描述要遵循的规范版本。moov box:媒体的元数据信息。mdat:特定媒体数据。说明:mp4中默认的写入字节顺序是Big-Endian。

2. mp4文件基本信息

mp4 文件分析工具:

mp4box.js:一个解析mp4的在线工具。 Bento4:包含mp4dump、mp4edit 和mp4encrypt 等工具。 MP4Box:与bento4类似,包含非常全面的工具。 l-smash: mp4盒子查看工具下图是使用mp4box.js打开mp4文件的界面:

image.pngmp4文件的基本信息

音频信息:

smplrate:采样率(采样率)。通道:通道数。比特率:比特率。 audiosamplenum:音频样本的数量。视频信息:

宽度、高度:视频的宽度/高度。 bitrate:比特率(码率),单位为秒。等于视频的总大小/持续时间。帧数:视频帧数。 fps:帧速率(每秒帧数)。 Total_time:时间长度,单位为ms。等于持续时间/时间尺度。 timescale:时间的粒度,1000表示1000个单位是1s。持续时间:时间粒度的数量。 videosamplenum:视频样本数。

3. 封装格式重要概念

3.1 box

mp4 文件由多个框组成。下图是盒子结构示意图。

图4 mp4_box.pngbox 由header 和body 组成。标题指定了盒子的大小和类型。 size 是整个盒子的大小,包括盒子标题。框类型,通常是四个ASCII 字符,如“ftyp”、“moov”等。这些框类型是预定义的,代表固定的含义。如果是“uuid”,则表示该box是用户自定义的扩展类型。如果框类型未定义,则应忽略它。如果header中的size为1,说明box长度需要更多的bit来描述,后面会有64位的largesize来描述box长度。如果size为0,则表示该box是文件的最后一个box,也是文件的结尾(也只存在于“mdat”类型的box中)。一个盒子可以容纳一个盒子,称为容器盒子。盒子有两种类型:盒子和全盒子。 FullBox 是Box 的扩展。 Header 中添加Version 和Flags 字段,定义如下:aligned(8) class Box (unsigned int(32) boxtype,

可选的unsigned int(8)[16] 扩展类型) {

无符号int(32) 大小;

无符号int(32) 类型=boxtype;

如果(大小==1){

无符号int(64) 大尺寸;

} 否则如果(大小==0){

//框延伸到文件末尾

}

if (boxtype=="uuid") {

无符号int(8)[16] 用户类型=扩展类型;

}

}FullBox 有版本和标志字段,

对齐(8)类FullBox(无符号整数(32)框类型,无符号整数(8)v,位(24)f)

扩展Box(boxtype) {

无符号int(8) 版本=v;

位(24)标志=f;

}

3.2 track

样本集合。对于媒体数据,轨道代表视频或音频序列。

3.3 sample

视频样本是一帧或一组连续的视频帧,音频样本是连续的音频。

3.4. sample table

表指示示例时序和物理布局。

3.5. chunk

由轨道的多个样本组成的单元。

在mp4 文件中,媒体内容位于moov 框中。一个moov 包含多个曲目。每个轨道都是一个随时间变化的媒体序列。轨道中的每个时间单元都是一个样本,样本按时间顺序排列。注意,一帧音频可以分解为多个音频样本,因此音频一般以样本为单位,而不是帧。

4. 重要box介绍

4.1 Sample Table Box(stbl)

“stbl”是mp4文件中最复杂的盒子,也是mp4文件格式的支柱。

stbl:样品台是一个容器盒。

语法:

类SampleTableBox 扩展Box("stbl") {

它的子框包括:

stsd:样本描述框,样本的描述信息。 stts:time to sample box,样本解码时间压缩表。 ctts:到样本箱的合成时间,样本的CTS和DTS时间差的压缩表。 stss:同步样本框,对于视频,关键帧的序列号。 stsz/stz2:样本大小框,每个样本的字节大小。 stsc:样本到块盒,样本-块映射表。 stco/co64:块偏移框,文件中的块偏移量。 Sample是媒体数据存储的单位。它存储在媒体块中。 chunk 和sample 的长度可以不同,如下图所示。

图5sample.jpg

4.2 Sample Description Box(stsd)

存储了编码类型和初始化解码器所需的信息。

有与特定轨道类型相关的信息。相同的轨道类型也可能具有不同的信息,例如使用不同的编码标准。

语法:

类SampleDescriptionBox (无符号int(32) handler_type)

扩展FullBox("stsd", 0, 0){

整数我;

无符号int(32) 条目计数;

for (i=1; i=条目计数; i++){

开关(处理程序类型){

case ‘soun’: //用于音轨

AudioSampleEntry();

休息;

case ‘vide’: //用于视频轨道

VisualSampleEntry();

休息;

case ‘hint’: //提示轨迹

提示样本条目();

休息;

case ‘meta’: //元数据轨道

MetadataSampleEntry();

休息;

}

}

}

}主要字段说明:

条目计数:条目数。handler_type:类型信息如“vide”、“soud”等,不同类型会提供不同的信息。对于音轨,使用“AudioSampleEntry”类型信息。

抽象类SampleEntry (无符号int(32) 格式)

扩展框(格式){

const unsigned int(8)[6] 保留=0;

无符号int(16) data_reference_index;

}

类AudioSampleEntry(编码名称) 扩展SampleEntry (编码名称){

const unsigned int(32)[2] 保留=0;

模板unsigned int(16) 通道数=2;

模板unsigned int(16) 样本大小=16;

无符号int(16) 预定义=0;

const 无符号int(16) 保留=0;

template unsigned int(32) 采样率={ 媒体默认采样率}16;

}format:视频或音频的编码格式。例如aac音频的格式值为mp4a。 AVC-1/H.264视频的格式值为avc1。 data_reference_index:使用此索引检索与当前示例描述关联的数据。数据引用存储在数据引用框中。通道数:通道数。样本大小:采样位数。默认值为16 位。采样率:采样率。 [16.16]格式化数据。对于视频轨道,请使用“VisualSampleEntry”类型信息。

类VisualSampleEntry(编码名称) 扩展SampleEntry (编码名称){

无符号int(16) 预定义=0;

const 无符号int(16) 保留=0;

无符号int(32)[3] 预定义=0;

无符号int(16) 宽度;

无符号int(16) 高度;

模板无符号int(32) 水平分辨率=0x00480000; //72 dpi

模板无符号int(32) 垂直分辨率=0x00480000; //72 dpi

const 无符号int(32) 保留=0;

模板无符号整数(16)frame_count=1;

string[32] 压缩机名称;

模板无符号int(16) 深度=0x0018;

int(16) 预定义=-1;

//派生规范中的其他框

CleanApertureBox拍手; //选修的

PixelAspectRatioBox pasp; //选修的

}width, height:像素宽度和高度。水平分辨率、垂直分辨率:每英寸像素值(dpi),数据格式为[16.16]。 frame_count:每个样本中的视频帧数,默认为1。一个样本中可以有多帧数据。

4.3 Decoding Time to Sample Box(stts)

包含该表的压缩版本,通过该表可以将解码时间映射到样本序列号。表中的每一项是连续相同的解码时间增量(Decode Delta)的数量和解码时间增量。通过累积时间增量,可以创建完整的采样时间表。

下面是解码时序和解码增量之间关系的说明:

图6 STTS_sample.PNGDT(解码时间):编码时间。 CT(composition time):创作时间。解码增量:编码时间增量。合成偏移:显示时间与解码时间之差,等于CT - DT。

计算方法:DT(n+1)=DT(n) + STTS(n) 其中STTS(n)

注意:这里的STTS(n) 是未压缩的Decode Delta 表。

DT(i)=SUM(对于delta(j) 的j=0 到i-1) 语法:

类TimeToSampleBox

扩展FullBox("stts", 版本=0, 0) {

无符号int(32) 条目计数;

整数我;

for (i=0; i 条目计数; i++) {

无符号整数(32)样本计数;

无符号int(32) 样本增量;

}

}重要字段说明:

Entry_count:表中的条目数。 sample_count: 相同时间长度的样本数。 Sample_delta:以时间刻度为单位的时间长度。

4.4 composition time to sample box(ctts)

该框提供了从解码时间到合成时间的偏移表,用于计算pts。

当解码时间和合成时间不同时,该表是必要的。如果box的版本等于0,则解码时间一定小于或等于合成时间,因此差值用无符号数表示。有如下公式:

注:CTTS(n)是未压缩表的第n个样本对应的偏移量。语法:

类CompositionOffsetBox

扩展FullBox("ctts", 版本=0, 0) {

无符号int(32) 条目计数;

整数我;

如果(版本==0){

for (i=0; i 条目计数; i++) {

无符号整数(32)样本计数;

无符号int(32) 样本偏移量;

}

}

否则如果(版本==1){

for (i=0; i 条目计数; i++) {

无符号整数(32)样本计数;

有符号int(32) 样本偏移量;

}

}

}主要字段说明:

Sample_count:连续相同偏移量的数量。 Sample_offset:CT 和DT 之间的偏移量。

4.5 sync sample box(stss)

它包含媒体中关键帧的示例表。如果该表不存在,则每个样本都是一个关键帧。

语法:

类SyncSampleBox

扩展FullBox("stss", 版本=0, 0) {

无符号int(32) 条目计数;

整数我;

for (i=0; i 条目计数; i++) {

无符号int(32) 样本数;

}

}主要字段说明:

Sample_number:媒体流中同步样本的序列号。

4.6 Sample Size Box(stsz/stz2)

包含样本数量和每个样本的字节大小。这个盒子比较大。

语法:

类SampleSizeBox 扩展FullBox("stsz", 版本=0, 0) {

无符号int(32) 样本大小;

无符号整数(32)样本计数;

如果(样本大小==0){

for (i=1; i=样本计数; i++) {

无符号int(32) 条目大小;

}

}

}主要字段说明:

Sample_size:指定默认样本字节大小。如果所有样本的大小不同,则该字段为0。sample_count:track中sample的数量。entry_size:每个sample的字节大小。Compact Sample SizeBox(stz2):压缩样本大小存储方法。

类CompactSampleSizeBox 扩展FullBox("stz2", 版本=0, 0) {

无符号int(24) 保留=0;

unsigned int(8) 字段大小;

无符号整数(32)样本计数;

for (i=1; i=样本计数; i++) {

无符号整数(字段大小)条目大小;

}

}field_size:指定表中条目的位大小,值为4、8或16。 (1)如果使用值4,则每个字节存储两个样本,大小为:

条目[i] 4 + 条目[i + 1]。 (2) 如果size不是用整数个字节填充,则最后一个字节未使用的部分用0填充。 Sample_count 是一个整数,给出下表中的条目数。 Entry_size 是一个整数,指定样本的大小,根据其编号进行索引。

4.7 Sample To Chunk Box(stsc)

介质中的样本被分成块。块可以具有不同的大小,并且块内的样本可以具有不同的大小。

通过stsc中的sample-chunk映射表可以找到包含指定样本的chunk,从而找到该样本。具有相同结构的块可以聚集在一起形成一个条目,该条目就是stsc映射表的条目。

语法:

类SampleToChunkBox

扩展FullBox("stsc", 版本=0, 0) {

无符号int(32) 条目计数;

for (i=1; i=条目计数; i++) {

无符号整数(32)first_chunk;

无符号整数(32)samples_per_chunk;

无符号int(32) 样本描述索引;

}

}主要字段说明:

first_chunk:一组chunk中第一个chunk的序号。块编号从1开始。samples_per_chunk:每个块中有多少个样本。 Sample_desc_idx:stsd 中样本desc 信息的索引。把一组相同结构的chunk放在一起进行管理,是为了压缩文件大小。用mp4box.js查看stsc box的信息如下:

image.png 第一组chunk的first_chunk序号为1,每个chunk中的样本数为1。因为第二组chunk的first_chunk序号为2,所以可以看出只有一个第一组块中的块。第二组chunk的first_chunk序号为2,每个chunk中的样本数为2。因为第三组chunk的first_chunk序号为24,所以可以看出有22个chunk,44个样本在第二组块中。

4.8 Chunk Offset Box(stco/co64)

Chunk Offset表存储了每个chunk在文件中的位置,这样就可以直接在文件中找到媒体数据,而无需解析box。

需要注意的是,一旦之前的框发生任何更改,该表将重新建立。语法:

类ChunkOffsetBox

扩展FullBox("stco", 版本=0, 0) {

无符号int(32) 条目计数;

对于(i=1;

i<= entry_count; i++) { unsigned int(32) chunk_offset;

} }主要字段说明: chunk_offset:chunk在文件中的位置。stco 有两种形式,如果你的视频过大的话,就有可能造成 chunkoffset 超过 32bit 的限制。所以,这里针对大 Video 额外创建了一个 co64 的 Box。它的功效等价于 stco,也是用来表示 sample 在 mdat box 中的位置。只是,里面 chunk_offset 是 64bit 的。 aligned(8) class ChunkLargeOffsetBox extends FullBox(‘co64’, version = 0, 0) { unsigned int(32) entry_count; for (i=1; i<= entry_count; i++) { unsigned int(64) chunk_offset; } }

5. 其他box介绍

以下是ISO/IEC 14496-12:2015文档给出的box的描述图: box.png

5.1 File Type Box(ftyp)

File Type Box一般在文件的开头,用来指示该 mp4文件使用的标准规范。为了早期规范版本兼容,允许不包含ftyp box。 语法: class FileTypeBox extends Box(‘ftyp’) { unsigned int(32) major_brand;// is a brand identifier unsigned int(32) minor_version;// is an informative integer for the minor version of the major brand unsigned int(32) compatible_brands[]; //is a list, to the end of the box, of brands }没有ftyp box的文件应该处理成ftyp的major_brand为"mp41",minor_version为0,compatible_brands只包含一个"mp41"。

5.2 Movie Box(moov)

Movie Box包含了文件媒体的metadata信息,“moov”是一个container box,具体内容信息在其子box中。一般情况下,“moov”会紧随着“ftyp”。 “moov”中包含1个“mvhd”和若干个“trak”。其中“mvhd”是header box,一般作为“moov”的第一个子box出现。“trak”包含了一个track的相关信息,是一个container box。 语法: class MovieBox extends Box(‘moov’){ }

5.3 Movie Header Box(mvhd)

语法: 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; }主要字段含义: version : box版本,0或1,一般为0。creation time : 创建时间(相对于UTC时间1904-01-01零点的秒数)。modification time : 修改时间 。timescale : 文件媒体在1秒时间内的刻度值,可理解为1秒长度的时间单元数。duration : 该track的时间长度,用duration和time scale值可以计算track时长,比如audio track的time scale = 8000, duration = 560128,时长为70.016,video track的time scale = 600, duration = 42000,时长为70。rate : 推荐播放速率,高16位和低16位分别为小数点整数部分和小数部分,即[16.16] 格式,该值为1.0(0x00010000)表示正常前向播放。volume : 推荐播放音量,[8.8] 格式,1.0(0x0100)表示最大音量。

5.4 Track Box(trak)

Track Box是一个container box,其子box包含了该track的媒体数据引用和描述(hint track除外)。一个mp4文件可以包含多个track,且至少有一个track,track之间是独立,有自己的时间和空间信息。“trak”必须包含一个“tkhd”和一个“mdia”,此外还有很多可选的box。其中“tkhd”为track header box,“mdia”为media box,该box是一个包含一些track媒体数据信息box的container box。 语法: class TrackBox extends Box(‘trak’) { }

5.5 Track Header Box(tkhd)

语法: 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; }主要字段含义: version : box版本,0或1,一般为0。flags : 24-bit整数,按位或操作结果值,预定义的值(0x000001 ,track_enabled,表示track是有效的)、(0x000002,track_in_movie,表示该track在播放中被使用)、(0x000004,track_in_preview,表示track在预览时被使用。track id : track id号,不能重复且不能为0。duration : track的时间长度,计量单位timescale在mvhd中。volume : [8.8] 格式,如果为音频track,1.0(0x0100)表示最大音量;否则为0。width : 宽,[16.16] 格式值。height : 高,[16.16] 格式值,不必与sample的像素尺寸一致,用于播放时的展示宽高。

5.6 Media Box(mdia)

Media Box也是个container box。 语法: class MediaBox extends Box(‘mdia’) { }其子box的结构和种类还是比较复杂的。 “mdia”定义了track媒体类型以及sample数据,描述sample信息。 一个“mdia”必须包含如下容器: 一个Media Header Atom(mdhd)一个Handler Reference(hdlr)一个media information(minf)和User Data下面依次看一下这几个box的结构。

5.7 Media Header Box(mdhd)

mdhd 和 tkhd ,内容大致都是一样的。不过tkhd 通常是对指定的 track 设定相关属性和内容。而 mdhd 是针对于独立的 media 来设置的。不过两者一般都是一样的。 语法: class MediaHeaderBox extends FullBox(‘mdhd’, 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; } bit(1) pad = 0; unsigned int(5)[3] language; // ISO-639-2/T language code unsigned int(16) pre_defined = 0; }主要字段含义: version: box版本,0或1,一般为0。timescale: 同mvhd中的timescale。duration: track的时间长度。language: 媒体语言码。最高位为0,后面15位为3个字符(见ISO 639-2/T标准中定义)。

5.8 Handler Reference Box(hdlr)

“hdlr”解释了媒体的播放过程信息,该box也可以被包含在meta box(meta)中。 语法: class HandlerBox extends FullBox(‘hdlr’, version = 0, 0) { unsigned int(32) pre_defined = 0; unsigned int(32) handler_type; const unsigned int(32)[3] reserved = 0; string name; }主要字段含义:handler type: 在media box中,该值为4个字符,会有以下取值:‘vide’ Video track ‘soun’ Audio track ‘hint’ Hint track ‘meta’ Timed Metadata track ‘auxv’ Auxiliary Video trackname: human-readable name for the track type,以‘’结尾的 UTF-8 字符串。用于调试后者检查的目的。

5.9 Media Information Box(minf)

重要的容器 box,“minf”存储了解释track媒体数据的handler-specific信息,media handler用这些信息将媒体时间映射到媒体数据并进行处理。“minf”是一个container box,其实际内容由子box说明。 语法: class MediaInformationBox extends Box(‘minf’) { }“minf”中的信息格式和内容与媒体类型以及解释媒体数据的media handler密切相关,其他media handler不知道如何解释这些信息。 一般情况下,“minf”包含一个header box,一个“dinf”和一个“stbl”,其中,header box根据track type(即media handler type)分为“vmhd”、“smhd”、“hmhd”和“nmhd”,“dinf”为data information box,“stbl”为sample table box。下面分别介绍。

5.10 Media Information Header Box(vmhd、smhd、hmhd、nmhd)

vmhd、smhd这两个box在解析时,非不可或缺的(有时候得看播放器),缺了的话,有可能会被认为格式不正确。Video Media Header Box(vmhd)语法: class VideoMediaHeaderBox extends FullBox(‘vmhd’, version = 0, 1) { template unsigned int(16) graphicsmode = 0; // copy, see below template unsigned int(16)[3] opcolor = {0, 0, 0}; }主要字段含义: graphics mode:视频合成模式,为0时拷贝原始图像,否则与opcolor进行合成。opcolor: 一组(red,green,blue),graphics modes使用。Sound Media Header Box(smhd) 语法: class SoundMediaHeaderBox extends FullBox(‘smhd’, version = 0, 0) { template int(16) balance = 0; const unsigned int(16) reserved = 0; }主要字段含义: balance:立体声平衡,[8.8] 格式值,一般为0表示中间,-1.0表示全部左声道,1.0表示全部右声道。Hint Media Header Box(hmhd) Null Media Header Box(nmhd) 非视音频媒体使用该box。

5.11 Data Information Box(dinf)

“dinf”解释如何定位媒体信息,是一个container box。 语法: class DataInformationBox extends Box(‘dinf’) { }“dinf”一般包含一个“dref”(data reference box)。 “dref”下会包含若干个“url”或“urn”,这些box组成一个表,用来定位track数据。简单的说,track可以被分成若干段,每一段都可以根据“url”或“urn”指向的地址来获取数据,sample描述中会用这些片段的序号将这些片段组成一个完整的track。一般情况下,当数据被完全包含在文件中时,“url”或“urn”中的定位字符串是空的。 “dref”的语法: class DataEntryUrlBox (bit(24) flags) extends FullBox(‘url ’, version = 0, flags) { string location; } class DataEntryUrnBox (bit(24) flags) extends FullBox(‘urn ’, version = 0, flags) { string name; string location; } class DataReferenceBox extends FullBox(‘dref’, version = 0, 0) { unsigned int(32) entry_count; for (i=1; i<= entry_count; i++) { DataEntryBox(entry_version, entry_flags) data_entry; } }主要字段含义: entry count:“url”或“urn”表的元素个数。entry_version:entry格式的版本。entry_flags:当“url”或“urn”的box flag为1时,表示数据在该文件的Moov Box中。“url”或“urn”都是box,“url”的内容为location字符串,“urn”的内容为名称字符串和location字符串。

6. 实用技术

6.1 moov移到mdat前面

ffmpeg默认情况下生成moov是在mdat写完成之后再写入,所以moov是在mdat的后面,使用faststart参数可以将moov移到mdat前面。 ./ffmpeg -i demo.flv -c copy output.mp4moov在mdat后面 image.png使用faststart参数ffmpeg -i out.flv -c copy -movflags faststart out2.mp4moov在mdat前面 image.png

6.2 如何实现seek

stbl.png例如,我们需要seek到30s。 需要做如下工作:

END,本文到此结束,如果可以帮助到大家,还望关注本站哦!

用户评论

莫阑珊

这个标题听起来很有技术含量啊!

    有18位网友表示赞同!

泪湿青衫

想了解一下MP4视频是如何工作的吗?

    有6位网友表示赞同!

病态的妖孽

这方面的知识应该挺重要的吧,能看懂视频的内部结构。

    有13位网友表示赞同!

空谷幽兰

感觉可以学到很多干货!学习一下MP4文件格式解析很有用。

    有10位网友表示赞同!

暮光薄凉

我记得之前看过一些关于视频格式的文章,但没深入了解过。

    有9位网友表示赞同!

ˉ夨落旳尐孩。

这篇文章是不是要讲一些专业的编码技术?

    有16位网友表示赞同!

半世晨晓。

对程序员来说,理解MP4是必须的呀!

    有19位网友表示赞同!

迷路的男人

不知道解析MP4文件需要哪些软件工具?

    有18位网友表示赞同!

我一个人

视频播放器是如何实现解码的呢?

    有19位网友表示赞同!

棃海

这篇文章应该会讲解MP4的文件结构和各个组成部分吧?

    有9位网友表示赞同!

拽年很骚

学习一下MP4格式,对做影视作品的人也很重要。

    有8位网友表示赞同!

孤独症

感觉这种技术含量很高的知识能让我 broaden my horizons ,

    有12位网友表示赞同!

巷口酒肆

视频压缩算法也是很有意思的,文章会不会提到这些?

    有12位网友表示赞同!

坠入深海i

如果能看懂MP4文件的内容,也许能修改视频格式吗?

    有13位网友表示赞同!

蝶恋花╮

我很想了解一下不同的视频格式有什么区别。

    有14位网友表示赞同!

苍白的笑〃

MP4文件解析是不是一个比较复杂的领域?

    有6位网友表示赞同!

命运不堪浮华

这篇文章的难易程度怎么样?適合初学者学习吗?

    有12位网友表示赞同!

﹎℡默默的爱

MP4文件在现实生活中应用场景还挺多的吧?

    有11位网友表示赞同!

呆萌

我觉得学习一下MP4格式解析,未来可以帮助我更好地理解视频和音频技术。

    有20位网友表示赞同!

【MP4文件格式深度解析:核心技术及细节解读】相关文章:

1.蛤蟆讨媳妇【哈尼族民间故事】

2.米颠拜石

3.王羲之临池学书

4.清代敢于创新的“浓墨宰相”——刘墉

5.“巧取豪夺”的由来--米芾逸事

6.荒唐洁癖 惜砚如身(米芾逸事)

7.拜石为兄--米芾逸事

8.郑板桥轶事十则

9.王献之被公主抢亲后的悲惨人生

10.史上真实张三丰:在棺材中竟神奇复活