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)
188 self.log.error(self.tid, "Error: %s" % e)
192 def _check_opened_file(self, stdw, _stdin):
196 return open(self.args["outfile"])
198 os.write(stdw, _stdin.read(1024))
202 def _start_outfile(self, outfd):
207 filename = self.args["input"].split("://")[1]
208 _stdin = open(filename)
209 size = int(os.path.getsize(filename))
211 self.log.error(self.tid, "Error: Mencoder stdin"\
212 " setup error: %s" % e)
213 outfd.write("Error: Mencoder stdin setup error: %s" %e)
220 stdr, stdw = os.pipe()
222 if not self._run_mencoder(input=stdr):
225 stdout = self._check_opened_file(stdw, _stdin)
229 while self.proc and self.proc.poll() == None:
231 data_in = _stdin.read(4096)
233 os.write(stdw, data_in)
235 d = stdout.read(4096)
236 self.status = utils.progress_bar(int(total_read),
243 d = stdout.read(4096)
246 self.log.error(self.tid, "Error: %s" % e)
250 self.log.info(self.tid, "OK: Done")
255 def _start(self, outfd):
256 # Play a file on disk or DVD
257 if not self._run_mencoder(output=subprocess.PIPE):
260 if not self.params_first("multicast", None):
262 while self.proc and self.proc.poll() == None:
263 d = self.proc.stdout.read(1024)
266 self.log.error(self.tid, "Error: %s" % e)
271 multicast_ip = self.params_first("multicast",
273 multicast_port = int(self.params_first("multicastport",
275 sock = socket.socket(socket.AF_INET,
276 socket.SOCK_DGRAM, socket.IPPROTO_UDP)
277 sock.setsockopt(socket.IPPROTO_IP,
278 socket.IP_MULTICAST_TTL, 2)
280 while self.proc and self.proc.poll() == None:
281 d = self.proc.stdout.read(1024)
282 sock.sendto(d, (multicast_ip, multicast_port))
284 self.log.error(self.tid, "Error: %s" % e)
287 self.log.info(self.tid, "OK: Done")
291 def _run_mencoder(self, input=None, output=None):
293 self.proc = subprocess.Popen(self.mencoder_opts, stdin=input,
294 stdout=output, close_fds=True)
296 self.log.error(self.tid, "Error: Mencoder: %s" % e)
302 def start(self, outfd):
303 print "mencoder_opts: %s" % self.mencoder_opts
304 cmd = " ".join(self.mencoder_opts)
305 self.log.debug(self.tid, "Plugin's tid: %s" % self.tid)
306 self.log.debug(self.tid, "Mencoder: %s" % cmd)
310 if self.args["outfile"] == "-" and \
311 self.args["type"] in ["file", "dvd", "tv"]:
312 ret = self._start(outfd)
314 elif self.args["type"] == "myth":
315 ret = mythtv.start_myth(self, outfd)
318 ret = self._start_outfile(outfd)
323 self.log.error(self.tid, "Error: Problems while "\
324 "starting streaming.")
329 def _aux_stop(self, obj, next=False):
332 os.kill(obj.pid, signal.SIGKILL)
334 os.kill(obj.pid+1, signal.SIGKILL)
347 self._aux_stop(self.proc, True)
348 self._aux_stop(self.gmyth)