实现 CRC 算法
Implementing a CRC algorithm
我正在尝试实现某些视频接口标准中定义的 CRC 算法:
原始数据是 10 位字,被压缩成 8 位字节,我在 numpy 中提取和使用没有问题。
CRC 有多项式:
CRC(X) = X^18 + X^5 + X^4 + 1
我相信这给了我常数:
POLY = 0x40031
我已经尝试了几种不同的实现方式,但我生成的任何东西都与我的示例数据不匹配。
此实现的灵感来自 this
MASK = 0x3FFFF
class MYCRC:
crc_table = []
def __init__(self):
if not self.crc_table:
for i in range(1024):
k = i
for j in range(10):
if k & 1:
k ^= POLY
k >>= 1
self.crc_table.append(k)
def calc(self, crc, data):
crc ^= MASK
for d in data:
crc = (crc >> 10) ^ self.crc_table[(crc & 0x3FF) ^ d]
return crc ^ MASK
然后是我从某个地方(不确定在哪里)提取的这个实现
def crc_calc(crc, p):
crc = MASK & ~crc
for i in range(len(p)):
crc = (crc ^ p[i]) # & BIG_MASK
for j in range(10):
crc = ((crc >> 1) ^ (POLY & -(crc & 1))) # & BIG_MASK
return MASK & ~crc
我还查看了使用 this library,它支持使用自定义多项式,但它似乎是为使用 8 位数据而构建的,而不是我拥有的 10 位数据。
我不确定如何最好地共享测试数据,因为我只有整个帧,如果导出为 numpy 文件大约 5MB。
我也不清楚我应该提供给 CRC 计算的数据范围。我认为从阅读它来看,它应该是从一行中的第一个活动样本开始,直到之后的行的行数,然后是在该范围内计算的校验和。从硬件的角度来看,这是最有意义的,但标准对我来说并不清楚。
编辑:
pastebin 的 10 行测试数据,这包括嵌入式校验和。
在一行数据中,样本 0-7 是 EAV 标记,8-11 是行号,12-16 是两个校验和。数据是两个交错的视频数据流(亮度通道和 CbCr 通道)。
标准规定校验和是 运行 从第一个活动样本到行数据的末尾,我将其解释为从一行的样本 740 到下一行的样本 11 运行s .
根据 SMPTE292M 的第 5 节,数据是 10 位数据,不能低于 0x3 或高于 0x3FC。根据 table 4,CRC 的结果应该是 18 位,它被拆分并作为两个字嵌入到流中(其中一位填充另一位的非)请注意,每个通道都有一个校验和的数据,这两个校验和在每行 12-16
编辑 2
some longer test data 跨越从消隐数据到活动帧数据的跳跃
必须反映CRC计算。 (提示 Table 9 中的注释:“注意 – CRC0 是错误检测代码的 MSB。”)
此 C 例程正确检查示例中的 CRC:
// Update the CRC-18 crc with the low ten bits of word.
// Polynomial = 1000000000000110001
// Reflected (dropping x^18) = 10 0011 0000 0000 0000 = 0x23000
unsigned crc18(unsigned crc, unsigned word) {
crc ^= word & 0x3ff;
for (int k = 0; k < 10; k++)
crc = crc & 1 ? (crc >> 1) ^ 0x23000 : crc >> 1;
return crc;
}
确实,检查的范围是从活动行的开始到行号,一直到流中的两个 CRC 之前。该计算与这两个 CRC 匹配。每个 CRC 都是根据流中的交替字来计算的。 CRC 初始化为零。
我正在尝试实现某些视频接口标准中定义的 CRC 算法:
原始数据是 10 位字,被压缩成 8 位字节,我在 numpy 中提取和使用没有问题。
CRC 有多项式:
CRC(X) = X^18 + X^5 + X^4 + 1
我相信这给了我常数:
POLY = 0x40031
我已经尝试了几种不同的实现方式,但我生成的任何东西都与我的示例数据不匹配。 此实现的灵感来自 this
MASK = 0x3FFFF
class MYCRC:
crc_table = []
def __init__(self):
if not self.crc_table:
for i in range(1024):
k = i
for j in range(10):
if k & 1:
k ^= POLY
k >>= 1
self.crc_table.append(k)
def calc(self, crc, data):
crc ^= MASK
for d in data:
crc = (crc >> 10) ^ self.crc_table[(crc & 0x3FF) ^ d]
return crc ^ MASK
然后是我从某个地方(不确定在哪里)提取的这个实现
def crc_calc(crc, p):
crc = MASK & ~crc
for i in range(len(p)):
crc = (crc ^ p[i]) # & BIG_MASK
for j in range(10):
crc = ((crc >> 1) ^ (POLY & -(crc & 1))) # & BIG_MASK
return MASK & ~crc
我还查看了使用 this library,它支持使用自定义多项式,但它似乎是为使用 8 位数据而构建的,而不是我拥有的 10 位数据。
我不确定如何最好地共享测试数据,因为我只有整个帧,如果导出为 numpy 文件大约 5MB。 我也不清楚我应该提供给 CRC 计算的数据范围。我认为从阅读它来看,它应该是从一行中的第一个活动样本开始,直到之后的行的行数,然后是在该范围内计算的校验和。从硬件的角度来看,这是最有意义的,但标准对我来说并不清楚。
编辑: pastebin 的 10 行测试数据,这包括嵌入式校验和。 在一行数据中,样本 0-7 是 EAV 标记,8-11 是行号,12-16 是两个校验和。数据是两个交错的视频数据流(亮度通道和 CbCr 通道)。 标准规定校验和是 运行 从第一个活动样本到行数据的末尾,我将其解释为从一行的样本 740 到下一行的样本 11 运行s .
根据 SMPTE292M 的第 5 节,数据是 10 位数据,不能低于 0x3 或高于 0x3FC。根据 table 4,CRC 的结果应该是 18 位,它被拆分并作为两个字嵌入到流中(其中一位填充另一位的非)请注意,每个通道都有一个校验和的数据,这两个校验和在每行 12-16
编辑 2 some longer test data 跨越从消隐数据到活动帧数据的跳跃
必须反映CRC计算。 (提示 Table 9 中的注释:“注意 – CRC0 是错误检测代码的 MSB。”)
此 C 例程正确检查示例中的 CRC:
// Update the CRC-18 crc with the low ten bits of word.
// Polynomial = 1000000000000110001
// Reflected (dropping x^18) = 10 0011 0000 0000 0000 = 0x23000
unsigned crc18(unsigned crc, unsigned word) {
crc ^= word & 0x3ff;
for (int k = 0; k < 10; k++)
crc = crc & 1 ? (crc >> 1) ^ 0x23000 : crc >> 1;
return crc;
}
确实,检查的范围是从活动行的开始到行号,一直到流中的两个 CRC 之前。该计算与这两个 CRC 匹配。每个 CRC 都是根据流中的交替字来计算的。 CRC 初始化为零。