Version 5 (modified by 11 years ago) (diff) | ,
---|
Preparing the streamload experiment
To get ready to evaluate how effective this streamloading scheme is, the experimenter implemented a simple streamload server and client. He decides that the server will host some video metadata files that contain some basic information about the video for which they are named. For example:
<video chunks="40" layers="3" chunktime="1.65" buffer="4" url="chunks/" />
He creates a set of these files with different buffer sizes (e.g. 'video2.xml' has a buffer size of 2, 'video3.xml' has a buffer size of 3, etc.)
The streamload client will request this video metadata file from the server, and then request one subchunk at a time until it has played the entire video:
#!/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.chunks: thistime = time.time() if thistime-start >= 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)