3 __author__ = "Artur Duque de Souza"
4 __author_email__ = "artur.souza@indt.org.br"
15 import lib.utils as utils
16 import lib.server as server
17 import plugins.transcoders.mencoder_lib.mythtv as mythtv
19 from select import select
20 import lib.transcoder as transcoder
22 __all__ = ("TranscoderMencoder",)
24 class TranscoderMencoder(transcoder.Transcoder):
25 """Transcoder class that implements a transcoder using Mencoder"""
26 mencoder_path = utils.which("mencoder")
33 # only works with avi container
36 def _setup_params(self):
37 params_first = self.params_first
40 self.args["local"] = params_first("local", False)
41 self.args["language"] = params_first("language", False)
42 self.args["subtitle"] = params_first("subtitle", False)
43 self.args["format"] = params_first("format", "mpeg1")
44 self.args["outfile"] = params_first("outfile", "-")
47 self.args["type"] = params_first("type", "file")
48 self.args["input"] = params_first("uri", "-")
51 self.args["acodec"] = params_first("acodec", "mp2")
52 self.args["abitrate"] = params_first("abitrate", 192)
53 self.args["volume"] = params_first("volume", 5)
56 self.args["mux"] = params_first("mux", "mpeg")
57 self.args["fps"] = params_first("fps", 25)
58 self.args["vcodec"] = params_first("vcodec", "mpeg1video")
59 self.args["vbitrate"] = params_first("vbitrate", 400)
60 self.args["width"] = params_first("width", 320)
61 self.args["height"] = params_first("height", 240)
65 def _setup_audio(self):
66 if self.args["acodec"] == "mp3lame":
67 audio = "-oac mp3lame -lameopts cbr:br=%s vol=%s" % (
68 self.args["abitrate"], self.args["volume"])
70 audio = "-oac lavc -lavcopts acodec=%s:abitrate=%s" % (
71 self.args["acodec"], self.args["abitrate"])
77 def _setup_video(self):
78 video = " -of %s" % self.args["mux"]
79 video += " -ofps %s" % self.args["fps"]
81 vcodec = self.args["vcodec"]
82 if vcodec == "nuv" or vcodec == "xvid"\
83 or vcodec == "qtvideo" or vcodec == "copy":
84 video += " -ovc %s" % vcodec
86 video += " -ovc lavc -lavcopts vcodec=%s:vbitrate=%s" % (
87 vcodec, self.args["vbitrate"])
89 if self.args["mux"] == "mpeg":
90 video += " -mpegopts format=%s" % self.args["format"]
91 video += " -vf scale=%s:%s" % (self.args["width"], self.args["height"])
97 def _arg_append(self, args, options):
98 for arg in shlex.split(options):
102 def _setup_mencoder_opts(self, args):
103 args.append(self.mencoder_path)
105 if self.args["outfile"] == "-" and self.args["type"]:
106 args.append(self.args["input"])
110 if self.args["language"]:
111 self._arg_append(args, "-alang %s" % self.args["language"])
113 if self.args["subtitle"]:
114 self._arg_append(args, "-slang %s" % self.args["subtitle"])
115 self._arg_append(args, "-subfps %s" % self.args["fps"])
117 self._arg_append(args, "-idx")
118 self._arg_append(args, "-cache 1024")
119 self._arg_append(args, self._setup_audio())
120 self._arg_append(args, self._setup_video())
122 self._arg_append(args, "-really-quiet")
123 self._arg_append(args, "-o %s" % self.args["outfile"])
124 self._arg_append(args, "2>%s" % os.devnull)
127 def _setup_filename(self):
128 """This function setups the file to encode parsing the uri.
134 If the last one is detected we have to parse the uri to find args.
135 Then we store all the args inside a dictionary: self.args['gmyth-cat']
137 _type = self.args["type"]
140 if not os.path.exists(self.args["input"]):
142 "File requested does not exist: %s." % self.args["input"]
144 self.args["input"] = "file://%s" % self.args["input"]
147 self.args["input"] = "dvd://".join(self.args["input"])
149 elif _type == "myth":
150 self.args["gmyth-cat"] = mythtv._setup_mythfilename(self)
154 def __init__(self, params):
155 transcoder.Transcoder.__init__(self, params)
156 self.mencoder_opts = []
160 self._setup_filename()
161 self._setup_mencoder_opts(self.mencoder_opts)
163 self.log.error(self.tid, e)
167 def _check_opened_file(self, stdw, _stdin):
171 return open(self.args["outfile"])
173 os.write(stdw, _stdin.read(1024))
177 def _start_outfile(self, outfd):
180 # fix this (not necessary)
185 _stdin = open(self.args["input"])
186 size = int(os.path.getsize(self.args["input"]))
188 self.log.error(self.tid, "Mencoder stdin setup error: %s" % e)
195 stdr, stdw = os.pipe()
197 if not self._run_mencoder(input=stdr):
200 stdout = self._check_opened_file(stdw, _stdin)
203 while self.proc and self.proc.poll() == None:
205 data_in = _stdin.read(4096)
207 os.write(stdw, data_in)
209 d = stdout.read(4096)
210 self.status = utils.progress_bar(self.log,
218 d = stdout.read(4096)
221 self.log.error(self.tid, "Problems handling data: %s" % e)
225 self.log.info(self.tid, "%s: Finished sending data to client" % repr(self))
229 def _start(self, outfd):
230 # Play a file on disk or DVD
231 if not self._run_mencoder(output=subprocess.PIPE):
235 while self.proc and self.proc.poll() == None:
236 d = self.proc.stdout.read(1024)
239 self.log.error(self.tid, "Problems handling data: %s" % e)
242 self.log.info(self.tid, "%s: Finished sending data to client" % repr(self))
246 def _run_mencoder(self, input=None, output=None):
248 self.proc = subprocess.Popen(self.mencoder_opts, stdin=input,
249 stdout=output, close_fds=True)
251 self.log.error(self.tid, "Error executing mencoder: %s" % e)
257 def start(self, outfd):
258 cmd = " ".join(self.mencoder_opts)
259 self.log.debug(self.tid, "Plugin's tid: %s" % self.tid)
260 self.log.debug(self.tid, "Mencoder: %s" % cmd)
265 if self.args["outfile"] == "-" and \
266 self.args["type"] in ["file", "dvd"]:
267 ret = self._start(outfd)
269 elif self.args["type"] == "myth":
270 ret = mythtv.start_myth(self, outfd)
273 ret = self._start_outfile(outfd)
278 self.log.error(self.tid, "Problems while starting streaming.")
283 def _aux_stop(self, obj, next=False):
286 os.kill(obj.pid, signal.SIGKILL)
288 os.kill(obj.pid+1, signal.SIGKILL)
301 self._aux_stop(self.proc, True)
302 self._aux_stop(self.gmyth)