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