Just for fun I created a OpenCV application in python without g-streamer (unless Python openCV uses it). And I let it save to disk M2 ssd. The framerate was not super stable but was pretty stable at 40fps.
So it seems that Orin cant save to disk at 3x60fps.
Here is the code below reproducing max working fps save to disk. It seems that gstreamer is not good enough in this particular case. I would like though to set the output FPS (since the discrete fps from the camera is either 60 or 10) with g-streamer to see if I can save 3x30 fps stable. something like
gst-launch-1.0 v4l2src device=/dev/video0 ! ‘video/x-raw , width=(int)1280 , height=(int)720 , format=(string)GRAY8 , framerate=(fraction)60/1’ ! nvvidconv ! ‘video/x-raw(memory:NVMM),width=(int)1280, height=(int)720, format=I420’ ! videorate ! ‘video/x-raw, framerate=(fraction)30/1’ ! nvv4l2h264enc ! h264parse ! multifilesink location=‘/mnt/fileshare01/HSP/240131_trials/ID0_Image01_1%09d.h264’
So incoming framerate with resolution by the camera in the first part then convert it to I420 and set framerate to 30. I would really like to know where the bottle neck is if Orin just cant manage the writing of the file to disk. The problem would result in 3x AGX Orin/Jetson Orin just for frame grabbing.
import cv2
import threading
import time
import os
def capture_and_save(camera_id, output_path_template, resolution=(1280, 720), show_fps=False):
# Open the camera
cap = cv2.VideoCapture(camera_id)
# Set the resolution
cap.set(cv2.CAP_PROP_FRAME_WIDTH, resolution[0])
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, resolution[1])
if not cap.isOpened():
print(f"Error: Unable to open camera {camera_id}")
return
# Initialize frame counter and FPS variables
frame_counter = 0
start_time = time.time()
fps_counter = 0
# Create the output directory if it doesn't exist
output_directory = "/home/localuser/Output"
os.makedirs(output_directory, exist_ok=True)
try:
while True:
# Capture frame-by-frame
ret, frame = cap.read()
if not ret:
print(f"Error: Couldn't read frame from camera {camera_id}")
break
# Save the frame to disk as JPEG with unique filename
output_path = os.path.join(output_directory, output_path_template.format(camera_id=camera_id, counter=frame_counter))
cv2.imwrite(output_path, frame, [cv2.IMWRITE_JPEG_QUALITY, 95])
# Increment frame counter
frame_counter += 1
# Calculate FPS and print every 10 seconds if show_fps is True
fps_counter += 1
elapsed_time = time.time() - start_time
if elapsed_time >= 10:
fps = fps_counter / elapsed_time
if show_fps:
print(f"Camera {camera_id} FPS: {fps:.2f}")
start_time = time.time()
fps_counter = 0
finally:
# Release the camera
cap.release()
def main():
# Set the camera IDs (0, 2, 4 for three different cameras)
camera_ids = [0, 2, 4]
# Create threads for each camera
threads = []
for i, camera_id in enumerate(camera_ids):
output_path_template = f"camera_{i + 1}_frame_{{counter}}.jpg"
thread = threading.Thread(target=capture_and_save, args=(camera_id, output_path_template))
threads.append(thread)
thread.start()
# Wait for all threads to finish
for thread in threads:
thread.join()
print("Image capture complete.")
if __name__ == "__main__":
main()