Loading [MathJax]/jax/input/TeX/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >多媒体文件格式剖析:TS篇

多媒体文件格式剖析:TS篇

作者头像
马上就说
发布于 2020-12-11 07:26:54
发布于 2020-12-11 07:26:54
5.3K0
举报
文章被收录于专栏:码上就说码上就说

前情提要

我记得之前在多媒体文件格式剖析:M3U8篇中讲解了什么是流式视频,什么不是流式视频?其实有一个更简单更明确的解释,能够用于直播的格式是流式视频格式,反之则不是。

现在我们回看一下,MP4封装格式是不能用于直播的,当然因为MP4的BOX结构并不适用于直播,那么FLV和M3U8就是妥妥为直播而生的,我们平时看直播的时候从中间任何一个时间点进入都是可以播放的,说明流式视频格式是没有冗余的封装部分的,它所包含的必定是简洁的、直观的用于解析播放的数据。

之前分享过M3U8格式,我们知道M3U8是有一个一个TS分片数据组成的,现在我们就要研究一下TS的格式。


TS介绍

TS是一种音视频封装格式,全称为MPEG2-TS。其中TS即"Transport Stream"的缩写。

从上面分析已经获知TS是流式格式,所以MPEG2-TS格式的特点就是要求从视频流的任一片段开始都是可以独立解码的。

我们可以看出,TS格式是主要用于直播的码流结构,具有很好的容错能力。通常TS流的后缀是.ts、.mpg或者.mpeg,多数播放器直接支持这种格式的播放。TS流中不包含快速seek的机制,只能通过协议层实现seek。HLS协议基于TS流实现的。


TS格式分析

TS文件(流)可以分为三层:TS层(Transport Stream)、PES层(Packet Elemental Stream)、ES层(Elementary Stream)。

ES层就是音视频数据,PES层是在音视频数据上加了时间戳等对数据帧的说明信息,TS层是在PES层上加入了数据流识别和传输的必要信息。TS文件(码流)由多个TS Packet组成的。

下图是TS文件(码流)的分层结构图:

  • TS层

TS包大小固定为188字节,TS层分为三个部分:TS Header、Adaptation Field、Payload。

TS Header固定4个字节;Adaptation Field可能存在也可能不存在,主要作用是给不足188字节的数据做填充;Payload是PES数据。

1.TS Header

TS包的包头提供关于传输方面的信息。

TS包的包头长度不固定,前4个字节是固定的,后面可能跟有自适应字段(适配域)。4个字节是最小包头。包头的结构体字段如下:


sync_byte(同步字节):固定为0x47;该字节由解码器识别,使包头和有效负载可相互分离。

ransport_error_indicator(传输错误标志):’1‘表示在相关的传输包中至少有一个不可纠正的错误位。当被置1后,在错误被纠正之前不能重置为0。

payload_unit_start_indicator(负载起始标志):为1时,表示当前TS包的有效载荷中包含PES或者PSI的起始位置;在前4个字节之后会有一个调整字节,其的数值为后面调整字段的长度length。因此有效载荷开始的位置应再偏移1+[length]个字节。

transport_priority(传输优先级标志):‘1’表明当前TS包的优先级比其他具有相同PID, 但此位没有被置‘1’的TS包高。

PID:指示存储与分组有效负载中数据的类型。

transport_scrambling_control(加扰控制标志):表示TS流分组有效负载的加密模式。空包为‘00’,如果传输包包头中包括调整字段,不应被加密。其他取值含义是用户自定义的。

adaptation_field_control(适配域控制标志):表示包头是否有调整字段或有效负载。‘00’为ISO/IEC未来使用保留;‘01’仅含有效载荷,无调整字段;‘10’ 无有效载荷,仅含调整字段;‘11’ 调整字段后为有效载荷,调整字段中的前一个字节表示调整字段的长度length,有效载荷开始的位置应再偏移[length]个字节。空包应为‘10’。

continuity_counter(连续性计数器):随着每一个具有相同PID的TS流分组而增加,当它达到最大值后又回复到0。范围为0~15。

2.TS Adaptation Field

Adaptation Field的长度要包含传输错误指示符标识的一个字节。

PCR是节目时钟参考,PCR、DTS、PTS都是对同一个系统时钟的采样值,PCR是递增的,因此可以将其设置为DTS值,音频数据不需要PCR。

打包TS流时PAT和PMT表是没有Adaptation Field的,不够的长度直接补0xff即可。

视频流和音频流都需要加adaptation field,通常加在一个帧的第一个ts包和最后一个ts包里,中间的ts包不加。

3.TS Payload

TS包中Payload所传输的信息包括两种类型:视频、音频的PES包以及辅助数据;节目专用信息PSI。

TS包也可以是空包。空包用来填充TS流,可能在重新进行多路复用时被插入或删除。

视频、音频的ES流需进行打包形成视频、音频的 PES流。辅助数据(如图文电视信息)不需要打成PES包。

  • PES层

PES结构如上图。PES层是在每一个视频/音频帧上加入了时间戳等信息,PES包内容很多,下面我们说明一下最常用的字段:

  • pes start code:开始码,固定为0x000001。
  • stream id:音频取值(0xc0-0xdf),通常为0xc0;视频取值(0xe0-0xef),通常为0xe0。
  • pes packet length:后面pes数据的长度,0表示长度不限制,只有视频数据长度会超过0xffff。
  • pes data length:后面数据的长度,取值5或10。
  • pts:33bit值
  • dts:33bit值

关于时间戳PTS和DTS的说明:

  • PTS是显示时间戳、DTS是解码时间戳。
  • 视频数据两种时间戳都需要,音频数据的PTS和DTS相同,所以只需要PTS。

有PTS和DTS两种时间戳是B帧引起的,I帧和P帧的PTS等于DTS。如果一个视频没有B帧,则PTS永远和DTS相同。

从文件中顺序读取视频帧,取出的帧顺序和DTS顺序相同。DTS算法比较简单,初始值 + 增量即可,PTS计算比较复杂,需要在DTS的基础上加偏移量。

音频的PES中只有PTS(同DTS),视频的I、P帧两种时间戳都要有,视频B帧只要PTS(同DTS)。

  • ES 层

ES层指的就是音视频数据。一般的,视频为H.264视频,音频为AAC音频。


TS流生成及解析流程

1.TS 流生成流程

  • 将原始音视频数据压缩之后,压缩结果组成一个基本码流(ES)。
  • 对ES(基本码流)进行打包形成PES。
  • 在PES包中加入时间戳信息(PTS/DTS)。
  • 将PES包内容分配到一系列固定长度的传输包(TS Packet)中。
  • 在传输包中加入定时信息(PCR)。
  • 在传输包中加入节目专用信息(PSI) 。
  • 连续输出传输包形成具有恒定比特率的MPEG-TS流。

2. TS 流解析流程

  • 复用的MPEG-TS流中解析出TS包;
  • 从TS包中获取PAT及对应的PMT;
  • 从而获取特定节目的音视频PID;
  • 通过PID筛选出特定音视频相关的TS包,并解析出PES;
  • 从PES中读取到PTS/DTS,并从PES中解析出基本码流ES;
  • 将ES交给解码器,获得压缩前的原始音视频数据。
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-04-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 音视频平凡之路 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Jekyll搭建博客并部署到GitHub
尝试过很多Windows搭建静态网页博客的方法,都是失败告终。试了几次Jekyll,这一次终于成功了。想把一些坑路分享一下。
繁华是客
2023/03/03
1.2K0
Ruby 应用容器封装踩坑记录(Lobsters)
本文使用「署名 4.0 国际 (CC BY 4.0)」许可协议,欢迎转载、或重新修改使用,但需要注明来源。 署名 4.0 国际 (CC BY 4.0)
soulteary
2020/03/22
5.5K0
Ruby 应用容器封装踩坑记录(Lobsters)
Ruby on Rails 基础(5)
其实就是一捆gems Tip: 查看本地有哪些 gem ,可以通过如下方式 [root@h202 ruby]# gem list *** LOCAL GEMS *** actionmailer (4.2.6) actionpack (4.2.6) actionview (4.2.6) activejob (4.2.6) ... ... rdoc (4.2.1) rvm (1.11.3.9) sprockets (3.6.0) sprockets-rails (3.0.4) test-unit (3.1.
franket
2021/11/25
1.2K0
Ruby on Rails 基础(6)
没有创建成功,但是反馈结果却是成功 (说明这是一批命令,最后一个反馈结果正常),并且生成一个文件目录
franket
2021/11/25
2.2K0
Jekyll 运行的时候提示错误 cannot load such file -- webrick (LoadError)
这是因为: 从 Ruby 3.0 开始 webrick 已经不在绑定到 Ruby 中了,请参考链接: Ruby 3.0.0 Released 中的说明。
HoneyMoose
2021/10/27
6780
Jekyll 运行的时候提示错误 cannot load such file -- webrick (LoadError)
Jekyll 搭建静态博客
一直以来都想搭建一个自己的博客,但是近半年做项目太忙,再加上教研室的网络很坑爹,所以也一直没顾得上。之前用过 WordPress 托管在免费的京东云擎上,但是速度太慢。在知乎上看到一些相关的内容,于是选择了在github上用jekyll搭建博客。
零式的天空
2022/03/21
5620
Jekyll 搭建静态博客
听说你想要部署 Octopress?满足你
Octopress 是一个面向开发者的博客系统,广受程序员的喜爱。既然大家有需求,那么 Octopress 也要安排上~
腾讯云开发TCB
2020/06/03
1.1K0
Portable Jekyll-最便捷的JEKYLL安装
建议不要把 ruby 放到 Github Page Folder 中,否则会在 build 的时候会报以下错误
szhshp
2022/09/21
3920
2020年3月27日,Github被攻击。我的GitPage博客也挂了,紧急修复之路
万万没想到!Github 竟然受到攻击了!还能让我使用了 GitPage 的博客瘫痪了!
小傅哥
2020/03/28
1.2K0
2020年3月27日,Github被攻击。我的GitPage博客也挂了,紧急修复之路
搭建jekyll博客
主流的个人博客都是用hexo搭建的,一部分人喜欢用jekyll搭建,下面我们来细说一下操作流程
ppjun
2018/09/05
8910
Forklift ETL 基础(一)(2)
file 就是当前目录中的 plan.rb 文件(可以不是这个文件名,自定义其它文件名),接在 forklift 后面,作为第一个参数
franket
2021/10/18
3160
【Jekyll搭建GITHUB个人博客】安装Ruby 环境、包管理器 RubyGems、Jekyll与错误解决
今天在博客专家群看到CSDN韩俊强发表了一篇用Jekyll搭建个人博客的文章,感觉很好。 搭建博客方便很多,开始一直想着自己搭建博客,然后一直没什么时间,在做另外一个项目,所以现在就考虑用Jekyll在GITHUB上搭建博客了。
谙忆
2021/01/21
6830
【Jekyll搭建GITHUB个人博客】安装Ruby 环境、包管理器 RubyGems、Jekyll与错误解决
RabbitMQ管理9
运行生产脚本 [root@h102 ruby]# ruby p.rb /usr/local/rvm/rubies/ruby-2.2.1/lib/ruby/site_ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in `require': cannot load such file -- bunny (LoadError) from /usr/local/rvm/rubies/ruby-2.2.1/lib/ruby/site_ruby/2.2.0/ru
franket
2022/04/23
2850
Forklift ETL 基础(一)(1)
Forklift ETL 是基于 Ruby 语言用来对 Mysql 和 Elasticsearch 进行 ETL 的工具集
franket
2021/10/18
5550
使用github+jekyll搭建个人博客
给自己一个小空间 聊聊起初 每次看到大牛们的博客,都会激起一颗一定要搭建自己博客的心,毕竟有着一颗向大牛们看齐的心。但是一直不知道如何下手,从最初的csdn写写博客到在github上建立仓库写代码分享,虽然也能够记录一些事情,但是总感觉缺少点什么——对,就是像是这东西并不是自己的。后来偶然机会知道了github的gh-pages功能可以搭建个人博客,然后兴致冲冲地去折腾了一番,但是了解到并不能搭建后台,突然间又像浇了一盘冷水一样,知道现在都还存留着这个博客的残骸,看这里http://rynxiao.gith
糊糊糊糊糊了
2018/05/09
1K0
使用github+jekyll搭建个人博客
Flutter--missing compatible arch in ffi_c.bundle
在运行Flutter Macos的时候,提示一下问题,没有找ffi_c.bundle在M1架构处理器下的文件。
None_Ling
2021/11/24
4650
提升Mac os x 10.10+xcode6.1之后,Cocoapods发生故障的解决方案
提升Mac OS X 10.10+Xcode 6.1之后。Cocoapods图书馆管理也依赖于相应升级。现在最新的Release版本号是 0.34。在之前的版本号。当数据库更新和管理,你会遇到一个错误,如下面的
全栈程序员站长
2022/07/06
3890
CentOS 7 安装ror出现的问题
看提示,需要执行 gem install sassc -v '2.4.0' --source 'https://rubygems.org/'
天地一小儒
2022/12/28
7730
Install Jekyll
前言 这里演示一下如何用十分钟搭建一个 Jekyll 博客 Tip: 当前最新版本 Jekyll 1.4.3 ---- 操作 环境 [root@ci ~]# hostnamectl Static hostname: ci Icon name: computer-vm Chassis: vm Machine ID: 8d13a50988cc5c4972347415eddf7d47 Boot ID: 10b2ba6eee6941
franket
2021/08/11
7250
Ruby——报错总结
我的Gemfile中指定的版本是2.5.1但是系统中ruby的实际版本是2.5.3,两种解决办法
思索
2024/08/16
3570
相关推荐
Jekyll搭建博客并部署到GitHub
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档