SVO recording crashes when used in multprocessing

On my jetson Xavier AGX I want to record for two cameras the svo files.

When I am use my code without multiprocessing everthing works fine. as soon as I create a process and reach the function enable_recording(recording_param), the proces stops and no errors are thrown.

Is there a solution?

main.py

from loguru import logger
from camera_logging import CamRecorder
import sys
import multiprocessing
from time import sleep

def create_process():
    cl = CamRecorder()
    logger.debug("Start recording")
    cl.start_recording()
    

@logger.catch
def main():
    p1 = multiprocessing.Process(target=create_process)
    p1.start()
    p1.join()
    

if __name__ == "__main__":
    logger.add("logs/{time}.log", rotation="100 MB",level="INFO")
    # logger.add(sys.stdout, level="INFO")
    main()
camera_logging 
import sys
import pyzed.sl as sl
from signal import signal, SIGINT
from loguru import logger
import time
from pathlib import Path
from utils import check_path,dateandtime,svo_path
import os
from time import sleep


class CamRecorder:
    def __init__(self,cam_serial_nr:str = "",rec_duration_s:int=10,output_folder:Path = "/home/code/logging/svo",file_prefix: str = "cam1") -> None:
        if cam_serial_nr:
            self.cam_serial_nr = cam_serial_nr
            self.cam = sl.Camera(self.cam_serial_nr)
        else:
            logger.info("No camera serial number provided, using first camera found")
            self.cam = sl.Camera()
            pass
        self.output_path =  check_path(output_folder)
        self.file_prefix = file_prefix   
        self.rec_duration_s = rec_duration_s 
        self.signal = signal(SIGINT, self.handler) # signal handler for ctrl-c
        self.init = sl.InitParameters()
        self.init.camera_resolution = sl.RESOLUTION.VGA
        self.init.depth_mode = sl.DEPTH_MODE.NONE
        self.init.camera_fps = 15
        self.init.coordinate_units = sl.UNIT.METER
        self.init.coordinate_system = sl.COORDINATE_SYSTEM.RIGHT_HANDED_Y_UP
        self.init.camera_disable_self_calib = True
        self.init.sdk_verbose = True
        self.status = self.cam.open(self.init)
        self.run = 0
        if self.status != sl.ERROR_CODE.SUCCESS:
            logger.error(repr(self.status))
            exit(1)
        logger.debug("Camera opened")

    def handler(self,signal_received, frame):
        """handler for ctrl-c to stop recording"""
        logger.info("SIGINT or CTRL-C detected. Exiting gracefully")
        self.cam.disable_recording()
        self.cam.close()
        self.run = 0
        
    def start_recording(self):
        """Start recording SVO file"""
        logger.info("SVO is Recording, use Ctrl-C to stop.")
        path = str(svo_path(self.output_path,self.file_prefix))
        recording_param = sl.RecordingParameters(path, sl.SVO_COMPRESSION_MODE.H264)
        logger.debug(f"{recording_param.video_filename}")
        try:
            # here the process stops without errors
            err = print(self.cam.enable_recording(recording_param))
        except:
            logger.error("Error in enable_recording")

        if err != sl.ERROR_CODE.SUCCESS:
            logger.error("Failed to start recording")
            exit(1)
            
        
        logger.debug(f"Recording duration is {self.rec_duration_s} seconds")
        runtime = sl.RuntimeParameters()
        frames_recorded = 0
        self.run = 1
        fps = self.cam.get_camera_information().camera_fps   
        # run until ctrl-c or stop_recording is called
        while self.run:
            if self.cam.grab(runtime) == sl.ERROR_CODE.SUCCESS :
                frames_recorded += 1
                duration = frames_recorded / fps
                if duration > self.rec_duration_s:
                    logger.debug(f"Recording duration reached, save current recording to {recording_param.video_filename}")
                    self.cam.disable_recording()#stop recording
                    sleep(0.1) #give camera time to close recording
                    recording_param.video_filename = svo_path(self.output_path,self.file_prefix)
                    self.cam.enable_recording(recording_param) #restart recording
                    frames_recorded = 0 #reset counter
                    
        #done recording
        self.cam.disable_recording()    
        self.cam.close()
        
        
    def stop_recording(self):
        self.cam.disable_recording()
        self.run = 0
        return True
    
    def reconnect_cam(self):
        try:
            self.cam.close()
            sleep(0.1)
            self.cam.open(self.init)
            return True
        except:
            return False
        
    def is_recording(self):
        return self.cam.is_recording_enabled()

BR Sandro

Hello and thank you for reaching out,

I think I am missing a file to reproduce this, utils.py, can you also provide that ?

1 Like
from pathlib import Path
from datetime import datetime
import os
from loguru import logger as lo

def check_path(path:str= "")-> Path:
    """Check if path exists, if not raise FileNotFoundError"""
    lo.debug(f"Checking path {path}")
    if path:
        path = Path(path)
        if path.exists():
            return Path(path)
        else:
            raise FileNotFoundError(f"Path {path} does not exist.")
    else:
        raise ValueError("Path cannot be empty.")

def dateandtime()-> str:
    """Return current date and time as string"""
    return datetime.now().strftime("%Y-%m-%d_%H-%M-%S")

def svo_path(folder:str , prefix:str)-> str:
    """Return path to SVO file"""
    return str(os.path.join(folder,f"{prefix}_{dateandtime()}.svo"))

There is an issue in your code.

            err = print(self.cam.enable_recording(recording_param))

should actually be

            err = self.cam.enable_recording(recording_param)

Then, on my computer, it works perfectly.

1 Like