gmyth-stream/server/plugins/media/mencoder.py
author morphbr
Wed Apr 04 17:08:11 2007 +0100 (2007-04-04)
branchtrunk
changeset 497 08a2d7d67ae5
parent 492 63d9475228ac
child 498 7a0c3906dce2
permissions -rw-r--r--
[svn r502] GMyth-Streamer: code cleanup
     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 is "file" or opt is "dvd":
    37 
    38                 if self.acodec is "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 is "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                              " -o %s 1> /dev/null 2> /dev/null" % (
    50                     self.filename, self.fps, self.mux, audio, self.vcodec,
    51                     self.vbitrate, self.width, self.height, self.fifo)
    52 
    53             elif opt is "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 -o %s"\
    57                              " -ofps %s 1> /dev/null 2> /dev/null" % (
    58                     self.filename, self.language, self.width, self.height, audio,
    59                     self.mux, self.vcodec, self.vbitrate, self.fifo, self.fps)
    60 
    61             elif opt is "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 is "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         self.fifo = self.config.get("Mencoder", "fifo_path")
   101 
   102         self.args = ""
   103         self.kind = ""
   104         self.set_args(options)
   105 
   106         if self.kind is "file" and not os.path.exists(self.filename):
   107             msg = "File requested does not exist. SETUP failed."
   108             lib.log(msg)
   109             return msg
   110 
   111         # good one: /tmp/dvb.mpg avi mpeg4 400 25 mp3lame 192 320 240 5000
   112         #4 mpeg mpeg1video 400 25 mp3lame 192 400 240 5000 language=en local dvd
   113         self.path = self.config.get("Mencoder", "path")
   114 
   115         if self.socket is not None:
   116             del(self.socket)
   117 
   118         self.socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
   119         self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
   120         self.socket.bind( ('', self.port) )
   121         self.socket.listen(1)
   122 
   123         return 0
   124 
   125 
   126     def play(self):
   127 
   128         try:
   129             os.mkfifo(self.fifo)
   130         except:
   131             lib.log("Fifo already exists")
   132 
   133         lib.log("Starting Mencoder: %s %s" % (self.path, self.args) )
   134         # exec Mencoder
   135         self.mencoder_pid = Popen(self.path + self.args, shell=True)
   136 
   137         fifo = open(self.fifo)
   138 
   139         self.child_pid = os.fork()
   140 
   141         if self.child_pid is 0:
   142             conn,addr= self.socket.accept()
   143             lib.log("Sending Data to client: %s" % addr[0])
   144 
   145             data = fifo.read(1024)
   146             conn.settimeout(5)
   147             retry = 0
   148 
   149             while data is not "" and retry < 5:
   150                 try:
   151                     conn.send(data)
   152                     r, w, x = select([conn], [], [], 0)
   153                     if conn in r:
   154                         back = conn.recv(1024)
   155                         if back is "OK" and self.mplayer and not self.mplayer_pid:
   156                             self.run_mplayer()
   157 
   158                 except socket.error:
   159                     lib.log("Socket error (maybe timeout ?)")
   160                     retry += 1
   161 
   162                 data = fifo.read(1024)
   163 
   164             if retry < 5:
   165                 lib.log("Finished sending Data to client: %s" % addr[0])
   166             else:
   167                 lib.log("Client timed out")
   168 
   169             sys.exit(0)
   170 
   171 
   172     def stop(self):
   173         try:
   174             os.kill(self.mencoder_pid.pid + 1, signal.SIGKILL)
   175             self.mplayer = None
   176         except:
   177             lib.log("Trying to stop before playing...")
   178 
   179         if self.socket is not None:
   180             lib.log("Closing socket")
   181             self.socket.close()
   182 
   183             lib.log("Trying to stop Mencoder process")
   184             if self.child_pid is not None:
   185                 os.kill(self.child_pid, signal.SIGABRT)