예제 #1
0
def main():
    """
    """
    F = 'bqmall.bin'

    s = BitStream(filename=F)

    nals = list(s.findall('0x000001', bytealigned=True))
    size = [y - x for x, y in zip(nals, nals[1:])]

    for i, n in zip(nals, size):
        print
        print "!! Found NAL @ offset {0:d} ({0:#x})".format((i + 24) / 8)
        read_nal_unit(s, i, n / 8)  # bits to bytes
예제 #2
0
class H26xParser:
    """
    H.264 extractor for Annex B streams.
    """

    START_CODE_PREFIX = "0x00000001"
    START_CODE_PREFIX_SHORT = "0x000001"
    VALID_CALLBACKS = [
        "sps",
        "pps",
        "slice",
        "aud",
        "nalu"
    ]

    def __init__(self, f, verbose=False, use_bitstream=None):
        """
        Create a new extractor for a .264/h264 file in Annex B format.

        f: input file
        use_bitstream: blob to use as bitstream (for testing)
        verbose: whether to print out NAL structure and fields
        """
        if use_bitstream:
            # testing the parser in a bitstream
            self.file = None
            self.stream = BitStream(use_bitstream)
        else:
            fn, ext = os.path.splitext(os.path.basename(f))
            valid_input_ext = ['.264', '.h264']
            # TODO: extend for H.265
            # valid_input_ext = ['.264', 'h264', '.265', '.h265']
            if not ext in valid_input_ext:
                raise RuntimeError("Valid input types: " + str(valid_input_ext))
            bitstream_file = f
            self.file = bitstream_file
            self.stream = BitStream(filename=bitstream_file)
        self.verbose = verbose
        self.callbacks = {}

    def set_callback(self, name, fun):
        """
        Set a callback function for raw data extracted. The function will be called with the raw
        bytes of the complete NALU. Valid callbacks are:

        - aud: for every AUD found
        - nalu: for every complete NAL unit found
        - sps: for every SPS NAL unit found
        - pps: for every PPS NAL unit found
        - slice: for every VCL NAL unit found with a slice in it (args: data, buffer_size, first_mb_in_slice)

        Raw data for all callbacks never includes the start code, but all the NAL headers, except
        for the "nalu" callback.
        """
        if name not in self.VALID_CALLBACKS:
            raise RuntimeError(name + " is not a valid callback. Choose one of " + str(self.VALID_CALLBACKS) + ".")
        if not callable(fun):
            raise RuntimeError(str(fun) + " is not a callable function")

        self.callbacks[name] = fun

    def __call(self, name, *args):
        """
        Calls a given callback, and silently skips if it is not implemented.

        name: name of the callback, e.g. "nalu", "aud", whatever
        args: will be expanded to the list of arguments, so you can call this with:
              self.__call("foo", arg1, arg2, ...)
        """
        if name not in self.VALID_CALLBACKS:
            return
        if name not in self.callbacks.keys():
            return
        else:
            self.callbacks[name](*args)

    def _get_nalu_positions(self):
        """
        Saves all the NALU positions as bit positions in self.nal_unit_positions
        """
        self.nal_unit_positions = list(self.stream.findall(self.START_CODE_PREFIX, bytealigned=True))
        self.short_nal_unit_positions = list(self.stream.findall(self.START_CODE_PREFIX_SHORT, bytealigned=True))

        if not self.nal_unit_positions and not self.short_nal_unit_positions:
            print("No NALUs found in stream")
            sys.exit(1)

        if not self.nal_unit_positions:
            self.nal_unit_positions = self.short_nal_unit_positions
        else:
            # if there were extraneous 3-byte NAL unit start codes, use them too
            extra_nal_unit_pos = set([max(s - 8, 0) for s in self.short_nal_unit_positions]) - set(self.nal_unit_positions)
            if len(extra_nal_unit_pos) and self.nal_unit_positions:
                if self.verbose:
                    print("Warning: 3-byte extra NAL unit start code found")
                self.nal_unit_positions.extend([s + 8 for s in extra_nal_unit_pos])
                self.nal_unit_positions = sorted(self.nal_unit_positions)

        self.end_of_stream = len(self.stream)
        self.nal_unit_positions.append(self.end_of_stream)
        return self.nal_unit_positions

    def _decode_nalu(self, nalu_bytes):
        """
        Returns nal_unit_type and RBSP payload from a NALU stream
        """
        if "0x" + nalu_bytes[0: 4*8].hex == self.START_CODE_PREFIX:
            start_code = nalu_bytes.read('bytes:4')
        else:
            start_code = nalu_bytes.read('bytes:3')
        forbidden_zero_bit = nalu_bytes.read(1)
        nal_ref_idc = nalu_bytes.read('uint:2')
        nal_unit_type = nalu_bytes.read('uint:5')
        nal_unit_payload = nalu_bytes[nalu_bytes.pos:]

        rbsp_payload = BitStream()
        for i in range(int(len(nal_unit_payload)/8)):
            if len(nal_unit_payload) - nal_unit_payload.pos >= 24 and \
               nal_unit_payload.peek('bits:24') == '0x000003':
                rbsp_payload.append(nal_unit_payload.read('bits:8'))
                rbsp_payload.append(nal_unit_payload.read('bits:8'))
                nal_unit_payload.read('bits:8')
            else:
                if nal_unit_payload.pos == len(nal_unit_payload):
                    continue
                rbsp_payload.append(nal_unit_payload.read('bits:8'))

        return nal_unit_type, rbsp_payload

    def parse(self):
        """
        Parse the bitstream and extract each NALU.
        Call the respective callbacks for each NALU type found.
        """

        self._get_nalu_positions()
        nalu_sps = None
        nalu_pps = None
        for current_nalu_pos, next_nalu_pos in zip(self.nal_unit_positions, islice(self.nal_unit_positions, 1, None)):
            current_nalu_bytepos = int(current_nalu_pos / 8)
            next_nalu_bytepos = int(next_nalu_pos / 8)
            nalu_bytes = self.stream[current_nalu_pos: next_nalu_pos]

            self.__call('nalu', nalu_bytes)

            if self.verbose:
                print("")
                print("========================================================================================================")
                print("")
                print("NALU bytepos:\t[" + str(current_nalu_bytepos) + ", " + str(next_nalu_bytepos - 1) + "]")
                print("NALU offset:\t" + str(current_nalu_bytepos) + " Bytes")
                print("NALU length:\t" + str(next_nalu_bytepos - current_nalu_bytepos) + " Bytes (including start code)")

            current_nalu_stream_segment = BitStream(self.stream[current_nalu_pos: next_nalu_pos])

            nal_unit_type, rbsp_payload = self._decode_nalu(current_nalu_stream_segment)

            if self.verbose:
                print("NALU type:\t" + str(nal_unit_type) + " (" + nalutypes.get_description(nal_unit_type) + ")")
                print("NALU bytes:\t" + str(nalu_bytes))
                print("NALU RBSP:\t" + str(rbsp_payload))
                print("")

            if nal_unit_type == nalutypes.NAL_UNIT_TYPE_SPS:
                nalu_sps = nalutypes.SPS(rbsp_payload, self.verbose)
                self.__call('sps', rbsp_payload)
            elif nal_unit_type == nalutypes.NAL_UNIT_TYPE_PPS:
                nalu_pps = nalutypes.PPS(rbsp_payload, self.verbose)
                self.__call('pps', rbsp_payload)
            elif nal_unit_type == nalutypes.NAL_UNIT_TYPE_AUD:
                aud = nalutypes.AUD(rbsp_payload, self.verbose)
                self.__call('aud', rbsp_payload)
            elif nal_unit_type == nalutypes.NAL_UNIT_TYPE_CODED_SLICE_NON_IDR:
                nalu_slice = nalutypes.CodedSliceNonIDR(rbsp_payload, nalu_sps, nalu_pps, self.verbose)
                self.__call('slice', rbsp_payload)
            elif nal_unit_type == nalutypes.NAL_UNIT_TYPE_CODED_SLICE_IDR:
                nalu_slice = nalutypes.CodedSliceIDR(rbsp_payload, nalu_sps, nalu_pps, self.verbose)
                self.__call('slice', rbsp_payload)
class GmoFile():
  def __init__(self, data = None, offset = 0, filename = None):
    self.data = None
    self.__gim_files = []
    
    self.gimconv = GimConverter()
    
    if not data == None:
      self.load_data(data, offset)
    elif not filename == None:
      self.load_file(filename)
  
  def load_file(self, filename):
    data = BitStream(filename = filename)
    self.load_data(data)
  
  def load_data(self, data, offset = 0):
    if not data[offset * 8 : offset * 8 + GMO_MAGIC.len] == GMO_MAGIC:
      _LOGGER.error("GMO header not found at 0x%04X." % offset)
      return
    
    data.bytepos = offset + GMO_SIZE_OFFSET
    gmo_size = data.read("uintle:32") + GMO_SIZE_DIFF
    
    self.data = BitStream(data[offset * 8 : (offset + gmo_size) * 8])
    
    self.__find_gims()
  
  def save(self, filename):
    with open(filename, "wb") as f:
      self.data.tofile(f)
  
  def __find_gims(self):
    if self.data == None:
      return
    
    self.__gim_files = []
    
    for gim_start in self.data.findall(GIM_MAGIC, bytealigned = True):
      gim_size_pos  = gim_start + (GIM_SIZE_OFFSET * 8) # Bit pos.
      gim_size      = self.data[gim_size_pos : gim_size_pos + 32].uintle + GIM_SIZE_DIFF
      
      # And turn it into a byte position.
      gim_start /= 8
      self.__gim_files.append((gim_start, gim_size))
  
  def gim_count(self):
    return len(self.__gim_files)
  
  def get_gim(self, gim_id):
    if gim_id >= self.gim_count():
      raise GimIndexError("Invalid GIM ID.")
    
    gim_start, gim_size = self.__gim_files[gim_id]
    gim_data = self.data[gim_start * 8 : (gim_start + gim_size) * 8]
    
    return gim_data
  
  def replace_png_file(self, gim_id, filename, quantize_to_fit = True):
  
    if quantize_to_fit:
      quantize_order = [QuantizeType.auto, QuantizeType.index8, QuantizeType.index4]
    else:
      quantize_order = [QuantizeType.auto]
    quantize_id = 0
    
    (fd, temp_gim) = tempfile.mkstemp(suffix = ".gim", prefix = "sdse-")
    os.close(fd) # Don't need the open file handle.
    
    while True:
      self.gimconv.png_to_gim(filename, temp_gim, quantize_order[quantize_id])
      
      try:
        self.replace_gim_file(gim_id, temp_gim)
      except GimSizeError:
        quantize_id += 1
      except GimIndexError:
        os.remove(temp_gim)
        raise
      else:
        # If we didn't except, that means we succeeded, so we can leave.
        _LOGGER.debug("Quantized PNG to %s" % quantize_order[quantize_id])
        break
      
      if quantize_id > len(quantize_order):
        _LOGGER.error("Unable to convert %s into a GIM small enough to insert." % filename)
        break
    
    os.remove(temp_gim)
  
  def replace_gim_file(self, gim_id, filename):
    gim_data = BitStream(filename = filename)
    self.replace_gim(gim_id, gim_data)
  
  def replace_gim(self, gim_id, gim_data):
    if gim_id >= self.gim_count():
      raise GimIndexError("Invalid GIM ID.")
    
    gim_start, gim_size = self.__gim_files[gim_id]
    
    if gim_data.len / 8 > gim_size:
      raise GimSizeError("GIM too large. %d bytes > %d bytes" % (gim_data.len / 8, gim_size))
      # return
    
    self.data.overwrite(gim_data, gim_start * 8)
    
    # Leave the length alone, though, because we know we have that much space
    # to work with from the original GIM file that was there, and there's no
    # point in shrinking that down if someone happens to want to re-replace
    # this GIM file without reloading the whole thing.
  
  def extract(self, directory, to_png = False):
    if not os.path.isdir(directory):
      os.makedirs(directory)
    
    for id in range(self.gim_count()):
      gim = self.get_gim(id)
      
      out_gim = os.path.join(directory, "%04d.gim" % id)
      out_png = os.path.join(directory, "%04d.png" % id)
      
      with open(out_gim, "wb") as f:
        gim.tofile(f)
      
      if to_png:
        self.gimconv.gim_to_png(out_gim, out_png)
        os.remove(out_gim)
예제 #4
0
def main():
    """
    """

    if args.infile == args.outfile :
        print ('Error! Source and Destination can not be the same file!')
        sys.exit()

    if not os.path.exists(args.infile) :
        print ('Error! Given input file name not found! Please check path given in CMD or set in script code!')
        sys.exit()
    if md_arg_str :
        md = re.findall('\d+',md_arg_str)
        if len(md) != 10 :
            print ('Specified wrong "-masterdisplay" parameter! Please check!\n Example: G(13250,34500)B(7500,3000)R(34000,16000)WP(15635,16450)L(10000000,1) or do not specify')
            sys.exit()

    if maxcll :
        mcll = re.findall('\d+',maxcll)
    sei_ok = 0 
    
    F = open (args.infile,'r+b')
    o = open (args.outfile,'wb')

    print ('Parsing the infile:')
    print ('')
    print ('==========================')
    print ('')
    print ('Prepending SEI data')
    s = BitStream(F.read(chunk))
    
    nals = list(s.findall('0x000001', bytealigned=True))
    sps_nals = list(s.findall('0x00000142', bytealigned=True))
    sei_pref_nals = list (s.findall('0x0000014e', bytealigned=True))
    size = [y - x for x,y in zip(nals,nals[1:])]
    sps_pos = list(set(nals).intersection(sps_nals))
    sei_pref_nals_pos = list(set(nals).intersection(sei_pref_nals))
    sps_size = size[nals.index(sps_nals[0])]
    if sei_pref_nals :
        sei_pref_nal_size = ( size[nals.index(sei_pref_nals[0])])
### MAXCLL & MAXFALL ###

    if args.maxcll or md_arg_str :
        sei_forbidden_zero_bit  = 0
        sei_nal_unit_type = 39
        sei_nuh_layer_id = 0
        sei_nuh_temporal_id_plus1 = 1
        new_sei_string = pack ('uint:1,2*uint:6,uint:3',sei_forbidden_zero_bit,sei_nal_unit_type,sei_nuh_layer_id,sei_nuh_temporal_id_plus1)
        print ('Starting new SEI NALu...')

        if maxcll :
            sei_last_payload_type_byte = 144
            sei_last_payload_size_byte = 4
            sei_max_content_light_level = int(mcll[0])
            sei_max_pic_average_light_level = int(mcll[1])
            new_sei_string += pack ('2*uint:8,2*uint:16',sei_last_payload_type_byte,sei_last_payload_size_byte,sei_max_content_light_level,sei_max_pic_average_light_level)
            print ('SEI message with MaxCLL=',sei_max_content_light_level,' and MaxFall=',sei_max_pic_average_light_level,' created in SEI NAL')

        if md_arg_str :
            md_sei_last_payload_type_byte = 137
            md_sei_last_payload_size_byte = 24
            #MD string ref
            #G(13250,34500)B(7500,3000)R(34000,16000)WP(15635,16450)L(10000000,1)
            new_sei_string += pack ('2*uint:8',md_sei_last_payload_type_byte,md_sei_last_payload_size_byte)
            for i in range (len(md)-2) :
                new_sei_string += pack ('uint:16',int(md[i]))

            new_sei_string += pack ('uint:32',int(md[8]))
            new_sei_string += pack ('uint:32',int(md[9]))

            new_sei_string.replace ('0x0000','0x000003',bytealigned=True)
            print ('SEI message Mastering Display Data',md_arg_str,'created in SEI NAL')     

        new_sei_string = '0x00000001' + new_sei_string + '0x00'
        sei_ok = True



### ------------------ ###   
    
    print ('Looking for SPS.........', sps_pos)
    print ('SPS_Nals_addresses', sps_pos)
    print ('SPS NAL Size', sps_size)
    print ('Starting reading SPS NAL contents')

    
    s.pos = sps_pos[0]
    t = s.peek(sps_size)

    t.pos = t.pos + 24

    forbidden_zero_bit  = t.read('uint:1')
    nal_unit_type = t.read('uint:6')
    nuh_layer_id = t.read('uint:6')
    nuh_temporal_id_plus1 = t.read('uint:3')
    nal_t = t[:]

# 7.3.1.1
    # Convert NAL data (Annex B format) to RBSP data

    t.tobytes()
    t.replace ('0x000003','0x0000')
    
    
# SPS parse block


    sps_video_parameter_set_id = t.read('uint:4')
    sps_max_sub_layers_minus1 = t.read('uint:3')
    sps_temporal_id_nesting_flag = t.read('uint:1')
    ptl = profile_tier_level(t, sps_max_sub_layers_minus1)
    sps_seq_parameter_set_id = t.read('ue')
    chroma_format_idc = t.read('ue')
    if chroma_format_idc == 3:
        separate_colour_plane_flag = t.read('uint:1')
    pic_width_in_luma_samples = t.read ('ue')
    pic_height_in_luma_samples = t.read ('ue')
    conformance_window_flag = t.read ('uint:1')
    if (conformance_window_flag) :
        conf_win_left_offset = t.read('ue')
        conf_win_right_offset = t.read('ue')
        conf_win_top_offset = t.read('ue')
        conf_win_bottom_offset = t.read('ue')
    bit_depth_luma_minus8 = t.read ('ue')
    bit_depth_chroma_minus8 = t.read ('ue')
    log2_max_pic_order_cnt_lsb_minus4 = t.read('ue')
    sps_sub_layer_ordering_info_present_flag = t.read('uint:1')
#   for (i = (sps_sub_layer_ordering_info_present_flag ? 0 : sps.max_sub_layers_minus1); i <= sps.max_sub_layers_minus1; i++)
    if sps_sub_layer_ordering_info_present_flag :
            sps_max_dec_pic_buffering_minus1 = t.read('ue')
            sps_max_num_reorder_pics = t.read('ue')
            sps_max_latency_increase_plus1 = t.read('ue')

    log2_min_luma_coding_block_size_minus3 = t.read ('ue')
    log2_diff_max_min_luma_coding_block_size = t.read ('ue')
    log2_min_luma_transform_block_size_minus2 = t.read ('ue')
    log2_diff_max_min_luma_transform_block_size = t.read ('ue')
    max_transform_hierarchy_depth_inter = t.read ('ue')
    max_transform_hierarchy_depth_intra = t.read ('ue')
    scaling_list_enabled_flag = t.read ('uint:1')
    """
    if( scaling_list_enabled_flag ) {
    sps_scaling_list_data_present_flag u(1)
    if( sps_scaling_list_data_present_flag )
    scaling_list_data( )
    }
    """
    amp_enabled_flag = t.read ('uint:1')
    sample_adaptive_offset_enabled_flag = t.read ('uint:1')
    pcm_enabled_flag = t.read ('uint:1')
    if pcm_enabled_flag :
        pcm_sample_bit_depth_luma_minus1 = t.read ('uint:4')
        pcm_sample_bit_depth_chroma_minus1 = t.read ('uint:4')
        log2_min_pcm_luma_coding_block_size_minus3  = t.read ('ue')
        log2_diff_max_min_pcm_luma_coding_block_size = t.read ('ue')
        pcm_loop_filter_disabled_flag = t.read ('uint:1')
    num_short_term_ref_pic_sets = t.read ('ue')
    if num_short_term_ref_pic_sets :
        for i in range (num_short_term_ref_pic_sets):
            if i != 0 :
                inter_ref_pic_set_prediction_flag = t.read ('uint:1')
        
            if not 'inter_ref_pic_set_prediction_flag' in globals() :
                """    
            
                if i == num_short_term_ref_pic_sets :
                    delta_idx_minus1 = t.read ('ue')
                if not 'delta_idx_minus1' in globals():
                    delta_idx_minus1 = 0
                delta_rps_sign = t.read ('uint:1')
                abs_delta_rps_minus1 = t.read ('ue')
                for j in range (NumDeltaPoc) :
                    used_by_curr_pic_flag[j] = t.read ('uint:1')
                if used_by_curr_pic_flag[j] :
                    use_delta_flag[j] = t.read ('uint:1')
        
             else:      
                """            
            
                num_negative_pics = t.read ('ue')
                num_positive_pics = t.read ('ue')
                delta_poc_s0_minus1 = [t.read ('ue') for _ in range (num_negative_pics)]
                used_by_curr_pic_s0_flag = [ t.read ('uint:1') for _ in range (num_negative_pics)]
                delta_poc_s1_minus1 = [t.read ('ue') for _ in range(num_positive_pics)]
                used_by_curr_pic_s1_flag = [t.read ('uint:1') for _ in range(num_positive_pics)]

          
    long_term_ref_pics_present_flag = t.read ('uint:1')
    if long_term_ref_pics_present_flag :
        num_long_term_ref_pics_sps = t.read ('ue')
        
        for i in range < (num_long_term_ref_pics_sps): 
            lt_ref_pic_poc_lsb_sps[i] = t.read ('ue')
            used_by_curr_pic_lt_sps_flag[i] = t.read ('uint:1')
       
    sps_temporal_mvp_enabled_flag = t.read ('uint:1')
    strong_intra_smoothing_enabled_flag = t.read ('uint:1')
    vui_parameters_present_flag = t.read ('uint:1')
    if vui_parameters_present_flag :
       vp = vui_parameters(t)
    sps_extension_present_flag = t.read ('uint:1')
    if sps_extension_present_flag :
        sps_range_extension_flag = t.read ('uint:1')
        sps_multilayer_extension_flag = t.read ('uint:1')
        sps_3d_extension_flag = t.read ('uint:1')
        sps_extension_5bits = t.read ('uint:1')
    tb = rbsp_trailing_bits(t,len(t))
    print ('Reading of SPS NAL finished. Read ',len(t),' of SPS NALu data.\n')
    
# print block
    """
    print ('sps_video_parameter_set_id', sps_video_parameter_set_id)
    print ('sps_max_sub_layers_minus1', sps_max_sub_layers_minus1)
    print ('sps_temporal_id_nesting_flag', sps_temporal_id_nesting_flag)
    ptl.show()
    print ('sps_seq_parameter_set_id', sps_seq_parameter_set_id)
    print ('chroma_format_idc', chroma_format_idc)
    if chroma_format_idc == 3:
        print ('separate_colour_plane_flag', separate_colour_plane_flag)
    print ('pic_width_in_luma_samples ', pic_width_in_luma_samples) #produces wrong number
    print ('pic_height_in_luma_samples', pic_height_in_luma_samples) #produces wrong number
    print ('conformance_window_flag', conformance_window_flag)
    print ('bit_depth_luma_minus8', bit_depth_luma_minus8)
    print ('bit_depth_chroma_minus8', bit_depth_chroma_minus8)
    print ('log2_max_pic_order_cnt_lsb_minus4', log2_max_pic_order_cnt_lsb_minus4)
    print ('sps_sub_layer_ordering_info_present_flag', sps_sub_layer_ordering_info_present_flag)

    if sps_sub_layer_ordering_info_present_flag :
       print ('sps_max_dec_pic_buffering_minus1', sps_max_dec_pic_buffering_minus1)
       print ('sps_max_num_reorder_pics', sps_max_num_reorder_pics)
       print ('sps_max_latency_increase_plus1', sps_max_latency_increase_plus1)
    
    print ('log2_min_luma_coding_block_size_minus3',log2_min_luma_coding_block_size_minus3)
    print ('log2_diff_max_min_luma_coding_block_size',log2_diff_max_min_luma_coding_block_size)
    print ('log2_min_luma_transform_block_size_minus2',log2_min_luma_transform_block_size_minus2)
    print ('log2_diff_max_min_luma_transform_block_size', log2_diff_max_min_luma_transform_block_size)
    print ('max_transform_hierarchy_depth_inter', max_transform_hierarchy_depth_inter)
    print ('max_transform_hierarchy_depth_intra', max_transform_hierarchy_depth_intra)
    print ('scaling_list_enabled_flag',scaling_list_enabled_flag)
    print ('amp_enabled_flag',amp_enabled_flag)
    print ('sample_adaptive_offset_enabled_flag',sample_adaptive_offset_enabled_flag)
    print ('pcm_enabled_flag',pcm_enabled_flag)
    if pcm_enabled_flag :
        print ('pcm_sample_bit_depth_luma_minus1',pcm_sample_bit_depth_luma_minus1)
        print ('pcm_sample_bit_depth_chroma_minus1',pcm_sample_bit_depth_chroma_minus1)
        print ('log2_min_pcm_luma_coding_block_size_minus3',log2_min_pcm_luma_coding_block_size_minus3)
        print ('log2_diff_max_min_pcm_luma_coding_block_size',log2_diff_max_min_pcm_luma_coding_block_size)
        print ('pcm_loop_filter_disabled_flag',pcm_loop_filter_disabled_flag)
    print ('num_short_term_ref_pic_sets',num_short_term_ref_pic_sets)
    print ('long_term_ref_pics_present_flag',long_term_ref_pics_present_flag)
    print ('sps_temporal_mvp_enabled_flag',sps_temporal_mvp_enabled_flag)
    print ('strong_intra_smoothing_enabled_flag',strong_intra_smoothing_enabled_flag)
    print ('vui_parameters_present_flag',vui_parameters_present_flag)
    if vui_parameters_present_flag :
        vp.show()
    print ('sps_extension_present_flag',sps_extension_present_flag)
    """
# New BS write Block
    print ('Making modified SPS NALu...')
    new_bs = BitStream()
    new_bs += pack('uint:4,uint:3,uint:1',sps_video_parameter_set_id,sps_max_sub_layers_minus1,sps_temporal_id_nesting_flag)
    new_bs += pack ('uint:2,uint:1,uint:5',ptl.general_profile_space, ptl.general_tier_flag,ptl.general_profile_idc)
    for i in range (32) :
        new_bs += pack('uint:1',int(ptl.general_profile_compatibility_flag[i]))
    new_bs += pack ('uint:1',ptl.general_progressive_source_flag)
    new_bs += pack ('uint:1',ptl.general_interlaced_source_flag)
    new_bs += pack ('uint:1',ptl.general_non_packed_constraint_flag)
    new_bs += pack ('uint:1',ptl.general_frame_only_constraint_flag)
    new_bs += pack ('uint:44',ptl.general_reserved_zero_44bits)
    new_bs += pack ('uint:8',ptl.general_level_idc)
    new_bs += pack ('ue',sps_seq_parameter_set_id)
    new_bs += pack ('ue',chroma_format_idc)
    if chroma_format_idc == 3:
        new_bs += pack ('uint:1',separate_colour_plane_flag)
    new_bs += pack ('ue',pic_width_in_luma_samples)
    new_bs += pack ('ue',pic_height_in_luma_samples)
    new_bs += pack ('uint:1',conformance_window_flag)
    if (conformance_window_flag) :
        new_bs += pack ('ue',conf_win_left_offset)
        new_bs += pack ('ue',conf_win_right_offset)
        new_bs += pack ('ue',conf_win_top_offset)
        new_bs += pack ('ue',conf_win_bottom_offset)
    new_bs += pack ('ue',bit_depth_luma_minus8)
    new_bs += pack ('ue',bit_depth_chroma_minus8)
    new_bs += pack ('ue',log2_max_pic_order_cnt_lsb_minus4)
    new_bs += pack ('uint:1',sps_sub_layer_ordering_info_present_flag)
#   for (i = (sps_sub_layer_ordering_info_present_flag ? 0 : sps.max_sub_layers_minus1); i <= sps.max_sub_layers_minus1; i++)
    if sps_sub_layer_ordering_info_present_flag :
            new_bs += pack ('ue',sps_max_dec_pic_buffering_minus1)
            new_bs += pack ('ue',sps_max_num_reorder_pics)
            new_bs += pack ('ue',sps_max_latency_increase_plus1)
    new_bs += pack ('ue',log2_min_luma_coding_block_size_minus3)
    new_bs += pack ('ue',log2_diff_max_min_luma_coding_block_size)
    new_bs += pack ('ue',log2_min_luma_transform_block_size_minus2)
    new_bs += pack ('ue',log2_diff_max_min_luma_transform_block_size)
    new_bs += pack ('ue',max_transform_hierarchy_depth_inter)
    new_bs += pack ('ue',max_transform_hierarchy_depth_intra)
    new_bs += pack ('uint:1',scaling_list_enabled_flag)
    #
    new_bs += pack ('uint:1',amp_enabled_flag)
    new_bs += pack ('uint:1',sample_adaptive_offset_enabled_flag)
    new_bs += pack ('uint:1',pcm_enabled_flag)
    if pcm_enabled_flag :
        new_bs += pack ('uint:4',pcm_sample_bit_depth_luma_minus1)
        new_bs += pack ('uint:4',pcm_sample_bit_depth_chroma_minus1)
        new_bs += pack ('ue',log2_min_pcm_luma_coding_block_size_minus3)
        new_bs += pack ('ue',log2_diff_max_min_pcm_luma_coding_block_size)
        new_bs += pack ('uint:1',pcm_loop_filter_disabled_flag)
    new_bs += pack ('ue',num_short_term_ref_pic_sets)


    if num_short_term_ref_pic_sets :
        for i in range (num_short_term_ref_pic_sets) :
            if i != 0 :
                new_bs += pack ('uint:1',inter_ref_pic_set_prediction_flag)

        
        
            if  not 'inter_ref_pic_set_prediction_flag' in globals() :
                """     
                if i == num_short_term_ref_pic_sets :
                    new_bs += pack ('ue',delta_idx_minus1)
                new_bs += pack ('uint:1', delta_rps_sign)
                new_bs += pack ('ue',abs_delta_rps_minus1)
                for j in range (NumDeltaPocs[i - (delta_idx_minus1 +1)]) :
                    new_bs += pack ('uint:1', used_by_curr_pic_flag[j])
                    if used_by_curr_pic_flag[j] :
                        new_bs += pack ('uint:1',use_delta_flag[j])
        
            else :
                """    
                new_bs += pack ('ue',num_negative_pics)
                new_bs += pack ('ue',num_positive_pics)
                new_bs += [pack ('ue',delta_poc_s0_minus1[_]) for _ in range (num_negative_pics)]
                new_bs += [pack ('uint:1',used_by_curr_pic_s0_flag[_]) for _ in range (num_negative_pics)]
                new_bs += [pack ('ue',delta_poc_s1_minus1[_]) for _ in range(num_positive_pics)]
                new_bs += [pack ('uint:1',used_by_curr_pic_s1_flag[_]) for _ in range(num_positive_pics)]
        

    new_bs += pack ('uint:1',long_term_ref_pics_present_flag)
    if long_term_ref_pics_present_flag :
        new_bs += pack ('ue',num_long_term_ref_pics_sps)
    new_bs += pack ('uint:1',sps_temporal_mvp_enabled_flag)
    new_bs += pack ('uint:1',strong_intra_smoothing_enabled_flag)
    new_bs += pack ('uint:1',vui_parameters_present_flag)
# VUI VP pack Section
    if vui_parameters_present_flag :
       new_bs += pack ('uint:1',vp.aspect_ratio_info_present_flag)
       if vp.aspect_ratio_info_present_flag :
            new_bs += pack ('uint:8',vp.aspect_ratio_idc)
            if vp.aspect_ratio_idc == 255 :
                new_bs += pack ('uint:16',vp.sar_width)
                new_bs += pack ('uint:16',vp.sar_height)
       new_bs += pack ('uint:1',vp.overscan_info_present_flag)
       if vp.overscan_info_present_flag :
           new_bs += pack ('uint:1',vp.overscan_appropriate_flag)
       new_bs += pack ('uint:1',vp.video_signal_type_present_flag)
       if vp.video_signal_type_present_flag :
           new_bs += pack ('uint:3',vp.video_format)
           new_bs += pack ('uint:1',vp.video_full_range_flag)
           new_bs += pack ('uint:1',vp.colour_description_present_flag)
           if vp.colour_description_present_flag :
               new_bs += pack ('uint:8',vp.colour_primaries)
               new_bs += pack ('uint:8',vp.transfer_characteristics)
               new_bs += pack ('uint:8',vp.matrix_coeffs)
       new_bs += pack ('uint:1',vp.chroma_loc_info_present_flag)
       if vp.chroma_loc_info_present_flag :
           new_bs += pack ('ue',vp.chroma_sample_loc_type_top_field)
           new_bs += pack ('ue',vp.chroma_sample_loc_type_bottom_field)
       new_bs += pack ('uint:1',vp.neutral_chroma_indication_flag)
       new_bs += pack ('uint:1',vp.field_seq_flag)
       new_bs += pack ('uint:1',vp.frame_field_info_present_flag)
       new_bs += pack ('uint:1',vp.default_display_window_flag)
       if vp.default_display_window_flag :
           new_bs += pack ('ue',vp.def_disp_win_left_offset)
           new_bs += pack ('ue',vp.def_disp_win_right_offset)
           new_bs += pack ('ue',vp.def_disp_win_top_offset)
           new_bs += pack ('ue',vp.def_disp_win_bottom_offset)
       new_bs += pack ('uint:1',vp.vui_timing_info_present_flag)
       if vp.vui_timing_info_present_flag :
           new_bs += pack ('uint:32',vp.vui_num_units_in_tick)
           new_bs += pack ('uint:32',vp.vui_time_scale)
           new_bs += pack ('uint:1',vp.vui_poc_proportional_to_timing_flag)
           if vp.vui_poc_proportional_to_timing_flag :
               new_bs += pack ('ue',vp.vui_num_ticks_poc_diff_one_minus1)
           new_bs += pack ('uint:1',vp.vui_hrd_parameters_present_flag)
           """
           if( vui_hrd_parameters_present_flag )
           hrd_parameters( 1, sps_max_sub_layers_minus1 )
           """
       new_bs += pack ('uint:1',vp.bitstream_restriction_flag)
       if vp. bitstream_restriction_flag :
           new_bs += pack ('uint:1',vp.tiles_fixed_structure_flag)
           new_bs += pack ('uint:1',vp.motion_vectors_over_pic_boundaries_flag)
           new_bs += pack ('uint:1',vp.restricted_ref_pic_lists_flag)
           new_bs += pack ('ue',vp.min_spatial_segmentation_idc)
           new_bs += pack ('ue',vp.max_bytes_per_pic_denom)
           new_bs += pack ('ue',vp.max_bits_per_min_cu_denom)
           new_bs += pack ('ue',vp.log2_max_mv_length_horizontal)
           new_bs += pack ('ue',vp.log2_max_mv_length_vertical)

    new_bs += pack ('uint:1',sps_extension_present_flag)
    if sps_extension_present_flag :
        new_bs += pack ('uint:1',sps_range_extension_flag)
        new_bs += pack ('uint:1',sps_multilayer_extension_flag)
        new_bs += pack ('uint:1',sps_3d_extension_flag)
        new_bs += pack ('uint:1',sps_extension_5bits)

    new_bs += pack ('uint:1',tb.rbsp_stop_one_bit)
    while len(new_bs) < t.pos :
        new_bs += pack ('uint:1',tb.rbsp_alignment_zero_bit)

#    self.sub_layer_profile_present_flag = []
#    self.sub_layer_level_present_flag = []
#    for i in range(maxNumSubLayersMinus1):
#        self.sub_layer_profile_present_flag.append(t.read('uint:1'))
#        self.sub_layer_level_present_flag.append(t.read('uint:1'))
    
    pre_new_bs = pack ('uint:1,2*uint:6,uint:3', forbidden_zero_bit,nal_unit_type,nuh_layer_id,nuh_temporal_id_plus1)
    new_bs.replace ('0x0000','0x000003',bytealigned=True)
    new_bs = pre_new_bs + new_bs + '0x00'
    nal_t_rep = nal_t[24:]
    repl = s.replace (nal_t_rep,new_bs, bytealigned=True)
    print ('Made modified SPS NALu - OK')
    if sei_ok :
        s.prepend (new_sei_string)
        print ('New SEI prepended')
    print ('Writing new stream...')
    s.tofile(o)
    progr = chunk
    while True:
        s = F.read(chunk)
        o.write(s)
        if progr < os.path.getsize(args.infile):
            print ('\rProgress ',int(round((progr/os.path.getsize(args.infile))*100)),'%',end='')
        progr = progr + chunk
        if not s:
            break
    o.close()
    F.close()
    print ('\rProgress: 100 %')
    print ('=====================')
    print ('Done!')
    print ('')
    print ('File ',args.outfile,' created.')
    sys.exit()
예제 #5
0
import sys
import bitstring
import shutil
import random
import pandas as pd
import subprocess

from bitstring import BitStream, BitArray, ConstBitStream, pack
name = str(sys.argv[1])
name = name.split('.')[0]
s = BitStream(filename=str(sys.argv[1]))  # take the file name
posu = None
if (len(sys.argv) == 3):
    posu = str(sys.argv[2])
pcksTOPs = list(
    s.findall('0x00000001',
              bytealigned=True))  # All frame headers includes VPS,SPS and PPS
pcks = list(s.findall(
    '0x000001',
    bytealigned=True))  # Find NAL for slices includes VPS,SPS,PPS and SEI
pcksAdj = [
    p + 8 for p in pcksTOPs
]  # +8 to bring the postion to first of 0x00'000001 from 0x'00000001) to compare positions found
b = set(pcksAdj)
allowedIDS = [i for i, item in enumerate(pcks) if item not in b]
del allowedIDS[0:12]  # exclude SEI NAL which has delimiter 0x000001


def conceal_p1(s, posi):
    #constants:
    NAL_header = 16
    NAL_delimiter = 24
예제 #6
0
class GmoFile():
    def __init__(self, data=None, offset=0, filename=None):
        self.data = None
        self.__gim_files = []

        self.gimconv = GimConverter()

        if not data == None:
            self.load_data(data, offset)
        elif not filename == None:
            self.load_file(filename)

    def load_file(self, filename):
        data = BitStream(filename=filename)
        self.load_data(data)

    def load_data(self, data, offset=0):
        if not data[offset * 8:offset * 8 + GMO_MAGIC.len] == GMO_MAGIC:
            _LOGGER.error("GMO header not found at 0x%04X." % offset)
            return

        data.bytepos = offset + GMO_SIZE_OFFSET
        gmo_size = data.read("uintle:32") + GMO_SIZE_DIFF

        self.data = BitStream(data[offset * 8:(offset + gmo_size) * 8])

        self.__find_gims()

    def save(self, filename):
        with open(filename, "wb") as f:
            self.data.tofile(f)

    def __find_gims(self):
        if self.data == None:
            return

        self.__gim_files = []

        for gim_start in self.data.findall(GIM_MAGIC, bytealigned=True):
            gim_size_pos = gim_start + (GIM_SIZE_OFFSET * 8)  # Bit pos.
            gim_size = self.data[gim_size_pos:gim_size_pos +
                                 32].uintle + GIM_SIZE_DIFF

            # And turn it into a byte position.
            gim_start /= 8
            self.__gim_files.append((gim_start, gim_size))

    def gim_count(self):
        return len(self.__gim_files)

    def get_gim(self, gim_id):
        if gim_id >= self.gim_count():
            raise GimIndexError("Invalid GIM ID.")

        gim_start, gim_size = self.__gim_files[gim_id]
        gim_data = self.data[gim_start * 8:(gim_start + gim_size) * 8]

        return gim_data

    def replace_png_file(self, gim_id, filename, quantize_to_fit=True):

        if quantize_to_fit:
            quantize_order = [
                QuantizeType.auto, QuantizeType.index8, QuantizeType.index4
            ]
        else:
            quantize_order = [QuantizeType.auto]
        quantize_id = 0

        (fd, temp_gim) = tempfile.mkstemp(suffix=".gim", prefix="sdse-")
        os.close(fd)  # Don't need the open file handle.

        while True:
            self.gimconv.png_to_gim(filename, temp_gim,
                                    quantize_order[quantize_id])

            try:
                self.replace_gim_file(gim_id, temp_gim)
            except GimSizeError:
                quantize_id += 1
            except GimIndexError:
                os.remove(temp_gim)
                raise
            else:
                # If we didn't except, that means we succeeded, so we can leave.
                _LOGGER.debug("Quantized PNG to %s" %
                              quantize_order[quantize_id])
                break

            if quantize_id > len(quantize_order):
                _LOGGER.error(
                    "Unable to convert %s into a GIM small enough to insert." %
                    filename)
                break

        os.remove(temp_gim)

    def replace_gim_file(self, gim_id, filename):
        gim_data = BitStream(filename=filename)
        self.replace_gim(gim_id, gim_data)

    def replace_gim(self, gim_id, gim_data):
        if gim_id >= self.gim_count():
            raise GimIndexError("Invalid GIM ID.")

        gim_start, gim_size = self.__gim_files[gim_id]

        if gim_data.len / 8 > gim_size:
            raise GimSizeError("GIM too large. %d bytes > %d bytes" %
                               (gim_data.len / 8, gim_size))
            # return

        self.data.overwrite(gim_data, gim_start * 8)

        # Leave the length alone, though, because we know we have that much space
        # to work with from the original GIM file that was there, and there's no
        # point in shrinking that down if someone happens to want to re-replace
        # this GIM file without reloading the whole thing.

    def extract(self, directory, to_png=False):
        if not os.path.isdir(directory):
            os.makedirs(directory)

        for id in range(self.gim_count()):
            gim = self.get_gim(id)

            out_gim = os.path.join(directory, "%04d.gim" % id)
            out_png = os.path.join(directory, "%04d.png" % id)

            with open(out_gim, "wb") as f:
                gim.tofile(f)

            if to_png:
                self.gimconv.gim_to_png(out_gim, out_png)
                os.remove(out_gim)