def process_trun(self, data, output):
     """Adjust time of tfdt if offset set."""
     version_and_flags = str_to_uint32(data[8:12])
     # version = version_and_flags >> 24
     flags = version_and_flags & 0xffffff
     sample_count = str_to_uint32(data[12:16])
     offset = 16
     if flags & 0x1:  # data_offset_present
         offset += 4
     if flags & 0x4:  # first_sample_flags
         offset += 4
     output += data[:offset]
     for i in range(sample_count):
         if flags & 0x100:  # sample_duration present
             output += data[offset:offset + 4]
             offset += 4
         if flags & 0x200:  # sample_size present
             output += data[offset:offset + 4]
             offset += 4
         if flags & 0x400:  # sample_flags present
             sample_flags = str_to_uint32(data[offset:offset + 4])
             if sample_flags != 0x2000000:  # Depends on other samples
                 sample_flags |= 0x10000
             output += uint32_to_str(sample_flags)
             offset += 4
         if flags & 0x800:  # composition_time_offset present
             output += data[offset:offset + 4]
             offset += 4
     return output
Example #2
0
    def process_tfhd(self, data):
        "Process the mvhd box and set timescale."
        tf_flags = str_to_uint32(data[8:12]) & 0xffffff
        #print "tfhd flags = %06x" % tf_flags

        if self.new_default_sample_duration is not None:
            output = uint32_to_str(str_to_uint32(data[0:4]) + 4)
            output += data[4:8]
            output += uint32_to_str(tf_flags | 0x8)
        else:
            output = data[0:8]
            output += uint32_to_str(tf_flags)

        if self.new_track_id is not None:
            old_track_id = str_to_uint32(data[12:16])
            output += uint32_to_str(self.new_track_id)
            print "Changed trackId from %d to %d" % (old_track_id, self.new_track_id)
        else:
            output += data[12:16]

        if self.new_default_sample_duration is not None:
            output += uint32_to_str(self.new_default_sample_duration)
            print "Added new default sample duration: %d"%(self.new_default_sample_duration)

        output += data[16:]
        return output
 def process_trex(self, data):
     "Get potential default values."
     self.track_id = str_to_uint32(data[12:16])
     self.default_sample_description_index = str_to_uint32(data[16:20])
     self.default_sample_duration = str_to_uint32(data[20:24])
     self.default_sample_size = str_to_uint32(data[24:28])
     self.default_sample_flags = str_to_uint32(data[28:32])
     return data
Example #4
0
 def process_tfhd(self, data):
     "Process the mvhd box and set timescale."
     tf_flags = str_to_uint32(data[8:12]) & 0xffffff
     print "tfhd flags = %06x" % tf_flags
     output = data[0:12]
     if self.new_track_id is not None:
         old_track_id = str_to_uint32(data[12:16])
         output += uint32_to_str(self.new_track_id)
         print "Changed trackId from %d to %d" % (old_track_id, self.new_track_id)
     else:
         output += data[12:16]
     output += data[16:]
     return output
 def process_tfhd(self, data):
     "Process the mvhd box and set timescale."
     tf_flags = str_to_uint32(data[8:12]) & 0xffffff
     print "tfhd flags = %06x" % tf_flags
     output = data[0:12]
     if self.new_track_id is not None:
         old_track_id = str_to_uint32(data[12:16])
         output += uint32_to_str(self.new_track_id)
         print "Changed trackId from %d to %d" % (old_track_id, self.new_track_id)
     else:
         output += data[12:16]
     output += data[16:]
     return output
Example #6
0
 def filterbox(self, box_type, data, file_pos, path=""):
     "Filter box or tree of boxes recursively."
     #pylint: disable=too-many-branches
     if path == "":
         path = box_type
     else:
         path = "%s.%s" % (path, box_type)
     output = ""
     if path in ("moov", "moov.trak", "moov.trak.mdia"):
         output += data[:8]
         pos = 8
         while pos < len(data):
             size, box_type = self.check_box(data[pos:pos + 8])
             output += self.filterbox(box_type, data[pos:pos + size],
                                      file_pos + len(output), path)
             pos += size
     elif path == "moov.mvhd":  # Set movie duration
         version = ord(data[8])
         if version == 1:
             self.movie_timescale = str_to_uint32(data[28:32])
             output += data[:32]
             output += '\xff' * 8  # duration
             output += data[40:]
         else:  # version = 0
             self.movie_timescale = str_to_uint32(data[20:24])
             output += data[:24]
             output += '\xff' * 4  # duration
             output += data[28:]
     elif path == "moov.trak.tkhd":  # Set trak duration
         version = ord(data[8])
         if version == 1:
             output += data[:36]
             output += '\xff' * 8  # duration
             output += data[44:]
         else:  # version = 0
             output += data[:28]
             output += '\xff' * 4  # duration
             output += data[32:]
     elif path == "moov.trak.mdia.mdhd":  # Set media duration
         version = ord(data[8])
         if version == 1:
             output += data[:32]
             output += '\xff' * 8  # duration
             output += data[40:]
         else:  # version = 0
             output += data[:24]
             output += '\xff' * 4  # duration
             output += data[28:]
     else:
         output = data
     return output
 def filterbox(self, box_type, data, file_pos, path=""):
     "Filter box or tree of boxes recursively."
     #pylint: disable=too-many-branches
     if path == "":
         path = box_type
     else:
         path = "%s.%s" % (path, box_type)
     output = ""
     if path in ("moov", "moov.trak", "moov.trak.mdia"):
         output += data[:8]
         pos = 8
         while pos < len(data):
             size, box_type = self.check_box(data[pos:pos + 8])
             output += self.filterbox(box_type, data[pos:pos + size], file_pos + len(output), path)
             pos += size
     elif path == "moov.mvhd": # Set movie duration
         version = ord(data[8])
         if version == 1:
             self.movie_timescale = str_to_uint32(data[28:32])
             output += data[:32]
             output += '\xff'*8 # duration
             output += data[40:]
         else: # version = 0
             self.movie_timescale = str_to_uint32(data[20:24])
             output += data[:24]
             output += '\xff'*4 # duration
             output += data[28:]
     elif path == "moov.trak.tkhd": # Set trak duration
         version = ord(data[8])
         if version == 1:
             output += data[:36]
             output += '\xff'*8 # duration
             output += data[44:]
         else: # version = 0
             output += data[:28]
             output += '\xff'*4 # duration
             output += data[32:]
     elif path == "moov.trak.mdia.mdhd": # Set media duration
         version = ord(data[8])
         if version == 1:
             output += data[:32]
             output += '\xff'*8 # duration
             output += data[40:]
         else: # version = 0
             output += data[:24]
             output += '\xff'*4 # duration
             output += data[28:]
     else:
         output = data
     return output
Example #8
0
 def process_mvhd(self, data):
     "Process the mvhd box and set timescale."
     output = ""
     version = ord(data[8])
     if version == 1:
         self.movie_timescale = str_to_uint32(data[28:32])
         output += data[:32]
         output += '\x00' * 8  # duration
         output += data[40:]
     else:  # version = 0
         self.movie_timescale = str_to_uint32(data[20:24])
         output += data[:24]
         output += '\x00' * 4  # duration
         output += data[28:]
     return output
 def process_mvhd(self, data):
     "Process the mvhd box and set timescale."
     output = ""
     version = ord(data[8])
     if version == 1:
         self.movie_timescale = str_to_uint32(data[28:32])
         output += data[:32]
         output += '\x00'*8 # duration
         output += data[40:]
     else: # version = 0
         self.movie_timescale = str_to_uint32(data[20:24])
         output += data[:24]
         output += '\x00'*4 # duration
         output += data[28:]
     return output
Example #10
0
 def filterbox(self, box_type, data, file_pos, path=""):
     "Filter box or tree of boxes recursively."
     if path == "":
         path = box_type
     else:
         path = "%s.%s" % (path, box_type)
     output = ""
     if path in ("moov", "moov.trak", "moov.trak.mdia"):
         output += data[:8]
         pos = 8
         while pos < len(data):
             size, box_type = self.check_box(data[pos:pos + 8])
             output += self.filterbox(box_type, data[pos:pos + size],
                                      file_pos + len(output), path)
             pos += size
     elif path == "moov.trak.mdia.mdhd":  # Find timescale
         self.track_timescale = str_to_uint32(data[20:24])
         #print "Found track_timescale=%d" % self.track_timescale
         output = data
     elif path == "moov.trak.mdia.hdlr":  # Find track type
         self.handler_type = data[16:20]
         output = data
     else:
         output = data
     return output
Example #11
0
 def process_tkhd(self, data):
     "Process tkhd and set flags, trackId and duration."
     version = ord(data[8])
     output = data[0:9]
     output += '\x00' + '\x00' + '\x07'  # Set flags to 0x000007
     pos = 12
     if version == 1:
         drange = 16
     else:
         drange = 8
     output += data[pos:pos + drange]
     pos += drange
     if self.new_track_id is not None:
         old_track_id = str_to_uint32(data[pos:pos + 4])
         output += uint32_to_str(self.new_track_id)
         print "Changed trackId from %d to %d" % (old_track_id,
                                                  self.new_track_id)
     else:
         output += data[pos:pos + 4]
     pos += 4
     output += data[pos:pos + 4]
     pos += 4
     if version == 1:
         output += '\x00' * 8  # duration
         pos += 8
     else:  # version = 0
         output += '\x00' * 4  # duration
         pos += 4
     output += data[pos:]
     return output
 def process_tkhd(self, data):
     "Process tkhd and set flags, trackId and duration."
     version = ord(data[8])
     output = data[0:9]
     output += '\x00' + '\x00' + '\x07' # Set flags to 0x000007
     pos = 12
     if version == 1:
         drange = 16
     else:
         drange = 8
     output += data[pos:pos+drange]
     pos += drange
     if self.new_track_id is not None:
         old_track_id = str_to_uint32(data[pos:pos+4])
         output += uint32_to_str(self.new_track_id)
         print "Changed trackId from %d to %d" % (old_track_id, self.new_track_id)
     else:
         output += data[pos:pos+4]
     pos += 4
     output += data[pos:pos+4]
     pos += 4
     if version == 1:
         output += '\x00'*8 # duration
         pos += 8
     else: # version = 0
         output += '\x00'*4 # duration
         pos += 4
     output += data[pos:]
     return output
Example #13
0
    def process_trun(self, data, output):
        """Adjust composition_time_offset to start at 0 if present."""
        version_and_flags = str_to_uint32(data[8:12])
        version = version_and_flags >> 24
        flags = version_and_flags & 0x00ffffff

        cto_present = flags & 0x000800  # composition_time_offset_present

        if not cto_present:
            return data  # Nothing to do

        output = data[:8] + '\x01' + data[9:12]  # Full header version 1

        sample_count = str_to_uint32(data[12:16])
        offset = 16

        if flags & 0x000001:  # data-offset-present
            offset += 4

        if flags & 0x000004:  # first-sample-flags-present
            offset += 4

        output += data[12:offset]
        cto_shift = None

        optional_bytes_before_cto = 0
        if flags & 0x000100:  # sample-duration-present
            optional_bytes_before_cto += 4
        if flags & 0x000200:  # sample-size-present
            optional_bytes_before_cto += 4
        if flags & 0x000400:  # sample-flags-present
            optional_bytes_before_cto += 4

        for i in range(sample_count):
            output += data[offset:offset + optional_bytes_before_cto]
            offset += optional_bytes_before_cto

            cto = str_to_sint32(data[offset:offset + 4])
            if i == 0:
                cto_shift = -cto
            cto += cto_shift
            output += sint32_to_str(cto)
            offset += 4

        return output
 def process_mfhd(self, data):
     "Extract sequence number."
     sequence_number = str_to_uint32(data[12:16])
     segment = {
         'sequence_number': sequence_number,
         'moof_start_offset': self.last_moof_start
     }
     self.input_segments.append(segment)
     return data
 def process_mdhd(self, data):
     "Extract track timescale."
     version = ord(data[8])
     if version == 1:
         offset = 28
     else:
         offset = 20
     self.track_timescale = str_to_uint32(data[offset:offset + 4])
     return data
 def process_trun(self, data):
     """Extract trun information into self.segments[-1] and self.samples"""
     version_and_flags = str_to_uint32(data[8:12])
     # version = version_and_flags >> 24
     flags = version_and_flags & 0xffffff
     sample_count = str_to_uint32(data[12:16])
     first_sample_flags = None
     pos = 16
     start = self.base_media_decode_time
     data_offset = self.last_moof_start
     if flags & 0x1:  # data_offset_present
         data_offset += str_to_uint32(data[pos:pos + 4])
         pos += 4
     else:
         raise ValueError("Cannot handle case without data_offset")
     if flags & 0x4:  # first_sample_flags
         first_sample_flags = str_to_uint32(data[pos:pos + 4])
         pos += 4
         if flags & 0x400:  # sample_flags present
             raise ValueError("Sample flags are not allowed with first")
     self.trun_base_size = pos  # How many bytes this far
     if self.trun_sample_flags is None:
         self.trun_sample_flags = flags
     for i in range(sample_count):
         sample_duration = self.default_sample_duration
         sample_size = self.default_sample_size
         sample_flags = self.default_sample_flags
         if i == 0 and first_sample_flags is not None:
             sample_flags = first_sample_flags
         cto = self.default_sample_cto
         if flags & 0x100:  # sample_duration present
             sample_duration = str_to_uint32(data[pos:pos + 4])
             pos += 4
         if flags & 0x200:  # sample_size present
             sample_size = str_to_uint32(data[pos:pos + 4])
             pos += 4
         if flags & 0x400:  # sample_flags present
             sample_flags = str_to_uint32(data[pos:pos + 4])
             pos += 4
         if flags & 0x800:  # composition_time_offset present
             cto = str_to_uint32(data[pos:pos + 4])
             pos += 4
         if cto is None:
             cto = 0
         sample = SampleData(start, sample_duration, sample_size,
                             data_offset, sample_flags, cto)
         self.samples.append(sample)
         start += sample_duration
         data_offset += sample_size
     seg = self.input_segments[-1]
     seg['duration'] = start - self.base_media_decode_time
     return data
Example #17
0
    def process_trun(self, data):
        tf_flags = str_to_uint32(data[8:12]) & 0xffffff

        output = data[0:8]
        output += uint32_to_str(tf_flags)

        print "Changing trun sample count"
        output += uint32_to_str(1)

        if tf_flags & 1:
            data_offset = str_to_uint32(data[16:20])
            if self.new_default_sample_duration is not None:
                print "Changing trun data offset: %d to %d"%(data_offset, data_offset + 4)
                data_offset += 4

            output += uint32_to_str(data_offset)

            output += data[20:]

        return output
 def process_tfdt(self, data):
     "Extract baseMediaDecodeTime."
     version = ord(data[8])
     if version == 0:
         self.base_media_decode_time = str_to_uint32(data[12:16])
     else:
         self.base_media_decode_time = str_to_uint64(data[12:20])
     seg = self.input_segments[-1]
     seg['base_media_decode_time'] = self.base_media_decode_time
     self.tfdt_size = len(data)
     return data
 def process_sidx(self, data, file_pos):
     "Extract sidx parts."
     version = ord(data[8])
     timescale = str_to_uint32(data[16:20])
     if version == 0:
         earliest_time = str_to_uint32(data[20:24])
         first_offset = str_to_uint32(data[24:28])
         pos = 28
     else:
         earliest_time = str_to_uint32(data[20:28])
         first_offset = str_to_uint64(data[28:36])
         pos = 36
     if first_offset != 0:
         raise ValueError("Only supports first_offset == 0")
     pos += 2
     reference_count = str_to_uint16(data[pos:pos + 2])
     pos += 2
     sidx_data = {'timescale': timescale, 'segments': []}
     offset = file_pos + len(data) + first_offset
     start = earliest_time
     for i in range(reference_count):
         field = str_to_uint32(data[pos:pos + 4])
         pos += 4
         reference_type = field >> 31
         if reference_type != 0:
             raise ValueError("Only sidx reference type == 0 supported")
         size = field & 0x7fffffff
         duration = str_to_uint32(data[pos:pos + 4])
         if self.verbose:
             print("Input sidx %d: dur=%d" % (i + 1, duration))
         pos += 4
         field = str_to_uint32(data[pos:pos + 4])
         pos += 4
         starts_with_sap = field >> 31
         if starts_with_sap != 1:
             raise ValueError("Only sidx with starts_with_sap supported")
         sap_type = (field >> 28) & 0x7
         if sap_type != 1:
             raise ValueError("Only sap type 1 supported, not %d" %
                              sap_type)
         sap_delta_time = field & 0x0fffffff
         if sap_delta_time != 0:
             raise ValueError("Only sap_delta_time == 0 supported")
         seg_data = {
             'offset': offset,
             'size': size,
             'start': start,
             'duration': duration
         }
         sidx_data['segments'].append(seg_data)
         offset += size
         start += duration
     self.sidx_data = sidx_data
     return data
Example #20
0
def change_brands(indata, major_brand, compatibility_brands, minor_version=0):
    "Change brands in input string indata and return new string."
    size = str_to_uint32(indata)
    ftyp = indata[4:8]
    assert ftyp == "ftyp"
    in_major_brand = indata[8:12]
    print "Changing major brand %s - > %s" % (in_major_brand, major_brand)
    in_minor_version = str_to_uint32(indata[12:16])
    print "minorVersion: %s -> %s" % (in_minor_version, minor_version)
    pos = 16
    in_compatibility_brands = []
    while pos < size:
        in_compatibility_brands.append(indata[pos:pos+4])
        pos += 4
    print "Compatibility brands: %s -> %s" % (in_compatibility_brands, compatibility_brands)

    out_size = 16 + 4*len(compatibility_brands)
    outdata = uint32_to_str(out_size) + "ftyp" + major_brand + uint32_to_str(minor_version)
    for brand in compatibility_brands:
        outdata += brand
    outdata += indata[size:]
    return outdata
def change_brands(indata, major_brand, compatibility_brands, minor_version=0):
    "Change brands in input string indata and return new string."
    size = str_to_uint32(indata)
    ftyp = indata[4:8]
    assert ftyp == "ftyp"
    in_major_brand = indata[8:12]
    print "Changing major brand %s - > %s" % (in_major_brand, major_brand)
    in_minor_version = str_to_uint32(indata[12:16])
    print "minorVersion: %s -> %s" % (in_minor_version, minor_version)
    pos = 16
    in_compatibility_brands = []
    while pos < size:
        in_compatibility_brands.append(indata[pos : pos + 4])
        pos += 4
    print "Compatibility brands: %s -> %s" % (in_compatibility_brands, compatibility_brands)

    out_size = 16 + 4 * len(compatibility_brands)
    outdata = uint32_to_str(out_size) + "ftyp" + major_brand + uint32_to_str(minor_version)
    for brand in compatibility_brands:
        outdata += brand
    outdata += indata[size:]
    return outdata
Example #22
0
 def process_tfdt(self, data, output):
     """Adjust time of tfdt if offset set."""
     version = ord(data[8])
     if version == 0: # 32-bit baseMediaDecodeTime
         tfdt = str_to_uint32(data[12:16])
         if self.offset != None:
             tfdt += self.offset
             output += data[:12] + uint32_to_str(tfdt) + data[16:]
         else:
             output += data
     else:
         output = data[:12]
         tfdt = str_to_uint64(data[12:20])
         if self.offset != None:
             tfdt += self.offset
             output += uint64_to_str(tfdt)
         else:
             output += data
     self.tfdt = tfdt
     return output
 def process_tfdt(self, data, output):
     """Adjust time of tfdt if offset set."""
     version = ord(data[8])
     if version == 0: # 32-bit baseMediaDecodeTime
         tfdt = str_to_uint32(data[12:16])
         if self.offset != None:
             tfdt += self.offset
             output += data[:12] + uint32_to_str(tfdt) + data[16:]
         else:
             output += data
     else:
         output = data[:12]
         tfdt = str_to_uint64(data[12:20])
         if self.offset != None:
             tfdt += self.offset
             output += uint64_to_str(tfdt)
         else:
             output += data
     self.tfdt = tfdt
     return output
Example #24
0
    def process_file(self):
        "Process the file and add or remove lmsg."
        ifh = open(self.file_path, "rb")
        data = ifh.read()
        styplen = str_to_uint32(data[:4])
        box_type = data[4:8]
        assert box_type == "styp"

        pos = 16
        lmsg_found = False
        while pos < styplen:
            compatible_brand = data[pos:pos + 4]
            if compatible_brand == "lmsg":
                lmsg_found = True
                if self.remove_lmsg_flag:
                    print "Found lmsg to remove"
                    break
            pos += 4
        ofh = cStringIO.StringIO()
        if self.add_lmsg_flag and not lmsg_found:
            ofh.write(uint32_to_str(styplen + 4))
            ofh.write(data[4:styplen])
            ofh.write("lmsg")
            ofh.write(data[styplen:])
            print "Adding lmsg"
        elif self.remove_lmsg_flag and lmsg_found:
            ofh.write(uint32_to_str(styplen - 4))
            ofh.write(data[4:pos])
            ofh.write(data[pos + 4:])
        else:
            print "No change done to %s" % self.file_path
            return  # Nothing to do
        ifh.close()
        replace = open(self.file_path, "wb")
        replace.write(ofh.getvalue())
        replace.close()
        print "Wrote %s" % self.file_path
    def process_file(self):
        "Process the file and add or remove lmsg."
        ifh = open(self.file_path, "rb")
        data = ifh.read()
        styplen = str_to_uint32(data[:4])
        box_type = data[4:8]
        assert box_type == "styp"

        pos = 16
        lmsg_found = False
        while pos < styplen:
            compatible_brand = data[pos:pos+4]
            if compatible_brand == "lmsg":
                lmsg_found = True
                if self.remove_lmsg_flag:
                    print "Found lmsg to remove"
                    break
            pos += 4
        ofh = cStringIO.StringIO()
        if self.add_lmsg_flag and not lmsg_found:
            ofh.write(uint32_to_str(styplen+4))
            ofh.write(data[4:styplen])
            ofh.write("lmsg")
            ofh.write(data[styplen:])
            print "Adding lmsg"
        elif self.remove_lmsg_flag and lmsg_found:
            ofh.write(uint32_to_str(styplen-4))
            ofh.write(data[4:pos])
            ofh.write(data[pos+4:])
        else:
            print "No change done to %s" % self.file_path
            return # Nothing to do
        ifh.close()
        replace = open(self.file_path, "wb")
        replace.write(ofh.getvalue())
        replace.close()
        print "Wrote %s" % self.file_path
 def filterbox(self, box_type, data, file_pos, path=""):
     "Filter box or tree of boxes recursively."
     if path == "":
         path = box_type
     else:
         path = "%s.%s" % (path, box_type)
     output = ""
     if path in ("moov", "moov.trak", "moov.trak.mdia"):
         output += data[:8]
         pos = 8
         while pos < len(data):
             size, box_type = self.check_box(data[pos:pos + 8])
             output += self.filterbox(box_type, data[pos:pos+size], file_pos + len(output), path)
             pos += size
     elif path == "moov.trak.mdia.mdhd": # Find timescale
         self.track_timescale = str_to_uint32(data[20:24])
         #print "Found track_timescale=%d" % self.track_timescale
         output = data
     elif path == "moov.trak.mdia.hdlr": # Find track type
         self.handler_type = data[16:20]
         output = data
     else:
         output = data
     return output
    def process_tfhd(self, data):
        """Check flags and set default values.

        We are only interested in some values."""
        tf_flags = str_to_uint32(data[8:12]) & 0xffffff
        self.track_id = str_to_uint32(data[12:16])
        pos = 16
        if tf_flags & 0x000001:  # base_data_offset_present
            base_data_offset = str_to_uint64(data[pos:pos + 8])
            pos += 8
        if tf_flags & 0x000002:  # sample-description-index-present
            sample_description_index = str_to_uint32(data[pos:pos + 4])
            pos += 4
        if tf_flags & 0x000008:  # default_sample_duration_present
            self.default_sample_duration = str_to_uint32(data[pos:pos + 4])
            pos += 4
        if tf_flags & 0x000010:  # default_sample_size_present
            self.default_sample_size = str_to_uint32(data[pos:pos + 4])
            pos += 4
        if tf_flags & 0x000020:  # default_sample_flags_present
            self.default_sample_flags = str_to_uint32(data[pos:pos + 4])
            pos += 4
        return data
    def process_trun(self, data):
        """Remove all samples but one, and change offset and report size."""
        size, b_type = self.check_box(data)
        assert b_type == "trun"
        self.trun_data = {'size': size}
        # version = ord(data[8])

        flags = str_to_uint32(data[8:12]) & 0xffffff
        has_data_offset = flags & 0x0001
        if not has_data_offset:
            raise ValueError("Cannot shorten segment without data_offset")
        has_first_sample_flags = flags & 0x0004
        has_sample_duration = flags & 0x0100
        if not has_sample_duration:
            raise ValueError("Cannot shorten segment without sample duration")
        has_sample_size = flags & 0x0200
        if not has_sample_size:
            raise ValueError("Cannot shorten segment without sample_size")
        has_sample_flags = flags & 0x0400
        has_sample_composition_time_offset = flags & 0x0800

        sample_count = str_to_uint32(data[12:16])

        entry_offset = 16

        data_offset = str_to_uint32(data[entry_offset:entry_offset + 4])
        entry_offset += 4

        if has_first_sample_flags:
            entry_offset += 4

        sample_row_size = ((has_sample_duration and 4) +
                           (has_sample_size and 4) + (has_sample_flags and 4) +
                           (has_sample_composition_time_offset and 4))

        # Iterate over all samples and add up duration.
        # Set the duration of the I-frame to the total duration

        total_duration = 0

        pos = entry_offset
        for i in range(sample_count):
            total_duration += str_to_uint32(data[pos:pos + 4])
            pos += 4
            if i == 0:
                sample_size = str_to_uint32(data[pos:pos + 4])
                self.trun_data['first_sample_size'] = sample_size
            pos += 4
            if has_sample_flags:
                pos += 4
            if has_sample_composition_time_offset:
                pos += 4

        new_size = size - (sample_count - 1) * sample_row_size
        self.trun_data['new_size'] = new_size

        new_data_offset = data_offset - (size - new_size)

        # Here starts the trun output
        output = uint32_to_str(new_size) + data[4:12]
        output += uint32_to_str(1)  # 1 sample
        output += uint32_to_str(new_data_offset)
        pos = entry_offset
        if has_first_sample_flags:
            output += data[pos:pos + 4]
            pos += 4
        output += uint32_to_str(total_duration)
        pos += 4
        output += data[pos:pos + sample_row_size - 4]

        return output
 def check_box(self, data):
     "Check the type of box starting at position pos."
     #pylint: disable=no-self-use
     size = str_to_uint32(data[:4])
     box_type = data[4:8]
     return (size, box_type)
Example #30
0
 def check_box(self, data):
     "Check the type of box starting at position pos."
     #pylint: disable=no-self-use
     size = str_to_uint32(data[:4])
     box_type = data[4:8]
     return (size, box_type)