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"]
92 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")
124 if self.args["outfile"] != "-":
125 self.args["outfile"] = ".transcoded/%s" % (
126 os.path.basename(self.args["outfile"]))
128 self._arg_append(args, "-o %s" % self.args["outfile"])
129 self._arg_append(args, "2>%s" % os.devnull)
132 def _setup_filename(self):
133 """This function setups the file to encode parsing the uri.
139 If the last one is detected we have to parse the uri to find args.
140 Then we store all the args inside a dictionary: self.args['gmyth-cat']
142 _type = self.args["type"]
145 if not os.path.exists(self.args["input"]):
147 "File requested does not exist: %s." % self.args["input"]
149 self.args["input"] = "file://%s" % self.args["input"]
152 self.args["input"] = "dvd://%s" % self.args["input"]
154 elif _type == "myth":
155 self.args["gmyth-cat"] = mythtv._setup_mythfilename(self)
158 driver = self.params_first("driver", "v4l2")
159 norm = self.params_first("norm", "pal-m")
160 channel = self.params_first("channel", "13")
161 chanlist = self.params_first("chanlist", "us-bcast")
162 outfmt = self.params_first("outfmt", "yuy2")
163 vdev = self.params_first("vdev", "/dev/video0")
164 adev = self.params_first("adev", "/dev/dsp")
166 self.args["input"] = "tv:// -v -tv driver=%s:norm=%s:channel=%s:" \
167 "chanlist=%s:width=%s:height=%s:outfmt=%s:" \
168 "device=%s:adevice=%s" % (driver, norm,
176 def __init__(self, params):
177 transcoder.Transcoder.__init__(self, params)
178 self.mencoder_opts = []
182 self._setup_filename()
183 self._setup_mencoder_opts(self.mencoder_opts)
185 self.log.error(self.tid, "Error: %s" % e)
189 def _check_opened_file(self, stdw, _stdin):
193 return open(self.args["outfile"])
195 os.write(stdw, _stdin.read(1024))
199 def _start_outfile(self, outfd):
204 filename = self.args["input"].split("://")[1]
205 _stdin = open(filename)
206 size = int(os.path.getsize(filename))
208 self.log.error(self.tid, "Error: Mencoder stdin"\
209 " setup error: %s" % e)
210 outfd.write("Error: Mencoder stdin setup error: %s" %e)
217 stdr, stdw = os.pipe()
219 if not self._run_mencoder(input=stdr):
222 stdout = self._check_opened_file(stdw, _stdin)
226 while self.proc and self.proc.poll() == None:
228 data_in = _stdin.read(4096)
230 os.write(stdw, data_in)
232 d = stdout.read(4096)
233 self.status = utils.progress_bar(int(total_read),
240 d = stdout.read(4096)
243 self.log.error(self.tid, "Error: %s" % e)
247 self.log.info(self.tid, "OK: Done")
252 def _start(self, outfd):
253 # Play a file on disk or DVD
254 if not self._run_mencoder(output=subprocess.PIPE):
258 while self.proc and self.proc.poll() == None:
259 d = self.proc.stdout.read(1024)
262 self.log.error(self.tid, "Error: %s" % e)
265 self.log.info(self.tid, "OK: Done")
269 def _run_mencoder(self, input=None, output=None, error=os.devnull):
271 self.proc = subprocess.Popen(self.mencoder_opts, stdin=input,
272 stdout=output, stderr=error,
275 self.log.error(self.tid, "Error: Mencoder: %s" % e)
281 def start(self, outfd):
282 cmd = " ".join(self.mencoder_opts)
283 self.log.debug(self.tid, "Plugin's tid: %s" % self.tid)
284 self.log.debug(self.tid, "Mencoder: %s" % cmd)
288 if self.args["outfile"] == "-" and \
289 self.args["type"] in ["file", "dvd", "tv"]:
290 ret = self._start(outfd)
292 elif self.args["type"] == "myth":
293 ret = mythtv.start_myth(self, outfd)
296 ret = self._start_outfile(outfd)
301 self.log.error(self.tid, "Error: Problems while "\
302 "starting streaming.")
307 def _aux_stop(self, obj, next=False):
310 os.kill(obj.pid, signal.SIGKILL)
312 os.kill(obj.pid+1, signal.SIGKILL)
325 self._aux_stop(self.proc, True)
326 self._aux_stop(self.gmyth)