Fixed captures trying to restart recording for a stopped stream
This commit is contained in:
parent
cbf709e8d8
commit
646dc24a91
2 changed files with 51 additions and 59 deletions
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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")
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue