def record_to(self, dest): try: self.dest_path = dest os.makedirs(os.path.dirname(dest), exist_ok=True) self.dest_video = cv2.VideoWriter( self.dest_path, _FourCC, self.src_fps, (self.src_width, self.src_height)) except BaseException as exc: log.warn( f'VideoSource [{self.video_source_id}] - start record to {dest} failed: {exc}' )
def _write_frame(self, frame: np.ndarray): # noinspection PyBroadException try: if self.dest_video is not None: if frame is None: self._decode_frame() frame = self.cur_frame with self.dest_lock: self.dest_video.write(frame.astype('uint8')) except BaseException as exc: log.warn( f'VideoSource [{self.video_source_id}] - write frame failed: {exc}' )
def stop_record(self): # noinspection PyBroadException try: if self.dest_video is None: return video_writer = self.dest_video self.dest_video = None self.dest_path = None if video_writer is not None: with self.dest_lock: video_writer.release() except BaseException as exc: log.warn( f'VideoSource [{self.video_source_id}] - stop record failed: {exc}' )
def __init__( self, stream_url, video_config=None, video_source_id=None, event_listener=None, ): import copy log.warn( f'VideoSource init: stream_url={stream_url} video_config={video_config}' ) try: stream_url = int(stream_url) except ValueError: pass self.stream_url: str = stream_url self.video: Optional[cv2.VideoCapture] = None self.src_width = -1 self.src_height = -1 self.src_fps = -1 self.read_lock = Lock() self.dest_path = None self.dest_video = None self.dest_lock = Lock() self.cur_frame = None self.cur_frame_num = -1 self.decoded = False self.vidconfig: dict = copy.deepcopy(self.DfConfig) self.update_conf(video_config) self.video_source_id = video_source_id self.callback: Callable = event_listener self.stt = VideoSourceStt.Init self.corrupt = False self.scale_width = self.vidconfig['scale_width'] self.scale_height = self.vidconfig['scale_height'] self.auto_retry = self.vidconfig['auto_retry'] self.auto_pass = self.vidconfig['auto_pass'] self.stream_subscriber_ids = set() self.cur_frame_stream_data = None self.cur_frame_stream_id = -1
def start(self, first_access_check=True): if (self.stt is VideoSourceStt.TryingToCapture or self.stt is VideoSourceStt.Running or self.stt is VideoSourceStt.Retrying): return if first_access_check and not self.check(): raise IOError('Access video failed') log.warn(f'VideoSource [{self.video_source_id}] - connecting...') self.stt = VideoSourceStt.TryingToCapture self.video = self._get_video() self._get_video_info() if self.video is None: self._notify_listener(VideoSourceStt.Stopped) raise IOError('Access video failed') self.corrupt = False self.stt = VideoSourceStt.Running if self.auto_pass: thread = Thread(target=self._stream_loop) thread.daemon = True thread.start()
def _stream_loop(self): self.cur_frame_num = -1 while not self.corrupt and self.auto_pass: grabbed = self.video.grab() if not grabbed: if self.auto_retry: self.video = self._get_video() self._get_video_info() continue else: self.stop() break self.decoded = False _WriteVideoExecutor.submit(self._write_frame, None) if sys.getsizeof(self.cur_frame_num) > _FrameNumStorage: self.cur_frame_num = 0 else: self.cur_frame_num += 1 log.warn(f'VideoSource [{self.video_source_id}] - stopped') self.stt = VideoSourceStt.Stopped
def _get_video(self): with self.read_lock: video = None while not self.corrupt: # noinspection PyBroadException try: video = cv2.VideoCapture(self.stream_url) if video.isOpened(): log.warn( f'VideoSource [{self.video_source_id}] - connect successfully, streaming' ) self._notify_listener(VideoSourceStt.Running) self.stt = VideoSourceStt.Running break except BaseException: pass if not self.auto_retry: log.warn( f'VideoSource [{self.video_source_id}] - connect failed, stopped' ) self._notify_listener(VideoSourceStt.Stopped) self.stt = VideoSourceStt.Stopped break if self.stt is not VideoSourceStt.Retrying: self.stt = VideoSourceStt.Retrying log.warn( f'VideoSource [{self.video_source_id}] - connect failed') self._notify_listener(VideoSourceStt.Stopped) time.sleep(3) log.warn( f'VideoSource [{self.video_source_id}] - retry connect') return video