Skip to content

Commit

Permalink
Support V2 max resolution
Browse files Browse the repository at this point in the history
Adds construction of CameraInfo component prior to camera init to
determine the camera name and max-res
  • Loading branch information
waveform80 committed May 25, 2016
1 parent 4799e06 commit d9ad40b
Show file tree
Hide file tree
Showing 3 changed files with 145 additions and 43 deletions.
63 changes: 41 additions & 22 deletions picamera/camera.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,13 @@ def docstring_values(values, indent=8):
sorted(values.items(), key=itemgetter(1)))


class PiCameraMaxResolution(object):
"""
Singleton representing the maximum resolution of the camera module.
"""
PiCameraMaxResolution = PiCameraMaxResolution()


class PiCamera(object):
"""
Provides a pure Python interface to the Raspberry Pi's camera module.
Expand Down Expand Up @@ -176,7 +183,8 @@ class PiCamera(object):
CAMERA_PREVIEW_PORT = 0
CAMERA_VIDEO_PORT = 1
CAMERA_CAPTURE_PORT = 2
MAX_RESOLUTION = mo.PiCameraResolution(2592, 1944)
MAX_RESOLUTION = PiCameraMaxResolution # modified by PiCamera.__init__
MAX_FRAMERATE = 90
DEFAULT_ANNOTATE_SIZE = 32
CAPTURE_TIMEOUT = 30

Expand Down Expand Up @@ -347,27 +355,38 @@ def __init__(
self._overlays = []
self._raw_format = 'yuv'
self._image_effect_params = None
self._exif_tags = {
'IFD0.Model': 'RP_OV5647',
'IFD0.Make': 'RaspberryPi',
}
if resolution is None:
# Get screen resolution
w = ct.c_uint32()
h = ct.c_uint32()
if bcm_host.graphics_get_display_size(0, w, h) == -1:
w = 1280
h = 720
with mo.MMALCameraInfo() as camera_info:
info = camera_info.control.params[mmal.MMAL_PARAMETER_CAMERA_INFO]
self._exif_tags = {
'IFD0.Model': 'RP_OV5647',
'IFD0.Make': 'RaspberryPi',
}
if camera_info.info_rev > 1:
self._exif_tags['IFD0.Model'] = 'RP_%s' % info.cameras[camera_num].camera_name
if PiCamera.MAX_RESOLUTION is PiCameraMaxResolution:
PiCamera.MAX_RESOLUTION = mo.PiCameraResolution(
info.cameras[camera_num].max_width,
info.cameras[camera_num].max_height,
)
if resolution is None:
# Get screen resolution
w = ct.c_uint32()
h = ct.c_uint32()
if bcm_host.graphics_get_display_size(0, w, h) == -1:
w = 1280
h = 720
else:
w = int(w.value)
h = int(h.value)
resolution = mo.PiCameraResolution(w, h)
elif resolution is PiCameraMaxResolution:
resolution = PiCamera.MAX_RESOLUTION
else:
w = int(w.value)
h = int(h.value)
resolution = mo.PiCameraResolution(w, h)
else:
resolution = mo.to_resolution(resolution)
if framerate is None:
framerate = 30
else:
framerate = mo.to_fraction(framerate)
resolution = mo.to_resolution(resolution)
if framerate is None:
framerate = 30
else:
framerate = mo.to_fraction(framerate)
try:
stereo_mode = self.STEREO_MODES[stereo_mode]
except KeyError:
Expand Down Expand Up @@ -1951,7 +1970,7 @@ def _set_framerate(self, value):
self._check_camera_open()
self._check_recording_stopped()
value = mo.to_fraction(value)
if not (0 <= value <= 100):
if not (0 <= value <= self.MAX_FRAMERATE):
raise PiCameraValueError("Invalid framerate: %.2ffps" % value)
sensor_mode = self.sensor_mode
clock_mode = self.CLOCK_MODES[self.clock_mode]
Expand Down
25 changes: 24 additions & 1 deletion picamera/mmal.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,11 @@ def MMAL_FOURCC(s):
class MMAL_BOOL_T(ct.c_int32):
# This only exists to ensure we've got a distinct type to ct.c_int32
# for mmalobj to perform dict-lookups against
pass
def __str__(self):
return ['MMAL_FALSE', 'MMAL_TRUE'][bool(self.value)]

def __repr__(self):
return str(self)


class MMAL_CORE_STATISTICS_T(ct.Structure):
Expand Down Expand Up @@ -944,6 +948,7 @@ class MMAL_PARAMETER_CAMERA_CONFIG_T(ct.Structure):

MMAL_PARAMETER_CAMERA_INFO_MAX_CAMERAS = 4
MMAL_PARAMETER_CAMERA_INFO_MAX_FLASHES = 2
MMAL_PARAMETER_CAMERA_INFO_MAX_STR_LEN = 16

class MMAL_PARAMETER_CAMERA_INFO_CAMERA_T(ct.Structure):
_fields_ = [
Expand All @@ -953,6 +958,15 @@ class MMAL_PARAMETER_CAMERA_INFO_CAMERA_T(ct.Structure):
('lens_present', MMAL_BOOL_T),
]

class MMAL_PARAMETER_CAMERA_INFO_CAMERA_V2_T(ct.Structure):
_fields_ = [
('port_id', ct.c_uint32),
('max_width', ct.c_uint32),
('max_height', ct.c_uint32),
('lens_present', MMAL_BOOL_T),
('camera_name', ct.c_char * MMAL_PARAMETER_CAMERA_INFO_MAX_STR_LEN),
]

MMAL_PARAMETER_CAMERA_INFO_FLASH_TYPE_T = ct.c_uint32 # enum
MMAL_PARAMETER_CAMERA_INFO_FLASH_TYPE_XENON = 0
MMAL_PARAMETER_CAMERA_INFO_FLASH_TYPE_LED = 1
Expand All @@ -973,6 +987,15 @@ class MMAL_PARAMETER_CAMERA_INFO_T(ct.Structure):
('flashes', MMAL_PARAMETER_CAMERA_INFO_FLASH_T * MMAL_PARAMETER_CAMERA_INFO_MAX_FLASHES),
]

class MMAL_PARAMETER_CAMERA_INFO_V2_T(ct.Structure):
_fields_ = [
('hdr', MMAL_PARAMETER_HEADER_T),
('num_cameras', ct.c_uint32),
('num_flashes', ct.c_uint32),
('cameras', MMAL_PARAMETER_CAMERA_INFO_CAMERA_V2_T * MMAL_PARAMETER_CAMERA_INFO_MAX_CAMERAS),
('flashes', MMAL_PARAMETER_CAMERA_INFO_FLASH_T * MMAL_PARAMETER_CAMERA_INFO_MAX_FLASHES),
]

MMAL_PARAMETER_CAPTUREMODE_MODE_T = ct.c_uint32 # enum
(
MMAL_PARAM_CAPTUREMODE_WAIT_FOR_END,
Expand Down
100 changes: 80 additions & 20 deletions picamera/mmalobj.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@

PARAM_TYPES = {
mmal.MMAL_PARAMETER_ALGORITHM_CONTROL: mmal.MMAL_PARAMETER_ALGORITHM_CONTROL_T,
mmal.MMAL_PARAMETER_ANNOTATE: mmal.MMAL_PARAMETER_CAMERA_ANNOTATE_V3_T, # XXX adjust for firmware
mmal.MMAL_PARAMETER_ANNOTATE: None, # adjusted by MMALCamera.annotate_rev
mmal.MMAL_PARAMETER_ANTISHAKE: mmal.MMAL_PARAMETER_BOOLEAN_T,
mmal.MMAL_PARAMETER_AUDIO_LATENCY_TARGET: mmal.MMAL_PARAMETER_AUDIO_LATENCY_TARGET_T,
mmal.MMAL_PARAMETER_AWB_MODE: mmal.MMAL_PARAMETER_AWBMODE_T,
Expand All @@ -71,7 +71,7 @@
mmal.MMAL_PARAMETER_CAMERA_CLOCKING_MODE: mmal.MMAL_PARAMETER_CAMERA_CLOCKING_MODE_T,
mmal.MMAL_PARAMETER_CAMERA_CONFIG: mmal.MMAL_PARAMETER_CAMERA_CONFIG_T,
mmal.MMAL_PARAMETER_CAMERA_CUSTOM_SENSOR_CONFIG: ct.c_uint32,
mmal.MMAL_PARAMETER_CAMERA_INFO: mmal.MMAL_PARAMETER_CAMERA_INFO_T,
mmal.MMAL_PARAMETER_CAMERA_INFO: None, # adjusted by MMALCameraInfo.info_rev
mmal.MMAL_PARAMETER_CAMERA_INTERFACE: mmal.MMAL_PARAMETER_CAMERA_INTERFACE_T,
mmal.MMAL_PARAMETER_CAMERA_MIN_ISO: mmal.MMAL_PARAMETER_UINT32_T,
mmal.MMAL_PARAMETER_CAMERA_NUM: mmal.MMAL_PARAMETER_INT32_T,
Expand Down Expand Up @@ -1332,31 +1332,45 @@ class MMALCamera(MMALComponent):
component_type = mmal.MMAL_COMPONENT_DEFAULT_CAMERA
opaque_output_subformats = ('OPQV-single', 'OPQV-dual', 'OPQV-strips')

annotate_structs = (
mmal.MMAL_PARAMETER_CAMERA_ANNOTATE_T,
mmal.MMAL_PARAMETER_CAMERA_ANNOTATE_V2_T,
mmal.MMAL_PARAMETER_CAMERA_ANNOTATE_V3_T,
)

def __init__(self):
super(MMALCamera, self).__init__()
mp = self.control.params[mmal.MMAL_PARAMETER_ANNOTATE]
self.annotate_rev = {
ct.sizeof(mmal.MMAL_PARAMETER_CAMERA_ANNOTATE_T): 1,
ct.sizeof(mmal.MMAL_PARAMETER_CAMERA_ANNOTATE_V2_T): 2,
ct.sizeof(mmal.MMAL_PARAMETER_CAMERA_ANNOTATE_V3_T): 3,
}.get(mp.hdr.size, 3)
if PARAM_TYPES[mmal.MMAL_PARAMETER_ANNOTATE] is None:
found = False
# try largest struct to smallest as later firmwares still happily
# accept earlier revision structures
# XXX do old firmwares reject too-large structs?
for struct in reversed(MMALCamera.annotate_structs):
try:
PARAM_TYPES[mmal.MMAL_PARAMETER_ANNOTATE] = struct
self.control.params[mmal.MMAL_PARAMETER_ANNOTATE]
except PiCameraMMALError:
pass
else:
found = True
break
if not found:
PARAM_TYPES[mmal.MMAL_PARAMETER_ANNOTATE] = None
raise PiCameraMMALError(
mmal.MMAL_EINVAL, "unknown camera annotation structure revision")

def _get_annotate_rev(self):
return {
mmal.MMAL_PARAMETER_CAMERA_ANNOTATE_T: 1,
mmal.MMAL_PARAMETER_CAMERA_ANNOTATE_V2_T: 2,
mmal.MMAL_PARAMETER_CAMERA_ANNOTATE_V3_T: 3,
}[PARAM_TYPES[mmal.MMAL_PARAMETER_ANNOTATE]]
try:
return MMALCamera.annotate_structs.index(PARAM_TYPES[mmal.MMAL_PARAMETER_ANNOTATE]) + 1
except IndexError:
raise PiCameraMMALError(
mmal.MMAL_EINVAL, "unknown camera annotation structure revision")
def _set_annotate_rev(self, value):
try:
PARAM_TYPES[mmal.MMAL_PARAMETER_ANNOTATE] = {
1: mmal.MMAL_PARAMETER_CAMERA_ANNOTATE_T,
2: mmal.MMAL_PARAMETER_CAMERA_ANNOTATE_V2_T,
3: mmal.MMAL_PARAMETER_CAMERA_ANNOTATE_V3_T,
}[value]
except KeyError:
PARAM_TYPES[mmal.MMAL_PARAMETER_ANNOTATE] = MMALCamera.annotate_structs[value - 1]
except IndexError:
raise PiCameraMMALError(
mmal.MMAL_EINVAL, "cannot set annotation revision")
mmal.MMAL_EINVAL, "invalid camera annotation structure revision")
annotate_rev = property(_get_annotate_rev, _set_annotate_rev, doc="""\
The annotation capabilities of the firmware have evolved over time and
several structures are available for querying and setting video
Expand All @@ -1373,6 +1387,52 @@ class MMALCameraInfo(MMALComponent):
"""
component_type = mmal.MMAL_COMPONENT_DEFAULT_CAMERA_INFO

info_structs = (
mmal.MMAL_PARAMETER_CAMERA_INFO_T,
mmal.MMAL_PARAMETER_CAMERA_INFO_V2_T,
)

def __init__(self):
super(MMALCameraInfo, self).__init__()
if PARAM_TYPES[mmal.MMAL_PARAMETER_CAMERA_INFO] is None:
found = False
# try smallest structure to largest as later firmwares reject
# older structures
for struct in MMALCameraInfo.info_structs:
try:
PARAM_TYPES[mmal.MMAL_PARAMETER_CAMERA_INFO] = struct
self.control.params[mmal.MMAL_PARAMETER_CAMERA_INFO]
except PiCameraMMALError:
pass
else:
found = True
break
if not found:
PARAM_TYPES[mmal.MMAL_PARAMETER_CAMERA_INFO] = None
raise PiCameraMMALError(
mmal.MMAL_EINVAL, "unknown camera info structure revision")

def _get_info_rev(self):
try:
return MMALCameraInfo.info_structs.index(PARAM_TYPES[mmal.MMAL_PARAMETER_CAMERA_INFO]) + 1
except IndexError:
raise PiCameraMMALError(
mmal.MMAL_EINVAL, "unknown camera info structure revision")
def _set_info_rev(self, value):
try:
PARAM_TYPES[mmal.MMAL_PARAMETER_CAMERA_INFO] = MMALCameraInfo.info_structs[value - 1]
except IndexError:
raise PiCameraMMALError(
mmal.MMAL_EINVAL, "invalid camera info structure revision")
info_rev = property(_get_info_rev, _set_info_rev, doc="""\
The camera information capabilities of the firmware have evolved over
time and several structures are available for querying camera
information. When initialized, :class:`MMALCameraInfo` will attempt
to discover which structure is in use by the extant firmware. This
property can be used to discover the structure version and to modify
the version in use for other purposes (e.g. testing).
""")


class MMALDownstreamComponent(MMALComponent):
"""
Expand Down

0 comments on commit d9ad40b

Please sign in to comment.