TSカプセル化フォーマットの概要
TS (トランスポート ストリーム) は一般的なビデオ パッケージング形式で、主にデジタル TV やオンライン ビデオ伝送の分野で使用されます。利点と欠点は次のとおりです。
利点:
1. 強力な耐障害性: 送信中にパケット損失またはエラー情報損失が発生した場合、データの完全性を確保するために迅速に回復できます。
2. ランダムアクセスをサポート: TS 形式はデータをセグメント化し、各セグメントに独立してアクセスおよび制御できるため、ビデオへのランダムアクセスが実現します。
3.優れたリアルタイム性能:TSカプセル化形式はセグメント化された伝送方式を採用しており、各データセグメントのサイズが比較的小さいため、遅延を効果的に削減し、リアルタイムデータ伝送を実現できます。
4. 優れた信頼性: TS カプセル化フォーマットは多重化をサポートしており、複数のデータ ストリームを混合してデータ伝送効率と信頼性を向上させることができます。
短所:
1. 複雑なエンコードとデコード: TS カプセル化フォーマットはビデオ データをセグメント化して統合する必要があり、これには高度なオーディオおよびビデオ コーディング技術が必要です 2. より大きなファイル: 特定の
データ ヘッダー情報が導入される TS セグメンテーション メカニズム
3. サポートされていません字幕処理: TS カプセル化形式は字幕データ処理をサポートしていないため、ユーザーは手動で字幕を追加する必要があります
TSパケット
TSカプセル化フォーマットのデータ単位はtsパケットである。各パケットには独自の pid があり、パケット サイズは 188 バイトに固定されています。
ts パッケージは、pat パッケージ、pmt パッケージ、pes パッケージの 3 つのカテゴリに分類されます。
- PAT (Program Associate Table) パッケージは最初のパッケージであり、ts のエントリであり、その pid は 0x00 に固定されています。pat パッケージには pmt パッケージの pid が含まれており、pmt パッケージは pat パッケージを通じて見つけることができます。
- PMT (Program Map Table) は、オーディオ、ビデオ、データ情報などのストリームのコンテンツ情報を記述するために使用されます。pmt パケットにはデータ ストリーム パケットの PID が格納され、オーディオ パケットの PID は 0x102、ビデオ パケットの PID は 0x101 です。
- PES(Packetized Elementary Stream)パケットは、音声や映像などのマルチメディアデータ情報を伝送するために使用される基本的なデータ単位です。
TS ストリームでは、PAT パケットと PMT パケットが繰り返し実装され、リアルタイムのデコードを保証するために 1 つのパケットが約 0.5 秒で現れます。PAT テーブルは TS ストリームの基礎であり、TS ストリームの解析や番組の検索はすべて PAT テーブルから始まります。
TSパケットの構造
ts パケットの固定サイズは 188 バイトで、対応する構造式は次のとおりです。
tsPacket = tsheader + アダプテーション フィールド + ペイロード;
tsheader: ts データ パケットのヘッダー、各データ パケットにそれがあり、ファイル ヘッダーは 4 バイトに固定されています。
アダプテーション フィールド: データ充填フィールド、一部のデータ パケットにはこのフィールドがありますが、一部のデータ パケットにはこのフィールドが存在しません (データとして使用されます) fill)
ペイロード: オーディオとビデオのデータ フィールド。pes データとオーディオとビデオの元のデータを格納するために使用されます。
さまざまなタイプのパケットの構造は次のとおりです。
TS流: 由一个个188字节的数据包组成
+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| TS | = | Packet 1 | Packet 2 | Packet 3 | ... | Packet n-1| Packet n |
+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
一个Packet: 4bytes 184bytes
+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Packet | = | ts header | Packet data |
+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
PAT/PMT包结构, 只包含tsheader和PMT/PAT, 不包含adaption和pes
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ts header | PAT/PMT | Stuffing Bytss |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
PES包结构,可能包含adaption和pes字段
4 byte x byte 184-x byte
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ts header | adaptation field | payload(pes) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
tsヘッダのデータ構造
各 TS パケットには ts ヘッダーフィールドが含まれており、そのサイズは 4 バイト固定であり、4 バイト内の各データビットの意味は次のとおりです: 合計 4 バイト (32 ビット
)
sync_byte (8bit) 同步字节,固定为0x47
transport_error_indicator (1bit) 传输错误指示符, 通常都为'0'
payload_unit_start_indicator (1bit) 负载单元起始标示符,一个完整的数据包开始时标记为 '1'
transport_priority (1bit) 传输优先级,0为低优先级,1为高优先级,通常取0
pid (13bit) 传输包的PID, pat包固定为0x0000
transport_scrambling_control (2bit) 传输加扰控制,00表示未加密
adaptation_field_control (2bit) 是否包含自适应区(adaption):00保留;01无自适应域,含有效负载;10含自适应域,无有效负载;11为同时带有自适应域和有效负载
continuity_counter (4bit) 递增计数器,从0-f,起始值不一定取0,但必须是连续的
PATフィールドのデータ構造
PAT (Program Associate Table) プログラム アソシエート テーブルの構造は次のとおりです。
table_id (8bit) PAT表固定为0x00
section_syntax_indicator (1bit) 段语法标志位, 固定为1
zero (1bit) 固定为0
reserved (2bit) 保留位,固定为11
section_length (12bit) 段长度(后面数据的长度),表示从下一个字段开始到CRC32(包含)之间有用的字节数
transport_stream_id (16bit) 传输流ID,固定为0x0001, 区别于一个网络中其它多路复用的流
reserved (2bit) 固定为11
version_number (5bit) 版本号,固定为00000,如果PAT有变化则版本号加1
current_next_indicator (1bit) 固定为1,表示这个PAT表可以用,如果为0则要等待下一个PAT表
section_number (8bit) 分段的号码. PAT可能分为多段传输, 第一段为00, 以后每个分段加1, 最多可能有256个分段
last_section_number (8bit) 固定为0x00, 最后一个分段的号码
开始循环,按顺序可能包含多个下面结构
program_number (16bit) 节目号为0x0000时表示这是NIT,节目号为0x0001时,表示这是PAT
reserved (3bbit) 固定为111
PID (13bit) 节目号对应内容的PID值0x1000, 也就是pmt的pid
结束循环
CRC32 (32bit) 前面数据的CRC32校验码
PMTフィールドのデータ構造
PMT(Program Map Table)、プログラムマッピングテーブル、パッケージのPIDはPATテーブルから取得できます。
table_id (8bit) PMT表取值随意, 这里给定0x02
section_syntax_indicator (1bit) 段语法标志位, 固定为1
zero (1bit) 固定为0
reserved (2bit) 保留位,固定为11
section_length (12bit) 后面数据的长度, 表示从下一个字段开始到CRC32(含)之间有用的字节数
program_number (16bit) 频道号码,表示当前的PMT关联到的频道, 取值0x0001
reserved (2bit) 固定为11
version_number (5bit) PMT版本号码,固定为00000,如果PAT有变化则版本号加1
current_next_indicator (1bit) 发送的PMT表是当前有效还是下一个PMT有效, 固定为1
section_number (8bit) 固定为0x00, PMT可能分为多段传输,第一段为00, 以后每个分段加1, 最多可能有256个分段
last_section_number (8bit) 分段数,固定为0x00
reserved (3bit) 保留位, 固定为111
PCR_PID (13bit) PCR(节目参考时钟)所在TS分组的PID,指定为视频PID
reserved (4bit) 固定为1111
program_info_length (12bit) 节目描述信息,指定为0x000表示没有,前2bit为00, 该域指出跟随其后对节目信息的描述的字节数。
开始循环,按顺序可能包含多个
stream_type (8bit) 流类型,标志是Video还是Audio还是其他数据,h.264编码对应0x1b,aac编码对应0x0f,mp3编码对应0x03
reserved (3bit) 固定为111
elementary_PID (13bit) 与stream_type对应的PID
reserved (4bit) 固定为1111
ES_info_length (12bit) 描述信息,指定为0x000表示没有
结束循环
reserved_5 3bit 保留位, 固定为0x07
reserved_6 4bit 保留位, 固定为0x0F
CRC32 32bit 前面数据的CRC32校验码
アダプテーションフィールドのデータ構造情報
アダプテーションフィールドは、オーディオおよびビデオデータが不十分な場合にデータで埋められます。
adaptation_field_length (8bit) adaption字段的长度(后面的字段不包括当前字段)
discontinuity_indicator (1bit) 指示数据流是否存在不连续的情况
randort7_acce55_indicator (1bit) 指示数据流中是否存在重要的组或关键帧
elementary_stream_priority_indicator (1bit) 指示数据流的优先级
PCR_flag (1bit) PCR(Programme Clock Reference)字段是否存在
OPCR_flag (1bit) OPCR字段是否存在
splicing_point_flag (1bit) 数据流中是否存在插播点
transport_private_data_flag (1bit) 是否存在私有数据
adaptation_field_extension_flag (1bit) 用于指示是否存在ADAPTATION FIELD EXTENSION
//PCR_flag==1 控制TS数据流同步的42位时间戳
program_clock_reference_base (33bit)
Reserved (6bit)
program_clock_reference_extension (9bit)
//OPCR_flag==1 ( Optional Program Clock Reference)
//用于同步接收到的多个数据流,其在时间戳方面与 PCR 相似,但只在数据流中的某些节目中使用
original_program_clock_reference_base 33bit
Reserved 6bit
original_program_clock_reference_extension 9bit
//splicing_point_flag==1
splice_countdown (8bit)
//transport_private_data_flag==1
transport_private_data_length (8bit)
for (1=0,i<transport_private_data_length; i++){
private data byte (8bit)
}
//adaptation_field_extension_flag==1
adaptation_field_extension_length (8bit)
Itw_flag (1bit)
piecewise_rate_flag (1bit)
seamless_splice_flag (1bit)
Reserved (5bit)
//Itw_flag==1
ltw_valid_flag (1bit)
ltw_offset (15bit)
//piecewise_rate_flag ==1
reserved (2bit)
piecewise_rate (22bit)
//seamless_splice_flag==1
Splice_type (4bit)
DTS_next_AU[32..30] (3bit)
marker_bit (1bit)
DTS_next_AU[29 ..15] (15bit)
marker_bit (1bit)
DTS_next_AU[14..0] (15bit)
marker_bit (1bit)
for (i=0;i<N;i++){
reserved (8bit)
}
//last
for(i=0i<N;i++){
stuffing_byte (8bit)
}
TS ストリームがパッケージ化される場合、PAT テーブルと PMT テーブルには Adaptation フィールドがありません。長さが十分でない場合は、直接 0xff を追加します。ビデオ ストリームとオーディオ ストリームの両方でアダプテーション フィールドを追加する必要があります。これは通常、フレームの最初の ts パケットと最後の ts パケットに追加され、中間の ts パケットは追加されません。
ts ファイルをパッケージ化するときは注意してください。PCR クロックを追加する必要があります。追加しないと、VLC プレーヤーでの再生に失敗します。動画の長さを取得できません。
ここでは、Java 実装を例として、PCR 値の生成方法を紹介します。
void create_adaption_field(AdaptionField adption_field, long pts, boolean has_pcr)
{
int index = 0;
Arrays.fill(adption_field.adaption_buffer,0,adption_field.adaption_buffer.length, (byte) 0xFF);
if (has_pcr)
{
//包含pcr
long pcrValue = pts * 300;
long PCR_BSE = pcrValue / 300;
long PCR_EXT = pcrValue % 300;
后续可能会更新,7个字节
adption_field.adaption_buffer[index++] = 0x07;
//取0x50表示包含PCR
adption_field.adaption_buffer[index++] = 0x50;
adption_field.adaption_buffer[index++] = (byte)((byte)0xff & (PCR_BSE >> 25)); //PCR_BASE的前8位
adption_field.adaption_buffer[index++] = (byte)((byte)0xff & (PCR_BSE >> 17)); //PCR_BASE的紧跟8位
adption_field.adaption_buffer[index++] = (byte)((byte)0xff & (PCR_BSE >> 9)); //PCR_BASE的紧跟8位
adption_field.adaption_buffer[index++] = (byte)((byte)0xff & (PCR_BSE >> 1)); //PCR_BASE的紧跟8位
adption_field.adaption_buffer[index++] = (byte)((PCR_BSE << 7 | PCR_EXT >> 8 | 0x7e) & 0xFF);
adption_field.adaption_buffer[index++] = (byte)(0xff & PCR_EXT);
}
else
{
//不包含pcr
adption_field.adaption_buffer[index++] = 0x07; //后续可能会更新, 7个字节
adption_field.adaption_buffer[index++] = 0x00; //0x00都不包含
}
adption_field.adaption_field_size = index;
}
PESフィールドのデータ構造
pes 層 (ts 層のペイロード) は、タイムスタンプやその他の情報を各ビデオ/オーディオ フレームに追加します。pes パッケージには多くのコンテンツが含まれていますが、最も一般的に使用されるものだけを残します。
長さは 14 (pts のみを含む)/18 (pts と dts を含む) バイトです。
pes_start_code (24bit) 开始码,固定为0x000001
stream id (8bit) 音频取值(0xc0~0xdf),通常为0xc0,视频取值(0xe0-0xef),通常为0xe0
pes_packet_length (16bit) 后面pes数据的长度,0表示长度不限制,只有视频数据长度会超过0xffff
flag (8bit) 是否加密, 通常取值0x80,表示数据不加密、无优先级、备份的数据
flag (8bit) 是否包含pts和dts, 取值0x80表示只含有pts,取值0xc0表示含有pts和dts
pes_data_length (8bit) 后面数据的长度,取值5或10
pts (40bit) pts显示时间戳
dts (40bit) dts解码时间戳
pts は表示タイム スタンプ、dts はデコード タイム スタンプです。ビデオ データには両方のタイム スタンプが必要です。オーディオ データでは pts と dts は同じであるため、pts のみが必要です。
B フレームによるタイムスタンプには pts と dts の 2 種類があり、I フレームと P フレームの pts は dts と同じになります。ビデオに B フレームがない場合、pts は常に dts と同じになります。ファイルからビデオ フレームを順番に読み取り、抽出されたフレームの順序は dts の順序と同じになります。
TS データフローのパケット化戦略
ここでは、AAC オーディオ データのフレームを例として、TS カプセル化形式のパケット化戦略を説明します。通常、TS パケットは完全なフレームを送信できず、オーディオおよびビデオ データのフレームを複数のパケットに分割する必要があります。 1. まず
、フローの先頭として PAT パケットと PMT パケットをフローに追加します
2. 次に、アダプションと PES を含むデータ パケットの先頭として最初の PES パケットを追加します。パケットには、フレームの長さ、サンプリング レート、pts/dts などの情報が含まれています。
3. 分割データ PES パケットを中央に追加します。これには tsheader とオーディオおよびビデオ データのみが含まれます。
4. 最後のデータ パケットには、ts ヘッダー、Adaption、最後にオーディオおよびビデオ データが含まれますが、PES フィールドは含まれません。
対応する構造を次の図に示します。
+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
| TS | = | PAT包 | PMT包 | PES1 | ... | PES n |
+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
第一个PES包: 4Byte 8Byte 14Byte(pts) 162Btte
+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Packet | = | ts header | Adaption | PES | paylod |
+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
中间的PES包, 只包含tsheader和payload, 不包含adaption和pes
4Byte 184Byte
+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Packet | = | ts header | payload |
+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
最后一个PES包 包含tsheader、adaption、payload
4 byte x byte 184-x byte
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ts header | adaptation field | payload |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+