[svn r521] * GMyth-Streamer: trunk
authormorphbr
Tue Apr 10 01:07:35 2007 +0100 (2007-04-10)
branchtrunk
changeset 516f353f0da6f07
parent 515 18f08fa8e216
child 517 348964b09e4a
[svn r521] * GMyth-Streamer:
- Mencoder clean-up
|- Subtitle support
|- Changed os.popen for subprocess.Popen
|- Mencoder setup clean-up

- Lib update
|- Created function to list media in directories
gmyth-stream/server/lib.py
gmyth-stream/server/main.py
gmyth-stream/server/plugins/media/mencoder.py
gmyth-stream/server/stream.conf
gmyth-stream/server/tests/client.py
     1.1 --- a/gmyth-stream/server/lib.py	Mon Apr 09 23:33:35 2007 +0100
     1.2 +++ b/gmyth-stream/server/lib.py	Tue Apr 10 01:07:35 2007 +0100
     1.3 @@ -3,6 +3,8 @@
     1.4  import os
     1.5  import stat
     1.6  
     1.7 +global ext = ['mpg', 'avi', 'mp4', 'nuv', 'mpeg', 'mov']
     1.8 +
     1.9  def now():
    1.10      return time.strftime("%Y-%m-%d %H:%M:%S");
    1.11  
    1.12 @@ -22,4 +24,13 @@
    1.13                  return path
    1.14      return ""
    1.15  
    1.16 +def list_media_files(directory, file_list):
    1.17 +    for root, dirs, files in os.walk(directory):
    1.18 +        for name in files:
    1.19 +            if os.path.splitext(name)[1].strip(".") in ext:
    1.20 +                media = os.path.join(root,name)
    1.21 +                if media not in file_list
    1.22 +                file_list.append(os.path.join(root,name))
    1.23  
    1.24 +    return True
    1.25 +
     2.1 --- a/gmyth-stream/server/main.py	Mon Apr 09 23:33:35 2007 +0100
     2.2 +++ b/gmyth-stream/server/main.py	Tue Apr 10 01:07:35 2007 +0100
     2.3 @@ -71,23 +71,35 @@
     2.4      nextport += 1
     2.5      ret = media.setup(filename, mux, vcodec, vbitrate, fps, acodec,
     2.6                        abitrate, width, height, nextport, options)
     2.7 -    if ret == True:
     2.8 +    if ret:
     2.9          server.sendOk()
    2.10      else:
    2.11          server.sendNotOk(ret)
    2.12 +
    2.13      return True
    2.14  
    2.15  def do_play(server):
    2.16 -    media.play()
    2.17 -    server.sendOk("%d" % nextport)
    2.18 +    ret = media.play()
    2.19 +    if ret:
    2.20 +        server.sendOk("%d" % nextport)
    2.21 +    else:
    2.22 +        server.sendNotOk(ret)
    2.23 +
    2.24      return True
    2.25  
    2.26 -
    2.27  def do_stop(server):
    2.28      media.stop()
    2.29      server.sendOk()
    2.30      return True
    2.31  
    2.32 +def do_list(server, *directory):
    2.33 +    file_list = []
    2.34 +    for j in directory:
    2.35 +        list_media_files(j, file_list)
    2.36 +
    2.37 +    server.sendOk()
    2.38 +    return True
    2.39 +
    2.40  def do_quit(server):
    2.41      server.finish = 1
    2.42      media.stop()
    2.43 @@ -99,6 +111,7 @@
    2.44      "SETUP": do_setup,
    2.45      "PLAY": do_play,
    2.46      "STOP": do_stop,
    2.47 +    "LIST": do_list,
    2.48      "QUIT": do_quit,
    2.49      }
    2.50  
     3.1 --- a/gmyth-stream/server/plugins/media/mencoder.py	Mon Apr 09 23:33:35 2007 +0100
     3.2 +++ b/gmyth-stream/server/plugins/media/mencoder.py	Tue Apr 10 01:07:35 2007 +0100
     3.3 @@ -2,9 +2,11 @@
     3.4  import sys
     3.5  import lib
     3.6  import time
     3.7 +import shlex
     3.8  import signal
     3.9  import socket
    3.10  import ConfigParser
    3.11 +import logging as log
    3.12  
    3.13  from select import *
    3.14  from subprocess import *
    3.15 @@ -14,28 +16,20 @@
    3.16      def __init__(self, config):
    3.17  
    3.18          self.config = config
    3.19 -        self.args = ""
    3.20 -        self.language = "en"
    3.21 +        self.path = ""
    3.22 +        self.args = []
    3.23 +        self.language = None
    3.24 +        self.subtitle = None
    3.25 +        self.mpegopts = None
    3.26          self.socket = None
    3.27          self.child_pid = None
    3.28          self.mplayer = None
    3.29          self.mencoder_pid = None
    3.30          self.mplayer_pid = None
    3.31 -        signal.signal(signal.SIGABRT, self.kill_handler)
    3.32  
    3.33      # __init__
    3.34  
    3.35 -    def kill_handler(self, sig, frame):
    3.36 -        try:
    3.37 -            os.kill(self.mplayer_pid.pid, signal.SIGKILL)
    3.38 -            log.debug("Killed Mplayer")
    3.39 -            sys.exit(0)
    3.40 -        except:
    3.41 -            log.error("Problems closing child")
    3.42 -
    3.43 -    # kill_handler
    3.44 -
    3.45 -    def set_args(self, options):
    3.46 +    def setup_opts(self, options):
    3.47  
    3.48          for opt in options:
    3.49  
    3.50 @@ -44,17 +38,27 @@
    3.51  
    3.52              elif opt.find("language=") >= 0:
    3.53                  try:
    3.54 -                    self.language = opt.split("=")[1]
    3.55 -                except:
    3.56 -                    log.error("Bad language option")
    3.57 +                    lan = opt.split("=")[1]
    3.58 +                    if len(lan) < 2:
    3.59 +                        self.language = lan
    3.60 +                except Exception, e:
    3.61 +                    log.error("Bad language option: %s" % e)
    3.62 +
    3.63 +            elif opt.find("subtitle=") >= 0:
    3.64 +                try:
    3.65 +                    sub = opt.split("=")[1]
    3.66 +                    if len(sub) < 2:
    3.67 +                        self.language = sub
    3.68 +                except Exception, e:
    3.69 +                    log.error("Bad subtitle option: %s" % e)
    3.70  
    3.71              elif opt.find("format=") >= 0:
    3.72                  try:
    3.73 -                    self.mux += " -mpegopts format=%s" % opt.split("=")[1]
    3.74 -                except:
    3.75 -                    log.error("Bad format option")
    3.76 +                    self.mpegopts = opt.split("=")[1]
    3.77 +                except Exception, e:
    3.78 +                    log.error("Bad format option: %s" % e)
    3.79  
    3.80 -    # set_args
    3.81 +    # setup_opts
    3.82  
    3.83      def run_mplayer(self):
    3.84          msg = self.filename
    3.85 @@ -67,7 +71,6 @@
    3.86  
    3.87      # run_mplayer
    3.88  
    3.89 -
    3.90      def setup_mencoder(self):
    3.91          self.path = self.config.get("Mencoder", "path")
    3.92          mp = Popen([self.path], stdout=PIPE, close_fds=True)
    3.93 @@ -81,67 +84,117 @@
    3.94          log.info("Mencoder version: %s" % version)
    3.95  
    3.96          if self.mencoder_old:
    3.97 -            self.fifo = self.config.get("Mencoder", "fifo_path")
    3.98 +            try:
    3.99 +                self.fifo = self.config.get("Mencoder", "fifo_path")
   3.100 +                os.mkfifo(self.fifo)
   3.101 +            except Exception, e:
   3.102 +                log.info("Fifo: %s" % e)
   3.103          else:
   3.104              self.fifo = "-"
   3.105  
   3.106      # setup_mencoder
   3.107  
   3.108 -    def setup_audio(self, acodec):
   3.109 +    def setup_audio(self):
   3.110  
   3.111 -        if acodec == "mp3lame":
   3.112 +        if self.acodec == "mp3lame":
   3.113              return "-oac mp3lame -lameopts cbr:br=%s vol=5" % self.abitrate
   3.114          else:
   3.115 -            return = "-oac lavc -lavcopts acodec=%s:abitrate=%s" % (\
   3.116 +            return "-oac lavc -lavcopts acodec=%s:abitrate=%s" % (\
   3.117                  self.acodec, self.abitrate)
   3.118  
   3.119 +    # setup_audio
   3.120 +
   3.121 +
   3.122 +    def setup_video(self):
   3.123 +
   3.124 +        video = ""
   3.125 +
   3.126 +        video += " -of %s" % self.mux
   3.127 +        video += " -ofps %s" % self.fps
   3.128 +
   3.129 +        if self.vcodec == "nuv" or self.vcodec == "xvid"\
   3.130 +               or self.vcodec == "qtvideo" or self.vcodec == "copy":
   3.131 +            video += " -ovc %s" % self.vcodec
   3.132 +        else:
   3.133 +            video += " -ovc lavc -lavcopts vcodec=%s:vbitrate=%s" % (
   3.134 +                self.vcodec, self.vbitrate)
   3.135 +
   3.136 +        if self.mux == "mpeg" and self.mpegopts is not None:
   3.137 +            video += " -mpegopts format=%s" % self.mpegopts
   3.138 +
   3.139 +        video += " -vf scale=%s:%s" % (self.width, self.height)
   3.140 +
   3.141 +        return video
   3.142 +
   3.143 +    # setup_video
   3.144 +
   3.145 +
   3.146 +    def arg_append(self, args, options):
   3.147 +        l = shlex.split(options)
   3.148 +        for i in l:
   3.149 +            args.append(i)
   3.150 +
   3.151 +    # arg_append
   3.152 +
   3.153 +    def setup_args(self, args):
   3.154 +
   3.155 +        args.append(self.path)
   3.156 +        args.append(self.filename)
   3.157 +
   3.158 +        if self.language != None:
   3.159 +            self.arg_append(args, "-alang %s" % self.language)
   3.160 +
   3.161 +        if self.subtitle != None:
   3.162 +            self.arg_append(args, "-slang %s" % self.subtitle)
   3.163 +            self.arg_append(args, "-subfps %s" % self.fps)
   3.164 +
   3.165 +        self.arg_append(args, "-idx")
   3.166 +        self.arg_append(args, self.audio_opts)
   3.167 +        self.arg_append(args, self.video_opts)
   3.168 +
   3.169 +        self.arg_append(args, "-really-quiet")
   3.170 +        self.arg_append(args, "-o %s" % self.fifo)
   3.171 +        self.arg_append(args, "2> %s" % os.devnull)
   3.172 +
   3.173 +    # setup_args
   3.174 +
   3.175      def setup_filename(self, filename):
   3.176          try:
   3.177              self.kind, self.filename = filename.split("://")
   3.178          except:
   3.179              return (False, "Wrong filename protocol")
   3.180  
   3.181 -        audio = setup_audio(self.acodec)
   3.182 -
   3.183          if self.kind == "file":
   3.184              if not os.path.exists(self.filename):
   3.185                  msg = "File requested does not exist. SETUP failed."
   3.186                  log.error(msg)
   3.187                  return (False, msg)
   3.188  
   3.189 -            self.args += " %s -mf fps=%s -of %s %s"\
   3.190 -                         " -ovc lavc -lavcopts vcodec=%s:vbitrate=%s -vf scale=%s:%s"\
   3.191 -                         " -really-quiet -o %s 2>/dev/null" % (
   3.192 -                self.filename, self.fps, self.mux, audio, self.vcodec,
   3.193 -                self.vbitrate, self.width, self.height, self.fifo)
   3.194 -
   3.195          elif self.kind == "dvd":
   3.196 -            self.args += " dvd://%s -alang %s -vf scale=%s:%s %s"\
   3.197 -                         " -of %s -ovc lavc -lavcopts vcodec=%s:vbitrate=%s"\
   3.198 -                         " -ofps %s -really-quiet -o %s 2>/dev/null" % (
   3.199 -                self.filename, self.language, self.width, self.height, audio,
   3.200 -                self.mux, self.vcodec, self.vbitrate, self.fps, self.fifo)
   3.201 +            self.filename = "dvd://" + filename
   3.202  
   3.203          return (True, "")
   3.204  
   3.205      # setup_filename
   3.206  
   3.207 -    def setup_socket(self, socket):
   3.208 -        if socket != None:
   3.209 -            del(socket)
   3.210 +    def setup_socket(self):
   3.211 +        if self.socket != None:
   3.212 +            del(self.socket)
   3.213  
   3.214 -        socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
   3.215 -        socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
   3.216 +        self.socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
   3.217 +        self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
   3.218  
   3.219          try:
   3.220 -            socket.bind( ('', self.port) )
   3.221 -            socket.listen(1)
   3.222 +            self.socket.bind( ('', self.port) )
   3.223 +            self.socket.listen(1)
   3.224          except Exception, e:
   3.225              log.error("Could not create socket: %s" % e)
   3.226              return (False, e)
   3.227  
   3.228          return (True, "")
   3.229  
   3.230 +    # setup_socket
   3.231 +
   3.232      '''
   3.233      MENCODER SETUP DESCRIPTION
   3.234      ===========================
   3.235 @@ -154,6 +207,12 @@
   3.236  
   3.237      '''
   3.238  
   3.239 +
   3.240 +    # good one: /tmp/dvb.mpg avi mpeg4 400 25 mp3lame 192 320 240
   3.241 +    # file:///tmp/dvb.mpg mpeg mpeg1video 400 25 mp2 192 320 240 format=mpeg1
   3.242 +    # dvd://4 mpeg mpeg1video 400 25 mp3lame 192 400 240 language=en local
   3.243 +    # file:///tmp/mpg/bad_day.mpg avi mpeg4 400 25 mp3 192 320 240
   3.244 +
   3.245      def setup(self, filename, mux, vcodec, vbitrate,\
   3.246                fps, acodec, abitrate, width, height, port, options):
   3.247  
   3.248 @@ -168,18 +227,17 @@
   3.249          self.port = int(port)
   3.250  
   3.251          self.setup_mencoder()
   3.252 +
   3.253          ret_val = self.setup_filename(filename)
   3.254 -
   3.255          if not ret_val[0]:
   3.256              return ret_val[1]
   3.257  
   3.258 -        self.set_args(options)
   3.259 +        self.setup_opts(options)
   3.260 +        self.audio_opts = self.setup_audio()
   3.261 +        self.video_opts = self.setup_video()
   3.262 +        self.setup_args(self.args)
   3.263  
   3.264 -        # good one: /tmp/dvb.mpg avi mpeg4 400 25 mp3lame 192 320 240 5000 file
   3.265 -        # /tmp/dvb.mpg mpeg mpeg1video 400 25 mp2 192 320 240 5000 format=mpeg1 file
   3.266 -        #4 mpeg mpeg1video 400 25 mp3lame 192 400 240 5000 language=en local dvd
   3.267 -        ret_val = setup_socket(self.socket)
   3.268 -
   3.269 +        ret_val = self.setup_socket()
   3.270          if not ret_val[0]:
   3.271              return ret_val[1]
   3.272  
   3.273 @@ -189,30 +247,25 @@
   3.274  
   3.275      def play(self):
   3.276  
   3.277 -        if self.mencoder_old:
   3.278 -            try:
   3.279 -                os.mkfifo(self.fifo)
   3.280 -            except:
   3.281 -                lib.log("Fifo already exists")
   3.282 +        log.info("Starting Mencoder: %s" % self.args )
   3.283  
   3.284 +        try:
   3.285 +            self.mencoder_pid = Popen(self.args, stdout=PIPE, close_fds=True)
   3.286 +        except Exception, e:
   3.287 +            msg = "Could not init Mencoder: %s" % e
   3.288 +            log.error(msg)
   3.289 +            return msg
   3.290  
   3.291 -        lib.log("Starting Mencoder: %s %s" % (self.path, self.args) )
   3.292 -        # exec Mencoder
   3.293 -        if self.mencoder_old:
   3.294 -            self.mencoder_pid = Popen(self.path + self.args, shell=True,
   3.295 -                                      close_fds=True)
   3.296 -            self.pout = open(self.fifo)
   3.297 -        else:
   3.298 -            self.path += self.args
   3.299 -            pin, self.pout = os.popen2(self.path)
   3.300 +        if self.mencoder_old: self.pout = open(self.fifo)
   3.301 +        else: self.pout = self.mencoder_pid.stdout
   3.302  
   3.303          self.child_pid = os.fork()
   3.304  
   3.305          if self.child_pid == 0:
   3.306 -            conn,addr= self.socket.accept()
   3.307 -            lib.log("Sending Data to client: %s" % addr[0])
   3.308 +            conn, addr = self.socket.accept()
   3.309 +            log.info("Sending Data to client: %s" % addr[0])
   3.310  
   3.311 -            data = self.pout.read(1024)
   3.312 +            data = self.pout.read(4096)
   3.313  
   3.314              conn.settimeout(5)
   3.315              retry = 0
   3.316 @@ -226,34 +279,43 @@
   3.317                          if back == "OK" and self.mplayer and not self.mplayer_pid:
   3.318                              self.run_mplayer()
   3.319  
   3.320 -                except socket.error:
   3.321 -                    lib.log("Socket error (maybe timeout ?)")
   3.322 +                except socket.error, e:
   3.323 +                    log.error("Socket error: %s" % e)
   3.324                      retry += 1
   3.325  
   3.326 -                data = self.pout.read(1024)
   3.327 +                data = self.pout.read(4096)
   3.328  
   3.329              if retry < 5:
   3.330 -                lib.log("Finished sending Data to client: %s" % addr[0])
   3.331 +                log.info("Finished sending Data to client: %s" % addr[0])
   3.332              else:
   3.333 -                lib.log("Client timed out")
   3.334 +                log.error("Client timed out, retried more than %s times" % retry)
   3.335  
   3.336 +            os.kill(self.mencoder_pid.pid, signal.SIGKILL)
   3.337              sys.exit(0)
   3.338  
   3.339 +        return True
   3.340 +
   3.341 +        # play
   3.342 +
   3.343  
   3.344      def stop(self):
   3.345          try:
   3.346 -            if self.mplayer_old:
   3.347 -                os.kill(self.mencoder_pid.pid + 1, signal.SIGKILL)
   3.348 -            else:
   3.349 -                self.pout.close()
   3.350 -            self.mplayer = None
   3.351 -        except:
   3.352 -            lib.log("Trying to stop before playing...")
   3.353  
   3.354 -        if self.socket != None:
   3.355 -            lib.log("Closing socket")
   3.356 -            self.socket.close()
   3.357 +            if self.mencoder_pid:
   3.358 +                os.kill(self.mencoder_pid.pid, signal.SIGKILL)
   3.359 +                self.mencoder_pid = None
   3.360  
   3.361 -            lib.log("Trying to stop Mencoder process")
   3.362 +            if self.mplayer_pid:
   3.363 +                os.kill(self.mplayer_pid.pid, signal.SIGKILL)
   3.364 +                self.mplayer_pid = None
   3.365 +
   3.366 +            if self.socket != None:
   3.367 +                self.socket.close()
   3.368 +
   3.369              if self.child_pid != None:
   3.370 -                os.kill(self.child_pid, signal.SIGABRT)
   3.371 +                os.kill(self.child_pid, signal.SIGKILL)
   3.372 +
   3.373 +        except Exception, e:
   3.374 +            log.error("Stop error: %s" % e)
   3.375 +
   3.376 +    # stop
     4.1 --- a/gmyth-stream/server/stream.conf	Mon Apr 09 23:33:35 2007 +0100
     4.2 +++ b/gmyth-stream/server/stream.conf	Tue Apr 10 01:07:35 2007 +0100
     4.3 @@ -15,9 +15,9 @@
     4.4  
     4.5  
     4.6  [FFmpeg]
     4.7 -path = /usr/bin/ffmpeg
     4.8 +path = /usr/local/bin/ffmpeg
     4.9  
    4.10  
    4.11  [Mencoder]
    4.12 -path = /usr/bin/mencoder
    4.13 +path = /usr/local/bin/mencoder
    4.14  fifo_path = /tmp/teste
     5.1 --- a/gmyth-stream/server/tests/client.py	Mon Apr 09 23:33:35 2007 +0100
     5.2 +++ b/gmyth-stream/server/tests/client.py	Tue Apr 10 01:07:35 2007 +0100
     5.3 @@ -6,10 +6,10 @@
     5.4  
     5.5  if len(sys.argv) < 2:
     5.6      HOST = 'localhost'
     5.7 -    PORT = 5000
     5.8 +    PORT = 50000
     5.9  elif len(sys.argv) == 2:
    5.10      HOST = sys.argv[1]
    5.11 -    PORT = 5000
    5.12 +    PORT = 50000
    5.13  else:
    5.14      HOST = sys.argv[1]
    5.15      PORT = int(sys.argv[2])
    5.16 @@ -25,25 +25,25 @@
    5.17  
    5.18  
    5.19  mplayer = os.popen("which mplayer").read().strip()
    5.20 -mplayer += " - 1> /dev/null"
    5.21 +mplayer += " -idx - -vo x11 1> /dev/null"
    5.22  pin, pout = os.popen2(mplayer)
    5.23  
    5.24 -#teste = open("/tmp/teste2", "w")
    5.25 +#teste = open("teste.avi", "w")
    5.26  
    5.27 -data = socket.recv(1024)
    5.28 +data = socket.recv(4096)
    5.29  i = 0
    5.30  
    5.31  while (data != ""):
    5.32      pin.write(data)
    5.33      #teste.write(data)
    5.34 -    data = socket.recv(1024)
    5.35 -    if (i == 500):
    5.36 -        socket.send("OK")
    5.37 +    data = socket.recv(4096)
    5.38 +    #if (i == 500):
    5.39 +    #    socket.send("OK")
    5.40      i += 1
    5.41  
    5.42  pin.close()
    5.43  socket.close()
    5.44 -
    5.45 +#teste.close()
    5.46  
    5.47  # from select import select
    5.48  # r, w, x = select([pout], []. [], 0)