I'm trying to calculate the CRC checksum for an ALAsset. My goal is to save all the CRCs and compare them at a later time to see if the asset has been changed, but every time I generate a CRC for the same asset, I get a different result.
To generate CRC:
#import "CRC32.h"
#import <zlib.h>
@implementation CRC32
+ (uint32_t)CRC32Value:(NSData*)data
{
uLong crc = crc32(0L, Z_NULL, 0);
crc = crc32(crc, [data bytes], [data length]);
return crc;
}
@end
How it is used:
void(^assetEnumerator)(ALAsset *, NSUInteger, BOOL *) = ^(ALAsset *result, NSUInteger index, BOOL *stop)
{
if(result == nil)
{
return;
}
CrawlAssetData *assetData = [[CrawlAssetData alloc] init];
[assetData setCrc:[CRC32 CRC32Value:[NSData dataWithBytes:&(result)
length:sizeof(result)]]];
Here are my results when generating the CRC on different occasions for the same asset:
id: 17575
url: assets-library://asset/asset.JPG?id=BB282CBD-F5B1-4771-B48B-E021224C7384&ext=JPG
filesize: 1394332
crc: 3605102491
creationtime: 2456085.397025
id: 17826
url: assets-library://asset/asset.JPG?id=BB282CBD-F5B1-4771-B48B-E021224C7384&ext=JPG
filesize: 1394332
crc: 1383370697
creationtime: 2456085.397025
As you can see, the filesize and url are the same but the CRC is different.
Am I calculating the CRC wrong? Or should I be using a different part of the ALAsset to generate the CRC? Perhaps some data is different every time an ALAsset is retrieved?
Thanks in advance!
This line:
[assetData setCrc:[CRC32 CRC32Value:[NSData dataWithBytes:&(result)
length:sizeof(result)]]];
...is calculating the CRC of the address of your ALAsset instance, not its data.
You can verify this by splitting the line:
NSData *crcData = [NSData dataWithBytes:&(result)
length:sizeof(result)];
NSLog( @"crcData length: %d", [crcData length]);
[assetData setCrc:[CRC32 CRC32Value:crcData]];
My guess is that in the output you'll see crcData length: 4
.
Based on a follow up comment by the question asker (with a correction) the code to do this is:
ALAssetRepresentation *rep = [result defaultRepresentation];
uint8_t *buffer = malloc(rep.size);
NSUInteger buffered = [rep getBytes:buffer
fromOffset:0
length:rep.size
error:nil];
NSData *data = [NSData dataWithBytesNoCopy:buffer
length:buffered
freeWhenDone:YES];
uint32_t CRC32 = [CRC32 CRC32Value:data];
[assetData setCrc:CRC32];
In particular, note that sizeof(NSData*)
(or NSData *a; sizeof(A)
) is always going to be the size of a pointer (4 on 32 bit systems like the iPhone, 8 for 64 bit Mac OS X), not the length of the byte data stored in the NSData
. There's no normal reason to get the sizeof()
a NSObject pointer.