def testSaioInput(self): "Test that saio offset is according to what file analysis shows.d" fileName = join(CONTENT_ROOT, "testpic_2s/cenc1.m4s") self.f = mediasegmentfilter.MediaSegmentFilter(fileName) self.f.filter() self.assertEqual(self.f.size_change, 0) self.assertEqual(self.f.new_saio_value, self.input_saio_offset)
def testSaioChanged(self): "Test that saio offset changed by 4 (tfdt box size increase)." fileName = join(CONTENT_ROOT, "testpic_2s/cenc1.m4s") self.f = mediasegmentfilter.MediaSegmentFilter(fileName, offset=1564997232, track_timescale=90000) self.f.filter() self.assertEqual(self.f.size_change, 4) self.assertEqual(self.f.new_saio_value, self.input_saio_offset + 4)
def checkAndUpdateMediaData(self): """Check all segments for good values and return startTimes and total duration.""" lastGoodSegments = [] print("Checking all the media segment durations for deviations.") def writeSegTiming(ofh, firstSegmentInRepeat, firstStartTimeInRepeat, duration, repeatCount): data = pack(configprocessor.SEGTIMEFORMAT, firstSegmentInRepeat, repeatCount, firstStartTimeInRepeat, duration) ofh.write(data) for content_type in self.as_data.keys(): as_data = self.as_data[content_type] as_data['datFile'] = "%s_%s.dat" % (self.base_name, content_type) adaptation_set = as_data['as'] print("Checking %s with timescale %d" % (content_type, as_data['track_timescale'])) if self.segDuration is None: self.segDuration = adaptation_set.duration else: assert self.segDuration == adaptation_set.duration track_timescale = as_data['track_timescale'] with open(as_data['datFile'], "wb") as ofh: for (rep_nr, rep_data) in enumerate(as_data['reps']): rep_id = rep_data['id'] rep_data['endNr'] = None rep_data['startTick'] = None rep_data['endTick'] = None if self.firstSegmentInLoop >= 0: assert rep_data['firstNumber'] == self.firstSegmentInLoop else: self.firstSegmentInLoop = rep_data['firstNumber'] if self.mpdSegStartNr >= 0: assert adaptation_set.start_number == self.mpdSegStartNr else: self.mpdSegStartNr = adaptation_set.start_number segTicks = self.segDuration*track_timescale maxDiffInTicks = int(track_timescale*0.1) # Max 100ms segNr = rep_data['firstNumber'] repeatCount = -1 firstSegmentInRepeat = -1 firstStartTimeInRepeat = -1 lastDuration = 0 while (True): segmentPath = rep_data['absMediaPath'] % segNr if not os.path.exists(segmentPath): if self.verbose: print("\nLast good %s segment is %d, endTime=%.3fs, totalTime=%.3fs" % ( rep_id, rep_data['endNr'], rep_data['endTime'], rep_data['endTime']-rep_data['startTime'])) break msf = mediasegmentfilter.MediaSegmentFilter( segmentPath, default_sample_duration = rep_data[ 'default_sample_duration']) msf.filter() tfdt = msf.get_tfdt_value() duration = msf.get_duration() print("{0} {1:8d} {2} {3}".format(content_type, segNr, tfdt, duration)) if duration == lastDuration: repeatCount += 1 else: if lastDuration != 0 and rep_nr == 0: writeSegTiming(ofh, firstSegmentInRepeat, firstStartTimeInRepeat, lastDuration, repeatCount) repeatCount = 0 lastDuration = duration firstSegmentInRepeat = segNr firstStartTimeInRepeat = tfdt if rep_data['startTick'] is None: rep_data['startTick'] = tfdt rep_data['startTime'] = rep_data['startTick']/float(track_timescale) print("First %s segment is %d starting at time %.3fs" % (rep_id, segNr, rep_data['startTime'])) # Check that there is not too much drift. We want to end with at most maxDiffInTicks endTick = tfdt + duration idealTicks = (segNr - rep_data['firstNumber'] + 1)*segTicks + rep_data['startTick'] absDiffInTicks = abs(idealTicks - endTick) if absDiffInTicks < maxDiffInTicks: # This is a good wrap point rep_data['endTick'] = tfdt + duration rep_data['endTime'] = rep_data['endTick']/float(track_timescale) rep_data['endNr'] = segNr else: raise DashAnalyzerError("Too much drift in the duration of the segments") segNr += 1 if self.verbose: sys.stdout.write(".") if rep_nr == 0: writeSegTiming(ofh, firstSegmentInRepeat, firstStartTimeInRepeat, duration, repeatCount) lastGoodSegments.append(rep_data['endNr']) as_data['totalTicks'] = rep_data['endTick'] - rep_data['startTick'] self.lastSegmentInLoop = min(lastGoodSegments) self.nrSegmentsInLoop = self.lastSegmentInLoop-self.firstSegmentInLoop+1 self.loopTime = self.nrSegmentsInLoop*self.segDuration if self.verbose: print("") print("Will loop segments %d-%d with loop time %ds" % (self.firstSegmentInLoop, self.lastSegmentInLoop, self.loopTime))
def check_and_update_media_data(self): """Check all segments for good values and return startTimes and total duration.""" # pylint: disable=too-many-locals,too-many-branches,too-many-statements #lastGoodSegments = [] seg_duration = None print("Checking all the media segment durations for deviations.") for content_type in self.as_data.keys(): if content_type == "video": as_data = self.as_data[content_type] adaptation_set = as_data['as'] print("Checking %s with timescale %d" % (content_type, as_data['track_timescale'])) if self.seg_duration is None: seg_duration = adaptation_set.duration self.seg_duration = seg_duration else: assert self.seg_duration == adaptation_set.duration track_timescale = as_data['track_timescale'] # Parse SCC file scc_parser = SCCParser(self.scc_filepath, track_timescale) scc_parser.parse() self.scc_data = scc_parser.result for rep_data in as_data['reps']: rep_id = rep_data['id'] rep_data['endNr'] = None rep_data['startTick'] = None rep_data['endTick'] = None if self.first_segment_in_loop >= 0: assert rep_data[ 'firstNumber'] == self.first_segment_in_loop else: self.first_segment_in_loop = rep_data['firstNumber'] if self.mpd_seg_start_nr >= 0: assert adaptation_set.start_number == self.mpd_seg_start_nr else: self.mpd_seg_start_nr = adaptation_set.start_number seg_ticks = self.seg_duration * track_timescale max_diff_in_ticks = int(track_timescale * 0.1) # Max 100ms seg_nr = rep_data['firstNumber'] while True: segment_path = rep_data['absMediaPath'] % seg_nr if not os.path.exists(segment_path): if self.verbose: print( "\nLast good %s segment is %d, endTime=%.3fs, totalTime=%.3fs" % (rep_id, rep_data['endNr'], rep_data['endTime'], rep_data['endTime'] - rep_data['startTime'])) break # print "Parsing segment: " + segment_path msf = mediasegmentfilter.MediaSegmentFilter( segment_path) msf.filter() tfdt = msf.get_tfdt_value() duration = msf.get_duration() start_time = tfdt / float(track_timescale) end_time = start_time + (duration / float(track_timescale)) print("Segment " + str(seg_nr) + ", start:" + str(start_time) + ", end:" + str(end_time)) scc_data_for_segment = self.get_scc_data( start_time, end_time) if len(scc_data_for_segment): # for i in scc_data_for_segment: # print " ",i['start_time'], 'bytes:', len(i['cea608']) # Insert data into segment cc_filter = CCInsertFilter(segment_path, scc_data_for_segment, track_timescale, tfdt) output = cc_filter.filter() print( os.path.join(self.out_path, "%d.m4s" % seg_nr)) with open( os.path.join(self.out_path, "%d.m4s" % seg_nr), "wb") as fil: fil.write(output) fil.close() if rep_data['startTick'] is None: rep_data['startTick'] = tfdt rep_data['startTime'] = rep_data[ 'startTick'] / float(track_timescale) # print "First %s segment is %d starting at time %.3fs" % (rep_id, seg_nr, # rep_data['startTime']) # Check that there is not too much drift. We want to end with at most max_diff_in_ticks end_tick = tfdt + duration ideal_ticks = (seg_nr - rep_data['firstNumber'] + 1) * seg_ticks + rep_data['startTick'] abs_diff_in_ticks = abs(ideal_ticks - end_tick) if abs_diff_in_ticks < max_diff_in_ticks: # This is a good wrap point rep_data['endTick'] = tfdt + duration rep_data['endTime'] = rep_data['endTick'] / float( track_timescale) rep_data['endNr'] = seg_nr seg_nr += 1 if self.verbose: sys.stdout.write(".")