BAT表、链接描述符、文件内容与CRC32/MPEG-2校验

2023-10-11 11:30

本文主要是介绍BAT表、链接描述符、文件内容与CRC32/MPEG-2校验,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

BAT表、链接描述符、文件内容与CRC32/MPEG-2校验

0. 前言

这些笔记是几年前学习TS流解析和解复用的时候写的,现在整理出来记录一下。

当时的目标有如下两个:

  1. 解析接受到的TS流
  2. 从TS流中提取BAT表等数据,并解析具体内容。

1. TS包分析

需要解析TS流,先要解析接受到的每个TS包。

1.1 TS包结构

一个TS包由包头和包数据组成,总长度一般为188字节(也可能是204字节)。

包头一般为4字节左右,包含这个TS包的各种信息,剩余的是TS包数据。在数据中,可能会存在调整字节(非有效负载)。

1.2 TS包头和数据分析

TS包头由4字节组成,结构定义如下(C):

// Transport packet header
typedef struct TS_packet_header
{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 adaption_field_control            : 2;unsigned continuity_counter                : 4;
} TS_packet_header;

解析:

数据长度数据含义
sync_byte8bit同步字节,一般是0x47
transport_error_indicator1bit该位值为1时,表示在相关的传送包中至少有一个不可纠正的错误,只有在错误纠正之后,该位才能被重新置0。
payload_unit_start_indicator1bit该字段用来表示TS包的有效净荷有PES包或者PSI数据的情况。payload_unit_start_indicator为1时,在前4个字节之后会有一个调整字节,它的数值决定了负载内容的具体开始位置。例如:47 40 00 17 00第五个字节是00,说明紧跟着00之后就是具体的负载内容(有效负载)。
transport_priority1bit传输优先级,1为高优先级
PID12bitPacket ID号码,唯一的号码对应不同的包
transport_scrambling_control2bit加密标志(00:未加密;其他表示已加密)
adaptation_field_control2bit表示传送流包首部是否跟随有调整字段。01仅含有效负载,10仅含调整字段,11含有调整字段和有效负载。为00的话解码器不进行处理。
continuity_counter4bit范围0-15,具有相同的PID的TS分组传输时每次加1,到15后清0。不过,有些情况下是不计数的。如下:(1)TS分组无有效负载。(2)复制的TS分组和原分组这个值一样。(3)标志discontinuity_indicator为1时。

参考:

http://www.cnblogs.com/shakin/p/3714848.html
http://www.cnblogs.com/jiangzhaowei/p/3625944.html

TS流调整参考:http://blog.csdn.net/cabbage2008/article/details/49837143
较详细的数据结构:http://blog.csdn.net/a31898534/article/details/4399353

可用以下代码结合上文协同了解(http://blog.csdn.net/a31898534/article/details/4399353 )。

transport_packet() {sync_byte                                                                    // 8transport_error_indicator                                          //1payload_unit_start_indicator                                    //1transport_priority                                                       // 1PID                                                                             //13transport_scrambling_control                                  // 2adaptation_field_control                                            //2continuity_counter                                                      //4if(adaptation_field_control=='10'  || adaptation_field_control=='11') {adaptation_field()}if(adaptation_field_control=='01' || adaptation_field_control=='11') {for (i=0; i<N; i++) {data_byte                                                                   //8}}
}

2. BAT表语法解析

2.1 BAT表简介

BAT表的一个片段如下(包含表头,不含TS包的同步字节内容)

PositionHexText
00004a f2 ed 70 11 ff 00 00 f2 e0 47 08 64 61 74 61 63 61J…p…G.dataca
001273 74 4a f5 00 01 00 01 a0 01 80 02 00 90 5f 00 00 00stJ…_…
002400 01 02 00 02 07 00 03 07 00 04 07 00 05 07 00 06 01
003600 07 01 00 08 01 00 09 01 00 0a 01 00 0b 08 00 0c 08
004800 0d 08 00 0e 08 00 0f 03 00 10 00 00 11 00 00 12 00

2.2 BAT表的语法和解析

BAT表语法如下:

语法表中(只说明几个重要的):

语法长度(Bit)解析
table_id8用于确定表类型,0x4A代表bouquet_association_section
section_syntax_indicator1段语法标志,此处必须是1
section_length12段长,单位Byte
bouquet_id16Bouquet表ID,在数据广播中此处为0x7011
version_number5数据版本号,从0起递增,到1f后归零
current_next_indicator1置于‘1’时指示发送的有条件访问表为当前有效的。该比特设置为‘0’时,它指示发送的有条件访问表尚未有效并且下一个有条件访问表将生效
section_number8(分段传输表时的)本段编号,第一段表编号应为0x00
last_section_number8最后一段编号
descriptor-描述符

|CRC32|4|从表头到数据的最后一字节的CRC32校验,算法使用CRC32/MPEG-2

上图中从最后一个reserved_future_use到最后的CRC32前的大括号均未在此出现

按照上述表格解析例子中的BAT表,得出以下结果(descriptor部分在后文进行分析):

2.3 链接描述符linkage_descriptor

在上文给出的例子中,从0xa开始的内容是链接描述符。

链接描述符的语法如下:

其中值得注意的是:

  • descriptor_tag:在这里有两种descriptor_tag。tag = 0x47是表名,不用注意此段数据。tag = 0x4A才是值得注意的数据。
  • linkage_type:链接类型,在这里是0x80。
  • PID:文件信息所在的PID。
  • table_ext_id:实际上就是文件编号
  • last_section_num:该文件编号对应的文件在传输中的总段数

2.4 解析用途

对BAT表的解析主要是为了了解一下信息:

  1. 文件内容所在的PID
  2. 文件总数和每个文件总段数。

3. CRC32/MPEG2校验

3.1 CRC32/MPEG2参数模型

该校验的参数模型如下:

其中各参数定义:

  • NAME:名称

  • WIDTH:宽度,即CRC比特数

  • POLY:生成项的简写。以16进制表示,即是0x04C11DB7。忽略了最高位的"1",即完整的生成项是0x104C11DB7。重要的一点是,这是“未颠倒”的生成项!前面说过,“颠倒的”生成项是0xEDB88320。

  • INIT:这是算法开始时寄存器的初始化预置值,十六进制表示。这个值可以直接赋值给“直驱表法”算法中的寄存器,作为寄存器的初始值!
    而对于“驱动表法”算法及“直接计算法”,寄存器的初始值必须是0!前面几次循环先将待测数据移入到寄存器中,当寄存器装满后,再用这个初始化预置值去XOR寄存器,这样寄存器就被这个值初始化了!
    这点很重要!!如果在“驱动表法”算法开始时,寄存器的初始值不为0,那么寄存器中的值就会相当于是待测数据了,这样算出的CRC结果就不对了!我们的目的是用预置值去初始化寄存器,而不是将预置值作为待测数据去处理!

  • REFIN 这个值是真TRUE或假FALSE。
    如果这个值是FALSE,表示待测数据的每个字节都不用“颠倒”,即BIT7仍是作为最高位,BIT0作为最低位。
    如果这个值是TRUE,表示待测数据的每个字节都要先“颠倒”,即BIT7作为最低位,BIT0作为最高位。

  • REFOUT:这个值是真TRUE或假FALSE。
    如果这个值是FALSE,表示计算结束后,寄存器中的值直接进入XOROUT处理即可。
    如果这个值是TRUE,表示计算结束后,寄存器中的值要先“颠倒”,再进入XOROUT处理。注意,这是将整个寄存器的值颠倒,因为寄存器的各个字节合起来表达了一个值,如果只是对各个字节各自颠倒,那结果值就错误了。

  • XOROUT:这是W位长的16进制数值。
    这个值与经REFOUT后的寄存器的值相XOR,得到的值就是最终正式的CRC值!

参考:http://www.360doc.com/content/14/0513/22/7991404_377367845.shtml

3.2 CRC32/MPEG2校验的Java实现

算法的实现使用CRC32表的方式,整体代码如下:

public class TsCRC32Utils {static final long[] CrcTable = {0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7,0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3,0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef,0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb,0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4,0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08,0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc,0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050,0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1,0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5,0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9,0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd,0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2,0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e,0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a,0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676,0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4};public static int CRC32(byte[] indata) {int i;int crc = 0xFFFFFFFF;for(i = 0; i < indata.length; i++)crc = (int) ((crc << 8) ^ CrcTable[(int) (((crc >> 24) ^ indata[i]) & 0xFF)]);return crc;}
}

4. ABS文件内容的获取

ABS文件内容所在的PID可通过分析BAT表来读取。

此处的PID为0x200。

4.1 语法分析


先放一段例子进行分析:

000005c0h: 90 B6 3E 0E 4F FF 00 00 0F 32 32 38 5F 32 33 34 ; 惗>.O...228_234
000005d0h: 5F 30 30 37 2E 78 6D 6C 00 00 06 21 3C 3F 78 6D ; _007.xml...!<?xm
000005e0h: 6C 20 76 65 72 73 69 6F 6E 3D 22 31 2E 30 22 20 ; l version="1.0" 

table_id:此处必定是0x90。
section_syntax_indicator:必须是1。
section_length:本段长度(Byte)。
table_id_ext:文件编号(和BAT表里的保持一致)
section_number:当前段编号
last_section_number:最后一段编号,和BAT表里的信息一致
file_data_length:文件长度(注意:这里的文件长度是指本段的长度)

4.2 注意事项

  1. 实际使用时必须使用CRC32/MPEG-2校验接收到的数据。
  2. 注意判断文件是否接收完成。
  3. 注意内存的使用情况。

这篇关于BAT表、链接描述符、文件内容与CRC32/MPEG-2校验的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/187742

相关文章

Python将博客内容html导出为Markdown格式

《Python将博客内容html导出为Markdown格式》Python将博客内容html导出为Markdown格式,通过博客url地址抓取文章,分析并提取出文章标题和内容,将内容构建成html,再转... 目录一、为什么要搞?二、准备如何搞?三、说搞咱就搞!抓取文章提取内容构建html转存markdown

Java进行文件格式校验的方案详解

《Java进行文件格式校验的方案详解》这篇文章主要为大家详细介绍了Java中进行文件格式校验的相关方案,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、背景异常现象原因排查用户的无心之过二、解决方案Magandroidic Number判断主流检测库对比Tika的使用区分zip

使用Python实现获取网页指定内容

《使用Python实现获取网页指定内容》在当今互联网时代,网页数据抓取是一项非常重要的技能,本文将带你从零开始学习如何使用Python获取网页中的指定内容,希望对大家有所帮助... 目录引言1. 网页抓取的基本概念2. python中的网页抓取库3. 安装必要的库4. 发送HTTP请求并获取网页内容5. 解

Python实现常用文本内容提取

《Python实现常用文本内容提取》在日常工作和学习中,我们经常需要从PDF、Word文档中提取文本,本文将介绍如何使用Python编写一个文本内容提取工具,有需要的小伙伴可以参考下... 目录一、引言二、文本内容提取的原理三、文本内容提取的设计四、文本内容提取的实现五、完整代码示例一、引言在日常工作和学

Java中使用注解校验手机号格式的详细指南

《Java中使用注解校验手机号格式的详细指南》在现代的Web应用开发中,数据校验是一个非常重要的环节,本文将详细介绍如何在Java中使用注解对手机号格式进行校验,感兴趣的小伙伴可以了解下... 目录1. 引言2. 数据校验的重要性3. Java中的数据校验框架4. 使用注解校验手机号格式4.1 @NotBl

SpringBoot使用Jasypt对YML文件配置内容加密的方法(数据库密码加密)

《SpringBoot使用Jasypt对YML文件配置内容加密的方法(数据库密码加密)》本文介绍了如何在SpringBoot项目中使用Jasypt对application.yml文件中的敏感信息(如数... 目录SpringBoot使用Jasypt对YML文件配置内容进行加密(例:数据库密码加密)前言一、J

使用Python快速实现链接转word文档

《使用Python快速实现链接转word文档》这篇文章主要为大家详细介绍了如何使用Python快速实现链接转word文档功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 演示代码展示from newspaper import Articlefrom docx import

如何解决Pycharm编辑内容时有光标的问题

《如何解决Pycharm编辑内容时有光标的问题》文章介绍了如何在PyCharm中配置VimEmulator插件,包括检查插件是否已安装、下载插件以及安装IdeaVim插件的步骤... 目录Pycharm编辑内容时有光标1.如果Vim Emulator前面有对勾2.www.chinasem.cn如果tools工

C#比较两个List集合内容是否相同的几种方法

《C#比较两个List集合内容是否相同的几种方法》本文详细介绍了在C#中比较两个List集合内容是否相同的方法,包括非自定义类和自定义类的元素比较,对于非自定义类,可以使用SequenceEqual、... 目录 一、非自定义类的元素比较1. 使用 SequenceEqual 方法(顺序和内容都相等)2.

Spring常见错误之Web嵌套对象校验失效解决办法

《Spring常见错误之Web嵌套对象校验失效解决办法》:本文主要介绍Spring常见错误之Web嵌套对象校验失效解决的相关资料,通过在Phone对象上添加@Valid注解,问题得以解决,需要的朋... 目录问题复现案例解析问题修正总结  问题复现当开发一个学籍管理系统时,我们会提供了一个 API 接口去