wiki:GEC16Agenda/WiMAX-Tutorial/Streamload/01

Version 5 (modified by Fraida Fund, 7 years ago) (diff)

--

Previous

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)

Next