3 __author__ = "Artur Duque de Souza"
4 __author_email__ = "artur.souza@indt.org.br"
17 import lib.utils as utils
18 import lib.server as server
19 import plugins.transcoders.mencoder_lib.mythtv as mythtv
21 from select import select
22 import lib.transcoder as transcoder
24 __all__ = ("TranscoderMencoder",)
26 class TranscoderMencoder(transcoder.Transcoder):
27 """Transcoder class that implements a transcoder using Mencoder"""
28 mencoder_path = utils.which("mencoder")
35 # only works with avi container
38 def _setup_params(self):
39 params_first = self.params_first
42 self.args["local"] = params_first("local", False)
43 self.args["language"] = params_first("language", False)
44 self.args["subtitle"] = params_first("subtitle", False)
45 self.args["format"] = params_first("format", "mpeg1")
46 self.args["outfile"] = params_first("outfile", "-")
49 self.args["type"] = params_first("type", "file")
50 self.args["input"] = params_first("uri", "-")
53 self.args["acodec"] = params_first("acodec", "mp2")
54 self.args["abitrate"] = params_first("abitrate", 192)
55 self.args["volume"] = params_first("volume", 5)
58 self.args["mux"] = params_first("mux", "mpeg")
59 self.args["fps"] = params_first("fps", 25)
60 self.args["vcodec"] = params_first("vcodec", "mpeg1video")
61 self.args["vbitrate"] = params_first("vbitrate", 400)
62 self.args["width"] = params_first("width", 320)
63 self.args["height"] = params_first("height", 240)
67 def _setup_audio(self):
68 if self.args["acodec"] == "mp3lame":
69 audio = "-oac mp3lame -lameopts cbr:br=%s vol=%s" % (
70 self.args["abitrate"], self.args["volume"])
72 audio = "-oac lavc -lavcopts acodec=%s:abitrate=%s" % (
73 self.args["acodec"], self.args["abitrate"])
79 def _setup_video(self):
80 video = " -of %s" % self.args["mux"]
81 video += " -ofps %s" % self.args["fps"]
83 vcodec = self.args["vcodec"]
84 if vcodec == "nuv" or vcodec == "xvid"\
85 or vcodec == "qtvideo" or vcodec == "copy":
86 video += " -ovc %s" % vcodec
88 video += " -ovc lavc -lavcopts vcodec=%s:vbitrate=%s" % (
89 vcodec, self.args["vbitrate"])
91 if self.args["mux"] == "mpeg":
92 video += " -mpegopts format=%s" % self.args["format"]
94 video += " -vf scale=%s:%s" % (self.args["width"], self.args["height"])
99 def _arg_append(self, args, options):
100 for arg in shlex.split(options):
104 def _setup_mencoder_opts(self, args):
105 args.append(self.mencoder_path)
107 if self.args["type"] and self.args["type"] == "tv":
108 self._arg_append(args, self.args["tv"])
109 elif self.args["outfile"] == "-" and self.args["type"]:
110 args.append(self.args["input"])
114 if self.args["language"]:
115 self._arg_append(args, "-alang %s" % self.args["language"])
117 if self.args["subtitle"]:
118 self._arg_append(args, "-slang %s" % self.args["subtitle"])
119 self._arg_append(args, "-subfps %s" % self.args["fps"])
121 self._arg_append(args, "-idx")
122 self._arg_append(args, "-cache 1024")
123 self._arg_append(args, self._setup_audio())
124 self._arg_append(args, self._setup_video())
126 self._arg_append(args, "-really-quiet")
128 if self.args["outfile"] != "-":
129 self.args["outfile"] = ".transcoded/%s" % (
130 os.path.basename(self.args["outfile"]))
132 self._arg_append(args, "-o %s" % self.args["outfile"])
133 self._arg_append(args, "2>%s" % os.devnull)
136 def _setup_filename(self):
137 """This function setups the file to encode parsing the uri.
143 If the last one is detected we have to parse the uri to find args.
144 Then we store all the args inside a dictionary: self.args['gmyth-cat']
146 _type = self.args["type"]
149 if not os.path.exists(self.args["input"]):
151 "File requested does not exist: %s." % self.args["input"]
153 self.args["input"] = "file://%s" % self.args["input"]
156 self.args["input"] = "dvd://%s" % self.args["input"]
158 elif _type == "myth":
159 self.args["gmyth-cat"] = mythtv._setup_mythfilename(self)
162 driver = self.params_first("driver", "v4l2")
163 norm = self.params_first("norm", "pal-m")
164 channel = self.params_first("channel", "13")
165 chanlist = self.params_first("chanlist", "us-bcast")
166 outfmt = self.params_first("outfmt", "yuy2")
167 vdev = self.params_first("vdev", "/dev/video0")
168 adev = self.params_first("adev", "/dev/dsp")
169 self.args["tv"] = "tv:// -v -tv driver=%s:norm=%s:channel=%s:" \
170 "chanlist=%s:width=%s:height=%s:outfmt=%s:" \
171 "device=%s:adevice=%s" % (driver, norm,
179 def __init__(self, params):
180 transcoder.Transcoder.__init__(self, params)
181 self.mencoder_opts = []
185 self._setup_filename()
186 self._setup_mencoder_opts(self.mencoder_opts)
189 self.log.error(self.tid, "Error: %s" % e)
195 def _check_opened_file(self, stdw, _stdin):
199 return open(self.args["outfile"])
201 os.write(stdw, _stdin.read(1024))
205 def _start_outfile(self, outfd):
210 filename = self.args["input"].split("://")[1]
211 _stdin = open(filename)
212 size = int(os.path.getsize(filename))
214 self.log.error(self.tid, "Error: Mencoder stdin"\
215 " setup error: %s" % e)
216 outfd.write("Error: Mencoder stdin setup error: %s" %e)
223 stdr, stdw = os.pipe()
225 if not self._run_mencoder(input=stdr):
228 stdout = self._check_opened_file(stdw, _stdin)
232 while self.proc and self.proc.poll() == None:
234 data_in = _stdin.read(4096)
236 os.write(stdw, data_in)
238 d = stdout.read(4096)
239 self.status = utils.progress_bar(total_read,
246 d = stdout.read(4096)
249 self.log.error(self.tid, "Error: %s" % e)
253 self.log.info(self.tid, "OK: Done")
258 def _start(self, outfd):
259 # Play a file on disk or DVD
260 if not self._run_mencoder(output=subprocess.PIPE):
264 while self.proc and self.proc.poll() == None:
265 d = self.proc.stdout.read(1024)
268 self.log.error(self.tid, "Error: %s" % e)
271 self.log.info(self.tid, "OK: Done")
275 def _run_mencoder(self, input=None, output=None):
277 self.proc = subprocess.Popen(self.mencoder_opts, stdin=input,
278 stdout=output, close_fds=True)
280 self.log.error(self.tid, "Error: Mencoder: %s" % e)
286 def start(self, outfd):
287 cmd = " ".join(self.mencoder_opts)
288 self.log.debug(self.tid, "Plugin's tid: %s" % self.tid)
289 self.log.debug(self.tid, "Mencoder: %s" % cmd)
293 if self.args["outfile"] == "-" and \
294 self.args["type"] in ["file", "dvd", "tv"]:
295 ret = self._start(outfd)
297 elif self.args["type"] == "myth":
298 ret = mythtv.start_myth(self, outfd)
301 ret = self._start_outfile(outfd)
306 self.log.error(self.tid, "Error: Problems while "\
307 "starting streaming.")
312 def _aux_stop(self, obj, next=False):
315 os.kill(obj.pid, signal.SIGKILL)
317 os.kill(obj.pid+1, signal.SIGKILL)
330 self._aux_stop(self.proc, True)
331 self._aux_stop(self.gmyth)