aboutsummaryrefslogtreecommitdiff
path: root/src/argaze/utils/UtilsFeatures.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/argaze/utils/UtilsFeatures.py')
-rw-r--r--src/argaze/utils/UtilsFeatures.py51
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."""