From 83c8bd794b4149ccdcd8e5e22b1ac08f39c035e0 Mon Sep 17 00:00:00 2001 From: Naushir Patuck Date: Tue, 17 Mar 2026 12:28:36 +0000 Subject: [PATCH 1/2] tests: Add bypass for imx219 in stop_slow_framerate test The sensor has a limit on the min fps that can be set, so will fail this test. Signed-off-by: Naushir Patuck --- tests/stop_slow_framerate.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/stop_slow_framerate.py b/tests/stop_slow_framerate.py index 6b1bdc76..e4381429 100755 --- a/tests/stop_slow_framerate.py +++ b/tests/stop_slow_framerate.py @@ -5,6 +5,11 @@ from picamera2 import Picamera2 picam2 = Picamera2() + +if picam2.camera_properties['Model'] == "imx219": + print("SKIPPED (imx219 test bypass)") + quit() + config = picam2.create_preview_configuration( controls={'FrameRate': 0.2, 'ExposureTime': 5000, 'AnalogueGain': 1.0, 'ColourGains': (1, 1)}) picam2.configure(config) From 2d3924f5aa1287781746a772e5b7addf77401d48 Mon Sep 17 00:00:00 2001 From: David Plowman Date: Wed, 18 Mar 2026 11:53:26 +0000 Subject: [PATCH 2/2] Improve FfmpegOutput shutdown if there's an error in the Ffmpeg process Set a flag to stop us continually re-trying when it's already failed, but leave the tidying up proper to the stop() method. This stops us seeing a few mildly disconcerting errors (unless we want to, of course). Signed-off-by: David Plowman --- picamera2/outputs/ffmpegoutput.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/picamera2/outputs/ffmpegoutput.py b/picamera2/outputs/ffmpegoutput.py index 1f35c763..7fa3e3ab 100644 --- a/picamera2/outputs/ffmpegoutput.py +++ b/picamera2/outputs/ffmpegoutput.py @@ -37,6 +37,7 @@ def __init__(self, output_filename, audio=False, audio_device="default", audio_s audio_samplerate=48000, audio_codec="aac", audio_bitrate=128000, audio_filter=None, pts=None): super().__init__(pts=pts) self.ffmpeg = None + self.output_broken = False self.output_filename = output_filename self.audio = audio self.audio_device = audio_device @@ -86,7 +87,10 @@ def start(self): def stop(self): super().stop() if self.ffmpeg is not None: - self.ffmpeg.stdin.close() # FFmpeg needs this to shut down tidily + try: + self.ffmpeg.stdin.close() # FFmpeg needs this to shut down tidily + except Exception: + pass try: # Give it a moment to flush out video frames, but after that make sure we terminate it. self.ffmpeg.wait(timeout=self.timeout) @@ -103,13 +107,15 @@ def stop(self): def outputframe(self, frame, keyframe=True, timestamp=None, packet=None, audio=False): if audio: raise RuntimeError("FfmpegOutput does not support audio packets from Picamera2") - if self.recording and self.ffmpeg: + if self.recording and not self.output_broken: # Handle the case where the FFmpeg prcoess has gone away for reasons of its own. try: self.ffmpeg.stdin.write(frame) self.ffmpeg.stdin.flush() # forces every frame to get timestamped individually except Exception as e: # presumably a BrokenPipeError? should we check explicitly? - self.ffmpeg = None + # Don't clear up the ffmpeg process here, that's what stop() is for. But + # set a flag so that we don't keep coming back and re-trying to no avail... + self.output_broken = True if self.error_callback: self.error_callback(e) else: