-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathstreamer.py
executable file
·139 lines (131 loc) · 4.25 KB
/
streamer.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
###
# RTP/RTCP streamer
###
import random
import select
import socket
import sys
import time
import RTP
import os
import scp
import wav
import helpers
import signal
class Client():
rtp = 0 # rtp port
rtcp = 0 # rtcp port
STREAM = False # bool,if streaming on for this client
ip = '' # # Client ip
index = 0 # song byte index
sequence = random.randint(1,10000)
timestamp = random.randint(1,10000)
def bind(PORT):
""" Create UDP socket and bind given port with it. """
#HOST = '127.0.0.1' # Local host
HOST = helpers.tcpLocalIp()
s = None
for res in socket.getaddrinfo(HOST, PORT, socket.AF_UNSPEC, socket.SOCK_DGRAM):
af, socktype, proto, canonname, sa = res
try:
s = socket.socket(af, socktype, proto)
except socket.error as msg:
print 'Streamer: '+str(msg)
s = None
continue
try:
s.bind(sa)
except socket.error as msg:
print 'Streamer: '+str(msg)
s.close()
s = None
continue
break
return s
def SIGTERMhandler(signum, frame):
exit(0)
def SIGINThandler(signum, frame):
exit(0)
# One streamer per song/record for all clients
def main():
signal.signal(signal.SIGINT, SIGINThandler)
signal.signal(signal.SIGTERM, SIGTERMhandler)
""" Control section for streamer. """
# Create unix socket for IPC
socket_path = sys.argv[2]
if os.path.exists(socket_path): #Caution
sys.exit(1)
unix_socket = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
unix_socket.bind(socket_path)
# Create rtp and rtcp socket
while True:
while True:
port = random.randint(10000,65000)
rtp_socket = bind(port)
if rtp_socket is None:
continue
else:
break
rtcp_socket = bind(port + 1)
if rtcp_socket is None:
rtp_socket.close()
else:
break
inputs = []
inputs.append(unix_socket) # Add unix socket
inputs.append(rtcp_socket) # Add rtcp socket
# Is list filled once
ONCE = False
# List of client
clients = dict() #dict containing all clients for this song
rtpheader = RTP.RTPMessage(24567)
wavef = wav.Wave(sys.argv[1])
song = wavef.getdata()
songsize = wavef.getnframes()
while True:
try:
inputready,outputready,exceptready = select.select(inputs,[],[],0)
except select.error as msg:
print 'Streamer: '+str(msg)
for option in inputready:
if option is unix_socket:
data,addr = unix_socket.recvfrom(1024)
m = scp.SCPMessage()
t = m.parse(data)
if m.command == "SETUP":
ONCE = True
c = Client()
c.rtp = m.clientRtpPort
c.rtcp = m.clientRtcpPort
c.ip = m.clientIp
clients[addr] = c
unix_socket.sendto(m.createPort(None,str(port),str(port+1)),addr)
elif m.command == "TEARDOWN":
clients.pop(addr)
elif m.command == "PLAY":
clients[addr].STREAM = True
unix_socket.sendto(m.createRunning(str(clients[addr].sequence), str(clients[addr].timestamp)),addr)
elif m.command == "PAUSE":
clients[addr].STREAM = False
if option is rtcp_socket:
data = rtcp_socket.recv(1024)
pass
vs = clients.values()
for v in vs:
if v.STREAM and v.index < songsize:
buff = rtpheader.createMessage(v.sequence,v.timestamp,0)
packet = buffer(buff)
packet = packet + song[v.index:v.index+1400]
rtp_socket.sendto(packet,(v.ip,int(v.rtp)))
v.index = v.index + 1400
v.sequence = v.sequence + 1
v.timestamp = v.timestamp + 1400
time.sleep(0.175)
if ONCE and len(clients) == 0:
break
unix_socket.close()
os.remove(socket_path)
rtp_socket.close()
rtcp_socket.close()
if __name__ == "__main__":
main()