1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/gmyth-stream/server/0.1/lib.py Wed Apr 18 15:59:10 2007 +0100
1.3 @@ -0,0 +1,36 @@
1.4 +import time
1.5 +import logging
1.6 +import os
1.7 +import stat
1.8 +
1.9 +ext = ['mpg', 'avi', 'mp4', 'nuv', 'mpeg', 'mov']
1.10 +
1.11 +def now():
1.12 + return time.strftime("%Y-%m-%d %H:%M:%S");
1.13 +
1.14 +def log(msg):
1.15 + logging.log(logging.DEBUG, msg)
1.16 + new_msg = "[%s] %s" % (now(), msg)
1.17 + return new_msg
1.18 +
1.19 +
1.20 +bin_path_list = os.environ["PATH"].split(os.pathsep)
1.21 +def which(prg):
1.22 + for d in bin_path_list:
1.23 + path = os.path.join(d, prg)
1.24 + if os.path.exists(path):
1.25 + st = os.stat(path)
1.26 + if st[stat.ST_MODE] & 0111:
1.27 + return path
1.28 + return ""
1.29 +
1.30 +def list_media_files(directory, file_list):
1.31 + for root, dirs, files in os.walk(directory):
1.32 + for name in files:
1.33 + if os.path.splitext(name)[1].strip(".") in ext:
1.34 + media = os.path.join(root,name)
1.35 + if media not in file_list:
1.36 + file_list.append(os.path.join(root,name))
1.37 +
1.38 + return True
1.39 +
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/gmyth-stream/server/0.1/main.py Wed Apr 18 15:59:10 2007 +0100
2.3 @@ -0,0 +1,185 @@
2.4 +#!/usr/bin/python
2.5 +
2.6 +import os
2.7 +import lib
2.8 +import sys
2.9 +import imp
2.10 +import ConfigParser
2.11 +import logging as log
2.12 +
2.13 +log.basicConfig(level=log.DEBUG,
2.14 + format="%(asctime)s %(levelname)-8s %(message)s",
2.15 + datefmt='%Y-%m-%d %H:%M:%S')
2.16 +
2.17 +config = ConfigParser.ConfigParser()
2.18 +config.read("stream.conf")
2.19 +
2.20 +def load_module(pathlist, name):
2.21 + fp, path, desc = imp.find_module(name, pathlist)
2.22 + try:
2.23 + module = imp.load_module(name, fp, path, desc)
2.24 + return module
2.25 + finally:
2.26 + if fp:
2.27 + fp.close()
2.28 +
2.29 +
2.30 +media_plugin = config.get("Media", "engine")
2.31 +media_plugin_module = load_module(["./plugins/media"], media_plugin)
2.32 +media = media_plugin_module.Media(config)
2.33 +
2.34 +comm_plugin = config.get("Comm", "engine")
2.35 +comm_plugin_module = load_module(["./plugins/comm"], comm_plugin)
2.36 +server = comm_plugin_module.Server(config)
2.37 +
2.38 +log.info("Starting GMyth-Stream server")
2.39 +
2.40 +
2.41 +'''
2.42 +PROTOCOL DESCRIPTION
2.43 +=====================
2.44 +
2.45 +COMMAND OPTIONS
2.46 +
2.47 +-> SETUP DESCRIPTION
2.48 +|-> used to setup transcoding and streaming parameters
2.49 +|-> must be used before any "PLAY" command
2.50 +|-> e.g:
2.51 +
2.52 +file://file_name mux vcodec vbitrate fps acodec abitrate width height options
2.53 +dvd://title_number mux vcodec vbitrate fps acodec abitrate width height options
2.54 +
2.55 +-> PLAY DESCRIPTION
2.56 + |-> used to start transcoding and streaming of file
2.57 + |-> must be used just if SETUP was used before
2.58 + |-> after it, _must_ send STOP
2.59 +
2.60 +-> STOP DESCRIPTION
2.61 + |-> used to stop transcoding and streaming process
2.62 + |-> must be used just if PLAY was used before
2.63 + |-> must be used after PLAY
2.64 +
2.65 +-> QUIT DESCRIPTION
2.66 + |-> used to quit the main loop (quit program)
2.67 +
2.68 +'''
2.69 +nextport = 0
2.70 +setup = (False, "STOPPED")
2.71 +
2.72 +def do_setup(server, filename, mux, vcodec, vbitrate, fps, acodec, abitrate,
2.73 + width, height, *options):
2.74 + global nextport
2.75 + global setup
2.76 +
2.77 + if setup[1] != "PLAYING":
2.78 + nextport += 1
2.79 + ret = media.setup(filename, mux, vcodec, vbitrate, fps, acodec,
2.80 + abitrate, width, height, nextport, options)
2.81 + if ret[0]:
2.82 + server.sendOk()
2.83 + else:
2.84 + server.sendNotOk(ret[1])
2.85 +
2.86 + setup = (True, setup[1])
2.87 +
2.88 + else: server.sendNotOk("You must STOP before SETingUP again")
2.89 +
2.90 + return True
2.91 +
2.92 +def do_play(server):
2.93 + global setup
2.94 +
2.95 + if setup[0] and setup[1] == "STOPPED":
2.96 + setup = (setup[0], "PLAYING")
2.97 + ret = media.play()
2.98 + if ret[0]:
2.99 + server.sendOk("%d" % nextport)
2.100 + else:
2.101 + server.sendNotOk(ret[1])
2.102 +
2.103 + else:
2.104 + if setup[1] == "STOPPED":
2.105 + server.sendNotOk("You must SETUP before PLAYing")
2.106 + else:
2.107 + server.sendNotOk("You must STOP before PLAYing again")
2.108 +
2.109 + return True
2.110 +
2.111 +def do_stop(server):
2.112 + global setup
2.113 +
2.114 + media.stop()
2.115 + setup = (False, "STOPPED")
2.116 + server.sendOk()
2.117 + return True
2.118 +
2.119 +def do_list(server, *directory):
2.120 + file_list = []
2.121 + for j in directory:
2.122 + lib.list_media_files(j, file_list)
2.123 +
2.124 + server.sendOk(file_list)
2.125 + return True
2.126 +
2.127 +def do_quit(server):
2.128 + server.finish = 1
2.129 + media.stop()
2.130 + server.sendOk()
2.131 + return True
2.132 +
2.133 +
2.134 +mapping = {
2.135 + "SETUP": do_setup,
2.136 + "PLAY": do_play,
2.137 + "STOP": do_stop,
2.138 + "LIST": do_list,
2.139 + "QUIT": do_quit,
2.140 + }
2.141 +
2.142 +
2.143 +def dispatch(server, msg):
2.144 + pieces = msg.split()
2.145 + if len(pieces) < 1:
2.146 + log.error("Invalid client command format: %r" % msg)
2.147 + server.sendNotOk("Invalid Format")
2.148 + return False
2.149 +
2.150 + cmd = pieces[0]
2.151 + f = mapping.get(cmd, None)
2.152 + if not f:
2.153 + log.error("Unknow command: %r" % msg)
2.154 + server.sendNotOk("Unknow Command")
2.155 + return False
2.156 +
2.157 + try:
2.158 + return f(server, *pieces[1:])
2.159 + except Exception, e:
2.160 + log.error("Could not execute %r: %s" % (msg, e))
2.161 + server.sendNotOk(str(e))
2.162 + return False
2.163 +
2.164 +
2.165 +
2.166 +while not server.finish:
2.167 + conn, client, port = server.getRequest()
2.168 + if nextport == 0:
2.169 + nextport = port
2.170 +
2.171 + while not server.finish:
2.172 + msg = server.getMsg()
2.173 + if not msg:
2.174 + break
2.175 +
2.176 + log.info("Client %s sent command: %r" % (client, msg))
2.177 + dispatch(server, msg)
2.178 +
2.179 + log.info("Closing connection with %s" % (client,))
2.180 + server.disconnect_client(conn)
2.181 + try:
2.182 + os.wait()
2.183 + except Exception, e:
2.184 + log.error(e)
2.185 +
2.186 +server.stop()
2.187 +log.info("Server stopped. Closing...")
2.188 +
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/gmyth-stream/server/0.1/plugins/comm/tcp.py Wed Apr 18 15:59:10 2007 +0100
3.3 @@ -0,0 +1,79 @@
3.4 +import lib
3.5 +import time
3.6 +import socket
3.7 +import logging as log
3.8 +
3.9 +class Server(object):
3.10 +
3.11 + def __init__(self, config):
3.12 + self.host = '0.0.0.0'
3.13 + self.port = int(config.get("Comm", "port"))
3.14 + self.finish = 0
3.15 +
3.16 + addr = (self.host, self.port)
3.17 + log.debug("Setup TCP server at %s:%s" % addr)
3.18 + self.tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
3.19 + self.tcp.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
3.20 + self.tcp.bind(addr)
3.21 + self.tcp.listen(1)
3.22 + log.info("TCP server listening at %s:%s (sock=%d)" %
3.23 + (self.host, self.port, self.tcp.fileno()))
3.24 +
3.25 + def getMsg(self):
3.26 + bytes = []
3.27 + try:
3.28 + while 1:
3.29 + c = self.con.recv(1)
3.30 + bytes.append(c)
3.31 + if not c or c == "\n":
3.32 + break
3.33 + except Exception, e:
3.34 + log.error("Error reading message from client: %s" % e)
3.35 + return None
3.36 +
3.37 + if not bytes or bytes[-1] != "\n":
3.38 + msg = "".join(bytes)
3.39 + log.error("Invalid message from client: %r" % msg)
3.40 + return None
3.41 +
3.42 + # remove \n and \r
3.43 + bytes.pop()
3.44 + if bytes[-1] == "\r":
3.45 + bytes.pop()
3.46 +
3.47 + msg = "".join(bytes)
3.48 + log.debug("RECV: %r" % msg)
3.49 + return msg
3.50 +
3.51 + def sendMsg(self, msg):
3.52 + log.debug("SEND: %r" % msg)
3.53 + self.con.send(msg + "\n")
3.54 +
3.55 + def sendOk(self, payload=None):
3.56 + self.sendMsg("OK %d" % bool(payload is not None))
3.57 + if payload is not None:
3.58 + if not isinstance(payload, (tuple, list)):
3.59 + payload = (payload,)
3.60 + for e in payload:
3.61 + self.sendMsg("+%s" % e)
3.62 + self.sendMsg(".")
3.63 +
3.64 + def sendNotOk(self, reason=""):
3.65 + self.sendMsg("NOTOK %r" % reason)
3.66 +
3.67 + def getRequest(self):
3.68 + log.debug("Wait for client request at %s:%s (sock=%d)" %
3.69 + (self.host, self.port, self.tcp.fileno()))
3.70 + self.con, self.client = self.tcp.accept()
3.71 + log.info("Incoming request from %s (con=%s)" %
3.72 + (self.client, self.con.fileno()))
3.73 + return (self.con, self.client, self.port)
3.74 +
3.75 + def disconnect_client(self, connection):
3.76 + log.info("Closed request from %s (con=%s)" %
3.77 + (self.client, self.con.fileno()))
3.78 + connection.close()
3.79 +
3.80 + def stop(self):
3.81 + log.debug("Stop")
3.82 + self.tcp.close()
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/gmyth-stream/server/0.1/plugins/comm/xmlrpc.py Wed Apr 18 15:59:10 2007 +0100
4.3 @@ -0,0 +1,102 @@
4.4 +import lib
4.5 +import SimpleXMLRPCServer
4.6 +
4.7 +
4.8 +class Handler:
4.9 +
4.10 + def __init__(self, recv_pool, send_pool):
4.11 + self.recv_pool = recv_pool
4.12 + self.send_pool = send_pool
4.13 + self.getMsg = self.sendMsg
4.14 +
4.15 + def _listMethods(self):
4.16 + return ['setup', 'play', 'stop', 'close', 'getMsg']
4.17 +
4.18 + def _methodHelp(self, method):
4.19 +
4.20 + if method == 'setup':
4.21 + return "Setup the Media: setup( filename, mux, vcodec, vbitrate,"\
4.22 + " fps, acodec, abitrate, width, height, port, options"
4.23 + elif method == 'play':
4.24 + return "Play the Media: play()"
4.25 + elif method == 'stop':
4.26 + return "Stop the Media: stop()"
4.27 + elif method == 'close':
4.28 + return "Close the connection: close()"
4.29 + elif method == 'getMsg':
4.30 + return "Return the first message in the pool: getMsg()"
4.31 + else:
4.32 + # By convention, return empty
4.33 + # string if no help is available
4.34 + return ""
4.35 +
4.36 + def setup(self, filename, mux, vcodec, vbitrate,\
4.37 + fps, acodec, abitrate, width, height, port, options):
4.38 +
4.39 + msg = "%s %s %s %s %s %s %s" % (filename, mux, vcodec, vbitrate,\
4.40 + fps, acodec, abitrate, width, height, port)
4.41 +
4.42 + if len(options) > 0:
4.43 + for opt in options:
4.44 + msg += " %s" % opt
4.45 +
4.46 + self.recv_pool.append("SETUP")
4.47 + self.recv_pool.append(msg)
4.48 + return self.sendMsg()
4.49 +
4.50 + def play(self):
4.51 + self.recv_pool.append("PLAY")
4.52 + return self.sendMsg()
4.53 +
4.54 + def stop(self):
4.55 + self.recv_pool.append("STOP")
4.56 + return self.sendMsg()
4.57 +
4.58 + def close(self):
4.59 + self.recv_pool.append("CLOSE")
4.60 + return self.sendMsg()
4.61 +
4.62 + def sendMsg(self):
4.63 + if self.send_pool != []:
4.64 + return self.send_pool.pop(0)
4.65 + else:
4.66 + return ""
4.67 +
4.68 +
4.69 +class Server:
4.70 +
4.71 + def __init__(self, config):
4.72 + self.host = 'localhost'
4.73 + self.port = int(config.get("Comm", "port"))
4.74 + self.finish = 0
4.75 + self.recv_pool = []
4.76 + self.send_pool = []
4.77 +
4.78 + self.handler = Handler(self.recv_pool, self.send_pool)
4.79 +
4.80 + self.xmlrpc = SimpleXMLRPCServer.SimpleXMLRPCServer((self.host, self.port))
4.81 + self.xmlrpc.register_instance(self.handler)
4.82 +
4.83 +
4.84 + def getMsg(self, size):
4.85 + if self.recv_pool != []:
4.86 + return self.recv_pool.pop(0)
4.87 + else:
4.88 + return ""
4.89 +
4.90 + def sendMsg(self, msg):
4.91 + self.send_pool.append(msg)
4.92 +
4.93 + def Ack(self, command):
4.94 + msg = "[%s] Command %s received" % (lib.now(), command)
4.95 + self.sendMsg(msg + "\n")
4.96 +
4.97 + def getRequest(self):
4.98 + self.xmlrpc.handle_request()
4.99 + return (0, "RPC Client")
4.100 +
4.101 + def disconnect_client(self, connection):
4.102 + connection = 0
4.103 +
4.104 + def stop(self):
4.105 + self.xmlrpc.server_close()
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/gmyth-stream/server/0.1/plugins/media/ffmpeg.py Wed Apr 18 15:59:10 2007 +0100
5.3 @@ -0,0 +1,91 @@
5.4 +import os
5.5 +import sys
5.6 +import lib
5.7 +import time
5.8 +import socket
5.9 +import ConfigParser
5.10 +
5.11 +class Media:
5.12 +
5.13 + def __init__(self, config):
5.14 +
5.15 + self.config = config
5.16 + self.socket = None
5.17 + self.child_pid = None
5.18 +
5.19 + def setup(self, filename, mux, vcodec, vbitrate,\
5.20 + fps, acodec, abitrate, width, height, port):
5.21 +
5.22 + self.filename = filename
5.23 + self.mux = mux
5.24 + self.vcodec = vcodec
5.25 + self.vbitrate = int(vbitrate)
5.26 + self.fps = int(fps)
5.27 + self.acodec = acodec
5.28 + self.abitrate = int(abitrate)
5.29 + self.width = int(width)
5.30 + self.height = int(height)
5.31 +
5.32 + self.port = int(port)
5.33 +
5.34 + # good one: /tmp/mpg/cpm.mpg mpeg mpeg1video 400 25 mp2 192 320 240 5000
5.35 + self.path = self.config.get("FFmpeg", "path")
5.36 + self.path += " -i %s -f %s -vcodec %s -b %d -r %d -acodec %s -ab %d -s %dx%d -" % (
5.37 + self.filename, self.mux, self.vcodec, self.vbitrate,\
5.38 + self.fps, self.acodec, self.abitrate, self.width, self.height)
5.39 +
5.40 + if (self.socket != None):
5.41 + del(self.socket)
5.42 +
5.43 + self.socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
5.44 + self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
5.45 + self.socket.bind( ('', self.port) )
5.46 + self.socket.settimeout(10)
5.47 + self.socket.listen(1)
5.48 +
5.49 + def play(self):
5.50 +
5.51 + lib.log("Starting FFmpeg: %s" % self.path)
5.52 +
5.53 + # exec FFmpeg and get stdout
5.54 + child_stdin, child_stdout = os.popen2(self.path)
5.55 + child_stdin.close()
5.56 +
5.57 + self.child_pid = os.fork()
5.58 + if (self.child_pid == 0):
5.59 + #child
5.60 +
5.61 + conn,addr= self.socket.accept()
5.62 + lib.log("Sending Data to client: %s" % addr[0])
5.63 + data = child_stdout.read(1024)
5.64 + conn.settimeout(5)
5.65 + retry = 0
5.66 +
5.67 + while( data != "" and retry < 5):
5.68 + try:
5.69 + conn.send(data)
5.70 + except socket.error:
5.71 + lib.log("Socket error (maybe timeout ?)")
5.72 + retry = retry + 1
5.73 +
5.74 + data = child_stdout.read(1024)
5.75 +
5.76 + if (retry < 5):
5.77 + lib.log("Finished sending Data to client: %s" % addr[0])
5.78 + else:
5.79 + lib.log("Client timed out")
5.80 +
5.81 + child_stdout.close()
5.82 + #conn.close()
5.83 + #sys.exit()
5.84 +
5.85 +
5.86 + def stop(self):
5.87 +
5.88 + if (self.socket != None):
5.89 + lib.log("Closing socket")
5.90 + self.socket.close()
5.91 +
5.92 + lib.log("Trying to stop FFmpeg process")
5.93 + if (self.child_pid != None):
5.94 + os.kill(self.child_pid, 9)
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/gmyth-stream/server/0.1/plugins/media/gstreamer-rtp.py Wed Apr 18 15:59:10 2007 +0100
6.3 @@ -0,0 +1,218 @@
6.4 +import pygst
6.5 +pygst.require("0.10")
6.6 +import gst
6.7 +import gobject
6.8 +
6.9 +class Media:
6.10 + class StreamData:
6.11 + stream_count = 0
6.12 +
6.13 + def __init__ (self, pipe, abin, vbin):
6.14 +
6.15 + self.stream_count += 1
6.16 + self.Id = self.stream_count
6.17 + self.Pipe = pipe
6.18 + self.Abin = abin
6.19 + self.Vbin = vbin
6.20 + self.Loop = gobject.MainLoop()
6.21 + self.ACaps = ""
6.22 + self.VCaps = ""
6.23 + self.Ready = False
6.24 +
6.25 +
6.26 + def __init__(self, config):
6.27 + # set gstreamer basic options
6.28 + self.config = config
6.29 + self.pipe = None
6.30 + self.streams = []
6.31 +
6.32 +
6.33 + def setup(self, filename, mux, vcodec, vbitrate,
6.34 + fps, acodec, abitrate, width, height, port, options):
6.35 +
6.36 + ## Pipelines
6.37 + self.pipe = gst.Pipeline ()
6.38 + uri = "file://" + filename
6.39 + print "Opening Uri:" + uri
6.40 + src = gst.element_make_from_uri (gst.URI_SRC, uri, "src")
6.41 + if (src is None):
6.42 + return None
6.43 +
6.44 + decode = gst.element_factory_make ("decodebin", "decode")
6.45 + if (decode is None):
6.46 + return None
6.47 +
6.48 +
6.49 + #video encode
6.50 + #queue ! videoscale ! video/x-raw-yuv,width=240,height=144 ! videorate ! ffenc_h263p bitrate=256000 me-method=2 ! rtph263ppay ! udpsink host=224.0.0.1 port=5000
6.51 + vbin = gst.Bin ()
6.52 + vqueue = gst.element_factory_make ("queue", "vqueue")
6.53 + vscale = gst.element_factory_make ("videoscale", "vscale")
6.54 + vrate = gst.element_factory_make ("videorate", "vrate")
6.55 + vencode = gst.element_factory_make ("ffenc_mpeg4", "vencode")
6.56 + vpay = gst.element_factory_make ("rtpmp4vpay", "vpay")
6.57 + vsink = gst.element_factory_make ("udpsink", "vsink")
6.58 +
6.59 + if (None in [vbin, vqueue, vscale, vrate, vencode, vpay, vsink]):
6.60 + print "Fail to create video encode elements."
6.61 + return None
6.62 +
6.63 + vscale_pad = vscale.get_pad("sink")
6.64 + if (vscale_pad is None):
6.65 + print "Fail to get vscale sink pad."
6.66 + return None
6.67 +
6.68 + vscale_caps = gst.caps_from_string ("video/x-raw-yuv, width=%s, height=%s" % (width, height))
6.69 + if (vscale_caps is None):
6.70 + print "Fail to create video caps"
6.71 + return None
6.72 +
6.73 + if (not vscale_pad.set_caps (vscale_caps)):
6.74 + print "Fail to set video output caps"
6.75 + return None
6.76 +
6.77 + vencode.set_property ("bitrate", 256000)
6.78 + vencode.set_property ("me-method", 2)
6.79 +
6.80 + vsink.set_property ("host", "224.0.0.1")
6.81 + vsink.set_property ("port", 5000)
6.82 +
6.83 + vbin.add (vqueue, vscale, vrate, vencode, vpay, vsink)
6.84 + if (not gst.element_link_many (vqueue, vscale, vrate, vencode, vpay, vsink)):
6.85 + print "Fail to link video elements"
6.86 + return None
6.87 +
6.88 + vbin.add_pad (gst.GhostPad ("sink", vqueue.get_pad ("sink")))
6.89 +
6.90 + #audio encode
6.91 + #audio/x-raw-int ! queue ! audioconvert ! faac ! rtpmp4gpay ! udpsink name=upd_audio host=224.0.0.1 port=5002
6.92 + abin = gst.Bin ()
6.93 + aqueue = gst.element_factory_make ("queue", "vqueue")
6.94 + aconvert = gst.element_factory_make ("audioconvert", "aconvert")
6.95 + aencode = gst.element_factory_make ("faac", "aencode")
6.96 + apay = gst.element_factory_make ("rtpmp4gpay", "apay")
6.97 + asink = gst.element_factory_make ("udpsink", "asink")
6.98 +
6.99 + if (None in [abin, aqueue, aconvert, aencode, apay, asink]):
6.100 + print "Fail to create video encode elements."
6.101 + return None
6.102 +
6.103 + asink.set_property ("host", "224.0.0.1")
6.104 + asink.set_property ("port", 5002)
6.105 +
6.106 + abin.add (aqueue, aconvert, aencode, apay, asink)
6.107 + if (not gst.element_link_many (aqueue, aconvert, aencode, apay, asink)):
6.108 + print "Fail to link video elements"
6.109 + return None
6.110 +
6.111 + abin.add_pad (gst.GhostPad ("sink", aqueue.get_pad ("sink")))
6.112 +
6.113 + self.pipe.add (src, decode, abin, vbin)
6.114 + gst.element_link_many (src, decode)
6.115 +
6.116 + stream_data = self.StreamData (self.pipe, abin, vbin)
6.117 +
6.118 + bus = self.pipe.get_bus()
6.119 + bus.add_signal_watch()
6.120 + bus.connect("message", self.__on_bus_message, stream_data)
6.121 +
6.122 + decode.connect("new-decoded-pad", self.__on_decode_new_pad, stream_data)
6.123 + decode.connect("unknown-type", self.__on_decode_unknown_type, stream_data)
6.124 +
6.125 +
6.126 + self.pipe.set_state (gst.STATE_PAUSED)
6.127 + print "Running Pipe"
6.128 + stream_data.Loop.run ()
6.129 + print "End run"
6.130 +
6.131 + a_caps = stream_data.ACaps
6.132 + v_caps = stream_data.VCaps
6.133 + stream_id = stream_data.Id
6.134 +
6.135 + self.streams.append (stream_data)
6.136 +
6.137 + def play(self):
6.138 +
6.139 + print "Trying to play pipeline: %s" % self.pipe
6.140 + try:
6.141 + if (self.pipe):
6.142 + self.pipe.set_state(gst.STATE_PLAYING)
6.143 + except gobject.GError, e:
6.144 + print "Error: " + str(e)
6.145 +
6.146 +
6.147 + def stop(self):
6.148 +
6.149 + print "Trying to stop pipeline: %s" % self.pipe
6.150 + try:
6.151 + if (self.pipeline):
6.152 + self.pipeline.set_state(gst.STATE_NULL)
6.153 + except gobject.GError, e:
6.154 + print "Error: " + str(e)
6.155 +
6.156 + def __on_bus_message (self, bus, message, stream_data):
6.157 +
6.158 + t = message.type
6.159 + if (t == gst.MESSAGE_STATE_CHANGED):
6.160 + oldstate = -1
6.161 + newstate = -1
6.162 + pending = -1
6.163 + oldstate, newstate, pending = message.parse_state_changed ()
6.164 + if ((oldstate == gst.STATE_READY) and \
6.165 + (newstate == gst.STATE_PAUSED) and \
6.166 + (pending == gst.STATE_VOID_PENDING) and \
6.167 + (stream_data.Ready == False)):
6.168 + state_changed_status, current_state, pending_state = stream_data.Pipe.get_state ()
6.169 + if ((current_state == gst.STATE_PAUSED) and \
6.170 + (pending_state == gst.STATE_VOID_PENDING)):
6.171 + print "Pipe paused"
6.172 + self.__fill_sink_pads (stream_data)
6.173 + stream_data.Loop.quit ()
6.174 + stream_data.Ready = True
6.175 + elif (t == gst.MESSAGE_ERROR):
6.176 + err, debug = message.parse_error()
6.177 + print "Error: %s" % err, debug
6.178 + stream_data.Loop.quit ()
6.179 + stream_data.Ready = False
6.180 +
6.181 + return True
6.182 +
6.183 +
6.184 + def __fill_sink_pads (self, stream_data):
6.185 +
6.186 + asink = stream_data.Abin.get_by_name ("asink")
6.187 + vsink = stream_data.Vbin.get_by_name ("vsink")
6.188 +
6.189 + asink_pad = asink.get_pad ("sink")
6.190 + stream_data.ACaps = asink_pad.get_negotiated_caps().to_string()
6.191 + print "ACAPS " + stream_data.ACaps
6.192 +
6.193 + vsink_pad = vsink.get_pad ("sink")
6.194 + stream_data.VCaps = vsink_pad.get_negotiated_caps().to_string()
6.195 + print "ACAPS " + stream_data.VCaps
6.196 +
6.197 +
6.198 +
6.199 + def __on_decode_unknown_type (self, decode, pad, caps, stream_data):
6.200 +
6.201 + print "Unknown Type"
6.202 + return None
6.203 +
6.204 + def __on_decode_new_pad (self, decode, pad, arg1, stream_data):
6.205 +
6.206 + caps = pad.get_caps().to_string()
6.207 + print "New pad " + caps
6.208 + if (caps.rfind ("audio") != -1):
6.209 + apad = stream_data.Abin.get_pad ("sink")
6.210 + if (pad.link (apad) != gst.PAD_LINK_OK):
6.211 + print "Error on link audio pad"
6.212 + return None
6.213 + elif (caps.rfind ("video") != -1):
6.214 + vpad = stream_data.Vbin.get_pad ("sink")
6.215 + if (pad.link (vpad) != gst.PAD_LINK_OK):
6.216 + print "Error on link video pad"
6.217 + return None
6.218 + else:
6.219 + print "Invalid caps"
6.220 +
6.221 +
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
7.2 +++ b/gmyth-stream/server/0.1/plugins/media/gstreamer.py Wed Apr 18 15:59:10 2007 +0100
7.3 @@ -0,0 +1,290 @@
7.4 +#vim:ts=4:sw=4:et
7.5 +import pygst
7.6 +pygst.require("0.10")
7.7 +import gst
7.8 +import gobject
7.9 +import socket
7.10 +import time
7.11 +from threading import Thread
7.12 +
7.13 +class Media:
7.14 + class StreamListener(Thread):
7.15 + def __init__ (self, stream_data):
7.16 + Thread.__init__(self)
7.17 + self.stream = stream_data
7.18 + print "Thread Created"
7.19 +
7.20 + def run (self):
7.21 + #Create socket
7.22 + print "Waiting connection"
7.23 + self.stream.Socket.listen(1)
7.24 + self.stream.Connection, self.stream.Addr = self.stream.Socket.accept ()
7.25 + print "Connection requested"
7.26 + self.stream.Sink.set_property ("fd", self.stream.Connection.fileno())
7.27 + self.stream.Pipe.set_state(gst.STATE_PLAYING)
7.28 + print "PLAYING"
7.29 +
7.30 +
7.31 + class StreamData:
7.32 + stream_count = 0
7.33 +
7.34 + def __init__ (self, pipe, abin, vbin, sink):
7.35 + self.stream_count += 1
7.36 + self.Id = self.stream_count
7.37 + self.Pipe = pipe
7.38 + self.Abin = abin
7.39 + self.Vbin = vbin
7.40 + self.Sink = sink
7.41 + self.Loop = gobject.MainLoop()
7.42 + self.ACaps = ""
7.43 + self.VCaps = ""
7.44 + self.Ready = False
7.45 + self.Socket = None
7.46 + self.Connection = None
7.47 + self.Addr = None
7.48 +
7.49 + def __init__(self, config):
7.50 + # set gstreamer basic options
7.51 + self.config = config
7.52 + self.streams = []
7.53 + self.socket = None
7.54 + self.connection = None
7.55 + self.addr = None
7.56 + self.ready = False
7.57 + self.current = None
7.58 +
7.59 +
7.60 + def setup(self, uri, mux, vcodec, vbitrate,
7.61 + fps, acodec, abitrate, width, height, port, options):
7.62 +
7.63 + ## Pipelines
7.64 + pipe = gst.Pipeline ()
7.65 + print "Opening Uri:" + uri
7.66 + src = gst.element_make_from_uri (gst.URI_SRC, uri, "src")
7.67 + #src = gst.element_factory_make ("gnomevfssrc", "src")
7.68 + src.set_property ("location", uri)
7.69 + if (src is None):
7.70 + print "Fail to create src element"
7.71 + return None
7.72 +
7.73 + print ("Create source")
7.74 + decode = gst.element_factory_make ("decodebin", "decode")
7.75 + if (decode is None):
7.76 + print "Fail to create decodebin"
7.77 + return None
7.78 +
7.79 + print ("Create source")
7.80 + mux = gst.element_factory_make ("avimux", "mux")
7.81 + if (mux is None):
7.82 + print "Fail to create mux"
7.83 + return None
7.84 +
7.85 + sink = gst.element_factory_make ("fdsink", "sink")
7.86 + if (sink is None):
7.87 + print "Fail to create fdsink"
7.88 + return None
7.89 +
7.90 + print ("Create source")
7.91 +
7.92 + #video encode
7.93 + #queue ! videoscale ! video/x-raw-yuv,width=240,height=144 ! videorate ! ffenc_h263p bitrate=256000 me-method=2 ! rtph263ppay ! udpsink host=224.0.0.1 port=5000
7.94 + vbin = gst.Bin ()
7.95 + vqueue = gst.element_factory_make ("queue", "vqueue")
7.96 + colorspace = gst.element_factory_make ("ffmpegcolorspace", "")
7.97 + vrate = gst.element_factory_make ("videorate", "vrate")
7.98 + vencode = gst.element_factory_make ("ffenc_mpeg4", "vencode")
7.99 + #vencode = gst.element_factory_make ("ffenc_msmpeg4v1", "vencode")
7.100 + vqueue_src = gst.element_factory_make ("queue", "vqueue_src")
7.101 +
7.102 + #if (int(vbitrate) > 0):
7.103 + vencode.set_property ("bitrate", 200)
7.104 + #vencode.set_property ("quant-type", 1)
7.105 + vencode.set_property ("pass", 2)
7.106 + vencode.set_property ("quantizer", 5)
7.107 + #vencode.set_property ("me-method", 1)
7.108 +
7.109 +
7.110 + if (None in [vbin, vqueue, vrate, vencode, vqueue_src]):
7.111 + print "Fail to create video encode elements."
7.112 + return None
7.113 +
7.114 + vbin.add (vqueue)
7.115 + if ((int(width) > 0) and (int(height) > 0)):
7.116 + print ("formating output to %d / %d" % (int(width), int(height)))
7.117 +
7.118 + vscale = gst.element_factory_make ("ffvideoscale", "vscale")
7.119 +
7.120 + vbin.add (vscale);
7.121 + if (not vqueue.link (vscale)):
7.122 + print "Fail to link video elements"
7.123 + return None
7.124 +
7.125 + vbin.add (colorspace)
7.126 +
7.127 + if (not vscale.link (colorspace, \
7.128 + gst.caps_from_string ("video/x-raw-yuv,width=(int)%d,height=(int)%d" % (int(width), int(height))))):
7.129 + print "Fail to link video elements"
7.130 + return None
7.131 + else:
7.132 + vbin.add (colorspace)
7.133 + vqueue.link (colorspace)
7.134 +
7.135 + vbin.add (vrate, vencode, vqueue_src)
7.136 + if (not colorspace.link (vrate)):
7.137 + print "Fail to colorspace with vrate"
7.138 + return None
7.139 +
7.140 +
7.141 + if (not vrate.link (vencode, \
7.142 + gst.caps_from_string ("video/x-raw-yuv,framerate=(fraction)10/1"))):
7.143 + print "Fail to link vrate element"
7.144 + return None
7.145 +
7.146 + if (not vencode.link (vqueue_src)):
7.147 + print "Fail to link video encode with queue"
7.148 + return None
7.149 +
7.150 + vbin.add_pad (gst.GhostPad ("sink", vqueue.get_pad ("sink")))
7.151 + vbin.add_pad (gst.GhostPad ("src", vqueue_src.get_pad ("src")))
7.152 +
7.153 + #audio encode
7.154 + #audio/x-raw-int ! queue ! audioconvert ! faac ! rtpmp4gpay ! udpsink name=upd_audio host=224.0.0.1 port=5002
7.155 + abin = gst.Bin ()
7.156 + aqueue = gst.element_factory_make ("queue", "aqueue")
7.157 + aconvert = gst.element_factory_make ("audioconvert", "aconvert")
7.158 + arate = gst.element_factory_make ("audioresample", "arate")
7.159 + #aencode = gst.element_factory_make ("ffenc_ac3", "aencode")
7.160 + aencode = gst.element_factory_make ("queue", "aencode")
7.161 + #aencode = gst.element_factory_make ("lame", "aencode")
7.162 + #aencode = gst.element_factory_make ("ffenc_mp2", "aencode")
7.163 + aqueue_src = gst.element_factory_make ("queue", "aqueue_src")
7.164 +
7.165 + if (None in [abin, aqueue, arate, aencode, aqueue_src]):
7.166 + print "Fail to create video encode elements."
7.167 + return None
7.168 +
7.169 + abin.add (aqueue, aconvert, arate, aencode, aqueue_src)
7.170 + if (not gst.element_link_many (aqueue, aconvert, arate, aencode, aqueue_src)):
7.171 + print "Fail to link video elements"
7.172 + return None
7.173 +
7.174 + abin.add_pad (gst.GhostPad ("sink", aqueue.get_pad ("sink")))
7.175 + abin.add_pad (gst.GhostPad ("src", aqueue_src.get_pad ("src")))
7.176 +
7.177 + #Finish Pipeline
7.178 + pipe.add (src, decode, abin, vbin, mux, sink)
7.179 + gst.element_link_many (src, decode)
7.180 + gst.element_link_many (mux, sink)
7.181 +
7.182 + #Linking decode with mux
7.183 + mux_audio = mux.get_pad ("audio_0")
7.184 + mux_video = mux.get_pad ("video_0")
7.185 +
7.186 + audio_pad = abin.get_pad ("src")
7.187 + video_pad = vbin.get_pad ("src")
7.188 +
7.189 + if (audio_pad.link (mux_audio) != gst.PAD_LINK_OK):
7.190 + print "Fail to link audio with mux"
7.191 + return None
7.192 +
7.193 + if (video_pad.link (mux_video) != gst.PAD_LINK_OK):
7.194 + print "Fail to link audio with mux"
7.195 + return None
7.196 +
7.197 + stream_data = self.StreamData (pipe, abin, vbin, sink)
7.198 + bus = pipe.get_bus()
7.199 + bus.add_signal_watch()
7.200 + bus.connect ("message", self.__on_bus_message, stream_data)
7.201 +
7.202 + decode.connect("new-decoded-pad", self.__on_decode_new_pad, stream_data)
7.203 + decode.connect("unknown-type", self.__on_decode_unknown_type, stream_data)
7.204 +
7.205 + print ("Create source")
7.206 + pipe.set_state (gst.STATE_PAUSED)
7.207 + print "Running Pipe"
7.208 + stream_data.Loop.run ()
7.209 + print "End run"
7.210 +
7.211 +
7.212 + #Create socket
7.213 + stream_data.Socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
7.214 + print "Bind on port %d" % port
7.215 + stream_data.Socket.bind(('', int (port)))
7.216 + self.streams.append (stream_data)
7.217 + return (True, "")
7.218 +
7.219 + def play(self):
7.220 + print "Play"
7.221 + stream = self.streams[0]
7.222 + self.current = self.StreamListener(stream)
7.223 + self.current.start ()
7.224 + time.sleep (1)
7.225 + return (True, "")
7.226 +
7.227 + def stop(self):
7.228 + self.current.join ()
7.229 + self.current = None
7.230 + stream = self.streams[0]
7.231 + stream.Pipe.set_state(gst.STATE_NULL)
7.232 + del (stream.Pipe)
7.233 + stream.Pipe = None
7.234 + stream.Abin = None
7.235 + stream.Vbin = None
7.236 + stream.Sink = None
7.237 + if (stream.Connection != None):
7.238 + stream.Connection.close ()
7.239 +
7.240 + self.streams = []
7.241 + time.sleep (5)
7.242 + return (True, "")
7.243 +
7.244 +
7.245 + def __on_bus_message (self, bus, message, stream_data):
7.246 +
7.247 + t = message.type
7.248 + if (t == gst.MESSAGE_STATE_CHANGED):
7.249 + oldstate = -1
7.250 + newstate = -1
7.251 + pending = -1
7.252 + oldstate, newstate, pending = message.parse_state_changed ()
7.253 + if ((oldstate == gst.STATE_READY) and \
7.254 + (newstate == gst.STATE_PAUSED) and \
7.255 + (pending == gst.STATE_VOID_PENDING) and \
7.256 + (stream_data.Ready == False)):
7.257 + state_changed_status, current_state, pending_state = stream_data.Pipe.get_state ()
7.258 + if ((current_state == gst.STATE_PAUSED) and \
7.259 + (pending_state == gst.STATE_VOID_PENDING)):
7.260 + print "Pipe paused"
7.261 + stream_data.Loop.quit ()
7.262 + stream_data.Ready = True
7.263 + elif (t == gst.MESSAGE_ERROR):
7.264 + err, debug = message.parse_error()
7.265 + print "Error: %s" % err, debug
7.266 + stream_data.Loop.quit ()
7.267 + stream_data.Ready = False
7.268 +
7.269 + return True
7.270 +
7.271 + def __on_decode_unknown_type (self, decode, pad, caps, stream_data):
7.272 +
7.273 + print "Unknown Type"
7.274 + return None
7.275 +
7.276 + def __on_decode_new_pad (self, decode, pad, arg1, stream_data):
7.277 +
7.278 + caps = pad.get_caps().to_string()
7.279 + print "New pad " + caps
7.280 + if (caps.rfind ("audio") != -1):
7.281 + apad = stream_data.Abin.get_pad ("sink")
7.282 + if (pad.link (apad) != gst.PAD_LINK_OK):
7.283 + print "Error on link audio pad"
7.284 + return None
7.285 + elif (caps.rfind ("video") != -1):
7.286 + vpad = stream_data.Vbin.get_pad ("sink")
7.287 + if (pad.link (vpad) != gst.PAD_LINK_OK):
7.288 + print "Error on link video pad"
7.289 + return None
7.290 + else:
7.291 + print "Invalid caps"
7.292 + print "Linked"
7.293 +
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
8.2 +++ b/gmyth-stream/server/0.1/plugins/media/mencoder.py Wed Apr 18 15:59:10 2007 +0100
8.3 @@ -0,0 +1,411 @@
8.4 +from __future__ import division
8.5 +
8.6 +import os
8.7 +import sys
8.8 +import lib
8.9 +import time
8.10 +import shlex
8.11 +import signal
8.12 +import socket
8.13 +import ConfigParser
8.14 +import logging as log
8.15 +
8.16 +from select import *
8.17 +from subprocess import *
8.18 +
8.19 +class Media(object):
8.20 +
8.21 + def __init__(self, config):
8.22 +
8.23 + self.config = config
8.24 + self.do_cleanup()
8.25 +
8.26 + # __init__()
8.27 +
8.28 +
8.29 + def do_cleanup(self):
8.30 + self.path = ""
8.31 + self.args = []
8.32 + self.language = None
8.33 + self.subtitle = None
8.34 + self.mpegopts = None
8.35 + self.socket = None
8.36 + self.child_pid = None
8.37 + self.mplayer = None
8.38 + self.mencoder_pid = None
8.39 + self.mplayer_pid = None
8.40 + self.audio_opts = None
8.41 + self.video_opts = None
8.42 + self.gst_pipe = None
8.43 + self.gst_pid = None
8.44 + self.transcode_local = None
8.45 +
8.46 + # do_cleanup()
8.47 +
8.48 +
8.49 + def setup_opts(self, options):
8.50 +
8.51 + for opt in options:
8.52 +
8.53 + if opt == "local":
8.54 + self.mplayer = lib.which("mplayer")
8.55 +
8.56 + elif opt.find("language=") >= 0:
8.57 + try:
8.58 + lan = opt.split("=")[1]
8.59 + if len(lan) < 2:
8.60 + self.language = lan
8.61 + except Exception, e:
8.62 + log.error("Bad language option: %s" % opt)
8.63 +
8.64 + elif opt.find("subtitle=") >= 0:
8.65 + try:
8.66 + sub = opt.split("=")[1]
8.67 + if len(sub) < 2:
8.68 + self.language = sub
8.69 + except Exception, e:
8.70 + log.error("Bad subtitle option: %s" % opt)
8.71 +
8.72 + elif opt.find("format=") >= 0:
8.73 + try:
8.74 + self.mpegopts = opt.split("=")[1]
8.75 + except Exception, e:
8.76 + log.error("Bad format option: %s" % opt)
8.77 +
8.78 + elif opt.find("outfile=") >= 0:
8.79 + try:
8.80 + self.transcode_local = opt.split("=")[1]
8.81 + except Exception, e:
8.82 + log.error("Bad outfile option: %s" % opt)
8.83 +
8.84 + # setup_opts()
8.85 +
8.86 +
8.87 + def run_mplayer(self):
8.88 + msg = self.filename
8.89 +
8.90 + if self.kind == "dvd":
8.91 + msg = "dvd://" + msg
8.92 +
8.93 + self.mplayer_pid = Popen([self.mplayer, self.filename, "1> %s" % os.devnull,\
8.94 + "2> %s" % os.devnull], stdout=PIPE, close_fds=True)
8.95 +
8.96 + # run_mplayer()
8.97 +
8.98 +
8.99 + def setup_mencoder(self):
8.100 + self.path = self.config.get("Mencoder", "path")
8.101 + mp = Popen([self.path], stdout=PIPE, close_fds=True)
8.102 +
8.103 + version = mp.stdout.read().split("MEncoder ")[1].split(" (C)")[0].split("-")[-1]
8.104 +
8.105 + if version > "4.1.1": self.mencoder_old = False
8.106 + else: self.mencoder_old = True
8.107 +
8.108 + os.kill(mp.pid, signal.SIGKILL)
8.109 + log.info("Mencoder version: %s" % version)
8.110 +
8.111 + if self.mencoder_old:
8.112 + try:
8.113 + self.fifo = self.config.get("Mencoder", "fifo_path")
8.114 + os.mkfifo(self.fifo)
8.115 + except Exception, e:
8.116 + log.info("Fifo: %s" % e)
8.117 + else:
8.118 + self.fifo = "-"
8.119 +
8.120 + # setup_mencoder()
8.121 +
8.122 +
8.123 + def setup_audio(self):
8.124 +
8.125 + if self.acodec == "mp3lame":
8.126 + return "-oac mp3lame -lameopts cbr:br=%s vol=5" % self.abitrate
8.127 + else:
8.128 + return "-oac lavc -lavcopts acodec=%s:abitrate=%s" % (\
8.129 + self.acodec, self.abitrate)
8.130 +
8.131 + # setup_audio()
8.132 +
8.133 +
8.134 + def setup_video(self):
8.135 +
8.136 + video = ""
8.137 +
8.138 + video += " -of %s" % self.mux
8.139 + video += " -ofps %s" % self.fps
8.140 +
8.141 + if self.vcodec == "nuv" or self.vcodec == "xvid"\
8.142 + or self.vcodec == "qtvideo" or self.vcodec == "copy":
8.143 + video += " -ovc %s" % self.vcodec
8.144 + else:
8.145 + video += " -ovc lavc -lavcopts vcodec=%s:vbitrate=%s" % (
8.146 + self.vcodec, self.vbitrate)
8.147 +
8.148 + if self.mux == "mpeg" and self.mpegopts is not None:
8.149 + video += " -mpegopts format=%s" % self.mpegopts
8.150 +
8.151 + video += " -vf scale=%s:%s" % (self.width, self.height)
8.152 +
8.153 + return video
8.154 +
8.155 + # setup_video()
8.156 +
8.157 +
8.158 + def arg_append(self, args, options):
8.159 + l = shlex.split(options)
8.160 + for i in l:
8.161 + args.append(i)
8.162 +
8.163 + # arg_append()
8.164 +
8.165 +
8.166 + def setup_args(self, args):
8.167 +
8.168 + args.append(self.path)
8.169 +
8.170 + #args.append(self.filename)
8.171 + args.append("-")
8.172 +
8.173 + if self.language != None:
8.174 + self.arg_append(args, "-alang %s" % self.language)
8.175 +
8.176 + if self.subtitle != None:
8.177 + self.arg_append(args, "-slang %s" % self.subtitle)
8.178 + self.arg_append(args, "-subfps %s" % self.fps)
8.179 +
8.180 + self.arg_append(args, "-idx")
8.181 + self.arg_append(args, self.audio_opts)
8.182 + self.arg_append(args, self.video_opts)
8.183 +
8.184 + self.arg_append(args, "-really-quiet")
8.185 + self.arg_append(args, "-o %s" % self.fifo)
8.186 + self.arg_append(args, "2> %s" % os.devnull)
8.187 +
8.188 + # setup_args()
8.189 +
8.190 +
8.191 + def setup_filename(self, filename):
8.192 + try:
8.193 + self.kind, self.filename = filename.split("://")
8.194 + except:
8.195 + return (False, "Wrong filename protocol")
8.196 +
8.197 + if self.kind == "file":
8.198 + if not os.path.exists(self.filename):
8.199 + msg = "File requested does not exist. SETUP failed."
8.200 + log.error(msg)
8.201 + return (False, msg)
8.202 +
8.203 + elif self.kind == "dvd":
8.204 + self.filename = "dvd://" + filename
8.205 +
8.206 + elif self.kind == "myth":
8.207 + self.filename = filename
8.208 + self.gst_pipe = os.pipe()
8.209 + print self.gst_pipe[0]
8.210 + print self.gst_pipe[1]
8.211 +
8.212 + return (True, "")
8.213 +
8.214 + # setup_filename()
8.215 +
8.216 +
8.217 + def setup_socket(self):
8.218 + if self.socket != None:
8.219 + self.socket = None
8.220 +
8.221 + self.socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
8.222 + self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
8.223 +
8.224 + try:
8.225 + self.socket.bind( ('', self.port) )
8.226 + self.socket.listen(1)
8.227 + except Exception, e:
8.228 + log.error("Could not create socket: %s" % e)
8.229 + return (False, e)
8.230 +
8.231 + return (True, "")
8.232 +
8.233 + # setup_socket()
8.234 +
8.235 +
8.236 + '''
8.237 + MENCODER SETUP DESCRIPTION
8.238 + ===========================
8.239 +
8.240 + -> mux, vcodecs and acodecs
8.241 + |-> mencoder (-of | -ovc | -oac) help
8.242 +
8.243 + -> if used mpeg as mux:
8.244 + |-> to setup format: format=%s as an option at the end
8.245 +
8.246 + '''
8.247 +
8.248 +
8.249 + # good one: /tmp/dvb.mpg avi mpeg4 400 25 mp3lame 192 320 240
8.250 + # file:///tmp/dvb.mpg mpeg mpeg1video 400 25 mp2 192 320 240 format=mpeg1
8.251 + # dvd://4 mpeg mpeg1video 400 25 mp3lame 192 400 240 language=en local
8.252 + # file:///tmp/mpg/bad_day.mpg avi mpeg4 400 25 mp3 192 320 240
8.253 +
8.254 + def setup(self, filename, mux, vcodec, vbitrate,\
8.255 + fps, acodec, abitrate, width, height, port, options):
8.256 +
8.257 + if self.args != []:
8.258 + self.do_cleanup()
8.259 +
8.260 + self.mux = mux
8.261 + self.vcodec = vcodec
8.262 + self.vbitrate = vbitrate
8.263 + self.fps = fps
8.264 + self.acodec = acodec
8.265 + self.abitrate = abitrate
8.266 + self.width = width
8.267 + self.height = height
8.268 + self.port = int(port)
8.269 +
8.270 + self.setup_mencoder()
8.271 +
8.272 + ret_val = self.setup_filename(filename)
8.273 +
8.274 + if not ret_val[0]:
8.275 + return ret_val
8.276 +
8.277 + self.setup_opts(options)
8.278 + self.audio_opts = self.setup_audio()
8.279 + self.video_opts = self.setup_video()
8.280 + self.setup_args(self.args)
8.281 +
8.282 + ret_val = self.setup_socket()
8.283 + return ret_val
8.284 +
8.285 + # setup()
8.286 +
8.287 + def play_loop(self, conn):
8.288 + data = self.pout.read(4096)
8.289 +
8.290 + conn.settimeout(5)
8.291 + retry = 0
8.292 +
8.293 + if not self.transcode_local:
8.294 + while data != "" and retry < 5:
8.295 + try:
8.296 + conn.send(data)
8.297 + r, w, x = select([conn], [], [], 0)
8.298 + if conn in r:
8.299 + back = conn.recv(1024)
8.300 + if back == "OK" and self.mplayer and not self.mplayer_pid:
8.301 + self.run_mplayer()
8.302 +
8.303 + except socket.error, e:
8.304 + log.error("Socket error: %s" % e)
8.305 + retry += 1
8.306 +
8.307 + data = self.pout.read(4096)
8.308 +
8.309 + else:
8.310 + local = open(self.transcode_local, "w")
8.311 + total = os.path.getsize(self.filename)
8.312 + partial = 4096
8.313 +
8.314 + while data != "":
8.315 + try:
8.316 + local.write(data)
8.317 + except Exception, e:
8.318 + log.error("Write error: %s" % e)
8.319 +
8.320 + data = self.pout.read(4096)
8.321 + partial += len(data)
8.322 + conn.send("%.2f\n" % (partial * 100 / total) )
8.323 +
8.324 + local.close()
8.325 + conn.send("DONE\n")
8.326 +
8.327 + return retry
8.328 +
8.329 + # play_loop()
8.330 +
8.331 +
8.332 + def play(self):
8.333 +
8.334 + if self.gst_pipe:
8.335 + try:
8.336 + gst = [ lib.which("gst-launch-0.10"), "--gst-debug-level=0" ]
8.337 + self.arg_append(gst, "mythtvsrc location=%s" % self.filename)
8.338 + self.arg_append(gst, "! fdsink fd=2")
8.339 + self.gst_pid = Popen(gst, close_fds=True)
8.340 + log.info("Running Gstreamer: %s" % gst);
8.341 + except Exception, e:
8.342 + msg = "Could not init Gstreamer: %s" % e
8.343 + log.error(msg)
8.344 + return (False, msg)
8.345 +
8.346 +
8.347 + log.info("Starting Mencoder: %s" % self.args )
8.348 + try:
8.349 + if not self.gst_pipe:
8.350 + self.stdin = open(self.filename)
8.351 + else:
8.352 + self.stdin = self.gst_pid.stdout
8.353 +
8.354 + self.mencoder_pid = Popen(self.args, stdin=self.stdin, stdout=PIPE, close_fds=True)
8.355 + except Exception, e:
8.356 + msg = "Could not init Mencoder: %s" % e
8.357 + log.error(msg)
8.358 + return (False, msg)
8.359 +
8.360 + if self.mencoder_old: self.pout = open(self.fifo)
8.361 + else: self.pout = self.mencoder_pid.stdout
8.362 +
8.363 + self.child_pid = os.fork()
8.364 +
8.365 + if self.child_pid == 0:
8.366 + conn, addr = self.socket.accept()
8.367 +
8.368 + log.info("Sending Data to client: %s" % addr[0])
8.369 + retry = self.play_loop(conn)
8.370 +
8.371 + if retry < 5:
8.372 + log.info("Finished sending Data to client: %s" % addr[0])
8.373 + else:
8.374 + log.error("Client timed out, retried more than %s times" % retry)
8.375 +
8.376 + os.kill(self.mencoder_pid.pid, signal.SIGKILL)
8.377 + sys.exit(0)
8.378 +
8.379 + return (True, "")
8.380 +
8.381 + # play()
8.382 +
8.383 +
8.384 + def stop(self):
8.385 + try:
8.386 +
8.387 + if self.mencoder_pid:
8.388 + os.kill(self.mencoder_pid.pid, signal.SIGTERM)
8.389 + self.mencoder_pid = None
8.390 +
8.391 + if self.mplayer_pid:
8.392 + os.kill(self.mplayer_pid.pid, signal.SIGTERM)
8.393 + self.mplayer_pid = None
8.394 +
8.395 + if self.socket:
8.396 + self.socket.close()
8.397 + self.socket = None
8.398 +
8.399 + if self.child_pid:
8.400 + os.kill(self.child_pid, signal.SIGTERM)
8.401 + self.child_pid = None
8.402 +
8.403 + if self.gst_pid:
8.404 + os.kill(self.gst_pid.pid, signal.SIGTERM)
8.405 + self.gst_pid = None
8.406 +
8.407 + self.do_cleanup()
8.408 +
8.409 + os.wait()
8.410 +
8.411 + except Exception, e:
8.412 + log.error("Stop error: %s" % e)
8.413 +
8.414 + # stop()
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
9.2 +++ b/gmyth-stream/server/0.1/plugins/media/vlc.py Wed Apr 18 15:59:10 2007 +0100
9.3 @@ -0,0 +1,80 @@
9.4 +import os
9.5 +import sys
9.6 +import time
9.7 +import socket
9.8 +import ConfigParser
9.9 +
9.10 +class Media:
9.11 +
9.12 + def __init__(self, config):
9.13 +
9.14 + self.config = config
9.15 + self.pipe = ""
9.16 + self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
9.17 +
9.18 + self.path = config.get("Vlc", "path")
9.19 + self.host = config.get("Vlc", "host")
9.20 + self.port = int(config.get("Vlc", "port"))
9.21 + self.pwd = config.get("Vlc", "pwd")
9.22 +
9.23 + # exec VLC
9.24 + pid = os.fork()
9.25 + if (pid == 0):
9.26 + #child
9.27 + print "ESTOU EM CHILD"
9.28 + self.path += " -I telnet -d 1> /dev/null 2> /dev/null &"
9.29 + os.system(self.path)
9.30 + sys.exit(0)
9.31 + else:
9.32 + print "ESTOU EM PARENT 1"
9.33 + time.sleep(3)
9.34 + print "ESTOU EM PARENT 2"
9.35 + self.sock.connect( (self.host, self.port) )
9.36 + self.sock.send("%s\n" % self.pwd)
9.37 +
9.38 +
9.39 + def insert_file(self, filename):
9.40 +
9.41 + self.sock.send("setup output0 input %s\n" % filename)
9.42 +
9.43 +
9.44 +
9.45 + def setup(self, filename, mux, vcodec, vbitrate,\
9.46 + fps, acodec, abitrate, width, height, port):
9.47 +
9.48 + self.filename = filename
9.49 + self.mux = mux
9.50 + self.vcodec = vcodec
9.51 + self.vbitrate = int(vbitrate)
9.52 + self.fps = int(fps)
9.53 + self.acodec = acodec
9.54 + self.abitrate = int(abitrate)
9.55 + self.width = int(width)
9.56 + self.height = int(height)
9.57 +
9.58 + self.port = int(port)
9.59 +
9.60 +
9.61 + self.pipe = "#transcode{vcodec=%s,vb=%d,"\
9.62 + "fps=25.0,scale=1,acodec=mpga,"\
9.63 + "ab=64,channels=1,width=%d,height=%d}"\
9.64 + ":duplicate{dst=std{access=http,"\
9.65 + "mux=mpeg1,dst=:%d}}" % (self.vcodec, self.vbitrate,\
9.66 + self.widht, self.height,\
9.67 + self.port)
9.68 +
9.69 + self.sock.send("setup output0 broadcast %s\n" % self.pipe)
9.70 + self.insert_file(self.filename)
9.71 +
9.72 + def play(self):
9.73 +
9.74 + print "Trying to play: %s" % self.pipe
9.75 + self.sock.send("control output0 play\n")
9.76 +
9.77 +
9.78 + def stop(self):
9.79 +
9.80 + print "Trying to stop: %s" % self.pipe
9.81 + self.sock.send("control output0 stop\n")
9.82 +
9.83 +
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
10.2 +++ b/gmyth-stream/server/0.1/stream.conf Wed Apr 18 15:59:10 2007 +0100
10.3 @@ -0,0 +1,23 @@
10.4 +[Comm]
10.5 +engine = tcp
10.6 +port = 50000
10.7 +
10.8 +
10.9 +[Media]
10.10 +engine = mencoder
10.11 +
10.12 +
10.13 +[Vlc]
10.14 +path = /usr/local/bin/vlc
10.15 +host = 127.0.0.1
10.16 +port = 4212
10.17 +pwd = admin
10.18 +
10.19 +
10.20 +[FFmpeg]
10.21 +path = /usr/local/bin/ffmpeg
10.22 +
10.23 +
10.24 +[Mencoder]
10.25 +path = /usr/local/bin/mencoder
10.26 +fifo_path = /tmp/teste
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
11.2 +++ b/gmyth-stream/server/0.1/tests/client.py Wed Apr 18 15:59:10 2007 +0100
11.3 @@ -0,0 +1,51 @@
11.4 +import os
11.5 +import sys
11.6 +import time
11.7 +import socket
11.8 +
11.9 +
11.10 +if len(sys.argv) < 2:
11.11 + HOST = 'localhost'
11.12 + PORT = 50000
11.13 +elif len(sys.argv) == 2:
11.14 + HOST = sys.argv[1]
11.15 + PORT = 50000
11.16 +else:
11.17 + HOST = sys.argv[1]
11.18 + PORT = int(sys.argv[2])
11.19 +
11.20 +socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
11.21 +socket.settimeout(10)
11.22 +
11.23 +try:
11.24 + socket.connect( (HOST,PORT) )
11.25 +except:
11.26 + print "\n--> Could not connect to ('%s':'%d')\n" % (HOST,PORT)
11.27 + sys.exit(-1)
11.28 +
11.29 +
11.30 +mplayer = os.popen("which mplayer").read().strip()
11.31 +mplayer += " -idx - -vo x11 1> /dev/null"
11.32 +pin, pout = os.popen2(mplayer)
11.33 +
11.34 +#teste = open("teste.avi", "w")
11.35 +
11.36 +data = socket.recv(4096)
11.37 +i = 0
11.38 +
11.39 +while (data != ""):
11.40 + pin.write(data)
11.41 + #teste.write(data)
11.42 + data = socket.recv(4096)
11.43 + #if (i == 500):
11.44 + # socket.send("OK")
11.45 + i += 1
11.46 +
11.47 +pin.close()
11.48 +socket.close()
11.49 +#teste.close()
11.50 +
11.51 +# from select import select
11.52 +# r, w, x = select([pout], []. [], 0)
11.53 +# if pout in r:
11.54 +# pout.read(32)
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
12.2 +++ b/gmyth-stream/server/0.2/gms.py Wed Apr 18 15:59:10 2007 +0100
12.3 @@ -0,0 +1,20 @@
12.4 +#!/usr/bin/env python
12.5 +
12.6 +import sys
12.7 +import os
12.8 +import logging as log
12.9 +from lib.server import serve_forever, load_plugins_transcoders
12.10 +
12.11 +log_level = log.INFO
12.12 +for p in sys.argv[1:]:
12.13 + if p == "-v" or p == "--verbose":
12.14 + log_level -= 10
12.15 +
12.16 +log.basicConfig(level=log_level,
12.17 + format=("### %(asctime)s %(name)-18s %(levelname)-8s "
12.18 + "\t%(message)s"),
12.19 + datefmt="%Y-%m-%d %H:%M:%S")
12.20 +
12.21 +pd = os.path.join("plugins", "transcoders")
12.22 +load_plugins_transcoders(pd)
12.23 +serve_forever()
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
13.2 +++ b/gmyth-stream/server/0.2/lib/server.py Wed Apr 18 15:59:10 2007 +0100
13.3 @@ -0,0 +1,464 @@
13.4 +#!/usr/bin/env python
13.5 +
13.6 +__author__ = "Gustavo Sverzut Barbieri / Artur Duque de Souza"
13.7 +__author_email__ = "barbieri@gmail.com / artur.souza@indt.org.br"
13.8 +__license__ = "GPL"
13.9 +__version__ = "0.3"
13.10 +
13.11 +import os
13.12 +import threading
13.13 +import SocketServer
13.14 +import BaseHTTPServer
13.15 +import socket
13.16 +import urlparse
13.17 +import cgi
13.18 +import lib.utils as utils
13.19 +import logging as log
13.20 +
13.21 +__all__ = ("Transcoder", "RequestHandler", "Server", "serve_forever",
13.22 + "load_plugins_transcoders")
13.23 +
13.24 +class Transcoder(object):
13.25 + log = log.getLogger("gmyth-stream.transcoder")
13.26 + priority = 0 # negative values have higher priorities
13.27 + name = None # to be used in requests
13.28 +
13.29 + def __init__(self, params):
13.30 + self.params = params
13.31 + # __init__()
13.32 +
13.33 +
13.34 + def params_first(self, key, default=None):
13.35 + if default is None:
13.36 + return self.params[key][0]
13.37 + else:
13.38 + try:
13.39 + return self.params[key][0]
13.40 + except:
13.41 + return default
13.42 + # params_first()
13.43 +
13.44 +
13.45 + def get_mimetype(self):
13.46 + mux = self.params_first("mux", "mpg")
13.47 +
13.48 + if mux == "mpeg":
13.49 + return "video/mpeg"
13.50 + elif mux == "avi":
13.51 + return "video/x-msvideo"
13.52 + else:
13.53 + return "application/octet-stream"
13.54 + # get_mimetype()
13.55 +
13.56 +
13.57 + def start(self, outfile):
13.58 + return True
13.59 + # start()
13.60 +
13.61 +
13.62 + def stop(self):
13.63 + return Tru
13.64 + # stop()
13.65 +
13.66 +
13.67 + def __str__(self):
13.68 + return '%s("%s", mux="%s", params=%s)' % \
13.69 + (self.__class__.__name__,
13.70 + self.params_first("uri", "None"),
13.71 + self.params_first("mux", "mpg"),
13.72 + self.params)
13.73 + # __str__()
13.74 +# Transcoder
13.75 +
13.76 +
13.77 +
13.78 +class RequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
13.79 + log = log.getLogger("gmyth-stream.request")
13.80 + def_transcoder = None
13.81 + transcoders = utils.PluginSet(Transcoder)
13.82 +
13.83 + @classmethod
13.84 + def load_plugins_transcoders(cls, directory):
13.85 + cls.transcoders.load_from_directory(directory)
13.86 +
13.87 + if cls.def_transcoder is None and cls.transcoders:
13.88 + cls.def_transcoder = cls.transcoders[0].name
13.89 + # load_plugins_transcoders()
13.90 +
13.91 +
13.92 + def do_dispatch(self, body):
13.93 + self.url = self.path
13.94 +
13.95 + pieces = urlparse.urlparse(self.path)
13.96 + self.path = pieces[2]
13.97 + self.query = cgi.parse_qs(pieces[4])
13.98 +
13.99 + if self.path == "/":
13.100 + self.serve_main(body)
13.101 + elif self.path == "/shutdown.do":
13.102 + self.serve_shutdown(body)
13.103 + elif self.path == "/stop-transcoder.do":
13.104 + self.serve_stop_transcoder(body)
13.105 + elif self.path == "/status.do":
13.106 + self.serve_status(body)
13.107 + elif self.path == "/play.do":
13.108 + self.serve_play(body)
13.109 + elif self.path == "/stream.do":
13.110 + self.serve_stream(body)
13.111 + else:
13.112 + self.send_error(404, "File not found")
13.113 + # do_dispatch()
13.114 +
13.115 +
13.116 + def do_GET(self):
13.117 + self.do_dispatch(True)
13.118 + # do_GET()
13.119 +
13.120 +
13.121 + def do_HEAD(self):
13.122 + self.do_dispatch(False)
13.123 + # do_HEAD()
13.124 +
13.125 +
13.126 + def _nav_items(self):
13.127 + self.wfile.write("""\
13.128 + <li><a href="/play.do">Play</a></li>
13.129 + <li><a href="/status.do">Status</a></li>
13.130 + <li><a href="/stop-transcoder.do">Stop transcoders</a></li>
13.131 + <li><a href="/shutdown.do">Shutdown Server</a></li>
13.132 +""")
13.133 + # _nav_items()
13.134 +
13.135 +
13.136 + def serve_main(self, body):
13.137 + self.send_response(200)
13.138 + self.send_header("Content-Type", "text/html")
13.139 + self.send_header('Connection', 'close')
13.140 + self.end_headers()
13.141 + if body:
13.142 + self.wfile.write("""\
13.143 +<html>
13.144 + <head><title>Catota Server</title></head>
13.145 + <body>
13.146 +<h1>Welcome to Catota Server</h1>
13.147 +<ul>
13.148 +""")
13.149 + self._nav_items()
13.150 + self.wfile.write("""\
13.151 +</ul>
13.152 + </body>
13.153 +</html>
13.154 +""")
13.155 + # serve_main()
13.156 +
13.157 +
13.158 + def serve_play(self, body):
13.159 + self.send_response(200)
13.160 + self.send_header("Content-Type", "text/html")
13.161 + self.send_header('Connection', 'close')
13.162 + self.end_headers()
13.163 + if body:
13.164 + self.wfile.write("""\
13.165 +<html>
13.166 + <head><title>Catota Server</title></head>
13.167 + <body>
13.168 + <h1>Play</h1>
13.169 + <form action="/stream.do" method="GET">
13.170 + <input type="text" name="type" value="file" />://<input type="text" name="location" value=""/>
13.171 + <input type="submit" />
13.172 + </form>
13.173 + <ul>
13.174 +""")
13.175 + self._nav_items()
13.176 + self.wfile.write("""\
13.177 + </ul>
13.178 + </body>
13.179 +</html>
13.180 +""")
13.181 + # serve_play()
13.182 +
13.183 +
13.184 + def serve_shutdown(self, body):
13.185 + self.send_response(200)
13.186 + self.send_header("Content-Type", "text/html")
13.187 + self.send_header('Connection', 'close')
13.188 + self.end_headers()
13.189 + if body:
13.190 + self.wfile.write("""\
13.191 +<html>
13.192 + <head><title>Catota Server Exited</title></head>
13.193 + <body>
13.194 + <h1>Catota is not running anymore</h1>
13.195 + </body>
13.196 +</html>
13.197 +""")
13.198 + self.server.server_close()
13.199 + # serve_shutdown()
13.200 +
13.201 +
13.202 + def serve_stop_all_transcoders(self, body):
13.203 + self.send_response(200)
13.204 + self.send_header("Content-Type", "text/html")
13.205 + self.send_header('Connection', 'close')
13.206 + self.end_headers()
13.207 + if body:
13.208 + self.server.stop_transcoders()
13.209 + self.wfile.write("""\
13.210 +<html>
13.211 + <head><title>Catota Server Stopped Transcoders</title></head>
13.212 + <body>
13.213 + <h1>Catota stopped running transcoders</h1>
13.214 + <ul>
13.215 +""")
13.216 + self._nav_items()
13.217 + self.wfile.write("""\
13.218 + </ul>
13.219 + </body>
13.220 +</html>
13.221 + """)
13.222 + # serve_stop_all_transcoders()
13.223 +
13.224 +
13.225 + def serve_stop_selected_transcoders(self, body, requests):
13.226 + self.send_response(200)
13.227 + self.send_header("Content-Type", "text/html")
13.228 + self.send_header('Connection', 'close')
13.229 + self.end_headers()
13.230 + if body:
13.231 + self.wfile.write("""\
13.232 +<html>
13.233 + <head><title>Catota Server Stopped Transcoders</title></head>
13.234 + <body>
13.235 + <h1>Catota stopped running transcoders:</h1>
13.236 + <ul>
13.237 + """)
13.238 + transcoders = self.server.get_transcoders()
13.239 +
13.240 + for req in requests:
13.241 + try:
13.242 + host, port = req.split(":")
13.243 + except IndexError:
13.244 + continue
13.245 +
13.246 + port = int(port)
13.247 + addr = (host, port)
13.248 +
13.249 + for t, r in transcoders:
13.250 + if r.client_address == addr:
13.251 + t.stop()
13.252 + self.server.del_transcoders(self, t)
13.253 + self.wfile.write("""\
13.254 + <li>%s: %s:%s</li>
13.255 +""" % (t, addr[0], addr[1]))
13.256 + t.stop()
13.257 + break
13.258 + self.wfile.write("""\
13.259 + </ul>
13.260 + <ul>
13.261 +""")
13.262 + self._nav_items()
13.263 + self.wfile.write("""\
13.264 + </ul>
13.265 + </body>
13.266 +</html>
13.267 +""")
13.268 + # serve_stop_selected_transcoders()
13.269 +
13.270 +
13.271 + def serve_stop_transcoder(self, body):
13.272 + req = self.query.get("request", None)
13.273 + if req and "all" in req:
13.274 + self.serve_stop_all_transcoders(body)
13.275 + elif req:
13.276 + self.serve_stop_selected_transcoders(body, req)
13.277 + else:
13.278 + self.serve_status(body)
13.279 + # serve_stop_transcoder()
13.280 +
13.281 +
13.282 + def serve_status(self, body):
13.283 + self.send_response(200)
13.284 + self.send_header("Content-Type", "text/html")
13.285 + self.send_header('Connection', 'close')
13.286 + self.end_headers()
13.287 + if body:
13.288 + self.wfile.write("""\
13.289 +<html>
13.290 + <head><title>Catota Server Status</title></head>
13.291 + <body>
13.292 + <h1>Catota Status</h1>
13.293 +""")
13.294 + tl = self.server.get_transcoders()
13.295 + if not tl:
13.296 + self.wfile.write("<p>No running transcoder.</p>\n")
13.297 + else:
13.298 + self.wfile.write("<p>Running transcoders:</p>\n")
13.299 + self.wfile.write("""\
13.300 + <ul>
13.301 + <li><a href="/stop-transcoder.do?request=all">[STOP ALL]</a></li>
13.302 +""")
13.303 + for transcoder, request in tl:
13.304 + self.wfile.write("""\
13.305 + <li>%s: %s:%s <a href="/stop-transcoder.do?request=%s:%s">[STOP]</a></li>
13.306 +""" % (transcoder, request.client_address[0], request.client_address[1],
13.307 + request.client_address[0], request.client_address[1]))
13.308 +
13.309 + self.wfile.write("""\
13.310 + </ul>
13.311 + <ul>
13.312 +""")
13.313 + self._nav_items()
13.314 + self.wfile.write("""\
13.315 + </ul>
13.316 + </body>
13.317 +</html>
13.318 +""")
13.319 + # serve_status()
13.320 +
13.321 +
13.322 + def _get_transcoder(self):
13.323 + # get transcoder option: mencoder is the default
13.324 + request_transcoders = self.query.get("transcoder", ["mencoder"])
13.325 +
13.326 + for t in request_transcoders:
13.327 + transcoder = self.transcoders.get(t)
13.328 + if transcoder:
13.329 + return transcoder
13.330 +
13.331 + if not transcoder:
13.332 + return self.transcoders[self.def_transcoder]
13.333 + # _get_transcoder()
13.334 +
13.335 +
13.336 + def serve_stream(self, body):
13.337 + transcoder = self._get_transcoder()
13.338 + try:
13.339 + obj = transcoder(self.query)
13.340 + except Exception, e:
13.341 + self.send_error(500, str(e))
13.342 + return
13.343 +
13.344 + self.send_response(200)
13.345 + self.send_header("Content-Type", obj.get_mimetype())
13.346 + self.send_header('Connection', 'close')
13.347 + self.end_headers()
13.348 +
13.349 + if body:
13.350 + self.server.add_transcoders(self, obj)
13.351 + obj.start(self.wfile)
13.352 + self.server.del_transcoders(self, obj)
13.353 + # serve_stream()
13.354 +
13.355 +
13.356 + def log_request(self, code='-', size='-'):
13.357 + self.log.info('"%s" %s %s', self.requestline, str(code), str(size))
13.358 + # log_request()
13.359 +
13.360 +
13.361 + def log_error(self, format, *args):
13.362 + self.log.error("%s: %s" % (self.address_string(), format % args))
13.363 + # log_error()
13.364 +
13.365 +
13.366 + def log_message(self, format, *args):
13.367 + self.log.info("%s: %s" % (self.address_string(), format % args))
13.368 + # log_message()
13.369 +# RequestHandler
13.370 +
13.371 +
13.372 +
13.373 +class Server(SocketServer.ThreadingMixIn, BaseHTTPServer.HTTPServer):
13.374 + log = log.getLogger("gmyth-streamer.server")
13.375 + run = True
13.376 + _transcoders = {}
13.377 + _lock = threading.RLock()
13.378 +
13.379 + def serve_forever(self):
13.380 + self.log.info("GMyth-Streamer serving HTTP on %s:%s" %
13.381 + self.socket.getsockname())
13.382 + try:
13.383 + while self.run:
13.384 + self.handle_request()
13.385 + except KeyboardInterrupt, e:
13.386 + pass
13.387 +
13.388 + self.log.debug("Stopping all remaining transcoders...")
13.389 + self.stop_transcoders()
13.390 + self.log.debug("Transcoders stopped!")
13.391 + # serve_forever()
13.392 +
13.393 +
13.394 + def get_request(self):
13.395 + skt = self.socket
13.396 + old = skt.gettimeout()
13.397 + skt.settimeout(0.5)
13.398 + while self.run:
13.399 + try:
13.400 + r = skt.accept()
13.401 + skt.settimeout(old)
13.402 + return r
13.403 + except socket.timeout, e:
13.404 + pass
13.405 + raise socket.error("Not running")
13.406 + # get_request()
13.407 +
13.408 +
13.409 + def server_close(self):
13.410 + self.run = False
13.411 + self.stop_transcoders()
13.412 +
13.413 + BaseHTTPServer.HTTPServer.server_close(self)
13.414 + # server_close()
13.415 +
13.416 +
13.417 + def stop_transcoders(self):
13.418 + self._lock.acquire()
13.419 + for transcoder, request in self._transcoders.iteritems():
13.420 + self.log.info("Stop transcoder: %s, client=%s" %
13.421 + (transcoder, request.client_address))
13.422 + transcoder.stop()
13.423 + self._lock.release()
13.424 + # stop_transcoders()
13.425 +
13.426 +
13.427 + def get_transcoders(self):
13.428 + self._lock.acquire()
13.429 + try:
13.430 + return self._transcoders.items()
13.431 + finally:
13.432 + self._lock.release()
13.433 + # get_transcoders()
13.434 +
13.435 +
13.436 + def add_transcoders(self, request, transcoder):
13.437 + self._lock.acquire()
13.438 + try:
13.439 + self._transcoders[transcoder] = request
13.440 + finally:
13.441 + self._lock.release()
13.442 + # add_transcoders()
13.443 +
13.444 +
13.445 + def del_transcoders(self, request, transcoder):
13.446 + self._lock.acquire()
13.447 + try:
13.448 + del self._transcoders[transcoder]
13.449 + finally:
13.450 + self._lock.release()
13.451 + # del_transcoders()
13.452 +# Server
13.453 +
13.454 +
13.455 +
13.456 +def serve_forever(host="0.0.0.0", port=40000):
13.457 + addr = (host, port)
13.458 +
13.459 + RequestHandler.protocol_version = "HTTP/1.0"
13.460 + httpd = Server(addr, RequestHandler)
13.461 + httpd.serve_forever()
13.462 +# serve_forever()
13.463 +
13.464 +
13.465 +def load_plugins_transcoders(directory):
13.466 + RequestHandler.load_plugins_transcoders(directory)
13.467 +# load_plugins_transcoders()
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
14.2 +++ b/gmyth-stream/server/0.2/lib/utils.py Wed Apr 18 15:59:10 2007 +0100
14.3 @@ -0,0 +1,148 @@
14.4 +#!/usr/bin/env
14.5 +
14.6 +__author__ = "Gustavo Sverzut Barbieri / Artur Duque de Souza"
14.7 +__author_email__ = "barbieri@gmail.com / artur.souza@indt.org.br"
14.8 +__license__ = "GPL"
14.9 +__version__ = "0.3"
14.10 +
14.11 +import os
14.12 +import stat
14.13 +import sys
14.14 +import logging
14.15 +import urllib
14.16 +import gobject
14.17 +import imp
14.18 +
14.19 +log = logging.getLogger("gmyth-stream.utils")
14.20 +
14.21 +__all__ = ("which", "load_plugins", "PluginSet")
14.22 +
14.23 +def which(app):
14.24 + """function to implement which(1) unix command"""
14.25 + pl = os.environ["PATH"].split(os.pathsep)
14.26 + for p in pl:
14.27 + path = os.path.join(p, app)
14.28 + if os.path.isfile(path):
14.29 + st = os.stat(path)
14.30 + if st[stat.ST_MODE] & 0111:
14.31 + return path
14.32 + return ""
14.33 +# which()
14.34 +
14.35 +
14.36 +def _load_module(pathlist, name):
14.37 + fp, path, desc = imp.find_module(name, pathlist)
14.38 + try:
14.39 + module = imp.load_module(name, fp, path, desc)
14.40 + return module
14.41 + finally:
14.42 + if fp:
14.43 + fp.close()
14.44 +# _load_module()
14.45 +
14.46 +
14.47 +class PluginSet(object):
14.48 + def __init__(self, basetype, *items):
14.49 + self.basetype = basetype
14.50 + self.map = {}
14.51 + self.list = []
14.52 +
14.53 + for i in items:
14.54 + self._add(i)
14.55 + self._sort()
14.56 + # __init__()
14.57 +
14.58 +
14.59 + def _add(self, item):
14.60 + self.map[item.name] = item
14.61 + self.list.append(item)
14.62 + # _add()
14.63 +
14.64 +
14.65 + def add(self, item):
14.66 + self._add()
14.67 + self._sort()
14.68 + # add()
14.69 +
14.70 +
14.71 + def __getitem__(self, spec):
14.72 + if isinstance(spec, basestring):
14.73 + return self.map[spec]
14.74 + else:
14.75 + return self.list[spec]
14.76 + # __getitem__()
14.77 +
14.78 +
14.79 + def get(self, name, default=None):
14.80 + self.map.get(name, default)
14.81 + # get()
14.82 +
14.83 +
14.84 + def __iter__(self):
14.85 + return self.list.__iter__()
14.86 + # __iter__()
14.87 +
14.88 +
14.89 + def __len__(self):
14.90 + return len(self.list)
14.91 + # __len__()
14.92 +
14.93 +
14.94 + def _sort(self):
14.95 + self.list.sort(lambda a, b: cmp(a.priority, b.priority))
14.96 + # _sort()
14.97 +
14.98 +
14.99 + def update(self, pluginset):
14.100 + self.map.update(pluginset.map)
14.101 + self.list.extend(pluginset.list)
14.102 + self._sort()
14.103 + # update()
14.104 +
14.105 +
14.106 + def load_from_directory(self, directory):
14.107 + for i in load_plugins(directory, self.basetype):
14.108 + self._add(i)
14.109 + self._sort()
14.110 + # load_from_directory()
14.111 +
14.112 +
14.113 + def __str__(self):
14.114 + lst = []
14.115 + for o in self.list:
14.116 + lst.append('"%s" (%s)' % (o.name, o.__name__))
14.117 +
14.118 + return "%s(basetype=%s, items=[%s])" % \
14.119 + (self.__class__.__name__,
14.120 + self.basetype.__name__,
14.121 + ", ".join(lst))
14.122 + # __str__()
14.123 +# PluginSet
14.124 +
14.125 +
14.126 +def load_plugins(directory, basetype):
14.127 + tn = basetype.__name__
14.128 + log.debug("Loading plugins from %s, type=%s" % (directory, tn))
14.129 +
14.130 +
14.131 + plugins = []
14.132 + for d in os.listdir(directory):
14.133 + if not d.endswith(".py"):
14.134 + continue
14.135 +
14.136 + name = d[0: -3]
14.137 + if name == "__init__":
14.138 + continue
14.139 +
14.140 + directory.replace(os.path.sep, ".")
14.141 + mod = _load_module([directory], name)
14.142 + for sym in dir(mod):
14.143 + cls = getattr(mod, sym)
14.144 + if isinstance(cls, type) and issubclass(cls, basetype) and \
14.145 + cls != basetype:
14.146 + plugins.append(cls)
14.147 + log.info("Loaded %s (%s) from %s" % \
14.148 + (cls.__name__, tn, os.path.join(directory, d)))
14.149 +
14.150 + return plugins
14.151 +# load_plugins()
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
15.2 +++ b/gmyth-stream/server/0.2/plugins/transcoders/gstreamer.py Wed Apr 18 15:59:10 2007 +0100
15.3 @@ -0,0 +1,305 @@
15.4 +#vim:ts=4:sw=4:et
15.5 +import pygst
15.6 +pygst.require("0.10")
15.7 +import gst
15.8 +import gobject
15.9 +import time
15.10 +import lib.utils as utils
15.11 +import lib.server as server
15.12 +
15.13 +from threading import Thread
15.14 +
15.15 +__all__ = ("TranscoderGstreamer",)
15.16 +
15.17 +class TranscoderGstreamer(server.Transcoder):
15.18 + gstreamer_path = utils.which("gst-launch-0.10")
15.19 + name = "gstreamer"
15.20 + priority = -2
15.21 +
15.22 + # StreamListener()
15.23 +
15.24 + class StreamData:
15.25 + stream_count = 0
15.26 +
15.27 + def __init__(self, log, pipe, abin, vbin, sink):
15.28 + self.log = log
15.29 + self.stream_count += 1
15.30 + self.Id = self.stream_count
15.31 + self.Pipe = pipe
15.32 + self.Abin = abin
15.33 + self.Vbin = vbin
15.34 + self.Sink = sink
15.35 + self.Loop = gobject.MainLoop()
15.36 + self.ACaps = ""
15.37 + self.VCaps = ""
15.38 + self.Ready = False
15.39 + self.Connection = None
15.40 + self.Addr = None
15.41 + # __init__()
15.42 +
15.43 + # StreamData()
15.44 +
15.45 +
15.46 + def __init__(self, params):
15.47 + server.Transcoder.__init__(self, params)
15.48 + # set gstreamer basic options
15.49 + self.connection = None
15.50 + self.addr = None
15.51 + self.ready = False
15.52 + self.quit = False
15.53 +
15.54 + self.log.info("Params for Gstreamer: %s" % self.params)
15.55 + # __init__()
15.56 +
15.57 +
15.58 + def _create_start_elements(self, uri):
15.59 + self.log.info("Opening Uri:" + uri)
15.60 + src = gst.element_make_from_uri(gst.URI_SRC, uri, "src")
15.61 + decode = gst.element_factory_make("decodebin", "decode")
15.62 + mux = gst.element_factory_make("avimux", "mux")
15.63 + sink = gst.element_factory_make("fdsink", "sink")
15.64 +
15.65 + return [src, decode, mux, sink]
15.66 + # _create_start_elements()
15.67 +
15.68 +
15.69 + def _setup_video_encode(self, vbin, width, height):
15.70 + vqueue = gst.element_factory_make("queue", "vqueue")
15.71 + colorspace = gst.element_factory_make("ffmpegcolorspace", "")
15.72 + vrate = gst.element_factory_make("videorate", "vrate")
15.73 + vencode = gst.element_factory_make("ffenc_mpeg4", "vencode")
15.74 + vqueue_src = gst.element_factory_make("queue", "vqueue_src")
15.75 +
15.76 + vencode.set_property("bitrate", 200)
15.77 +
15.78 + if None in [vbin, vqueue, vrate, vencode, vqueue_src]:
15.79 + self.log.info("Fail to create video encode elements.")
15.80 + return False
15.81 +
15.82 + vbin.add(vqueue)
15.83 + if int(width) > 0 and int(height) > 0:
15.84 + self.log.info(("Formating output to %d / %d" %(int(width), int(height))))
15.85 +
15.86 + vscale = gst.element_factory_make("ffvideoscale", "vscale")
15.87 +
15.88 + vbin.add(vscale);
15.89 + if not vqueue.link(vscale):
15.90 + self.log.info("Fail to link video elements")
15.91 + return False
15.92 +
15.93 + vbin.add(colorspace)
15.94 +
15.95 + if not vscale.link(colorspace, \
15.96 + gst.caps_from_string("video/x-raw-yuv,width=(int)%d,height=(int)%d" %(\
15.97 + int(width), int(height)))):
15.98 + self.log.info("Fail to link video elements")
15.99 + return False
15.100 + else:
15.101 + vbin.add(colorspace)
15.102 + vqueue.link(colorspace)
15.103 +
15.104 + vbin.add(vrate, vencode, vqueue_src)
15.105 + if not colorspace.link(vrate):
15.106 + self.log.info("Fail to colorspace with vrate")
15.107 + return False
15.108 +
15.109 + if not vrate.link(vencode, \
15.110 + gst.caps_from_string("video/x-raw-yuv,framerate=(fraction)10/1")):
15.111 + self.log.info("Fail to link vrate element")
15.112 + return False
15.113 +
15.114 + if not vencode.link(vqueue_src):
15.115 + self.log.info("Fail to link video encode with queue")
15.116 + return False
15.117 +
15.118 + vbin.add_pad(gst.GhostPad("sink", vqueue.get_pad("sink")))
15.119 + vbin.add_pad(gst.GhostPad("src", vqueue_src.get_pad("src")))
15.120 +
15.121 + return True
15.122 + # _setup_video_encode()
15.123 +
15.124 +
15.125 + def _setup_audio_encode(self, abin):
15.126 + aqueue = gst.element_factory_make("queue", "aqueue")
15.127 + aconvert = gst.element_factory_make("audioconvert", "aconvert")
15.128 + arate = gst.element_factory_make("audioresample", "arate")
15.129 + aencode = gst.element_factory_make("queue", "aencode")
15.130 + aqueue_src = gst.element_factory_make("queue", "aqueue_src")
15.131 +
15.132 + if None in [abin, aqueue, arate, aencode, aqueue_src]:
15.133 + self.log.info("Fail to create video encode elements.")
15.134 + return False
15.135 +
15.136 + abin.add(aqueue, aconvert, arate, aencode, aqueue_src)
15.137 +
15.138 + if not gst.element_link_many(aqueue, aconvert, arate, aencode, aqueue_src):
15.139 + self.log.info("Fail to link video elements")
15.140 + return False
15.141 +
15.142 + abin.add_pad(gst.GhostPad("sink", aqueue.get_pad("sink")))
15.143 + abin.add_pad(gst.GhostPad("src", aqueue_src.get_pad("src")))
15.144 +
15.145 + return True
15.146 + # _setup_audio_encode()
15.147 +
15.148 +
15.149 + def setup(self, uri, mux, vcodec, vbitrate,
15.150 + fps, acodec, abitrate, width, height, options):
15.151 +
15.152 + ## Pipelines
15.153 + pipe = gst.Pipeline()
15.154 + src, decode, mux, sink = self._create_start_elements(uri)
15.155 +
15.156 + if None in [src, decode, mux, sink]:
15.157 + self.log.info("Problems with while starting basic elements");
15.158 + return False
15.159 +
15.160 + #video encode
15.161 + #queue ! videoscale ! video/x-raw-yuv,width=240,height=144 ! videorate !
15.162 + #ffenc_h263p bitrate=256000 me-method=2 ! rtph263ppay ! udpsink host=224.0.0.1
15.163 + #port=5000
15.164 +
15.165 + vbin = gst.Bin()
15.166 + if not self._setup_video_encode(vbin, width, height):
15.167 + return False
15.168 +
15.169 + #audio encode
15.170 + #audio/x-raw-int ! queue ! audioconvert ! faac ! rtpmp4gpay !
15.171 + #udpsink name=upd_audio host=224.0.0.1 port=5002
15.172 +
15.173 + abin = gst.Bin()
15.174 + if not self._setup_audio_encode(abin):
15.175 + return False
15.176 +
15.177 + #Finish Pipeline
15.178 + pipe.add(src, decode, abin, vbin, mux, sink)
15.179 + gst.element_link_many(src, decode)
15.180 + gst.element_link_many(mux, sink)
15.181 +
15.182 + #Linking decode with mux
15.183 + mux_audio = mux.get_pad("audio_0")
15.184 + mux_video = mux.get_pad("video_0")
15.185 +
15.186 + audio_pad = abin.get_pad("src")
15.187 + video_pad = vbin.get_pad("src")
15.188 +
15.189 + if audio_pad.link(mux_audio) != gst.PAD_LINK_OK:
15.190 + self.log.info("Fail to link audio with mux")
15.191 + return False
15.192 +
15.193 + if video_pad.link(mux_video) != gst.PAD_LINK_OK:
15.194 + self.log.info("Fail to link audio with mux")
15.195 + return False
15.196 +
15.197 + self.stream_data = self.StreamData(self.log, pipe, abin, vbin, sink)
15.198 + bus = pipe.get_bus()
15.199 + bus.add_signal_watch()
15.200 + bus.connect("message", self.__on_bus_message, self.stream_data)
15.201 +
15.202 + decode.connect("new-decoded-pad", self.__on_decode_new_pad, self.stream_data)
15.203 + decode.connect("unknown-type", self.__on_decode_unknown_type, self.stream_data)
15.204 +
15.205 + self.log.info("Setting PIPELINE state to PAUSED")
15.206 + pipe.set_state(gst.STATE_PAUSED)
15.207 + self.log.info("Running Loop")
15.208 + self.stream_data.Loop.run()
15.209 + # setup()
15.210 +
15.211 + def __on_bus_message(self, bus, message, stream_data):
15.212 +
15.213 + t = message.type
15.214 +
15.215 + if t == gst.MESSAGE_STATE_CHANGED:
15.216 + oldstate = -1
15.217 + newstate = -1
15.218 + pending = -1
15.219 +
15.220 + oldstate, newstate, pending = message.parse_state_changed()
15.221 +
15.222 + if oldstate == gst.STATE_READY and \
15.223 + newstate == gst.STATE_PAUSED and \
15.224 + pending == gst.STATE_VOID_PENDING and \
15.225 + stream_data.Ready == False:
15.226 +
15.227 + state_changed_status, current_state, pending_state = stream_data.Pipe.get_state()
15.228 + if current_state == gst.STATE_PAUSED and \
15.229 + pending_state == gst.STATE_VOID_PENDING:
15.230 + self.log.info("Pipe paused")
15.231 + stream_data.Loop.quit()
15.232 + stream_data.Ready = True
15.233 +
15.234 + elif t == gst.MESSAGE_EOS:
15.235 + self.log.info("Pipe finished")
15.236 + stream_data.Loop.quit()
15.237 + self.quit = True
15.238 +
15.239 + elif t == gst.MESSAGE_ERROR:
15.240 + err, debug = message.parse_error()
15.241 + self.log.error("Error: %s %s" %(err, debug))
15.242 + stream_data.Loop.quit()
15.243 + stream_data.Ready = False
15.244 +
15.245 + return True
15.246 + # __on_bus_message()
15.247 +
15.248 + def __on_decode_unknown_type(self, decode, pad, caps, stream_data):
15.249 + self.log.info("Unknown Type")
15.250 + return None
15.251 + # __on_decode_unknown_type
15.252 +
15.253 + def __on_decode_new_pad(self, decode, pad, arg1, stream_data):
15.254 +
15.255 + caps = pad.get_caps().to_string()
15.256 + self.log.info("New pad " + caps)
15.257 + if caps.rfind("audio") != -1:
15.258 + apad = stream_data.Abin.get_pad("sink")
15.259 + if pad.link(apad) != gst.PAD_LINK_OK:
15.260 + self.log.info("Error on link audio pad")
15.261 + return None
15.262 + elif caps.rfind("video") != -1:
15.263 + vpad = stream_data.Vbin.get_pad("sink")
15.264 + if pad.link(vpad) != gst.PAD_LINK_OK:
15.265 + self.log.info("Error on link video pad")
15.266 + return None
15.267 + else:
15.268 + self.log.info("Invalid caps")
15.269 + self.log.info("Linked")
15.270 + # __on_decode_new_pad
15.271 +
15.272 +
15.273 + def start(self, outfd):
15.274 + params_first = self.params_first
15.275 +
15.276 + self.setup(params_first("uri", ""), params_first("mux", "avi"),
15.277 + params_first("vcodec", "ffenc_h263p"), params_first("vbitrate", 256000),
15.278 + params_first("fps", 25), params_first("acodec", "faac"),
15.279 + params_first("abitrate", 192000), params_first("width", 320),
15.280 + params_first("height", 240), params_first("options", ""))
15.281 +
15.282 + self.log.info("Play %s", outfd.fileno())
15.283 + self.stream_data.Sink.set_property("fd", outfd.fileno())
15.284 + self.log.info("Setting Pipeline state to PLAYING")
15.285 + self.stream_data.Pipe.set_state(gst.STATE_PLAYING)
15.286 +
15.287 + # keep playing until EOS
15.288 + self.log.info("QUIT: %s" % self.quit)
15.289 +
15.290 + i = 0
15.291 + loop = gobject.MainLoop()
15.292 + loop.run()
15.293 +
15.294 + self.log.info("quit loop")
15.295 +
15.296 + return True
15.297 + # start()
15.298 +
15.299 + def stop(self):
15.300 + self.log.info("Stop stream_data: %s" % self.stream_data)
15.301 +
15.302 + if self.stream_data:
15.303 + self.stream_data.Pipe.set_state(gst.STATE_NULL)
15.304 + self.quit = True
15.305 +
15.306 + del self.stream_data
15.307 + self.stream_data = None
15.308 + # stop
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
16.2 +++ b/gmyth-stream/server/0.2/plugins/transcoders/mencoder.py Wed Apr 18 15:59:10 2007 +0100
16.3 @@ -0,0 +1,123 @@
16.4 +import lib.utils as utils
16.5 +import lib.server as server
16.6 +import os
16.7 +import signal
16.8 +import subprocess
16.9 +
16.10 +__all__ = ("TranscoderMencoder",)
16.11 +
16.12 +class TranscoderMencoder(server.Transcoder):
16.13 + mencoder_path = utils.which("mencoder")
16.14 + def_mencoder_outfile = os.path.join(os.path.sep, "tmp",
16.15 + "mencoder-fifo-%(uid)s-%(pid)s")
16.16 + name = "mencoder"
16.17 + priority = -1
16.18 +
16.19 + def __init__(self, params):
16.20 + server.Transcoder.__init__(self, params)
16.21 + self.proc = None
16.22 + self.args = None
16.23 +
16.24 + vars = {"uid": os.getuid(), "pid": os.getpid()}
16.25 + mencoder_outfile_base = self.def_mencoder_outfile % vars
16.26 + mencoder_outfile = mencoder_outfile_base
16.27 + i = 0
16.28 + while os.path.exists(mencoder_outfile):
16.29 + i += 1
16.30 + mencoder_outfile = mencoder_outfile_base + ".%s" % i
16.31 +
16.32 + self.mencoder_outfile = mencoder_outfile
16.33 + os.mkfifo(self.mencoder_outfile)
16.34 +
16.35 + args = [self.mencoder_path, "-really-quiet",
16.36 + "-o", self.mencoder_outfile]
16.37 +
16.38 + params_first = self.params_first
16.39 +
16.40 + type = params_first("type")
16.41 + location = params_first("location")
16.42 + args.append("%s://%s" % (type, location))
16.43 +
16.44 + mux = params_first("mux", "avi")
16.45 + args.extend(["-of", mux])
16.46 +
16.47 + acodec = params_first("acodec", "mp3")
16.48 + abitrate = params_first("abitrate", "128")
16.49 + if acodec == "mp3lame":
16.50 + args.extend(["-oac", "mp3lame", "-lameopts",
16.51 + "cbr:br=%s" % abitrate])
16.52 + else:
16.53 + args.extend(["-oac", "lavc", "-lavcopts",
16.54 + "acodec=%s:abitrate=%s" % (acodec, abitrate)])
16.55 +
16.56 + vcodec = params_first("vcodec", "mpeg4")
16.57 + vbitrate = params_first("vbitrate", "400")
16.58 + args.extend(["-ovc", "lavc", "-lavcopts",
16.59 + "vcodec=%s:vbitrate=%s" % (vcodec, vbitrate)])
16.60 +
16.61 + fps = params_first("fps", "24")
16.62 + args.extend(["-ofps", fps])
16.63 +
16.64 + width = params_first("width", "320")
16.65 + height = params_first("height", "240")
16.66 + args.extend(["-vf", "scale=%s:%s" % (width, height)])
16.67 +
16.68 + self.args = args
16.69 + # __init__()
16.70 +
16.71 +
16.72 + def _unlink_fifo(self):
16.73 + try:
16.74 + os.unlink(self.mencoder_outfile)
16.75 + except Exception, e:
16.76 + pass
16.77 + # _unlink_fifo()
16.78 +
16.79 +
16.80 + def start(self, outfd):
16.81 + cmd = " ".join(self.args)
16.82 + self.log.info("Mencoder: %s" % cmd)
16.83 +
16.84 + try:
16.85 + self.proc = subprocess.Popen(self.args, close_fds=True)
16.86 + except Exception, e:
16.87 + self.log.error("Error executing mencoder: %s" % cmd)
16.88 + return False
16.89 +
16.90 + try:
16.91 + fifo_read = open(self.mencoder_outfile)
16.92 + except Exception, e:
16.93 + self.log.error("Error opening fifo: %s" % cmd)
16.94 + return False
16.95 +
16.96 + try:
16.97 + while self.proc and self.proc.poll() == None:
16.98 + d = fifo_read.read(1024)
16.99 + outfd.write(d)
16.100 + except Exception, e:
16.101 + self.log.error("Problems handling data: %s" % e)
16.102 + self._unlink_fifo()
16.103 + return False
16.104 +
16.105 + self._unlink_fifo()
16.106 + return True
16.107 + # start()
16.108 +
16.109 +
16.110 + def stop(self):
16.111 + if self.proc:
16.112 + try:
16.113 + os.kill(self.proc.pid, signal.SIGTERM)
16.114 + except OSError, e:
16.115 + pass
16.116 +
16.117 + try:
16.118 + self.proc.wait()
16.119 + except Exception, e:
16.120 + pass
16.121 +
16.122 + self.proc = None
16.123 +
16.124 + self._unlink_fifo()
16.125 + # stop()
16.126 +# TranscoderMencoder
17.1 --- a/gmyth-stream/server/lib.py Wed Apr 18 15:47:40 2007 +0100
17.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
17.3 @@ -1,36 +0,0 @@
17.4 -import time
17.5 -import logging
17.6 -import os
17.7 -import stat
17.8 -
17.9 -ext = ['mpg', 'avi', 'mp4', 'nuv', 'mpeg', 'mov']
17.10 -
17.11 -def now():
17.12 - return time.strftime("%Y-%m-%d %H:%M:%S");
17.13 -
17.14 -def log(msg):
17.15 - logging.log(logging.DEBUG, msg)
17.16 - new_msg = "[%s] %s" % (now(), msg)
17.17 - return new_msg
17.18 -
17.19 -
17.20 -bin_path_list = os.environ["PATH"].split(os.pathsep)
17.21 -def which(prg):
17.22 - for d in bin_path_list:
17.23 - path = os.path.join(d, prg)
17.24 - if os.path.exists(path):
17.25 - st = os.stat(path)
17.26 - if st[stat.ST_MODE] & 0111:
17.27 - return path
17.28 - return ""
17.29 -
17.30 -def list_media_files(directory, file_list):
17.31 - for root, dirs, files in os.walk(directory):
17.32 - for name in files:
17.33 - if os.path.splitext(name)[1].strip(".") in ext:
17.34 - media = os.path.join(root,name)
17.35 - if media not in file_list:
17.36 - file_list.append(os.path.join(root,name))
17.37 -
17.38 - return True
17.39 -
18.1 --- a/gmyth-stream/server/main.py Wed Apr 18 15:47:40 2007 +0100
18.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
18.3 @@ -1,185 +0,0 @@
18.4 -#!/usr/bin/python
18.5 -
18.6 -import os
18.7 -import lib
18.8 -import sys
18.9 -import imp
18.10 -import ConfigParser
18.11 -import logging as log
18.12 -
18.13 -log.basicConfig(level=log.DEBUG,
18.14 - format="%(asctime)s %(levelname)-8s %(message)s",
18.15 - datefmt='%Y-%m-%d %H:%M:%S')
18.16 -
18.17 -config = ConfigParser.ConfigParser()
18.18 -config.read("stream.conf")
18.19 -
18.20 -def load_module(pathlist, name):
18.21 - fp, path, desc = imp.find_module(name, pathlist)
18.22 - try:
18.23 - module = imp.load_module(name, fp, path, desc)
18.24 - return module
18.25 - finally:
18.26 - if fp:
18.27 - fp.close()
18.28 -
18.29 -
18.30 -media_plugin = config.get("Media", "engine")
18.31 -media_plugin_module = load_module(["./plugins/media"], media_plugin)
18.32 -media = media_plugin_module.Media(config)
18.33 -
18.34 -comm_plugin = config.get("Comm", "engine")
18.35 -comm_plugin_module = load_module(["./plugins/comm"], comm_plugin)
18.36 -server = comm_plugin_module.Server(config)
18.37 -
18.38 -log.info("Starting GMyth-Stream server")
18.39 -
18.40 -
18.41 -'''
18.42 -PROTOCOL DESCRIPTION
18.43 -=====================
18.44 -
18.45 -COMMAND OPTIONS
18.46 -
18.47 --> SETUP DESCRIPTION
18.48 -|-> used to setup transcoding and streaming parameters
18.49 -|-> must be used before any "PLAY" command
18.50 -|-> e.g:
18.51 -
18.52 -file://file_name mux vcodec vbitrate fps acodec abitrate width height options
18.53 -dvd://title_number mux vcodec vbitrate fps acodec abitrate width height options
18.54 -
18.55 --> PLAY DESCRIPTION
18.56 - |-> used to start transcoding and streaming of file
18.57 - |-> must be used just if SETUP was used before
18.58 - |-> after it, _must_ send STOP
18.59 -
18.60 --> STOP DESCRIPTION
18.61 - |-> used to stop transcoding and streaming process
18.62 - |-> must be used just if PLAY was used before
18.63 - |-> must be used after PLAY
18.64 -
18.65 --> QUIT DESCRIPTION
18.66 - |-> used to quit the main loop (quit program)
18.67 -
18.68 -'''
18.69 -nextport = 0
18.70 -setup = (False, "STOPPED")
18.71 -
18.72 -def do_setup(server, filename, mux, vcodec, vbitrate, fps, acodec, abitrate,
18.73 - width, height, *options):
18.74 - global nextport
18.75 - global setup
18.76 -
18.77 - if setup[1] != "PLAYING":
18.78 - nextport += 1
18.79 - ret = media.setup(filename, mux, vcodec, vbitrate, fps, acodec,
18.80 - abitrate, width, height, nextport, options)
18.81 - if ret[0]:
18.82 - server.sendOk()
18.83 - else:
18.84 - server.sendNotOk(ret[1])
18.85 -
18.86 - setup = (True, setup[1])
18.87 -
18.88 - else: server.sendNotOk("You must STOP before SETingUP again")
18.89 -
18.90 - return True
18.91 -
18.92 -def do_play(server):
18.93 - global setup
18.94 -
18.95 - if setup[0] and setup[1] == "STOPPED":
18.96 - setup = (setup[0], "PLAYING")
18.97 - ret = media.play()
18.98 - if ret[0]:
18.99 - server.sendOk("%d" % nextport)
18.100 - else:
18.101 - server.sendNotOk(ret[1])
18.102 -
18.103 - else:
18.104 - if setup[1] == "STOPPED":
18.105 - server.sendNotOk("You must SETUP before PLAYing")
18.106 - else:
18.107 - server.sendNotOk("You must STOP before PLAYing again")
18.108 -
18.109 - return True
18.110 -
18.111 -def do_stop(server):
18.112 - global setup
18.113 -
18.114 - media.stop()
18.115 - setup = (False, "STOPPED")
18.116 - server.sendOk()
18.117 - return True
18.118 -
18.119 -def do_list(server, *directory):
18.120 - file_list = []
18.121 - for j in directory:
18.122 - lib.list_media_files(j, file_list)
18.123 -
18.124 - server.sendOk(file_list)
18.125 - return True
18.126 -
18.127 -def do_quit(server):
18.128 - server.finish = 1
18.129 - media.stop()
18.130 - server.sendOk()
18.131 - return True
18.132 -
18.133 -
18.134 -mapping = {
18.135 - "SETUP": do_setup,
18.136 - "PLAY": do_play,
18.137 - "STOP": do_stop,
18.138 - "LIST": do_list,
18.139 - "QUIT": do_quit,
18.140 - }
18.141 -
18.142 -
18.143 -def dispatch(server, msg):
18.144 - pieces = msg.split()
18.145 - if len(pieces) < 1:
18.146 - log.error("Invalid client command format: %r" % msg)
18.147 - server.sendNotOk("Invalid Format")
18.148 - return False
18.149 -
18.150 - cmd = pieces[0]
18.151 - f = mapping.get(cmd, None)
18.152 - if not f:
18.153 - log.error("Unknow command: %r" % msg)
18.154 - server.sendNotOk("Unknow Command")
18.155 - return False
18.156 -
18.157 - try:
18.158 - return f(server, *pieces[1:])
18.159 - except Exception, e:
18.160 - log.error("Could not execute %r: %s" % (msg, e))
18.161 - server.sendNotOk(str(e))
18.162 - return False
18.163 -
18.164 -
18.165 -
18.166 -while not server.finish:
18.167 - conn, client, port = server.getRequest()
18.168 - if nextport == 0:
18.169 - nextport = port
18.170 -
18.171 - while not server.finish:
18.172 - msg = server.getMsg()
18.173 - if not msg:
18.174 - break
18.175 -
18.176 - log.info("Client %s sent command: %r" % (client, msg))
18.177 - dispatch(server, msg)
18.178 -
18.179 - log.info("Closing connection with %s" % (client,))
18.180 - server.disconnect_client(conn)
18.181 - try:
18.182 - os.wait()
18.183 - except Exception, e:
18.184 - log.error(e)
18.185 -
18.186 -server.stop()
18.187 -log.info("Server stopped. Closing...")
18.188 -
19.1 --- a/gmyth-stream/server/plugins/comm/tcp.py Wed Apr 18 15:47:40 2007 +0100
19.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
19.3 @@ -1,79 +0,0 @@
19.4 -import lib
19.5 -import time
19.6 -import socket
19.7 -import logging as log
19.8 -
19.9 -class Server(object):
19.10 -
19.11 - def __init__(self, config):
19.12 - self.host = '0.0.0.0'
19.13 - self.port = int(config.get("Comm", "port"))
19.14 - self.finish = 0
19.15 -
19.16 - addr = (self.host, self.port)
19.17 - log.debug("Setup TCP server at %s:%s" % addr)
19.18 - self.tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
19.19 - self.tcp.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
19.20 - self.tcp.bind(addr)
19.21 - self.tcp.listen(1)
19.22 - log.info("TCP server listening at %s:%s (sock=%d)" %
19.23 - (self.host, self.port, self.tcp.fileno()))
19.24 -
19.25 - def getMsg(self):
19.26 - bytes = []
19.27 - try:
19.28 - while 1:
19.29 - c = self.con.recv(1)
19.30 - bytes.append(c)
19.31 - if not c or c == "\n":
19.32 - break
19.33 - except Exception, e:
19.34 - log.error("Error reading message from client: %s" % e)
19.35 - return None
19.36 -
19.37 - if not bytes or bytes[-1] != "\n":
19.38 - msg = "".join(bytes)
19.39 - log.error("Invalid message from client: %r" % msg)
19.40 - return None
19.41 -
19.42 - # remove \n and \r
19.43 - bytes.pop()
19.44 - if bytes[-1] == "\r":
19.45 - bytes.pop()
19.46 -
19.47 - msg = "".join(bytes)
19.48 - log.debug("RECV: %r" % msg)
19.49 - return msg
19.50 -
19.51 - def sendMsg(self, msg):
19.52 - log.debug("SEND: %r" % msg)
19.53 - self.con.send(msg + "\n")
19.54 -
19.55 - def sendOk(self, payload=None):
19.56 - self.sendMsg("OK %d" % bool(payload is not None))
19.57 - if payload is not None:
19.58 - if not isinstance(payload, (tuple, list)):
19.59 - payload = (payload,)
19.60 - for e in payload:
19.61 - self.sendMsg("+%s" % e)
19.62 - self.sendMsg(".")
19.63 -
19.64 - def sendNotOk(self, reason=""):
19.65 - self.sendMsg("NOTOK %r" % reason)
19.66 -
19.67 - def getRequest(self):
19.68 - log.debug("Wait for client request at %s:%s (sock=%d)" %
19.69 - (self.host, self.port, self.tcp.fileno()))
19.70 - self.con, self.client = self.tcp.accept()
19.71 - log.info("Incoming request from %s (con=%s)" %
19.72 - (self.client, self.con.fileno()))
19.73 - return (self.con, self.client, self.port)
19.74 -
19.75 - def disconnect_client(self, connection):
19.76 - log.info("Closed request from %s (con=%s)" %
19.77 - (self.client, self.con.fileno()))
19.78 - connection.close()
19.79 -
19.80 - def stop(self):
19.81 - log.debug("Stop")
19.82 - self.tcp.close()
20.1 --- a/gmyth-stream/server/plugins/comm/xmlrpc.py Wed Apr 18 15:47:40 2007 +0100
20.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
20.3 @@ -1,102 +0,0 @@
20.4 -import lib
20.5 -import SimpleXMLRPCServer
20.6 -
20.7 -
20.8 -class Handler:
20.9 -
20.10 - def __init__(self, recv_pool, send_pool):
20.11 - self.recv_pool = recv_pool
20.12 - self.send_pool = send_pool
20.13 - self.getMsg = self.sendMsg
20.14 -
20.15 - def _listMethods(self):
20.16 - return ['setup', 'play', 'stop', 'close', 'getMsg']
20.17 -
20.18 - def _methodHelp(self, method):
20.19 -
20.20 - if method == 'setup':
20.21 - return "Setup the Media: setup( filename, mux, vcodec, vbitrate,"\
20.22 - " fps, acodec, abitrate, width, height, port, options"
20.23 - elif method == 'play':
20.24 - return "Play the Media: play()"
20.25 - elif method == 'stop':
20.26 - return "Stop the Media: stop()"
20.27 - elif method == 'close':
20.28 - return "Close the connection: close()"
20.29 - elif method == 'getMsg':
20.30 - return "Return the first message in the pool: getMsg()"
20.31 - else:
20.32 - # By convention, return empty
20.33 - # string if no help is available
20.34 - return ""
20.35 -
20.36 - def setup(self, filename, mux, vcodec, vbitrate,\
20.37 - fps, acodec, abitrate, width, height, port, options):
20.38 -
20.39 - msg = "%s %s %s %s %s %s %s" % (filename, mux, vcodec, vbitrate,\
20.40 - fps, acodec, abitrate, width, height, port)
20.41 -
20.42 - if len(options) > 0:
20.43 - for opt in options:
20.44 - msg += " %s" % opt
20.45 -
20.46 - self.recv_pool.append("SETUP")
20.47 - self.recv_pool.append(msg)
20.48 - return self.sendMsg()
20.49 -
20.50 - def play(self):
20.51 - self.recv_pool.append("PLAY")
20.52 - return self.sendMsg()
20.53 -
20.54 - def stop(self):
20.55 - self.recv_pool.append("STOP")
20.56 - return self.sendMsg()
20.57 -
20.58 - def close(self):
20.59 - self.recv_pool.append("CLOSE")
20.60 - return self.sendMsg()
20.61 -
20.62 - def sendMsg(self):
20.63 - if self.send_pool != []:
20.64 - return self.send_pool.pop(0)
20.65 - else:
20.66 - return ""
20.67 -
20.68 -
20.69 -class Server:
20.70 -
20.71 - def __init__(self, config):
20.72 - self.host = 'localhost'
20.73 - self.port = int(config.get("Comm", "port"))
20.74 - self.finish = 0
20.75 - self.recv_pool = []
20.76 - self.send_pool = []
20.77 -
20.78 - self.handler = Handler(self.recv_pool, self.send_pool)
20.79 -
20.80 - self.xmlrpc = SimpleXMLRPCServer.SimpleXMLRPCServer((self.host, self.port))
20.81 - self.xmlrpc.register_instance(self.handler)
20.82 -
20.83 -
20.84 - def getMsg(self, size):
20.85 - if self.recv_pool != []:
20.86 - return self.recv_pool.pop(0)
20.87 - else:
20.88 - return ""
20.89 -
20.90 - def sendMsg(self, msg):
20.91 - self.send_pool.append(msg)
20.92 -
20.93 - def Ack(self, command):
20.94 - msg = "[%s] Command %s received" % (lib.now(), command)
20.95 - self.sendMsg(msg + "\n")
20.96 -
20.97 - def getRequest(self):
20.98 - self.xmlrpc.handle_request()
20.99 - return (0, "RPC Client")
20.100 -
20.101 - def disconnect_client(self, connection):
20.102 - connection = 0
20.103 -
20.104 - def stop(self):
20.105 - self.xmlrpc.server_close()
21.1 --- a/gmyth-stream/server/plugins/media/ffmpeg.py Wed Apr 18 15:47:40 2007 +0100
21.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
21.3 @@ -1,91 +0,0 @@
21.4 -import os
21.5 -import sys
21.6 -import lib
21.7 -import time
21.8 -import socket
21.9 -import ConfigParser
21.10 -
21.11 -class Media:
21.12 -
21.13 - def __init__(self, config):
21.14 -
21.15 - self.config = config
21.16 - self.socket = None
21.17 - self.child_pid = None
21.18 -
21.19 - def setup(self, filename, mux, vcodec, vbitrate,\
21.20 - fps, acodec, abitrate, width, height, port):
21.21 -
21.22 - self.filename = filename
21.23 - self.mux = mux
21.24 - self.vcodec = vcodec
21.25 - self.vbitrate = int(vbitrate)
21.26 - self.fps = int(fps)
21.27 - self.acodec = acodec
21.28 - self.abitrate = int(abitrate)
21.29 - self.width = int(width)
21.30 - self.height = int(height)
21.31 -
21.32 - self.port = int(port)
21.33 -
21.34 - # good one: /tmp/mpg/cpm.mpg mpeg mpeg1video 400 25 mp2 192 320 240 5000
21.35 - self.path = self.config.get("FFmpeg", "path")
21.36 - self.path += " -i %s -f %s -vcodec %s -b %d -r %d -acodec %s -ab %d -s %dx%d -" % (
21.37 - self.filename, self.mux, self.vcodec, self.vbitrate,\
21.38 - self.fps, self.acodec, self.abitrate, self.width, self.height)
21.39 -
21.40 - if (self.socket != None):
21.41 - del(self.socket)
21.42 -
21.43 - self.socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
21.44 - self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
21.45 - self.socket.bind( ('', self.port) )
21.46 - self.socket.settimeout(10)
21.47 - self.socket.listen(1)
21.48 -
21.49 - def play(self):
21.50 -
21.51 - lib.log("Starting FFmpeg: %s" % self.path)
21.52 -
21.53 - # exec FFmpeg and get stdout
21.54 - child_stdin, child_stdout = os.popen2(self.path)
21.55 - child_stdin.close()
21.56 -
21.57 - self.child_pid = os.fork()
21.58 - if (self.child_pid == 0):
21.59 - #child
21.60 -
21.61 - conn,addr= self.socket.accept()
21.62 - lib.log("Sending Data to client: %s" % addr[0])
21.63 - data = child_stdout.read(1024)
21.64 - conn.settimeout(5)
21.65 - retry = 0
21.66 -
21.67 - while( data != "" and retry < 5):
21.68 - try:
21.69 - conn.send(data)
21.70 - except socket.error:
21.71 - lib.log("Socket error (maybe timeout ?)")
21.72 - retry = retry + 1
21.73 -
21.74 - data = child_stdout.read(1024)
21.75 -
21.76 - if (retry < 5):
21.77 - lib.log("Finished sending Data to client: %s" % addr[0])
21.78 - else:
21.79 - lib.log("Client timed out")
21.80 -
21.81 - child_stdout.close()
21.82 - #conn.close()
21.83 - #sys.exit()
21.84 -
21.85 -
21.86 - def stop(self):
21.87 -
21.88 - if (self.socket != None):
21.89 - lib.log("Closing socket")
21.90 - self.socket.close()
21.91 -
21.92 - lib.log("Trying to stop FFmpeg process")
21.93 - if (self.child_pid != None):
21.94 - os.kill(self.child_pid, 9)
22.1 --- a/gmyth-stream/server/plugins/media/gstreamer-rtp.py Wed Apr 18 15:47:40 2007 +0100
22.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
22.3 @@ -1,218 +0,0 @@
22.4 -import pygst
22.5 -pygst.require("0.10")
22.6 -import gst
22.7 -import gobject
22.8 -
22.9 -class Media:
22.10 - class StreamData:
22.11 - stream_count = 0
22.12 -
22.13 - def __init__ (self, pipe, abin, vbin):
22.14 -
22.15 - self.stream_count += 1
22.16 - self.Id = self.stream_count
22.17 - self.Pipe = pipe
22.18 - self.Abin = abin
22.19 - self.Vbin = vbin
22.20 - self.Loop = gobject.MainLoop()
22.21 - self.ACaps = ""
22.22 - self.VCaps = ""
22.23 - self.Ready = False
22.24 -
22.25 -
22.26 - def __init__(self, config):
22.27 - # set gstreamer basic options
22.28 - self.config = config
22.29 - self.pipe = None
22.30 - self.streams = []
22.31 -
22.32 -
22.33 - def setup(self, filename, mux, vcodec, vbitrate,
22.34 - fps, acodec, abitrate, width, height, port, options):
22.35 -
22.36 - ## Pipelines
22.37 - self.pipe = gst.Pipeline ()
22.38 - uri = "file://" + filename
22.39 - print "Opening Uri:" + uri
22.40 - src = gst.element_make_from_uri (gst.URI_SRC, uri, "src")
22.41 - if (src is None):
22.42 - return None
22.43 -
22.44 - decode = gst.element_factory_make ("decodebin", "decode")
22.45 - if (decode is None):
22.46 - return None
22.47 -
22.48 -
22.49 - #video encode
22.50 - #queue ! videoscale ! video/x-raw-yuv,width=240,height=144 ! videorate ! ffenc_h263p bitrate=256000 me-method=2 ! rtph263ppay ! udpsink host=224.0.0.1 port=5000
22.51 - vbin = gst.Bin ()
22.52 - vqueue = gst.element_factory_make ("queue", "vqueue")
22.53 - vscale = gst.element_factory_make ("videoscale", "vscale")
22.54 - vrate = gst.element_factory_make ("videorate", "vrate")
22.55 - vencode = gst.element_factory_make ("ffenc_mpeg4", "vencode")
22.56 - vpay = gst.element_factory_make ("rtpmp4vpay", "vpay")
22.57 - vsink = gst.element_factory_make ("udpsink", "vsink")
22.58 -
22.59 - if (None in [vbin, vqueue, vscale, vrate, vencode, vpay, vsink]):
22.60 - print "Fail to create video encode elements."
22.61 - return None
22.62 -
22.63 - vscale_pad = vscale.get_pad("sink")
22.64 - if (vscale_pad is None):
22.65 - print "Fail to get vscale sink pad."
22.66 - return None
22.67 -
22.68 - vscale_caps = gst.caps_from_string ("video/x-raw-yuv, width=%s, height=%s" % (width, height))
22.69 - if (vscale_caps is None):
22.70 - print "Fail to create video caps"
22.71 - return None
22.72 -
22.73 - if (not vscale_pad.set_caps (vscale_caps)):
22.74 - print "Fail to set video output caps"
22.75 - return None
22.76 -
22.77 - vencode.set_property ("bitrate", 256000)
22.78 - vencode.set_property ("me-method", 2)
22.79 -
22.80 - vsink.set_property ("host", "224.0.0.1")
22.81 - vsink.set_property ("port", 5000)
22.82 -
22.83 - vbin.add (vqueue, vscale, vrate, vencode, vpay, vsink)
22.84 - if (not gst.element_link_many (vqueue, vscale, vrate, vencode, vpay, vsink)):
22.85 - print "Fail to link video elements"
22.86 - return None
22.87 -
22.88 - vbin.add_pad (gst.GhostPad ("sink", vqueue.get_pad ("sink")))
22.89 -
22.90 - #audio encode
22.91 - #audio/x-raw-int ! queue ! audioconvert ! faac ! rtpmp4gpay ! udpsink name=upd_audio host=224.0.0.1 port=5002
22.92 - abin = gst.Bin ()
22.93 - aqueue = gst.element_factory_make ("queue", "vqueue")
22.94 - aconvert = gst.element_factory_make ("audioconvert", "aconvert")
22.95 - aencode = gst.element_factory_make ("faac", "aencode")
22.96 - apay = gst.element_factory_make ("rtpmp4gpay", "apay")
22.97 - asink = gst.element_factory_make ("udpsink", "asink")
22.98 -
22.99 - if (None in [abin, aqueue, aconvert, aencode, apay, asink]):
22.100 - print "Fail to create video encode elements."
22.101 - return None
22.102 -
22.103 - asink.set_property ("host", "224.0.0.1")
22.104 - asink.set_property ("port", 5002)
22.105 -
22.106 - abin.add (aqueue, aconvert, aencode, apay, asink)
22.107 - if (not gst.element_link_many (aqueue, aconvert, aencode, apay, asink)):
22.108 - print "Fail to link video elements"
22.109 - return None
22.110 -
22.111 - abin.add_pad (gst.GhostPad ("sink", aqueue.get_pad ("sink")))
22.112 -
22.113 - self.pipe.add (src, decode, abin, vbin)
22.114 - gst.element_link_many (src, decode)
22.115 -
22.116 - stream_data = self.StreamData (self.pipe, abin, vbin)
22.117 -
22.118 - bus = self.pipe.get_bus()
22.119 - bus.add_signal_watch()
22.120 - bus.connect("message", self.__on_bus_message, stream_data)
22.121 -
22.122 - decode.connect("new-decoded-pad", self.__on_decode_new_pad, stream_data)
22.123 - decode.connect("unknown-type", self.__on_decode_unknown_type, stream_data)
22.124 -
22.125 -
22.126 - self.pipe.set_state (gst.STATE_PAUSED)
22.127 - print "Running Pipe"
22.128 - stream_data.Loop.run ()
22.129 - print "End run"
22.130 -
22.131 - a_caps = stream_data.ACaps
22.132 - v_caps = stream_data.VCaps
22.133 - stream_id = stream_data.Id
22.134 -
22.135 - self.streams.append (stream_data)
22.136 -
22.137 - def play(self):
22.138 -
22.139 - print "Trying to play pipeline: %s" % self.pipe
22.140 - try:
22.141 - if (self.pipe):
22.142 - self.pipe.set_state(gst.STATE_PLAYING)
22.143 - except gobject.GError, e:
22.144 - print "Error: " + str(e)
22.145 -
22.146 -
22.147 - def stop(self):
22.148 -
22.149 - print "Trying to stop pipeline: %s" % self.pipe
22.150 - try:
22.151 - if (self.pipeline):
22.152 - self.pipeline.set_state(gst.STATE_NULL)
22.153 - except gobject.GError, e:
22.154 - print "Error: " + str(e)
22.155 -
22.156 - def __on_bus_message (self, bus, message, stream_data):
22.157 -
22.158 - t = message.type
22.159 - if (t == gst.MESSAGE_STATE_CHANGED):
22.160 - oldstate = -1
22.161 - newstate = -1
22.162 - pending = -1
22.163 - oldstate, newstate, pending = message.parse_state_changed ()
22.164 - if ((oldstate == gst.STATE_READY) and \
22.165 - (newstate == gst.STATE_PAUSED) and \
22.166 - (pending == gst.STATE_VOID_PENDING) and \
22.167 - (stream_data.Ready == False)):
22.168 - state_changed_status, current_state, pending_state = stream_data.Pipe.get_state ()
22.169 - if ((current_state == gst.STATE_PAUSED) and \
22.170 - (pending_state == gst.STATE_VOID_PENDING)):
22.171 - print "Pipe paused"
22.172 - self.__fill_sink_pads (stream_data)
22.173 - stream_data.Loop.quit ()
22.174 - stream_data.Ready = True
22.175 - elif (t == gst.MESSAGE_ERROR):
22.176 - err, debug = message.parse_error()
22.177 - print "Error: %s" % err, debug
22.178 - stream_data.Loop.quit ()
22.179 - stream_data.Ready = False
22.180 -
22.181 - return True
22.182 -
22.183 -
22.184 - def __fill_sink_pads (self, stream_data):
22.185 -
22.186 - asink = stream_data.Abin.get_by_name ("asink")
22.187 - vsink = stream_data.Vbin.get_by_name ("vsink")
22.188 -
22.189 - asink_pad = asink.get_pad ("sink")
22.190 - stream_data.ACaps = asink_pad.get_negotiated_caps().to_string()
22.191 - print "ACAPS " + stream_data.ACaps
22.192 -
22.193 - vsink_pad = vsink.get_pad ("sink")
22.194 - stream_data.VCaps = vsink_pad.get_negotiated_caps().to_string()
22.195 - print "ACAPS " + stream_data.VCaps
22.196 -
22.197 -
22.198 -
22.199 - def __on_decode_unknown_type (self, decode, pad, caps, stream_data):
22.200 -
22.201 - print "Unknown Type"
22.202 - return None
22.203 -
22.204 - def __on_decode_new_pad (self, decode, pad, arg1, stream_data):
22.205 -
22.206 - caps = pad.get_caps().to_string()
22.207 - print "New pad " + caps
22.208 - if (caps.rfind ("audio") != -1):
22.209 - apad = stream_data.Abin.get_pad ("sink")
22.210 - if (pad.link (apad) != gst.PAD_LINK_OK):
22.211 - print "Error on link audio pad"
22.212 - return None
22.213 - elif (caps.rfind ("video") != -1):
22.214 - vpad = stream_data.Vbin.get_pad ("sink")
22.215 - if (pad.link (vpad) != gst.PAD_LINK_OK):
22.216 - print "Error on link video pad"
22.217 - return None
22.218 - else:
22.219 - print "Invalid caps"
22.220 -
22.221 -
23.1 --- a/gmyth-stream/server/plugins/media/gstreamer.py Wed Apr 18 15:47:40 2007 +0100
23.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
23.3 @@ -1,290 +0,0 @@
23.4 -#vim:ts=4:sw=4:et
23.5 -import pygst
23.6 -pygst.require("0.10")
23.7 -import gst
23.8 -import gobject
23.9 -import socket
23.10 -import time
23.11 -from threading import Thread
23.12 -
23.13 -class Media:
23.14 - class StreamListener(Thread):
23.15 - def __init__ (self, stream_data):
23.16 - Thread.__init__(self)
23.17 - self.stream = stream_data
23.18 - print "Thread Created"
23.19 -
23.20 - def run (self):
23.21 - #Create socket
23.22 - print "Waiting connection"
23.23 - self.stream.Socket.listen(1)
23.24 - self.stream.Connection, self.stream.Addr = self.stream.Socket.accept ()
23.25 - print "Connection requested"
23.26 - self.stream.Sink.set_property ("fd", self.stream.Connection.fileno())
23.27 - self.stream.Pipe.set_state(gst.STATE_PLAYING)
23.28 - print "PLAYING"
23.29 -
23.30 -
23.31 - class StreamData:
23.32 - stream_count = 0
23.33 -
23.34 - def __init__ (self, pipe, abin, vbin, sink):
23.35 - self.stream_count += 1
23.36 - self.Id = self.stream_count
23.37 - self.Pipe = pipe
23.38 - self.Abin = abin
23.39 - self.Vbin = vbin
23.40 - self.Sink = sink
23.41 - self.Loop = gobject.MainLoop()
23.42 - self.ACaps = ""
23.43 - self.VCaps = ""
23.44 - self.Ready = False
23.45 - self.Socket = None
23.46 - self.Connection = None
23.47 - self.Addr = None
23.48 -
23.49 - def __init__(self, config):
23.50 - # set gstreamer basic options
23.51 - self.config = config
23.52 - self.streams = []
23.53 - self.socket = None
23.54 - self.connection = None
23.55 - self.addr = None
23.56 - self.ready = False
23.57 - self.current = None
23.58 -
23.59 -
23.60 - def setup(self, uri, mux, vcodec, vbitrate,
23.61 - fps, acodec, abitrate, width, height, port, options):
23.62 -
23.63 - ## Pipelines
23.64 - pipe = gst.Pipeline ()
23.65 - print "Opening Uri:" + uri
23.66 - src = gst.element_make_from_uri (gst.URI_SRC, uri, "src")
23.67 - #src = gst.element_factory_make ("gnomevfssrc", "src")
23.68 - src.set_property ("location", uri)
23.69 - if (src is None):
23.70 - print "Fail to create src element"
23.71 - return None
23.72 -
23.73 - print ("Create source")
23.74 - decode = gst.element_factory_make ("decodebin", "decode")
23.75 - if (decode is None):
23.76 - print "Fail to create decodebin"
23.77 - return None
23.78 -
23.79 - print ("Create source")
23.80 - mux = gst.element_factory_make ("avimux", "mux")
23.81 - if (mux is None):
23.82 - print "Fail to create mux"
23.83 - return None
23.84 -
23.85 - sink = gst.element_factory_make ("fdsink", "sink")
23.86 - if (sink is None):
23.87 - print "Fail to create fdsink"
23.88 - return None
23.89 -
23.90 - print ("Create source")
23.91 -
23.92 - #video encode
23.93 - #queue ! videoscale ! video/x-raw-yuv,width=240,height=144 ! videorate ! ffenc_h263p bitrate=256000 me-method=2 ! rtph263ppay ! udpsink host=224.0.0.1 port=5000
23.94 - vbin = gst.Bin ()
23.95 - vqueue = gst.element_factory_make ("queue", "vqueue")
23.96 - colorspace = gst.element_factory_make ("ffmpegcolorspace", "")
23.97 - vrate = gst.element_factory_make ("videorate", "vrate")
23.98 - vencode = gst.element_factory_make ("ffenc_mpeg4", "vencode")
23.99 - #vencode = gst.element_factory_make ("ffenc_msmpeg4v1", "vencode")
23.100 - vqueue_src = gst.element_factory_make ("queue", "vqueue_src")
23.101 -
23.102 - #if (int(vbitrate) > 0):
23.103 - vencode.set_property ("bitrate", 200)
23.104 - #vencode.set_property ("quant-type", 1)
23.105 - vencode.set_property ("pass", 2)
23.106 - vencode.set_property ("quantizer", 5)
23.107 - #vencode.set_property ("me-method", 1)
23.108 -
23.109 -
23.110 - if (None in [vbin, vqueue, vrate, vencode, vqueue_src]):
23.111 - print "Fail to create video encode elements."
23.112 - return None
23.113 -
23.114 - vbin.add (vqueue)
23.115 - if ((int(width) > 0) and (int(height) > 0)):
23.116 - print ("formating output to %d / %d" % (int(width), int(height)))
23.117 -
23.118 - vscale = gst.element_factory_make ("ffvideoscale", "vscale")
23.119 -
23.120 - vbin.add (vscale);
23.121 - if (not vqueue.link (vscale)):
23.122 - print "Fail to link video elements"
23.123 - return None
23.124 -
23.125 - vbin.add (colorspace)
23.126 -
23.127 - if (not vscale.link (colorspace, \
23.128 - gst.caps_from_string ("video/x-raw-yuv,width=(int)%d,height=(int)%d" % (int(width), int(height))))):
23.129 - print "Fail to link video elements"
23.130 - return None
23.131 - else:
23.132 - vbin.add (colorspace)
23.133 - vqueue.link (colorspace)
23.134 -
23.135 - vbin.add (vrate, vencode, vqueue_src)
23.136 - if (not colorspace.link (vrate)):
23.137 - print "Fail to colorspace with vrate"
23.138 - return None
23.139 -
23.140 -
23.141 - if (not vrate.link (vencode, \
23.142 - gst.caps_from_string ("video/x-raw-yuv,framerate=(fraction)10/1"))):
23.143 - print "Fail to link vrate element"
23.144 - return None
23.145 -
23.146 - if (not vencode.link (vqueue_src)):
23.147 - print "Fail to link video encode with queue"
23.148 - return None
23.149 -
23.150 - vbin.add_pad (gst.GhostPad ("sink", vqueue.get_pad ("sink")))
23.151 - vbin.add_pad (gst.GhostPad ("src", vqueue_src.get_pad ("src")))
23.152 -
23.153 - #audio encode
23.154 - #audio/x-raw-int ! queue ! audioconvert ! faac ! rtpmp4gpay ! udpsink name=upd_audio host=224.0.0.1 port=5002
23.155 - abin = gst.Bin ()
23.156 - aqueue = gst.element_factory_make ("queue", "aqueue")
23.157 - aconvert = gst.element_factory_make ("audioconvert", "aconvert")
23.158 - arate = gst.element_factory_make ("audioresample", "arate")
23.159 - #aencode = gst.element_factory_make ("ffenc_ac3", "aencode")
23.160 - aencode = gst.element_factory_make ("queue", "aencode")
23.161 - #aencode = gst.element_factory_make ("lame", "aencode")
23.162 - #aencode = gst.element_factory_make ("ffenc_mp2", "aencode")
23.163 - aqueue_src = gst.element_factory_make ("queue", "aqueue_src")
23.164 -
23.165 - if (None in [abin, aqueue, arate, aencode, aqueue_src]):
23.166 - print "Fail to create video encode elements."
23.167 - return None
23.168 -
23.169 - abin.add (aqueue, aconvert, arate, aencode, aqueue_src)
23.170 - if (not gst.element_link_many (aqueue, aconvert, arate, aencode, aqueue_src)):
23.171 - print "Fail to link video elements"
23.172 - return None
23.173 -
23.174 - abin.add_pad (gst.GhostPad ("sink", aqueue.get_pad ("sink")))
23.175 - abin.add_pad (gst.GhostPad ("src", aqueue_src.get_pad ("src")))
23.176 -
23.177 - #Finish Pipeline
23.178 - pipe.add (src, decode, abin, vbin, mux, sink)
23.179 - gst.element_link_many (src, decode)
23.180 - gst.element_link_many (mux, sink)
23.181 -
23.182 - #Linking decode with mux
23.183 - mux_audio = mux.get_pad ("audio_0")
23.184 - mux_video = mux.get_pad ("video_0")
23.185 -
23.186 - audio_pad = abin.get_pad ("src")
23.187 - video_pad = vbin.get_pad ("src")
23.188 -
23.189 - if (audio_pad.link (mux_audio) != gst.PAD_LINK_OK):
23.190 - print "Fail to link audio with mux"
23.191 - return None
23.192 -
23.193 - if (video_pad.link (mux_video) != gst.PAD_LINK_OK):
23.194 - print "Fail to link audio with mux"
23.195 - return None
23.196 -
23.197 - stream_data = self.StreamData (pipe, abin, vbin, sink)
23.198 - bus = pipe.get_bus()
23.199 - bus.add_signal_watch()
23.200 - bus.connect ("message", self.__on_bus_message, stream_data)
23.201 -
23.202 - decode.connect("new-decoded-pad", self.__on_decode_new_pad, stream_data)
23.203 - decode.connect("unknown-type", self.__on_decode_unknown_type, stream_data)
23.204 -
23.205 - print ("Create source")
23.206 - pipe.set_state (gst.STATE_PAUSED)
23.207 - print "Running Pipe"
23.208 - stream_data.Loop.run ()
23.209 - print "End run"
23.210 -
23.211 -
23.212 - #Create socket
23.213 - stream_data.Socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
23.214 - print "Bind on port %d" % port
23.215 - stream_data.Socket.bind(('', int (port)))
23.216 - self.streams.append (stream_data)
23.217 - return (True, "")
23.218 -
23.219 - def play(self):
23.220 - print "Play"
23.221 - stream = self.streams[0]
23.222 - self.current = self.StreamListener(stream)
23.223 - self.current.start ()
23.224 - time.sleep (1)
23.225 - return (True, "")
23.226 -
23.227 - def stop(self):
23.228 - self.current.join ()
23.229 - self.current = None
23.230 - stream = self.streams[0]
23.231 - stream.Pipe.set_state(gst.STATE_NULL)
23.232 - del (stream.Pipe)
23.233 - stream.Pipe = None
23.234 - stream.Abin = None
23.235 - stream.Vbin = None
23.236 - stream.Sink = None
23.237 - if (stream.Connection != None):
23.238 - stream.Connection.close ()
23.239 -
23.240 - self.streams = []
23.241 - time.sleep (5)
23.242 - return (True, "")
23.243 -
23.244 -
23.245 - def __on_bus_message (self, bus, message, stream_data):
23.246 -
23.247 - t = message.type
23.248 - if (t == gst.MESSAGE_STATE_CHANGED):
23.249 - oldstate = -1
23.250 - newstate = -1
23.251 - pending = -1
23.252 - oldstate, newstate, pending = message.parse_state_changed ()
23.253 - if ((oldstate == gst.STATE_READY) and \
23.254 - (newstate == gst.STATE_PAUSED) and \
23.255 - (pending == gst.STATE_VOID_PENDING) and \
23.256 - (stream_data.Ready == False)):
23.257 - state_changed_status, current_state, pending_state = stream_data.Pipe.get_state ()
23.258 - if ((current_state == gst.STATE_PAUSED) and \
23.259 - (pending_state == gst.STATE_VOID_PENDING)):
23.260 - print "Pipe paused"
23.261 - stream_data.Loop.quit ()
23.262 - stream_data.Ready = True
23.263 - elif (t == gst.MESSAGE_ERROR):
23.264 - err, debug = message.parse_error()
23.265 - print "Error: %s" % err, debug
23.266 - stream_data.Loop.quit ()
23.267 - stream_data.Ready = False
23.268 -
23.269 - return True
23.270 -
23.271 - def __on_decode_unknown_type (self, decode, pad, caps, stream_data):
23.272 -
23.273 - print "Unknown Type"
23.274 - return None
23.275 -
23.276 - def __on_decode_new_pad (self, decode, pad, arg1, stream_data):
23.277 -
23.278 - caps = pad.get_caps().to_string()
23.279 - print "New pad " + caps
23.280 - if (caps.rfind ("audio") != -1):
23.281 - apad = stream_data.Abin.get_pad ("sink")
23.282 - if (pad.link (apad) != gst.PAD_LINK_OK):
23.283 - print "Error on link audio pad"
23.284 - return None
23.285 - elif (caps.rfind ("video") != -1):
23.286 - vpad = stream_data.Vbin.get_pad ("sink")
23.287 - if (pad.link (vpad) != gst.PAD_LINK_OK):
23.288 - print "Error on link video pad"
23.289 - return None
23.290 - else:
23.291 - print "Invalid caps"
23.292 - print "Linked"
23.293 -
24.1 --- a/gmyth-stream/server/plugins/media/mencoder.py Wed Apr 18 15:47:40 2007 +0100
24.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
24.3 @@ -1,411 +0,0 @@
24.4 -from __future__ import division
24.5 -
24.6 -import os
24.7 -import sys
24.8 -import lib
24.9 -import time
24.10 -import shlex
24.11 -import signal
24.12 -import socket
24.13 -import ConfigParser
24.14 -import logging as log
24.15 -
24.16 -from select import *
24.17 -from subprocess import *
24.18 -
24.19 -class Media(object):
24.20 -
24.21 - def __init__(self, config):
24.22 -
24.23 - self.config = config
24.24 - self.do_cleanup()
24.25 -
24.26 - # __init__()
24.27 -
24.28 -
24.29 - def do_cleanup(self):
24.30 - self.path = ""
24.31 - self.args = []
24.32 - self.language = None
24.33 - self.subtitle = None
24.34 - self.mpegopts = None
24.35 - self.socket = None
24.36 - self.child_pid = None
24.37 - self.mplayer = None
24.38 - self.mencoder_pid = None
24.39 - self.mplayer_pid = None
24.40 - self.audio_opts = None
24.41 - self.video_opts = None
24.42 - self.gst_pipe = None
24.43 - self.gst_pid = None
24.44 - self.transcode_local = None
24.45 -
24.46 - # do_cleanup()
24.47 -
24.48 -
24.49 - def setup_opts(self, options):
24.50 -
24.51 - for opt in options:
24.52 -
24.53 - if opt == "local":
24.54 - self.mplayer = lib.which("mplayer")
24.55 -
24.56 - elif opt.find("language=") >= 0:
24.57 - try:
24.58 - lan = opt.split("=")[1]
24.59 - if len(lan) < 2:
24.60 - self.language = lan
24.61 - except Exception, e:
24.62 - log.error("Bad language option: %s" % opt)
24.63 -
24.64 - elif opt.find("subtitle=") >= 0:
24.65 - try:
24.66 - sub = opt.split("=")[1]
24.67 - if len(sub) < 2:
24.68 - self.language = sub
24.69 - except Exception, e:
24.70 - log.error("Bad subtitle option: %s" % opt)
24.71 -
24.72 - elif opt.find("format=") >= 0:
24.73 - try:
24.74 - self.mpegopts = opt.split("=")[1]
24.75 - except Exception, e:
24.76 - log.error("Bad format option: %s" % opt)
24.77 -
24.78 - elif opt.find("outfile=") >= 0:
24.79 - try:
24.80 - self.transcode_local = opt.split("=")[1]
24.81 - except Exception, e:
24.82 - log.error("Bad outfile option: %s" % opt)
24.83 -
24.84 - # setup_opts()
24.85 -
24.86 -
24.87 - def run_mplayer(self):
24.88 - msg = self.filename
24.89 -
24.90 - if self.kind == "dvd":
24.91 - msg = "dvd://" + msg
24.92 -
24.93 - self.mplayer_pid = Popen([self.mplayer, self.filename, "1> %s" % os.devnull,\
24.94 - "2> %s" % os.devnull], stdout=PIPE, close_fds=True)
24.95 -
24.96 - # run_mplayer()
24.97 -
24.98 -
24.99 - def setup_mencoder(self):
24.100 - self.path = self.config.get("Mencoder", "path")
24.101 - mp = Popen([self.path], stdout=PIPE, close_fds=True)
24.102 -
24.103 - version = mp.stdout.read().split("MEncoder ")[1].split(" (C)")[0].split("-")[-1]
24.104 -
24.105 - if version > "4.1.1": self.mencoder_old = False
24.106 - else: self.mencoder_old = True
24.107 -
24.108 - os.kill(mp.pid, signal.SIGKILL)
24.109 - log.info("Mencoder version: %s" % version)
24.110 -
24.111 - if self.mencoder_old:
24.112 - try:
24.113 - self.fifo = self.config.get("Mencoder", "fifo_path")
24.114 - os.mkfifo(self.fifo)
24.115 - except Exception, e:
24.116 - log.info("Fifo: %s" % e)
24.117 - else:
24.118 - self.fifo = "-"
24.119 -
24.120 - # setup_mencoder()
24.121 -
24.122 -
24.123 - def setup_audio(self):
24.124 -
24.125 - if self.acodec == "mp3lame":
24.126 - return "-oac mp3lame -lameopts cbr:br=%s vol=5" % self.abitrate
24.127 - else:
24.128 - return "-oac lavc -lavcopts acodec=%s:abitrate=%s" % (\
24.129 - self.acodec, self.abitrate)
24.130 -
24.131 - # setup_audio()
24.132 -
24.133 -
24.134 - def setup_video(self):
24.135 -
24.136 - video = ""
24.137 -
24.138 - video += " -of %s" % self.mux
24.139 - video += " -ofps %s" % self.fps
24.140 -
24.141 - if self.vcodec == "nuv" or self.vcodec == "xvid"\
24.142 - or self.vcodec == "qtvideo" or self.vcodec == "copy":
24.143 - video += " -ovc %s" % self.vcodec
24.144 - else:
24.145 - video += " -ovc lavc -lavcopts vcodec=%s:vbitrate=%s" % (
24.146 - self.vcodec, self.vbitrate)
24.147 -
24.148 - if self.mux == "mpeg" and self.mpegopts is not None:
24.149 - video += " -mpegopts format=%s" % self.mpegopts
24.150 -
24.151 - video += " -vf scale=%s:%s" % (self.width, self.height)
24.152 -
24.153 - return video
24.154 -
24.155 - # setup_video()
24.156 -
24.157 -
24.158 - def arg_append(self, args, options):
24.159 - l = shlex.split(options)
24.160 - for i in l:
24.161 - args.append(i)
24.162 -
24.163 - # arg_append()
24.164 -
24.165 -
24.166 - def setup_args(self, args):
24.167 -
24.168 - args.append(self.path)
24.169 -
24.170 - #args.append(self.filename)
24.171 - args.append("-")
24.172 -
24.173 - if self.language != None:
24.174 - self.arg_append(args, "-alang %s" % self.language)
24.175 -
24.176 - if self.subtitle != None:
24.177 - self.arg_append(args, "-slang %s" % self.subtitle)
24.178 - self.arg_append(args, "-subfps %s" % self.fps)
24.179 -
24.180 - self.arg_append(args, "-idx")
24.181 - self.arg_append(args, self.audio_opts)
24.182 - self.arg_append(args, self.video_opts)
24.183 -
24.184 - self.arg_append(args, "-really-quiet")
24.185 - self.arg_append(args, "-o %s" % self.fifo)
24.186 - self.arg_append(args, "2> %s" % os.devnull)
24.187 -
24.188 - # setup_args()
24.189 -
24.190 -
24.191 - def setup_filename(self, filename):
24.192 - try:
24.193 - self.kind, self.filename = filename.split("://")
24.194 - except:
24.195 - return (False, "Wrong filename protocol")
24.196 -
24.197 - if self.kind == "file":
24.198 - if not os.path.exists(self.filename):
24.199 - msg = "File requested does not exist. SETUP failed."
24.200 - log.error(msg)
24.201 - return (False, msg)
24.202 -
24.203 - elif self.kind == "dvd":
24.204 - self.filename = "dvd://" + filename
24.205 -
24.206 - elif self.kind == "myth":
24.207 - self.filename = filename
24.208 - self.gst_pipe = os.pipe()
24.209 - print self.gst_pipe[0]
24.210 - print self.gst_pipe[1]
24.211 -
24.212 - return (True, "")
24.213 -
24.214 - # setup_filename()
24.215 -
24.216 -
24.217 - def setup_socket(self):
24.218 - if self.socket != None:
24.219 - self.socket = None
24.220 -
24.221 - self.socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
24.222 - self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
24.223 -
24.224 - try:
24.225 - self.socket.bind( ('', self.port) )
24.226 - self.socket.listen(1)
24.227 - except Exception, e:
24.228 - log.error("Could not create socket: %s" % e)
24.229 - return (False, e)
24.230 -
24.231 - return (True, "")
24.232 -
24.233 - # setup_socket()
24.234 -
24.235 -
24.236 - '''
24.237 - MENCODER SETUP DESCRIPTION
24.238 - ===========================
24.239 -
24.240 - -> mux, vcodecs and acodecs
24.241 - |-> mencoder (-of | -ovc | -oac) help
24.242 -
24.243 - -> if used mpeg as mux:
24.244 - |-> to setup format: format=%s as an option at the end
24.245 -
24.246 - '''
24.247 -
24.248 -
24.249 - # good one: /tmp/dvb.mpg avi mpeg4 400 25 mp3lame 192 320 240
24.250 - # file:///tmp/dvb.mpg mpeg mpeg1video 400 25 mp2 192 320 240 format=mpeg1
24.251 - # dvd://4 mpeg mpeg1video 400 25 mp3lame 192 400 240 language=en local
24.252 - # file:///tmp/mpg/bad_day.mpg avi mpeg4 400 25 mp3 192 320 240
24.253 -
24.254 - def setup(self, filename, mux, vcodec, vbitrate,\
24.255 - fps, acodec, abitrate, width, height, port, options):
24.256 -
24.257 - if self.args != []:
24.258 - self.do_cleanup()
24.259 -
24.260 - self.mux = mux
24.261 - self.vcodec = vcodec
24.262 - self.vbitrate = vbitrate
24.263 - self.fps = fps
24.264 - self.acodec = acodec
24.265 - self.abitrate = abitrate
24.266 - self.width = width
24.267 - self.height = height
24.268 - self.port = int(port)
24.269 -
24.270 - self.setup_mencoder()
24.271 -
24.272 - ret_val = self.setup_filename(filename)
24.273 -
24.274 - if not ret_val[0]:
24.275 - return ret_val
24.276 -
24.277 - self.setup_opts(options)
24.278 - self.audio_opts = self.setup_audio()
24.279 - self.video_opts = self.setup_video()
24.280 - self.setup_args(self.args)
24.281 -
24.282 - ret_val = self.setup_socket()
24.283 - return ret_val
24.284 -
24.285 - # setup()
24.286 -
24.287 - def play_loop(self, conn):
24.288 - data = self.pout.read(4096)
24.289 -
24.290 - conn.settimeout(5)
24.291 - retry = 0
24.292 -
24.293 - if not self.transcode_local:
24.294 - while data != "" and retry < 5:
24.295 - try:
24.296 - conn.send(data)
24.297 - r, w, x = select([conn], [], [], 0)
24.298 - if conn in r:
24.299 - back = conn.recv(1024)
24.300 - if back == "OK" and self.mplayer and not self.mplayer_pid:
24.301 - self.run_mplayer()
24.302 -
24.303 - except socket.error, e:
24.304 - log.error("Socket error: %s" % e)
24.305 - retry += 1
24.306 -
24.307 - data = self.pout.read(4096)
24.308 -
24.309 - else:
24.310 - local = open(self.transcode_local, "w")
24.311 - total = os.path.getsize(self.filename)
24.312 - partial = 4096
24.313 -
24.314 - while data != "":
24.315 - try:
24.316 - local.write(data)
24.317 - except Exception, e:
24.318 - log.error("Write error: %s" % e)
24.319 -
24.320 - data = self.pout.read(4096)
24.321 - partial += len(data)
24.322 - conn.send("%.2f\n" % (partial * 100 / total) )
24.323 -
24.324 - local.close()
24.325 - conn.send("DONE\n")
24.326 -
24.327 - return retry
24.328 -
24.329 - # play_loop()
24.330 -
24.331 -
24.332 - def play(self):
24.333 -
24.334 - if self.gst_pipe:
24.335 - try:
24.336 - gst = [ lib.which("gst-launch-0.10"), "--gst-debug-level=0" ]
24.337 - self.arg_append(gst, "mythtvsrc location=%s" % self.filename)
24.338 - self.arg_append(gst, "! fdsink fd=2")
24.339 - self.gst_pid = Popen(gst, close_fds=True)
24.340 - log.info("Running Gstreamer: %s" % gst);
24.341 - except Exception, e:
24.342 - msg = "Could not init Gstreamer: %s" % e
24.343 - log.error(msg)
24.344 - return (False, msg)
24.345 -
24.346 -
24.347 - log.info("Starting Mencoder: %s" % self.args )
24.348 - try:
24.349 - if not self.gst_pipe:
24.350 - self.stdin = open(self.filename)
24.351 - else:
24.352 - self.stdin = self.gst_pid.stdout
24.353 -
24.354 - self.mencoder_pid = Popen(self.args, stdin=self.stdin, stdout=PIPE, close_fds=True)
24.355 - except Exception, e:
24.356 - msg = "Could not init Mencoder: %s" % e
24.357 - log.error(msg)
24.358 - return (False, msg)
24.359 -
24.360 - if self.mencoder_old: self.pout = open(self.fifo)
24.361 - else: self.pout = self.mencoder_pid.stdout
24.362 -
24.363 - self.child_pid = os.fork()
24.364 -
24.365 - if self.child_pid == 0:
24.366 - conn, addr = self.socket.accept()
24.367 -
24.368 - log.info("Sending Data to client: %s" % addr[0])
24.369 - retry = self.play_loop(conn)
24.370 -
24.371 - if retry < 5:
24.372 - log.info("Finished sending Data to client: %s" % addr[0])
24.373 - else:
24.374 - log.error("Client timed out, retried more than %s times" % retry)
24.375 -
24.376 - os.kill(self.mencoder_pid.pid, signal.SIGKILL)
24.377 - sys.exit(0)
24.378 -
24.379 - return (True, "")
24.380 -
24.381 - # play()
24.382 -
24.383 -
24.384 - def stop(self):
24.385 - try:
24.386 -
24.387 - if self.mencoder_pid:
24.388 - os.kill(self.mencoder_pid.pid, signal.SIGTERM)
24.389 - self.mencoder_pid = None
24.390 -
24.391 - if self.mplayer_pid:
24.392 - os.kill(self.mplayer_pid.pid, signal.SIGTERM)
24.393 - self.mplayer_pid = None
24.394 -
24.395 - if self.socket:
24.396 - self.socket.close()
24.397 - self.socket = None
24.398 -
24.399 - if self.child_pid:
24.400 - os.kill(self.child_pid, signal.SIGTERM)
24.401 - self.child_pid = None
24.402 -
24.403 - if self.gst_pid:
24.404 - os.kill(self.gst_pid.pid, signal.SIGTERM)
24.405 - self.gst_pid = None
24.406 -
24.407 - self.do_cleanup()
24.408 -
24.409 - os.wait()
24.410 -
24.411 - except Exception, e:
24.412 - log.error("Stop error: %s" % e)
24.413 -
24.414 - # stop()
25.1 --- a/gmyth-stream/server/plugins/media/vlc.py Wed Apr 18 15:47:40 2007 +0100
25.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
25.3 @@ -1,80 +0,0 @@
25.4 -import os
25.5 -import sys
25.6 -import time
25.7 -import socket
25.8 -import ConfigParser
25.9 -
25.10 -class Media:
25.11 -
25.12 - def __init__(self, config):
25.13 -
25.14 - self.config = config
25.15 - self.pipe = ""
25.16 - self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
25.17 -
25.18 - self.path = config.get("Vlc", "path")
25.19 - self.host = config.get("Vlc", "host")
25.20 - self.port = int(config.get("Vlc", "port"))
25.21 - self.pwd = config.get("Vlc", "pwd")
25.22 -
25.23 - # exec VLC
25.24 - pid = os.fork()
25.25 - if (pid == 0):
25.26 - #child
25.27 - print "ESTOU EM CHILD"
25.28 - self.path += " -I telnet -d 1> /dev/null 2> /dev/null &"
25.29 - os.system(self.path)
25.30 - sys.exit(0)
25.31 - else:
25.32 - print "ESTOU EM PARENT 1"
25.33 - time.sleep(3)
25.34 - print "ESTOU EM PARENT 2"
25.35 - self.sock.connect( (self.host, self.port) )
25.36 - self.sock.send("%s\n" % self.pwd)
25.37 -
25.38 -
25.39 - def insert_file(self, filename):
25.40 -
25.41 - self.sock.send("setup output0 input %s\n" % filename)
25.42 -
25.43 -
25.44 -
25.45 - def setup(self, filename, mux, vcodec, vbitrate,\
25.46 - fps, acodec, abitrate, width, height, port):
25.47 -
25.48 - self.filename = filename
25.49 - self.mux = mux
25.50 - self.vcodec = vcodec
25.51 - self.vbitrate = int(vbitrate)
25.52 - self.fps = int(fps)
25.53 - self.acodec = acodec
25.54 - self.abitrate = int(abitrate)
25.55 - self.width = int(width)
25.56 - self.height = int(height)
25.57 -
25.58 - self.port = int(port)
25.59 -
25.60 -
25.61 - self.pipe = "#transcode{vcodec=%s,vb=%d,"\
25.62 - "fps=25.0,scale=1,acodec=mpga,"\
25.63 - "ab=64,channels=1,width=%d,height=%d}"\
25.64 - ":duplicate{dst=std{access=http,"\
25.65 - "mux=mpeg1,dst=:%d}}" % (self.vcodec, self.vbitrate,\
25.66 - self.widht, self.height,\
25.67 - self.port)
25.68 -
25.69 - self.sock.send("setup output0 broadcast %s\n" % self.pipe)
25.70 - self.insert_file(self.filename)
25.71 -
25.72 - def play(self):
25.73 -
25.74 - print "Trying to play: %s" % self.pipe
25.75 - self.sock.send("control output0 play\n")
25.76 -
25.77 -
25.78 - def stop(self):
25.79 -
25.80 - print "Trying to stop: %s" % self.pipe
25.81 - self.sock.send("control output0 stop\n")
25.82 -
25.83 -
26.1 --- a/gmyth-stream/server/stream.conf Wed Apr 18 15:47:40 2007 +0100
26.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
26.3 @@ -1,23 +0,0 @@
26.4 -[Comm]
26.5 -engine = tcp
26.6 -port = 50000
26.7 -
26.8 -
26.9 -[Media]
26.10 -engine = mencoder
26.11 -
26.12 -
26.13 -[Vlc]
26.14 -path = /usr/local/bin/vlc
26.15 -host = 127.0.0.1
26.16 -port = 4212
26.17 -pwd = admin
26.18 -
26.19 -
26.20 -[FFmpeg]
26.21 -path = /usr/local/bin/ffmpeg
26.22 -
26.23 -
26.24 -[Mencoder]
26.25 -path = /usr/local/bin/mencoder
26.26 -fifo_path = /tmp/teste
27.1 --- a/gmyth-stream/server/tests/client.py Wed Apr 18 15:47:40 2007 +0100
27.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
27.3 @@ -1,51 +0,0 @@
27.4 -import os
27.5 -import sys
27.6 -import time
27.7 -import socket
27.8 -
27.9 -
27.10 -if len(sys.argv) < 2:
27.11 - HOST = 'localhost'
27.12 - PORT = 50000
27.13 -elif len(sys.argv) == 2:
27.14 - HOST = sys.argv[1]
27.15 - PORT = 50000
27.16 -else:
27.17 - HOST = sys.argv[1]
27.18 - PORT = int(sys.argv[2])
27.19 -
27.20 -socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
27.21 -socket.settimeout(10)
27.22 -
27.23 -try:
27.24 - socket.connect( (HOST,PORT) )
27.25 -except:
27.26 - print "\n--> Could not connect to ('%s':'%d')\n" % (HOST,PORT)
27.27 - sys.exit(-1)
27.28 -
27.29 -
27.30 -mplayer = os.popen("which mplayer").read().strip()
27.31 -mplayer += " -idx - -vo x11 1> /dev/null"
27.32 -pin, pout = os.popen2(mplayer)
27.33 -
27.34 -#teste = open("teste.avi", "w")
27.35 -
27.36 -data = socket.recv(4096)
27.37 -i = 0
27.38 -
27.39 -while (data != ""):
27.40 - pin.write(data)
27.41 - #teste.write(data)
27.42 - data = socket.recv(4096)
27.43 - #if (i == 500):
27.44 - # socket.send("OK")
27.45 - i += 1
27.46 -
27.47 -pin.close()
27.48 -socket.close()
27.49 -#teste.close()
27.50 -
27.51 -# from select import select
27.52 -# r, w, x = select([pout], []. [], 0)
27.53 -# if pout in r:
27.54 -# pout.read(32)