-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmjpeg_client.py
88 lines (59 loc) · 2.28 KB
/
mjpeg_client.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
from http.client import HTTPConnection, IncompleteRead
from urllib.parse import urlparse
from threading import Thread
from time import sleep
class MJPEGClientIterator:
"""An iterable producing JPEG-encoded video frames from an MJPEG stream URL."""
def __init__(self, url):
o = urlparse(url)
h = HTTPConnection(o.hostname, port=o.port)
h.request('GET', o.path)
response = h.getresponse()
if response.status == 200:
self.response = response
mimetype, options = response.headers['Content-Type'].split("; ")
self._boundary = options.split("=")[1]
# print(mimetype, self._boundary)
else:
raise Exception("HTTP %d: %s" % (response.status, response.reason))
def __iter__(self):
"""Yields JPEG-encoded video frames."""
# TODO: handle chunked encoding delimited by marker instead
# of content-length.
while True:
length = None
#if line == (self._boundary+"\r\n").encode('ascii'):
while True:
l = self.response.fp.readline()
# print("Chunk start")
# l = self.response.fp.readline()
# l = self.response.fp.readline()
# print(l)
if l.startswith(b"Content-Length:"):
length = int(l.split(b" ")[1])
# print("found length", length)
if length is not None and l== b"\r\n":
break
yield self.response.fp.read(length)
# Look for an empty line, signifying the end of the headers.
class MJPEGClient:
def __init__(self, url):
self.url = url
self.__frame = None
self.__run = False
def start(self):
self.__run = True
self.__client = iter(MJPEGClientIterator(self.url))
self.__t = Thread(target=self.update)
self.__t.daemon = True
self.__t.start()
def update(self):
while self.__run:
self.__frame = next(self.__client)
def stop(self):
self.__run = False
def __iter__(self):
while self.__run and not self.__frame:
sleep(1)
while True:
yield self.__frame