gmyth-stream/server/plugins/media/mencoder.py
author rosfran
Mon Apr 09 23:33:35 2007 +0100 (2007-04-09)
branchtrunk
changeset 515 18f08fa8e216
parent 511 16312d0021cb
child 516 f353f0da6f07
permissions -rw-r--r--
[svn r520] Gets and sets functions to the parameters.
     1 import os
     2 import sys
     3 import lib
     4 import time
     5 import signal
     6 import socket
     7 import ConfigParser
     8 
     9 from select import *
    10 from subprocess import *
    11 
    12 class Media(object):
    13 
    14     def __init__(self, config):
    15 
    16         self.config = config
    17         self.args = ""
    18         self.language = "en"
    19         self.socket = None
    20         self.child_pid = None
    21         self.mplayer = None
    22         self.mencoder_pid = None
    23         self.mplayer_pid = None
    24         signal.signal(signal.SIGABRT, self.kill_handler)
    25 
    26     # __init__
    27 
    28     def kill_handler(self, sig, frame):
    29         try:
    30             os.kill(self.mplayer_pid.pid, signal.SIGKILL)
    31             log.debug("Killed Mplayer")
    32             sys.exit(0)
    33         except:
    34             log.error("Problems closing child")
    35 
    36     # kill_handler
    37 
    38     def set_args(self, options):
    39 
    40         for opt in options:
    41 
    42             if opt == "local":
    43                 self.mplayer = lib.which("mplayer")
    44 
    45             elif opt.find("language=") >= 0:
    46                 try:
    47                     self.language = opt.split("=")[1]
    48                 except:
    49                     log.error("Bad language option")
    50 
    51             elif opt.find("format=") >= 0:
    52                 try:
    53                     self.mux += " -mpegopts format=%s" % opt.split("=")[1]
    54                 except:
    55                     log.error("Bad format option")
    56 
    57     # set_args
    58 
    59     def run_mplayer(self):
    60         msg = self.filename
    61 
    62         if self.kind == "dvd":
    63             msg = "dvd://" + msg
    64 
    65         self.mplayer_pid = Popen([self.mplayer, self.filename, "1> %s" % os.devnull,\
    66                                   "2> %s" % os.devnull], stdout=PIPE, close_fds=True)
    67 
    68     # run_mplayer
    69 
    70 
    71     def setup_mencoder(self):
    72         self.path = self.config.get("Mencoder", "path")
    73         mp = Popen([self.path], stdout=PIPE, close_fds=True)
    74 
    75         version = mp.stdout.read().split("MEncoder ")[1].split(" (C)")[0].split("-")[-1]
    76 
    77         if version > "4.1.1": self.mencoder_old = False
    78         else: self.mencoder_old = True
    79 
    80         os.kill(mp.pid, signal.SIGKILL)
    81         log.info("Mencoder version: %s" % version)
    82 
    83         if self.mencoder_old:
    84             self.fifo = self.config.get("Mencoder", "fifo_path")
    85         else:
    86             self.fifo = "-"
    87 
    88     # setup_mencoder
    89 
    90     def setup_audio(self, acodec):
    91 
    92         if acodec == "mp3lame":
    93             return "-oac mp3lame -lameopts cbr:br=%s vol=5" % self.abitrate
    94         else:
    95             return = "-oac lavc -lavcopts acodec=%s:abitrate=%s" % (\
    96                 self.acodec, self.abitrate)
    97 
    98     def setup_filename(self, filename):
    99         try:
   100             self.kind, self.filename = filename.split("://")
   101         except:
   102             return (False, "Wrong filename protocol")
   103 
   104         audio = setup_audio(self.acodec)
   105 
   106         if self.kind == "file":
   107             if not os.path.exists(self.filename):
   108                 msg = "File requested does not exist. SETUP failed."
   109                 log.error(msg)
   110                 return (False, msg)
   111 
   112             self.args += " %s -mf fps=%s -of %s %s"\
   113                          " -ovc lavc -lavcopts vcodec=%s:vbitrate=%s -vf scale=%s:%s"\
   114                          " -really-quiet -o %s 2>/dev/null" % (
   115                 self.filename, self.fps, self.mux, audio, self.vcodec,
   116                 self.vbitrate, self.width, self.height, self.fifo)
   117 
   118         elif self.kind == "dvd":
   119             self.args += " dvd://%s -alang %s -vf scale=%s:%s %s"\
   120                          " -of %s -ovc lavc -lavcopts vcodec=%s:vbitrate=%s"\
   121                          " -ofps %s -really-quiet -o %s 2>/dev/null" % (
   122                 self.filename, self.language, self.width, self.height, audio,
   123                 self.mux, self.vcodec, self.vbitrate, self.fps, self.fifo)
   124 
   125         return (True, "")
   126 
   127     # setup_filename
   128 
   129     def setup_socket(self, socket):
   130         if socket != None:
   131             del(socket)
   132 
   133         socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
   134         socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
   135 
   136         try:
   137             socket.bind( ('', self.port) )
   138             socket.listen(1)
   139         except Exception, e:
   140             log.error("Could not create socket: %s" % e)
   141             return (False, e)
   142 
   143         return (True, "")
   144 
   145     '''
   146     MENCODER SETUP DESCRIPTION
   147     ===========================
   148 
   149     -> mux, vcodecs and acodecs
   150      |-> mencoder (-of | -ovc | -oac) help
   151 
   152     -> if used mpeg as mux:
   153      |-> to setup format: format=%s as an option at the end
   154 
   155     '''
   156 
   157     def setup(self, filename, mux, vcodec, vbitrate,\
   158               fps, acodec, abitrate, width, height, port, options):
   159 
   160         self.mux = mux
   161         self.vcodec = vcodec
   162         self.vbitrate = vbitrate
   163         self.fps = fps
   164         self.acodec = acodec
   165         self.abitrate = abitrate
   166         self.width = width
   167         self.height = height
   168         self.port = int(port)
   169 
   170         self.setup_mencoder()
   171         ret_val = self.setup_filename(filename)
   172 
   173         if not ret_val[0]:
   174             return ret_val[1]
   175 
   176         self.set_args(options)
   177 
   178         # good one: /tmp/dvb.mpg avi mpeg4 400 25 mp3lame 192 320 240 5000 file
   179         # /tmp/dvb.mpg mpeg mpeg1video 400 25 mp2 192 320 240 5000 format=mpeg1 file
   180         #4 mpeg mpeg1video 400 25 mp3lame 192 400 240 5000 language=en local dvd
   181         ret_val = setup_socket(self.socket)
   182 
   183         if not ret_val[0]:
   184             return ret_val[1]
   185 
   186         return True
   187 
   188     # setup
   189 
   190     def play(self):
   191 
   192         if self.mencoder_old:
   193             try:
   194                 os.mkfifo(self.fifo)
   195             except:
   196                 lib.log("Fifo already exists")
   197 
   198 
   199         lib.log("Starting Mencoder: %s %s" % (self.path, self.args) )
   200         # exec Mencoder
   201         if self.mencoder_old:
   202             self.mencoder_pid = Popen(self.path + self.args, shell=True,
   203                                       close_fds=True)
   204             self.pout = open(self.fifo)
   205         else:
   206             self.path += self.args
   207             pin, self.pout = os.popen2(self.path)
   208 
   209         self.child_pid = os.fork()
   210 
   211         if self.child_pid == 0:
   212             conn,addr= self.socket.accept()
   213             lib.log("Sending Data to client: %s" % addr[0])
   214 
   215             data = self.pout.read(1024)
   216 
   217             conn.settimeout(5)
   218             retry = 0
   219 
   220             while data != "" and retry < 5:
   221                 try:
   222                     conn.send(data)
   223                     r, w, x = select([conn], [], [], 0)
   224                     if conn in r:
   225                         back = conn.recv(1024)
   226                         if back == "OK" and self.mplayer and not self.mplayer_pid:
   227                             self.run_mplayer()
   228 
   229                 except socket.error:
   230                     lib.log("Socket error (maybe timeout ?)")
   231                     retry += 1
   232 
   233                 data = self.pout.read(1024)
   234 
   235             if retry < 5:
   236                 lib.log("Finished sending Data to client: %s" % addr[0])
   237             else:
   238                 lib.log("Client timed out")
   239 
   240             sys.exit(0)
   241 
   242 
   243     def stop(self):
   244         try:
   245             if self.mplayer_old:
   246                 os.kill(self.mencoder_pid.pid + 1, signal.SIGKILL)
   247             else:
   248                 self.pout.close()
   249             self.mplayer = None
   250         except:
   251             lib.log("Trying to stop before playing...")
   252 
   253         if self.socket != None:
   254             lib.log("Closing socket")
   255             self.socket.close()
   256 
   257             lib.log("Trying to stop Mencoder process")
   258             if self.child_pid != None:
   259                 os.kill(self.child_pid, signal.SIGABRT)