[svn r658] Added g_main_context_iteration to while loop on reading from FileTransfer.
8 import lib.utils as utils
9 import lib.server as server
11 from select import select
13 __all__ = ("TranscoderMencoder",)
15 class TranscoderMencoder(server.Transcoder):
16 """Transcoder class that implements a transcoder using Mencoder"""
17 mencoder_path = utils.which("mencoder")
24 # only works with avi container
27 def _setup_params(self):
28 params_first = self.params_first
31 self.args["local"] = params_first("local", False)
32 self.args["language"] = params_first("language", False)
33 self.args["subtitle"] = params_first("subtitle", False)
34 self.args["format"] = params_first("format", "mpeg1")
35 self.args["outfile"] = params_first("outfile", "-")
36 self.args["sendback"] = params_first("sendback", True)
38 # handle sendback variable
39 if self.args["sendback"] == "False":
40 self.args["sendback"] = False
43 uri = params_first("uri", "file:-").split(":", 1)
44 self.args["type"] = uri[0]
45 self.args["input"] = uri[1]
48 self.args["acodec"] = params_first("acodec", "mp2")
49 self.args["abitrate"] = params_first("abitrate", 192)
50 self.args["volume"] = params_first("volume", 5)
53 self.args["mux"] = params_first("mux", "mpeg")
54 self.args["fps"] = params_first("fps", 25)
55 self.args["vcodec"] = params_first("vcodec", "mpeg1video")
56 self.args["vbitrate"] = params_first("vbitrate", 400)
57 self.args["width"] = params_first("width", 320)
58 self.args["height"] = params_first("height", 240)
62 def _setup_audio(self):
63 if self.args["acodec"] == "mp3lame":
64 audio = "-oac mp3lame -lameopts cbr:br=%s vol=%s" % (
65 self.args["abitrate"], self.args["volume"])
67 audio = "-oac lavc -lavcopts acodec=%s:abitrate=%s" % (
68 self.args["acodec"], self.args["abitrate"])
74 def _setup_video(self):
75 video = " -of %s" % self.args["mux"]
76 video += " -ofps %s" % self.args["fps"]
78 vcodec = self.args["vcodec"]
79 if vcodec == "nuv" or vcodec == "xvid"\
80 or vcodec == "qtvideo" or vcodec == "copy":
81 video += " -ovc %s" % vcodec
83 video += " -ovc lavc -lavcopts vcodec=%s:vbitrate=%s" % (
84 vcodec, self.args["vbitrate"])
86 if self.args["mux"] == "mpeg":
87 video += " -mpegopts format=%s" % self.args["format"]
88 video += " -vf scale=%s:%s" % (self.args["width"], self.args["height"])
94 def _arg_append(self, args, options):
95 for arg in shlex.split(options):
99 def _setup_mencoder_opts(self, args):
100 args.append(self.mencoder_path)
102 if self.args["outfile"] == "-" and self.args["type"]:
103 args.append(self.args["input"])
107 if self.args["language"]:
108 self._arg_append(args, "-alang %s" % self.args["language"])
110 if self.args["subtitle"]:
111 self._arg_append(args, "-slang %s" % self.args["subtitle"])
112 self._arg_append(args, "-subfps %s" % self.args["fps"])
114 self._arg_append(args, "-idx")
115 self._arg_append(args, "-cache 1024")
116 self._arg_append(args, self._setup_audio())
117 self._arg_append(args, self._setup_video())
119 self._arg_append(args, "-really-quiet")
120 self._arg_append(args, "-o %s" % self.args["outfile"])
121 self._arg_append(args, "2>%s" % os.devnull)
125 def _setup_filename(self):
126 _type = self.args["type"]
129 if not os.path.exists(self.args["input"]):
131 "File requested does not exist: %s." % self.args["input"]
133 self.args["input"] = "file://%s" % self.args["input"]
136 self.args["input"] = "dvd://".join(self.args["input"])
138 elif _type == "myth":
139 # gmyth-cat -h 192.168.1.124 -p 6543 -c 111
140 # gmyth-cat -h 192.168.1.124 -p 6543 -f file.nuv
141 # myth://IP:PORT:type:file
142 self.args["gmyth-cat"] = self.args["input"].split(":")
143 self.args["input"] = "-"
147 def __init__(self, params):
148 server.Transcoder.__init__(self, params)
149 self.mencoder_opts = []
153 self._setup_filename()
154 self._setup_mencoder_opts(self.mencoder_opts)
160 def _check_opened_file(self, stdw, _stdin):
164 return open(self.args["outfile"])
166 os.write(stdw, _stdin.read(1024))
170 def _start_outfile(self, outfd):
173 # fix this (not necessary)
178 _stdin = open(self.args["input"])
179 size = int(os.path.getsize(self.args["input"]))
181 self.log.error("Mencoder stdin setup error: %s" % e)
188 stdr, stdw = os.pipe()
190 if not self._run_mencoder(input=stdr):
193 stdout = self._check_opened_file(stdw, _stdin)
196 while self.proc and self.proc.poll() == None:
198 data_in = _stdin.read(4096)
200 os.write(stdw, data_in)
202 d = stdout.read(4096)
203 if self.args["sendback"]:
205 self.status = total_read * 100 / size
211 d = stdout.read(4096)
212 if self.args["sendback"] and d != "":
216 self.log.error("Problems handling data: %s" % e)
220 self.log.info("%s: Finished sending data to client" % repr(self))
221 if not self.args["sendback"]:
227 def _start(self, outfd):
228 # Play a file on disk or DVD
229 if not self._run_mencoder(output=subprocess.PIPE):
233 while self.proc and self.proc.poll() == None:
234 d = self.proc.stdout.read(1024)
237 self.log.error("Problems handling data: %s" % e)
240 self.log.info("%s: Finished sending data to client" % repr(self))
244 def _start_myth(self, outfd):
245 # gmyth-cat -h 192.168.1.124 -p 6543 -c 111
246 # gmyth-cat -h 192.168.1.124 -p 6543 -f file.nuv
247 # myth://IP:PORT:type:file
248 host = self.args["gmyth-cat"][0]
249 port = self.args["gmyth-cat"][1]
250 kind = self.args["gmyth-cat"][2]
251 fchan = self.args["gmyth-cat"][3]
253 gmyth_cat = utils.which("gmyth-cat")
254 opts = [gmyth_cat, "-h", host, "-p", port, "-" + kind, fchan]
257 self.gmyth = subprocess.Popen(opts, stdout=subprocess.PIPE,
258 stderr=subprocess.PIPE,
261 self.log.error("Error executing gmyth-cat: %s" % e)
264 err = self.gmyth.stderr
266 if not self._run_mencoder(input=self.gmyth.stdout,
267 output=subprocess.PIPE):
272 size = err.read(20).split("\n")[0].split("Size:")[1]
273 self.log.debug("Size of file: %s" % size)
274 flags = fcntl.fcntl (err, fcntl.F_GETFL, 0) | os.O_NONBLOCK
275 fcntl.fcntl(err, fcntl.F_SETFL, flags)
278 while self.proc and self.proc.poll() == None:
279 r, w, x = select([err, self.proc.stdout], [], [], 0)
280 if self.proc.stdout in r:
281 d = self.proc.stdout.read(4096)
284 if err in r and kind == "f":
285 partial = err.read(50).split("\n")[-2]
287 utils.progress_bar(self.log, int(partial), int(size), 50)
291 self.log.error("Problems handling data: %s" % e)
297 def _run_mencoder(self, input=None, output=None):
299 self.proc = subprocess.Popen(self.mencoder_opts, stdin=input,
300 stdout=output, close_fds=True)
302 self.log.error("Error executing mencoder: %s" % e)
308 def start(self, outfd):
309 cmd = " ".join(self.mencoder_opts)
310 self.log.debug("Mencoder: %s" % cmd)
314 if self.args["outfile"] == "-" and self.args["type"] in ["file", "dvd"]:
315 ret = self._start(outfd)
317 elif self.args["type"] == "myth":
318 ret = self._start_myth(outfd)
321 ret = self._start_outfile(outfd)
331 os.kill(self.proc.pid, signal.SIGKILL)
344 os.kill(self.gmyth.pid, signal.SIGKILL)