diff options
Diffstat (limited to 'src/argaze/utils/UtilsFeatures.py')
-rw-r--r-- | src/argaze/utils/UtilsFeatures.py | 51 |
1 files changed, 33 insertions, 18 deletions
diff --git a/src/argaze/utils/UtilsFeatures.py b/src/argaze/utils/UtilsFeatures.py index f7d74c7..05821b1 100644 --- a/src/argaze/utils/UtilsFeatures.py +++ b/src/argaze/utils/UtilsFeatures.py @@ -249,7 +249,7 @@ class FileWriter(DataFeatures.PipelineStepObject): # Write into file print(log, file=self.__file, flush=True) -class VideoWriter(DataFeatures.PipelineStepObject): +class VideoWriter(DataFeatures.PipelineStepObject, DataFeatures.SharedObject): """Open ffmpeg application as sub-process. FFmpeg input PIPE: RAW images in BGR color format FFmpeg output MP4 file encoded with HEVC codec. @@ -269,6 +269,9 @@ class VideoWriter(DataFeatures.PipelineStepObject): @DataFeatures.PipelineStepInit def __init__(self, **kwargs): + + # Init parent classes + DataFeatures.SharedObject.__init__(self) # Init private attributes self.__path = None @@ -319,36 +322,48 @@ class VideoWriter(DataFeatures.PipelineStepObject): @DataFeatures.PipelineStepEnter def __enter__(self): """Check that folder structure exist then, open ffmpeg subprocess.""" + + # Use lock feature + with self._lock: - import subprocess as sp - import shlex + import subprocess as sp + import shlex - if not os.path.exists(self.__path.parent.absolute()): - - os.makedirs(self.__path.parent.absolute()) + if not os.path.exists(self.__path.parent.absolute()): + + os.makedirs(self.__path.parent.absolute()) - self.__process = sp.Popen(shlex.split(f'ffmpeg -hide_banner -loglevel error -y -s {self.__width}x{self.__height} -pixel_format bgr24 -f rawvideo -r {self.__fps} -i pipe: -vcodec libx265 -x265-params log-level=error -pix_fmt yuv420p -crf 24 {self.__path}'), stdin=sp.PIPE) - + self.__process = sp.Popen(shlex.split(f'ffmpeg -hide_banner -loglevel error -y -s {self.__width}x{self.__height} -pixel_format bgr24 -f rawvideo -r {self.__fps} -i pipe: -vcodec libx265 -x265-params log-level=error -pix_fmt yuv420p -crf 24 {self.__path}'), stdin=sp.PIPE) + @DataFeatures.PipelineStepExit def __exit__(self, exception_type, exception_value, exception_traceback): - # Close and flush stdin - self.__process.stdin.close() + # Use lock feature + with self._lock: + + # Close and flush stdin + self.__process.stdin.close() - # Wait for sub-process to finish - self.__process.wait() + # Wait for sub-process to finish + self.__process.wait() - # Terminate the sub-process - # Note: We don't have to terminate the sub-process (after process.wait(), the sub-process is supposed to be closed). - self.__process.terminate() + # Terminate the sub-process + # Note: We don't have to terminate the sub-process (after process.wait(), the sub-process is supposed to be closed). + self.__process.terminate() def write(self, image: numpy.array): """Write raw video frame to input stream of ffmpeg sub-process.""" - # Resize image to adapt to video resolution - output = cv2.resize(image, dsize=(self.__width, self.__height), interpolation=cv2.INTER_LINEAR) + # Use lock feature + with self._lock: + + # Check if subprocess still alive + if self.__process.poll() is None: + + # Resize image to adapt to video resolution + output = cv2.resize(image, dsize=(self.__width, self.__height), interpolation=cv2.INTER_LINEAR) - self.__process.stdin.write(output.tobytes()) + self.__process.stdin.write(output.tobytes()) def PrintCallStack(method): """Define a decorator to print call stack until the decorated method.""" |