ts文件(或ts流)是一种常见的视频封装格式。
在了解ts之前,简要介绍下封装和编码。
封装,也叫多路复用(mux)。封装的目的一般为了在一个文件(流)中能同时存储视频(video)、音频(audio)、字幕(subtitle)等内容——这也正是“复用”的含义所在(分时复用)。封装还有另一个作用是在网络环境下确保数据的可靠快速传输
编码的目的是为了压缩媒体数据。有别于通用文件数据的压缩,在图像或音频压缩的时候,可以借助图像特性(如前后关联、相邻图块关联)或声音特性(听觉模型)进行压缩,可以达到比通用压缩技术更高的压缩比。
es
即Elementary Stream,直译为基本码流。由编码器编码输出的数据即es,如,对于H264,就是一个个NALU(Network Abstract Layer Unit)。
更通用的说法是es由一个个AU(Access Unit)组成,一个es流中只包含一种类型的数据(音频、或视频、或字幕等)。
在ffmpeg中通过AVPacket的data获取到的就是es数据;在android的MediaCodec解码时传入的也是es数据;H264的JM解码器(ldecod)要求传入的也是es数据。
pes
pes,即Packetized Elementary Stream(打包的es)。是在es基础上按如下图格式添加pes头、pes可选头后组成。
一个pes包内也是只能包含一种类型的数据。(但是pes作为一个“单元”,多个pes可以交替排列不同类型的数据,这就是“复用”)
stream id用于标识这个PES包携带的数据类型(specifies the type and number of the elementary stream)。也有一些预设的值表示特定用途。
stream_id -- In Program Streams, the stream_id specifies the type and number of the elementary stream as defined by the stream_id table 2-19. In Transport Streams, the stream_id may be set to any valid value which correctly describes the elementary stream type as defined in table 2-19. In Transport Streams, the elementary stream type is specified in the Program Specific Information as specified in 2.4.4 on page 44.
packet length表示其后的数据长度,最大2^16-1,即65535
PES_packet_length -- A 16 bit field specifying the number of bytes in the PES packet following the last byte of the field. A value of 0 indicates that the PES packet length is neither specified nor bounded and is allowed only in PES packets whose payload is a video elementary stream contained in Transport Stream packets.
ts
ts,即transport stream,传输流。
每个ts包固定188字节,是在pes的基础上加入ts头组成。(需要注意的是一个ts包中的payload不一定是一个完整的pes包)。
一个个ts包组成的序列就是一个ts文件。(也可以通过http、rtsp等协议进行网络串流)。
在蓝光格式中,对ts进行了额外扩展,称为m2ts。m2ts在ts的头前加入额外4字节的时间戳。
ps,program stream,节目流。与ts类似,也是在pes的基础上打包得到,所不同的是pes的包长不固定。
之所以要设计ts和ps两种不同的格式,是考虑了不同的应用场景。在信道环境较为恶劣、传输误码较高时,一般采用 TS 码流,而在信道环境较好、传输误码较低时一般采用 PS 码流(因为ts是固定包长,在数据出错丢失后,很容易在固定位置通过检测同步信息重新恢复同步)。