Commit 917b3a70 authored by Olivier Aubert's avatar Olivier Aubert
Browse files

Remove the obsolete vlc/python directory. Up-to-date version of python...

Remove the obsolete vlc/python directory. Up-to-date version of python bindings lie in bindings/python
parent 1af4a45f
all:
python setup.py build
install:
python setup.py install
clean:
rm -Rf build
from distutils.core import setup, Extension
FFMPEG_DIR = '../ffmpeg'
vlc = Extension('vlc',
sources = ['vlcmodule.c'],
include_dirs = ['../include'],
libraries = ['vlc', 'rt', 'dl' , 'pthread', 'ffmpeg', 'm',
'memcpymmx','stream_out_transcode',
'i420_rgb_mmx','i420_yuy2_mmx','i420_ymga_mmx',
'i422_yuy2_mmx','memcpymmxext','memcpy3dn',
'avcodec'],
library_dirs = [ '../lib',
'../modules/stream_out', '../modules/encoder/ffmpeg',
'../modules/misc/memcpy','../modules/video_chroma',
'../modules/codec/ffmpeg', FFMPEG_DIR + '/libavcodec'])
setup (name = 'PackageName',
version = '1.0',
description = 'This is a demonstration package',
ext_modules = [vlc])
#include <Python.h>
#include <vlc/vlc.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
static PyObject *vlc_create(PyObject *self, PyObject *args)
{
int iRc;
iRc = VLC_Create();
return Py_BuildValue("i", iRc);
}
static PyObject *vlc_init(PyObject *self, PyObject *args)
{
int iVlc;
char *pArgv[] = { "vlc", "--sout", NULL };
int iRc;
if (!PyArg_ParseTuple(args, "is", &iVlc, &pArgv[2]))
return NULL;
iRc = VLC_Init(iVlc, 3, pArgv);
return Py_BuildValue("i", iRc);
}
static PyObject *vlc_addTarget(PyObject *self, PyObject *args)
{
int iVlc;
char *file;
int iRc;
if (!PyArg_ParseTuple(args, "is", &iVlc, &file))
return NULL;
iRc = VLC_AddTarget(iVlc, file, 0, 0, PLAYLIST_APPEND, PLAYLIST_END);
return Py_BuildValue("i", iRc);
}
static PyObject *vlc_play(PyObject *self, PyObject *args)
{
int iVlc;
int iRc;
if (!PyArg_ParseTuple(args, "i", &iVlc))
return NULL;
iRc = VLC_Play(iVlc);
return Py_BuildValue("i", iRc);
}
static PyObject *vlc_stop(PyObject *self, PyObject *args)
{
int iVlc;
int iRc;
if (!PyArg_ParseTuple(args, "i", &iVlc))
return NULL;
iRc = VLC_CleanUp(iVlc);
return Py_BuildValue("i", iRc);
}
static PyObject *vlc_pause(PyObject *self, PyObject *args)
{
int iVlc;
int iRc;
if (!PyArg_ParseTuple(args, "i", &iVlc))
return NULL;
iRc = VLC_Pause(iVlc);
return Py_BuildValue("i", iRc);
}
static PyMethodDef VlcMethods[] = {
{"create", vlc_create, METH_VARARGS, _("Create a vlc thread.")},
{"init", vlc_init, METH_VARARGS, _("Initialize a vlc thread.")},
{"addTarget", vlc_addTarget, METH_VARARGS, _("Add a target in the playlist.")},
{"play", vlc_play, METH_VARARGS, _("Play")},
{"stop", vlc_stop, METH_VARARGS, _("Stop")},
{"pause", vlc_pause, METH_VARARGS, _("Pause")},
{NULL, NULL, 0, NULL} /* Sentinel */
};
void initvlc(void)
{
Py_InitModule("vlc", VlcMethods);
}
#!/usr/bin/python -O
#
# VideoLAN RTSP Server
#
# Author: Cyril Deguet <asmax@via.ecp.fr>
import cfg
from sap import SapServer
from session import Session
class AnnounceList:
"List of streams to be announced"
def __init__(self):
# Create the SAP server
self.multicastList = {}
self.sapServer = SapServer()
self.sapServer.start()
def readPlaylist(self):
pass
def addMulticastSession(self, session):
"Add a multicast session in the announce list"
self.multicastList[session.id] = session
def delMulticastSession(self, session):
"Delete a multicast session from the announce list"
del self.multicastList[session.id]
# Nice kludge to share global variables ;-)
pass
#!/usr/bin/python -O
#
# VideoLAN RTSP Server
#
# Author: Cyril Deguet <asmax@via.ecp.fr>
import cfg, string, threading
class PlayList:
"Contains the media playlist"
def __init__(self):
self.lock = threading.Lock()
def readConfig(self, filename):
"Read the playlist file"
f = open(filename)
newList = {}
while 1:
line = string.strip(f.readline())
if line == "":
break
items = string.split(line, '\t')
newList[items[0]] = {'file':items[1], 'name':items[2], 'addr':items[3]}
self.lock.acquire()
self.list = newList
self.lock.release()
def getMedia(self, uri):
"Return the description of an item in the playlist"
self.lock.acquire()
if self.list.has_key(uri):
media = self.list[uri]
else:
media = None
self.lock.release()
return media
#!/usr/bin/python
#
# VideoLAN RTSP Server
#
# Author: Cyril Deguet <asmax@via.ecp.fr>
#
# See: RFC 2326 Real Time Streaming Protocol
# RFC 2327 Session Description Protocol
import cfg, mimetools, re, socket, time, SocketServer, string, sys
from sap import SdpMessage
class RtspServerHandler(SocketServer.StreamRequestHandler):
"Request handler of the server socket"
version = "RTSP/1.0"
ok = "200 OK"
badRequest = "400 Bad request"
uriNotFound = "404 Not found"
sessionNotFound = "454 Session not found"
invalidHeader = "456 Header field not valid for resource"
internalError = "500 Internal server error"
notImplemented = "501 Not implemented"
def error(self, message, cseq):
self.wfile.write(self.version + " " + message + "\r\n" + \
"Cseq: " + cseq + "\r\n" + \
"\r\n")
def parseHeader(self, header):
"Split a RTCP header into a mapping of parameters"
list = map(string.strip, re.split('[; \n]*', header, re.S))
result = {}
for item in list:
m = re.match('([^=]*)(?:=(.*))?', item)
if m is None:
return None
result[m.group(1)] = m.group(2)
return result
def optionsMethod(self):
"Handle an OPTION request"
response = "Public: OPTIONS, DESCRIBE, SETUP, PLAY, PAUSE, PING, TEARDOWN\r\n" + \
"\r\n"
return response
def pingMethod(self, msg):
"Handle a PING request"
cseq = msg.getheader('cseq')
id = msg.getheader('Session')
if id is None:
self.error(self.badRequest, cseq)
return
response = "Session: " + id + "\r\n" + \
"\r\n"
return response
def describeMethod(self, msg, uri):
"Handle a DESCRIBE request"
cseq = msg.getheader('cseq')
# Find the URI in the playlist
media = cfg.playlist.getMedia(uri)
if media is None:
self.error(self.uriNotFound, cseq)
return None
message = SdpMessage(media['name'], media['addr'], uri)
description = message.getMessage()
size = `len(description)`
response = "Content-Type: application/sdp\r\n" + \
"Content-Length: " + size + "\r\n" + \
"\r\n" + description
return response
def setupMethod(self, msg, uri):
"Handle a SETUP request"
cseq = msg.getheader('cseq')
# Find the URI in the playlist
media = cfg.playlist.getMedia(uri)
if media is None:
self.error(self.uriNotFound, cseq)
return None
transportHeader = msg.getheader('transport')
if transportHeader is None:
self.error(self.badRequest, cseq)
return None
transport = self.parseHeader(transportHeader)
# Check the multicast/unicast fields in the headers
if transport.has_key('multicast'):
type = "multicast"
elif transport.has_key('unicast'):
type = "unicast"
else:
self.error(self.invalidHeader, cseq)
return None
# Check the destination field in the headers
dest= None
if transport.has_key('destination'):
dest = transport['destination']
if dest is None:
dest = media['addr'] # default destination address
id = cfg.sessionList.newSession(uri, dest)
if id is None:
self.error(self.internalError, cseq)
return None
response = "Session: " + id + "\r\n" + \
"Transport: RTP/MP2T/UDP;" + type + ";destination=" + dest + "\r\n" + \
"\r\n"
return response
def playMethod(self, msg, uri):
"Handle a PLAY request"
cseq = msg.getheader('cseq')
# Find the URI in the playlist
media = cfg.playlist.getMedia(uri)
if media is None:
self.error(self.uriNotFound, cseq)
return None
id = msg.getheader('Session')
session = cfg.sessionList.getSession(id)
if session is None:
self.error(self.sessionNotFound, cseq)
return None
if session.play() < 0:
self.error(self.internalError, cseq)
return None
response = "Session: " + id + "\r\n" + \
"\r\n"
return response
def pauseMethod(self, msg, uri):
"Handle a PAUSE request"
cseq = msg.getheader('cseq')
# Find the URI in the playlist
media = cfg.playlist.getMedia(uri)
if media is None:
self.error(self.uriNotFound, cseq)
return None
id = msg.getheader('Session')
session = cfg.sessionList.getSession(id)
if session is None:
self.error(self.sessionNotFound, cseq)
return None
if session.pause() < 0:
self.error(self.internalError, cseq)
return None
response = "Session: " + id + "\r\n" + \
"\r\n"
return response
def teardownMethod(self, msg, uri):
"Handle a TEARDOWN request"
cseq = msg.getheader('cseq')
# Find the URI in the playlist
media = cfg.playlist.getMedia(uri)
if media is None:
self.error(self.uriNotFound, cseq)
return None
id = msg.getheader('Session')
session = cfg.sessionList.getSession(id)
if session is None:
self.error(self.sessionNotFound, cseq)
return None
if session.stop() < 0:
self.error(self.internalError, cseq)
return None
if cfg.sessionList.delSession(id) < 0:
self.error(self.internalError, cseq)
return None
response = "\r\n"
return response
def parseRequest(self):
"Parse a RSTP request"
requestLine = self.rfile.readline()
m = re.match("(?P<method>[A-Z]+) (?P<uri>(\*|(?:(?P<protocol>rtsp|rtspu)://" + \
"(?P<host>[^:/]*)(:(?P<port>\d*))?(?P<path>.*)))) " + \
"RTSP/(?P<major>\d)\.(?P<minor>\d)", requestLine)
if m is None:
self.error(self.badRequest, "0")
return
uri = m.group('uri')
# Get the message headers
msg = mimetools.Message(self.rfile, "0")
cseq = msg.getheader('CSeq')
if cseq is None:
self.error(self.badRequest, "0")
return
method = m.group('method')
if method == 'OPTIONS':
response = self.optionsMethod()
elif method == 'DESCRIBE':
response = self.describeMethod(msg, uri)
elif method == 'SETUP':
response = self.setupMethod(msg, uri)
elif method == 'PLAY':
response = self.playMethod(msg, uri)
elif method == 'PAUSE':
response = self.pauseMethod(msg, uri)
elif method == 'PING':
response = self.pingMethod(msg)
elif method == 'TEARDOWN':
response = self.teardownMethod(msg, uri)
else:
self.error(self.notImplemented, cseq)
return
# Send the response
if response is None:
return
else:
self.wfile.write(self.version + " " + self.ok + "\r\n" + \
"CSeq: " + cseq + "\r\n" + \
response)
def handle(self):
"Handle an incoming request"
while 1:
try:
self.parseRequest()
except IOError:
return
rtsp://hostname.domain.org:1554/film1 /opt/media/film1.mpg A sample stream file 239.255.12.42
rtsp://hostname.domain.org:1554/film2 /opt/media/film2.mpg Another stream 239.255.42.12
#!/usr/bin/python -O
#
# VideoLAN RTSP Server
#
# Author: Cyril Deguet <asmax@via.ecp.fr>
import cfg,socket,struct,time,threading
def ntpTime():
"Return the current time in NTP decimal format"
return "%d" % (int(time.time()) + 2208988800L)
class SdpMessage:
"Build a SDP message"
uri = "http://www.videolan.org/"
def __init__(self, sessionName, address, uri):
"Build the message"
self.sessionName = sessionName
self.address = address
self.uri = uri
def getMessage(self):
"Return the SDP message"
msg = "v=0\r\n" + \
"o=asmax " + ntpTime() + " " + ntpTime() + \
" IN IP4 sphinx.via.ecp.fr\r\n" + \
"s=" + self.sessionName + "\r\n" + \
"u=" + self.uri + "\r\n" + \
"t=0 0\r\n" + \
"c=IN IP4 " + self.address + "/1\r\n" + \
"m=video 1234 RTP/MP2T 33\r\n" + \
"a=control:" + self.uri + "\r\n"
return msg
class SapServer(threading.Thread):
"SAP server class"
PORT = 9875
GROUP = "224.2.127.254"
TTL = 1
def __init__(self):
# Open the socket
self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, self.TTL)
self.sock.connect((self.GROUP, self.PORT))
def sendMessage(self, message):
"Message must be a SdpMessage"
# FIXME
header = " " + struct.pack("!BH", 12, 4212) + socket.inet_aton('138.195.156.214')
data = header + message.getMessage()
self.sock.send(data)
def announce(self):
for id, session in cfg.announceList.multicastList.items():
message = SdpMessage(session.name, session.dest, session.uri)
self.sendMessage(message)
def run(self):
while 1:
self.announce()
time.sleep(1)
#!/usr/bin/python -O
#
# VideoLAN RTSP Server
#
# Author: Cyril Deguet <asmax@via.ecp.fr>
import cfg, random, time
from streamer import VlcError, VlcStreamer
class Session:
"RTSP Session"
def __init__(self, id, uri, dest):
self.id = id
self.uri = uri
self.dest = dest
self.state = 'ready'
media = cfg.playlist.getMedia(self.uri)
self.fileName = media['file']
self.name = media['name']
address = "rtp/ts://" + dest
self.streamer = VlcStreamer(self.fileName, address)
def play(self):
"Play this session"
if self.state == 'playing':
print "Session " + self.id + " (" + self.fileName + "): already playing"
return 0
self.state = 'playing'
print "Session " + self.id + " (" + self.fileName + "): play"
try:
self.streamer.play()
except VlcError:
print "Streamer: play failed"
return -1
cfg.announceList.addMulticastSession(self)
return 0
def pause(self):
"Pause this session"
print "Session " + self.id + " (" + self.fileName + "): pause"
self.state = 'ready'
try:
self.streamer.pause()
except VlcError:
print "Streamer: pause failed"
return -1
return 0
def stop(self):
"Stop this session"
print "Session " + self.id + " (" + self.fileName + "): stop"
try:
self.streamer.stop()
except VlcError:
print "Streamer: stop failed"
return -1
return 0
class SessionList:
"Manages RTSP sessions"
list = {}
chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
def __init__(self):
self.rand = random.Random(time.time())
def newSessionId(self):
"Build a random session id"
id = ""
for x in range(12):
id += self.chars[self.rand.randrange(0, len(self.chars), 1)]
return id
def newSession(self, uri, dest):
"Create a new RTSP session"
id = self.newSessionId()
while self.list.has_key(id):
id = self.newSessionId()
try:
session = Session(id, uri, dest)
except VlcError:
print "Streamer: creation failed"
return None
self.list[id] = session