[svn r596] Fixed memory leak when dealocating GMythChannelInfo.
1 from __future__ import division
14 from subprocess import *
18 def __init__(self, config):
35 self.mencoder_pid = None
36 self.mplayer_pid = None
37 self.audio_opts = None
38 self.video_opts = None
41 self.transcode_local = None
46 def setup_opts(self, options):
51 self.mplayer = lib.which("mplayer")
53 elif opt.find("language=") >= 0:
55 lan = opt.split("=")[1]
59 log.error("Bad language option: %s" % opt)
61 elif opt.find("subtitle=") >= 0:
63 sub = opt.split("=")[1]
67 log.error("Bad subtitle option: %s" % opt)
69 elif opt.find("format=") >= 0:
71 self.mpegopts = opt.split("=")[1]
73 log.error("Bad format option: %s" % opt)
75 elif opt.find("outfile=") >= 0:
77 self.transcode_local = opt.split("=")[1]
79 log.error("Bad outfile option: %s" % opt)
84 def run_mplayer(self):
87 if self.kind == "dvd":
90 self.mplayer_pid = Popen([self.mplayer, self.filename, "1> %s" % os.devnull,\
91 "2> %s" % os.devnull], stdout=PIPE, close_fds=True)
96 def setup_mencoder(self):
97 self.path = self.config.get("Mencoder", "path")
98 mp = Popen([self.path], stdout=PIPE, close_fds=True)
100 version = mp.stdout.read().split("MEncoder ")[1].split(" (C)")[0].split("-")[-1]
102 if version > "4.1.1": self.mencoder_old = False
103 else: self.mencoder_old = True
105 os.kill(mp.pid, signal.SIGKILL)
106 log.info("Mencoder version: %s" % version)
108 if self.mencoder_old:
110 self.fifo = self.config.get("Mencoder", "fifo_path")
113 log.info("Fifo: %s" % e)
120 def setup_audio(self):
122 if self.acodec == "mp3lame":
123 return "-oac mp3lame -lameopts cbr:br=%s vol=5" % self.abitrate
125 return "-oac lavc -lavcopts acodec=%s:abitrate=%s" % (\
126 self.acodec, self.abitrate)
131 def setup_video(self):
135 video += " -of %s" % self.mux
136 video += " -ofps %s" % self.fps
138 if self.vcodec == "nuv" or self.vcodec == "xvid"\
139 or self.vcodec == "qtvideo" or self.vcodec == "copy":
140 video += " -ovc %s" % self.vcodec
142 video += " -ovc lavc -lavcopts vcodec=%s:vbitrate=%s" % (
143 self.vcodec, self.vbitrate)
145 if self.mux == "mpeg" and self.mpegopts is not None:
146 video += " -mpegopts format=%s" % self.mpegopts
148 video += " -vf scale=%s:%s" % (self.width, self.height)
155 def arg_append(self, args, options):
156 l = shlex.split(options)
163 def setup_args(self, args):
165 args.append(self.path)
167 #args.append(self.filename)
170 if self.language != None:
171 self.arg_append(args, "-alang %s" % self.language)
173 if self.subtitle != None:
174 self.arg_append(args, "-slang %s" % self.subtitle)
175 self.arg_append(args, "-subfps %s" % self.fps)
177 self.arg_append(args, "-idx")
178 self.arg_append(args, self.audio_opts)
179 self.arg_append(args, self.video_opts)
181 self.arg_append(args, "-really-quiet")
182 self.arg_append(args, "-o %s" % self.fifo)
183 self.arg_append(args, "2> %s" % os.devnull)
188 def setup_filename(self, filename):
190 self.kind, self.filename = filename.split("://")
192 return (False, "Wrong filename protocol")
194 if self.kind == "file":
195 if not os.path.exists(self.filename):
196 msg = "File requested does not exist. SETUP failed."
200 elif self.kind == "dvd":
201 self.filename = "dvd://" + filename
203 elif self.kind == "myth":
204 self.filename = filename
205 self.gst_pipe = os.pipe()
206 print self.gst_pipe[0]
207 print self.gst_pipe[1]
214 def setup_socket(self):
215 if self.socket != None:
218 self.socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
219 self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
222 self.socket.bind( ('', self.port) )
223 self.socket.listen(1)
225 log.error("Could not create socket: %s" % e)
234 MENCODER SETUP DESCRIPTION
235 ===========================
237 -> mux, vcodecs and acodecs
238 |-> mencoder (-of | -ovc | -oac) help
240 -> if used mpeg as mux:
241 |-> to setup format: format=%s as an option at the end
246 # good one: /tmp/dvb.mpg avi mpeg4 400 25 mp3lame 192 320 240
247 # file:///tmp/dvb.mpg mpeg mpeg1video 400 25 mp2 192 320 240 format=mpeg1
248 # dvd://4 mpeg mpeg1video 400 25 mp3lame 192 400 240 language=en local
249 # file:///tmp/mpg/bad_day.mpg avi mpeg4 400 25 mp3 192 320 240
251 def setup(self, filename, mux, vcodec, vbitrate,\
252 fps, acodec, abitrate, width, height, port, options):
259 self.vbitrate = vbitrate
262 self.abitrate = abitrate
265 self.port = int(port)
267 self.setup_mencoder()
269 ret_val = self.setup_filename(filename)
274 self.setup_opts(options)
275 self.audio_opts = self.setup_audio()
276 self.video_opts = self.setup_video()
277 self.setup_args(self.args)
279 ret_val = self.setup_socket()
284 def play_loop(self, conn):
285 data = self.pout.read(4096)
290 if not self.transcode_local:
291 while data != "" and retry < 5:
294 r, w, x = select([conn], [], [], 0)
296 back = conn.recv(1024)
297 if back == "OK" and self.mplayer and not self.mplayer_pid:
300 except socket.error, e:
301 log.error("Socket error: %s" % e)
304 data = self.pout.read(4096)
307 local = open(self.transcode_local, "w")
308 total = os.path.getsize(self.filename)
315 log.error("Write error: %s" % e)
317 data = self.pout.read(4096)
319 conn.send("%.2f\n" % (partial * 100 / total) )
333 gst = [ lib.which("gst-launch-0.10"), "--gst-debug-level=0" ]
334 self.arg_append(gst, "mythtvsrc location=%s" % self.filename)
335 self.arg_append(gst, "! fdsink fd=2")
336 self.gst_pid = Popen(gst, close_fds=True)
337 log.info("Running Gstreamer: %s" % gst);
339 msg = "Could not init Gstreamer: %s" % e
344 log.info("Starting Mencoder: %s" % self.args )
346 if not self.gst_pipe:
347 self.stdin = open(self.filename)
349 self.stdin = self.gst_pid.stdout
351 self.mencoder_pid = Popen(self.args, stdin=self.stdin, stdout=PIPE, close_fds=True)
353 msg = "Could not init Mencoder: %s" % e
357 if self.mencoder_old: self.pout = open(self.fifo)
358 else: self.pout = self.mencoder_pid.stdout
360 self.child_pid = os.fork()
362 if self.child_pid == 0:
363 conn, addr = self.socket.accept()
365 log.info("Sending Data to client: %s" % addr[0])
366 retry = self.play_loop(conn)
369 log.info("Finished sending Data to client: %s" % addr[0])
371 log.error("Client timed out, retried more than %s times" % retry)
373 os.kill(self.mencoder_pid.pid, signal.SIGKILL)
384 if self.mencoder_pid:
385 os.kill(self.mencoder_pid.pid, signal.SIGTERM)
386 self.mencoder_pid = None
389 os.kill(self.mplayer_pid.pid, signal.SIGTERM)
390 self.mplayer_pid = None
397 os.kill(self.child_pid, signal.SIGTERM)
398 self.child_pid = None
401 os.kill(self.gst_pid.pid, signal.SIGTERM)
409 log.error("Stop error: %s" % e)