示例#1
0
 def pushData(self, data, fragment_duration, level, view, caps_data):
     debug(DEBUG, '%s pushData: pushed %s of data for level %s', self, 
         format_bytes(len(data)),
         level)
     self.evicted_segment = 0
     self.checkGstbuffer()
     
     # check view change for playout buffer eviction
     if (view != self.current_view):
         # check if gstreamer has enough data (for limiting rebuffering events)
         self.checkGstbuffer()
         # flush playout buffer
         byte = 0
         sec  = 0
         self.evicted_segment = len(self.pushed_segments)
         for segment in self.pushed_segments:
             byte += segment["len_segment"]
             sec  += segment["dur_segment"]
             
         self.queue['byte']   -= byte
         self.queue['sec']    -= sec
         del self.pushed_segments
         self.pushed_segments  = []
         self.playtime        -= sec
         
         # set new current view
         self.current_view = view
     
     # fill playout buffer
     self.queue['byte'] +=len(data)
     self.queue['sec']  +=fragment_duration
     self.pushed_segments.append(dict(len_segment=len(data), dur_segment=fragment_duration, data=data))
 def __harmonic_mean(v):
     '''Computes the harmonic mean of vector v'''
     x = numpy.array(v)
     debug(DEBUG+1, "%s __harmonic_mean: Bwe vect: %s", self, str(x))
     m =  1.0/(sum(1.0/x)/len(x))
     debug(DEBUG, "%s__harmonic_mean: Harmonic mean: %s/s", self, format_bytes(m))
     return m
示例#3
0
 def _onDataReceiving(self, connection, data_diff, remaining_data):
     '''
     Does something before segment download is completed (used with persistent connection)
     '''
     self.remaining_data = remaining_data
     debug(DEBUG+1, '%s _onDataReceiving: %s %s', self, format_bytes(data_diff), format_bytes(remaining_data))
     self.rate_calc.update(data_diff)
示例#4
0
 def pushData(self, data, fragment_duration, level, caps_data):
     debug(DEBUG, '%s pushData: pushed %s of data for level %s', self, 
         format_bytes(len(data)),
         level)
     self.queue['byte']+=len(data)
     self.queue['sec']+=fragment_duration
     self.pushed_segments.append(dict(len_segment=len(data),dur_segment=fragment_duration))
示例#5
0
    def fetchNextSegment(self,calledWithPort): 
        '''
        Schedules the download of the next segment at current level
        '''
	#print ("MY PID IS "+str(os.getpid()))
	test=calledWithPort;
        playlist = self.parser.playlists[self.getCurrentLevel()]
        debug(DEBUG+1, '%s fetchNextSegment level: %d cur_index: %d', self, self.getCurrentLevel(), self.getCurrentSegmentIndex())
        #
        if self.getCurrentSegmentIndex() < playlist['start_index']:
            self.setCurrentSegmentIndex(playlist['start_index'])
        if self.getCurrentSegmentIndex() > playlist['end_index']:
            # else live video (ONLY HLS!!)
            if playlist['is_live'] and self.parser.getPlaylistType() == 'HLS':
                debug(DEBUG, '%s fetchNextSegment cur_index %d', self, self.getCurrentSegmentIndex())
                self.parser.updateLevelSegmentsList(self.getCurrentLevel()).addCallback(self._updatePlaylistDone)
            # if video is vod
            else:
                debug(DEBUG, '%s fetchNextSegment last index', self)
            return
        cur_index=self.getCurrentSegmentIndex()
        levels = self.parser.getLevels()
        url_segment = playlist['segments'][cur_index]['url']
        byterange = playlist['segments'][cur_index]['byterange']
        if byterange != '':
            debug(DEBUG, '%s fetchNextSegment level: %d (%s/s) %d/%d : %s (byterange=%s)', self,
                self.getCurrentLevel(), 
                format_bytes(float(levels[self.getCurrentLevel()]['rate'])),
                self.getCurrentSegmentIndex(), 
                playlist['end_index'], url_segment, byterange)
        else:
            debug(DEBUG, '%s fetchNextSegment level: %d (%s/s) %d/%d : %s', self,
                self.getCurrentLevel(), 
                format_bytes(float(levels[self.getCurrentLevel()]['rate'])),
                self.getCurrentSegmentIndex(), 
                playlist['end_index'], url_segment)
        if self.controller.isBuffering():
            idle_duration = 0.0 #fetch segment after the last segment download is completed
	    print colored('GETTING AN IDLE DURATION OF '+str(idle_duration),'green')
        else:
            #FIXME 
	    #uncomment idle_duration again!
	    #idle_duration =0.0 
	    idle_duration = self.controller.getIdleDuration()
	    print colored('GETTING AN IDLE DURATION OF '+str(idle_duration),'green')
        # load the next segment
	#if calledWithPort:
	 #   if calledWithPort==getLocalport():
	#	reactor.callLater(idle_duration, self.startDownload, url_segment, byterange)
	    #    print("port seen from fetchNextSegment= "+str(getLocalport()))
	   #     print('called with port was '+ str(getLocalport()))
	  #  else:
         #       print('RACE CONDITION!!!!!!')
	#	print("port seen from fetchNextSegment= "+str(getLocalport()))
	#	return

	#else:	
	#    print('fetchNextSegment was not called from ZMQ')
	print("calling start download with test= "+str(test))
        reactor.callLater(idle_duration, self.startDownload, url_segment, byterange)
示例#6
0
 def pushData(self, data, fragment_duration, level, caps_data):
     debug(DEBUG, '%s pushData: pushed %s of data for level %s', self,
           format_bytes(len(data)), level)
     self.queue['byte'] += len(data)
     self.queue['sec'] += fragment_duration
     self.pushed_segments.append(
         dict(len_segment=len(data), dur_segment=fragment_duration))
示例#7
0
    def checkBuffering(self, _arg):
        '''
        Checks if the playback is going to buffering.
        Estimates the time required to complete the download of the current segment and verifies that it is less than the playout buffer lenght.

        In the case of "warning buffering", it deletes the current segment download, calculates the control action and sets the new level.
        This feature is available only with persistent connection.
        '''
        #FIXME Can't use it without persistent connection
        if self.rate_calc.rate and self.cur_index > self.inactive_cycle:
            remaining_secs = float(self.remaining_data/self.rate_calc.rate)
            debug(DEBUG+1,"%s checkBuffering: rate %s/s, remaining_data %s, remaining_secs %.3f, queued_time %.2f ", self, 
                format_bytes(self.rate_calc.rate), format_bytes(self.remaining_data), remaining_secs, self.media_engine.getQueuedTime()) 
            #Can cancel download only if the current level is greater than 0
            if self.media_engine.getQueuedTime() < remaining_secs and self.getCurrentLevel() > 0: 
                self.connection.stop()
                self.stop_segment_request = time.time() #update stop reqest when warning buffering occurs
                self.bwe = self.rate_calc.rate
                #Passing player parameters at the controller to calculate the control action
                self.updateFeedback(flag_check_buffering=True)
                #calc control action
                self.controller.setControlAction(self.controller.calcControlAction())
                # set new level
                if self.cur_index > self.inactive_cycle:
                    self.setLevel(self.controller.getControlAction())
                    debug(0,"%s WARNING BUFFERING!!! Delete and reload segment at level: %d", self, self.getCurrentLevel())
        else:
            return
示例#8
0
    def playNextGotRequest(self, data, factory):
        '''
        Updates feedbacks, calculates the control action and sets level of the next segment.

        :param data: downloaded data
        :param factory: the twisted factory (used without persistent connection)
        '''
        self.stop_segment_request = time.time()
        download_time = (self.stop_segment_request - self.start_segment_request)
        self.last_downloaded_time = download_time
        self.bwe = len(data)/download_time
        self.last_fragment_size = len(data)
        self.downloaded_bytes += len(data)
        self.downloaded_segments += 1
        debug(DEBUG, '%s __got_request: bwe: %s/s (fragment size: %s)', self, 
            format_bytes(self.bwe), format_bytes(len(data)))
        self.queuedTime = self.media_engine.getQueuedTime() + self.parser.getFragmentDuration()
        self.queuedBytes = self.media_engine.getQueuedBytes() + len(data)
        self.media_engine.pushData(data, self.parser.getFragmentDuration(), self.getCurrentLevel(), self.parser._getCapsDemuxer())
        del data
        self.cur_index += 1
        #Do something before calculating new control action
        self._onNewSegment()
        #Passing player parameters at the controller to calculate the control action
        self.updateFeedback(flag_check_buffering=False)
        #calc control action
        self.controller.setControlAction(self.controller.calcControlAction())
        # set new level
        if self.getDownloadedSegments() > self.getInactiveCycles():
            if self.enable_stress_test:
                self.stressTest()
            else:
                self.setLevel(self.controller.getControlAction())
        self.fetchNextSegment()
示例#9
0
    def setLevel(self, rate):
        '''
        Sets the level corresponding to the rate specified in B/s

        :param rate: rate in B/s that determines the level. The level is the one whose rate is the highest below ``rate``.
        '''
	

	if self.getPrio()==1:
		new_level=0
		self.setCurrentLevel(new_level)
		print("Prio next segment= true ")
		print("!!!PRIO")
		return new_level
		

	else:
		print("Prio next segment= false ")
		print("My socket is "+str(getLocalport()))

		new_level = self.controller.quantizeRate(rate)
		if new_level != self.getCurrentLevel():
		    debug(DEBUG, "%s setLevel: level: %d", self, new_level)
		    self.setCurrentLevel(new_level)
		    
		    #self.onLevelChanged()
		return new_level
示例#10
0
    def _onDataReceived(self, connection, data):
        '''
        Does something when segment download is completed (used with persistent connection)
        '''

        debug(DEBUG+1, '%s _onDataReceived: %s', self, format_bytes(len(data)))  
        self.playNextGotRequest(data, None)
示例#11
0
    def _onDataReceived(self, connection, data):
        '''
        Does something when segment download is completed (used with persistent connection)
        '''

        debug(DEBUG+1, '%s _onDataReceived: %s', self, format_bytes(len(data)))  
        self.playNextGotRequest(data, None)
    def calcControlAction(self):
        video_rates = self.feedback['rates']
        T_tilde = self.feedback['last_download_time']
        tau = self.feedback['fragment_duration']
        x_tilde = self.feedback['cur_rate'] * self.feedback[
            'fragment_duration'] / T_tilde  #bandwidth estimate sample on the last downloaded segment
        T_hat_old = self.getIdleDuration()
        #Actual inter-request time
        T = max(T_hat_old, T_tilde)
        self.T_old = T
        k = self.k
        w = self.w  #in B/s
        beta = self.beta

        x_hat = max(
            0,
            self.x_hat_last + T * k * (w - max(0, self.x_hat_last - x_tilde)))

        self.x_hat_last = x_hat
        control_action = self.__ewma_filter(x_hat)

        r = self.quantizeSpecialRate(control_action)
        B = self.feedback['queued_time']

        T_hat = r * float(tau) / control_action + beta * (float(B) -
                                                          float(self.Q))
        self.setIdleDuration(T_hat - T_tilde)
        debug(
            DEBUG,
            "%s calcControlAction: ca: %s/s r: %s/s x_tilde: %s/s x_hat: %s/s T_tilde: %.2f T_hat: %.2f T: %.2f",
            self, format_bytes(control_action), format_bytes(r),
            format_bytes(x_tilde), format_bytes(x_hat), T_tilde, T_hat, T)
        return r
示例#13
0
 def _onDataReceiving(self, connection, data_diff, remaining_data):
     '''
     Does something before segment download is completed (used with persistent connection)
     '''
     self.remaining_data = remaining_data
     debug(DEBUG+1, '%s _onDataReceiving: %s %s', self, format_bytes(data_diff), format_bytes(remaining_data))
     self.rate_calc.update(data_diff)
示例#14
0
    def checkBuffering(self, _arg):
	#exactly what we are doing?!?!?!?
        '''
        Checks if the playback is going to buffering.
        Estimates the time required to complete the download of the current segment and verifies that it is less than the playout buffer lenght.

        In the case of "warning buffering", it deletes the current segment download, calculates the control action and sets the new level.
        This feature is available only with persistent connection.
        '''
        #FIXME Can't use it without persistent connection
        if self.rate_calc.rate and self.cur_index > self.inactive_cycle:
            remaining_secs = float(self.remaining_data/self.rate_calc.rate)
            debug(DEBUG+1,"%s checkBuffering: rate %s/s, remaining_data %s, remaining_secs %.3f, queued_time %.2f ", self, 
                format_bytes(self.rate_calc.rate), format_bytes(self.remaining_data), remaining_secs, self.media_engine.getQueuedTime()) 
            #Can cancel download only if the current level is greater than 0
            if self.media_engine.getQueuedTime() < remaining_secs and self.getCurrentLevel() > 0: 
                self.connection.stop()
                self.stop_segment_request = time.time() #update stop reqest when warning buffering occurs
                self.bwe = self.rate_calc.rate
                #Passing player parameters at the controller to calculate the control action
                self.updateFeedback(flag_check_buffering=True)
                #calc control action
                self.controller.setControlAction(self.controller.calcControlAction())
                # set new level
                if self.cur_index > self.inactive_cycle:
                    self.setLevel(self.controller.getControlAction())
                    debug(0,"%s WARNING BUFFERING!!! Delete and reload segment at level: %d", self, self.getCurrentLevel())
        else:
            return
示例#15
0
    def startDownload(self, url, byterange=''):
        '''
        Starts the segment download and set the timestamp of start segment download

        :param url: segment url
        :param byterange: segment byterange (logical segmentation of video level)
        '''
        debug(DEBUG + 1, '%s startDownload %s (byterange %s)', self, url,
              byterange)
        # start download
        if self.use_persistent_connection:
            # start a new connection
            if not self.connection:
                self._initConnection(url)
                return
            if not self.connection.client:
                return
            _, _, path = parse_url(url)
            self.connection.makeRequest(path, byterange)
        else:
            if byterange == '':
                d = getPage(url, agent=USER_AGENT)
            else:
                d = getPage(url,
                            agent=USER_AGENT,
                            headers=dict(range='bytes=' + byterange))
            d.deferred.addCallback(self.playNextGotRequest, d)
            d.deferred.addErrback(self.playNextGotError, d)
        self.start_segment_request = time.time()
示例#16
0
    def startDownload(self, url, byterange=''):
        '''
        Starts the segment download and set the timestamp of start segment download

        :param url: segment url
        :param byterange: segment byterange (logical segmentation of video level)
        '''
        debug(DEBUG+1, '%s startDownload %s (byterange %s)', self, url, byterange)
        # start download
        if self.use_persistent_connection:
            # start a new connection
            if not self.connection:
                self._initConnection(url)
                return
            if not self.connection.client:
                return
            _, _, path = parse_url(url)
            self.connection.makeRequest(path, byterange)
        else:
            if byterange == '':
                d = getPage(url, agent=USER_AGENT)
            else:
                d = getPage(url, agent=USER_AGENT, headers=dict(range='bytes='+byterange))
            d.deferred.addCallback(self.playNextGotRequest, d)
            d.deferred.addErrback(self.playNextGotError, d)
        self.start_segment_request = time.time()
    def updateLevelSegmentsList(self, level):
        '''Updater playlist for current level'''
        playlist = self.playlists[level]
        playlist = self.deletePlaylist(playlist)    #Only for VOD and Live. Not for Live+REC 
        c = defer.Deferred()
        debug(DEBUG-1, '%s updateLevelSegmentsList: %s', self, playlist['url'])
        # page callback
        def got_playlist(data, factory):
            debug(DEBUG+1, 'updateLevelSegmentsList: %s', data)
            cur_index = start_index = 0
	    segment_duration=4
            # FIXME for live streams
            #cur_index = playlist.get('end_index', -1) + 1
            for line in data.split('\n'):
                line = line.strip()
                if not line:
                    continue
                if line.startswith('#EXT-X-TARGETDURATION:'):
                    self.fragment_duration = 4
                    #setIdleDuration(fragment_duration)
                elif line.startswith('#EXTINF:'):
                    line = line.replace('#EXTINF:', '')
                    segment_duration = 4
                elif line.startswith('#EXT-X-MEDIA-SEQUENCE:'):
                    line = line.replace('#EXT-X-MEDIA-SEQUENCE:', '')
                    cur_index = start_index = 1
                elif not line.startswith('#'):
                    try:
                        index = hasGetIndex(line)
                    except Exception:
                        index = cur_index
                        cur_index += 1
                    # first segments, set start_time
                    if len(playlist['segments']) == 0:
                        playlist['start_index'] = index
                        self.start_time = max(self.start_time, index*self.fragment_duration)
                        #playlist['duration'] = self.start_time
                    if index > playlist['end_index']:
                        if not line.startswith('http'):
                            line = os.path.join(os.path.dirname(factory.url), line)
                        _c = dict(url=line,byterange='',dur=segment_duration)
                        playlist['segments'][index] = _c
                        playlist['end_index'] = index
                        playlist['duration'] += segment_duration
                elif line.startswith('#EXT-X-ENDLIST'):
                    duration = playlist['duration']
                    playlist['is_live'] = True
            #print pformat(playlist)
            self.playlists[level] = playlist
            c.callback(1)
        # error handling
        def got_error(e, factory):
            debug(0, '%s updateLevelSegmentsList url: %s error: %s', self, factory.url, e)
            reactor.callLater(self.fragment_duration*0.5, 
                self.updateLevelSegmentsList, level)
        d = getPage(playlist['url'], agent=USER_AGENT)
        d.deferred.addCallback(got_playlist, d)
        d.deferred.addErrback(got_error, d)
        return c
示例#18
0
 def on_data_received(self, connection, data, level):
     debug(DEBUG+1, '%s on_data_received: %s', self, format_bytes(len(data)))
     self.fd[level] = StringIO.StringIO(data)
     #print "level", level
     self.playlists[level]["header_data"]=data
     self.parse_atom(0,len(data)-1, level)
     self.deferredList[level].callback(1)
     self.connection_list[level].stop()
示例#19
0
 def init_connection(self, url, byterange, level):
     if self.connection_list[level]:
         self.connection_list[level].stop()
     debug(DEBUG+1, '%s init_connection: %s', self, url)
     self.connection_list[level] = ClientFactory(url)
     self.connection_list[level].connect('connection-made', self.on_connection_made, url, byterange, level)
     self.connection_list[level].connect('connection-lost', self.on_connection_lost)
     self.connection_list[level].connect('data-received', self.on_data_received, level)
示例#20
0
 def stop(self):
     '''
     Stops the media engine.
     '''
     if not self.is_runnning:
         return
     debug(DEBUG, '%s stop', self)
     self.is_runnning = False
 def start(self):
     '''
     Starts the media engine.
     '''
     if self.is_runnning:
         return
     debug(DEBUG, '%s start', self)
     self.is_runnning = True
示例#22
0
 def _onConnectionMade(self, connection, host):
     '''
     Does something when connection with host is established (only with persistent connection).
     '''
     debug(DEBUG+1, '%s _onConnectionMade: %s', self, host)
     if self.logger:
         self.logger.log_comment('Host: %s' %host)
     reactor.callLater(0.1, self.fetchNextSegment)
示例#23
0
 def _onConnectionMade(self, connection, host):
     '''
     Does something when connection with host is established (only with persistent connection).
     '''
     debug(DEBUG + 1, '%s _onConnectionMade: %s', self, host)
     if self.logger:
         self.logger.log_comment('Host: %s' % host)
     reactor.callLater(0.1, self.fetchNextSegment)
示例#24
0
 def pushData(self, data, fragment_duration, level, caps_data):
     buf = gst.Buffer(data)
     buf.duration = long(fragment_duration * 1e9)
     debug(DEBUG,
           '%s pushData: pushed %s of data (duration= %.2fs) for level %s',
           self, format_bytes(len(data)), fragment_duration, level)
     self.pipeline.get_by_name('src').emit('push-buffer', buf)
     del buf
 def stop(self):
     '''
     Stops the media engine.
     '''
     if not self.is_runnning:
         return
     debug(DEBUG, '%s stop', self)
     self.is_runnning = False
示例#26
0
 def init_connection(self, url, byterange, level):
     if self.connection_list[level]:
         self.connection_list[level].stop()
     debug(DEBUG+1, '%s init_connection: %s', self, url)
     self.connection_list[level] = ClientFactory(url)
     self.connection_list[level].connect('connection-made', self.on_connection_made, url, byterange, level)
     self.connection_list[level].connect('connection-lost', self.on_connection_lost)
     self.connection_list[level].connect('data-received', self.on_data_received, level)
示例#27
0
 def on_data_received(self, connection, data, level):
     debug(DEBUG+1, '%s on_data_received: %s', self, format_bytes(len(data)))
     self.fd[level] = StringIO.StringIO(data)
     #print "level", level
     self.playlists[level]["header_data"]=data
     self.parse_atom(0,len(data)-1, level)
     self.deferredList[level].callback(1)
     self.connection_list[level].stop()
示例#28
0
 def start(self):
     '''
     Starts the media engine.
     '''
     if self.is_runnning:
         return
     debug(DEBUG, '%s start', self)
     self.is_runnning = True
示例#29
0
 def fetchNextSegment(self):
     '''
     Schedules the download of the next segment at current level
     '''
     playlist = self.parser.playlists[self.getCurrentLevel()]
     debug(DEBUG + 1, '%s fetchNextSegment level: %d cur_index: %d', self,
           self.getCurrentLevel(), self.getCurrentSegmentIndex())
     #
     if self.getCurrentSegmentIndex() < playlist['start_index']:
         self.setCurrentSegmentIndex(playlist['start_index'])
     if self.getCurrentSegmentIndex() > playlist['end_index']:
         # else live video (ONLY HLS!!)
         if playlist['is_live'] and self.parser.getPlaylistType() == 'HLS':
             debug(DEBUG, '%s fetchNextSegment cur_index %d', self,
                   self.getCurrentSegmentIndex())
             self.parser.updateLevelSegmentsList(
                 self.getCurrentLevel()).addCallback(
                     self._updatePlaylistDone)
         # if video is vod
         else:
             debug(DEBUG, '%s fetchNextSegment last index', self)
             self.terminated = True
             #process = subprocess.Popen(os.getpid())
             #process.send_signal(signal.SIGINT)
             #sys.exit()
         return
     cur_index = self.getCurrentSegmentIndex()
     levels = self.parser.getLevels()
     url_segment = playlist['segments'][cur_index]['url']
     byterange = playlist['segments'][cur_index]['byterange']
     if byterange != '':
         debug(
             DEBUG,
             '%s fetchNextSegment level: %d (%s/s) %d/%d : %s (byterange=%s)',
             self, self.getCurrentLevel(),
             format_bytes(float(levels[self.getCurrentLevel()]['rate'])),
             self.getCurrentSegmentIndex(), playlist['end_index'],
             url_segment, byterange)
     else:
         debug(DEBUG, '%s fetchNextSegment level: %d (%s/s) %d/%d : %s',
               self, self.getCurrentLevel(),
               format_bytes(float(levels[self.getCurrentLevel()]['rate'])),
               self.getCurrentSegmentIndex(), playlist['end_index'],
               url_segment)
     if self.controller.feedback['queued_time'] < self.controller.feedback[
             'max_buffer_time']:
         idle_duration = 0.0  #fetch segment after the last segment download is completed
     else:
         idle_duration = max(
             0.0, self.controller.feedback['queued_time'] -
             self.controller.feedback['max_buffer_time'] -
             self.controller.feedback['last_download_time'])
     # if bandwidth is varried per segment set new bandwidth
     if self.mu is not None and self.sigma is not None:
         self.setNewBandwidth()
     # load the next segment
     reactor.callLater(idle_duration, self.startDownload, url_segment,
                       cur_index, byterange)
示例#30
0
 def updateLevelSegmentsList(self, level):
     '''Updater playlist for current level'''
     playlist = self.playlists[level]
     playlist = self.deletePlaylist(playlist)    #Only for VOD and Live. Not for Live+REC 
     c = defer.Deferred()
     debug(DEBUG-1, '%s updateLevelSegmentsList: %s', self, playlist['url'])
     # page callback
     def got_playlist(data, factory):
         debug(DEBUG+1, 'updateLevelSegmentsList: %s', data)
         cur_index = start_index = 0
         # FIXME for live streams
         #cur_index = playlist.get('end_index', -1) + 1
         for line in data.split('\n'):
             line = line.strip()
             if not line:
                 continue
             if line.startswith('#EXT-X-TARGETDURATION:'):
                 self.fragment_duration = float(line.replace('#EXT-X-TARGETDURATION:', ''))
                 #setIdleDuration(fragment_duration)
             elif line.startswith('#EXTINF:'):
                 line = line.replace('#EXTINF:', '')
                 segment_duration = float(line.split(',')[0])
             elif line.startswith('#EXT-X-MEDIA-SEQUENCE:'):
                 line = line.replace('#EXT-X-MEDIA-SEQUENCE:', '')
                 cur_index = start_index = int(line)
             elif not line.startswith('#'):
                 try:
                     index = hasGetIndex(line)
                 except Exception:
                     index = cur_index
                     cur_index += 1
                 # first segments, set start_time
                 if len(playlist['segments']) == 0:
                     playlist['start_index'] = index
                     self.start_time = max(self.start_time, index*self.fragment_duration)
                     #playlist['duration'] = self.start_time
                 if index > playlist['end_index']:
                     if not line.startswith('http'):
                         line = os.path.join(os.path.dirname(factory.url), line)
                     _c = dict(url=line,byterange='',dur=segment_duration)
                     playlist['segments'][index] = _c
                     playlist['end_index'] = index
                     playlist['duration'] += segment_duration
             elif line.startswith('#EXT-X-ENDLIST'):
                 duration = playlist['duration']
                 playlist['is_live'] = True
         #print pformat(playlist)
         self.playlists[level] = playlist
         c.callback(1)
     # error handling
     def got_error(e, factory):
         debug(0, '%s updateLevelSegmentsList url: %s error: %s', self, factory.url, e)
         reactor.callLater(self.fragment_duration*0.5, 
             self.updateLevelSegmentsList, level)
     d = getPage(playlist['url'], agent=USER_AGENT)
     d.deferred.addCallback(got_playlist, d)
     d.deferred.addErrback(got_error, d)
     return c
示例#31
0
 def _on_done(res):
     playlists = self.parser.getPlaylists()
     levels = self.parser.getLevels()
     fragment_duration = self.parser.getFragmentDuration()
     caps = self.parser._getCapsDemuxer()
     self.controller.setIdleDuration(
         fragment_duration
     )  #Default pause interval when isBuffering return False
     if self.getCurrentLevel() > self.getMaxLevel(
     ) or self.getCurrentLevel() == -1:
         self.setCurrentLevel(self.getMaxLevel())
     #opts for Logger
     opts = [
         ('enqueued_b', int, ''),  #2
         ('enqueued_t', float, 'visible=1,subplot=2'),  #3
         ('bwe', float, 'visible=1,subplot=1'),  #4
         ('cur', int, 'visible=1,subplot=1'),  #5
         ('level', int, 'visible=1,subplot=3'),  #6
         ('max_level', int, ''),  #7
         ('player_status', int, 'visible=1,subplot=3'),  #8
         ('paused_time', float, ''),  #9
         ('downloaded_bytes', int, ''),  #10
         ('cpu', float, 'visible=1,subplot=4'),  #11
         ('mem', float, 'visible=1,subplot=5'),  #12
         ('rss', float, ''),  #13
         ('vms', float, ''),  #14
         ('ts_start_req', float, ''),  #15
         ('ts_stop_req', float, ''),  #16
     ]
     for i in range(0, len(levels)):
         opts.append(('q%d' % i, int, 'visible=0'))
     if self.log_sub_dir:
         self.log_dir = self.log_dir + '/' + self.log_sub_dir
         #Create Logger
         self.logger = Logger(opts,
                              log_period=self.log_period,
                              log_prefix=self.log_prefix,
                              comment=self.log_comment,
                              log_dir=self.log_dir)
         debug(DEBUG + 1, 'levels: %s', levels)
         debug(DEBUG + 1, 'playlists: %s', playlists)
     if self.enable_stress_test:
         self.inactive_cycle = 0
     if self.check_warning_buffering:
         self.rate_calc.start()
         self.rate_calc.connect('update', self.checkBuffering)
     #Init media_engine
     self.media_engine.setVideoContainer(
         self.parser.getVideoContainer())
     self.media_engine.connect('status-changed', self._onStatusChanged)
     self.media_engine.start()
     #start logger
     reactor.callLater(self.log_period, self.log)
     #
     print colored("[play()] I call fetchNextSegment() [1]", 'red')
     self.fetchNextSegment()
     print colored("[play()] I called fetchNextSegment() [2]", 'red')
示例#32
0
 def pushData(self, data, fragment_duration, level, caps_data):
     buf = gst.Buffer(data)
     buf.duration = long(fragment_duration*1e9)
     debug(DEBUG, '%s pushData: pushed %s of data (duration= %ds) for level %s', self, 
         format_bytes(len(data)),
         fragment_duration,
         level)
     self.pipeline.get_by_name('src').emit('push-buffer', buf)
     del buf
示例#33
0
 def calcControlAction(self):    
     T = self.feedback['last_download_time']
     cur = self.feedback['cur_rate']
     tau = self.feedback['fragment_duration']
     x = cur * tau / T
     y = self.__ewma_filter(x) 
     self.setIdleDuration(tau-T)
     debug(DEBUG, "%s calcControlAction: y: %s/s x: %s/s T: %.2f", self, 
         format_bytes(y), format_bytes(x), T)
     return y
    def setIdleDuration(self, idle):
        '''
        Sets idle duration when in steady state

        :param idle: seconds of idle between two consecutive downloads.
        '''
        if idle < 0:
            idle = 0
        debug(DEBUG, '%s setting Idle duration: %.2f', self, idle)
        self.idle_duration = idle
示例#35
0
 def calcControlAction(self):    
     T = self.feedback['last_download_time']
     cur = self.feedback['cur_rate']
     tau = self.feedback['fragment_duration']
     x = cur * tau / T
     y = self.__ewma_filter(x) 
     self.setIdleDuration(tau-T)
     debug(DEBUG, "%s calcControlAction: y: %s/s x: %s/s T: %.2f", self, 
         format_bytes(y), format_bytes(x), T)
     return y
示例#36
0
    def setIdleDuration(self, idle):
        '''
        Sets idle duration when in steady state

        :param idle: seconds of idle between two consecutive downloads.
        '''
        if idle < 0:
            idle = 0
        debug(DEBUG, '%s setting Idle duration: %.2f', self, idle)
        self.idle_duration = idle
示例#37
0
 def startDownload(self, url, byterange, level):
     # start download
     debug(DEBUG+1, '%s startDownload %s %s', self, url, byterange)
     # start a new connection
     if not self.connection_list[level]:
         self.init_connection(url, byterange, level)
         return
     if not self.connection_list[level].client:
         return
     _, _, path = parse_url(url)
     self.connection_list[level].makeRequest(path, byterange)
示例#38
0
    def playNextGotError(self, error, factory):
        '''
        Handles error when download a segment without persistent connection

        :param error: the occurred error
        :param factory: the twisted factory (used without persistent connection)
        '''
        debug(0, '%s playNextGotError url: %s error: %s', self, factory.url, error)
        # update playlist
        if self.parser.getPlaylistType()=='HLS':
            self.parser.updateLevelSegmentsList(self.cur_level).addCallback(self._updatePlaylistDone)
示例#39
0
 def _onConnectionLost(self, connection):
     '''
     Does something when connection with host is lost (only with persistent connection).
     '''
     self.connection = None
     if self.parser.getPlaylistType()=='HLS':
         debug(0, '%s _onConnectionLost', self)
         self.parser.updateLevelSegmentsList(self.cur_level).addCallback(self._updatePlaylistDone)
     else:   #only for youtube (for check buffering)
         debug(DEBUG, '%s _onConnectionLost', self)
         self.fetchNextSegment()
示例#40
0
 def _updatePlaylistDone(self, data):
     '''
     Called when the playlist for the current level is update
     '''
     playlist = self.parser.playlists[self.getCurrentLevel()]
     debug(DEBUG+1, '%s playlist: %s', self, pformat(playlist))
     # start play if playlist has more than 2 fragments
     if len(playlist['segments']) > 2 and self.getCurrentSegmentIndex() < playlist['end_index']:
         self.fetchNextSegment()
     else:
         reactor.callLater(self.parser.getFragmentDuration(), self.fetchNextSegment)
示例#41
0
 def startDownload(self, url, byterange, level):
     # start download
     debug(DEBUG+1, '%s startDownload %s %s', self, url, byterange)
     # start a new connection
     if not self.connection_list[level]:
         self.init_connection(url, byterange, level)
         return
     if not self.connection_list[level].client:
         return
     _, _, path = parse_url(url)
     self.connection_list[level].makeRequest(path, byterange)
示例#42
0
    def playNextGotError(self, error, factory):
        '''
        Handles error when download a segment without persistent connection

        :param error: the occurred error
        :param factory: the twisted factory (used without persistent connection)
        '''
        debug(0, '%s playNextGotError url: %s error: %s', self, factory.url, error)
        # update playlist
        if self.parser.getPlaylistType()=='HLS':
            self.parser.updateLevelSegmentsList(self.cur_level).addCallback(self._updatePlaylistDone)
示例#43
0
 def _onConnectionLost(self, connection):
     '''
     Does something when connection with host is lost (only with persistent connection).
     '''
     self.connection = None
     if self.parser.getPlaylistType() == 'HLS':
         debug(0, '%s _onConnectionLost', self)
         self.parser.updateLevelSegmentsList(self.cur_level).addCallback(
             self._updatePlaylistDone)
     else:  #only for youtube (for check buffering)
         debug(DEBUG, '%s _onConnectionLost', self)
         self.fetchNextSegment()
示例#44
0
    def setLevel(self, rate):
        '''
        Sets the level corresponding to the rate specified in B/s

        :param rate: rate in B/s that determines the level. The level is the one whose rate is the highest below ``rate``.
        '''
        new_level = self.controller.quantizeRate(rate)
        if new_level != self.getCurrentLevel():
            debug(DEBUG, "%s setLevel: level: %d", self, new_level)
            self.setCurrentLevel(new_level)
            #self.onLevelChanged()
        return new_level
示例#45
0
 def _initConnection(self, url):
     '''
     Initializes connection with url (only with persistent connection)
     '''
     if self.connection:
         self.connection.stop()
     debug(DEBUG + 1, '%s _initConnection: %s', self, url)
     self.connection = ClientFactory(url)
     self.connection.connect('connection-made', self._onConnectionMade)
     self.connection.connect('connection-lost', self._onConnectionLost)
     self.connection.connect('data-received', self._onDataReceived)
     self.connection.connect('data-receiving', self._onDataReceiving)
示例#46
0
    def setLevel(self, rate):
        '''
        Sets the level corresponding to the rate specified in B/s

        :param rate: rate in B/s that determines the level. The level is the one whose rate is the highest below ``rate``.
        '''
        new_level = self.controller.quantizeRate(rate)
        if new_level != self.getCurrentLevel():
            debug(DEBUG, "%s setLevel: level: %d", self, new_level)
            self.setCurrentLevel(new_level)
            #self.onLevelChanged()
        return new_level
示例#47
0
 def _initConnection(self, url):
     '''
     Initializes connection with url (only with persistent connection)
     '''
     if self.connection:
         self.connection.stop()
     debug(DEBUG+1, '%s _initConnection: %s', self, url)
     self.connection = ClientFactory(url)
     self.connection.connect('connection-made', self._onConnectionMade)
     self.connection.connect('connection-lost', self._onConnectionLost)
     self.connection.connect('data-received', self._onDataReceived)
     self.connection.connect('data-receiving', self._onDataReceiving)
        def got_page(data, factory):
            debug(DEBUG, '%s loadHlsPlaylist from %s:\n%s', self, factory.url, data)
            cur = None
            for line in data.split('\n'):
                line = line.strip()
                line = line.replace(", ",",");
                #print line
                if line.startswith('#EXT-X-STREAM-INF:'):
                    line = line.replace('#EXT-X-STREAM-INF:', '')
                    vr = None
                    res = None
                    for field in line.split(','):
                        if field.startswith('BANDWIDTH='):
                            field = field.replace('BANDWIDTH=', '')
                            vr = int(field)  #in B/s
                        elif field.startswith('RESOLUTION='):
                            field = field.replace('RESOLUTION=', '')
                            res = field
		    width=(res.split("x")[0])
		    print "width="+str(width)	
		    height=(res.split("x")[1])
		    print "height="+str(height)
		    vr=float(vr/1000)
		    vr=float(vr)/float(float(height)*float(width))
                    self.levels.append(dict(rate=vr,resolution=res))
		    print(self.levels)
                    cur = dict(url='', 
                        is_live=True,
                        segments=[], 
                        start_index=-1, end_index=-1, 
                        duration=0.0)
                    continue
                elif cur:
                    if not line.startswith('http'):
                        line = os.path.join(os.path.dirname(factory.url), line)
                    cur['url'] = line
                    self.playlists.append(cur)
                    cur = None
            #if self.cur_level >= len(self.playlists):
            #    self.cur_level = max(self.cur_level, len(self.playlists)-1)
            deferredList = []
	    for i in range(len(self.levels)):
		print "unsorted "+str(self.levels[i])
	    
	    for i in range(len(self.levels)):
		print "sorted "+str(self.levels[i])
                deferredList.append(self.updateLevelSegmentsList(i))
            dl = defer.DeferredList(deferredList)
	    
            def _on_done(res):
                self.deferred.callback(True)    
            dl.addCallback(_on_done)
示例#49
0
 def _updatePlaylistDone(self, data):
     '''
     Called when the playlist for the current level is update
     '''
     playlist = self.parser.playlists[self.getCurrentLevel()]
     debug(DEBUG + 1, '%s playlist: %s', self, pformat(playlist))
     # start play if playlist has more than 2 fragments
     if len(playlist['segments']) > 2 and self.getCurrentSegmentIndex(
     ) < playlist['end_index']:
         self.fetchNextSegment()
     else:
         reactor.callLater(self.parser.getFragmentDuration(),
                           self.fetchNextSegment)
示例#50
0
    def _updatePlaylistDone(self, data):
        '''
        Called when the playlist for the current level is update
        '''
        playlist = self.parser.playlists[self.getCurrentLevel()]
        debug(DEBUG+1, '%s playlist: %s', self, pformat(playlist))
        # start play if playlist has more than 2 fragments
        if len(playlist['segments']) > 2 and self.getCurrentSegmentIndex() < playlist['end_index']:
	    print colored("[_updatePlaylistDone] I call fetchNextSegment() from if [1]",'red');	
            self.fetchNextSegment('')
        else:
	    print colored("[_updatePlaylistDone] I call fetchNextSegment() from if [1]",'red');	
            reactor.callLater(self.parser.getFragmentDuration(), self.fetchNextSegment,calledWithPort='')
示例#51
0
 def onRunning(self):
     if self.getQueuedTime(
     ) >= self.min_queue_time and self.status == self.PAUSED:
         self.pipeline.set_state(gst.STATE_PLAYING)
         self.status = self.PLAYING
         debug(DEBUG, '%s running', self)
         self.emit('status-changed')
     elif self.getQueuedTime() == 0 and self.status == self.PLAYING:
         self.pipeline.set_state(gst.STATE_PAUSED)
         self.status = self.PAUSED
         debug(DEBUG, '%s underrun', self)
         self.emit('status-changed')
     reactor.callLater(0.1, self.onRunning)
示例#52
0
 def _on_done(res): 
     playlists = self.parser.getPlaylists()
     levels = self.parser.getLevels()
     fragment_duration = self.parser.getFragmentDuration()
     caps = self.parser._getCapsDemuxer()
     self.controller.setIdleDuration(fragment_duration)  #Default pause interval when isBuffering return False
     if self.getCurrentLevel() > self.getMaxLevel() or self.getCurrentLevel() == -1:
         self.setCurrentLevel(self.getMaxLevel())
     #opts for Logger
     opts = [
         ('enqueued_b', int, ''),                        #2
         ('enqueued_t', float, 'visible=1,subplot=2'),   #3
         ('bwe', float, 'visible=1,subplot=1'),          #4
         ('cur', int, 'visible=1,subplot=1'),            #5
         ('level', int, 'visible=1,subplot=3'),          #6
         ('max_level', int, ''),                         #7
         ('player_status', int, 'visible=1,subplot=3'),  #8
         ('paused_time', float, ''),                     #9
         ('downloaded_bytes', int, ''),                  #10
         ('cpu', float, 'visible=1,subplot=4'),          #11
         ('mem', float, 'visible=1,subplot=5'),          #12
         ('rss', float, ''),                             #13
         ('vms', float, ''),                             #14
         ('ts_start_req', float, ''),                    #15
         ('ts_stop_req', float, ''),                     #16
     ]
     for i in range(0,len(levels)):
         opts.append(('q%d' %i, int, 'visible=0'))
     if self.log_sub_dir:     
         self.log_dir = self.log_dir + '/'+ self.log_sub_dir
         #Create Logger
         self.logger = Logger(opts, log_period=self.log_period, 
             log_prefix=self.log_prefix, comment=self.log_comment, 
             log_dir=self.log_dir)
         debug(DEBUG+1, 'levels: %s', levels)
         debug(DEBUG+1, 'playlists: %s', playlists)
     if self.enable_stress_test:
         self.inactive_cycle = 0
     if self.check_warning_buffering:
         self.rate_calc.start()
         self.rate_calc.connect('update', self.checkBuffering)
     #Init media_engine
     self.media_engine.setVideoContainer(self.parser.getVideoContainer())
     self.media_engine.connect('status-changed', self._onStatusChanged)
     self.media_engine.start()
     #start logger
     reactor.callLater(self.log_period, self.log)
     #
     self.fetchNextSegment()
示例#53
0
 def got_playlist(data, factory):
     debug(DEBUG+1, 'updateLevelSegmentsList: %s', data)
     cur_index = start_index = 0
     # FIXME for live streams
     #cur_index = playlist.get('end_index', -1) + 1
     for line in data.split('\n'):
         line = line.strip()
         if not line:
             continue
         if line.startswith('#EXT-X-TARGETDURATION:'):
             self.fragment_duration = float(line.replace('#EXT-X-TARGETDURATION:', ''))
             #setIdleDuration(fragment_duration)
         elif line.startswith('#EXTINF:'):
             line = line.replace('#EXTINF:', '')
             segment_duration = float(line.split(',')[0])
         elif line.startswith('#EXT-X-MEDIA-SEQUENCE:'):
             line = line.replace('#EXT-X-MEDIA-SEQUENCE:', '')
             cur_index = start_index = int(line)
         elif not line.startswith('#'):
             try:
                 index = hasGetIndex(line)
             except Exception:
                 index = cur_index
                 cur_index += 1
             # first segments, set start_time
             if len(playlist['segments']) == 0:
                 playlist['start_index'] = index
                 self.start_time = max(self.start_time, index*self.fragment_duration)
                 #playlist['duration'] = self.start_time
             if index > playlist['end_index']:
                 if not line.startswith('http'):
                     line = os.path.join(os.path.dirname(factory.url), line)
                 _c = dict(url=line,byterange='',dur=segment_duration)
                 playlist['segments'][index] = _c
                 playlist['end_index'] = index
                 playlist['duration'] += segment_duration
         elif line.startswith('#EXT-X-ENDLIST'):
             duration = playlist['duration']
             playlist['is_live'] = True
     #print pformat(playlist)
     self.playlists[level] = playlist
     c.callback(1)
示例#54
0
 def quantizeRate(self,rate):
     video_rates = self.feedback['rates']
     cur = self.feedback['cur_rate'] 
     level = self.feedback['level']
     D_up = self.eps*rate
     D_down = 0
     
     r_up = self.__levelLessThanRate(rate - D_up)
     r_down = self.__levelLessThanRate(rate - D_down)
     new_level = 0
     if level < r_up:
         new_level = r_up
     elif r_up <= level and level <= r_down:
         new_level = level
     else:
         new_level = r_down
     debug(DEBUG, "%s quantizeRate: rate: %s/s cur: %s/s D_up: %s/s D_down: %s/s r_up: %d r_down: %d new_level: %d", self, 
         format_bytes(rate), format_bytes(cur), format_bytes(D_up), format_bytes(D_down), r_up, r_down, new_level)
     debug(DEBUG, "%s quantizeRate: rates: %s", self, video_rates)
     return new_level
示例#55
0
    def start(self):
        BaseMediaEngine.start(self)
        #
        q = 0 #int(self.min_queue_time*1e9)   #min-threshold-time
        v_sink = 'fakesink sync=true'
        if self.getVideoContainer() == 'MP4':
            demux = self.DEMUX_MP4
            parse = self.PARSE_H264
        elif self.getVideoContainer() == 'MPEGTS':
            demux = self.DEMUX_MPEGTS
            parse = self.PARSE_H264
        elif self.getVideoContainer() == 'WEBM':
            demux = self.DEMUX_WEBM
            parse = self.PARSE_WEBM
        else:
            debug(0, '%s Cannot play: video/%s', self, self.getVideoContainer())
            return
        debug(DEBUG, '%s Playing type: video/%s', self, self.getVideoContainer())

        if self.decode_video:
            if not self.getVideoContainer() == 'WEBM':
                v_sink = self.DEC_VIDEO_H264
            else:
                v_sink = self.DEC_VIDEO_VP8
            desc = self.PIPELINE %(demux) + self.VIDEO_DEC %(parse, q, v_sink)
        else:
            desc = self.PIPELINE %(demux) + self.VIDEO_NODEC %(q, v_sink)
        debug(DEBUG, '%s pipeline: %s', self, desc)
        self.pipeline = gst.parse_launch(desc)
        self.queue = self.pipeline.get_by_name('queue_v')
        self.status = self.PAUSED
        self.pipeline.set_state(gst.STATE_PAUSED)
        self.onRunning()
示例#56
0
 def got_page(data, factory):
     debug(DEBUG, '%s loadHlsPlaylist from %s:\n%s', self, factory.url, data)
     cur = None
     for line in data.split('\n'):
         line = line.strip()
         line = line.replace(", ",",");
         #print line
         if line.startswith('#EXT-X-STREAM-INF:'):
             line = line.replace('#EXT-X-STREAM-INF:', '')
             vr = None
             res = None
             for field in line.split(','):
                 if field.startswith('BANDWIDTH='):
                     field = field.replace('BANDWIDTH=', '')
                     vr = int(field)/8.  #in B/s
                 elif field.startswith('RESOLUTION='):
                     field = field.replace('RESOLUTION=', '')
                     res = field
             self.levels.append(dict(rate=vr,resolution=res))
             cur = dict(url='', 
                 is_live=True,
                 segments=[], 
                 start_index=-1, end_index=-1, 
                 duration=0.0)
             continue
         elif cur:
             if not line.startswith('http'):
                 line = os.path.join(os.path.dirname(factory.url), line)
             cur['url'] = line
             self.playlists.append(cur)
             cur = None
     #if self.cur_level >= len(self.playlists):
     #    self.cur_level = max(self.cur_level, len(self.playlists)-1)
     deferredList = []
     for i in range(len(self.playlists)):
         deferredList.append(self.updateLevelSegmentsList(i))
     dl = defer.DeferredList(deferredList)
     def _on_done(res):
         self.deferred.callback(True)    
     dl.addCallback(_on_done)
示例#57
0
 def fetchNextSegment(self): 
     '''
     Schedules the download of the next segment at current level
     '''
     playlist = self.parser.playlists[self.getCurrentLevel()]
     debug(DEBUG+1, '%s fetchNextSegment level: %d cur_index: %d', self, self.getCurrentLevel(), self.getCurrentSegmentIndex())
     #
     if self.getCurrentSegmentIndex() < playlist['start_index']:
         self.setCurrentSegmentIndex(playlist['start_index'])
     if self.getCurrentSegmentIndex() > playlist['end_index']:
         # else live video (ONLY HLS!!)
         if playlist['is_live'] and self.parser.getPlaylistType() == 'HLS':
             debug(DEBUG, '%s fetchNextSegment cur_index %d', self, self.getCurrentSegmentIndex())
             self.parser.updateLevelSegmentsList(self.getCurrentLevel()).addCallback(self._updatePlaylistDone)
         # if video is vod
         else:
             debug(DEBUG, '%s fetchNextSegment last index', self)
         return
     cur_index=self.getCurrentSegmentIndex()
     levels = self.parser.getLevels()
     url_segment = playlist['segments'][cur_index]['url']
     byterange = playlist['segments'][cur_index]['byterange']
     if byterange != '':
         debug(DEBUG, '%s fetchNextSegment level: %d (%s/s) %d/%d : %s (byterange=%s)', self,
             self.getCurrentLevel(), 
             format_bytes(float(levels[self.getCurrentLevel()]['rate'])),
             self.getCurrentSegmentIndex(), 
             playlist['end_index'], url_segment, byterange)
     else:
         debug(DEBUG, '%s fetchNextSegment level: %d (%s/s) %d/%d : %s', self,
             self.getCurrentLevel(), 
             format_bytes(float(levels[self.getCurrentLevel()]['rate'])),
             self.getCurrentSegmentIndex(), 
             playlist['end_index'], url_segment)
     if self.controller.isBuffering():
         idle_duration = 0.0 #fetch segment after the last segment download is completed
     else:
         idle_duration = self.controller.getIdleDuration()
     # load the next segment
     reactor.callLater(idle_duration, self.startDownload, url_segment, byterange)
示例#58
0
    def calcControlAction(self):
        # call the actual adaptation algorithm
        next_level, Bdelay = self.adaptationAlgorithm()

        # debug prints
        debug(DEBUG, "%s feedback %s", self, self.feedback)
        debug(DEBUG, "%s fast start mode = %d", self, self.runningFastStart)
        debug(DEBUG, "%s next_level = %d, Bdelay = %f", self, next_level, Bdelay)

        # The algorithm returns Bdelay which represents the minimum buffer level
        # in seconds of playback when the next download must be started.
        # TAPAS wants to know how long it has to wait until the download of the
        # next segment.
        # Therefore we assume the that the buffer fill state falls below Bdelay
        # after (buffered seconds - Bdelay) seconds.
        self.setIdleDuration(0 if Bdelay == 0 else (self.feedback["queued_time"] - Bdelay))

        return self.feedback['rates'][next_level]
示例#59
0
 def got_error(e, factory):
     debug(0, '%s updateLevelSegmentsList url: %s error: %s', self, factory.url, e)
     reactor.callLater(self.fragment_duration*0.5, 
         self.updateLevelSegmentsList, level)
示例#60
0
 def got_error(e):
     debug(0, '%s loadHlsPlaylist error: %s', self, e)