improve frame memory management

This commit is contained in:
Blake Blackshear 2020-10-24 11:36:04 -05:00
parent 49258d6dbe
commit 35ba5e2f7c
3 changed files with 29 additions and 25 deletions

View File

@ -127,11 +127,11 @@ lxc.cap.drop:
``` ```
### Calculating shm-size ### Calculating shm-size
The default shm-size of 64m should be fine for most setups. If you start seeing segfault errors, it could be because you have too many high resolution cameras and you need to specify a higher shm size. The default shm-size of 64m is fine for setups with 3 or less 1080p cameras. If frigate is exiting with "Bus error" messages, it could be because you have too many high resolution cameras and you need to specify a higher shm size.
You can calculate the necessary shm-size for each camera with the following formula: You can calculate the necessary shm-size for each camera with the following formula:
``` ```
(width * height * 3 + 270480)/1048576 = <shm size in mb> (width * height * 1.5 * 7 + 270480)/1048576 = <shm size in mb>
``` ```
[Back to top](#documentation) [Back to top](#documentation)

View File

@ -185,7 +185,7 @@ def main():
config['zones'] = config.get('zones', {}) config['zones'] = config.get('zones', {})
# Queue for cameras to push tracked objects to # Queue for cameras to push tracked objects to
tracked_objects_queue = mp.Queue() tracked_objects_queue = mp.Queue(maxsize=len(CONFIG['cameras'].keys())*2)
# Queue for clip processing # Queue for clip processing
event_queue = mp.Queue() event_queue = mp.Queue()

View File

@ -127,34 +127,37 @@ def capture_frames(ffmpeg_process, camera_name, frame_shape, frame_manager: Fram
print(f"{camera_name}: stop event set. exiting capture thread...") print(f"{camera_name}: stop event set. exiting capture thread...")
break break
frame_bytes = ffmpeg_process.stdout.read(frame_size)
current_frame.value = datetime.datetime.now().timestamp() current_frame.value = datetime.datetime.now().timestamp()
frame_name = f"{camera_name}{current_frame.value}"
frame_buffer = frame_manager.create(frame_name, frame_size)
try:
frame_buffer[:] = ffmpeg_process.stdout.read(frame_size)
except:
print(f"{camera_name}: ffmpeg sent a broken frame. something is wrong.")
if len(frame_bytes) < frame_size: if ffmpeg_process.poll() != None:
print(f"{camera_name}: ffmpeg sent a broken frame. something is wrong.") print(f"{camera_name}: ffmpeg process is not running. exiting capture thread...")
frame_manager.delete(frame_name)
break
if ffmpeg_process.poll() != None: continue
print(f"{camera_name}: ffmpeg process is not running. exiting capture thread...")
break
else:
continue
fps.update() fps.update()
frame_num += 1 frame_num += 1
if (frame_num % take_frame) != 0: if (frame_num % take_frame) != 0:
skipped_fps.update() skipped_fps.update()
frame_manager.delete(frame_name)
continue continue
# if the queue is full, skip this frame # if the queue is full, skip this frame
if frame_queue.full(): if frame_queue.full():
skipped_fps.update() skipped_fps.update()
frame_manager.delete(frame_name)
continue continue
# put the frame in the frame manager # close the frame
frame_buffer = frame_manager.create(f"{camera_name}{current_frame.value}", frame_size) frame_manager.close(frame_name)
frame_buffer[:] = frame_bytes[:]
frame_manager.close(f"{camera_name}{current_frame.value}")
# add to the queue # add to the queue
frame_queue.put(current_frame.value) frame_queue.put(current_frame.value)
@ -282,9 +285,6 @@ def process_frames(camera_name: str, frame_queue: mp.Queue, frame_shape,
print(f"{camera_name}: frame {frame_time} is not in memory store.") print(f"{camera_name}: frame {frame_time} is not in memory store.")
continue continue
fps_tracker.update()
fps.value = fps_tracker.eps()
# look for motion # look for motion
motion_boxes = motion_detector.detect(frame) motion_boxes = motion_detector.detect(frame)
@ -355,9 +355,13 @@ def process_frames(camera_name: str, frame_queue: mp.Queue, frame_shape,
# now that we have refined our detections, we need to track objects # now that we have refined our detections, we need to track objects
object_tracker.match_and_update(frame_time, detections) object_tracker.match_and_update(frame_time, detections)
# add to the queue # add to the queue if not full
detected_objects_queue.put((camera_name, frame_time, object_tracker.tracked_objects)) if(detected_objects_queue.full()):
frame_manager.delete(f"{camera_name}{frame_time}")
detection_fps.value = object_detector.fps.eps() continue
else:
frame_manager.close(f"{camera_name}{frame_time}") fps_tracker.update()
fps.value = fps_tracker.eps()
detected_objects_queue.put((camera_name, frame_time, object_tracker.tracked_objects))
detection_fps.value = object_detector.fps.eps()
frame_manager.close(f"{camera_name}{frame_time}")