def start(self, output): """ Starts the encoder object writing to the specified output """ self.event.clear() self.stopped = False self.exception = None self._open_output(output) self.output_port[0].userdata = ct.cast(ct.pointer(ct.py_object(self)), ct.c_void_p) mmal_check( mmal.mmal_port_enable(self.output_port, _encoder_callback), prefix="Failed to enable encoder output port" ) for q in range(mmal.mmal_queue_length(self.pool[0].queue)): buf = mmal.mmal_queue_get(self.pool[0].queue) if not buf: raise PiCameraRuntimeError("Unable to get a required buffer from pool queue") mmal_check( mmal.mmal_port_send_buffer(self.output_port, buf), prefix="Unable to send a buffer to encoder output port", ) b = mmal.MMAL_BOOL_T() mmal_check( mmal.mmal_port_parameter_get_boolean(self.camera_port, mmal.MMAL_PARAMETER_CAPTURE, b), prefix="Failed to query capture status", ) self.started_capture = not bool(b) if self.started_capture: mmal_check( mmal.mmal_port_parameter_set_boolean(self.camera_port, mmal.MMAL_PARAMETER_CAPTURE, mmal.MMAL_TRUE), prefix="Failed to start capture", )
def start(self, output): """ Starts the encoder object writing to the specified output """ self.event.clear() self.stopped = False self.exception = None self._open_output(output) self.output_port[0].userdata = ct.cast(ct.pointer(ct.py_object(self)), ct.c_void_p) mmal_check(mmal.mmal_port_enable(self.output_port, _encoder_callback), prefix="Failed to enable encoder output port") for q in range(mmal.mmal_queue_length(self.pool[0].queue)): buf = mmal.mmal_queue_get(self.pool[0].queue) if not buf: raise PiCameraRuntimeError( "Unable to get a required buffer from pool queue") mmal_check(mmal.mmal_port_send_buffer(self.output_port, buf), prefix="Unable to send a buffer to encoder output port") b = mmal.MMAL_BOOL_T() mmal_check(mmal.mmal_port_parameter_get_boolean( self.camera_port, mmal.MMAL_PARAMETER_CAPTURE, b), prefix="Failed to query capture status") self.started_capture = not bool(b) if self.started_capture: mmal_check(mmal.mmal_port_parameter_set_boolean( self.camera_port, mmal.MMAL_PARAMETER_CAPTURE, mmal.MMAL_TRUE), prefix="Failed to start capture")
def stop(self): """ Stops the encoder, regardless of whether it's finished """ # The check on is_enabled below is not a race condition; we ignore the # EINVAL error in the case the port turns out to be disabled when we # disable below. The check exists purely to prevent stderr getting # spammed by our continued attempts to disable an already disabled port if self.encoder and self.output_port[0].is_enabled: if self.started_capture: self.started_capture = False mmal_check( mmal.mmal_port_parameter_set_boolean( self.camera_port, mmal.MMAL_PARAMETER_CAPTURE, mmal.MMAL_FALSE ), prefix="Failed to stop capture", ) try: mmal_check(mmal.mmal_port_disable(self.output_port), prefix="Failed to disable encoder output port") except PiCameraMMALError as e: if e.status != mmal.MMAL_EINVAL: raise self.stopped = True self.event.set() self._close_output()
def stop(self): """ Stops the encoder, regardless of whether it's finished """ # The check on is_enabled below is not a race condition; we ignore the # EINVAL error in the case the port turns out to be disabled when we # disable below. The check exists purely to prevent stderr getting # spammed by our continued attempts to disable an already disabled port if self.encoder and self.output_port[0].is_enabled: if self.started_capture: self.started_capture = False mmal_check( mmal.mmal_port_parameter_set_boolean( self.camera_port, mmal.MMAL_PARAMETER_CAPTURE, mmal.MMAL_FALSE), prefix="Failed to stop capture") try: mmal_check( mmal.mmal_port_disable(self.output_port), prefix="Failed to disable encoder output port") except PiCameraMMALError as e: if e.status != mmal.MMAL_EINVAL: raise self.stopped = True self.event.set() self._close_output()
def wait(self, timeout=None): """ Waits for the encoder to finish (successfully or otherwise) """ result = self.event.wait(timeout) if result: if self.started_capture: self.started_capture = False mmal_check( mmal.mmal_port_parameter_set_boolean( self.camera_port, mmal.MMAL_PARAMETER_CAPTURE, mmal.MMAL_FALSE), prefix="Failed to stop capture") try: mmal_check( mmal.mmal_port_disable(self.output_port), prefix="Failed to disable encoder output port") except PiCameraMMALError as e: if e.status != mmal.MMAL_EINVAL: raise self._close_output() # Check whether the callback set an exception if self.exception: raise self.exception return result
def _create_encoder(self, quality=85, thumbnail=(64, 48, 35), bayer=False): super(PiImageEncoder, self)._create_encoder() try: self.output_port[0].format[0].encoding = { 'jpeg': mmal.MMAL_ENCODING_JPEG, 'png': mmal.MMAL_ENCODING_PNG, 'gif': mmal.MMAL_ENCODING_GIF, 'bmp': mmal.MMAL_ENCODING_BMP, }[self.format] except KeyError: raise PiCameraValueError("Unrecognized format %s" % self.format) mmal_check( mmal.mmal_port_format_commit(self.output_port), prefix="Unable to set format on encoder output port") if self.format == 'jpeg': mmal_check( mmal.mmal_port_parameter_set_uint32( self.output_port, mmal.MMAL_PARAMETER_JPEG_Q_FACTOR, quality), prefix="Failed to set JPEG quality") mmal_check( mmal.mmal_port_parameter_set_boolean( self.camera_port, mmal.MMAL_PARAMETER_ENABLE_RAW_CAPTURE, int(bool(bayer))), prefix="Failed to set raw capture") if thumbnail is None: mp = mmal.MMAL_PARAMETER_THUMBNAIL_CONFIG_T( mmal.MMAL_PARAMETER_HEADER_T( mmal.MMAL_PARAMETER_THUMBNAIL_CONFIGURATION, ct.sizeof(mmal.MMAL_PARAMETER_THUMBNAIL_CONFIG_T) ), 0, 0, 0, 0) else: mp = mmal.MMAL_PARAMETER_THUMBNAIL_CONFIG_T( mmal.MMAL_PARAMETER_HEADER_T( mmal.MMAL_PARAMETER_THUMBNAIL_CONFIGURATION, ct.sizeof(mmal.MMAL_PARAMETER_THUMBNAIL_CONFIG_T) ), 1, *thumbnail) mmal_check( mmal.mmal_port_parameter_set(self.encoder[0].control, mp.hdr), prefix="Failed to set thumbnail configuration") mmal_check( mmal.mmal_component_enable(self.encoder), prefix="Unable to enable encoder component")
def _create_encoder(self, bitrate=17000000, intra_period=0, profile='high', quantization=0, inline_headers=True, sei=False): super(PiVideoEncoder, self)._create_encoder() try: self.output_port[0].format[0].encoding = { 'h264': mmal.MMAL_ENCODING_H264, 'mjpeg': mmal.MMAL_ENCODING_MJPEG, }[self.format] except KeyError: raise PiCameraValueError('Unrecognized format %s' % self.format) if not (0 <= bitrate <= 25000000): raise PiCameraValueError( 'bitrate must be between 0 (VBR) and 25Mbps') if quantization and bitrate: warnings.warn('Setting bitrate to 0 as quantization is non-zero', PiCameraWarning) bitrate = 0 self.output_port[0].format[0].bitrate = bitrate mmal_check(mmal.mmal_port_format_commit(self.output_port), prefix="Unable to set format on encoder output port") if self.format == 'h264': mp = mmal.MMAL_PARAMETER_VIDEO_PROFILE_T( mmal.MMAL_PARAMETER_HEADER_T( mmal.MMAL_PARAMETER_PROFILE, ct.sizeof(mmal.MMAL_PARAMETER_VIDEO_PROFILE_T), ), ) try: mp.profile[0].profile = { 'baseline': mmal.MMAL_VIDEO_PROFILE_H264_BASELINE, 'main': mmal.MMAL_VIDEO_PROFILE_H264_MAIN, 'high': mmal.MMAL_VIDEO_PROFILE_H264_HIGH, 'constrained': mmal.MMAL_VIDEO_PROFILE_H264_CONSTRAINED_BASELINE, }[profile] except KeyError: raise PiCameraValueError("Invalid H.264 profile %s" % profile) mp.profile[0].level = mmal.MMAL_VIDEO_LEVEL_H264_4 mmal_check(mmal.mmal_port_parameter_set(self.output_port, mp.hdr), prefix="Unable to set encoder H.264 profile") mmal_check(mmal.mmal_port_parameter_set_boolean( self.output_port, mmal.MMAL_PARAMETER_VIDEO_ENCODE_INLINE_HEADER, int(inline_headers)), prefix="Unable to set inline_headers") mmal_check(mmal.mmal_port_parameter_set_boolean( self.output_port, mmal.MMAL_PARAMETER_VIDEO_ENCODE_SEI_ENABLE, int(sei)), prefix="Enable to set SEI") if not (bitrate and inline_headers): # If inline_headers is disabled, or VBR encoding is configured, # disable the split function self._next_output = None if intra_period: mp = mmal.MMAL_PARAMETER_UINT32_T( mmal.MMAL_PARAMETER_HEADER_T( mmal.MMAL_PARAMETER_INTRAPERIOD, ct.sizeof(mmal.MMAL_PARAMETER_UINT32_T), ), intra_period) mmal_check(mmal.mmal_port_parameter_set( self.output_port, mp.hdr), prefix="Unable to set encoder intra_period") if quantization: mp = mmal.MMAL_PARAMETER_UINT32_T( mmal.MMAL_PARAMETER_HEADER_T( mmal.MMAL_PARAMETER_VIDEO_ENCODE_INITIAL_QUANT, ct.sizeof(mmal.MMAL_PARAMETER_UINT32_T), ), quantization) mmal_check(mmal.mmal_port_parameter_set(self.output_port, mp.hdr), prefix="Unable to set initial quantization") mp = mmal.MMAL_PARAMETER_UINT32_T( mmal.MMAL_PARAMETER_HEADER_T( mmal.MMAL_PARAMETER_VIDEO_ENCODE_MIN_QUANT, ct.sizeof(mmal.MMAL_PARAMETER_UINT32_T), ), quantization, ) mmal_check(mmal.mmal_port_parameter_set(self.output_port, mp.hdr), prefix="Unable to set minimum quantization") mp = mmal.MMAL_PARAMETER_UINT32_T( mmal.MMAL_PARAMETER_HEADER_T( mmal.MMAL_PARAMETER_VIDEO_ENCODE_MAX_QUANT, ct.sizeof(mmal.MMAL_PARAMETER_UINT32_T), ), quantization, ) mmal_check(mmal.mmal_port_parameter_set(self.output_port, mp.hdr), prefix="Unable to set maximum quantization") mmal_check(mmal.mmal_port_parameter_set_boolean( self.encoder[0].input[0], mmal.MMAL_PARAMETER_VIDEO_IMMUTABLE_INPUT, 1), prefix="Unable to set immutable flag on encoder input port") mmal_check(mmal.mmal_component_enable(self.encoder), prefix="Unable to enable video encoder component")
def _create_encoder( self, bitrate=17000000, intra_period=0, profile="high", quantization=0, inline_headers=True, **options ): super(PiVideoEncoder, self)._create_encoder(**options) try: self.output_port[0].format[0].encoding = { "h264": mmal.MMAL_ENCODING_H264, "mjpeg": mmal.MMAL_ENCODING_MJPEG, }[self.format] except KeyError: raise PiCameraValueError("Unrecognized format %s" % self.format) if not (0 <= bitrate <= 25000000): raise PiCameraValueError("bitrate must be between 0 (VBR) and 25Mbps") if quantization and bitrate: warnings.warn("Setting bitrate to 0 as quantization is non-zero", PiCameraWarning) bitrate = 0 self.output_port[0].format[0].bitrate = bitrate mmal_check(mmal.mmal_port_format_commit(self.output_port), prefix="Unable to set format on encoder output port") if self.format == "h264": mp = mmal.MMAL_PARAMETER_VIDEO_PROFILE_T( mmal.MMAL_PARAMETER_HEADER_T( mmal.MMAL_PARAMETER_PROFILE, ct.sizeof(mmal.MMAL_PARAMETER_VIDEO_PROFILE_T) ) ) try: mp.profile[0].profile = { "baseline": mmal.MMAL_VIDEO_PROFILE_H264_BASELINE, "main": mmal.MMAL_VIDEO_PROFILE_H264_MAIN, "high": mmal.MMAL_VIDEO_PROFILE_H264_HIGH, "constrained": mmal.MMAL_VIDEO_PROFILE_H264_CONSTRAINED_BASELINE, }[profile] except KeyError: raise PiCameraValueError("Invalid H.264 profile %s" % profile) mp.profile[0].level = mmal.MMAL_VIDEO_LEVEL_H264_4 mmal_check( mmal.mmal_port_parameter_set(self.output_port, mp.hdr), prefix="Unable to set encoder H.264 profile" ) mmal_check( mmal.mmal_port_parameter_set_boolean( self.output_port, mmal.MMAL_PARAMETER_VIDEO_ENCODE_INLINE_HEADER, int(inline_headers) ), prefix="Unable to set inline_headers", ) if not (bitrate and inline_headers): # If inline_headers is disabled, or VBR encoding is configured, # disable the split function self._next_output = None if intra_period: mp = mmal.MMAL_PARAMETER_UINT32_T( mmal.MMAL_PARAMETER_HEADER_T( mmal.MMAL_PARAMETER_INTRAPERIOD, ct.sizeof(mmal.MMAL_PARAMETER_UINT32_T) ), intra_period, ) mmal_check( mmal.mmal_port_parameter_set(self.output_port, mp.hdr), prefix="Unable to set encoder intra_period" ) if quantization: mp = mmal.MMAL_PARAMETER_UINT32_T( mmal.MMAL_PARAMETER_HEADER_T( mmal.MMAL_PARAMETER_VIDEO_ENCODE_INITIAL_QUANT, ct.sizeof(mmal.MMAL_PARAMETER_UINT32_T) ), quantization, ) mmal_check( mmal.mmal_port_parameter_set(self.output_port, mp.hdr), prefix="Unable to set initial quantization" ) mp = mmal.MMAL_PARAMETER_UINT32_T( mmal.MMAL_PARAMETER_HEADER_T( mmal.MMAL_PARAMETER_VIDEO_ENCODE_MIN_QUANT, ct.sizeof(mmal.MMAL_PARAMETER_UINT32_T) ), quantization, ) mmal_check( mmal.mmal_port_parameter_set(self.output_port, mp.hdr), prefix="Unable to set minimum quantization" ) mp = mmal.MMAL_PARAMETER_UINT32_T( mmal.MMAL_PARAMETER_HEADER_T( mmal.MMAL_PARAMETER_VIDEO_ENCODE_MAX_QUANT, ct.sizeof(mmal.MMAL_PARAMETER_UINT32_T) ), quantization, ) mmal_check( mmal.mmal_port_parameter_set(self.output_port, mp.hdr), prefix="Unable to set maximum quantization" ) mmal_check( mmal.mmal_port_parameter_set_boolean( self.encoder[0].input[0], mmal.MMAL_PARAMETER_VIDEO_IMMUTABLE_INPUT, 1 ), prefix="Unable to set immutable flag on encoder input port", ) mmal_check(mmal.mmal_component_enable(self.encoder), prefix="Unable to enable video encoder component")
def _create_encoder( self, bitrate=17000000, intra_period=0, profile='high', quantization=0, inline_headers=True, sei=False): super(PiVideoEncoder, self)._create_encoder() try: self.output_port[0].format[0].encoding = { 'h264': mmal.MMAL_ENCODING_H264, 'mjpeg': mmal.MMAL_ENCODING_MJPEG, }[self.format] except KeyError: raise PiCameraValueError('Unrecognized format %s' % self.format) if not (0 <= bitrate <= 25000000): raise PiCameraValueError('bitrate must be between 0 (VBR) and 25Mbps') if quantization and bitrate: warnings.warn('Setting bitrate to 0 as quantization is non-zero', PiCameraWarning) bitrate = 0 self.output_port[0].format[0].bitrate = bitrate mmal_check( mmal.mmal_port_format_commit(self.output_port), prefix="Unable to set format on encoder output port") if self.format == 'h264': mp = mmal.MMAL_PARAMETER_VIDEO_PROFILE_T( mmal.MMAL_PARAMETER_HEADER_T( mmal.MMAL_PARAMETER_PROFILE, ct.sizeof(mmal.MMAL_PARAMETER_VIDEO_PROFILE_T), ), ) try: mp.profile[0].profile = { 'baseline': mmal.MMAL_VIDEO_PROFILE_H264_BASELINE, 'main': mmal.MMAL_VIDEO_PROFILE_H264_MAIN, 'high': mmal.MMAL_VIDEO_PROFILE_H264_HIGH, 'constrained': mmal.MMAL_VIDEO_PROFILE_H264_CONSTRAINED_BASELINE, }[profile] except KeyError: raise PiCameraValueError("Invalid H.264 profile %s" % profile) mp.profile[0].level = mmal.MMAL_VIDEO_LEVEL_H264_4 mmal_check( mmal.mmal_port_parameter_set(self.output_port, mp.hdr), prefix="Unable to set encoder H.264 profile") mmal_check( mmal.mmal_port_parameter_set_boolean( self.output_port, mmal.MMAL_PARAMETER_VIDEO_ENCODE_INLINE_HEADER, int(inline_headers)), prefix="Unable to set inline_headers") mmal_check( mmal.mmal_port_parameter_set_boolean( self.output_port, mmal.MMAL_PARAMETER_VIDEO_ENCODE_SEI_ENABLE, int(sei)), prefix="Enable to set SEI") if not (bitrate and inline_headers): # If inline_headers is disabled, or VBR encoding is configured, # disable the split function self._next_output = None # We need the intra-period to calculate the SPS header timeout in # the split method below. If one is not set explicitly, query the # encoder's default if intra_period: mp = mmal.MMAL_PARAMETER_UINT32_T( mmal.MMAL_PARAMETER_HEADER_T( mmal.MMAL_PARAMETER_INTRAPERIOD, ct.sizeof(mmal.MMAL_PARAMETER_UINT32_T), ), intra_period ) mmal_check( mmal.mmal_port_parameter_set(self.output_port, mp.hdr), prefix="Unable to set encoder intra_period") self._intra_period = intra_period else: mp = mmal.MMAL_PARAMETER_UINT32_T( mmal.MMAL_PARAMETER_HEADER_T( mmal.MMAL_PARAMETER_INTRAPERIOD, ct.sizeof(mmal.MMAL_PARAMETER_UINT32_T), )) mmal_check( mmal.mmal_port_parameter_get(self.output_port, mp.hdr), prefix="Unable to get encoder intra_period") self._intra_period = mp.value elif self.format == 'mjpeg': # MJPEG doesn't have an intra_period setting as such, but as every # frame is a full-frame, the intra_period is effectively 1 self._intra_period = 1 if quantization: mp = mmal.MMAL_PARAMETER_UINT32_T( mmal.MMAL_PARAMETER_HEADER_T( mmal.MMAL_PARAMETER_VIDEO_ENCODE_INITIAL_QUANT, ct.sizeof(mmal.MMAL_PARAMETER_UINT32_T), ), quantization ) mmal_check( mmal.mmal_port_parameter_set(self.output_port, mp.hdr), prefix="Unable to set initial quantization") mp = mmal.MMAL_PARAMETER_UINT32_T( mmal.MMAL_PARAMETER_HEADER_T( mmal.MMAL_PARAMETER_VIDEO_ENCODE_MIN_QUANT, ct.sizeof(mmal.MMAL_PARAMETER_UINT32_T), ), quantization, ) mmal_check( mmal.mmal_port_parameter_set(self.output_port, mp.hdr), prefix="Unable to set minimum quantization") mp = mmal.MMAL_PARAMETER_UINT32_T( mmal.MMAL_PARAMETER_HEADER_T( mmal.MMAL_PARAMETER_VIDEO_ENCODE_MAX_QUANT, ct.sizeof(mmal.MMAL_PARAMETER_UINT32_T), ), quantization, ) mmal_check( mmal.mmal_port_parameter_set(self.output_port, mp.hdr), prefix="Unable to set maximum quantization") mmal_check( mmal.mmal_port_parameter_set_boolean( self.encoder[0].input[0], mmal.MMAL_PARAMETER_VIDEO_IMMUTABLE_INPUT, 1), prefix="Unable to set immutable flag on encoder input port") mmal_check( mmal.mmal_component_enable(self.encoder), prefix="Unable to enable video encoder component")
def _create_encoder( self, format, bitrate=17000000, intra_period=0, profile='high', quantization=0, inline_headers=True, **options): super(PiVideoEncoder, self)._create_encoder(format, **options) try: self.output_port[0].format[0].encoding = { 'h264': mmal.MMAL_ENCODING_H264, }[format] except KeyError: raise PiCameraValueError('Unrecognized format %s' % format) if not (0 <= bitrate <= 25000000): raise PiCameraValueError('bitrate must be between 0 (VBR) and 25Mbps') if quantization and bitrate: warnings.warn('Setting bitrate to 0 as quantization is non-zero', PiCameraWarning) bitrate = 0 self.output_port[0].format[0].bitrate = bitrate mmal_check( mmal.mmal_port_format_commit(self.output_port), prefix="Unable to set format on encoder output port") if intra_period: mp = mmal.MMAL_PARAMETER_UINT32_T( mmal.MMAL_PARAMETER_HEADER_T( mmal.MMAL_PARAMETER_INTRAPERIOD, ct.sizeof(mmal.MMAL_PARAMETER_UINT32_T), ), intra_period ) mmal_check( mmal.mmal_port_parameter_set(self.output_port, mp.hdr), prefix="Unable to set encoder intra_period") if quantization: mp = mmal.MMAL_PARAMETER_UINT32_T( mmal.MMAL_PARAMETER_HEADER_T( mmal.MMAL_PARAMETER_VIDEO_ENCODE_INITIAL_QUANT, ct.sizeof(mmal.MMAL_PARAMETER_UINT32_T), ), quantization ) mmal_check( mmal.mmal_port_parameter_set(self.output_port, mp.hdr), prefix="Unable to set quantization") mp = mmal.MMAL_PARAMETER_UINT32_T( mmal.MMAL_PARAMETER_HEADER_T( mmal.MMAL_PARAMETER_VIDEO_ENCODE_QP_P, ct.sizeof(mmal.MMAL_PARAMETER_UINT32_T), ), quantization + 6, ) mmal_check( mmal.mmal_port_parameter_set(self.output_port, mp.hdr), prefix="Unable to set quantization") mp = mmal.MMAL_PARAMETER_VIDEO_PROFILE_T( mmal.MMAL_PARAMETER_HEADER_T( mmal.MMAL_PARAMETER_PROFILE, ct.sizeof(mmal.MMAL_PARAMETER_VIDEO_PROFILE_T), ), ) try: mp.profile[0].profile = { 'baseline': mmal.MMAL_VIDEO_PROFILE_H264_BASELINE, 'main': mmal.MMAL_VIDEO_PROFILE_H264_MAIN, 'high': mmal.MMAL_VIDEO_PROFILE_H264_HIGH, 'constrained': mmal.MMAL_VIDEO_PROFILE_H264_CONSTRAINED_BASELINE, }[profile] except KeyError: raise PiCameraValueError("Invalid H.264 profile %s" % profile) mp.profile[0].level = mmal.MMAL_VIDEO_LEVEL_H264_4 mmal_check( mmal.mmal_port_parameter_set(self.output_port, mp.hdr), prefix="Unable to set encoder H.264 profile") mmal_check( mmal.mmal_port_parameter_set_boolean( self.input_port, mmal.MMAL_PARAMETER_VIDEO_IMMUTABLE_INPUT, 1), prefix="Unable to set immutable flag on encoder input port") mmal_check( mmal.mmal_port_parameter_set_boolean( self.output_port, mmal.MMAL_PARAMETER_VIDEO_ENCODE_INLINE_HEADER, int(inline_headers)), prefix="Unable to set inline_headers") if not (bitrate and inline_headers): # If inline_headers is disabled, or VBR encoding is configured, # disable the split function self._next_output = None mmal_check( mmal.mmal_component_enable(self.encoder), prefix="Unable to enable video encoder component")