mirror of
				https://github.com/blakeblackshear/frigate.git
				synced 2025-10-27 10:52:11 +01:00 
			
		
		
		
	experimental: running ffmpeg directly and capturing raw frames
This commit is contained in:
		
							parent
							
								
									9f8278ea8f
								
							
						
					
					
						commit
						2b51dc3e5b
					
				| @ -52,7 +52,8 @@ RUN  pip install -U pip \ | ||||
|  numpy \ | ||||
|  Flask \ | ||||
|  paho-mqtt \ | ||||
|  PyYAML | ||||
|  PyYAML \ | ||||
|  ffmpeg-python | ||||
| 
 | ||||
| # Download & build OpenCV | ||||
| RUN wget -q -P /usr/local/src/ --no-check-certificate https://github.com/opencv/opencv/archive/4.0.1.zip | ||||
|  | ||||
| @ -90,12 +90,12 @@ class FramePrepper(threading.Thread): | ||||
|                 frame_time = self.frame_time.value | ||||
|              | ||||
|             # convert to RGB | ||||
|             cropped_frame_rgb = cv2.cvtColor(cropped_frame, cv2.COLOR_BGR2RGB) | ||||
|             #cropped_frame_rgb = cv2.cvtColor(cropped_frame, cv2.COLOR_BGR2RGB) | ||||
|             # Resize to 300x300 if needed | ||||
|             if cropped_frame_rgb.shape != (300, 300, 3): | ||||
|                 cropped_frame_rgb = cv2.resize(cropped_frame_rgb, dsize=(300, 300), interpolation=cv2.INTER_LINEAR) | ||||
|             if cropped_frame.shape != (300, 300, 3): | ||||
|                 cropped_frame = cv2.resize(cropped_frame, dsize=(300, 300), interpolation=cv2.INTER_LINEAR) | ||||
|             # Expand dimensions since the model expects images to have shape: [1, 300, 300, 3] | ||||
|             frame_expanded = np.expand_dims(cropped_frame_rgb, axis=0) | ||||
|             frame_expanded = np.expand_dims(cropped_frame, axis=0) | ||||
| 
 | ||||
|             # add the frame to the queue | ||||
|             if not self.prepped_frame_queue.full(): | ||||
|  | ||||
| @ -6,6 +6,7 @@ import threading | ||||
| import ctypes | ||||
| import multiprocessing as mp | ||||
| import numpy as np | ||||
| import ffmpeg | ||||
| from . util import tonumpyarray | ||||
| from . object_detection import FramePrepper | ||||
| from . objects import ObjectCleaner, BestPersonFrame | ||||
| @ -16,48 +17,41 @@ def fetch_frames(shared_arr, shared_frame_time, frame_lock, frame_ready, frame_s | ||||
|     # convert shared memory array into numpy and shape into image array | ||||
|     arr = tonumpyarray(shared_arr).reshape(frame_shape) | ||||
| 
 | ||||
|     # start the video capture | ||||
|     video = cv2.VideoCapture() | ||||
|     video.open(rtsp_url) | ||||
|     print("Opening the RTSP Url...") | ||||
|     # keep the buffer small so we minimize old data | ||||
|     video.set(cv2.CAP_PROP_BUFFERSIZE,1) | ||||
|     ffmpeg_process = ( | ||||
|         ffmpeg | ||||
|         .input(rtsp_url,  | ||||
|             rtsp_transport="tcp",  | ||||
|             stimeout=5000000,  | ||||
|             use_wallclock_as_timestamps=1, | ||||
|             fflags="+genpts", | ||||
|             avoid_negative_ts="make_zero") | ||||
|         .output('pipe:', format='rawvideo', pix_fmt='rgb24') | ||||
|     ) | ||||
| 
 | ||||
|     print(ffmpeg_process.compile()) | ||||
| 
 | ||||
|     ffmpeg_process = ffmpeg_process.run_async(pipe_stdout=True) | ||||
| 
 | ||||
|     bad_frame_counter = 0 | ||||
|     while True: | ||||
|         # check if the video stream is still open, and reopen if needed | ||||
|         if not video.isOpened(): | ||||
|             success = video.open(rtsp_url) | ||||
|             if not success: | ||||
|                 time.sleep(1) | ||||
|                 continue | ||||
|         # grab the frame, but dont decode it yet | ||||
|         ret = video.grab() | ||||
|         # snapshot the time the frame was grabbed | ||||
|         frame_time = datetime.datetime.now() | ||||
|         if ret: | ||||
|             # go ahead and decode the current frame | ||||
|             ret, frame = video.retrieve() | ||||
|             if ret: | ||||
|                 # Lock access and update frame | ||||
|                 with frame_lock: | ||||
|                     arr[:] = frame | ||||
|                     shared_frame_time.value = frame_time.timestamp() | ||||
|                 # Notify with the condition that a new frame is ready | ||||
|                 with frame_ready: | ||||
|                     frame_ready.notify_all() | ||||
|                 bad_frame_counter = 0 | ||||
|             else: | ||||
|                 print("Unable to decode frame") | ||||
|                 bad_frame_counter += 1 | ||||
|         else: | ||||
|             print("Unable to grab a frame") | ||||
|             bad_frame_counter += 1 | ||||
|          | ||||
|         if bad_frame_counter > 100: | ||||
|             video.release() | ||||
|      | ||||
|     video.release() | ||||
|         in_bytes = ffmpeg_process.stdout.read(frame_shape[0] * frame_shape[1] * frame_shape[2]) | ||||
|         if not in_bytes: | ||||
|             print("No bytes received. Waiting 1 second before trying again.") | ||||
|             time.sleep(1) | ||||
|             continue | ||||
|         frame = ( | ||||
|             np | ||||
|             .frombuffer(in_bytes, np.uint8) | ||||
|             .reshape(frame_shape) | ||||
|         ) | ||||
|         # Lock access and update frame | ||||
|         with frame_lock: | ||||
|             shared_frame_time.value = datetime.datetime.now().timestamp() | ||||
|             arr[:] = frame | ||||
|         # Notify with the condition that a new frame is ready | ||||
|         with frame_ready: | ||||
|             frame_ready.notify_all() | ||||
| 
 | ||||
|     ffmpeg_process.wait() | ||||
| 
 | ||||
| # Stores 2 seconds worth of frames when motion is detected so they can be used for other threads | ||||
| class FrameTracker(threading.Thread): | ||||
| @ -279,7 +273,7 @@ class Camera: | ||||
|             frame = self.shared_frame_np.copy() | ||||
| 
 | ||||
|         # convert to RGB for drawing | ||||
|         frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) | ||||
|         #frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) | ||||
|         # draw the bounding boxes on the screen | ||||
|         for obj in detected_objects: | ||||
|             color = (255,0,0) | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user