一、 输入频率、符号率、调制方式锁定频道。
二、 接收当前频道上的PAT表,已知条件是PAT的PID固定为0,将PAT表解析保存。
三、 从PAT中取得NIT表的PID:
方法是:当program_number=0时,取得network_pid。当然将NIT表的PID固定认为是0x0010也是一种解决方法,但这种解决方法不是最基本的方式。
说明:如果从PAT表中找不到NIT的PID,则将NIT的PID默认为0x0010。
四、 根据NIT表的PID取得NIT表,解析并保存。
五、 从NIT表中的第一个descriptor()中取得network_name_descriptor可以得到网络名称,这个一般描述的是网络运营商的名称,可以在屏幕上显示,根据需要显示,不是必须的
六、 从NIT表中的第二个descriptor()循环中取得当前网络所管理的频道资源信息表cable_delivery_system_descriptor(),从中可以得到所有几个频道的关键字段值frequency(频率),modulation(调制方式),symbol_rate(符号率)。至此,网络信息资源已全部获得,这是非常关键的一步。
七、 根据上述网络信息,建上一个循环,分别各自锁定不同的频道。
八、 在已锁定的频道下,接收当前PAT表(PID=0)。通过分析program_number字段就可以知道在当前频道上共播放了多少个节目(服务),记录下每个服务的PMT表,解析并保存。
九、 通过一个PMT表的PID就可以接收这个节目的PMT表,解析并保存。
十、 在PMT表中取得以下几个关键字段:PCR_PID,分别取得流类型字段stream_type各自对应的流的基本PID(elementary_PID),如:当stream_type=0x02时,表示是视频流,那么此时,elementary_PID代表Video_PID,当stream_type=0x04时,表示是音频流,此时,elementary_PID代表Audio_PID.。
这里要着重注意:一个视频配套多个音频PID的情况。说明:到了这一步就可以实现一个节目的播放了。特别申明:在PMT表的第一个descriptor()循环中要检测是否有CA_descriptor()描述,如果有,则取出其中的CA_system_ID和CA_PID。通过这两个PID可以取得关于CA更详细的信息,关于CA这里不做更详细的解释和描述。
十一、接收SDT表,PID固定为0x0011,注意:由于SDT和BAT的PID完全一致,因此要通过table_id来区分,其中(table_id=0x4A表示是BAT表)table_id=0x42表示是当前服务描述SDT表,解析并保存。
说明:table_id=0x46表示是其他频道上的服务描述SDT表
十二、通过service_id(对应PMT表中的program_number)找到各自服务的名称(节目名,如:CCTV-1等)。在SDT表中的service_id中找到service_descriptor(),从中可以取得service_name(如:CCTV-1等)。
注意:这里free_CA_mode不能做为节目是否加密的判断标志,因为在有些加扰器里,并没有对该字段进行修改,比如barco的加扰器就是如此。还要注意两个特殊字段:EIT_schedule_flag,该值为1时,表示在当前频道上出现了时间表(用于报告一个服务里所包含的一天甚至一个月的节目预告)。当EIT_present_following_flag=1时,表示在当前频道上出现了出现/跟随事件信息表(当前时刻/下一时刻的信息)。
十三、从第八步循环,完成的有节目信息的收集:
说明:至此,除了节目时间、内容信息没有收集外,其余的节目信息已收集完毕,包括以下内容:
1、 共多少个频道。
2、 每个频道下有多少套可供播放的节目。
3、 每个节目的名称,相关PCR_PID,V_PID,A_PID等。
根据以上信息可以组织菜单,实现节目的播放了。
注意:要取得多语种描述的节目名称,可以从SDT表中的country_availability_descriptor()字段为:country_code=”CHN”代表中文,”ENG代表英文等”,但是要知道country_availability_descriptor()不是一定会播发的,也就是说这个表可能不存在。
节目内容和时间信息如何获取
一、 接收TDT表
TDT表的PID固定为0x0014,在所有的频道上都有,字段为OTC_time,比如:0xc079124500代表:1993/10/13,12:45:00,取得该时间后,就由STB的定时器自动去计算以后的时间了。
二、 接收EIT表:
在任一频道上可以取得全网的所有的EIT表,EIT表的PID固定为0x0012
当table_id=0x4e时,表示的是当前频道上实际的出现/跟随事件信息
当table_id=0x4f时,表示的是其它频道上的出现/跟随事件信息
当table_id=0x50-0x5f时,表示的是当前频道上的节目时间表
当table_id=0x60-0x6f时,表示的是其它频道上的节目时间表
当table_id=0x4e或0x4f时,如何区分当前出现时间和跟随时间呢?通过section_number 来区分,当section_number= 0x00时表示是当前时刻,当section_number=0x01时,表示的是下一时刻。在EIT表中有几个非常关键的字段,一个是transport_stream_id表示频道,与SDT表中的对应,service_id表示服务号(节目号),同时与PMT表中的program_number对应,如何获取一个节目的事件信息呢?
首先定位频道:transport_stream_id,在该频道下找到要检测的节目service_id
当table_id=0x4e时,表示是当前频道,如果现在手中已有的当前频道的transport_stream_id和在此条件下EIT表中的transport_stream_id能对应上的话,说明正确。
接下来,取得当前信息。方法是判断section_number=0x00的段确定后找到start_time,该事件的开始时间,duration持续时间,duration+start_time就是该事件(节目)的结束时间。通过descriptor()中的short_event_descriptor()可以取得多语种的节目名和节目简介信息,关键同为ISO_639_language_code(比如:“CHN”),event_name_char(比如:“新闻联播”),text_char(节目简介)。
在数字电视中简介部分暂可以不取(text_char)。
注意:当table_id=”0x4e”或”0x4f”时,for(;;)里面描述的事件只有一个。只有当table_id=0x50-0x5f或0x60-0x6f时才能出现多个。同样,取下一时刻信息时,要判断的条件为section_number=0x01。
这里有一个特殊的情况需要处理,那就是当running_status=0时,表示的是NVOD的参考事件描述,duration、start_time、event_name_char、text_char不属于DTV的EPG范畴,遇到这种情况需要屏蔽掉。
通过以上条件的循环,在一个物理频道上,可以取得所有的节目时间表和内容,包括一天或一周、一月、二个月的节目预告。至此,可以形成完整的EPG。
需要注意的事项:
1、 当接收到一个表后,一定要将version_number保存下来,当第二次接收这个表时,如果发现version_number发生了变化,则一定要开始重新接收所有相关联的表。
2、 还有一个可选机制,那就是接收RST表,该表用于描述EIT表的状态变化。RST表的播发不是必须的,不能作为EIT表接收的必要条件。