| from multiprocessing import Process, Queue |
| |
| |
| class BaseCamera(object): |
| process = {} # background process that reads frames from camera |
| frame = {} # frame queue |
| last_frame = {} |
| |
| def __init__(self, device): |
| """Start the background camera process if it isn't running yet.""" |
| self.device = device |
| BaseCamera.last_frame[self.device] = None |
| |
| if self.device not in BaseCamera.process: |
| BaseCamera.process[self.device] = None |
| |
| if BaseCamera.process[self.device] is None: |
| |
| BaseCamera.frame[device] = Queue(100) |
| |
| # start background frame process |
| BaseCamera.process[self.device] = Process(target=self._process, args=(self.device)) |
| BaseCamera.process[self.device].start() |
| |
| # wait until frames are available |
| BaseCamera.last_frame[self.device] = self.get_frame() |
| |
| def get_frame(self): |
| """Return the current camera frame.""" |
| |
| if BaseCamera.last_frame[self.device] is None: |
| BaseCamera.last_frame[self.device] = BaseCamera.frame[self.device].get(block=True) |
| return BaseCamera.last_frame[self.device] |
| elif not BaseCamera.frame[self.device].empty(): |
| BaseCamera.last_frame[self.device] = BaseCamera.frame[self.device].get() |
| return BaseCamera.last_frame[self.device] |
| else: |
| return BaseCamera.last_frame[self.device] |
| |
| def frames(self): |
| """"Generator that returns frames from the camera.""" |
| raise NotImplementedError('Must be implemented by subclasses.') |
| |
| def _process(self, device): |
| """Camera background process.""" |
| frames_iterator = self.frames() |
| for frame in frames_iterator: |
| BaseCamera.frame[device].put(frame, block=True) |
| |
| BaseCamera.process[device] = None |