Beispiel #1
0
 def process_saio(self, data):
     "Process saio and possibly change offset by size_change if needed."
     version_flags = str_to_uint32(data[8:12])
     version = version_flags >> 24
     flags = version_flags & 0xffffff
     pos = 12
     if flags & 0x1:
         pos += 8
     entry_count = str_to_uint32(data[pos:pos + 4])
     pos += 4
     output = data[:pos]
     delta_offset = self.size_change
     if version == 0:
         for i in range(entry_count):
             offset = str_to_uint32(data[pos:pos + 4])
             pos += 4
             output += uint32_to_str(offset + delta_offset)
             if i == 0:
                 self.new_saio_value = offset + delta_offset
     else:
         for i in range(entry_count):
             offset = str_to_uint64(data[pos:pos + 8])
             pos += 8
             output += uint64_to_str(offset + delta_offset)
             if i == 0:
                 self.new_saio_value = offset + delta_offset
     return output
Beispiel #2
0
    def process_tfdt(self, data):
        """Generate new timestamps for tfdt and change size of boxes above if needed.

       Try to keep in 32 bits if possible."""
        version = data[8]
        if self.track_timescale is not None:
            tfdt_offset = self.offset * self.track_timescale
        else:
            tfdt_offset = 0
        if version == 0:  # 32-bit baseMediaDecodeTime
            base_media_decode_time = str_to_uint32(data[12:16])
            new_base_media_decode_time = base_media_decode_time + tfdt_offset
            if new_base_media_decode_time < 4294967296:
                output = data[:12]
                output += uint32_to_str(new_base_media_decode_time)
            else:
                # print "Forced to change to 64-bit tfdt."
                self.size_change = 4
                output = uint32_to_str(
                    str_to_uint32(data[:4]) + self.size_change)
                output += data[4:8]
                output += b'\x01'
                output += data[9:12]
                output += uint64_to_str(new_base_media_decode_time)
        else:  # 64-bit
            # print "Staying at 64-bit tfdt."
            output = data[:12]
            base_media_decode_time = str_to_uint64(data[12:20])
            new_base_media_decode_time = base_media_decode_time + tfdt_offset
            output += uint64_to_str(new_base_media_decode_time)
        self.tfdt_value = new_base_media_decode_time
        return output
Beispiel #3
0
 def process_sidx(self, data):
     "Process sidx data and add to output."
     if not KEEP_SIDX:
         return b""
     output = b""
     version = data[8]
     timescale = str_to_uint32(data[16:20])
     if version == 0:
         # print("Changing sidx version to 1")
         size = str_to_uint32(data[0:4])
         sidx_size_expansion = 8
         output += uint32_to_str(size + sidx_size_expansion)
         output += data[4:8]
         output += b'\x01'
         output += data[9:20]
         earliest_presentation_time = str_to_uint32(data[20:24])
         first_offset = str_to_uint32(data[24:28])
     else:
         output += data[0:20]
         earliest_presentation_time = str_to_uint64(data[20:28])
         first_offset = str_to_uint64(data[28:36])
     new_presentation_time = earliest_presentation_time + timescale * self.offset
     output += uint64_to_str(new_presentation_time)
     output += uint64_to_str(first_offset)
     if version == 0:
         output += data[28:]
     else:
         output += data[36:]
     return output
Beispiel #4
0
 def process_tfhd(self, data):
     "Process tfhd (assuming that we know the ttml size size)."
     tf_flags = str_to_uint32(data[8:12]) & 0xffffff
     pos = 16
     if tf_flags & 0x01:
         raise MediaSegmentFilterError(
             "base-data-offset-present not supported in ttml segments")
     if tf_flags & 0x02:
         pos += 4
     if tf_flags & 0x08:
         self.default_sample_duration = str_to_uint32(data[pos:pos + 4])
         pos += 4
     elif self.ttml_size:
         raise MediaSegmentFilterError(
             "Cannot handle ttml segments with default_sample_duration absent"
         )
     output = data[:pos]
     if self.ttml_size:
         if tf_flags & 0x10:
             # old_ttml__size = str_to_uint32(data[pos:pos+4])
             output += uint32_to_str(self.ttml_size)
             # print("Changed ttml sample size from %d to %d" % (old_ttml__size, self.ttml_size))
             pos += 4
         else:
             raise MediaSegmentFilterError(
                 "Cannot handle ttml segments if default_sample_size_offset is absent"
             )
     if self.ttml_size:
         output += data[pos:]
     else:
         output = data
     return output
 def parse_trun(self, data, pos):
     "Parse trun box and find position of data_offset."
     flags = str_to_uint32(data[8:12]) & 0xffffff
     data_offset_present = flags & 1
     if data_offset_present:
         self.trun_data_offset = str_to_uint32(data[16:20])
         self.trun_data_offset_in_traf = pos + 16 - self.traf_start
 def process_trex(self, data):
     # 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
 def process_tkhd(self, data):
     "Filter track header box and find track_id."
     assert self.track_id is None, "Multiple tracks in init file %s. Not supported." % self.filename
     version = data[8]
     if version == 0:
         self._track_id = str_to_uint32(data[20:24])
     elif version == 1:
         self._track_id = str_to_uint32(data[28:32])
     return data
 def process_mvhd(self, data):
     "Set duration in mvhd."
     version = data[8]
     output = b""
     if version == 1:
         self.movie_timescale = str_to_uint32(data[28:32])
         output += data[:32]
         output += b'\x00' * 8  # duration
         output += data[40:]
     else:  # version = 0
         self.movie_timescale = str_to_uint32(data[20:24])
         output += data[:24]
         output += b'\x00' * 4  # duration
         output += data[28:]
     return output
 def process_tfhd(self, data):
     "Process a tfhd box and set trackID, defaultSampleDuration and defaultSampleSize"
     tf_flags = str_to_uint32(data[8:12]) & 0xffffff
     assert tf_flags == 0x020018, "Can only handle certain tf_flags combinations"
     output = data[:12]
     output += uint32_to_str(self.track_id)
     output += uint32_to_str(self.default_sample_duration)
     output += uint32_to_str(len(self.ttml_data))
     return output
Beispiel #10
0
    def process_tfdt_to_64bit(self, data, output):
        """Generate new timestamps for tfdt and change size of boxes above if needed.

        Note that the input output will be returned and can have another size."""
        version = data[8]
        tfdt_offset = self.offset * self.track_timescale
        if version == 0:  # 32-bit baseMediaDecodeTime
            self.size_change = 4
            output = uint32_to_str(str_to_uint32(data[:4]) + self.size_change)
            output += data[4:8]
            output += b'\x01'
            output += data[9:12]
            base_media_decode_time = str_to_uint32(data[12:16])
        else:  # 64-bit
            output = data[:12]
            base_media_decode_time = str_to_uint64(data[12:20])
        new_base_media_decode_time = base_media_decode_time + tfdt_offset
        output += uint64_to_str(new_base_media_decode_time)
        self.tfdt_value = new_base_media_decode_time
        return output
Beispiel #11
0
    def process_trun(self, data):
        "Get total duration from trun. Fix offset if self.size_change is non-zero."
        flags = str_to_uint32(data[8:12]) & 0xffffff
        sample_count = str_to_uint32(data[12:16])
        pos = 16
        data_offset_present = False
        if flags & 0x1:  # Data offset present
            data_offset_present = True
            pos += 4
        if flags & 0x4:
            pos += 4  # First sample flags present
        sample_duration_present = flags & 0x100
        sample_size_present = flags & 0x200
        sample_flags_present = flags & 0x400
        sample_comp_time_present = flags & 0x800
        duration = 0
        for _ in range(sample_count):
            if sample_duration_present:
                duration += str_to_uint32(data[pos:pos + 4])
                pos += 4
            elif self.default_sample_duration is not None:
                duration += self.default_sample_duration
            if sample_size_present:
                pos += 4
            if sample_flags_present:
                pos += 4
            if sample_comp_time_present:
                pos += 4
        self.duration = duration

        # Modify data_offset
        output = data[:16]
        if data_offset_present and self.size_change > 0:
            offset = str_to_sint32(data[16:20])
            offset += self.size_change
            output += sint32_to_str(offset)
        else:
            output += data[16:20]
        output += data[20:]
        return output
Beispiel #12
0
 def find_and_process_mdat(self, data):
     "Change the ttml part of mdat and update mdat size. Return full new data."
     pos = 0
     output = b""
     while pos < len(data):
         size = str_to_uint32(data[pos:pos + 4])
         boxtype = data[pos + 4:pos + 8]
         if boxtype != b'mdat':
             output += data[pos:pos + size]
         else:
             output += self.update_ttml_mdat(data[pos:pos + size])
         pos += size
     return output
Beispiel #13
0
 def process_styp(self, data):
     "Process styp and make sure lmsg presence follows the lmsg flag parameter. Add scte35 box if appropriate"
     lmsg = self.lmsg
     output = b""
     size = str_to_uint32(data[:4])
     pos = 8
     brands = []
     while pos < size:
         brand = data[pos:pos + 4]
         if brand != b"lmsg":
             brands.append(brand)
         pos += 4
     if lmsg:
         brands.append(b"lmsg")
     new_size = 8 + 4 * len(brands)
     output += uint32_to_str(new_size)
     output += b"styp"
     for brand in brands:
         output += brand
     scte35box = self.create_scte35box()
     output += scte35box
     return output
Beispiel #14
0
    def process_trun(self, data):
        """Process trun box."""
        # pylint: disable=too-many-locals,too-many-branches,too-many-statements
        output = data[:16]

        flags = str_to_uint32(data[8:12]) & 0xffffff
        sample_count = str_to_uint32(data[12:16])
        pos = 16
        # data_offset_present = False

        if flags & 0x1:  # Data offset present
            # data_offset_present = True
            self.trun_offset = str_to_uint32(data[16:20])
            output += uint32_to_str(self.trun_offset)
            pos += 4
        if flags & 0x4:
            pos += 4  # First sample flags present

        sample_duration_present = flags & 0x100
        sample_size_present = flags & 0x200
        sample_flags_present = flags & 0x400
        sample_comp_time_present = flags & 0x800
        sample_time_tfdt = self.tfdt

        orig_sample_pos = 0

        for i in range(sample_count):
            duration = 0
            size = 0
            flags = 0
            comp_time = 0

            if sample_duration_present:
                duration = str_to_uint32(data[pos:pos + 4])
                pos += 4
            if sample_size_present:
                size = str_to_uint32(data[pos:pos + 4])
                pos += 4
            if sample_flags_present:
                flags = str_to_uint32(data[pos:pos + 4])
                pos += 4
            if sample_comp_time_present:
                comp_time = str_to_uint32(data[pos:pos + 4])
                pos += 4

            start_time = 0
            if i == 0:
                start_time = (sample_time_tfdt) / float(self.time_scale)
            else:
                start_time = (sample_time_tfdt + comp_time) / float(
                    self.time_scale)

            end_time = (sample_time_tfdt + comp_time + duration) / float(
                self.time_scale)
            # start_time = (sample_time_tfdt) / float(self.time_scale)
            # end_time = (sample_time_tfdt + duration) / float(self.time_scale)

            # print("startTime:", start_time, "(", comp_time, ")", ", endTime:", end_time)

            scc_samples = self.get_scc_data(start_time, end_time)
            orig_sample_pos += size
            if len(scc_samples):
                print(
                    " ", i, "SampleTime: " + str(
                        (sample_time_tfdt) / float(self.time_scale)),
                    "num samples to add: ", len(scc_samples))
                scc_generated_data = generate_data(scc_samples)
                self.scc_map.append({
                    'pos': orig_sample_pos,
                    'scc': scc_generated_data,
                    'len': len(scc_generated_data)
                })
                size += len(scc_generated_data)

            if sample_duration_present:
                output += uint32_to_str(duration)
            if sample_size_present:
                output += uint32_to_str(size)
            if sample_flags_present:
                output += uint32_to_str(flags)
            if sample_comp_time_present:
                output += uint32_to_str(comp_time)

            sample_time_tfdt += duration

        return output
 def process_mdhd(self, data):
     "Process mdhd to get track_timscale."
     self._track_timescale = str_to_uint32(data[20:24])
     return data
 def check_box(self, data):
     "Check the type of box starting at position pos."
     size = str_to_uint32(data[:4])
     boxtype = data[4:8]
     return (size, boxtype)