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(int(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):
263 if not self.params_first("multicast", False):
265 while self.proc and self.proc.poll() == None:
266 d = self.proc.stdout.read(1024)
269 self.log.error(self.tid, "Error: %s" % e)
274 multicast_ip = self.params_first("multicast",
276 multicast_port = int(self.params_first("multicastport",
278 sock = socket.socket(socket.AF_INET,
279 socket.SOCK_DGRAM, socket.IPPROTO_UDP)
280 sock.setsockopt(socket.IPPROTO_IP,
281 socket.IP_MULTICAST_TTL, 2)
283 while self.proc and self.proc.poll() == None:
284 d = self.proc.stdout.read(1024)
285 sock.sendto(d, (multicast_ip, multicast_port))
287 self.log.error(self.tid, "Error: %s" % e)
290 self.log.info(self.tid, "OK: Done")
294 def _run_mencoder(self, input=None, output=None):
296 self.proc = subprocess.Popen(self.mencoder_opts, stdin=input,
297 stdout=output, close_fds=True)
299 self.log.error(self.tid, "Error: Mencoder: %s" % e)
305 def start(self, outfd):
306 print "mencoder_opts: %s" % self.mencoder_opts
307 cmd = " ".join(self.mencoder_opts)
308 self.log.debug(self.tid, "Plugin's tid: %s" % self.tid)
309 self.log.debug(self.tid, "Mencoder: %s" % cmd)
313 if self.args["outfile"] == "-" and \
314 self.args["type"] in ["file", "dvd", "tv"]:
315 ret = self._start(outfd)
317 elif self.args["type"] == "myth":
318 ret = mythtv.start_myth(self, outfd)
321 ret = self._start_outfile(outfd)
326 self.log.error(self.tid, "Error: Problems while "\
327 "starting streaming.")
332 def _aux_stop(self, obj, next=False):
335 os.kill(obj.pid, signal.SIGKILL)
337 os.kill(obj.pid+1, signal.SIGKILL)
350 self._aux_stop(self.proc, True)
351 self._aux_stop(self.gmyth)