Chinaunix首页 | 论坛 | 博客
  • 博客访问: 252683
  • 博文数量: 58
  • 博客积分: 2241
  • 博客等级: 大尉
  • 技术积分: 522
  • 用 户 组: 普通用户
  • 注册时间: 2009-08-07 09:53
文章分类
文章存档

2012年(4)

2011年(19)

2010年(31)

2009年(4)

分类:

2010-01-19 11:44:14

MPEG-2系统原理

MPEG-2系统原理之 第一章:MPEG-2简介

第一章 MPEG-2简介

什么是MPEG和MPEG-2?

MPEG是Moving Picture Experts Group 的简称,MPEG-2是MPEG和ISO组织设计的一个数字视频压缩规范,主要用于DVD和DVB上,当前的标准文档是ISO13818.

什么是DVB?

DVB是Digtal Video Broadcast的简称,是欧洲所有国家和其他部分国家和地区使用的数字电视标准.其中美国的ATSC标准也是在DVB标准的基础上实现的.

什么是TS码流和PS流?

TS是transport stream的简称,就是”传输流”.DVB数据广播采用的数据格式就是TS码流.

PS是program stream的简称,就是”节目流”.DVD中采用的数据格式就是PS流.

这两种流的格式是不同的,TS格式具有很强的错误校正功能,适合传输,而PS格式适合存储在媒体中. 在这里,着重描述的是TS码流格式.

什么是PID?

PID是Packet identification的简称,就是”包标志符”.DVB系统把不同的数据打包成不同的数据包,用系统唯一的一个13 bits数字标志该数据的类型.例如,PID=0x00表示是DVB系统中的PAT包,而PID=0x10表示是DVB系统的NIT包.不同的节目(包括 Video和Audio)分别采用不同的PID,例如,我们在PMT表中如果检测到PID=0x0120的PID是VIDEO数据,那么表示包号码是 0x0120的所有包都是Video数据,其他依此类推.

什么是PAT?

PAT是Program Association Table的简称,即”节目关联表”.PAT属于DVB系统流中的一个包,包号码(PID)是0x00.PAT表描述了DVB系统流中包含什么样的 PID,主要是描述当前流的NIT表格的PID号码是多少,当前流中有多少个不同类型PMT表,每个PMT表对应的频道号等信息.

什么是PMT?

PMT是Program Map Table的简称,即”节目影射表”.PMT的PID是服务器自由定义的(但不会和系统保留的PID冲突).这个PID是在PAT表中描述的,比如,如果 在PAT表中有0x100项的内容,那么说明所有PID是0x100的包都是PMT表.不同的频道有不同的PMT,也就是说,一个不同的PMT代表的是一 个不同频道.PMT表格和PAT表格配合在一起,就可以检测出DVB流中所有存在节目的所有PID,因此,数字电视搜台就是依靠这两个表格数据完成的.

什么是CAT?

CAT是Conditional Access Table的简称,即”条件访问表”,PID是0x01.CAT携带的是服务器的私有信息(CA系统就需要使用该表格实现节目的解密).

什么是SDT?

SDT是Service Description Table的简称,即”服务器描述表”,PID是0x11.SDT携带的是电视台名称和电视节目名称.DVB接收系统接收SDT表中的节目信息,实现比较友好的界面显示和操作.

什么是NIT和EIT?

NIT是Network Information Table的简称,即”网络信息表”.

EIT是Event Information Table的简称,即”环境信息表”.

NIT可以提供当前流的节目信息,也可以提供和当前流有关联的流的节目信息.

EIT提供的是流节目信息的改变,比如一个节目已经开始,或者已经结束的信息等.

什么是EPG?

EPG是Electronic Programme Guides的简称,即”电子节目指南”.该功能可实现预告近段时间即将播放的节目内容,同时支持基于内容的检索.

什么是teletext?

Teletext就是我们常说的”图文电视”,当然在MPEG-2中,图文电视已经数字化,也就是说,图文信息已经做为数字化信息在TS流中传播.但最 终,数字化的图文信息都将转化为模拟的VBI(VBI是Vertical Blanking Interval的缩写,中文是场消隐期,也叫场逆程)信息插入到正常的电视信号中实现图文电视的显示.图文电视有很多标准,比如close caption,WSS等,欧洲的DVB使用的teletext标准是ITU-R System B Teletext规格.该规格支持欧洲多种语言,支持简单图象和文本的混合显示.

MPEG-2系统原理之第二章 DVB系统的构成

第二章 DVB系统的构成

[本文不详细描述DVB系统的硬件构成,只是根据ISO13818中的描述,详细解释TS码流的格式和解复用原理.]

DVB的分类

DVB根据应用的不同,主要分为DVB-S,DVB-C,DVB-T,DVB-H等多种规格.不同的规格基本原理都是相同的,不同的主要是调制方式不同:

DVB-S,S是Satelite的首字母,应用于数字电视卫星广播,调制方式是QPSK.

DVB-C,C是Cable的首字母,应用于城市有线广播.调制方式是QAM所有格式: 16QAM,32QAM,64QAM,128QAM,256QAM.

DVB-T,T是Terrestrial的首字母,应用于陆地无线广播,调制方式是QPSK或者16QAM和64QAM.

DVB-H,H是Handheld的首字母,应用于手持无线广播,调制方式和DVB-T相同.

总的来说,不同的DVB系统只有前端系统是不同的,最终的数字信息都是相同的,也就是都是采用ISO13818描述的规格.前端系统主要是指调制方法和发 射方法等.因此,这里所叙述的内容,全部适用于所有的DVB系统,同时因为美国的ATSC系统也是在DVB系统上的小量更改和小部分功能增加,因此也适用 于ATSC标准.

基本系统描述如下:

(1)编码系统:

假设信号源有6个节目,则DVB系统先对这6个节目的所有数据(Video,Audio)进行压缩处理,然后经过一个叫做"复用"的程序进行节目的复用 (PID分配,即对6个节目分别分配不同的PID号码)形成叫做"PES"的包,然后再经过TS流处理程序,把这些PES包全部封装成TS码流格式,最后 把获得的TS格式的数字信号经过调制(实现的是频率的复用),然后经过D/A转换成模拟信号,再次调制成高频信号,经传输系统发送出去.

(2)解码系统

接收系统接收到高频信号,先转化为中频信号,然后再经过一个高速的A/D转换成数字信号,接着经过一个反调制程序,这样就得到了TS码流. TS码流进入一个称为"解复用"的程序,该程序实现自动分析TS流中的表格信息,读取所有可用的PID信息等,然后提取一个用户指定的PID(用户选择的 节目),把该节目的数字信号全部接收而忽略其他不需要的信号,然后Video,Audio信号分别进入不同的解压缩程序,分别对Video,Audio信 号进行解压缩和显示,如果该节目包含了Teletext和EPG,也有可能同时处理Teletext和EPG,并且把处理的结果和Video信号一起叠加 到屏幕上.

Packet的概念

(1)TS流是基于Packet的位流格式,每个包是188字节或者204字节(一般是188字节,204字节的格式仅仅是在188字节的Packet后部加上16字节的CRC数据,其他格式是一样的),整个TS流组成如下所示:

Packet 1 Packet 2 ...... Packet n

在实际使用中,因为TS流已经内部具有很强的错误处理能力,所以一般使用较多的是188字节一个包的格式,204字节一个包的格式据说一般在高清节目中使用较多.

所有的Packet格式都是统一的,包括一个Packet header和Packet datas.其中Packet header包含了同步字节(该字节固定是0x47,表示这个包的数据开始是正确的),该Packet的唯一号码(即PID)和其他一些信息.格式如下 (用C格式表示)

typedef struct

{

unsigned sync_byte:8;/*8 bits的同步字节*/

unsigned transport_error_indicator:1;/*1 bit的错误指示信息,1表示当前Packet至少有1bit的传输错误,0表示所有数据都正确*/

unsigned payload_unit_start_indicator:1;/*负载单元开始标志,请参考ISO13818-1了解该标志作用*/

unsigned transport_priority:1;/*1 bit的传输优先级标志,1表示高优先级,0表示低优先级*/

unsigned PID:13;/*13 bits的Packet ID号码,唯一的号码对应不同的包*/

unsigned transport_scrambling_control:2;/*2 bits的加密标志,00表示没有加密,其他表示已被加密*/

unsigned adaptation_field_control:2;/* 2 bits的附加区域控制,请参考ISO13818-1了解该标志作用*/

unsigned continuity_counter:4;/*4 bits的包递增计数器*/

}PACKET_HEADER;

以 上结构刚好占用32 bits,即4个字节,因此一个TS流的Packet头部的4字节是header信息,分析该header信息就可以知道当前Packet的属性.剩下的 184字节有可能是Video数据,也有可能是Audio数据,也有可能是DVB SI信息,怎么区分呢?其实很简单,就是利用header中的PID信息.上一章说了PAT是节目关联表,它的PID是0x0000.这个PID就是对应 这里header的PID.换句话就是说,如果我们发现一个Packet的PID等于0x0000,那么说明这个Packet是DVB的PAT表格而不是 Video数据或者Audio数据.

实际上,在信号编码成TS码流的时候,不同节目的Video,Audio等数据都分配了不同的 PID.例如,一个节目有两路Video,三路Audio,那么分配PID的时候可能是Video 1==0x100,Video 2==0x101,Audio 1==0x102,Audio 2==0x103,Audio 3==0x104,这样传输的TS码流中的PID就可能有以上的PID.因此,如果我们需要在程序中过滤出第一路Video和第二路Audio就可以这样 处理了(伪代码描述):

void Process_Packet(unsigned char*buff)

{

int PID=GETPID(buff);/*从当前的188字节缓冲区中获取PID信息*/

if(PID==0x100) /*PID等于第一路Video的PID,说明当前数据是Video数据*/

{

SaveToVideoBuffer(buff+4);/*把header后部的数据存到Video缓冲区,待后部处理*/

}

else if(PID==0x103)/*PID等于第二路Audio的PID,说明当前数据是Audio数据*/

{

SaveToAudioBuffer(buff+4);/*把header后部的数据存到Audio缓冲区*/

}

else/*其他PID则丢弃,当然如果PID是DVB系统保留的PID如PAT,PMT则必须处理*/

{

printf("unknown PID!\n");

}

}

现 在的问题是,编码的时候分配好的PID,在解码的时候是怎么知道什么PID对应什么数据呢?这就是DVB SI表格的分析与处理了,请参考第三章.这里先看一个实际的TS码流的例子.这里的数据是用UltraEdit用16进制格式打开TS码流文件得到的.文 件是Taiwan-551.ts.

这里仅仅截取了3个Packet的信息,请注意图中用红色标注的部分,这就是TS流Packet的4个 字节的头信息.这个TS流是采用每个包共188字节的格式,因为两个头信息的间隔是188个字节(第一个0x47到第二个0x47的间隔).以后的所有的 Packet都将是188字节的格式,这是DVB TS标准规定的固定大小.那么这三个包分别包含的是什么数据,下面我们可以自己分析一下.

先看第一个包,头信息数据是"0x47 0x07 0xe5 0x12",刚才已经知道了,header信息都是按位操作的(这就是为什么TS码流也可以叫做位流的原因),特别要注意的是定义和传输的时候都是MSB first,也就是说,先出现的位是数据的最高位.先转化成2进制格式:

01000111 00000111 11100101 00010010

请对照上面的PACKET_HEADER结构:

typedef struct

{

unsigned sync_byte:8;

unsigned transport_error_indicator:1;

unsigned payload_unit_start_indicator:1;

unsigned transport_priority:1;

unsigned PID:13;

unsigned transport_scrambling_control:2;

unsigned adaptation_field_control:2;

unsigned continuity_counter:4;

}PACKET_HEADER;

那么对照一下,我们可以发现:

sync_byte=01000111,就是0x47,这是DVB TS规定的同步字节,固定是0x47.

transport_error_indicator=0,表示当前包没有发生传输错误.

payload_unit_start_indicator=0,含义请参考ISO13818-1标准文档

transport_priority=0,表示当前包是低优先级.

PID=00111 11100101即0x07e5,这代表是什么呢,暂时还不知道(实际上是Video PID,参考下图)

transport_scrambling_control=00,表示节目没有加密

adaptation_field_control=01即0x01,具体含义请参考ISO13818-1

continuity_counte=0010即0x02,表示当前传送的相同类型的包是第3个

依此类推,再看一下第二个包"0x47 0x07 0xe5 0x13",2进制是01000111 00000111 11100101 00010011

sync_byte=01000111,就是0x47,这是DVB TS规定的同步字节,固定是0x47.

transport_error_indicator=0,表示当前包没有发生传输错误.

payload_unit_start_indicator=0,含义请参考ISO13818-1标准文档

transport_priority=0,表示当前包是低优先级.

PID=00111 11100101即0x07e5,这代表是什么呢,暂时还不知道(实际上是Video PID,参考下图)

transport_scrambling_control=00,表示节目没有加密

adaptation_field_control=01即0x01,具体含义请参考ISO13818-1

continuity_counte=0011即0x03,表示当前传送的相同类型的包是第4个(注意到了吧,以上两个包的PID都是0x07e5,所以这里的continuity_counte就递增一次)

第三个包是"0x47 0x07 0xf1 0x18",2进制是01000111 00000111 11110001 00011000.

sync_byte=01000111,就是0x47,这是DVB TS规定的同步字节,固定是0x47.

transport_error_indicator=0,表示当前包没有发生传输错误.

payload_unit_start_indicator=0,含义请参考ISO13818-1标准文档

transport_priority=0,表示当前包是低优先级.

PID=00111 11100101即0x07f1,这代表是什么呢,暂时还不知道(实际上是Audio PID,参考下图)

transport_scrambling_control=00,表示节目没有加密

adaptation_field_control=01即0x01,具体含义请参考ISO13818-1

continuity_counte=1000即0x08,表示当前传送的相同类型的包是第9个

请看解码程序<>读取该文件的结果:

上图我们可以发现,Taiwan-551.ts有一个节目叫"DIMO",它的Video PID是0x07e5,Audio PID是0x07e6

还有一个节目叫"Service 1",没有Video PID,它的Audio PID是0x07f1(说明是一个广播节目而非电视节目)

这个数据刚好和我们刚才的分析是吻合的.

但 是我想大家还有疑问,为什么0x07e5代表Video PID,0x07e6代表其中一个Audio PID呢?这就是刚才提到的,这是TS流在编码的时候就分配好了的.但是,在解码的时候是怎么知道0x07e5就代表的是Video而不是Audio呢? 这就是第三章的内容:DVB SI/PSI分析和处理.

MPEG-2系统原理之第三章:DVB SI/PSI分析和处理

第三章 DVB SI/PSI分析和处理

SI 是Specific Information的简称,PSI是program Specific Information.该机制允许DVB传送各种各样的讯息,比如节目名称,电视台名称,各种PID,私有信息,甚至单独传送数据实现数据通信等.这些 功能的实现都归功于SI/PSI.

在DVB标准中,定义了一个标准的PID用来实现SI/PSI.这些PID是系统保留的,因此DVB编码的时候并不会用这些PID做为Video PID或者Audio PID或者其他PID.在一个简单的解复用程序中,只需要提供处理PAT,PMT表格的程序即可实现解复用,当然如果需要更友好的界面和实现更复杂的功能 (如CA)则必须处理其他的SI表.在这里仅仅分析PAT,PMT,SDT表格,其他SI表格的分析,请参考ISO13818-1(MPEG-2系统层标 准)和EN300468(DVB SI标准)文档.

DVB定义的SI保留的PID分别是:

上表格的PID就是DVB保 留的PID,分配的其他PID一定不会占用这些PID.解复用程序需要使用到的表格只有PAT,PMT,SDT,而CA应用还需要使用CAT,EPG应用 还需要使用NIT,EIT,TDT,TOT等表格.所以在需要解复用的时候,伪代码需要这样写:

void Process_Packet(unsigned char*buff)

{

int PID=GETPID(buff);

if(PID==0x0000) /*这是PAT表*/

{

Process_PAT(buff+4);/*处理PAT表*/

}

else if(PID==......)/*Video 或者Audio*/

{

}

else/*其他不支持的PID*/

{

printf("Unknown PID!");

}

}

所有的表格都开始于Packet中的184字节的数据部分,但有的时候一个表格没有184字节,这时在Packet中就可能插入一些无效信息用来填充使整 个Packet依然保持是188字节.也可能用头信息中的payload_unit_start_indicator标志表格有个偏移位置(当 payload_unit_start_indicator=0表示表格数据直接从Packet区的第四个字节开始,否则表示有一个偏移量位置开始,具体 请参考ISO13818-1,第4字节到偏移量间的数据是系统填充的无效数据).

下面针对解复用程序详细分析一下PAT,PMT和SDT三类表格的格式.

PAT, Program Association Table,节目关联表

PAT表携带以下信息:

(1) TS流ID--- transport_stream_id,该ID标志唯一的流ID

(2) 节目频道号-- program_number,该号码标志TS流中的一个频道,该频道可以包含很多的节目(即可以包含多个Video PID和Audio PID)

(3) PMT的PID--- program_map_PID,表示本频道使用的哪个PID做为PMT的PID,因为可以有很多的频道,因此DVB规定PMT的PID可以由用户自己定义.

PAT表定义如下:

各字段含义如下:

table_id:8 bits,标志本表格的类型,应该是0x00

section_syntax_indicator:1 bit,段语法标志,应该是'1'

'0':固定的'0',这是为了防止和ISO13818Video流格式中的控制字冲突而设置的.

Reserved:保留的2bits,保留位一般都是'0'

section_length:12bits的段大小,单位是Bytes.

transport_stream_id:16bits的当前流ID,DVB内唯一.(事实上很多都是自定义的TS ID)

version_number:5bits版本号码,标注当前节目的版本.这是个非常有用的参数,当检测到这个字段改变时,说明TS流中的节目已经变化了,程序必须重新搜索节目.

current_next_indicator:1bit:当前还是未来使用标志符,一般情况下为'0'

section_number:8bits当前段号码

last_section_number:8bits最后段号码(section_number和last_section_number的功能是当 PAT内容>184字节时,PAT表会分成多个段(sections),解复用程序必须在全部接收完成后再进行PAT的分析)

从for()开始,就是描述了当前流中的频道数目(N),每一个频道对应的PMT PID是什么.解复用程序需要和上图类似的循环来接收所有的频道号码和对应的PMT PID,并把这些信息在缓冲区中保存起来.在后部的处理中需要使用到PMT PID.

CRC_32:本段的CRC校验值,一般是会忽略的.N是一个变量,计算方法是N=(section_length-9)/4.

从以上分析我们可以发现,PAT表主要包含频道号码和每一个频道对应的PMT的PID号码,这些信息我们在处理PAT表格的时候会保存起来,以后会使用到这些数据.例如我们可以定义这样的数据结构保存这些信息:

typedef struct

{

int channel_number;/*频道号*/

int pmt_pid;/*对应channel_number频道号的PMT的PID*/

}PMT_ITEM;

PMT_ITEM pmt[64];/*定义最多64个频道,这个结构在分析PAT表格的时候会更新*/

PMT, Program Map Table,节目影射表

如果一个TS流中含有多个频道,那么就会包含多个PID不同的PMT表.检测是否PMT的伪代码如下:

void Process_Packet(unsigned char*buff)

{

int I;

int PID=GETPID(buff);

if(PID==0x0000)/*PAT表格*/

{

Process_PAT(buff+4);

}

else if(PID==.....)/*Video PID或者Audio PID*/

{

}

else

{

/*在这里检测PID是否是PMT的PID*/

for(i=0;i<64;i++)

{

if(PID==pmt[i].pmt_pid)/*PID等于在PAT检测到的PMT PID相同*/

{

Process_PMT(buff+4);/*说明当前Packet是PMT,进入处理*/

break;

}

}

}

}

PMT表中包含的数据如下:

(1) 当前频道中包含的所有Video数据的PID

(2) 当前频道中包含的所有Audio数据的PID

(3) 和当前频道关联在一起的其他数据的PID(如数字广播,数据通讯等使用的PID)

PMT定义如下:

各字段含义如下:

table_id:8bits的ID,应该是0x02

section_syntax_indicator:1bit的段语法标志,应该是'1'

'0':固定是'0',如果不是说明数据有错.

reserved:2bits保留位,应该是'00'

section_length:16bits段长度,从program_number开始,到CRC_32(包含)的字节总数.

program_number:16bits的频道号码,表示当前的PMT关联到的频道.换句话就是说,当前描述的是program_number频道的信息.

reserved:2bits保留位,应该是'00'

version_number:版本号码,如果PMT内容有更新,则version_number会递增1通知解复用程序需要重新接收节目信息,否则version_number是固定不变的.

current_next_indicator:当前未来标志符,一般是0

section_number:当前段号码

last_section_number:最后段号码,含义和PAT中的对应字段相同,请参考PAT部分.

reserved:3bits保留位,一般是'000'.

PCR_PID:13bits的PCR PID,具体请参考ISO13818-1,解复用程序不使用该参数.

reserved:4bits保留位,一般是'0000'

program_info_length:节目信息长度(之后的是N个描述符结构,一般可以忽略掉,这个字段就代表描述符总的长度,单位是Bytes)

紧接着就是频道内部包含的节目类型和对应的PID号码了.

stream_type:8bits流类型,标志是Video还是Audio还是其他数据.

reserved:3 bits保留位.

elementary_PID:13bits对应的数据PID号码(如果stream_type是Video,那么这个PID就是Video PID,如果stream_type标志是Audio,那么这个PID就是Audio PID)

reserved:4 bits保留位.

ES_info_length:和program_info_length类似的信息长度(其后是N2个描述符号)

CRC_32:32bits段末尾是本段的CRC校验值,一般忽略.

从以上的分析可以看出,只要我们处理了PMT,那么我们就可以获取频道中所有的PID信息,例如当前频道包含多少个Video,共多少个Audio,和其他数据,还能知道每种数据对应的PID分别是什么.

这样如果我们要选择其中一个Video和Audio收看,那么只需要把要收看的节目的Video PID和Audio PID保存起来,在处理Packet的时候进行过滤即可实现.

比较全面实现解复用的伪代码如下:

int Video_PID=0x07e5,Audio_PID=0x07e6;/*一般是在PMT检索后由用户自己设置这两个全局值*/

void Process_Packet(unsigned char*buff)

{

int I;

int PID=GETPID(buff);/*获取当前Packet的PID*/

if(PID==0x0000)/*0x0000表示是PAT*/

{

Process_PAT(buff+4);

}

else if(PID==Video_PID)/*和Video_PID相等,说明当前Packet是一个Video Packet*/

{

SaveToVideoBuffer(buff+4);/*保存到Video缓冲区*/

}

else if(PID==Audio_PID)/*和Audio_PID相等,说明当前Packet是一个Audio Packet*/

{

SaveToAudioBuffer(buff+4);/*保存到Audio缓冲区*/

}

else

{

for( i=0;i<64;i++)

{

if(PID==pmt[i].pmt_pid)

{

Process_PMT(buff+4);

Break;

}

}

}

}

以上伪代码可以实现基本的解复用:检测所有的频道,检测所有stream的PID,选择特定的节目进行播放.只要读取每个Packet的188字节的内容,然后每次都调用Process_Packet()即可实现简单的解复用.

介绍到这里,我们就可以总结一下DVB搜台的原理了.

机顶盒先调整高频头到一个固定的频率(如498MHZ),如果此频率有数字信号,则COFDM芯片(如MT352)会自动把TS流数据传送给MPEG-2 decoder. MPEG-2 decoder先进行数据的同步,也就是等待完整的Packet的到来.然后循环查找是否出现PID==0x0000的Packet,如果出现了,则马上 进入分析PAT的处理,获取了所有的PMT的PID.接着循环查找是否出现PMT,如果发现了,则自动进入PMT分析,获取该频段所有的频道数据并保存. 如果没有发现PAT或者没有发现PMT,说明该频段没有信号,进入下一个频率扫描.

从以上描述可以看出,机顶盒搜索频率是随机发生的,要使每次机顶盒都能搜索到信号,则要求TS流每隔一段时间就发送一次PAT和PMT.事实上DVB传输 系统就是这么做的.因此无论何时接入终端系统,系统都能马上搜索到节目并正确解复用实现播放.不仅仅如此,其他数据也都是交替传送的.比如第一个 Packet可能是PAT,第二个Packet可能是PMT,而第三个Packet可能是Video 1,第四个Packet可能是Video 2,

只要系统传输速度足够快(就是称之为"码率"的东东),实现实时播放是没有任何问题的.

到这里虽然实现了解复用,但可以看出,使用的PID都是枯燥的数字,如果调台要用户自己输入数字那可是太麻烦了,而且还容易输入错误,操作非常不直观,即 使做成一个菜单让用户选择也是非常的呆板.针对这个问题,DVB系统提出了一个SDT表格,该表格标志一个节目的名称,并且能和PMT中的PID联系起 来,这样用户就可以通过直接选择节目名称来选择节目了.

SDT, Service description section,服务描述段

SDT可以提供的信息包括:

(1) 该节目是否在播放中

(2) 该节目是否被加密

(3) 该节目的名称

SDT定义如下:

各字段定义如下:

table_id:8bits的ID,可以是0x42,表示描述的是当前流的信息,也可以是0x46,表示是其他流的信息(EPG使用此参数)

section_syntax_indicator:段语法标志,一般是'1'

reserved_future_used:2bits保留未来使用

reserved:1bit保留位,防止控制字冲突,一般是'0',也有可能是'1'

section_length:12bits的段长度,单位是Bytes,从transport_stream_id开始,到CRC_32结束(包含)

transport_stream_id:16bits当前描述的流ID

reserved:2bits保留位

version_number:5bits的版本号码,如果数据更新则此字段递增1

current_next_indicator:当前未来标志,一般是'0',表示当前马上使用.

original_netword_id:16bits的原始网络ID号

reserved_future_use:8bits保留未来使用位

接下来是N个节目信息的循环:

service_id:16 bits的服务器ID,实际上就是PMT段中的program_number.

reserved_future_used:6bits保留未来使用位

EIT_schedule_flag:1bit的EIT信息,1表示当前流实现了该节目的EIT传送

EIT_present_following_flag:1bits的EIT信息,1表示当前流实现了该节目的EIT传送

running_status:3bits的运行状态信息:1-还未播放 2-几分钟后马上开始,3-被暂停播出,4-正在播放,其他---保留

free_CA_mode:1bits的加密信息,'1'表示该节目被加密.

紧接着的是描述符,一般是Service descriptor,分析此描述符可以获取servive_id指定的节目的节目名称.具体格式请参考EN300468中的Service descriptor部分.分析完毕,则节目名称和节目号码已经联系起来了.机顶盒程序就可以用这些节目名称代替PID让用户选择,从而实现比较友好的用 户界面!

下面参考一下<>中的界面和显示信息.

上 图是<>打开三个不同的码流文件(*.ts)形成的PID信息和节目名称.用户可以通过切换节目名称的下拉列表框切换节目,也可以 通过"视频流"和"音频流"下拉列表框切换Video和Audio!这些数据都是通过分析PAT,PMT和SDT得到的.

MPEG-2系统原理之第四章:Teletext原理

第四章 Teletext原理

欧洲采用的Teletext 标准叫做"ITU-R System B Teletext",标准文档是EN300472和EN300706.该标准支持以下特性:

(1) 24X40的文本字符显示,也支持简单的图象信息的显示.

(2) 支持多页码,应用程序可以自由切换到任意选定的页.

(3) 支持多语言,可以在teletext中指定所使用的语言.

(4) 文本支持自定义背景色,自定义前景色.支持长度,宽度加倍(double width,double height)

(5) 所有数据采用了奇偶校验和汉明码编码,具有比较强的错误处理功能.

(6) 格式基本兼容模拟TTX,支持VBI插入teletext数据.

Teletext 数据是在TS流中和Video,Audio数据一起传送的.EN300472规定采用以下方法识别teletext数据的PID:如果PMT段中的 stream_type==0xbd(private_stream_1),那么这个数据流就是teletext或者subtitle数据(统称为VBI 数据,具体区分还需要在teletext分析中处理),VBI数据开始于PES包的数据部分.

Teletext在PES包中的格式如下:

各字段含义:

data_identifier:数据标志符,如果是teletext必须等于0x10~0x1f.

data_unit_id:用来标志是teletext数据还是subtitle数据.0x02表示是teletext,0x03表示是subtitle.

data_field()是标准的teletext格式的数据包,参考下图.实际上,一个data_field就是teletext的一行数据.

data_field()的格式如下:

各字段含义如下:

reserved_future_use:2bits保留未来使用

field_parity:1bit的奇偶标志,'1'表示是偶数场(下半场),'0'表示奇数场(上半场)

line_offset:5bits,在VBI插入时指定的场线数据.(以上两个参数在使用VBI硬件插入才需要使用)

framing_code:8bits的帧同步代码,必须是0xe4.

magazine_and_packet_address:16bits,指定当前传送的杂志号码和包号码,采用的是汉明8/4编码.

其中的包号码(Packet address)实际上代表的是TTX页面的行号码(0-24).

data_block:320bits,40Bytes的数据块,全部采用奇偶校验,对应TTX页面的40列,范围是0x00-0x7f(最高位是奇偶校验位).把这部分的数据全部提取出来,就可以获得一个行的全部数据(TTX是24行X40列).

因此,解teletext的软件一般采用这样的流程:

(1) 分析PMT表,获取代表teletext的PID,标注为TTX_pid;

(2) 在解复用程序中过滤PID==TTX_pid的数据,解出PES的数据部分.

(3) 把第二步得到的数据部分全部保存到一个缓冲区,直到所有的数据全部缓冲完毕.

(4) 解出packet address,该数据代表当前的行号(0-24).如果是0,则本个data block包含的是主页面代码和

子页面代码.如果不是0(1-24),则说明data block是对应页的列数据(40个字节的ASCII),把这些数据解出保存到缓冲区.(这里必须和PID过滤一样,过滤主页面号码和子页面号码,即没有选择的页面忽略掉)

(5) 循环第(4)步直到所有的列数据全部解出.

(6) 把缓冲区中的24X40的数据显示出来.一般是在RAM中定义一个unsigned char TTX_DATA[24][40]数组保存.

Teletext是如何支持自定义前景色和背景色等特性的呢?实际上非常简单,就包含在每一行数据的40个字节中.我们知道可显示ASCII的范围是0x20~0x7f,小于0x20的代码在teletext中做为控制字符(需要在显示程序中处理),具体规定如下:

0x00-0x07:设置前景色,颜色分别是黑,红,绿,黄,蓝,洋青,洋蓝,白(设置后生效,也就是说,显示程序遇到这些代码,在随后的显示中必须改变前景色到对应的颜色)

0x08:开始闪烁功能,设置后生效.

0x09:结束闪烁功能,设置后生效

0x0a:BOX结束,设置后生效.

0x0b:BOX开始,设置后生效.

0x0c:正常象素大小,设置后生效.

0x0d:宽度加倍,设置后生效.

0x0e:长度加倍,设置后生效.

0x0f:宽度和长度都加倍,设置后生效.

0x10-0x17:设置马塞克颜色,颜色代码同0x00-0x07,设置后生效.

0x18:以后固定是显示空,直到遇到其他颜色属性.设置后生效.

0x19-0x1b:请参考EN300706标准.

0x1c:设置黑背景色.设置后马上生效.

0x1d:设置新的背景色,下一个字符指定背景颜色,代码同0x0-0x07.

0x1e:保持马塞克功能,设置后生效.

0x1f:取消马塞克功能,设置后生效.

以 上所描述的控制字符作用范围仅仅是一行.也就是说如果遇到新行,则设置全部恢复默认设置,EBU teletext的默认设置是:黑背景色,白前景色,无闪烁,无BOX,正常的象素大小,无任何马塞克功能.因此,teletext的显示程序必须一个字 符一个字符的分析数据,直到所有的数据全部显示完毕.

实际上,EBU teletext使用了4个规格,包括V1.0,V1.5,V2.5,V3.5.V1.0只支持ASCII文本和基本属性,其他规格还支持简单图象和Objects,请参考EN300706获取更多的信息.

EBU teletext格式使用了汉明编码方法,具体编码格式请参考EN300706.

下面可以参考一下<>中处理teletext的效果:

(1) 菜单上的数字是主页面,下一级菜单是子页面:

(2)teletext文字叠加在Video上的透明显示效果:

(3)teletext文字叠加在Video上不透明的显示效果:

(4)切换到其他页面的显示效果:

MPEG-2系统原理之第五章:EPG原理

第五章 EPG原理

EPG 就是"电子节目指南",相当于一个节目菜单的功能.在一个TS流中,可以提供当前流的所有信息,如频率,调制方式,频道号,所有节目的PID,名称等信 息,也可以根据需要提供其他相关联的TS流(例如同一电视台同步播放的其他频率的节目信息)的信息.解码器接收这些信息,形成一个固定格式的菜单让用户选 择需要收看的频道或节目,这就是"EPG".不仅如此,EPG还可以对节目进行分类,比如节目可以是电影,也可以是新闻,这样,把属于电影的节目归在一 起,把属于新闻的节目归在一起,这样对用户来说检索节目就变得非常的方便.

EPG的实现也归功于DVB的SI信息.和EPG功能相关的SI有NIT(网络信息表),EIT(环境信息表),SDT(服务描述表),BAT(群组关联表),TDT(日期时间表)和TOT(时间偏移表).下面简单分析这些表所携带的信息.

NIT,Network Information Table,网络信息表

NIT提供如网络名称(相当于电视台名称),传输参数(如频率,调制方式等).这个表格一般是解码器内部使用的数据,当然也可以做为EPG的一个显示数据提供给用户做为参考.

NIT格式如下:

各字段含义如下:

table_id:8 bits标志,应该是0x40或0x41.当table_id==0x40时候,这个NIT描述的是当前流的网络信息,否则描述的是其他流的网络信息(一般是电视台同步播放的其他TS流信息).

section_syntax_incicator:1bit的段语法标志,应该是'1'

reserved_future_use:1bit保留未来使用位,一般是'0'

reserved:2bits保留位,一般是'00',这是防止控制字冲突而设置的.

section_length:12bits段长度,从network_id开始,到CRC_32(包含)结束的字节总数.

network_id:16bits的网络ID号码,DVB内唯一的一个号码,标志不同的电视台.

Reserved:2bits保留意见位.

version_number:5bits的版本号码,当NIT内容有任何改变时,该字段会递增1(提醒解码器更新NIT信息).

current_next_indicator:1bit的当前下次使用标志,一般是'0'

section_number:8bits的当前段号码.

last_section_number:8bits的当前段号码.

reserved_future_use:4bits保留未来使用,现在应该是'0000'.

network_descriptors_length:12bits网络描述符长度,单位是字节.

descriptor():N个不同的描述符结构,一般是网络名称描述符,解码器在此获取当前的网络名称(即电视台名称)

reserved_future_use:4bits未来保留位,当前应是'0000'.

transport_stream_loop_length:12bits的字节总数,就是随后的循环的字节总数.

transport_stream_id:16bits的网络ID

original_network_id:16bits原始网络ID.如果original_network_id== transport_stream_id说明该TS流是直播节目,否则说明该TS流是转播节目.

transport_descriptors_length:12bits的描述符长度,随后的N个描述符占用的字节总数.

descriptor(),N个描述符,可以有多个连续但不相同的描述符号,如网络名称描述符,传输系统参数描述符,解码器分析这些描述符获取网络的不同信息.

CRC_32:整个段的CRC校验值,一般可以忽略.

EIT, Event Information Table,环境信息表

环境信息表提供如下信息:节目段的标识号、起始时间、节目长度、播放状态、是否加密;指向特定信息的链接信息;节目段多语种的简短介绍;节目段的详细介 绍;两段同样节目段的时间偏移;基本码流类型,如视频的幅型比、伴音的类型、字幕的类型等;使用的加密系统;节目类型,如电影/戏剧、新闻、综艺、体育、 少儿、音乐、艺术、社会政治、文教等;节目限定年龄的级别;给出实现交互式回传信道的电话号码;为满足各节目段的码率而提供的缓存大小信息及私有数据等.

环境信息表中提供了类似于广播电视报所提供的节目表的内容,在SI中,只有EIT才有可能被加密。根据EIT及其它表所提供的信息,可以出五花八门的电子节目指南。-如:按节目类型检索、按时间检索及对某类节目的锁定等.

EIT表格定义如下:

各字段定义如下:

table_id:8bits的表ID,如果当前表是重现/跟随信息,则table_id是0x4e(当前流)或0x4f(其他流),否则如果是时间段信息,则table_id是0x50~0x5f(当前流)或者0x60~0x6f(其他流).

section_syntax_indicator:1bit的段语发标志符,应该是'1'

reserved_future_use:1bit未来保留位,应该是'0'

reserved:2bits的保留位,应该是'00'

section_length:12bits的段长度,单位是bytes,从service_id开始到CRC_32(含)结束.

service_id:16bits的频道号,同PMT中的program_number;

reserved:同上.

version_number:5bitsEIT版本号码.内容有更新则此字段递增1,表示需要更新EIT信息.

current_next_indicator:1bit的当前下次应用标志,一般是'0'

section_number:8bits当前段号码.

last_section_number:8bits最后段号码.

transport_stream_id:16bits的TS流ID.

original_network_id:16bits的原始网络ID.

segment_last_section_number:未知功能.

last_table_id:未知功能.

随后是N个Event的信息:

event_id:16bits环境ID,流唯一数字.

start_time:40bits的开始时间.UTC格式.

duration:24bits的持续时间(节目长度),BCD格式.

running_status:2bits运行状态,定义和PMT中的running_status相同.

free_CA_mode:1bit的是否加密标志,'0'表示没有加密.

descriptors_loop_length:12bits描述符总长度,单位Bytes.

descriptors():N个描述符列表.

TDT和TOT提供的是系统时间信息,结构较简单,请参考EN300468文档!

RST,Running Status Table,播放状态表

RST提供的是TS流中的节目播放状态(是否正在播放等)的信息.

RST格式定义如下:

各字段含义如下:

table_id:8bits表ID标志,应该是0x71.

section_syntax_indicator:1bit的段语法标志,应该是'1'.

reserved_future_user:1bit未来保留位

reserve:2bits保留位.

section_length:12bits段长度,单位Bytes.实际就是随后的for()循环中所有的字节数目.

transport_stream_id:16bits的TS ID,DVB内唯一.

original_network_id:16bits原始网络ID.

serviced_id:16bits节目号,和PMT内的program_number相同含义.

event_id:16bits环境ID,同EIT定义.

reserved_future_use:5bits未来保留位.

running_status:3bits运行状态.0x01表示不在播放中,0x02表示即将播放,0x03表示播放被暂停,0x04表示正在正常播放,其他属于未定义状态.

实际上,以上标准SI表提供出的EPG信息是比较少的,实际上有用的EPG信息都是包含在描述符中,就是Table结构内部的descriptor()字 段中.DVB系统提供了很多标准的descriptor(),不同的描述符展示不同的信息.具体的描述符结构请参考EN300468.

标准描述符简单介绍如下:

(1) Bouquet name descriptor:组名称描述符,提供一个组的名称符号.

(2) CA identifier descriptor:CA系统控制字描述符,提供CA的加密字.

(3) Component descriptor:组件描述符号,提供系统内所有组件的名称等信息.

(4) Content descriptor:内容描述符号,提供系统节目的内容信息(实现按内容检索功能)

(5) Country availability descriptor:有效国家列表描述符号,提供该服务允许使用的国家名称列表.

(6) Data broadcast descriptor:数据广播描述符,提供数据广播信息.

(7) Data broadcast id descriptor:数据广播标志描述符号.

(8) Cable delivery system descriptor:DVB-C传输系统参数描述符,提供DVB-C参数信息.

(9) Satellite delivery system descriptor:DVB-S传输系统参数描述符,提供DVB-S参数信息.

(10) Terrestrial delivery system descriptor:DVB-T传输系统参数描述符,提供DVB-T参数信息.

(11) Extended event descriptor:扩展环境描述符号.

(12) Frequency list descriptor:频率列表描述符,提供所有的频率信息.

(13) Linkage descriptor:可连接描述符.

(14) Local time offset descriptor:当前时间信息.

(15) Mosaic descriptor:马塞克描述符.

(16) Multilingual bouquet name descriptor:多语言代码组名称描述符.

(17) Multilingual component descriptor:多语言组件描述符号.

(18) Multilingual network name descriptor:多语言网络名称描述符.

(19) Multilingual service name descriptor:多语言服务名称描述符.

(20) NVOD reference descriptor:VOD点播参考描述符.

(21) Network name descriptor:网络名称描述符.

(22) Private data specifier descriptor:私有数据描述符.

(23) Short smoothing buffer descriptor:传输速率描述符.

(24) Service descriptor:服务器描述符,提供电视台名称和电视节目名称等信息.

(25) Service list descriptor:节目列表描述符,提供所有的节目频道号和节目类型.

(26) Service move descriptor:节目删除描述符.

(27) Short event descriptor:短消息描述符.

(28) Stream identifier descriptor:流标志描述符.

(29) Stuffing descriptor:填充数据描述符.

(30) Subtitling descriptor:子字幕描述符.

(31) Telephone descriptor:电话号码描述符.

(32) Teletext descriptor:图文信息描述符.

(33) Time shifted event descriptor:时间消逝环境描述符.

以 上描述符结构定义在EN300468,所有的描述符都插入到不同的SI表中,因此描述符的分析应该结合不同的SI表来进行.但是这种插入又是有规律的,如 NIT表只可能插入Terrestrial delivery system descriptor之类或者Network name descriptor,绝对不可能插入Service descriptor!具体插入的什么描述符,只能通过描述符的第一个字节descriptor_tag来判断.

因为EPG的实现是非常灵活的,不同的应用需要不同的EPG功能,因此在<>中没有加入EPG功能.然而实际上,EPG功能比较容易实现,但因为EPG错综复杂的SI,写EPG功能之前还是需要仔细 理清思路才能实现的.

阅读(1276) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~