8 import lib.utils as utils
9 import lib.server as server
10 import plugins.transcoders.mencoder_lib.mythtv as mythtv
12 from select import select
14 __all__ = ("TranscoderMencoder",)
16 class TranscoderMencoder(server.Transcoder):
17 """Transcoder class that implements a transcoder using Mencoder"""
18 mencoder_path = utils.which("mencoder")
25 # only works with avi container
28 def _setup_params(self):
29 params_first = self.params_first
32 self.args["local"] = params_first("local", False)
33 self.args["language"] = params_first("language", False)
34 self.args["subtitle"] = params_first("subtitle", False)
35 self.args["format"] = params_first("format", "mpeg1")
36 self.args["outfile"] = params_first("outfile", "-")
39 self.args["type"] = params_first("type", "file")
40 self.args["input"] = params_first("uri", "-")
43 self.args["acodec"] = params_first("acodec", "mp2")
44 self.args["abitrate"] = params_first("abitrate", 192)
45 self.args["volume"] = params_first("volume", 5)
48 self.args["mux"] = params_first("mux", "mpeg")
49 self.args["fps"] = params_first("fps", 25)
50 self.args["vcodec"] = params_first("vcodec", "mpeg1video")
51 self.args["vbitrate"] = params_first("vbitrate", 400)
52 self.args["width"] = params_first("width", 320)
53 self.args["height"] = params_first("height", 240)
57 def _setup_audio(self):
58 if self.args["acodec"] == "mp3lame":
59 audio = "-oac mp3lame -lameopts cbr:br=%s vol=%s" % (
60 self.args["abitrate"], self.args["volume"])
62 audio = "-oac lavc -lavcopts acodec=%s:abitrate=%s" % (
63 self.args["acodec"], self.args["abitrate"])
69 def _setup_video(self):
70 video = " -of %s" % self.args["mux"]
71 video += " -ofps %s" % self.args["fps"]
73 vcodec = self.args["vcodec"]
74 if vcodec == "nuv" or vcodec == "xvid"\
75 or vcodec == "qtvideo" or vcodec == "copy":
76 video += " -ovc %s" % vcodec
78 video += " -ovc lavc -lavcopts vcodec=%s:vbitrate=%s" % (
79 vcodec, self.args["vbitrate"])
81 if self.args["mux"] == "mpeg":
82 video += " -mpegopts format=%s" % self.args["format"]
83 video += " -vf scale=%s:%s" % (self.args["width"], self.args["height"])
89 def _arg_append(self, args, options):
90 for arg in shlex.split(options):
94 def _setup_mencoder_opts(self, args):
95 args.append(self.mencoder_path)
97 if self.args["outfile"] == "-" and self.args["type"]:
98 args.append(self.args["input"])
102 if self.args["language"]:
103 self._arg_append(args, "-alang %s" % self.args["language"])
105 if self.args["subtitle"]:
106 self._arg_append(args, "-slang %s" % self.args["subtitle"])
107 self._arg_append(args, "-subfps %s" % self.args["fps"])
109 self._arg_append(args, "-idx")
110 self._arg_append(args, "-cache 1024")
111 self._arg_append(args, self._setup_audio())
112 self._arg_append(args, self._setup_video())
114 self._arg_append(args, "-really-quiet")
115 self._arg_append(args, "-o %s" % self.args["outfile"])
116 self._arg_append(args, "2>%s" % os.devnull)
119 def _setup_filename(self):
120 """This function setups the file to encode parsing the uri.
126 If the last one is detected we have to parse the uri to find args.
127 Then we store all the args inside a dictionary: self.args['gmyth-cat']
129 _type = self.args["type"]
132 if not os.path.exists(self.args["input"]):
134 "File requested does not exist: %s." % self.args["input"]
136 self.args["input"] = "file://%s" % self.args["input"]
139 self.args["input"] = "dvd://".join(self.args["input"])
141 elif _type == "myth":
142 self.args["gmyth-cat"] = mythtv._setup_mythfilename(self)
146 def __init__(self, params):
147 server.Transcoder.__init__(self, params)
148 self.mencoder_opts = []
152 self._setup_filename()
153 self._setup_mencoder_opts(self.mencoder_opts)
159 def _check_opened_file(self, stdw, _stdin):
163 return open(self.args["outfile"])
165 os.write(stdw, _stdin.read(1024))
169 def _start_outfile(self, outfd):
172 # fix this (not necessary)
177 _stdin = open(self.args["input"])
178 size = int(os.path.getsize(self.args["input"]))
180 self.log.error("Mencoder stdin setup error: %s" % e)
187 stdr, stdw = os.pipe()
189 if not self._run_mencoder(input=stdr):
192 stdout = self._check_opened_file(stdw, _stdin)
195 while self.proc and self.proc.poll() == None:
197 data_in = _stdin.read(4096)
199 os.write(stdw, data_in)
201 d = stdout.read(4096)
202 self.status = utils.progress_bar(self.log,
210 d = stdout.read(4096)
213 self.log.error("Problems handling data: %s" % e)
217 self.log.info("%s: Finished sending data to client" % repr(self))
221 def _start(self, outfd):
222 # Play a file on disk or DVD
223 if not self._run_mencoder(output=subprocess.PIPE):
227 while self.proc and self.proc.poll() == None:
228 d = self.proc.stdout.read(1024)
231 self.log.error("Problems handling data: %s" % e)
234 self.log.info("%s: Finished sending data to client" % repr(self))
238 def _run_mencoder(self, input=None, output=None):
240 self.proc = subprocess.Popen(self.mencoder_opts, stdin=input,
241 stdout=output, close_fds=True)
243 self.log.error("Error executing mencoder: %s" % e)
249 def start(self, outfd):
250 cmd = " ".join(self.mencoder_opts)
251 self.log.debug("Mencoder: %s" % cmd)
255 if self.args["outfile"] == "-" and self.args["type"] in ["file", "dvd"]:
256 ret = self._start(outfd)
258 elif self.args["type"] == "myth":
259 ret = mythtv.start_myth(self, outfd)
262 ret = self._start_outfile(outfd)
268 def _aux_stop(self, obj):
271 os.kill(obj.pid, signal.SIGKILL)
284 self._aux_stop(self.proc)
285 self._aux_stop(self.gmyth)