def __init__(self, infohash, storage, picker, backlog, max_rate_period, numpieces, chunksize, measurefunc, snub_time, kickbans_ok, kickfunc, banfunc, scheduler = None, supporter_ips = []): self.supporter_ips = supporter_ips self.infohash = infohash self.b64_infohash = b64encode(infohash) self.storage = storage self.picker = picker self.backlog = backlog self.max_rate_period = max_rate_period self.measurefunc = measurefunc self.totalmeasure = Measure(max_rate_period*storage.piece_length/storage.request_size) self.numpieces = numpieces self.chunksize = chunksize self.snub_time = snub_time self.kickfunc = kickfunc self.banfunc = banfunc self.disconnectedseeds = {} self.downloads = [] self.perip = {} self.gotbaddata = {} self.kicked = {} self.banned = {} self.kickbans_ok = kickbans_ok self.kickbans_halted = False self.super_seeding = False self.endgamemode = False self.endgame_queued_pieces = [] self.all_requests = [] self.discarded = 0L self.download_rate = 0 # self.download_rate = 25000 # 25K/s test rate self.bytes_requested = 0 self.last_time = clock() self.queued_out = {} self.requeueing = False self.paused = False self.scheduler = scheduler # SmoothIT_ self.logger = logging.getLogger("Tribler.Downloader") # _SmoothIT # hack: we should not import this since it is not part of the # core nor should we import here, but otherwise we will get # import errors # # _event_reporter stores events that are logged somewhere... from BaseLib.Core.Statistics.StatusReporter import get_reporter_instance self._event_reporter = get_reporter_instance() # check periodicaly self.scheduler(self.dlr_periodic_check, 1) self.support_required = True
def __init__(self, downloader, connection): # 2fastbt_ SingleDownloadHelperInterface.__init__(self) # _2fastbt # SmoothIT_ self.logger = logging.getLogger("Tribler.SingleDownload") self.support_required = True # _SmoothIT self.downloader = downloader self.connection = connection self.choked = True self.interested = False self.active_requests = [] self.measure = Measure(downloader.max_rate_period) self.peermeasure = Measure(downloader.max_rate_period) self.have = Bitfield(downloader.numpieces) self.last = -1000 self.last2 = -1000 self.example_interest = None self.backlog = 2 self.ip = connection.get_ip() self.guard = BadDataGuard(self) # 2fastbt_ self.helper = downloader.picker.helper # _2fastbt # boudewijn: VOD needs a download measurement that is not # averaged over a 'long' period. downloader.max_rate_period is # (by default) 20 seconds because this matches the unchoke # policy. self.short_term_measure = Measure(5) # boudewijn: each download maintains a counter for the number # of high priority piece requests that did not get any # responce within x seconds. self.bad_performance_counter = 0 #SmoothIT_ : collect block stats self.block_stats = [] # hold statistics of received blocks, format: piece_index, block_offset, block_size, sender_ip, sender_port, sender_id
def __init__(self, connection, ratelimiter, totalup, choker, storage, picker, config, is_supporter_seed=False): #SmoothIT: supporter seed self.connection = connection self.ratelimiter = ratelimiter self.totalup = totalup self.choker = choker self.storage = storage self.picker = picker self.config = config self.max_slice_length = config['max_slice_length'] self.choked = True self.cleared = True self.interested = False self.super_seeding = False self.buffer = [] self.measure = Measure(config['max_rate_period'], config['upload_rate_fudge']) self.was_ever_interested = False if storage.get_amount_left() == 0: if choker.super_seed: self.super_seeding = True # flag, and don't send bitfield self.seed_have_list = [] # set from piecepicker self.skipped_count = 0 else: if config['breakup_seed_bitfield']: bitfield, msgs = storage.get_have_list_cloaked() connection.send_bitfield(bitfield) for have in msgs: connection.send_have(have) else: connection.send_bitfield(storage.get_have_list()) else: if storage.do_I_have_anything(): connection.send_bitfield(storage.get_have_list()) self.piecedl = None self.piecebuf = None # Merkle self.hashlist = [] # SmoothIT_ self.is_supporter_seed = is_supporter_seed print >> sys.stderr, "Uploader: am_supporter_seed=%s" % self.is_supporter_seed
def __init__(self, downloader, url): # 2fastbt_ SingleDownloadHelperInterface.__init__(self) # _2fastbt self.downloader = downloader self.baseurl = url try: (scheme, self.netloc, path, pars, query, fragment) = urlparse(url) except: self.downloader.errorfunc('cannot parse http seed address: ' + url) return if scheme != 'http': self.downloader.errorfunc('http seed url not http: ' + url) return try: self.connection = HTTPConnection(self.netloc) except: self.downloader.errorfunc('cannot connect to http seed: ' + url) return self.seedurl = path if pars: self.seedurl += ';' + pars self.seedurl += '?' if query: self.seedurl += query + '&' self.seedurl += 'info_hash=' + quote(self.downloader.infohash) self.measure = Measure(downloader.max_rate_period) self.index = None self.url = '' self.requests = [] self.request_size = 0 self.endflag = False self.error = None self.retry_period = 30 self._retry_period = None self.errorcount = 0 self.goodseed = False self.active = False self.cancelled = False self.resched(randint(2, 10))
def __init__(self,bt1download,videostatus,videoinfo,videoanalyserpath,vodeventfunc): # dirty hack to get the Tribler Session from BaseLib.Core.Session import Session session = Session.get_instance() if session.get_overlay(): # see comment in else section on importing... from BaseLib.Core.CacheDB.SqliteVideoPlaybackStatsCacheDB import VideoPlaybackDBHandler self._playback_stats = VideoPlaybackDBHandler.get_instance() else: # hack: we should not import this since it is not part of # the core nor should we import here, but otherwise we # will get import errors from BaseLib.Player.Reporter import VideoPlaybackReporter self._playback_stats = VideoPlaybackReporter.get_instance() # add an event to indicate that the user wants playback to # start def set_nat(nat): self._playback_stats.add_event(self._playback_key, "nat:%s" % nat) self._playback_key = base64.b64encode(os.urandom(20)) self._playback_stats.add_event(self._playback_key, "play-init") self._playback_stats.add_event(self._playback_key, "piece-size:%d" % videostatus.piecelen) self._playback_stats.add_event(self._playback_key, "num-pieces:%d" % videostatus.movie_numpieces) self._playback_stats.add_event(self._playback_key, "bitrate:%d" % videostatus.bitrate) self._playback_stats.add_event(self._playback_key, "nat:%s" % session.get_nat_type(callback=set_nat)) self._complete = False self.videoinfo = videoinfo self.bt1download = bt1download self.piecepicker = bt1download.picker self.rawserver = bt1download.rawserver self.storagewrapper = bt1download.storagewrapper self.fileselector = bt1download.fileselector self.vodeventfunc = vodeventfunc self.videostatus = vs = videostatus # Add quotes around path, as that's what os.popen() wants on win32 if sys.platform == "win32" and videoanalyserpath is not None and videoanalyserpath.find(' ') != -1: self.video_analyser_path='"'+videoanalyserpath+'"' else: self.video_analyser_path=videoanalyserpath # counter for the sustainable() call. Every X calls the # buffer-percentage is updated. self.sustainable_counter = sys.maxint # boudewijn: because we now update the downloadrate for each # received chunk instead of each piece we do not need to # average the measurement over a 'long' period of time. Also, # we only update the downloadrate for pieces that are in the # high priority range giving us a better estimation on how # likely the pieces will be available on time. self.overall_rate = Measure(10) self.high_range_rate = Measure(2) # boudewijn: increase the initial minimum buffer size vs.increase_high_range() # buffer: a link to the piecepicker buffer self.has = self.piecepicker.has # number of pieces in buffer self.pieces_in_buffer = 0 self.data_ready = Condition() # Arno: Call FFMPEG only if the torrent did not provide the # bitrate and video dimensions. This is becasue FFMPEG # sometimes hangs e.g. Ivaylo's Xvid Finland AVI, for unknown # reasons # Arno: 2007-01-06: Since we use VideoLan player, videodimensions not important if vs.bitrate_set: self.doing_ffmpeg_analysis = False self.doing_bitrate_est = False self.videodim = None #self.movieselector.videodim else: self.doing_ffmpeg_analysis = True self.doing_bitrate_est = True self.videodim = None self.player_opened_with_width_height = False self.ffmpeg_est_bitrate = None # number of packets required to preparse the video # I say we need 128 KB to sniff size and bitrate # Arno: 2007-01-04: Changed to 1MB. It appears ffplay works better with some # decent prebuffering. We should replace this with a timing based thing, if not self.doing_bitrate_est: prebufsecs = self.PREBUF_SEC_VOD # assumes first piece is whole (first_piecelen == piecelen) piecesneeded = vs.time_to_pieces( prebufsecs ) bytesneeded = piecesneeded * vs.piecelen else: # Arno, 2007-01-08: for very high bitrate files e.g. # 850 kilobyte/s (500 MB for 10 min 20 secs) this is too small # and we'll have packet loss because we start too soon. bytesneeded = 1024 * 1024 piecesneeded = 1 + int(ceil((bytesneeded - vs.piecelen) / float(vs.piecelen))) self.max_prebuf_packets = min(vs.movie_numpieces, piecesneeded) if self.doing_ffmpeg_analysis and DEBUG: print >>sys.stderr,"vod: trans: Want",self.max_prebuf_packets,"pieces for FFMPEG analysis, piecesize",vs.piecelen if DEBUG: print >>sys.stderr,"vod: trans: Want",self.max_prebuf_packets,"pieces for prebuffering" self.nreceived = 0 if DEBUG: print >>sys.stderr,"vod: trans: Setting MIME type to",self.videoinfo['mimetype'] self.set_mimetype(self.videoinfo['mimetype']) # some statistics self.stat_playedpieces = 0 # number of pieces played successfully self.stat_latepieces = 0 # number of pieces that arrived too late self.stat_droppedpieces = 0 # number of pieces dropped self.stat_stalltime = 0.0 # total amount of time the video was stalled self.stat_prebuffertime = 0.0 # amount of prebuffer time used self.stat_pieces = PieceStats() # information about each piece # start periodic tasks self.curpiece = "" self.curpiece_pos = 0 # The outbuf keeps only the pieces from the base layer.. We play if we # have at least a piece from the base layer! self.outbuf = [] #self.last_pop = None # time of last pop self.reset_bitrate_prediction() self.lasttime=0 # For DownloadState self.prebufprogress = 0.0 self.prebufstart = time.time() self.playable = False self.usernotified = False self.outbuflen = None # LIVESOURCEAUTH self.authenticator = None self.refill_rawserv_tasker() self.tick_second() # link to others (last thing to do) self.piecepicker.set_transporter( self ) #self.start() if FAKEPLAYBACK: import threading class FakeReader(threading.Thread): def __init__(self,movie): threading.Thread.__init__(self) self.movie = movie def run(self): self.movie.start() while not self.movie.done(): self.movie.read() t = FakeReader(self) t.start()
def start( self, bytepos = 0, force = False ): """ Initialise to start playing at position `bytepos'. """ self._playback_stats.add_event(self._playback_key, "play") # ARNOTODO: we don't use start(bytepos != 0) at the moment. See if we # should. Also see if we need the read numbytes here, or that it # is better handled at a higher layer. For live it is currently # done at a higher level, see VariableReadAuthStreamWrapper because # we have to strip the signature. Hence the self.curpiece buffer here # is superfluous. Get rid off it or check if # # curpiece[0:piecelen] # # returns curpiece if piecelen has length piecelen == optimize for # piecesized case. # # For VOD seeking we may use the numbytes facility to seek to byte offsets # not just piece offsets. # vs = self.videostatus if vs.playing and not force: return # lock before changing startpos or any other playing variable self.data_ready.acquire() try: # Determine piece number and offset if bytepos < vs.piecelen: piece = vs.first_piece offset = bytepos else: newbytepos = bytepos - vs.first_piecelen piece = vs.first_piece + newbytepos / vs.piecelen + 1 offset = newbytepos % vs.piecelen if DEBUG: print >>sys.stderr,"vod: trans: === START, START, START, START, START, START, START, START, START, START, START, START, START,START" print >>sys.stderr,"vod: trans: === START at offset %d (piece %d) (forced: %s) ===" % (bytepos,piece,force) # Initialise all playing variables self.curpiece = "" # piece currently being popped self.curpiece_pos = offset # TODO self.set_pos( piece ) self.outbuf = [] #self.last_pop = time.time() self.reset_bitrate_prediction() vs.playing = True self.playbackrate = Measure( 60 ) # boudewijn: decrease the initial minimum buffer size vs.decrease_high_range() finally: self.data_ready.release() # ARNOTODO: start is called by non-NetworkThreads, these following methods # are usually called by NetworkThread. # # We now know that this won't be called until notify_playable() so # perhaps this can be removed? # # CAREFUL: if we use start() for seeking... that's OK. User won't be # able to seek before he got his hands on the stream, so after # notify_playable() # See what we can do right now self.update_prebuffering() self.refill_buffer()