+class FatalException(Exception):
+ pass
+
+def mkarg(arg):
+ if re.match("^[a-zA-Z0-9\-\\.,/@_:=]*$", arg):
+ return arg
+
+ if "'" not in arg:
+ return "'%s'" % arg
+ out = "\""
+ for c in arg:
+ if c in "\\$\"`":
+ out += "\\"
+ out += c
+ out += "\""
+ return out
+
+def midentify(source, field):
+ process = subprocess.Popen(
+ ["mplayer", "-frames", "0", "-identify", source],
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ )
+ for line in process.stdout:
+ try:
+ key, value = line.split("=")
+ except ValueError:
+ continue
+ if key == field:
+ return value.strip()
+
+
+
+class Command(object):
+ codec2exts = {
+ "xvid": "m4v",
+ "x264": "h264",
+ "faac": "aac",
+ "mp3lame": "mp3",
+ "copyac3": "ac3",
+ }
+
+ def __init__(self, profile, opts):
+ self.profile = profile
+ self.opts = opts
+ self.audio_tmp = "audio." + self.codec2exts[profile.acodec]
+ self.video_tmp = "video." + self.codec2exts[profile.vcodec]
+
+ def print_install_message(self):
+ print >>sys.stderr, "Problem with command: %s", self.name
+ if self.package:
+ print >>sys.stderr, "Try running:\n# aptitude install %s", self.package
+
+ def check_command(self, cmd):
+ if self.opts.dump:
+ return
+ if subprocess.Popen(["which", cmd], stdout=open("/dev/null", "w")).wait() != 0:
+ raise FatalException("Command '%s' is required" % cmd)
+
+ def check_no_file(self, path):
+ if os.path.exists(path):
+ raise FatalException("Output file '%s' exists." % path)
+
+ def do_exec(self, args):
+ if self.opts.dump:
+ print " ".join(map(mkarg, args))
+ else:
+ if subprocess.Popen(args).wait() != 0:
+ raise FatalException("Failure executing command: %s" % args)
+
+
+class MP4Box(Command):
+ def check(self):
+ self.check_command("MP4Box")
+ self.check_no_file(self.opts.output + ".mp4")
+
+ def run(self):
+ if self.opts.dump:
+ fps = "???"
+ else:
+ fps = midentify(self.video_tmp, "ID_VIDEO_FPS")
+
+ output = self.opts.output + ".mp4"
+ self.do_exec([
+ "MP4Box",
+ "-fps", fps,
+ "-add", self.video_tmp,
+ "-add", self.audio_tmp,
+ output
+ ])
+
+
+
+class MKVMerge(Command):
+ def check(self):
+ self.check_command("mkvmerge")
+ self.check_no_file(self.opts.output + ".mkv")
+
+ def run(self):
+ if self.opts.dump:
+ fps = "???"
+ else:
+ fps = midentify(self.video_tmp, "ID_VIDEO_FPS")
+
+ self.do_exec([
+ "mkvmerge",
+ "-o", self.opts.output + ".mkv",
+ "--default-duration", "0:%sfps"%fps,
+ self.video_tmp,
+ self.audio_tmp,
+ ])
+
+
+
+class MencoderMux(Command):
+ def check(self):
+ self.check_command("mencoder")
+ self.check_no_file(self.opts.output + ".avi")
+
+ def run(self):
+ self.do_exec([
+ "mencoder",
+ "-o", self.opts.output + ".avi",
+ "-oac", "copy", "-ovc", "copy",
+ "-noskip", "-mc", "0",
+ "-audiofile", self.audio_tmp,
+ self.video_tmp,
+ ])
+
+
+
+class Mencoder(Command):