-
Notifications
You must be signed in to change notification settings - Fork 0
/
multistream.py
175 lines (135 loc) · 5.61 KB
/
multistream.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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
import socket
import picamera
from Queue import Queue
from threading import Thread
kBeginOfMessage = 0b10000000
kEndOfMessage = 0b11000000
# This class exists so that the camera can use it as the file
# fileLikeObject it needs to write to. This object will then
# write the data into multiple clients.
class MultiWrite(file):
items = []
def write(self, data):
if self.items != None:
for writableObject in self.items:
writableObject.write(data)
def close(self):
if self.items != None:
for writableObject in self.items:
writableObject,close()
def flush(self):
if self.items != None:
for writableObject in self.items:
writableObject.flush()
def __str__(self):
return "MultiWrite instance with items: %s" % (self.items,)
def startRecordingIntoStream(fileLikeObject):
if not fileLikeObject in multiWrite.items:
print "appending %s to %s items" % (fileLikeObject, multiWrite)
multiWrite.items.append(fileLikeObject)
else:
print "%s already in multiWrite.items: %s" % (fileLikeObject, multiWrite.items)
if not camera.recording:
print "camera starting now"
camera.start_recording(multiWrite, format='h264', intra_period = 1, bitrate=0, quality=35)
#camera.start_recording(multiWrite, format='h264', intra_period = 1, bitrate=1200000)
else:
print "camera already recording"
def stopRecordingIntoStream(fileLikeObject):
if fileLikeObject in multiWrite.items:
print "removing ", fileLikeObject
multiWrite.items.remove(fileLikeObject)
else:
print "now removing ", fileLikeObject
if len(multiWrite.items) == 0:
print "no more listeners, stopping camera recording"
camera.stop_recording()
else:
print "camera continues to record, number of items in multiWrite is %s" % (len(multiWrite.items),)
def handleMessage(message, fileLikeObject):
for byte in message:
print "byte: ", ord(byte)
print "-- end of message --"
if ord(message[1]) == 0b00000001:
startRecordingIntoStream(fileLikeObject)
if ord(message[1]) == 0b00000000:
stopRecordingIntoStream(fileLikeObject)
def listenForBytes(connection, multiWrite):
fileLikeObject = connection.makefile('sb')
while True:
data = connection.recv(1026)
currentMessage = None
if not data:
print "%s has no more data, now considering it disconnected and closing the connection""" % (connection,)
stopRecordingIntoStream(fileLikeObject)
# maybe the connection did not actually disconnect
# so we make sure it really is disconnected and in
# this way the client knows we shut down
try:
connection.shutdown(2)
connection.close
except Exception as instance:
# print type(instance) # the exception instance
# print instance.args # arguments stored in .args
# print instance # __str__ logs args to be printed directly
print "Unable to close a connection that returns not more data: %s" % (instance,)
break
else:
for byte in data:
binaryByte = ord(byte)
if binaryByte == kBeginOfMessage:
currentMessage = byte
elif binaryByte == kEndOfMessage:
currentMessage += byte
handleMessage(currentMessage, fileLikeObject)
currentMessage = []
else:
if currentMessage != None:
currentMessage += byte
else:
print "Programming error: trying to appent a byte to the currentMessage, but there is no currentmessage yet."
# create a file-object that writes into the void (well it actually,
# writes into the sub-items, so this string is not really relevant).
multiWrite = MultiWrite("/dev/null")
try:
camera = picamera.PiCamera()
camera.led = False
camera.framerate = 30
camera.brightness = 50
camera.rotation = 270 # valid values are: 0, 90, 180, 270
print ""
print "camera rotation: %s" % (camera.rotation,)
print "camera on"
print "cameraresolution: %s" % (camera.resolution,)
print "framerate: %s" % (camera.framerate,)
print "brightness: %s" % (camera.brightness,)
except Exception as instance:
print "Unable to enable the camera: %s" % (instance,)
exit("1")
# setup a socket to listen on port 80
try:
socket = socket.socket()
host = ""
port = 82
socket.bind((host, port))
socket.listen(82)
print "socket set up"
except Exception as instance:
print "Unable to setup a listening socket: %s" % (instance,)
exit("1")
# this will run forever until the the socket closes / client disconnects / error in socket occurs
while True:
try:
connection, addr = socket.accept()
worker = Thread(target=listenForBytes, args=(connection,multiWrite))
worker.setDaemon(True)
worker.start()
print "Got connection from %s %s" % (connection, addr)
except ValueError:
print "ERROR IN MAIN WHILE LOOP: ", ValueError
print "Now shutting down socket and closing it."
# The constants SHUT_RD, SHUT_WR, SHUT_RDWR have the values 0, 1, 2,
# respectively, and are defined in <sys/socket.h> since glibc-2.1.91.
socket.shutdown(2)
socket.close
break