All pastes #581849 Raw Edit

Something

public text v1 · immutable
·published 2007-06-21 18:59 UTC
rendered paste body
class MusicHash(object):
    subatoms = [['moov'], ['trak', 'udta'], ['mdia', 'meta'], ['minf', 'ilst'], ['stbl'], ['stsd'], []]
    atoms_to_hash = ['mdat', 'oboe', 'apID']

    def __init__(self, data):
        self.data = data
        self.hash_func = md5.new()
        self._hash = None

    def hash__get(self):
        if self._hash != None:
            return self._hash
        return self.calculate_hash()
    hash = property(hash__get)

    def calculate_hash(self):
        if data[4:12] == 'ftypM4A ':
            self.hash_m4a()
        else:
            self.hash_default()
        self._hash = self.hash_func.hexdigest()
        return self._hash

    def hash_default(self):
        self.hash_func.update(self.data)

    def hash_m4a(self):
        self.drm = False
        self.parse_data(self.data, 0)
        
    def parse_data(self, data, depth):
        loc = 0
        while loc < len(data):
            size = struct.unpack('>L', data[loc:loc+4])[0]
            if size == 0:
                atom = data[loc+4:loc+8]
                subdata = data[loc+8:]
                break
            atom = data[loc+4:loc+8]
            subdata = data[loc+8:loc+size]
            if atom in self.subatoms[depth]:
                if atom == 'meta':
                    self.parse_data(subdata[4:], depth+1)
                elif atom == 'stsd':
                    self.parse_data(subdata[8:], depth +1)
                else:
                    self.parse_data(subdata, depth + 1)
            if atom == 'drms':
                self.drm = True
            if atom in self.atoms_to_hash:
                if atom == 'apID' and not self.drm:
                    self.hash_func.update(subdata)
                elif atom != 'apID':
                    self.hash_func.update(data[loc+4:loc+4+size])
            loc += size