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

View file

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