blob: fd4d653b5a4c2374ebe7a5ff1dd49a211ff0b4c1 [file] [log] [blame]
Shad Ansari26682be2021-10-26 03:52:35 +00001from multiprocessing import Process, Queue
Shad Ansari30a23732021-09-29 23:07:21 -07002
3
4class BaseCamera(object):
Shad Ansari26682be2021-10-26 03:52:35 +00005 process = {} # background process that reads frames from camera
Shad Ansaric9f48d32021-10-25 19:03:34 +00006 frame = {} # frame queue
Shad Ansari58644202021-11-01 15:04:43 +00007 last_frame = {}
Shad Ansari30a23732021-09-29 23:07:21 -07008
Shad Ansari58644202021-11-01 15:04:43 +00009 def __init__(self, device):
Shad Ansari26682be2021-10-26 03:52:35 +000010 """Start the background camera process if it isn't running yet."""
Shad Ansaric0726e62021-10-04 22:38:53 +000011 self.device = device
Shad Ansari58644202021-11-01 15:04:43 +000012 BaseCamera.last_frame[self.device] = None
13
Shad Ansari26682be2021-10-26 03:52:35 +000014 if self.device not in BaseCamera.process:
15 BaseCamera.process[self.device] = None
Shad Ansari58644202021-11-01 15:04:43 +000016
Shad Ansari26682be2021-10-26 03:52:35 +000017 if BaseCamera.process[self.device] is None:
Shad Ansaric9f48d32021-10-25 19:03:34 +000018
Shad Ansari58644202021-11-01 15:04:43 +000019 BaseCamera.frame[device] = Queue(100)
Shad Ansari30a23732021-09-29 23:07:21 -070020
Shad Ansari26682be2021-10-26 03:52:35 +000021 # start background frame process
22 BaseCamera.process[self.device] = Process(target=self._process, args=(self.device))
23 BaseCamera.process[self.device].start()
Shad Ansari30a23732021-09-29 23:07:21 -070024
25 # wait until frames are available
Shad Ansari58644202021-11-01 15:04:43 +000026 BaseCamera.last_frame[self.device] = self.get_frame()
Shad Ansari30a23732021-09-29 23:07:21 -070027
28 def get_frame(self):
29 """Return the current camera frame."""
Shad Ansari30a23732021-09-29 23:07:21 -070030
Shad Ansari58644202021-11-01 15:04:43 +000031 if BaseCamera.last_frame[self.device] is None:
32 BaseCamera.last_frame[self.device] = BaseCamera.frame[self.device].get(block=True)
33 return BaseCamera.last_frame[self.device]
34 elif not BaseCamera.frame[self.device].empty():
35 BaseCamera.last_frame[self.device] = BaseCamera.frame[self.device].get()
36 return BaseCamera.last_frame[self.device]
37 else:
38 return BaseCamera.last_frame[self.device]
Shad Ansari30a23732021-09-29 23:07:21 -070039
Shad Ansari341ca3a2021-09-30 12:10:00 -070040 def frames(self):
Shad Ansari30a23732021-09-29 23:07:21 -070041 """"Generator that returns frames from the camera."""
Shad Ansari341ca3a2021-09-30 12:10:00 -070042 raise NotImplementedError('Must be implemented by subclasses.')
Shad Ansari30a23732021-09-29 23:07:21 -070043
Shad Ansari26682be2021-10-26 03:52:35 +000044 def _process(self, device):
45 """Camera background process."""
Shad Ansari30a23732021-09-29 23:07:21 -070046 frames_iterator = self.frames()
47 for frame in frames_iterator:
Shad Ansaric9f48d32021-10-25 19:03:34 +000048 BaseCamera.frame[device].put(frame, block=True)
Shad Ansari4ae11682021-10-22 18:51:53 +000049
Shad Ansari26682be2021-10-26 03:52:35 +000050 BaseCamera.process[device] = None