From 7d2ff5d7e382d20828ed5a83895312177411fede Mon Sep 17 00:00:00 2001 From: shoofle Date: Tue, 30 Jul 2024 00:28:39 -0400 Subject: [PATCH] trying (and failing?) to get hw acceleration --- Pipfile | 1 + Pipfile.lock | 11 ++++- webcam.py | 137 +++++++++++++++++++++++++++++---------------------- 3 files changed, 90 insertions(+), 59 deletions(-) diff --git a/Pipfile b/Pipfile index 7ce390f..03ffc95 100644 --- a/Pipfile +++ b/Pipfile @@ -5,6 +5,7 @@ name = "pypi" [packages] opencv-python = "*" +wakepy = "*" [dev-packages] diff --git a/Pipfile.lock b/Pipfile.lock index f2c2a80..c3bff7c 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "9cd65918174126dae7310623cabe06ec6e5ce3f1bb0e255262749a78a55d3839" + "sha256": "943975627c31fb661a3a1e3a77e80b2e5634baf439d615ccba41a14d7edf09b1" }, "pipfile-spec": 6, "requires": { @@ -80,6 +80,15 @@ "index": "pypi", "markers": "python_version >= '3.6'", "version": "==4.10.0.84" + }, + "wakepy": { + "hashes": [ + "sha256:4e7e820512e0e69f9aa5fdded2d3225e6f7c9f000814300e8c37d1fa88fe1664", + "sha256:fee0722b554a859724f6f47ec28db1d513f15097f235b09ebb1b58f545f90db2" + ], + "index": "pypi", + "markers": "python_version >= '3.7'", + "version": "==0.9.1" } }, "develop": {} diff --git a/webcam.py b/webcam.py index 1644c4f..f2cbfc7 100644 --- a/webcam.py +++ b/webcam.py @@ -1,86 +1,107 @@ from datetime import datetime, date, time, timedelta import os import cv2 +from wakepy import keep def five_minute_segment_from(the_time): - return the_time.replace(minute=(the_time.minute // 1)*1, second=0, microsecond=0) + # this is mocked out too be a one minute segment instead + return the_time.replace(second=0, microsecond=0) + #return the_time.replace(minute=(the_time.minute // 1)*1, second=0, microsecond=0) + def path_to_video_at(time_stamp): - return 'videos/' + str(time_stamp) + '.mkv' + return 'videos/' + str(time_stamp) + '.mkv' # mkv required for h264 encoding -#delay for long delay -long_delay = timedelta(hours=1) +os.environ["OPENCV_FFMPEG_CAPTURE_OPTIONS"]="hwaccel;vaapi;hw_decoders_any;vaapi,vdpau" # maybe this enables hardware accelerated ffmpeg? +#delay for long delay +long_delay = timedelta(minutes=1) -queue = [(False, None)] * 100 #queue of recent frames last_time_stamp = five_minute_segment_from(datetime.now()) # live webcam feed -camera = cv2.VideoCapture(0) +camera = cv2.VideoCapture(0, cv2.CAP_FFMPEG) if not camera.isOpened(): print("Cannot open camera") exit() # video writer fourcc = cv2.VideoWriter_fourcc(*'H264') -out = cv2.VideoWriter(path_to_video_at(last_time_stamp), fourcc, camera.get(cv2.CAP_PROP_FPS), (int(camera.get(3)),int(camera.get(4)))) +video_writer = cv2.VideoWriter(path_to_video_at(last_time_stamp), + fourcc, + camera.get(cv2.CAP_PROP_FPS), + (int(camera.get(3)),int(camera.get(4))), + (cv2.VIDEOWRITER_PROP_HW_ACCELERATION, cv2.VIDEO_ACCELERATION_ANY) + ) # video feed from previously captured video -old_time = cv2.VideoCapture(path_to_video_at(last_time_stamp)) +old_time = cv2.VideoCapture(path_to_video_at(last_time_stamp), cv2.CAP_FFMPEG) +# fullscreen window yess good cv2.namedWindow("mirror", cv2.WINDOW_NORMAL) cv2.setWindowProperty("mirror", cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN) -idx = 0 -offset = 0 -longterm = False -while(True): - if last_time_stamp != five_minute_segment_from(datetime.now()): - # find file older than our long delay - old_file = path_to_video_at(five_minute_segment_from(datetime.now() - long_delay - timedelta(minutes=5))) - print(f"deleting old file {old_file}") - os.remove(old_file) - - out.release() - out = cv2.VideoWriter(path_to_video_at(last_time_stamp), - fourcc, - camera.get(cv2.CAP_PROP_FPS), - (int(camera.get(3)), int(camera.get(4))) - ) - if old_time.isOpened(): - old_time.release() - - new_file = path_to_video_at(five_minute_segment_from(datetime.now() - timedelta(minutes=10))) - pint(f"opening the previously recorded file {new_file} to read from for long mirror") - old_time = cv2.VideoCapture(new_file) - - last_time_stamp = five_minute_segment_from(datetime.now()) - - ret, frame = camera.read() - frame = cv2.flip(frame, 1) - - # record the frame to the appropriate file, and also to the short term buffer - out.write(frame) - queue[idx] = ret, frame - - prev_frame_valid, prev_frame = queue[(idx - offset) % len(queue)] - old_frame_valid, old_frame = old_time.read() - if not longterm and prev_frame_valid: - cv2.imshow('mirror', prev_frame) - elif longterm and old_frame_valid: - cv2.imshow('mirror', old_frame) - - key = cv2.waitKey(16) # listen for keyprress for some number of ms - if key & 0xFF == ord('q') or key == 27: # q or esc - break - if key & 0xFF == ord('a'): - offset += 1 - if key & 0xFF == ord('d'): - offset -= 1 - if key & 0xFF == ord('z'): - longterm = not longterm - - idx = (idx + 1) % len(queue) +queue = [(False, None)] * 100 #queue of recent frames +idx = 0 # current index into the frame queue +short_term_delay_frames = 20 # hoow many frames back are we going in the buffer when we're on a short term delay? +longterm = False # are we shoowing a long term delay? (versus a sshort term delay) + +with keep.presenting(): + while(True): + if last_time_stamp != five_minute_segment_from(datetime.now()): + # find file older than our long delay + old_file = path_to_video_at(five_minute_segment_from(datetime.now() - long_delay - timedelta(minutes=1))) + if os.path.isfile(old_file): + print(f"deleting old file {old_file}") + os.remove(old_file) + + video_writer.release() + newly_recording_file = path_to_video_at(five_minute_segment_from(datetime.now())) + + print(f"opening {newly_recording_file} too record this upcoming ssegment to") + video_writer = cv2.VideoWriter(newly_recording_file, + fourcc, + camera.get(cv2.CAP_PROP_FPS), + (int(camera.get(3)), int(camera.get(4))), + (cv2.VIDEOWRITER_PROP_HW_ACCELERATION, cv2.VIDEO_ACCELERATION_ANY) + ) + + + if old_time.isOpened(): + old_time.release() + + new_file = path_to_video_at(five_minute_segment_from(datetime.now() - long_delay)) + print(f"opening the previously recorded file {new_file} to read from for long mirror") + old_time = cv2.VideoCapture(new_file, cv2.CAP_FFMPEG) + + + last_time_stamp = five_minute_segment_from(datetime.now()) + + ret, frame = camera.read() + frame = cv2.flip(frame, 1) + + # record the frame to the appropriate file, and also to the short term buffer + video_writer.write(frame) + queue[idx] = ret, frame + + prev_frame_valid, prev_frame = queue[(idx - short_term_delay_frames) % len(queue)] + old_frame_valid, old_frame = old_time.read() + if not longterm and prev_frame_valid: + cv2.imshow('mirror', prev_frame) + elif longterm and old_frame_valid: + cv2.imshow('mirror', old_frame) + + key = cv2.waitKey(16) # listen for keyprress for 16 ms + if key & 0xFF == ord('q') or key == 27: # q or esc + break + if key & 0xFF == ord('a'): + short_term_delay_frames += 1 + if key & 0xFF == ord('d'): + short_term_delay_frames -= 1 + if key & 0xFF == ord('z'): + longterm = not longterm + + idx = (idx + 1) % len(queue) # After the loop release the cap object camera.release()