gmyth-stream/server/0.2/plugins/transcoders/mencoder.py
author renatofilho
Thu Apr 26 22:33:00 2007 +0100 (2007-04-26)
branchtrunk
changeset 600 7da2a5e32fa6
parent 585 a1783dab9ba6
child 605 4dd9bf602c18
permissions -rw-r--r--
[svn r606] added suport for multiple files
     1 import os
     2 import shlex
     3 import signal
     4 import subprocess
     5 import time
     6 
     7 import lib.utils as utils
     8 import lib.server as server
     9 
    10 from select import select
    11 
    12 __all__ = ("TranscoderMencoder",)
    13 
    14 class TranscoderMencoder(server.Transcoder):
    15     """Transcoder class that implements a transcoder using Mencoder"""
    16     mencoder_path = utils.which("mencoder")
    17     name = "mencoder"
    18     priority = -1
    19     args = {}
    20     proc = None
    21 
    22     # only works with avi container
    23     status = 0
    24 
    25     def _setup_params(self):
    26         params_first = self.params_first
    27 
    28         # general_opts
    29         self.args["local"]    = params_first("local", False)
    30         self.args["language"] = params_first("language", False)
    31         self.args["subtitle"] = params_first("subtitle", False)
    32         self.args["format"]   = params_first("format", "")
    33         self.args["outfile"]  = params_first("outfile", "-")
    34         self.args["sendback"] = params_first("sendback", True)
    35 
    36         # handle sendback variable
    37         if self.args["sendback"] == "False":
    38             self.args["sendback"] = False
    39 
    40         # input_opt
    41         uri = params_first("uri", "file://-").split("://")
    42         self.args["type"]     = uri[0]
    43         self.args["input"]    = uri[1]
    44 
    45         # audio_opts
    46         self.args["acodec"]   = params_first("acodec", "mp2")
    47         self.args["abitrate"] = params_first("abitrate", 192)
    48         self.args["volume"]   = params_first("volume", 5)
    49 
    50         # video_opts
    51         self.args["mux"]      = params_first("mux", "mpeg")
    52         self.args["fps"]      = params_first("fps", 25)
    53         self.args["vcodec"]   = params_first("vcodec", "mpeg1video")
    54         self.args["vbitrate"] = params_first("vbitrate", 400)
    55         self.args["width"]    = params_first("width", 320)
    56         self.args["height"]   = params_first("height", 240)
    57     # _setup_params()
    58 
    59 
    60     def _setup_audio(self):
    61         if self.args["acodec"] == "mp3lame":
    62             audio = "-oac mp3lame -lameopts cbr:br=%s vol=%s" % (
    63                 self.args["abitrate"], self.args["volume"])
    64         else:
    65             audio = "-oac lavc -lavcopts acodec=%s:abitrate=%s" % (
    66                 self.args["acodec"], self.args["abitrate"])
    67 
    68         return audio
    69     # _setup_audio()
    70 
    71 
    72     def _setup_video(self):
    73         video = " -of %s" % self.args["mux"]
    74         video += " -ofps %s" % self.args["fps"]
    75 
    76         vcodec = self.args["vcodec"]
    77         if vcodec == "nuv" or vcodec == "xvid"\
    78                or vcodec == "qtvideo" or vcodec == "copy":
    79             video += " -ovc %s" % vcodec
    80         else:
    81             video += " -ovc lavc -lavcopts vcodec=%s:vbitrate=%s" % (
    82                 vcodec, self.args["vbitrate"])
    83 
    84         video += " %s" % self.args["format"]
    85         video += " -vf scale=%s:%s" % (self.args["width"], self.args["height"])
    86 
    87         return video
    88     # _setup_video()
    89 
    90 
    91     def _arg_append(self, args, options):
    92         for arg in shlex.split(options):
    93             args.append(arg)
    94     # arg_append()
    95 
    96     def _setup_mencoder_opts(self, args):
    97         args.append(self.mencoder_path)
    98 
    99         if self.args["outfile"] == "-" and self.args["type"]:
   100             args.append(self.args["input"])
   101         else:
   102             args.append("-")
   103 
   104         if self.args["language"]:
   105             self._arg_append(args, "-alang %s" % self.args["language"])
   106 
   107         if self.args["subtitle"]:
   108             self._arg_append(args, "-slang %s" % self.args["subtitle"])
   109             self._arg_append(args, "-subfps %s" % self.args["fps"])
   110 
   111         self._arg_append(args, "-idx")
   112         self._arg_append(args, self._setup_audio())
   113         self._arg_append(args, self._setup_video())
   114 
   115         self._arg_append(args, "-really-quiet")
   116         self._arg_append(args, "-o %s" % self.args["outfile"])
   117         self._arg_append(args, "2>%s" % os.devnull)
   118     # _setup_args()
   119 
   120 
   121     def _setup_filename(self):
   122         _type = self.args["type"]
   123 
   124         if _type == "file":
   125             if not os.path.exists(self.args["input"]):
   126                 raise IOError,\
   127                       "File requested does not exist: %s." % self.args["input"]
   128 
   129         elif _type == "dvd":
   130             self.args["input"] = "dvd://".join(self.args["input"])
   131 
   132         elif _type == "myth":
   133             # gmyth-cat -h 192.168.1.124 -p 6543 -c 111
   134             # gmyth-cat -h 192.168.1.124 -p 6543 -f file.nuv
   135             # myth://IP:PORT:type:file
   136             self.args["gmyth-cat"] = self.args["input"].split(":")
   137     # _setup_filename()
   138 
   139 
   140     def __init__(self, params):
   141         server.Transcoder.__init__(self, params)
   142         self.mencoder_opts = []
   143 
   144         try:
   145             self._setup_params()
   146             self._setup_filename()
   147             self._setup_mencoder_opts(self.mencoder_opts)
   148         except Exception, e:
   149             self.log.error(e)
   150     # __init__()
   151 
   152 
   153     def _check_opened_file(self, stdw, _stdin):
   154         loop = True
   155         while loop:
   156             try:
   157                 return open(self.args["outfile"])
   158             except:
   159                 os.write(stdw, _stdin.read(1024))
   160     # _check_opened_file
   161 
   162 
   163     def _start_outfile(self, outfd):
   164         finished = False
   165 
   166         # fix this (not necessary)
   167         outfd.write("OK")
   168 
   169         # Configuring stdin
   170         _stdin = open(self.args["input"])
   171         size = int(os.path.getsize(self.args["input"]))
   172         self.status = 0
   173         total_read = 0
   174 
   175         # Configuring pipes
   176         stdr, stdw = os.pipe()
   177 
   178         try:
   179             self.proc = subprocess.Popen(self.mencoder_opts, stdin=stdr, close_fds=True)
   180         except Exception, e:
   181             self.log.error("Error executing mencoder: %s" % e)
   182             return False
   183 
   184         stdout = self._check_opened_file(stdw, _stdin)
   185 
   186         try:
   187             while self.proc and self.proc.poll() == None:
   188                 if not finished:
   189                     data_in = _stdin.read(4096)
   190                     if data_in != "":
   191                         os.write(stdw, data_in)
   192                         total_read += 4096
   193                         d = stdout.read(4096)
   194                         if self.args["sendback"]:
   195                             outfd.write(d)
   196                         self.status = total_read * 100 / size
   197                     else:
   198                         finished = True
   199                         os.close(stdw)
   200 
   201                 else:
   202                     d = stdout.read(4096)
   203                     if self.args["sendback"] and d != "":
   204                         outfd.write(d)
   205 
   206         except Exception, e:
   207             self.log.error("Problems handling data: %s" % e)
   208             return False
   209 
   210         self.log.info("%s: Finished sending data to client" % repr(self))
   211         if not self.args["sendback"]:
   212             outfd.write("DONE")
   213 
   214         return True
   215     # _start_outfile()
   216 
   217     def _start(self, outfd):
   218         try:
   219             self.proc = subprocess.Popen(self.mencoder_opts,
   220                                          stdout=subprocess.PIPE, close_fds=True)
   221         except Exception, e:
   222             self.log.error("Error executing mencoder: %s" % e)
   223             return False
   224 
   225 
   226         try:
   227             while self.proc and self.proc.poll() == None:
   228                 d = self.proc.stdout.read(1024)
   229                 outfd.write(d)
   230         except Exception, e:
   231             self.log.error("Problems handling data: %s" % e)
   232             return False
   233 
   234         self.log.info("%s: Finished sending data to client" % repr(self))
   235         return True
   236     # _start()
   237 
   238 
   239     def start(self, outfd):
   240         cmd = " ".join(self.mencoder_opts)
   241         self.log.debug("Mencoder: %s" % cmd)
   242 
   243         if self.args["outfile"] == "-":
   244             return self._start(outfd)
   245         else:
   246             return self._start_outfile(outfd)
   247     # start()
   248 
   249 
   250     def stop(self):
   251         if self.proc:
   252             try:
   253                 os.kill(self.proc.pid, signal.SIGTERM)
   254             except OSError, e:
   255                 pass
   256 
   257             try:
   258                 self.proc.wait()
   259             except Exception, e:
   260                 pass
   261 
   262             self.proc = None
   263     # stop()
   264 
   265 # TranscoderMencoder