OggFile's CRC checksum

作者在研究live555过程中发现其流化的opus文件无法被VLC播放,进一步研究发现是由于CRC32_IEEE校验和计算不一致导致。通过分析libogg源码并更新自己的CRC32实现,解决了这一问题。

这几天研究 live555,然而蛋疼滴发现它流化的 opus 文件,VLC 居然无法播放,于是想了解一下 opus 文件,看了 live555 的 OggFileParser 代码,发现 checksum 都被无视了,本来 UMU 也应该无视这个细节的,然而随便用自己以前写的 CRC32 代码验证了一下,居然不一样!而这份代码之前是测试过的,和 7-Zip 的 CRC-32 算出来是一致的。

因为 opus 文件是基于 ogg 文件格式的,所以阅读了一下 Ogg Documentation,发现确实不一样,它用的其实是 CRC32_IEEE,于是参考了 libogg 的 framing.c 和 ffmpeg\libavutil\crc.c 把自己的代码库给更新了,使用模版增强功能:

#pragma region "CRC"
// CRC_8_ATM        <false,  8,       0x07, 0>
// CRC_16_ANSI      <false, 16,     0x8005, 0>
// CRC_16_CCITT     <false, 16,     0x1021, 0>
// CRC_24_IEEE      <false, 24,   0x864CFB, 0>
// CRC_32_IEEE      <false, 32, 0x04C11DB7, 0>  -> OggFile's Checksum
// CRC_32_IEEE_LE   <true,  32, 0xEDB88320, 0>
// CRC_16_ANSI_LE   <true,  16,     0xA001, 0>
// defualt          <true,  32, 0xEDB88320, 0xFFFFFFFF>, 7 - Zip's CRC-32
template <bool kIsLE = true, uint8_t kBits = 32, uint32_t kPolynomial = 0xEDB88320, uint32_t kXorOut = 0xFFFFFFFF>
class CRC
{
public:
    CRC()
    {
        static_assert (kBits >= 8 && kBits <= 32 && kPolynomial < (1LL << kBits), "invalid bits");

        for (int i = 0; i < 256; ++i) {
            if (kIsLE) {
                register uint32_t crc = i;
                for (int j = 8; j > 0; --j) {
                    crc = (crc >> 1) ^ (kPolynomial & (-static_cast<int32_t>(crc & 1)));
                }
                crc32_table_[i] = crc;
            } else {
                register uint32_t crc = i << 24;
                for (int j = 8; j > 0; --j) {
                    crc = (crc << 1) ^ ((kPolynomial << (32 - kBits)) & (static_cast<int32_t>(crc) >> 31));
                }
                crc32_table_[i] = be2me_32(crc);
            }
        }
    }

    uint32_t GetCRC(uint32_t crcinit, const uint8_t* data, size_t data_size)
    {
        register uint32_t crc = crcinit ^ kXorOut;

        /* process not aligned message head */
        for (; (3 & (data - (uint8_t*)0)) && data_size > 0; ++data, --data_size) {
            crc = crc32_table_[static_cast<uint8_t>(crc) ^ *data] ^ (crc >> 8);
        }

        /* fast CRC32 calculation of a DWORD-aligned message */
        for (const uint8_t* e = data + (data_size & ~15); data < e; data += 4) {
            crc ^= le2me_32(*reinterpret_cast<const uint32_t *>(data));
            crc = crc32_table_[crc & 0xFF] ^ (crc >> 8);
            crc = crc32_table_[crc & 0xFF] ^ (crc >> 8);
            crc = crc32_table_[crc & 0xFF] ^ (crc >> 8);
            crc = crc32_table_[crc & 0xFF] ^ (crc >> 8);
        }

        /* process not aligned message tail */
        for (const uint8_t* e = data + (data_size & 15); data < e; ++data) {
            crc = crc32_table_[static_cast<uint8_t>(crc) ^ *data] ^ (crc >> 8);
        }
        return crc ^ kXorOut;
    }

private:
    uint32_t crc32_table_[256];
};
#pragma endregion

转载于:https://my.oschina.net/umu618/blog/1499874

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值