def decompress(compressed_data, c): br = BitReader(compressed_data) state = LzwState(c) state.clear() d = {} htab = {} output = [] output2 = [] while True: if br.isEnd(): return [] cur_code = br.getBits(state.req_bits) incode = cur_code if cur_code == state.M_EOD: break if cur_code == state.M_CLR: state.clear() else: if cur_code == state.next_code: cur_code = state.oldcode output.append(state.finchar) while cur_code >= state.M_CLR: if cur_code not in htab: return [] output.append(htab[cur_code]) cur_code = d[cur_code + 1] state.finchar = cur_code while True: output2.append(cur_code) if not output: break cur_code = output.pop() if state.next_code < 4096 and state.oldcode != -1: d[state.next_code + 1] = state.oldcode htab[state.next_code] = state.finchar state.next_code += 1 if state.next_code >= state.next_shift: if state.req_bits < 12: state.req_bits += 1 state.next_shift = 1 << state.req_bits state.oldcode = incode return bytes(output2)
def _parseSliceNALUnit(self, start, limit): sliceParser = BitReader(self.dataBuffer[start:limit]) sliceParser.skipBytes(4) sliceParser.readUnsignedExpGolombCodedInt() sliceType = sliceParser.readUnsignedExpGolombCodedInt() #print "{} Frame - Time: {}".format(self._getSliceTypeName(sliceType), self.timeUs) self._addNewFrame(sliceType, self.timeUs)
def _parseSEINALUnit(self, start, limit): seiParser = BitReader(self.dataBuffer[start:limit]) seiParser.skipBytes(4) # Parse payload type payloadType = 0 while True: data = seiParser.readUnsignedByte() payloadType += data if (data != 0xFF): break; # Parse payload size payloadSize = 0 while True: data = seiParser.readUnsignedByte() payloadSize += data if (data != 0xFF): break;
def __init__(self, data): self.__DDecode = [0] * 64 ## DC self.__DBits = [0] * 64 self.__Bits = 0 self.__initarrays() self.__bitreader: BitReader = None self.__tablesread3 = False self.__unpackblocktables = { "LD": DecodeTable(), "DD": DecodeTable(), "LDD": DecodeTable(), "RD": DecodeTable(), "BD": DecodeTable() } self.__prevlowdist = 0 self.__lowdistrepcount = 0 if data is not None: self.__bitreader = BitReader(data) self.__readTables30()
def prepare(self): self._findContainerType() if (self.containerType == self.CONTAINER_MPEG_TS): self._readHeader() self.readSamples() else: dataParser = BitReader(self.data) self.tracks[0] = PESReader(0, PESReader.TS_STREAM_TYPE_AAC) self.tracks[0].appendData(0, dataParser) self.tracks[0].payloadReader.consumeData(self.lastPts)
def test_bit_reader(): data = [0xfe, 0x8f, 0x00, 0xa0] reader = BitReader(data) print( hex(reader.readBits(1)) ) # 0x1 print( hex(reader.readUnsignedByte() )) #0xfd print( hex(reader.readBits(3) )) #0x0 print( hex(reader.readBits(3) )) #0x7 print( hex(reader.readBits(3) )) #0x4 print( hex(reader.readBits(3) )) #0x0 print( hex(reader.readBits(3) )) #0x0
def _parseSEINALUnit(self, start, limit): seiParser = BitReader(self.dataBuffer[start:limit]) seiParser.skipBytes(4) while True: data = seiParser.readUnsignedByte() if (data != 0xFF): break # Parse payload size while True: data = seiParser.readUnsignedByte() if (data != 0xFF): break
def _processTSPacket(self, packet): self.packetsCount = self.packetsCount + 1 packetParser = BitReader(packet) packetParser.skipBits(1) payload_unit_start_indicator = (packetParser.readBits(1) != 0) packetParser.skipBits(1) pid = packetParser.readBits(13) adaptation_field = (packetParser.readUnsignedByte() & 0x30) >> 4 if (adaptation_field > 1): length = packetParser.readUnsignedByte() if (length > 0): packetParser.skipBytes(length) if (adaptation_field == 1 or adaptation_field == 3): if (pid == 0): self._parseProgramId(payload_unit_start_indicator, packetParser) elif (pid == self.pmtId): self._parseProgramTable(payload_unit_start_indicator, packetParser) else: track = self.tracks[pid] if (track is not None): track.appendData(payload_unit_start_indicator, packetParser)
def _parseSPSNALUnit(self, start, limit): spsParser = BitReader(self.dataBuffer[start:limit]) spsParser.skipBytes(4) self.profileId = spsParser.readBits(8) self.levelId = spsParser.readBits(8) spsParser.skipBytes(1) spsParser.readUnsignedExpGolombCodedInt() chromaFormatIdc = 1 # default is 4:2:0 if (self.profileId == 100 or self.profileId == 110 or self.profileId == 122 or self.profileId == 244 or self.profileId == 44 or self.profileId == 83 or self.profileId == 86 or self.profileId == 118 or self.profileId == 128 or self.profileId == 138): chromaFormatIdc = spsParser.readUnsignedExpGolombCodedInt() if (chromaFormatIdc == 3): spsParser.skipBits(1) spsParser.readUnsignedExpGolombCodedInt() # bit_depth_luma_minus8 spsParser.readUnsignedExpGolombCodedInt() # bit_depth_chroma_minus8 spsParser.skipBits(1) # qpprime_y_zero_transform_bypass_flag seqScalingMatrixPresentFlag = spsParser.readBit() if (seqScalingMatrixPresentFlag == 1): limit = 12 if (chromaFormatIdc != 3): limit = 8 for i in range(0, limit): seqScalingListPresentFlag = spsParser.readBit() if (seqScalingListPresentFlag == 1): if (i < 6): self._skipScalingList(spsParser, 16) else: self._skipScalingList(spsParser, 64) spsParser.readUnsignedExpGolombCodedInt() # log2_max_frame_num_minus4 picOrderCntType = spsParser.readUnsignedExpGolombCodedInt() if (picOrderCntType == 0): spsParser.readUnsignedExpGolombCodedInt() # log2_max_pic_order_cnt_lsb_minus4 elif (picOrderCntType == 1): spsParser.skipBits(1) # delta_pic_order_always_zero_flag spsParser.readSignedExpGolombCodedInt() # offset_for_non_ref_pic spsParser.readSignedExpGolombCodedInt() # offset_for_top_to_bottom_field numRefFramesInPicOrderCntCycle = spsParser.readUnsignedExpGolombCodedInt( ) for i in range(0, numRefFramesInPicOrderCntCycle): spsParser.readSignedExpGolombCodedInt() #offset_for_ref_frame[i] self.numRefFrames = spsParser.readUnsignedExpGolombCodedInt() # max_num_ref_frames spsParser.skipBits(1) # gaps_in_frame_num_value_allowed_flag picWidthInMbs = spsParser.readUnsignedExpGolombCodedInt() + 1 picHeightInMapUnits = spsParser.readUnsignedExpGolombCodedInt() + 1 frameMbsOnlyFlag = spsParser.readBit() frameHeightInMbs = picHeightInMapUnits if (frameMbsOnlyFlag == 0): frameHeightInMbs += picHeightInMapUnits spsParser.skipBits(1) # mb_adaptive_frame_field_flag spsParser.skipBits(1) # direct_8x8_inference_flag self.frameWidth = picWidthInMbs * 16 self.frameHeight = frameHeightInMbs * 16 frameCroppingFlag = spsParser.readBit() if (frameCroppingFlag == 1): frameCropLeftOffset = spsParser.readUnsignedExpGolombCodedInt() frameCropRightOffset = spsParser.readUnsignedExpGolombCodedInt() frameCropTopOffset = spsParser.readUnsignedExpGolombCodedInt() frameCropBottomOffset = spsParser.readUnsignedExpGolombCodedInt() cropUnitX, cropUnitY = 0, 0 if (chromaFormatIdc == 0): cropUnitX = 1 cropUnitY = 2 - (1 if (frameMbsOnlyFlag == 1) else 0) else: subWidthC = (1 if (chromaFormatIdc == 3) else 2) subHeightC = (2 if (chromaFormatIdc == 1) else 1) cropUnitX = subWidthC cropUnitY = subHeightC * (2 - (1 if (frameMbsOnlyFlag == 1) else 0)) self.frameWidth -= (frameCropLeftOffset + frameCropRightOffset) * cropUnitX self.frameHeight -= (frameCropTopOffset + frameCropBottomOffset) * cropUnitY vui_parameters_present_flag = spsParser.readBit() if (vui_parameters_present_flag == 1): aspect_ratio_info_present_flag = spsParser.readBit() if (aspect_ratio_info_present_flag == 1): aspect_ratio_idc = spsParser.readUnsignedByte() if (aspect_ratio_idc == self.H264_ASPECT_RATIO_EXTENDED_SAR): self.aspectRatioNum = spsParser.readBits(16) self.aspectRatioDen = spsParser.readBits(16) else: self.aspectRatioNum = self.H264_ASPECT_RATIO_PIXEL_ASPECT[ aspect_ratio_idc][0] self.aspectRatioDen = self.H264_ASPECT_RATIO_PIXEL_ASPECT[ aspect_ratio_idc][1] if (self.aspectRatioNum != 0): self.displayAspectRatio = Fraction( self.frameWidth * self.aspectRatioNum, self.frameHeight * self.aspectRatioDen)
def _parseAUDNALUnit(self, start, limit): audParser = BitReader(self.dataBuffer[start:limit]) audParser.skipBytes(4)
class Unpack29: def __init__(self, data): self.__DDecode = [0] * 64 ## DC self.__DBits = [0] * 64 self.__Bits = 0 self.__initarrays() self.__bitreader: BitReader = None self.__tablesread3 = False self.__unpackblocktables = { "LD": DecodeTable(), "DD": DecodeTable(), "LDD": DecodeTable(), "RD": DecodeTable(), "BD": DecodeTable() } self.__prevlowdist = 0 self.__lowdistrepcount = 0 if data is not None: self.__bitreader = BitReader(data) self.__readTables30() def __initarrays(self): if self.__DDecode[1] == 0: Dist = 0 BitLength = 0 Slot = 0 for I in range(len(DBitLengthCounts)): for _ in range(DBitLengthCounts[I]): self.__DDecode[Slot] = Dist self.__DBits[Slot] = BitLength Slot += 1 Dist += (1 << BitLength) BitLength += 1 def __readTables30(self): BitLength = bytearray(BC) Table = bytearray(HUFF_TABLE_SIZE30) UnpOldTable = bytearray(HUFF_TABLE_SIZE30) BitField = self.__bitreader.Read16() if BitField & 0x8000: pass # BLOCK_PPM if (BitField & 0x4000) == 0: ##reset old table UnpOldTable = bytearray(HUFF_TABLE_SIZE30) self.__prevlowdist = 0 self.__lowdistrepcount = 0 self.__bitreader.AddBits(2) I = 0 while I < BC: Length = self.__bitreader.Read16() >> 12 self.__bitreader.AddBits(4) if Length == 15: ZeroCount = self.__bitreader.Read16() >> 12 self.__bitreader.AddBits(4) if ZeroCount == 0: BitLength[I] = 15 else: ZeroCount += 2 while ZeroCount > 0 and I < len(BitLength): BitLength[I] = 0 I += 1 ZeroCount -= 1 I -= 1 else: BitLength[I] = Length I += 1 self.__makedecodetables(BitLength, self.__unpackblocktables["BD"], BC30) tablesize = HUFF_TABLE_SIZE30 i = 0 while i < tablesize: number = self.__decodenumber(self.__unpackblocktables["BD"]) if number < 16: Table[i] = (number + UnpOldTable[i]) & 0xf i += 1 else: if number < 18: n = 0 if number == 16: n = (self.__bitreader.Read16() >> 13) + 3 self.__bitreader.AddBits(3) else: n = (self.__bitreader.Read16() >> 9) + 11 self.__bitreader.AddBits(7) if i == 0: return False else: while n > 0 and i < tablesize: n -= 1 Table[i] = Table[i - 1] i += 1 else: n = 0 if number == 18: n = (self.__bitreader.Read16() >> 13) + 3 self.__bitreader.AddBits(3) else: n = (self.__bitreader.Read16() >> 9) + 11 self.__bitreader.AddBits(7) while n > 0 and i < tablesize: n -= 1 Table[i] = 0 i += 1 self.__tablesread3 = True self.__makedecodetables(Table, self.__unpackblocktables['LD'], NC30) self.__makedecodetables(Table[NC30:], self.__unpackblocktables['DD'], DC30) self.__makedecodetables(Table[NC30 + DC30:], self.__unpackblocktables['LDD'], LDC30) self.__makedecodetables(Table[NC30 + DC30 + LDC30:], self.__unpackblocktables['RD'], RC30) UnpOldTable[:] = Table return True def __makedecodetables(self, lengthtable, decodetable: DecodeTable, size): decodetable.MaxNum = size lengthcount = [0] * 16 for i in range(size): lengthcount[lengthtable[i] & 0xf] += 1 lengthcount[0] = 0 decodetable.DecodeNum = [0] * len(decodetable.DecodeNum) decodetable.DecodePos[0] = 0 decodetable.DecodeLen[0] = 0 upperlimit = 0 for i in range(1, 16): upperlimit += lengthcount[i] leftaligned = upperlimit << (16 - i) upperlimit *= 2 decodetable.DecodeLen[i] = leftaligned decodetable.DecodePos[i] = decodetable.DecodePos[ i - 1] + lengthcount[i - 1] copydecodepos = [0] * len(decodetable.DecodePos) copydecodepos[:] = decodetable.DecodePos for i in range(size): curbitlength = lengthtable[i] & 0xf if curbitlength != 0: LastPos = copydecodepos[curbitlength] decodetable.DecodeNum[LastPos] = i copydecodepos[curbitlength] += 1 if size in (NC, NC30): decodetable.QuickBits = MAX_QUICK_DECODE_BITS else: decodetable.QuickBits = MAX_QUICK_DECODE_BITS - 3 quickdatasize = 1 << decodetable.QuickBits curbitlength = 1 for code in range(quickdatasize): bitfield = code << (16 - decodetable.QuickBits) while curbitlength < len(decodetable.DecodeLen) and \ bitfield>=decodetable.DecodeLen[curbitlength]: curbitlength += 1 decodetable.QuickLen[code] = curbitlength dist = bitfield - decodetable.DecodeLen[curbitlength - 1] dist >>= (16 - curbitlength) if curbitlength < len(decodetable.DecodePos): pos = decodetable.DecodePos[curbitlength] + dist if pos < size: decodetable.QuickNum[code] = decodetable.DecodeNum[pos] else: decodetable.QuickNum[code] = 0 else: decodetable.QuickNum[code] = 0 def __decodenumber(self, decodetable: DecodeTable): bitfield = self.__bitreader.Read16() & 0xfffe if bitfield < decodetable.DecodeLen[decodetable.QuickBits]: code = bitfield >> (16 - decodetable.QuickBits) self.__bitreader.AddBits(decodetable.QuickLen[code]) return decodetable.QuickNum[code] bits = 15 for i in range(decodetable.QuickBits + 1, 15): if bitfield < decodetable.DecodeLen[i]: bits = i break self.__bitreader.AddBits(bits) dist = bitfield - decodetable.DecodeLen[bits - 1] dist >>= (16 - bits) pos = decodetable.DecodePos[bits] + dist if pos > decodetable.MaxNum: pos = 0 return decodetable.DecodeNum[pos] @property def DDecode(self): return self.__DDecode @property def DBits(self): return self.__DBits @property def UnpackBlockTables(self): return self.__unpackblocktables
def _parseAACHeader(self, start): aacHeaderParser = BitReader(self.dataBuffer[start:start + self.ADTS_SYNC_SIZE + self.ADTS_HEADER_SIZE]) aacHeaderParser.skipBits(15) hasCrc = (aacHeaderParser.readBit() == 0) aacHeaderParser.skipBits(2) sampleRateIndex = aacHeaderParser.readBits(4) if(sampleRateIndex < len(self.ADTS_SAMPLE_RATES)): self.sampleRate = self.ADTS_SAMPLE_RATES[sampleRateIndex] else: self.sampleRate = sampleRateIndex self.frameDuration = (1000000 * 1024) / self.sampleRate; self.frames.append(Frame("I", self.timeUs)) aacHeaderParser.skipBits(1) self.channels = aacHeaderParser.readBits(3) aacHeaderParser.skipBits(4) self.currentFrameSize = aacHeaderParser.readBits(13) - self.ADTS_HEADER_SIZE - self.ADTS_SYNC_SIZE; if (hasCrc): self.currentFrameSize -= self.ADTS_CRC_SIZE;
def _parseSPSNALUnit(self, start, limit): spsParser = BitReader(self.dataBuffer[start:limit]) spsParser.skipBytes(4) self.profileId = spsParser.readBits(8) self.levelId = spsParser.readBits(8) spsParser.skipBytes(1) spsParser.readUnsignedExpGolombCodedInt() chromaFormatIdc = 1 # default is 4:2:0 if(self.profileId == 100 or self.profileId == 110 or self.profileId == 122 or self.profileId == 244 or self.profileId == 44 or self.profileId == 83 or self.profileId == 86 or self.profileId == 118 or self.profileId == 128 or self.profileId == 138): chromaFormatIdc = spsParser.readUnsignedExpGolombCodedInt() if(chromaFormatIdc == 3): spsParser.skipBits(1) spsParser.readUnsignedExpGolombCodedInt(); # bit_depth_luma_minus8 spsParser.readUnsignedExpGolombCodedInt(); # bit_depth_chroma_minus8 spsParser.skipBits(1); # qpprime_y_zero_transform_bypass_flag seqScalingMatrixPresentFlag = spsParser.readBit(); if(seqScalingMatrixPresentFlag == 1): limit = 12 if(chromaFormatIdc != 3): limit = 8 for i in range(0, limit): seqScalingListPresentFlag = spsParser.readBit(); if(seqScalingListPresentFlag == 1): if(i < 6): self._skipScalingList(spsParser, 16) else: self._skipScalingList(spsParser, 64) spsParser.readUnsignedExpGolombCodedInt(); # log2_max_frame_num_minus4 picOrderCntType = spsParser.readUnsignedExpGolombCodedInt(); if(picOrderCntType == 0): spsParser.readUnsignedExpGolombCodedInt(); # log2_max_pic_order_cnt_lsb_minus4 elif (picOrderCntType == 1): spsParser.skipBits(1); # delta_pic_order_always_zero_flag spsParser.readSignedExpGolombCodedInt(); # offset_for_non_ref_pic spsParser.readSignedExpGolombCodedInt(); # offset_for_top_to_bottom_field numRefFramesInPicOrderCntCycle = spsParser.readUnsignedExpGolombCodedInt(); for i in range(0, numRefFramesInPicOrderCntCycle): spsParser.readSignedExpGolombCodedInt(); #offset_for_ref_frame[i] self.numRefFrames = spsParser.readUnsignedExpGolombCodedInt(); # max_num_ref_frames spsParser.skipBits(1); # gaps_in_frame_num_value_allowed_flag picWidthInMbs = spsParser.readUnsignedExpGolombCodedInt() + 1; picHeightInMapUnits = spsParser.readUnsignedExpGolombCodedInt() + 1; frameMbsOnlyFlag = spsParser.readBit(); frameHeightInMbs = picHeightInMapUnits if(frameMbsOnlyFlag == 0): frameHeightInMbs += picHeightInMapUnits spsParser.skipBits(1) # mb_adaptive_frame_field_flag spsParser.skipBits(1); # direct_8x8_inference_flag self.frameWidth = picWidthInMbs * 16; self.frameHeight = frameHeightInMbs * 16; frameCroppingFlag = spsParser.readBit(); if (frameCroppingFlag == 1): frameCropLeftOffset = spsParser.readUnsignedExpGolombCodedInt(); frameCropRightOffset = spsParser.readUnsignedExpGolombCodedInt(); frameCropTopOffset = spsParser.readUnsignedExpGolombCodedInt(); frameCropBottomOffset = spsParser.readUnsignedExpGolombCodedInt(); cropUnitX, cropUnitY = 0, 0 if (chromaFormatIdc == 0): cropUnitX = 1; cropUnitY = 2 - (1 if (frameMbsOnlyFlag == 1) else 0); else: subWidthC = (1 if (chromaFormatIdc == 3) else 2); subHeightC = (2 if (chromaFormatIdc == 1) else 1); cropUnitX = subWidthC; cropUnitY = subHeightC * (2 - (1 if (frameMbsOnlyFlag == 1) else 0)); self.frameWidth -= (frameCropLeftOffset + frameCropRightOffset) * cropUnitX; self.frameHeight -= (frameCropTopOffset + frameCropBottomOffset) * cropUnitY; vui_parameters_present_flag = spsParser.readBit() if (vui_parameters_present_flag == 1): aspect_ratio_info_present_flag = spsParser.readBit() if (aspect_ratio_info_present_flag == 1): aspect_ratio_idc = spsParser.readUnsignedByte() if (aspect_ratio_idc == self.H264_ASPECT_RATIO_EXTENDED_SAR): self.aspectRatioNum = spsParser.readBits(16) self.aspectRatioDen = spsParser.readBits(16) else: self.aspectRatioNum = self.H264_ASPECT_RATIO_PIXEL_ASPECT[aspect_ratio_idc][0] self.aspectRatioDen = self.H264_ASPECT_RATIO_PIXEL_ASPECT[aspect_ratio_idc][1] if(self.aspectRatioNum != 0): self.displayAspectRatio = Fraction(self.frameWidth * self.aspectRatioNum, self.frameHeight * self.aspectRatioDen)
def _processTSPacket(self, packet): self.packetsCount = self.packetsCount + 1 packetParser = BitReader(packet) packetParser.skipBits(1) payload_unit_start_indicator = (packetParser.readBits(1) != 0) packetParser.skipBits(1) pid = packetParser.readBits(13) adaptation_field = (packetParser.readUnsignedByte() & 0x30) >> 4 if (adaptation_field > 1): length = packetParser.readUnsignedByte(); if (length > 0): packetParser.skipBytes(length) if (adaptation_field == 1 or adaptation_field == 3): if (pid == 0): self._parseProgramId(payload_unit_start_indicator, packetParser) elif (pid == self.pmtId): self._parseProgramTable(payload_unit_start_indicator, packetParser) else: track = self.tracks[pid] if(track is not None): track.appendData(payload_unit_start_indicator, packetParser)
def _parseAACHeader(self, start): #print "AAC Frame {},{},{},{},{}".format(hex(self.dataBuffer[start]), hex(self.dataBuffer[start+1]), self.dataBuffer[start+2], self.dataBuffer[start+3], self.dataBuffer[start+4]) aacHeaderParser = BitReader(self.dataBuffer[start:start + self.ADTS_SYNC_SIZE + self.ADTS_HEADER_SIZE]) aacHeaderParser.skipBits(15) hasCrc = (aacHeaderParser.readBit() == 0) aacHeaderParser.skipBits(2) sampleRateIndex = aacHeaderParser.readBits(4) if(sampleRateIndex < len(self.ADTS_SAMPLE_RATES)): self.sampleRate = self.ADTS_SAMPLE_RATES[sampleRateIndex] else: self.sampleRate = sampleRateIndex self.frameDuration = (1000000 * 1024L) / self.sampleRate; self.keyframeInterval = self.frameDuration aacHeaderParser.skipBits(1) self.channels = aacHeaderParser.readBits(3) aacHeaderParser.skipBits(4) self.currentFrameSize = aacHeaderParser.readBits(13) - self.ADTS_HEADER_SIZE - self.ADTS_SYNC_SIZE; if (hasCrc): self.currentFrameSize -= self.ADTS_CRC_SIZE;
args.add_argument('input_file', metavar='input_file', type=str) AddBooleanArg(args, '--apng', def_value=True, help_str='enable/disable APNG generation') AddBooleanArg(args, '--png', def_value=True, help_str='enable/disable PNG generation') AddBooleanArg(args, '--raw', def_value=False, help_str='enable/disable RAW pixel dumps') args.add_argument('--apng_delay', type=int, default=100, help='APNG frame delay in miliseconds') args.add_argument('--outdir', type=str, default=os.getcwd(), help='output directory') args = args.parse_args() filename_no_ext = os.path.splitext(os.path.basename(args.input_file))[0] out_path = args.outdir if not os.path.exists(out_path): os.makedirs(out_path) data = open(args.input_file, 'rb').read() br = BitReader(data) palette = mkutils.getPalette(br) print('Number of palette colors:', len(palette), '\n') file_idx = 0 files = [] while not br.isEnd(): print('Processing frame nr :', file_idx) cp = br.data_pos print('Compressed data offset:', hex(cp)) width, height, c, compressed_block = mkutils.getCompressedData(br) output = mklzw.decompress(compressed_block, c) if len(output) == 0: print('Decompression error, exiting.') break