Commit 8874ecc0 authored by Robert Kausch's avatar Robert Kausch Committed by Erik de Castro Lopo

Update CRC16 for larger data blocks when decoding.

parent 5579f292
/* libFLAC - Free Lossless Audio Codec library
* Copyright (C) 2000-2009 Josh Coalson
* Copyright (C) 2011-2016 Xiph.Org Foundation
* Copyright (C) 2011-2018 Xiph.Org Foundation
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
......@@ -109,6 +109,7 @@ struct FLAC__BitReader {
uint32_t consumed_words; /* #words ... */
uint32_t consumed_bits; /* ... + (#bits of head word) already consumed from the front of buffer */
uint32_t read_crc16; /* the running frame CRC */
uint32_t crc16_offset; /* the number of words in the current buffer that should not be CRC'd */
uint32_t crc16_align; /* the number of bits in the current consumed word that should not be CRC'd */
FLAC__BitReaderReadCallback read_callback;
void *client_data;
......@@ -117,32 +118,33 @@ struct FLAC__BitReader {
static inline void crc16_update_word_(FLAC__BitReader *br, brword word)
{
register uint32_t crc = br->read_crc16;
#if FLAC__BYTES_PER_WORD == 4
switch(br->crc16_align) {
case 0: crc = FLAC__CRC16_UPDATE((uint32_t)(word >> 24), crc); /* Falls through. */
case 8: crc = FLAC__CRC16_UPDATE((uint32_t)((word >> 16) & 0xff), crc); /* Falls through. */
case 16: crc = FLAC__CRC16_UPDATE((uint32_t)((word >> 8) & 0xff), crc); /* Falls through. */
case 24: br->read_crc16 = FLAC__CRC16_UPDATE((uint32_t)(word & 0xff), crc); /* Falls through. */
}
#elif FLAC__BYTES_PER_WORD == 8
switch(br->crc16_align) {
case 0: crc = FLAC__CRC16_UPDATE((uint32_t)(word >> 56), crc); /* Falls through. */
case 8: crc = FLAC__CRC16_UPDATE((uint32_t)((word >> 48) & 0xff), crc); /* Falls through. */
case 16: crc = FLAC__CRC16_UPDATE((uint32_t)((word >> 40) & 0xff), crc); /* Falls through. */
case 24: crc = FLAC__CRC16_UPDATE((uint32_t)((word >> 32) & 0xff), crc); /* Falls through. */
case 32: crc = FLAC__CRC16_UPDATE((uint32_t)((word >> 24) & 0xff), crc); /* Falls through. */
case 40: crc = FLAC__CRC16_UPDATE((uint32_t)((word >> 16) & 0xff), crc); /* Falls through. */
case 48: crc = FLAC__CRC16_UPDATE((uint32_t)((word >> 8) & 0xff), crc); /* Falls through. */
case 56: br->read_crc16 = FLAC__CRC16_UPDATE((uint32_t)(word & 0xff), crc);
}
#else
for( ; br->crc16_align < FLAC__BITS_PER_WORD; br->crc16_align += 8)
crc = FLAC__CRC16_UPDATE((uint32_t)((word >> (FLAC__BITS_PER_WORD-8-br->crc16_align)) & 0xff), crc);
br->read_crc16 = crc;
#endif
br->crc16_align = 0;
}
static inline void crc16_update_block_(FLAC__BitReader *br)
{
if(br->crc16_align)
crc16_update_word_(br, br->buffer[br->crc16_offset++]);
#if FLAC__BYTES_PER_WORD == 4
br->read_crc16 = FLAC__crc16_update_words32(br->buffer + br->crc16_offset, br->consumed_words - br->crc16_offset, br->read_crc16);
#elif FLAC__BYTES_PER_WORD == 8
br->read_crc16 = FLAC__crc16_update_words64(br->buffer + br->crc16_offset, br->consumed_words - br->crc16_offset, br->read_crc16);
#else
unsigned i;
for(i = br->crc16_offset; i < br->consumed_words; i++)
crc16_update_word_(br, br->buffer[i]);
#endif
br->crc16_offset = 0;
}
static FLAC__bool bitreader_read_from_client_(FLAC__BitReader *br)
{
uint32_t start, end;
......@@ -151,6 +153,8 @@ static FLAC__bool bitreader_read_from_client_(FLAC__BitReader *br)
/* first shift the unconsumed buffer data toward the front as much as possible */
if(br->consumed_words > 0) {
crc16_update_block_(br); /* CRC consumed words */
start = br->consumed_words;
end = br->words + (br->bytes? 1:0);
memmove(br->buffer, br->buffer+start, FLAC__BYTES_PER_WORD * (end - start));
......@@ -328,6 +332,7 @@ void FLAC__bitreader_reset_read_crc16(FLAC__BitReader *br, FLAC__uint16 seed)
FLAC__ASSERT((br->consumed_bits & 7) == 0);
br->read_crc16 = (uint32_t)seed;
br->crc16_offset = br->consumed_words;
br->crc16_align = br->consumed_bits;
}
......@@ -335,6 +340,10 @@ FLAC__uint16 FLAC__bitreader_get_read_crc16(FLAC__BitReader *br)
{
FLAC__ASSERT(0 != br);
FLAC__ASSERT(0 != br->buffer);
/* CRC consumed words up to here */
crc16_update_block_(br);
FLAC__ASSERT((br->consumed_bits & 7) == 0);
FLAC__ASSERT(br->crc16_align <= br->consumed_bits);
......@@ -397,7 +406,6 @@ FLAC__bool FLAC__bitreader_read_raw_uint32(FLAC__BitReader *br, FLAC__uint32 *va
/* (FLAC__BITS_PER_WORD - br->consumed_bits <= bits) ==> (FLAC__WORD_ALL_ONES >> br->consumed_bits) has no more than 'bits' non-zero bits */
*val = (FLAC__uint32)(word & (FLAC__WORD_ALL_ONES >> br->consumed_bits));
bits -= n;
crc16_update_word_(br, word);
br->consumed_words++;
br->consumed_bits = 0;
if(bits) { /* if there are still bits left to read, there have to be less than 32 so they will all be in the next word */
......@@ -416,7 +424,6 @@ FLAC__bool FLAC__bitreader_read_raw_uint32(FLAC__BitReader *br, FLAC__uint32 *va
}
/* at this point bits == FLAC__BITS_PER_WORD == 32; because of previous assertions, it can't be larger */
*val = (FLAC__uint32)word;
crc16_update_word_(br, word);
br->consumed_words++;
return true;
}
......@@ -663,7 +670,6 @@ FLAC__bool FLAC__bitreader_read_unary_unsigned(FLAC__BitReader *br, uint32_t *va
i++;
br->consumed_bits += i;
if(br->consumed_bits >= FLAC__BITS_PER_WORD) { /* faster way of testing if(br->consumed_bits == FLAC__BITS_PER_WORD) */
crc16_update_word_(br, br->buffer[br->consumed_words]);
br->consumed_words++;
br->consumed_bits = 0;
}
......@@ -671,7 +677,6 @@ FLAC__bool FLAC__bitreader_read_unary_unsigned(FLAC__BitReader *br, uint32_t *va
}
else {
*val += FLAC__BITS_PER_WORD - br->consumed_bits;
crc16_update_word_(br, br->buffer[br->consumed_words]);
br->consumed_words++;
br->consumed_bits = 0;
/* didn't find stop bit yet, have to keep going... */
......@@ -789,7 +794,7 @@ FLAC__bool FLAC__bitreader_read_rice_signed_block(FLAC__BitReader *br, int vals[
x = ucbits;
do {
/* didn't find stop bit yet, have to keep going... */
crc16_update_word_(br, br->buffer[cwords++]);
cwords++;
if (cwords >= words)
goto incomplete_msbs;
b = br->buffer[cwords];
......@@ -809,7 +814,7 @@ FLAC__bool FLAC__bitreader_read_rice_signed_block(FLAC__BitReader *br, int vals[
b <<= parameter;
} else {
/* there are still bits left to read, they will all be in the next word */
crc16_update_word_(br, br->buffer[cwords++]);
cwords++;
if (cwords >= words)
goto incomplete_lsbs;
b = br->buffer[cwords];
......@@ -865,7 +870,7 @@ incomplete_lsbs:
if(ucbits == 0 && cwords < words) {
/* don't leave the head word with no unconsumed bits */
crc16_update_word_(br, br->buffer[cwords++]);
cwords++;
ucbits = FLAC__BITS_PER_WORD;
}
......
......@@ -394,3 +394,43 @@ FLAC__uint16 FLAC__crc16(const FLAC__byte *data, uint32_t len)
return crc;
}
FLAC__uint16 FLAC__crc16_update_words32(const FLAC__uint32 *words, uint32_t len, FLAC__uint16 crc)
{
while (len >= 2) {
crc ^= words[0] >> 16;
crc = FLAC__crc16_table[7][crc >> 8 ] ^ FLAC__crc16_table[6][crc & 0xFF ] ^
FLAC__crc16_table[5][(words[0] >> 8) & 0xFF] ^ FLAC__crc16_table[4][ words[0] & 0xFF] ^
FLAC__crc16_table[3][ words[1] >> 24 ] ^ FLAC__crc16_table[2][(words[1] >> 16) & 0xFF] ^
FLAC__crc16_table[1][(words[1] >> 8) & 0xFF] ^ FLAC__crc16_table[0][ words[1] & 0xFF];
words += 2;
len -= 2;
}
if (len) {
crc ^= words[0] >> 16;
crc = FLAC__crc16_table[3][crc >> 8 ] ^ FLAC__crc16_table[2][crc & 0xFF ] ^
FLAC__crc16_table[1][(words[0] >> 8) & 0xFF] ^ FLAC__crc16_table[0][words[0] & 0xFF];
}
return crc;
}
FLAC__uint16 FLAC__crc16_update_words64(const FLAC__uint64 *words, uint32_t len, FLAC__uint16 crc)
{
while (len--) {
crc ^= words[0] >> 48;
crc = FLAC__crc16_table[7][crc >> 8 ] ^ FLAC__crc16_table[6][crc & 0xFF ] ^
FLAC__crc16_table[5][(words[0] >> 40) & 0xFF] ^ FLAC__crc16_table[4][(words[0] >> 32) & 0xFF] ^
FLAC__crc16_table[3][(words[0] >> 24) & 0xFF] ^ FLAC__crc16_table[2][(words[0] >> 16) & 0xFF] ^
FLAC__crc16_table[1][(words[0] >> 8) & 0xFF] ^ FLAC__crc16_table[0][ words[0] & 0xFF];
words++;
}
return crc;
}
......@@ -54,5 +54,7 @@ extern FLAC__uint16 const FLAC__crc16_table[8][256];
#endif
FLAC__uint16 FLAC__crc16(const FLAC__byte *data, uint32_t len);
FLAC__uint16 FLAC__crc16_update_words32(const FLAC__uint32 *words, uint32_t len, FLAC__uint16 crc);
FLAC__uint16 FLAC__crc16_update_words64(const FLAC__uint64 *words, uint32_t len, FLAC__uint16 crc);
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment