== Preparing the streamload experiment == To get ready to evaluate how effective this streamloading scheme is, the experimenter implemented a simple streamload client in Python: {{{ #!python #!/usr/bin/python import sys, time, httplib2, math, thread from xml.dom.minidom import parse, parseString from optparse import OptionParser class Finished(Exception): def __init__(self, value): self.value = value def __str__(self): return repr(self.value) class Wait(Exception): def __init__(self, value): self.value = value def __str__(self): return repr(self.value) class StreamLoad: def __init__(self): def getConfig(self, baseurl, video): self.video = video resp, content = httplib2.Http().request(baseurl + video + ".xml") doc = parseString(content) for node in doc.getElementsByTagName('video'): self.buf = int(node.attributes["buffer"].value) self.chunks = int(node.attributes["chunks"].value) self.layers = int(node.attributes["layers"].value) self.urlbase = str(baseurl) + str(node.attributes["url"].value) self.chunktime = float(node.attributes["chunktime"].value) def player(self): startbuf = 0 self.played = 0 start = self.starttime while self.played= self.chunktime and self.downloaded[0]>self.played: maxlayer = -1 for i in range(self.layers): if self.downloaded[i]>=self.played+1: maxlayer = i self.played+=1 start = thistime time.sleep(0.001) def start(self, window, sl): self.sl=sl if self.sl: self.window = int(window) else: self.window = int(self.buf) self.downloaded = {} for i in range(self.layers): self.downloaded[i] = 0 self.played = 0 self.starttime = 0 self.getNextPiece() self.starttime = time.time() self.t = thread.start_new_thread(self.player,()) while True: try: self.getNextPiece() except Wait: pass def nextUp(self): # Return chunk 1, layer 0 if we haven't downloaded anything yet if self.starttime == 0: return(1,0) base_chunks_played = self.played if base_chunks_played == self.chunks: raise Finished("all done here") # Download base layer if we are allowed to if (self.downloaded[0] - base_chunks_played) < self.buf and (self.downloaded[0] + 1) <= self.chunks: return (self.downloaded[0]+1,0) else: for i in range(self.layers-1): i = i+1 tmp = max(self.downloaded[i],base_chunks_played+1) # If it's in the window and not past the end of the video, download it if tmp - base_chunks_played <= self.window and tmp + 1 <= self.chunks: return (tmp + 1,i) # After all subchunks in the quality windows are downloaded, request one chunk at a time, lower layers first for i in range(self.layers-1): i = i + 1 # If I am the highest layer and I have less than the layer beneath me, get the next chunk in my layer if self.sl and i == self.layers-1 and self.downloaded[i] <= self.downloaded[i-1] and self.downloaded[i]+1<=self.chunks: return (self.downloaded[i]+1,i) # Otherwise, if I have less than or the same as the layer above me, download the next chunk if self.sl and i < self.layers-1 and self.downloaded[i] <= self.downloaded[i+1] and self.downloaded[i]+1<=self.chunks: return (self.downloaded[i]+1,i) raise Wait("Nothing to do") def getNextPiece(self): try: (chunk, layer) = self.nextUp() except Wait: return nxt = "chunk" + str(chunk) + "_" + str(layer) + ".264" try: resp, content = httplib2.Http().request(self.urlbase + nxt) except: print "Error downloading file" if chunk > self.played or chunk==self.chunks: try: with open(nxt ,'wb') as f: f.write(content) f.close() self.lastpiecetime = time.time() except: return self.downloaded[layer] = chunk if __name__ == "__main__": parser = OptionParser() parser.add_option("-u", "--url", dest="url", help="URL of video source") parser.add_option("-v", "--video", dest="video", help="Name of video") parser.add_option("-w", "--window", dest="window", default="5", help="Download window for enhancement layers") parser.add_option("-s", "--streamload", dest = "sl", default="True", help="Download in streamload mode") (options, args) = parser.parse_args() x = StreamLoad() x.getConfig(options.url,options.video) try: if options.sl == "True": x.start(int(options.window),True) else: x.start(int(options.window),False) except Finished: sys.exit(0) }}}