c++checksumcrccrc32

How to modify crc-32 to crc-32/mpeg-2


I am trying to code a function to match CRC 32 output from a device to the actual CRC-32 sum that I calculate. Following is my code:

#include <iostream> 
#include <string.h> 
#define CRC32_POLYNOMIAL 0xEDB88320
using namespace std;
unsigned int crc32b(unsigned char *message,size_t l)
{
   int i, j;
   unsigned int byte, crc, mask;

   i = 0;
   crc = 0xFFFFFFFF;
   while (i<l) {
      byte = message[i];            // Get next byte.
      crc = crc ^ byte;
      for (j = 7; j >= 0; j--) {    // Do eight times.
         mask = -(crc & 1);
         crc = (crc >> 1) ^ (0xEDB88320 & mask);
      }
      i = i + 1;
   }
   return ~crc;
}
int main()
{
    unsigned char Buff[] = {0x91,0xFF,0xFC,0xEA,0xFF,0xFF,0x70,0xFF,0xFD,0x87,0x00,0xFF,0xF9,0x1B,0xFF,0xF3,0x4E,0x00,0xFB,0x00,0x00,0x02,0x01,0xFB};
    unsigned long CRC =  crc32b((unsigned char *)Buff,24);
    cout << hex << CRC <<endl;
    getchar();
    return 0;
}

This gives me the 32 bit CRC output of following payload:

91FFFCEAFFFF70FFFD8700FFF91BFFF34E00FB00000201FB

as 1980AC80. However the device is giving the checksum as 8059143D.

Upon further inspection using online CRC calculators I found that the device is sending out CRC-32/MPEG-2 checksum value. (Can be verified here). I have browsed multiple sites but did not find any straight forward implementation of CRC32/MPEG2 which I can integrate in my code. Can anyone help?


Solution

  • As noted in the crcalc web page, CRC-32/MPEG-2 uses a left shifting (not reflected) CRC along with the CRC polynomial 0x104C11DB7 and initial CRC value of 0xFFFFFFFF, and not post complemented:

    unsigned int crc32b(unsigned char *message, size_t l)
    {
       size_t i, j;
       unsigned int crc, msb;
    
       crc = 0xFFFFFFFF;
       for(i = 0; i < l; i++) {
          // xor next byte to upper bits of crc
          crc ^= (((unsigned int)message[i])<<24);
          for (j = 0; j < 8; j++) {    // Do eight times.
                msb = crc>>31;
                crc <<= 1;
                crc ^= (0 - msb) & 0x04C11DB7;
          }
       }
       return crc;         // don't complement crc on output
    }