Fixed captures trying to restart recording for a stopped stream

This commit is contained in:
Joel Collins 2019-01-17 12:23:54 +00:00
parent cbf709e8d8
commit 646dc24a91
2 changed files with 51 additions and 59 deletions

View file

@ -313,6 +313,8 @@ class BaseCamera(object):
self.frames_iterator = self.frames() self.frames_iterator = self.frames()
logging.debug("Entering worker thread.") logging.debug("Entering worker thread.")
self.state['stream_active'] = True
for frame in self.frames_iterator: for frame in self.frames_iterator:
self.frame = frame self.frame = frame
self.event.set() # send signal to clients self.event.set() # send signal to clients
@ -337,5 +339,7 @@ class BaseCamera(object):
pass pass
logging.debug("BaseCamera worker thread exiting...") logging.debug("BaseCamera worker thread exiting...")
# Set stream_activate state
self.state['stream_active'] = False
# Reset thread # Reset thread
self.thread = None self.thread = None

View file

@ -210,7 +210,7 @@ class StreamingCamera(BaseCamera):
# Pause stream while changing settings # Pause stream while changing settings
if self.state['stream_active']: # If stream is active if self.state['stream_active']: # If stream is active
logging.info("Pausing stream to update config.") logging.info("Pausing stream to update config.")
self.pause_stream() # Pause stream self.stop_stream_recording() # Pause stream
paused_stream = True # Remember to unpause stream when done paused_stream = True # Remember to unpause stream when done
# PiCamera parameters (applied directly to PiCamera object) # PiCamera parameters (applied directly to PiCamera object)
@ -239,7 +239,7 @@ class StreamingCamera(BaseCamera):
# If stream was paused to update config, unpause # If stream was paused to update config, unpause
if paused_stream: if paused_stream:
logging.info("Resuming stream.") logging.info("Resuming stream.")
self.resume_stream() self.start_stream_recording()
else: else:
raise Exception( raise Exception(
@ -342,18 +342,17 @@ class StreamingCamera(BaseCamera):
# Update state dictionary # Update state dictionary
self.state['record_active'] = False self.state['record_active'] = False
def pause_stream( def stop_stream_recording(
self, self,
splitter_port: int=1, splitter_port: int=1,
resolution: Tuple[int, int]=None) -> None: resolution: Tuple[int, int]=None) -> None:
""" """
Pause capture on a splitter port. Sets the camera resolution to the still-image resolution, and stops recording if the stream is active.
Args: Args:
splitter_port (int): Splitter port to stop recording on splitter_port (int): Splitter port to stop recording on
resolution ((int, int)): Resolution to set the camera to, after stopping recording. resolution ((int, int)): Resolution to set the camera to, after stopping recording.
""" """
logging.debug("Pausing stream")
# If no resolution is specified, default to image_resolution # If no resolution is specified, default to image_resolution
if not resolution: if not resolution:
resolution = self.config['image_resolution'] resolution = self.config['image_resolution']
@ -361,36 +360,46 @@ class StreamingCamera(BaseCamera):
# Stop the camera video recording on port 1 # Stop the camera video recording on port 1
try: try:
self.camera.stop_recording(splitter_port=splitter_port) self.camera.stop_recording(splitter_port=splitter_port)
logging.info("Stopped MJPEG stream on port {1}. Switching to {0}.".format(resolution, splitter_port))
except picamera.exc.PiCameraNotRecording: except picamera.exc.PiCameraNotRecording:
logging.info("Not recording on splitter_port {}".format(splitter_port)) logging.info("Not recording on splitter_port {}".format(splitter_port))
# Increase the resolution for taking an image # Increase the resolution for taking an image
self.camera.resolution = resolution self.camera.resolution = resolution
def resume_stream( def start_stream_recording(
self, self,
splitter_port: int=1, splitter_port: int=1,
resolution: Tuple[int, int]=None) -> None: resolution: Tuple[int, int]=None) -> None:
""" """
Resume capture on a splitter port. Sets the camera resolution to the video/stream resolution, and starts recording if the stream should be active.
Args: Args:
splitter_port (int): Splitter port to start recording on splitter_port (int): Splitter port to start recording on
resolution ((int, int)): Resolution to set the camera to, before starting recording. resolution ((int, int)): Resolution to set the camera to, before starting recording. Defaults to `self.config['video_resolution']`.
""" """
logging.debug("Resuming stream")
# If no stream object exists
if not hasattr(self, 'stream'):
self.stream = io.BytesIO() # Create a stream object
# If no explicit resolution is passed
if not resolution: if not resolution:
resolution = self.config['video_resolution'] resolution = self.config['video_resolution'] # Default to video recording resolution
# Reduce the resolution for video streaming # Reduce the resolution for video streaming
self.camera.resolution = resolution self.camera.resolution = resolution
# Resume the video channel # If the stream should be active
self.camera.start_recording( if self.state['stream_active']:
self.stream, # Start recording on stream port
format='mjpeg', self.camera.start_recording(
quality=self.config['jpeg_quality'], self.stream,
splitter_port=splitter_port) format='mjpeg',
quality=self.config['jpeg_quality'],
splitter_port=splitter_port)
logging.debug("Started MJPEG stream at {} on port {}".format(resolution, splitter_port))
def capture( def capture(
self, self,
@ -421,31 +430,21 @@ class StreamingCamera(BaseCamera):
logging.info("Capturing to {}".format(output)) logging.info("Capturing to {}".format(output))
# Set resolution and stop stream recording if necesarry
# TODO: Do we really always want bayer data for full captures?
if not use_video_port: if not use_video_port:
self.stop_stream_recording()
# Pause video splitter port 1 self.camera.capture(
self.pause_stream() output_stream,
format=fmt,
quality=100,
resize=resize,
bayer=(not use_video_port) and bayer,
use_video_port=use_video_port)
self.camera.capture( # Set resolution and start stream recording if necesarry
output_stream, if not use_video_port:
format=fmt, self.start_stream_recording()
quality=100,
resize=resize,
bayer=bayer)
# Resume video splitter port 1
self.resume_stream()
else:
self.camera.capture(
output_stream,
format=fmt,
quality=100,
resize=resize,
bayer=False,
use_video_port=bayer)
return output return output
@ -471,7 +470,7 @@ class StreamingCamera(BaseCamera):
size = resolution size = resolution
if not use_video_port: if not use_video_port:
self.pause_stream(resolution=resolution) self.stop_stream_recording(resolution=resolution)
logging.debug("Creating PiYUVArray") logging.debug("Creating PiYUVArray")
with picamera.array.PiYUVArray(self.camera, size=size) as output: with picamera.array.PiYUVArray(self.camera, size=size) as output:
@ -485,7 +484,7 @@ class StreamingCamera(BaseCamera):
use_video_port=use_video_port) use_video_port=use_video_port)
if not use_video_port: if not use_video_port:
self.resume_stream() self.start_stream_recording()
if rgb: if rgb:
logging.debug("Converting to RGB") logging.debug("Converting to RGB")
@ -515,7 +514,7 @@ class StreamingCamera(BaseCamera):
size = resolution size = resolution
# Always pause stream, to prevent resizer memory issues # Always pause stream, to prevent resizer memory issues
self.pause_stream(resolution=resolution) self.stop_stream_recording(resolution=resolution)
logging.debug("Creating PiRGBArray") logging.debug("Creating PiRGBArray")
with picamera.array.PiRGBArray(self.camera, size=size) as output: with picamera.array.PiRGBArray(self.camera, size=size) as output:
@ -529,7 +528,7 @@ class StreamingCamera(BaseCamera):
use_video_port=use_video_port) use_video_port=use_video_port)
# Resume stream # Resume stream
self.resume_stream() self.start_stream_recording()
return output.array return output.array
@ -544,25 +543,14 @@ class StreamingCamera(BaseCamera):
""" """
# Run this initialisation method # Run this initialisation method
self.initialisation() self.initialisation()
self.wait_for_camera() self.wait_for_camera()
# Set stream resolution # Start stream recording (and set resolution)
self.camera.resolution = self.config['video_resolution'] self.start_stream_recording()
# Create stream
self.stream = io.BytesIO()
# Start recording on video splitter port 1
self.camera.start_recording(
self.stream,
format='mjpeg',
quality=self.config['jpeg_quality'],
splitter_port=1)
# Update state # Update state
logging.debug("STREAM ACTIVE") logging.debug("STREAM ACTIVE")
self.state['stream_active'] = True #self.state['stream_active'] = True
# While the iterator is not closed # While the iterator is not closed
try: try:
@ -582,7 +570,7 @@ class StreamingCamera(BaseCamera):
yield frame yield frame
# When GeneratorExit or StopIteration raised, run cleanup code # When GeneratorExit or StopIteration raised, run cleanup code
finally: finally:
logging.debug("Stopping stream recording on port 1") # Stop stream recording (and set resolution)
self.camera.stop_recording(splitter_port=1) self.stop_stream_recording()
self.state['stream_active'] = False
logging.debug("FRAME ITERATOR END") logging.debug("FRAME ITERATOR END")