From dc94e2aaf6800b7ce94a4acbbf5497cfde1aeef1 Mon Sep 17 00:00:00 2001 From: inodlite <1023852+inodlite@users.noreply.github.com> Date: Fri, 18 Aug 2017 23:57:48 -0700 Subject: [PATCH] Add initial support for local MMAL cameras --- motioneye/config.py | 26 +++++++++++++++++++++++--- motioneye/handlers.py | 14 ++++++++++++++ motioneye/static/js/main.js | 25 ++++++++++++++++++++----- motioneye/utils.py | 15 +++++++++++++-- 4 files changed, 70 insertions(+), 10 deletions(-) diff --git a/motioneye/config.py b/motioneye/config.py index b87fe8d..9d4e310 100644 --- a/motioneye/config.py +++ b/motioneye/config.py @@ -117,7 +117,8 @@ _KNOWN_MOTION_OPTIONS = { 'text_right', 'threshold', 'videodevice', - 'width' + 'width', + 'mmalcam_name' } @@ -540,7 +541,7 @@ def add_camera(device_details): while camera_id in camera_ids: camera_id += 1 - logging.info('adding new camera with id %(id)s...' % {'id': camera_id}) + logging.info('adding new %(prt)s camera with id %(id)s...' % {'prt': proto, 'id': camera_id}) # prepare a default camera config camera_config = {'@enabled': True} @@ -564,6 +565,11 @@ def add_camera(device_details): camera_config['@password'] = device_details['password'] camera_config['@remote_camera_id'] = device_details['remote_camera_id'] + elif proto == 'mmal': + camera_config['mmalcam_name'] = device_details['path'] + camera_config['width'] = 640 + camera_config['height'] = 480 + elif proto == 'netcam': camera_config['netcam_url'] = device_details['url'] camera_config['text_double'] = True @@ -812,10 +818,13 @@ def motion_camera_ui_to_dict(ui, old_config=None): if utils.is_v4l2_camera(old_config): proto = 'v4l2' + elif utils.is_mmal_camera(old_config): + proto = 'mmal' + else: proto = 'netcam' - if proto == 'v4l2': + if (proto == 'v4l2') or (proto == 'mmal'): # leave videodevice unchanged # resolution @@ -1234,6 +1243,17 @@ def motion_camera_dict_to_ui(data): # we have no other choice but use something like 640x480 as reference threshold = data['threshold'] * 100.0 / (640 * 480) + elif utils.is_mmal_camera(data): + ui['device_url'] = data['mmalcam_name'] + ui['proto'] = 'mmal' + + resolutions = utils.RPI_MMAL_RESOLUTIONS + resolutions = [r for r in resolutions if motionctl.resolution_is_valid(*r)] + ui['available_resolutions'] = [(str(w) + 'x' + str(h)) for (w, h) in resolutions] + ui['resolution'] = str(data['width']) + 'x' + str(data['height']) + + threshold = data['threshold'] * 100.0 / (data['width'] * data['height']) + else: # assuming v4l2 ui['device_url'] = data['videodevice'] ui['proto'] = 'v4l2' diff --git a/motioneye/handlers.py b/motioneye/handlers.py index e483e2b..022b82f 100644 --- a/motioneye/handlers.py +++ b/motioneye/handlers.py @@ -651,6 +651,20 @@ class ConfigHandler(BaseHandler): self.finish_json({'cameras': cameras}) + elif proto == 'mmal': + configured_devices = set() + for camera_id in config.get_camera_ids(): + data = config.get_camera(camera_id) + if utils.is_mmal_camera(data): + configured_devices.add(data['mmalcam_name']) + + if "vc.ril.camera" not in configured_devices: + cameras = [{'id': "vc.ril.camera", 'name': "VideoCore Camera (vc.ril.camera)"}] + else: + cameras = [] + + self.finish_json({'cameras': cameras}) + else: # assuming local motionEye camera listing cameras = [] camera_ids = config.get_camera_ids() diff --git a/motioneye/static/js/main.js b/motioneye/static/js/main.js index 329bc78..d32f400 100644 --- a/motioneye/static/js/main.js +++ b/motioneye/static/js/main.js @@ -2059,6 +2059,10 @@ function dict2CameraUi(dict) { case 'netcam': prettyType = 'Network Camera'; break; + + case 'mmal': + prettyType = 'MMAL Camera'; + break; case 'motioneye': prettyType = 'Remote motionEye Camera'; @@ -3316,7 +3320,7 @@ function getCameraIdsByInstance() { var cameraIdsByInstance = {}; getCameraFrames().each(function () { var instance; - if (this.config.proto == 'netcam' || this.config.proto == 'v4l2') { + if (this.config.proto == 'netcam' || this.config.proto == 'v4l2' || this.config.proto == 'mmal') { instance = ''; } else if (this.config.proto == 'motioneye') { @@ -3563,6 +3567,7 @@ function runAddCameraDialog() { 'Camera Type' + '' + '?' + '' + - '' + + '' + 'Camera' + '' + '?' + '' + - '' + + '' + '
' + '' + - '' + + '' + '
' + '' + ''); @@ -3614,7 +3619,7 @@ function runAddCameraDialog() { /* ui interaction */ function updateUi() { - content.find('tr.v4l2, tr.motioneye, tr.netcam, tr.mjpeg').css('display', 'none'); + content.find('tr.v4l2, tr.motioneye, tr.netcam, tr.mjpeg, tr.mmal').css('display', 'none'); if (typeSelect.val() == 'motioneye') { content.find('tr.motioneye').css('display', 'table-row'); @@ -3640,6 +3645,12 @@ function runAddCameraDialog() { 'Network cameras (or IP cameras) are devices that natively stream RTSP or MJPEG videos or plain JPEG images. ' + "Consult your device's manual to find out the correct RTSP, MJPEG or JPEG URL."); } + else if (typeSelect.val() == 'mmal') { + content.find('tr.mmal').css('display', 'table-row'); + addCameraInfo.html( + 'Local MMAL cameras are devices that are connected directly to your motionEye system. ' + + 'These are usually board-specific cameras.'); + } else if (typeSelect.val() == 'mjpeg') { usernameEntry.removeAttr('readonly'); @@ -3827,6 +3838,10 @@ function runAddCameraDialog() { data.proto = 'netcam'; data.camera_index = addCameraSelect.val(); } + else if (typeSelect.val() == 'mmal') { + data.path = addCameraSelect.val(); + data.proto = 'mmal'; + } else if (typeSelect.val() == 'mjpeg') { data = splitCameraUrl(urlEntry.val()); data.username = usernameEntry.val(); diff --git a/motioneye/utils.py b/motioneye/utils.py index e00b3d6..34f0dff 100644 --- a/motioneye/utils.py +++ b/motioneye/utils.py @@ -67,6 +67,15 @@ COMMON_RESOLUTIONS = [ (1920, 1080) ] +RPI_MMAL_RESOLUTIONS = [ + (640, 480), + (1280, 720), + (1280, 960), + (1920, 1080), + (1920, 1088), + (2592, 1944) +] + def _(x): return x # this could later be replaced by a proper translate function @@ -336,8 +345,7 @@ def get_disk_usage(path): def is_local_motion_camera(config): """Tells if a camera is managed by the local motion instance.""" - return bool(config.get('videodevice') or config.get('netcam_url')) - + return bool(config.get('videodevice') or config.get('netcam_url') or config.get('mmalcam_name')) def is_remote_camera(config): """Tells if a camera is managed by a remote motionEye server.""" @@ -348,6 +356,9 @@ def is_v4l2_camera(config): """Tells if a camera is a v4l2 device managed by the local motion instance.""" return bool(config.get('videodevice')) +def is_mmal_camera(config): + '''Tells if a camera is mmal device managed by the local motion instance.''' + return bool(config.get('mmalcam_name')) def is_net_camera(config): """Tells if a camera is a network camera managed by the local motion instance.""" -- 2.39.5