视频简介
视频定义
**视频(Video)**泛指将一系列静态影像以电信号的方式加以捕捉、记录、处理、储存、传送与重现的各种技术。连续的图像变化每秒超过24帧(frame)画面以上时,根据视觉暂留原理,人眼无法辨别单幅的静态画面;看上去是平滑连续的视觉效果,这样连续的画面叫作视频。
视频原理
视频的原理主要基于人眼的视觉残留现象,也称为视觉暂留现象。
当物体移动时,人眼对物体的印象不会立即消失,而是会持续大约1/24秒的时间。这意味着,如果一系列静态图像以超过每秒24帧的速率快速连续显示,人眼会将其感知为连续运动的视频。视频文件,如MP4、AVI、MKV等,实际上是连续时间序列图像的集合,这些图像经过压缩和封装以便存储和传输。播放视频时,需要专门的解码器或播放器对视频文件进行解压缩或解码,并在画布上以恒定的帧率展示时间序列影像。
图像表达原理
视频是由连续图像组成的,图像是表达视频的基本单位。视频中的图像表达模型有RGB 、HSI、YUV等多种模型,它们基于三原色原理,广泛用于视频的显示中。
人眼可见光波长范围为380nm-780nm,物体通过反射将可见光传入人眼中,人的大脑便有了物象,所有物象的颜色都可以看作是红®、绿(G)、蓝(B)三种可见光颜色的不同组合。
国际照度委员会(CIE)在1931年规定了三种基本色的波长分别为R:700nm G:546nm B:435.8nm。
RGB模型
光的三原色是红(Red)、绿(Green)、蓝(Blue)。
现代的显示器技术就是通过组合不同强度的三原色,来达成任何一种可见光的颜色。
图像储存中,通过记录每个像素红绿蓝强度,来记录图像的方法,称为RGB模型 (RGB Model),常见的图片格式中,PNG和BMP这图像格式就是基于RGB模型的。
YUV模型
YUV模型,又被称为亮度-色度模型(Luma-Chroma):
亮度:亮度是指图形原色的明暗程度。亮度的范围是从0-255,共256种色调。
色相:色相是指从物体反射或透过物体传播的颜色。简单的说色相就是色彩颜色,对色相的调整就是在多种颜色之间的变化,例如红、橙、黄、绿、青、蓝、紫七色组成,每一种颜色即道标一种色相。
饱和度:饱和度也成为彩度,是指颜色的强度或纯度。调整饱和度就是调整图像的彩度。将一个彩色图像的饱和度降为0时,就会变为灰色图像,增加饱和度就会增加彩度。
对比度:对比度是指不同颜色之间的差异,对比度越大,两种颜色之间的反差越大。反之颜色越接近。
YUV模型下,有不同的实现方式。用得比较多有YCbCr模型:它把RGB转换成一个亮度(Y),和 蓝色色度(Cb) 以及 红色色度(Cr)。
HSV模型
色调 H:用角度度量,取值范围为 0°~360°,从红色开始按逆时针方向计算,红色为 0°,绿色为 120°,蓝色为 240°。它们的补色是:黄色为 60°,青色为 180°,品红为 300°;
饱和度 S:饱和度 S 表示颜色接近光谱色的程度。一种颜色,可以看成是某种光谱色与白色混合的结果。其中光谱色所占的比例愈大,颜色接近光谱色的程度就愈高,颜色的饱和度也就愈高。饱和度高,颜色则深而艳。光谱色的白光成分为 0,饱和度达到最高。通常取值范围为 0%~100%,值越大,颜色越饱和。
明度 V:明度表示颜色明亮的程度,对于光源色,明度值与发光体的光亮度有关;对物体色,此值和物体的透射比或反射比有关。通常取值范围为 0%(黑) 到 100%(白) 。
HSV 模型的三维表示从 RGB 立方体演化而来。设想从 RGB 沿立方体对角线的白色顶点向黑色顶点观察,就可以看到立方体的六边形外形。 六边形边界表示色彩, 水平轴表示纯度,明度沿垂直轴测量。
视频的基础参数
图像基础
像素:图像的基本单元,即一个带有颜色的小块
分辨率:图像的大小或尺寸,用像素个数来表示。原始图像分辨率越高,图像就越清晰
位深:存储每位像素需要的二进制位数;位深越大,能够表示的颜色值就越多,色彩越丰富真实
跨距(Stride):图像存储时内存中每行像素所占用的空间。需要正确的设置,否则会出现花屏
帧率:1秒中内图像的数量,单位FPS
码率:视频在1s内的数据量的大小。一般码率越高,视频清晰度越高,存储时占用内存空间就越大,传输时使用流量越多,但还需要结合压缩算法和压缩速度综合考虑
视频帧
视频是由连续的图像构成的,视频中的一幅图像称为一帧,相当于电影中的一个镜头,帧是视频、动画中最小单位的单幅影像画面。
I帧(帧内编码帧):是一种自带全部信息的独立帧,无需参考其他图像便可独立进行解码,可以简单理解为一张静态画面。视频序列中的第一个帧始终都是I帧,因为它是关键帧。
P帧(帧间预测编码帧):需要参考前面的I帧才能进行编码。表示的是当前帧画面与前一帧(前一帧可能是I帧也可能是P帧)的差别。解码时需要用之前缓存的画面叠加上本帧定义的差别,生成最终画面。与I帧相比,P帧通常占用更少的数据位,但不足是,由于P帧对前面的P和I参考帧有着复杂的依耐性,因此对传输错误非常敏感。
B帧(双向预测编码帧):也就是B帧记录的是本帧与前后帧的差别。也就是说要解码B帧,不仅要取得之前的缓存画面,还要解码之后的画面,通过前后画面的与本帧数据的叠加取得最终的画面。B帧压缩率高,但是对解码性能要求较高。
:::info
当采样视频信号时,如果是通过逐行扫描,那么得到的信号就是一帧图像,通常帧频为25帧每秒(PAL制)、30帧每秒(NTSC制)。
当采样视频信号时,如果是通过隔行扫描(奇、偶数行),那么一帧图像就被分成了两场,通常场频为50Hz(PAL制)、60Hz(NTSC制)。
:::
视频分辨率
视频的分辨率是指每一帧图像的长宽积,比如说1920×1080的图像,说明它是由横纵1920×1080个像素点构成。
屏幕分辨率(像素密度)是指屏幕单位长度内显示的有效像素值,即:每英寸所包含的像素数目(Pixels Per Inch:PPI),常用规格有常见的有72,180和300等。
PPI超过300时,就可以算是视网膜屏了,肉眼已经分辨不出像素点。
广播电视和流媒体视频分辨率规格:(i-interlace隔行扫描,p-逐行扫描):
480i:720×480(水平480线,隔行扫描),和NTSC模拟电视清晰度相同,行频为15.25kHz,相当于我们所说的4CIF(720×576)
480P:720×480(水平480线,逐行扫描),较D1隔行扫描要清晰不少,和逐行扫描DVD规格相同,行频为31.5kHz
1080i:1920×1080(水平1080线,隔行扫描),高清方式采用最多的一种分辨率,分辨率为1920×1080i/60Hz,行频为33.75kHz
720p:1280×720(水平720线,逐行扫描),虽然分辨率较D3要低,但是因为逐行扫描,市面上更多人感觉相对于1080I(实际逐次540线)视觉效果更加清晰。不过个人感觉来说,在最大分辨率达到1920×1080的情况下,D3要比D4感觉更加清晰,尤其是文字表现力上,分辨率为1280×720p/60Hz,行频为45kHz
1080p:1920×1080(水平1080线,逐行扫描),目前民用高清视频的最高标准,分辨率为1920×1080P/60Hz,行频为67.5KHZ。
视频帧率
帧率是指每秒钟刷新的图片的帧数,也可以理解为图形处理器每秒钟能够刷新几次。常见的帧率有24000/1001=23.976, 30000/1001=29.970, 60000/1001=59.940, 25.000, 50.000等等。
一般来说30fps就是可以接受的,但是将性能提升至60fps则可以明显提升交互感和逼真感,一般来说帧率超过75fps,就不容易察觉到有明显的流畅度提升了。
视频码率
码率(码流、位元传输率、比特率、位元速率)是指视频文件在单位时间内使用的数据流量。单位一般是Kbps(Kbit/s)或者Mbps(Mbit/s)。
固定比特率-CBR(Constant Bitrate)指文件从头到尾都是一种位速率。相对于VBR和ABR来讲,它压缩出来的文件体积很大,但是码率恒定,对于传送带宽固定,需要即时传送并且没有暂存手段的视频串流来说,固定位元速率(Constant bit rate,CBR)比VBR更为适合。
动态比特率-VBR(Variable Bitrate)也就是没有固定的比特率,压缩软件在压缩时根据音频数据即时确定使用什么比特率。采用VBR编码的视频在大动态或复杂的画面时段会自动以较高的速率来记录影像,而在静止或简单的画面时段则降低速率。这样可以在保证画面品质恒定的前提下尽量减少传输率。;
平均比特率-ABR(Average Bitrate)是VBR的一种插值参数。LAME针对CBR不佳的文件体积比和VBR生成文件大小不定的特点独创了这种编码模式。ABR在指定的文件大小内,以每50帧(30帧约1秒)为一段,低频和不敏感频率使用相对低的流量,高频和大动态表现时使用高流量,可以做为VBR和CBR的一种折衷选择。
:::info
同样视频分辨率下,视频文件的码流越大,压缩比就越小,画面质量就越高。码流越大,说明单位时间内取样率越大,数据流精度就越高,处理出来的文件就越接近原始文件,图像质量越好,画质越清晰,要求播放设备的解码能力也越高。
:::
视频色深(位深)
色深(bit-depth),就是我们通常说的8bit和10bit,是指每个通道的精度(R\G\B为图像的三个通道)。8bit就是每个通道用一个8bit整数(0255)代表,10bit就是用10bit整数(01023)来显示,16bit则是0~65535。
视频重采样
视频采样定义了从连续信号中提取并组成离散信号的采样个数。视频采样率是指将模拟信号转换成数字信号时的采样频率,也就是单位时间内采样多少点,用赫兹(Hz)来表示。
重采样是指将原始视频重新进行采样的过程。现行所有的视频播放器都可以对原始视频数据进行重采样,以实现用户需要的播放效果。
:::info
采样率类似于动态影像的帧数,比如电影的采样率是24赫兹,PAL制式的采样率是25赫兹,NTSC制式的采样率是30赫兹。
:::
视频高低频
亮度变化较快,变动幅度大的区域,我们称之为高频区域。否则,亮度变化缓慢且不明显的区域,我们称为低频区域。
图像颜色空间
颜色空间分类:
**RGB:**指图像的每一个像素都是分别存储R、G、B三个值,且三个值依次排列存储。顺序不一定是R-B-G,RGB三个颜色有相关性,采集和渲染的时候是RBG
**YUV:**图像将亮度信息 Y 与色彩信息 U、V 分离开来。Y 表示亮度,是图像的总体轮廓,称之为 Y 分量。U、V 表示色度,主要描绘图像的色彩等信息,分别称为 U 分量和 V 分量
YUV
YUV分类:
YUV 4:4:4,每一个 Y 对应一组 UVYUV 4:2:2,每两个 Y 共用一组 UVYUV 4:2:0,每四个 Y 共用一组 UV
YUV存储方式:
Planar:先连续存储所有像素点的Y,然后接着存储所有像素点的U/V,之后再存储所有像素点的V/UPacked**:先存储完所有像素的Y,然后U、V连续的交错存储Tips**:U和V在一张图片中顺序固定,不同图片U和V谁在前不一定
YUV类型和存储类型关系:
YUV类型 | 存储类型 | |
---|---|---|
YUV 4:4:4 | I444 | |
YV24 | ||
YUV 4:2:2 | Packed | NV16 |
NV61 | ||
Planar | YU16(I422) | |
YV16 | ||
YUV 4:2:0 | Packed | NV12 |
NV21 | ||
Planar | YU12(I420) | |
YV12 |
I444:YUV顺序
YV24:YVU顺序
NV16:先存储完 Y,之后 U、V 连续交错存储
NV61:先存储完 Y,之后 V、U 连续交错存储
YU16(I422):YUV顺序
YV16:YVU顺序
NV12:先存储完 Y,之后 U、V 连续交错存储
NV21:先存储完 Y,之后 V、U 连续交错存储
YU12(I420):YUV顺序
YV12:YVU顺序
RGB与YUV互转规范
BT709:高清的标准
BT601:标清的标准
RBG与YUV转换公式
BT601 Limited Range:
//1、RGB->YUV
Y= 0.299*R+ 0.587*G+0.114*B
U=-0.172*R-0.339*G+0.511*B+128
V= 0.511*R-0.428*G-0.083*B+128
//2、YUV->RGB
R=Y+1.371*(V-128)
G=Y-0.336*(U-128)-0.698*(V-128)
B= Y+1.732*(U-128)
BT601 Full Range:
1、RGB->YUV
Y= 16+0.257*R+ 0.504*G+0.098*B
U=128-0.148*R-0.291*G+0.439*B
V=128+0.439*R-0.368*G-0.071*B
2、YUV->RGB
R= 1.164*(Y-16)+ 1.596*(V-128)
G=1.164*(Y-16)-0.392*(U-128)-0.812*(V-128)
B=1.164*(Y-16)+2.016*(U-128)
BT709 Limited Range:
//1、RGB->YUV
Y= 0.213*R+0.715*G+0.072*B
U=-0.117*R-0.394*G+ 0.511*B+128
V= 0.511*R-0.464*G-0.047*B+128
//2、YUV->RGB
R= Y+ 1.540*(V-128)
G=Y-0.183*(U-128)-0.459*(V-128)
B= Y+1.816*(U-128)
BT601 Full Range:
//1、RGB->YUV
Y= 16+0.183*R+ 0.614*G+0.062*B
U=128-0.101*R-0.339*G+0.439*B
V=128+0.439*R-0.339*G-0.040*B
//2、YUV->RGB
R=1.164*(Y-16)+1.792*(V-128)
G=1.164*(Y-16)-0.213*(U-128)-0.534*(V-128)
B=1.164*(Y-16)+2.114*(U-128)
视频编码及格式
编码基础概念
宏块
宏块:对于每一帧图像,划分成一个个块来进行编码。例如:16x16(H264、VP8),32x32(H265、VP9),64x64(H265、VP9、AV1),128x128(AV1)。
图像数据冗余
空间冗余:相邻的块很多时候都有比较明显的相似性
时间冗余:前后两帧图像的变化是比较小的,相似性很高
视觉冗余:人的眼睛对于图像中高频信息的敏感度是小于低频信息的
信息熵冗余:文件压缩
编码原理
帧内预测:为了提高熵编码的压缩率,先将当前编码块的相邻块像素经过帧内预测算法得到帧内预测块,再用当前编码块减去帧内预测块得到残差块,从而去掉空间冗余。
帧间预测:类似于帧内预测,在已经编码完成的帧中,先通过运动搜索得到帧间预测块,再与编码块相减得到残差块,从而去除时间冗余:
a)参考帧:预测块所在的已经编码的图像
b)运动矢量:预测块在参考帧中的坐标值(x0, y0)与编码块在编码帧中的坐标值(x1, y1)的差值(x0 - x1, y0 - y1)
c)运动搜索:在参考帧中去寻找预测块的过程
DCT 变换(离散余弦变换)和量化:将残差块变换到频域,分离高频和低频信息。
a)量化步长QStep:DCT变换块的系数都同时除以一个值,QStep越大得到量化后的系数就会越小,一般用量化参数QP(和QStep有对应映射表)
b)编码时:QStep 乘以量化后的系数得到变换系数,有损编码
c)QP 值越大,损失就越大,从而画面的清晰度就会越低,0的概率越大,压缩率越高
熵编码(以行程编码为例):视频编码中真正实现“压缩”的步骤,主要去除信息熵冗余。在出现连续多个 0 像素的时候压缩率会更高
编码器关键流程
视频压缩编码技术
视频压缩编码技术可分为两大类:无损压缩和有损压缩。
无损压缩
无损压缩也称为可逆编码,重构后的数据与原数据完全相同,适用于磁盘文件的压缩等。主要采用熵编码方式,包括香农编码、 哈夫曼编码和算术编码等。
香农编码
- 香农编码采用信源符号的累计概率分布函数来分配码字,效率不高,实用性不大,但对其他编码方法有很好的理论指导意义。
哈夫曼编码
- 哈夫曼编码完全依据出现概率来构造异字头的平均长度最短的码字。
- 基本方法为:先对图像数据扫描一遍,计算出各种像素出现的概率,按概率的大小指定不同长度的唯一码字,由此得到一张该图像的霍夫曼码表。
- 编码后的图像数据记录的是每个像素的码字,而码字与实际像素值的对应关系记录在码表中。
算术编码
- 算术编码是用符号的概率和编码间隔两个基本参数来描述的,在给定符号集和符号概率的情况下,算术编码可以给出接近最优的编码结果。
- 使用算术编码的压缩算法通常先要对输入符号的概率进行估计,然后再编码,估计越准,编码结果就越接近最优的结果。
有损压缩
有损压缩也称为不可逆编码,重构后的数据与原数据有差异,适用于任何允许有失真的场景,例如视频会议、可视电话、视频广播、视频监控等。
编码方式包括预测编码、变换编码、量化编码、混合编码等。
编码标准
H264->H265
VP8->VP9->AV1
技术选型
清晰度:AV1>H265>H264
专利费:AV1免费、H264收费、H265费用极高
压缩率:AV1>H265>H264
耗时:H264<H265<AV1
硬件支持:H264>H265>AV1
使用场景
屏幕编码:使用AV1, AV1原生标准就支持屏幕编码的优化
浏览器:VP9或AV1,浏览器原生不支持H265
机器性能:性能差机器使用H264、VP8,中高等机器可以考虑H265
性价比较高:H264
视频格式
视频文件格式
微软视频 :wmv、asf、asx
Real Player :rm、 rmvb
MPEG视频 :mp4
手机视频 :3gp
Apple视频 :mov、m4v
其他常见视频:avi、dat、mkv、flv、vob等
视频封装格式
封装格式也称多媒体容器,它只是为多媒体编码提供了一个“外壳”
AVI 格式(后缀为 .AVI):它的英文全称为 Audio Video Interleaved,即音频视频交错格式。这种视频格式的优点是图像质量好。由于无损 AVI 可以保存 alpha 通道,经常被我们使用。缺点太多,体积过于庞大,而且更加糟糕的是压缩标准不统一。
DV-AVI 格式(后缀为 .AVI):DV 的英文全称是 Digital Video Format,是由索尼、松下、 JVC 等多家厂商联合提出的一种家用数字视频格式。数字摄像机就是使用这种格式记录视频数据的。
QuickTime File Format 格式(后缀为 .MOV):具有较高的压缩比率和较完美的视频清晰度等特点,并可以保存 alpha 通道。
MPEG 格式(文件后缀可以是 .MPG .MPEG .MPE .DAT .VOB .ASF .3GP .MP4等) :
MPEG 文件格式是运动图像压缩算法的国际标准。MPEG 格式目前有三个压缩标准,分别是 MPEG-1、MPEG-2、和 MPEG-4。
WMV 格式(后缀为 .WMV .ASF) :WMV 格式的主要优点包括:本地或网络回放,丰富的流间关系以及扩展性等。
Flash Video 格式(后缀为.FLV) :随着视频网站的丰富, 这个格式已经非常普及。
Matroska 格式( 后缀为.MKV):是一种新的多媒体封装格式, 这个封装格式可把多种不同编码的视频及 16 条或以上不同格式的音频和语言不同的字幕封装到一个 Matroska Media 档内。Matroska 同时还可以提供非常好的交互功能, 而且比 MPEG 的方便、 强大。
常用视频格式及对应的文件格式:
视频封装格式 | 视频文件格式 |
---|---|
AVI(Audio Video Interleave) | AVI |
WMV(Windows Media Video) | WMV |
MPEG(Moving Picture Expert Group)分为 MPEG-1,MPEG-2,MPEG-4 | MPG MPEG VOB DAT 3GP MP4 |
Matroska | MKV |
Real Video | RM RMVB |
QuickTime File Format | MOV |
Flash Video | FLV |
视频编码格式
视频编码方式就是指能够对数字视频进行压缩或者解压缩( 视频解码)的程序或者设备,通常这种压缩属于有损数据压缩。也可以指通过过特定的压缩技术,将某个视频格式转换成另一种视频格式。常见的编码方式有:
H.26X 系列( 由 ITU[国际电传视讯联盟]主导)包括 H.261、H.262、H.263、 H.264、H.265。
H.261:主要在老的视频会议和视频电话产品中使用。
H.263:主要用在视频会议、视频电话和网络视频上。
H.264:H.264/MPEG-4 第十部分,或称 AVC( Advanced Video Coding, 高级视频编码) ,是一种视频压缩标准,一种被广泛使用的高精度视频的录制、压缩和发布格式。
H.265:高效率视频编码( High Efficiency Video Coding,简称 HEVC)是一种视频压缩标准,H.264/MPEG-4 AVC 的继任者。HEVC 被认为不仅提升图像质量,同时也能达到 H.264/MPEG-4 AVC 两倍之压缩率(等同于同样画面质量下比特率减少了 50%),可支持 4K 分辨率甚至到超高画质电视,最高分辨率可达到 8192×4320( 8K 分辨率),这是目前发展的趋势。
MPEG 系列(由 ISO[国际标准组织机构]下属的 MPEG[运动图象专家组]开发 )视频编码方面主要有
MPEG-1 第二部分( MPEG-1 第二部分主要使用在 VCD 上,有些在线视频也使用这种格式。该编解码器的质量大致上和原有的 VHS 录像带相当。
MPEG-2 第二部分( MPEG-2 第二部分等同于 H.262,使用在 DVD、SVCD 和大多数数字视频广播系统和有线分布系统(cable distribution systems) 中。)
MPEG-4 第二部分(MPEG-4 第二部分标准可以使用在网络传输、广播和媒体存储上。比起 MPEG-2 和第一版的 H.263,它的压缩性能有所提高。)
MPEG-4 第十部分(MPEG-4 第十部分技术上和 ITU-TH.264 是相同的标准,有时候也被叫做“AVC”)最后这两个编码组织合作,诞生了 H.264/AVC 标准。
其他系列:
AMV、AVS、Bink、CineForm、Cinepak、Dirac、DV、Indeo Video 、Pixlet、RealVideo、RTVideo、SheerVideo、Smacker、Sorenson Video、Theora、VC-1、VP3、VP6、VP7、VP8、VP9、WMV。
封装格式详解
MP4
简介
MP4(MPEG-4 Part 14)是一种标准的数字多媒体容器格式,其扩展名为.mp4,以存储数字音频及数字视频为主,也可存储字幕和静止图像。
广泛支持的编解码器或数据流格式有:
视频格式:H.264/AVC、H.265/HEVC、VP8/9等。
音频格式:AAC、MP3、Opus等。
在线解析 MP4 工具:
MP4box.js:https://gpac.github.io/mp4box.js/test/filereader.html
mp4parser:https://www.onlinemp4parser.com/
概念与术语是理解好MP4媒体封装格式和其操作算法的关键,为了方便了解MP4文件格式,需先了解以下几个概念与术语:
Box:MP4文件是由一个个Box组成的,可以将其理解为一个数据块,它由Header+Data组成,Data 可以存储媒体元数据和实际的音视频码流数据。Box可直接存储数据块,也可包含其它Box,我们把包含其它Box的Box称为container box。
Sample:可理解为采样,对于视频可理解为一帧数据,音频一帧数据就是一段固定时间的音频数据,可以由多个Sample数据组成,存储媒体数据的单位是sample。
Chunk:连续几个sample组成的单元被称为chunk,每个chunk在文件中有一个偏移量,整个偏移量从文件头算起,在这个chunk内,sample是连续存储的。
Track:表示一些chunk的集合,对于媒体数据而言就是一个视频序列或者音频序列,常说的音频/视频轨可对照该概念上。除了Video Track和Audio Track外,还可以有非媒体数据,比如Hint Track,这种类型的Track就不包含媒体数据,可以包含一些将其他数据打包成媒体数据的指示信息或者字幕信息。简单来说,Track是音视频中可以独立操作的媒体单位。
可理解为MP4文件中有多个Track,一个Track由多个Chunk组成,每个Chunk包含一组连续的Sample。例如视频流的一个Sample代表实际的nal数据,Chunk是数据存储的基本单位,它是一系列Sample数据的集合。
MP4整体结构
MP4 文件由 **box **组成,每个 box 分为 Header 和 Data。其中 Header 部分包含了 box 的类型和大小,Data 包含了子 box 或者数据,box 可以嵌套子 box。
典型 MP4 文件的基本结构:
这些boxes之间存在⼀定的层次关系,总结如下表所示,表中标记出了各个box必选或可选特性,√代表Box必选。
ftyp | √ | file type and compatibility ⽂件类型和兼容性 | |||||
pdin | progressive download information | ||||||
moov | √ | container for all the metadata 所有元数据的容器 | |||||
mvhd | √ | movie header, overall declarations 电影头,整体声明 | |||||
trak | √ | container for an individual track or stream 单个轨或流的容器 | |||||
tkhd | √ | track header, overall information about the track 轨的头部,关于该轨的概括信息,⽐如视频宽⾼ | |||||
tref | track reference container | ||||||
edts | edit list container | ||||||
elst | an edit list | ||||||
mdia | √ | container for the media information in a track 轨媒体信息的容器 | |||||
mdhd | √ | media header, overall information about the media 媒体头,关于媒体的总体信息 | |||||
hdlr | √ | handler, declares the media (handler) type 媒体的播放过程信息 | |||||
minf | √ | media information container 媒体信息容器 | |||||
vmhd | video media header, overall information (video track only) | ||||||
smhd | sound media header, overall information (sound track only) | ||||||
hmhd | hint media header, overall information (hint track only) | ||||||
nmhd | Null media header, overall information (some tracks only) | ||||||
dinf | √ | data information box, container 数据信息box,容器 | |||||
dref | √ | data reference box, declares source(s) of media data in track 如何定位媒体信息 | |||||
stbl | √ | sample table box, container for the time/space map 包含了track中的sample的所有时间和位置信息,以及sample的编解码等信息。利⽤这个表可以解析sample的时序、类型、⼤⼩以及在各⾃存储容器中的位置。 | |||||
stsd | √ | sample descriptions (codec types,initialization etc.) 如果是视频,包含:编码类型、宽⾼、⻓度等信息;如果是⾳频,包含:声道、采样率等信息 | |||||
stts | √ | (decoding) time-to-sample描述了sample时序的映射⽅法,我们可以通过它找到任何时间的sample。 | |||||
ctts | (composition) time to sample。 | ||||||
stsc | √ | sample-to-chunk, partial data-offset information ⽤chunk组织sample可以⽅便优化数据获取,⼀个chunk包含⼀个或多个sample。 | |||||
stsz | sample sizes (framing) 每个sample的⼤⼩。虽然这⾥没有打勾,但对于mp4还是⾮常必要的。 | ||||||
stz2 | compact sample sizes (framing) | ||||||
stco | √ | chunk offset, partial data-offset information 定义了每个chunk在媒体流中的偏移位置 | |||||
co64 | 64-bit chunk offset | ||||||
stss | sync sample table (random access points) ⽤于确定media中的关键帧 | ||||||
stsh | shadow sync sample table | ||||||
padb | sample padding bits | ||||||
stdp | sample degradation priority | ||||||
sdtp | independent and disposable samples | ||||||
sbgp | sample-to-group | ||||||
sgpd | sample group description | ||||||
subs | sub-sample information | ||||||
mvex | movie extends box | ||||||
mehd | movie extends header box | ||||||
trex | √ | track extends defaults | |||||
ipmc | IPMP Control Box | ||||||
moof | movie fragment | ||||||
mfhd | √ | movie fragment header | |||||
traf | track fragment | ||||||
tfhd | √ | track fragment header | |||||
trun | track fragment run | ||||||
sdtp | independent and disposable samples | ||||||
sbgp | sample-to-group | ||||||
subs | sub-sample information | ||||||
mfra | movie fragment random access | ||||||
tfra | track fragment random access | ||||||
mfro | √ | movie fragment random access offset | |||||
mdat | media data container | ||||||
free | free space | ||||||
skip | free space | ||||||
udta | user-data | ||||||
cprt | copyright etc. | ||||||
meta | metadata | ||||||
hdlr | √ | handler, declares the metadata (handler) type | |||||
dinf | data information box, container | ||||||
dref | data reference box, declares source(s) of metadata items | ||||||
ipmc | IPMP Control Box | ||||||
iloc | item location | ||||||
ipro | item protection | ||||||
sinf | protection scheme information box | ||||||
frma | original format box | ||||||
imif | IPMP Information box | ||||||
schm | scheme type box | ||||||
schi | scheme information box | ||||||
iinf | item information | ||||||
xml | XML container | ||||||
bxml | binary XML container | ||||||
pitm | primary item reference | ||||||
fiin | file delivery item information | ||||||
paen | partition entry | ||||||
fpar | file partition | ||||||
fecr | FEC reservoir | ||||||
segr | file delivery session group | ||||||
gitn | group id to name | ||||||
tsel | track selection | ||||||
meco | additional metadata container | ||||||
mere | metabox relation |
:::info
本⽂使⽤mediainfo和mp4box进⾏分析
:::
图中看到mp4⽂件由⼏个主要组成部分:
- ftype
File Type Box,一般在文件的开始位置,描述的文件的版本、兼容协议等。
- moov
Movie Box,包含本⽂件中所有媒体数据的宏观描述信息以及每路媒体轨道的具体信息。⼀般位于放在⽂件末尾,但如果为了⽀持http边下载边播放则需要将moov提前。注意,当改变moov位置时,内部⼀些值需要重新计算。
- mdat
MP4 的媒体数据信息主要存放在 Moov Box 中,是我们需要分析的重点。moov 的主要组成部分如下:
- mvhd
Movie Header Box,记录整个媒体⽂件的描述信息,如创建时间、修改时间、时间度量标尺、可播放时⻓等。
- udta
User Data Box,⾃定义数据。
- trak
Track Box,记录媒体流信息,⽂件中可以存在⼀个或多个track,它们之间是相互独⽴的。
每个track包含以下⼏个组成部分:
- tkhd
Track Header Box,包含关于媒体流的头信息。
- mdhd
Media Header Box,存放视频流创建时间,⻓度等信息。
- hdlr
Handler Reference Box,媒体的播放过程信息。
- minf
Media Information Box,解释track媒体数据的handler-specific信息。minf同样是个container box,其内部需要关注的内容是stbl,这也是moov中最复杂的部分。stbl包含了媒体流每⼀个sample在⽂件中的offset,pts,duration等信息。想要播放⼀个mp4⽂件,必须根据stbl正确找到每个sample并送给解码器。
⽽且需要注意的是,minf⾥⾯的⼦容器,⾳频和视频轨是有区别的,⽐如视频轨:vmhd, ⾳频轨则为:smhd
- stbl
Sample Table Box,上⽂提到mdia中最主要的部分是存放⽂件中每个sample信息的stbl。在解析stbl前,我们需要区分chunk和sample这两个概念。
在mp4⽂件中,sample是⼀个媒体流的基本单元,例如视频流的⼀个sample代表实际的nal数据。chunk是数据存储的基本单位,它是⼀系列sample数据的集合,⼀个chunk中可以包含⼀个或多的sample。
⼀个chunk包含⼀个或多个sample
stbl⽤来描述每个sample的信息,包含以下⼏个主要的⼦box:
- stsd
Sample Description Box,存放解码必须的描述信息。
下图示例中,对于h264的视频流,其具体类型为 avc1 ,extensions中其中存放有sps,pps等解码必要信息。
avcC:包含了视频编码器相关的信息,包括sps、pps等信息
- stts
Time-to-Sample Box,定义每个sample时⻓。Time-To-Sample的table entry布局如下:
–sample count:sample个数
–sample duration:sample持续时间
持续时间相同的连续sample可以放到⼀个entry⾥达到节省空间的⽬的。
- stss
Sync Sample Box,同步sample表,存放关键帧列表,关键帧是为了⽀持随机访问。
stss的table entry布局如下:
- stsc
Sample-To-Chunk Box,sample-chunk映射表。上⽂提到mp4通常把sample封装到chunk中,⼀个chunk可能会包含⼀个或者⼏个sample。Sample-To-Chunk Atom的table entry布局如下图所示:–First chunk:使⽤该表项的第⼀个chunk序号
–Samples per chunk:使⽤该表项的chunk中包含有⼏个sample
–Sample description ID:使⽤该表项的chunk参考的stsd表项序号
- stsz
ample Size Box,指定了每个sample的size。Sample Size Atom包含两sample总数和⼀张包含了每个sample size的表。
sample size 表的entry布局如下图:
- stco
Chunk Offset Box,指定了每个chunk在⽂件中的位置,这个表是确定每个sample在⽂件中位置的关键。该表包含了chunk个数和⼀个包含每个chunk在⽂件中偏移位置的表。每个表项的内存布局如下:
需要注意,这⾥stco只是指定的每个chunk在⽂件中的偏移位置,并没有给出每个sample在⽂件中的偏移。想要获得每个sample的偏移位置,需要结合 Sample Size box(stsz)和Sample-To-Chunk(stsc) 计算后取得。
AVI
简介
AVI即Audio Video Interleaved,音视频交错格式,基于RIFF文件结构。多用于音视频捕捉、编辑、回放等应用程序中。通常情况下,一个AVI文件可以包含多个不同类型的媒体流(典型的情况下有一个音频流和一个视频流),不过含有单一音频流或单一视频流的AVI文件也是合法的。AVI可以算是Windows操作系统上最基本的、也是最常用的一种媒体文件格式。
:::info
RIFF即Resource Interchange File Format,资源交互文件格式 。是由Microsoft提出的一种多媒体文件存储方式,不同编码的视频、音频文件按照RIFF保存,当提取文件时,可以根据RIFF的规则解析文件。常见的RIFF文件有:WAV、AVI等。
:::
最基本的数据单元:
//Chunks
typedef struct {
DWORD dwFourCC
DWORD dwSize //data
BYTE data[dwSize] // contains headers or video/audio data
} CHUNK;
//Lists
typedef struct {
DWORD dwList
DWORD dwSize //dwFourcc + data
DWORD dwFourCC
BYTE data[dwSize-4] // contains Lists and Chunks
} LIST;
Chunks由三部分组成:4字节的数据流格式ID,4字节的数据大小,数据。
Lists由四部分组成:4字节LIST(LIST块中可以再包含一系列的子块),4字节数据加fourCC大小,4字节数据流格式ID,数据。
AVI主要结构介绍
一个AVI文件通常有如下几个子块组成:
ID为"AVI"的RIFF,文件头
ID为"hdrl"的list,信息块,包含了音视频信息,描述媒体流信息
ID为"info"的list,包含编码该AVI的程序信息
ID为"junk"的chunk,无用的数据,用于字节对齐
ID为"movi"的list,数据块,包含了交错排列的音视频数据
ID为"idxl"的chunk,索引块,包含音视频排列的索引数据(可选块,不存在时seek会慢很多)
文件信息:
RIFF文件头
4个字节的"RIFF",4字节的RIFF文件大小(342872字节),4字节为RIFF文件类型"AVI"
hdrl列表
1)hdrl列表头
4字节的"LIST"描述信息,4字节list大小(8952字节),4字节list类型"hdrl"
2)avih块
用于描述主信息,该块可以用如下结构体表示:
typedef struct
{
DWORD dwMicroSecPerFrame; //显示每帧所需的时间ns,定义avi的显示速率
DWORD dwMaxBytesPerSec; // 最大数据传输率
DWORD dwPaddingGranularity; //记录块的长度须为此值的倍数,通常是2048
DWORD dwFlags; // AVI文件的特殊属性,包含文件中的任何标志字。如:有无索引块,是否是interlaced,是否含版权信息等
DWORD dwTotalFrames; // 数据帧的总数
DWORD dwInitialFrames; // 在开始播放前需要的帧数
DWORD dwStreams; //文件中包含的数据流种类
DWORD dwSuggestedBufferSize;//建议使用的缓冲区的大小,通常为存储一帧图像以及同步声音所需要的数据之和,大于最大的CHUNK的大小
DWORD dwWidth; //图像宽,像素
DWORD dwHeight; //图像高,像素
DWORD dwReserved[4]; //保留值dwScale,dwRate,dwStart,dwLength
} MainAVIHeader;
3)strl list头部
一个strl list中至少包含一个strh块和一个strf块。文件中有多少个流,就对应有多少个strl list。
上图可知存在两个流,Stream info 0,Stream info 1。
4)strh块
// AVI流头部
typedef struct
{
FourCC fcc; // 必须为 strh
DWORD cb; // 本数据结构的大小,不包括最初的8个字节(fcc和cb两个域)
FourCC fccType; // 流的类型: auds(音频流) vids(视频流) mids(MIDI流) txts(文字流)
FourCC fccHandler; // 指定流的处理者,对于音视频来说就是解码器
DWORD dwFlags; // 标记:是否允许这个流输出?调色板是否变化?
WORD wPriority; // 流的优先级(当有多个相同类型的流时优先级最高的为默认流)
WORD wLanguage; // 语言
DWORD dwInitialFrames; // 为交互格式指定初始帧数
DWORD dwScale; // 每帧视频大小或者音频采样大小
DWORD dwRate; // dwScale/dwRate,每秒采样率
DWORD dwStart; // 流的开始时间
DWORD dwLength; // 流的长度(单位与dwScale和dwRate的定义有关)
DWORD dwSuggestedBufferSize;// 读取这个流数据建议使用的缓存大小
DWORD dwQuality; // 流数据的质量指标(0 ~ 10,000)
DWORD dwSampleSize; // Sample的大小
RECT rcFrame; // 指定这个流(视频流或文字流)在视频主窗口中的显示位置,视频主窗口由AVIMAINHEADER结构中的dwWidth和dwHeight决定
} AVIStreamHeader;
5)strf块
该块用于描述流的具体信息
视频流,fccType = “vids”
音频流,fccType = “auds”
// 位图头
typedef struct
{
DWORD biSize;
LONG biWidth;
LONG biHeight;
WORD biPlanes;
WORD biBitCount;
DWORD biCompression;
DWORD biSizeImage;
LONG biXPelsPerMeter;
LONG biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
} BitmapInfoHeader;
// 位图信息
typedef struct
{
BitmapInfoHeader bmiHeader; // 位图头
RGBQUAD bmiColors[1]; // 调色板
} BitmapInfo;
// 音频波形信息
typedef struct
{
WORD wFormatTag;
WORD nChannels; // 声道数
DWORD nSamplesPerSec; // 采样率
DWORD nAvgBytesPerSec; // 每秒的数据量
WORD nBlockAlign; // 数据块对齐标志
WORD wBitsPerSample; // 每次采样的数据量
WORD cbSize; // 大小
} WaveFormatEx;
6)strd块与strn块
strd:可选的额外的头信息数据**strn:可选的流的名字
这两个块是可选的,本AVI文件不包含,故不分析。
info列表
该list用于描述编码该AVI文件的程序信息,包含一个isft块。
junk块
一些垃圾填充数据,用于内部数据的队齐(填充),直接跳过。
movi列表
idx1表
该块是可选的,描述音视频数据的索引块信息,在AVIMainHeader的dwFlags中指出是否包含索引块。有了索引块可以方便文件快进,如果没有索引块,在对AVI进行快进时需要计算位置,会很耗时。索引块可用如下结构体表示:
// 索引节点信息
typedef struct
{
DWORD dwChunkId; // 本数据块的四字符码(00dc 01wb)
DWORD dwFlags; // 说明本数据块是不是关键帧、是不是‘rec ’列表等信息
DWORD dwOffset; // 本数据块在文件中的偏移量
DWORD dwSize; // 本数据块的大小
} AVIIndexEntry;
FLV
简介
flv是什么格式的?FLV是一种常见的流媒体格式,全称为Flash Video。它是由Adobe公司开发的一种视频文件格式,广泛应用于网络视频播放和流媒体传输领域。总之,FLV格式是一种非常实用和常见的流媒体视频格式,具有较高的压缩比例和优秀的视频质量。在当前互联网上,FLV格式已经成为了网络视频播放和在线直播等领域的标准格式之一。
FLV文件格式
Flv由文件头(File Header)和 文件体(File Body)组成。
Flv Body由一系列的Tag组成,每个Tag又有一个preTagSize字段,标记着前面一个Tag的大小。
一般一个flv文件由一个头部信息,一个script Tag,以及若干个video Tag和audio Tag组成。
FLV Header
FLV Body
Flv Body由一个一个Tag组成,每个Tag都有一个preTagSize字段,标记着前面一个Tag的大小。
Tag : 类型包含音频audio、视频video、脚本scripts、可选加密元数据optional encryption metadata、 payload.
每个Tag由“Tag Header”和“Tag Data”组成,对于不同类型的Tag,“Tag Header”的格式都是相同的,“Tag Body”的格式就不一样了。
Flv Tag:
FLV Tag | Field | Type | Comment | |
---|---|---|---|---|
Tag Header | TagType | UI8 | Tag的类型,音频(0x08),视频(0x09),script data(0x12) | |
DataSize | UI24 | 表示Tag Data数据的大小 | ||
TimeStamp | UI24 | 表示该Tag的时间戳 | ||
TimeStamp Extented | UI8 | 时间戳的扩展位,当24位不够用时,该字节为最高字节,将时间戳扩展至32位 | ||
StreamID | UI24 | 总是为0 | ||
Tag Data | 不同类型的Tag,Tag Data部分数据格式不同 |
video tag:
audio tag:
script tag:
TS
简介
TS视频封装格式,是一种被广泛应用的多媒体文件格式。它的全称是MPEG2-TS,其中TS是“Transport Stream”的缩写。TS(Transport Stream)流是一种传输流,它由固定长度(188 字节)的 TS 包组成,TS 包是对PES包的一种封装方式,此外还有另一种封装形式是PS。PS(Program Stream)流是一种节目流,PS流由PS包组成,而一个PS包又由若干个PES包组成。
TS和PS的区别在于:TS格式主要应用于实时传送的节目流中,比如实时广播的电视节目;而PS格式主要应用于存储具有固定时长的节目文件,比如DVD电影。
文件结构概述
(1)TS流最初的作用是传输音视频数据,应用在电视广播系统,但是在直播、点播场景时,通常需要将音视频数据以".ts"的文件格式进行落盘,本文会重点介绍".ts"的封装格式。
(2)TS文件的基本单位是ts packet,在同一个标准中ts packet的大小是固定的,便于找到帧的起止位置,易于从包丢失中恢复,适合于有误码的环境,可在网络中进行远距离的传送;在不同标准中,ts packet的大小也不相同,共有有四种大小:
(1)188 bytes:MPEG-2标准(本文会基于MPEG-2的标准去讨论ts packet)
(2)192 bytes:188 bytes + 4 bytes时间码 --> 日本DVH-S标准
(3)204 bytes:188 bytes + 16 bytes前向纠错码(FEC) --> 美国ATSC标准
(4)208 bytes:188 bytes + 4 bytes时间码 + 16 bytes前向纠错码(FEC)
:::info
TS码流由于采用了固定长度的包结构,当传输误码破坏了某一TS包的同步信息时,接收机可在固定的位置检测它后面包中的同步信息,从而恢复同步,避免了信息丢失。因此,在信道环境较为恶劣,传输误码较高时,一般采用TS码流。由于TS码流具有较强的抵抗传输误码的能力,因此目前在传输媒体中进行传输的MPEG-2码流基本上都采用了TS码流的包格式。
:::
(3) 每一个ts packet的内部一定会有ts packet header,有可能会存在填充数据adaptation field和ts payload。ts packet header固定是4字节,ts packet payload大小不固定,如果ts packet payload不足184字节,需要填充数据adaptation field。如果ts packet payload是184字节则没有填充数据adaptation field。
(4)ts packet中携带两类信息:已压缩的音视频(PES、ES)和与之相关的符号化表(PSI)包括PAT和PMT,由包的PID来识别携带的是哪种信息。
(1)PAT:Program Association Table的简称,节目关联表。是接收数据的入口点,解析TS文件的起点。PAT包含所有频道编号(PID),比如共有CCTV1-CCTV14这些频道,通过读取PAT就会获取上述所有频道的编号(PID)。通过频道编号(PID)可以找到频道对应的PMT。
(2)PMT:Program Map Table的简称,节目映射表。连接节目号和节目元素的桥梁。PMT描述频道的具体信息,一个频道对应一个PMT,有几个频道就有几个PMT表。比如CCTV1对应一个PMT,CCTV2对应另一个PMT,CCTV1-CCTV14会对应14个PMT。
(3)PES:是在每一个视频/音频帧的基础上增加了pes header,形成了PES packet(pes header + es),pes header中最重要的就是PTS、DTS信息。
(4)ES:就是音视频裸数据了,常用的音频编码格式为AAC,和MP3 。视频编码格式为H.264和HEVC。其数据结构可以分别参考相应的编码规范手册。
(5)ts文件的结构如下图所示:
PAT PMT PMT PMT DATA DATA …DATA PAT PMT PMT PMT DATA DATA…
1、ts文件由一个个ts packet组成,在MPEG-2标准中ts packet的大小固定是188 bytes。
2、ts文件的第一个ts packet是PAT,描述所有节目。第二个ts packet是PMT,有几个节目就有几个ts packet存储PMT,然后才是音视频数据。正常情况下ts文件的第一帧一定是I帧。这样才能正常播放。
3、分析ts文件时发现,ts文件中往往不仅仅是一组PAT,PMT。这要从ts文件的生成说起,ts文件的生成主要有2种场景,一种是HLS流的落盘,另一种是其它文件转封装成ts。在HLS中,PAT和PMT是循环发送的,所以ts文件会有多组PAT、PMT。其它文件转封装成ts时,转封装的工具也会循环的写PAT、PMT。
4、正常情况下ts文件的第一组PAT、PMT后面是的第一帧数据是I帧。后续的PAT、PMT后面的帧不一定是I帧(可通过ffplay xx.ts -loglevel trace分析出来),此时通过PAT、PMT找到的音视频数据,如果不是I帧,也可以通过前面收到的sps、pps的数据进行解码,并结合前面收到的I帧还原出图像。
Ts Packet(Transport Stream Packet)
(1)每一个ts packet的内部一定会有ts packet header,有可能会存在填充数据adaptation field和ts payload。ts packet header固定是4字节,ts packet payload大小不固定。视频流和音频流都需要加adaptation field,通常加在一个帧的第一个ts包和最后一个ts包里,中间的ts包不加,第一个ts包和最后一个ts包里的adaptation field还不一样。adaptation field主要内容如下:
Field | Type | Comment |
---|---|---|
adaptation_field_length (填充数据长度) | 8 bit | 填充数据长度标识,表示此字节后面填充数据的长度。其值在0~183 bytes。从上图的官方定义中可以看出,无论是否有填充数据,此字段一定存在。 adaptation_field_length = 0~182:adaptation_field_control = 11,既有填充数据,也有有效载荷。 adaptation_field_length = 183:adaptation_field_control = 10,只有填充数据(此时adaptation_field_length后面占183 bytes,adaptation_field_length占1 byte,ts header占4 bytes)。 |
PCR_flag (PCR标志位) | 1 bit | PCR_flag = 0:没有PCR。 PCR_flag = 1:有PCR。 |
program_clock_reference_base (节目时钟参考PCR) | 42 bit | 音频、视频都可以通过pcr来设置时钟,保证音视频同步。但是很多播放器都不通过pcr来同步,都是以音频为基准来设置时钟。 |
stuffing_bytes (填充字节) | Nx8 bit | 填充字节,取值0xff。只填充用,无实际意义。 |
(2)ts payload如果存在则其内容是PAT、PMT、PES、ES的其中一种,ts payload也有可能不存在,此时ts packet只有ts header 和 adaptation field。ts packet是188 bytes,ts header是4 bytes,所以 ts payload最多是184 bytes。
Field | Type | Comment |
---|---|---|
data_byte (数据) | 0~184 bytes | ts payload。 |
PAT(Program Association Table)
(1)节目关联表,定义了当前TS流中所有的节目,其PID为0x0000,它是PSI的根节点,要查找节目(获取音视频数据)必须从PAT开始。当播放器对视频开始检索分析的时候,针对每个TS 包的header中PID数据进行判断,直到找到PAT表开始的地方进行有效数据起始分析。
Field | Type | Comment |
---|---|---|
table_id (表id) | 8 bit | 标识一个TS PSI分段的内容是节目关联分段,条件访问分段还是节目映射分段。对于PAT置为0x00。 |
section_syntax_indicator (段语法标志位) | 1 bit | 固定为1(官方解释: The section_syntax_indicator is a 1-bit field which shall be set to ‘1’. )。 |
0 | 1 bit | 0。 |
reversed (保留位) | 2 bit | 固定为11(每一位都是1,占2 bit所以是11)。 |
section_length (分段长度) | 12 bit | section_length后面直到CRC_32校验字段的字节数,其值不超过1021。 |
transport_stream_id (传输流id) | 16 bit | 其值由用户规定。该字段充当标签,标识网络内此传输流有别于任何其他多路复用流。 |
version_number (版本号) | 5 bit | current_next_indicator 设置为‘1’时,version_number 必须为当前有效的节目相关表的版本号。current_next_indicator 设置为‘0’时,version_number 为下一个有效的节目相关表的版本号。 |
current_next_indicator (指示符) | 1 bit | current_next_indicator = 1:发送的节目相关表为当前有效的。 current_next_indicator = 0:发送的该表尚未有效并且下一个表将生效。 |
section_number (分段号) | 8 bit | 表明该ts packet属于PAT的第几个分段,分段号从0开始。因为PAT可以描述很多PMT信息,所以长度可能比较长,ts packet的长度最多是188bytes,所以可能需要多个ts packt传输一个PAT。 |
last_section_number (最后一个分段号) | 8 bit | PAT最后的一个分段到序号(分段原因可参考"section_number"),也可以理解为PAT的最大分段数目,一般情况都是一个PAT表由一个ts packet传输 |
开始循环 | ||
program_number (节目编号) | 16 bit | 节目号为0x0000时表示这是NIT(network_PID),节目号为非0x0000时,表示这是PMT(program_map_PID) |
network_PID (网络信息表PID) | 13 bit | NIT(网络信息表)的PID值,指定应包含的传输流包的PID。network_PID 的值由用户自定义。用于描述整个网络,如多少TS流、频点和调制方式等信息(jsmpeg系列二 基础知识 TS码流 PAT PMT) |
program_map_PID (节目映射表PID) | 13 bit | PMT(节目映射表)的PID值,program_map_PID 的值由用户定义,但仅限于取表2-3 中所指定的值 |
结束循环 | ||
CRC_32 (校验码) | 32 bit | 校验值 |
PMT(Program Map Table)
节目映射表,该表的PID是由PAT给出的。PMT数据的信息可以理解为这个节目包含的音频和视频信息。其中包含了该路节目由那些流构成,流的类型(视频、音频、数据等)指定节目中视频、音频对应的ID,和当前频道关联在一起的其它数据PID(例如该节目的PCR所对应的PID)。
Field | Type | Comment |
---|---|---|
table_id (表id) | 8 bit | 标识一个TS PSI分段的内容是节目关联分段,条件访问分段还是节目映射分段。对于PMT置为0x02 |
section_syntax_indicator (段语法标志位) | 1 bit | 固定为1 |
0 | 1 bit | 0 |
eserved (保留位) | 2 bit | 固定为11(每一位都是1,占2 bit所以是11) |
section_length (分段长度) | 12 bit | section_length后面直到CRC_32校验字段的字节数,其值不超过1021 |
program_number (节目编号) | 16 bit | 指定program_map_PID 所适用的节目。一个节目定义必须仅在一个TS_program_map_section 内承载。这意味着节目定义从不超过1016(0x3F8) |
version_number (版本号) | 5 bit | 为TS_program_map_section 的版本号。当分段内承载的信息发生改变时,版本号应增1 模32。版本号涉及单个节目的定义,并因此涉及单个分段。当current_next_indicator为‘1’时,version_number 应为当前有效的TS_program_map_section 的version_number。current_next_indicator设置为‘0’时,version_number 应为下一个有效的TS_program_map_section 的version_number |
current_next_indicator (指示符) | 1 bit | 于‘1’时指示发送的节目相关表为当前有效的。该比特设置为‘0’时,它指示发送的该表尚未有效并且下一个表将生效 |
section_number (分段号) | 8 bit | 固定值为0x00 |
last_section_number (最后一个分段号) | 8 bit | 固定值为0x00 |
reserved (保留位) | 3 bit | 固定为111(每一位都是1,占3 bit所以是111) |
PCR_PID (PCR_PID) | 13 bit | 指示应包含PCR字段的ts packet的PID |
reserved (保留位) | 4 bit | 固定为1111(每一位都是1,占4 bit所以是1111) |
program_info_length (节目描述信息长度) | 12 bit | 表示紧跟在program_info_length后面的N个descriptor()的总长度 |
开始循环 | ||
descriptor() (描述信息) | 节目元素描述符,详见官方文档 | |
循环结束 | ||
开始循环 | ||
stream_type (流类型) | 8 bit | 流类型,标志是Video还是Audio还是Metadata或其它数据 |
reserved (保留位) | 3 bit | 固定为111(每一位都是1,占3 bit所以是111) |
elementary_PID (元素PID) | 13 bit | 指定携带相关元素的ts packet的PID;如果stream_type是video,则elementary_PID表示的是视频包的pid |
reserved (保留位) | 4 bit | 固定为1111(每一位都是1,占结束循环4 bit所以是1111) |
ES_info_length (ES信息长度) | 12 bit | 表示紧跟在ES_info_length后面的N2个descriptor()的总长度 |
开始循环 | ||
descriptor() (描述信息) | 用于描述节目内容,有视频和音频两种形式,描述了原始流的一些信息。详见下文 | |
结束循环 | ||
结束循环 | ||
CRC32 (校验码) | 32b | 校验值 |
上表中的descriptors()也有很多种,具体可查阅官方文档。本文重点介绍video/audio descriptor,内容如下:
-
Video stream descriptor:提供了标识视频元素的编码参数的基本信息。
| Field | Type | Comment |
| — | — | — |
| descriptor_tag | 8 bit | 描述descriptor类型,共有40多种类型,可详见官方文档。比如descriptor_tag = 2是video_stream_descriptor descriptor_tag = 3是audio_stream_descriptor |
| descriptor_length | 8 bit | descriptor_length后面的字节数 |
| multiple_frame_rate_flag | 1 bit | multiple_frame_rate_flag = 1:视频流中可能存在多个帧速率。 multiple_frame_rate_flag = 0:视频流中仅存在单个帧速率 |
| frame_rate_code | 4 bit | 帧率 |
| MPEG_1_only_flag | 1 bit | MPEG_1_only_flag = 1:表示视频流仅包含ISO/IEC 11172-2数据。
MPEG_1_only_flag = 0:表示视频流可以包含ITU-T Rec.H.22|ISO/IEC 13818-2视频数据和约束参数ISO/IEC 11172-2视频数据 |
| constrained_parameter_flag | 1 bit | constrained_parameter_flag = 1:表示视频流不应包含不受约束的ISO/IEC 11172-2视频数据。如果MPEG_1_only_flag设置为“0”,则constrained_parameter_flag应设置为“1”。
constrained_parameter_flag = 0:视频流可以包含受约束的参数和不受约束的ISO/IEC 11172-2视频流。 |
| still_picture_flag | 1 bit | still_picture_flag = 1:表示视频流仅包含静止图片。
still_picture_flag = 0:表示视频流可能包含运动或静止图像数据 |
| profile_and_level_indication | 8 bit | 指明profile和leve |
| chroma_format | 2 bit | 采样格式,比如01表示4:2:0 |
| frame_rate_extension_flag | 1 bit | frame_rate_extension_flag = 1时在 ITU-T Rec. H.262 | ISO/IEC 13818-2视屏流中,frame_rate_extension_n、frame_rate_extension_d都是非零值
无论frame_rate_extension_flag为何值ISO/IEC 11172-2视频流的两个字段均设置为零 |
| Reserved | 5 bit | 保留位,固定为11111(每一位都是1,占5 bit所以是11111) | -
Audio stream descriptor:音频流描述符提供识别音频基本流的编码版本的基本信息.
| Field | Type | Comment |
| — | — | — |
| descriptor_tag | 8 bit | 描述descriptor类型,共有40多种类型,可详见官方文档。比如descriptor_tag = 2是video_stream_descriptor descriptor_tag = 3是audio_stream_descriptor |
| descriptor_length | 8 bit | descriptor_length后面的字节数 |
| free_format_flag | 1 bit | free_format_flag = 1:表示音频流可能包含一个或多个bitrate_index设置为“0000”的音频帧。
free_format_flag = 0:则在音频流的任何音频帧中,bitrate_index都不是“0000”(参考ISO/IEC 13818-3的2.4.2.3) |
| ID | 1 bit | ID = 1:表示在音频流中的每个音频帧中ID字段设置为“0”(参见ISO/IEC 13818-3的2.4.2.3) |
| layer | 2 bit | 与层字段相同的方式编码。此字段中指示的层应等于或高于音频流的任何音频帧中指定的最高层 |
| variable_rate_audio_indicator | 1 bit | variable_rate_audio_indicator = 0:表示比特率字段的编码值在连续音频帧中不应改变,该连续音频帧旨在无中断地呈现 |
| reserved | 3 bit | 保留位,固定为111(每一位都是1,占3 bit所以是111) |
在PMT表中,有三个循环,循环次数分别是N,N1,N2,官方文档中没有描述这3个数的取值,那么这3个值是如何确定的呢?
(1)N = program_info_length/(1+1+descriptor_length) 字节
分子:program_info_length描述循环的总字节数。
分母:前2个加1是因为descriptor_tag,descriptor_length分别占1字节。descriptor_length描述后面的字节数,所以1个descriptor()占的字节数就是1+1+descriptor_length。
(2)N1 = (section_length-9-program_info_length-4)/(5+ES_info_length) 字节
分子:根据定义section_length的值是表示last_section_number到CRC_32的字节数,减9是last_section_number到program_info_length的占9字节,减program_info_length是紧跟在后面的循环占的字节数,减4是CRC_32占4字节。
分母:加5是stream_type到ES_info_length占的字节数,加ES_info_length是紧跟在后面的循环占的字节数。
(3)N2 = ES_info_length/(1+1+descriptor_length) 字节
分子:ES_info_length描述循环的总字节数。
分母:前2个加1是因为descriptor_tag,descriptor_length分别占1字节。descriptor_length描述后面的字节数,所以1个descriptor()占的字节数就是1+1+descriptor_length。
PES(Packetized Elementary Stream)
1、pes是对编码器原始数据的第一次打包,在这个过程中将es流分组、打包、加入包头信息等操作,其中加入的最主要的信息就是dts,pts。pes流的基本单位是pes packet,pes packet由pes packet header和playload组成。
2、一般视频一帧被打包成一个pes packet,一个pes packet的长度一般都大于ts packet的188字节,所以还是要进行切分,一个pes packet会被拆分成几部分,由多个ts packet携带。此时,只有携带第一个pes packet分组的ts packet才会有pes header,后面的ts packet只有es数据和填充字节,即不是每一个携带音视频数据的ts packet都有pes的打包数据(pes header)。
3、MPEG-2规定一个pes packet必须由整数个ts packet传输,如果承载一个pes packet的最后一个ts packet没有被装满,则用 adaptation field(填充数据)进行填充,如下所示:
第一个ts packet:ts header + (adaptation field) + pes header + 部分es
第二个ts packet:ts header + 部分es
…
最后一个ts packet:ts header + adaptation field(填充数据)+ 部分es
第一个ts packet如果有adaptation field则包含了同步时钟PCR_flag=1,最后一个ts packet的adaptation field是填充数据,没有同步时钟PCR_flag=0。
(1)pes packet header
Field | Type | Comment |
---|---|---|
packet_start_code_prefix (分组起始前缀字段) | 24 bit | 固定为0x000001 |
stream_id (流标识字段) | 8 bit | 它规定了基本流的号码和类型 |
PES_packet_length (PES包长度) | 16 bit | PES_packet_length后面的字节数目。值0表示PES分组长度既没有指定也没有限制 |
PTS_DTS_flags (PTS DTS标志) | 2 bit | PTS_DTS_flags = 10:只有PTS。 PTS_DTS_flags = 11:PTS、DTS都有。 PTS_DTS_flags = 00:PTS、DTS都没有。 禁止使用01 |
marker_bit (标志位) | 1 bit | 固定为1 |
PTS (显示时间) | 33 bit | 显示时间戳,分为3段 |
DTS (解码时间) | 33 bit | 解码时间戳,分为3段 |
ES_rate (ES接收速率) | 22 bit | 指定编码器接收pes packet字节的速率 |
trick_mode_control (特技模式控制) | 3 bit | 表示相关视频的特技方式,包括快进、慢动作、冻结帧、快速反向、慢反向等 |
(2)pes payload
Field | Type | Comment |
---|---|---|
PES_packet_data_bytes (PES包数据) | 8*PES_packet_length bit | 音视频数据,由stream_id或PID指示 |
ES(Elementary Stream)
1、es才是纯真正音视频数据,裸流,不带pts,类似H264编码的原始数据NALU或者音频AAC等编码原始数据。会有nalu header或adts header。包括视频、音频、sps、pps 等。
2、I帧时,如下图所示
解析过程
TS流生成过程
视频播放原理
视频播放器简介
视频播放器播放一个本地文件(或者互联网上的文件),需要经过一下几个步骤:
- 解协议
- 解封装
- 解码音
- 音视频同步
注意:本地文件也是一种协议
解协议
将流媒体协议的数据,解析为标准的相应的封装格式数据。音视频在网络上传播的时候,常常采用各种流媒体协议,例如 HTTP,RTMP,或是 MMS 等等。这些协议在传输视音频数据的同时,也会传输一些信令数据。这些信令数据包括对播放的控制(播放,暂停,停止),或者对网络状态的描述等。解协议的过程中会去除掉信令数据而只保留视音频数据。例如,采用 RTMP 协议传输的数据,经过解协议操作后,输出 FLV 格式的数据。
解封装
将输入的封装格式的数据,分离成为音频流压缩编码数据和视频流压缩编码数据。封装
格式种类很多,例如 MP4,MKV,RMVB,TS,FLV,AVI 等等,它的作用就是将已经压缩编码的视频数据和音频数据按照一定的格式放到一起。
例如,FLV 格式的数据,经过解封装操作后,输出 H.264 编码的视频码流和 AAC 编码的音频码流。
编码
将视频/音频压缩编码数据,解码成为非压缩的视频/音频原始数据。
音频的压缩编码标准包含 AAC,MP3,AC-3 等等,视频的压缩编码标准则包含 H.264,MPEG2,VC-1 等等。解码是整个系统中最重要也是最复杂的一个环节。通过解码,压缩编码的视频数据输出成为非压缩的颜色数据,例如 YUV420P,RGB 等等;压缩编码的音频数据输出成为非压缩的音频抽样数据,例如 PCM 数据。
音视频
根据解封装模块处理过程中获取到的参数信息,同步解码出来的视频和音频数据,并将视频音频数据送至系统的显卡和声卡播放出来。
视频转码原理
视频转码
视频转码是指将已经压缩编码的视频码流转换成另一个视频码流,以适应不同的网络带宽、不同的终端处理能力和不同的用户需求。
转码本质上是一个先解码,再编码的过程,因此转换前后的码流可能遵循相同的视频编码标准, 也可能不遵循相同的视频编码标准。
视频转码技术
视频转码技术使用的目的不同,其实现的手段也各不相同。大致上可以分为两类:
①、不同编码格式之间的视频数据转码
不同编码格式之间的数据转码,指通过转码方法改变视频数据的编码格式。通常这种数据转码会改变视频数据的现有码流和分辨率。
例如我们可以将基于 MPEG-2 格式的视频数据转换为 DV 、MPEG-4 或其它编码格式,同时根据其转码目的,指定转码产生视频数据的码流和分辨率。
这种转码方式设计的算法较为复杂,其实质上是一个重新编码的过程,涉及的算法复杂度和系统开销,是由转码所需图像质量要求及转码前后两种编码方式的相关度所决定的。②、相同编码格式之间的视频数据转码
相同编码格式的数据转码,指不改变压缩格式,只通过转码手段改变其码流或头文件信息。
根据其使用目的, 可分为改变码流和不改变码流两种。
如我们可以将 MPEG-2 全 I 帧 50Mbps 码流的视频数据转码为 MPEG-2 IBBP 帧 8Mbps 码流的视频数据,直接用于播出服务器用于播出。
非线性编辑
非线性编辑是借助计算机来进行数字化制作,几乎所有的工作都在计算机里完成,不再需要那么多的外部设备,对素材的调用也是瞬间实现,不用反反复复在磁带上寻找,突破单一的时间顺序编辑限制,可以按各种顺序排列,具有快捷简便、随机的特性。
非线性编辑只要上传一次就可以多次的编辑,信号质量始终不会变低,所以节省了设备、人力,提高了效率。
:::info
传统线性视频编辑是按照信息记录顺序,从磁带中重放视频数据来进行编辑,需要较多的外部设备,如放像机、录像机、特技发生器、字幕机,工作流程十分复杂。
非线性编辑系统是指把输入的各种视音频信号进行 A/D(模/数)转换,采用数字压缩技术将其存入计算机硬盘中。
非线性编辑没有采用磁带,而是使用硬盘作为存储介质,记录数字化的视音频信号,由于硬盘可以满足在 1/25s(PAL) 内完成任意一副画面的随机读取和存储,因此可以实现视音频编辑的非线性。
:::