gmyth-stream/server/plugins/media/mencoder.py
author morphbr
Wed Apr 04 21:18:43 2007 +0100 (2007-04-04)
branchtrunk
changeset 499 9900800a8dd6
parent 498 7a0c3906dce2
child 504 2b5355061b66
permissions -rw-r--r--
[svn r504] Gmyth-Streamer: mencoder stdout bug fix (Chenca's bug)
     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.language = "en"
    18         self.socket = None
    19         self.child_pid = None
    20         self.mplayer = None
    21         self.mencoder_pid = None
    22         self.mplayer_pid = None
    23         signal.signal(signal.SIGABRT, self.kill_handler)
    24 
    25     def kill_handler(self, sig, frame):
    26         try:
    27             os.kill(self.mplayer_pid.pid + 1, signal.SIGKILL)
    28             sys.exit(0)
    29         except:
    30             lib.log("Problems closing child")
    31 
    32     def set_args(self, options):
    33 
    34         for opt in options:
    35 
    36             if opt == "file" or opt == "dvd":
    37 
    38                 if self.acodec == "mp3lame":
    39                     audio = "-oac mp3lame -lameopts cbr:br=%s vol=5" % self.abitrate
    40                 else:
    41                     audio = "-oac lavc -lavcopts acodec=%s:abitrate=%s" % (\
    42                         self.acodec, self.abitrate)
    43 
    44 
    45             if opt == "file":
    46                 self.kind = "file"
    47                 self.args += " %s -mf fps=%s -of %s %s"\
    48                              " -ovc lavc -lavcopts vcodec=%s:vbitrate=%s -vf scale=%s:%s"\
    49                              " -really-quiet -o %s" % (
    50                     self.filename, self.fps, self.mux, audio, self.vcodec,
    51                     self.vbitrate, self.width, self.height, self.fifo)
    52 
    53             elif opt == "dvd":
    54                 self.kind = "dvd"
    55                 self.args += " dvd://%s -alang %s -vf scale=%s:%s %s"\
    56                              " -of %s -ovc lavc -lavcopts vcodec=%s:vbitrate=%s"\
    57                              " -ofps %s -really-quiet -o %s" % (
    58                     self.filename, self.language, self.width, self.height, audio,
    59                     self.mux, self.vcodec, self.vbitrate, self.fps, self.fifo)
    60 
    61             elif opt == "local":
    62                 self.mplayer = os.popen("which mplayer").read().strip()
    63 
    64             elif opt.find("language=") >= 0:
    65                 try:
    66                     self.language = opt.split("=")[1]
    67                 except:
    68                     lib.log("Bad language option")
    69 
    70             elif opt.find("format=") >= 0:
    71                 try:
    72                     self.mux += " -mpegopts format=%s" % opt.split("=")[1]
    73                 except:
    74                     lib.log("Bad format option")
    75 
    76 
    77     def run_mplayer(self):
    78         msg = "%s 1>/dev/null 2>/dev/null" % self.filename
    79 
    80         if self.kind == "dvd":
    81             msg = "dvd://" + msg
    82 
    83         self.mplayer += " " + msg
    84         self.mplayer_pid = Popen(self.mplayer, shell=True)
    85 
    86     def setup(self, filename, mux, vcodec, vbitrate,\
    87               fps, acodec, abitrate, width, height, port, options):
    88 
    89         self.filename = filename
    90         self.mux = mux
    91         self.vcodec = vcodec
    92         self.vbitrate = vbitrate
    93         self.fps = fps
    94         self.acodec = acodec
    95         self.abitrate = abitrate
    96         self.width = width
    97         self.height = height
    98 
    99         self.port = int(port)
   100 
   101         self.path = self.config.get("Mencoder", "path")
   102         a, b = os.popen2(self.path)
   103         version = b.read().split("MEncoder ")[1].split(" (C)")[0].split("-")[-1]
   104 
   105         if version > "4.1.1": self.mencoder_old = False
   106         else: self.mencoder_old = True
   107 
   108         a.close()
   109         b.close()
   110 
   111         if self.mencoder_old:
   112             self.fifo = self.config.get("Mencoder", "fifo_path")
   113         else:
   114             self.fifo = "-"
   115 
   116         self.args = ""
   117         self.kind = ""
   118         self.set_args(options)
   119 
   120         if self.kind == "file" and not os.path.exists(self.filename):
   121             msg = "File requested does not exist. SETUP failed."
   122             lib.log(msg)
   123             return msg
   124 
   125         # good one: /tmp/dvb.mpg avi mpeg4 400 25 mp3lame 192 320 240 5000 file
   126         #4 mpeg mpeg1video 400 25 mp3lame 192 400 240 5000 language=en local dvd
   127         if self.socket != None:
   128             del(self.socket)
   129 
   130         self.socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
   131         self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
   132         self.socket.bind( ('', self.port) )
   133         self.socket.listen(1)
   134 
   135         return 0
   136 
   137 
   138     def play(self):
   139 
   140         if self.mencoder_old:
   141             try:
   142                 os.mkfifo(self.fifo)
   143             except:
   144                 lib.log("Fifo already exists")
   145 
   146 
   147         lib.log("Starting Mencoder: %s %s" % (self.path, self.args) )
   148         # exec Mencoder
   149         if self.mencoder_old:
   150             self.mencoder_pid = Popen(self.path + self.args, shell=True)
   151             fifo = open(self.fifo)
   152         else:
   153             self.path += self.args
   154             pin, self.pout = os.popen2(self.path)
   155 
   156         self.child_pid = os.fork()
   157 
   158         if self.child_pid == 0:
   159             conn,addr= self.socket.accept()
   160             lib.log("Sending Data to client: %s" % addr[0])
   161 
   162             data = self.pout.read(1024)
   163 
   164             conn.settimeout(5)
   165             retry = 0
   166 
   167             while data != "" and retry < 5:
   168                 try:
   169                     conn.send(data)
   170                     r, w, x = select([conn], [], [], 0)
   171                     if conn in r:
   172                         back = conn.recv(1024)
   173                         if back == "OK" and self.mplayer and not self.mplayer_pid:
   174                             self.run_mplayer()
   175 
   176                 except socket.error:
   177                     lib.log("Socket error (maybe timeout ?)")
   178                     retry += 1
   179 
   180                 data = self.pout.read(1024)
   181 
   182             if retry < 5:
   183                 lib.log("Finished sending Data to client: %s" % addr[0])
   184             else:
   185                 lib.log("Client timed out")
   186 
   187             sys.exit(0)
   188 
   189 
   190     def stop(self):
   191         try:
   192             if self.mplayer_old:
   193                 os.kill(self.mencoder_pid.pid + 1, signal.SIGKILL)
   194             else:
   195                 self.pout.close()
   196             self.mplayer = None
   197         except:
   198             lib.log("Trying to stop before playing...")
   199 
   200         if self.socket != None:
   201             lib.log("Closing socket")
   202             self.socket.close()
   203 
   204             lib.log("Trying to stop Mencoder process")
   205             if self.child_pid != None:
   206                 os.kill(self.child_pid, signal.SIGABRT)