1.1 --- a/gmyth-stream/server/plugins/media/mencoder.py Mon Apr 09 16:22:37 2007 +0100
1.2 +++ b/gmyth-stream/server/plugins/media/mencoder.py Thu Apr 12 14:58:13 2007 +0100
1.3 @@ -2,9 +2,11 @@
1.4 import sys
1.5 import lib
1.6 import time
1.7 +import shlex
1.8 import signal
1.9 import socket
1.10 import ConfigParser
1.11 +import logging as log
1.12
1.13 from select import *
1.14 from subprocess import *
1.15 @@ -14,28 +16,20 @@
1.16 def __init__(self, config):
1.17
1.18 self.config = config
1.19 - self.args = ""
1.20 - self.language = "en"
1.21 + self.path = ""
1.22 + self.args = []
1.23 + self.language = None
1.24 + self.subtitle = None
1.25 + self.mpegopts = None
1.26 self.socket = None
1.27 self.child_pid = None
1.28 self.mplayer = None
1.29 self.mencoder_pid = None
1.30 self.mplayer_pid = None
1.31 - signal.signal(signal.SIGABRT, self.kill_handler)
1.32
1.33 # __init__
1.34
1.35 - def kill_handler(self, sig, frame):
1.36 - try:
1.37 - os.kill(self.mplayer_pid.pid, signal.SIGKILL)
1.38 - log.debug("Killed Mplayer")
1.39 - sys.exit(0)
1.40 - except:
1.41 - log.error("Problems closing child")
1.42 -
1.43 - # kill_handler
1.44 -
1.45 - def set_args(self, options):
1.46 + def setup_opts(self, options):
1.47
1.48 for opt in options:
1.49
1.50 @@ -44,17 +38,27 @@
1.51
1.52 elif opt.find("language=") >= 0:
1.53 try:
1.54 - self.language = opt.split("=")[1]
1.55 - except:
1.56 - log.error("Bad language option")
1.57 + lan = opt.split("=")[1]
1.58 + if len(lan) < 2:
1.59 + self.language = lan
1.60 + except Exception, e:
1.61 + log.error("Bad language option: %s" % e)
1.62 +
1.63 + elif opt.find("subtitle=") >= 0:
1.64 + try:
1.65 + sub = opt.split("=")[1]
1.66 + if len(sub) < 2:
1.67 + self.language = sub
1.68 + except Exception, e:
1.69 + log.error("Bad subtitle option: %s" % e)
1.70
1.71 elif opt.find("format=") >= 0:
1.72 try:
1.73 - self.mux += " -mpegopts format=%s" % opt.split("=")[1]
1.74 - except:
1.75 - log.error("Bad format option")
1.76 + self.mpegopts = opt.split("=")[1]
1.77 + except Exception, e:
1.78 + log.error("Bad format option: %s" % e)
1.79
1.80 - # set_args
1.81 + # setup_opts
1.82
1.83 def run_mplayer(self):
1.84 msg = self.filename
1.85 @@ -67,7 +71,6 @@
1.86
1.87 # run_mplayer
1.88
1.89 -
1.90 def setup_mencoder(self):
1.91 self.path = self.config.get("Mencoder", "path")
1.92 mp = Popen([self.path], stdout=PIPE, close_fds=True)
1.93 @@ -81,67 +84,117 @@
1.94 log.info("Mencoder version: %s" % version)
1.95
1.96 if self.mencoder_old:
1.97 - self.fifo = self.config.get("Mencoder", "fifo_path")
1.98 + try:
1.99 + self.fifo = self.config.get("Mencoder", "fifo_path")
1.100 + os.mkfifo(self.fifo)
1.101 + except Exception, e:
1.102 + log.info("Fifo: %s" % e)
1.103 else:
1.104 self.fifo = "-"
1.105
1.106 # setup_mencoder
1.107
1.108 - def setup_audio(self, acodec):
1.109 + def setup_audio(self):
1.110
1.111 - if acodec == "mp3lame":
1.112 + if self.acodec == "mp3lame":
1.113 return "-oac mp3lame -lameopts cbr:br=%s vol=5" % self.abitrate
1.114 else:
1.115 - return = "-oac lavc -lavcopts acodec=%s:abitrate=%s" % (\
1.116 + return "-oac lavc -lavcopts acodec=%s:abitrate=%s" % (\
1.117 self.acodec, self.abitrate)
1.118
1.119 + # setup_audio
1.120 +
1.121 +
1.122 + def setup_video(self):
1.123 +
1.124 + video = ""
1.125 +
1.126 + video += " -of %s" % self.mux
1.127 + video += " -ofps %s" % self.fps
1.128 +
1.129 + if self.vcodec == "nuv" or self.vcodec == "xvid"\
1.130 + or self.vcodec == "qtvideo" or self.vcodec == "copy":
1.131 + video += " -ovc %s" % self.vcodec
1.132 + else:
1.133 + video += " -ovc lavc -lavcopts vcodec=%s:vbitrate=%s" % (
1.134 + self.vcodec, self.vbitrate)
1.135 +
1.136 + if self.mux == "mpeg" and self.mpegopts is not None:
1.137 + video += " -mpegopts format=%s" % self.mpegopts
1.138 +
1.139 + video += " -vf scale=%s:%s" % (self.width, self.height)
1.140 +
1.141 + return video
1.142 +
1.143 + # setup_video
1.144 +
1.145 +
1.146 + def arg_append(self, args, options):
1.147 + l = shlex.split(options)
1.148 + for i in l:
1.149 + args.append(i)
1.150 +
1.151 + # arg_append
1.152 +
1.153 + def setup_args(self, args):
1.154 +
1.155 + args.append(self.path)
1.156 + args.append(self.filename)
1.157 +
1.158 + if self.language != None:
1.159 + self.arg_append(args, "-alang %s" % self.language)
1.160 +
1.161 + if self.subtitle != None:
1.162 + self.arg_append(args, "-slang %s" % self.subtitle)
1.163 + self.arg_append(args, "-subfps %s" % self.fps)
1.164 +
1.165 + self.arg_append(args, "-idx")
1.166 + self.arg_append(args, self.audio_opts)
1.167 + self.arg_append(args, self.video_opts)
1.168 +
1.169 + self.arg_append(args, "-really-quiet")
1.170 + self.arg_append(args, "-o %s" % self.fifo)
1.171 + self.arg_append(args, "2> %s" % os.devnull)
1.172 +
1.173 + # setup_args
1.174 +
1.175 def setup_filename(self, filename):
1.176 try:
1.177 self.kind, self.filename = filename.split("://")
1.178 except:
1.179 return (False, "Wrong filename protocol")
1.180
1.181 - audio = setup_audio(self.acodec)
1.182 -
1.183 if self.kind == "file":
1.184 if not os.path.exists(self.filename):
1.185 msg = "File requested does not exist. SETUP failed."
1.186 log.error(msg)
1.187 return (False, msg)
1.188
1.189 - self.args += " %s -mf fps=%s -of %s %s"\
1.190 - " -ovc lavc -lavcopts vcodec=%s:vbitrate=%s -vf scale=%s:%s"\
1.191 - " -really-quiet -o %s 2>/dev/null" % (
1.192 - self.filename, self.fps, self.mux, audio, self.vcodec,
1.193 - self.vbitrate, self.width, self.height, self.fifo)
1.194 -
1.195 elif self.kind == "dvd":
1.196 - self.args += " dvd://%s -alang %s -vf scale=%s:%s %s"\
1.197 - " -of %s -ovc lavc -lavcopts vcodec=%s:vbitrate=%s"\
1.198 - " -ofps %s -really-quiet -o %s 2>/dev/null" % (
1.199 - self.filename, self.language, self.width, self.height, audio,
1.200 - self.mux, self.vcodec, self.vbitrate, self.fps, self.fifo)
1.201 + self.filename = "dvd://" + filename
1.202
1.203 return (True, "")
1.204
1.205 # setup_filename
1.206
1.207 - def setup_socket(self, socket):
1.208 - if socket != None:
1.209 - del(socket)
1.210 + def setup_socket(self):
1.211 + if self.socket != None:
1.212 + del(self.socket)
1.213
1.214 - socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
1.215 - socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
1.216 + self.socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
1.217 + self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
1.218
1.219 try:
1.220 - socket.bind( ('', self.port) )
1.221 - socket.listen(1)
1.222 + self.socket.bind( ('', self.port) )
1.223 + self.socket.listen(1)
1.224 except Exception, e:
1.225 log.error("Could not create socket: %s" % e)
1.226 return (False, e)
1.227
1.228 return (True, "")
1.229
1.230 + # setup_socket
1.231 +
1.232 '''
1.233 MENCODER SETUP DESCRIPTION
1.234 ===========================
1.235 @@ -154,6 +207,12 @@
1.236
1.237 '''
1.238
1.239 +
1.240 + # good one: /tmp/dvb.mpg avi mpeg4 400 25 mp3lame 192 320 240
1.241 + # file:///tmp/dvb.mpg mpeg mpeg1video 400 25 mp2 192 320 240 format=mpeg1
1.242 + # dvd://4 mpeg mpeg1video 400 25 mp3lame 192 400 240 language=en local
1.243 + # file:///tmp/mpg/bad_day.mpg avi mpeg4 400 25 mp3 192 320 240
1.244 +
1.245 def setup(self, filename, mux, vcodec, vbitrate,\
1.246 fps, acodec, abitrate, width, height, port, options):
1.247
1.248 @@ -168,18 +227,17 @@
1.249 self.port = int(port)
1.250
1.251 self.setup_mencoder()
1.252 +
1.253 ret_val = self.setup_filename(filename)
1.254 -
1.255 if not ret_val[0]:
1.256 return ret_val[1]
1.257
1.258 - self.set_args(options)
1.259 + self.setup_opts(options)
1.260 + self.audio_opts = self.setup_audio()
1.261 + self.video_opts = self.setup_video()
1.262 + self.setup_args(self.args)
1.263
1.264 - # good one: /tmp/dvb.mpg avi mpeg4 400 25 mp3lame 192 320 240 5000 file
1.265 - # /tmp/dvb.mpg mpeg mpeg1video 400 25 mp2 192 320 240 5000 format=mpeg1 file
1.266 - #4 mpeg mpeg1video 400 25 mp3lame 192 400 240 5000 language=en local dvd
1.267 - ret_val = setup_socket(self.socket)
1.268 -
1.269 + ret_val = self.setup_socket()
1.270 if not ret_val[0]:
1.271 return ret_val[1]
1.272
1.273 @@ -189,30 +247,25 @@
1.274
1.275 def play(self):
1.276
1.277 - if self.mencoder_old:
1.278 - try:
1.279 - os.mkfifo(self.fifo)
1.280 - except:
1.281 - lib.log("Fifo already exists")
1.282 + log.info("Starting Mencoder: %s" % self.args )
1.283
1.284 + try:
1.285 + self.mencoder_pid = Popen(self.args, stdout=PIPE, close_fds=True)
1.286 + except Exception, e:
1.287 + msg = "Could not init Mencoder: %s" % e
1.288 + log.error(msg)
1.289 + return msg
1.290
1.291 - lib.log("Starting Mencoder: %s %s" % (self.path, self.args) )
1.292 - # exec Mencoder
1.293 - if self.mencoder_old:
1.294 - self.mencoder_pid = Popen(self.path + self.args, shell=True,
1.295 - close_fds=True)
1.296 - self.pout = open(self.fifo)
1.297 - else:
1.298 - self.path += self.args
1.299 - pin, self.pout = os.popen2(self.path)
1.300 + if self.mencoder_old: self.pout = open(self.fifo)
1.301 + else: self.pout = self.mencoder_pid.stdout
1.302
1.303 self.child_pid = os.fork()
1.304
1.305 if self.child_pid == 0:
1.306 - conn,addr= self.socket.accept()
1.307 - lib.log("Sending Data to client: %s" % addr[0])
1.308 + conn, addr = self.socket.accept()
1.309 + log.info("Sending Data to client: %s" % addr[0])
1.310
1.311 - data = self.pout.read(1024)
1.312 + data = self.pout.read(4096)
1.313
1.314 conn.settimeout(5)
1.315 retry = 0
1.316 @@ -226,34 +279,43 @@
1.317 if back == "OK" and self.mplayer and not self.mplayer_pid:
1.318 self.run_mplayer()
1.319
1.320 - except socket.error:
1.321 - lib.log("Socket error (maybe timeout ?)")
1.322 + except socket.error, e:
1.323 + log.error("Socket error: %s" % e)
1.324 retry += 1
1.325
1.326 - data = self.pout.read(1024)
1.327 + data = self.pout.read(4096)
1.328
1.329 if retry < 5:
1.330 - lib.log("Finished sending Data to client: %s" % addr[0])
1.331 + log.info("Finished sending Data to client: %s" % addr[0])
1.332 else:
1.333 - lib.log("Client timed out")
1.334 + log.error("Client timed out, retried more than %s times" % retry)
1.335
1.336 + os.kill(self.mencoder_pid.pid, signal.SIGKILL)
1.337 sys.exit(0)
1.338
1.339 + return True
1.340 +
1.341 + # play
1.342 +
1.343
1.344 def stop(self):
1.345 try:
1.346 - if self.mplayer_old:
1.347 - os.kill(self.mencoder_pid.pid + 1, signal.SIGKILL)
1.348 - else:
1.349 - self.pout.close()
1.350 - self.mplayer = None
1.351 - except:
1.352 - lib.log("Trying to stop before playing...")
1.353
1.354 - if self.socket != None:
1.355 - lib.log("Closing socket")
1.356 - self.socket.close()
1.357 + if self.mencoder_pid:
1.358 + os.kill(self.mencoder_pid.pid, signal.SIGKILL)
1.359 + self.mencoder_pid = None
1.360
1.361 - lib.log("Trying to stop Mencoder process")
1.362 + if self.mplayer_pid:
1.363 + os.kill(self.mplayer_pid.pid, signal.SIGKILL)
1.364 + self.mplayer_pid = None
1.365 +
1.366 + if self.socket != None:
1.367 + self.socket.close()
1.368 +
1.369 if self.child_pid != None:
1.370 - os.kill(self.child_pid, signal.SIGABRT)
1.371 + os.kill(self.child_pid, signal.SIGKILL)
1.372 +
1.373 + except Exception, e:
1.374 + log.error("Stop error: %s" % e)
1.375 +
1.376 + # stop