From: Calin Crisan Date: Sun, 24 Nov 2013 13:59:00 +0000 (+0200) Subject: implemented server side current picture caching based on a sequence X-Git-Url: http://www.vanbest.org/gitweb/?a=commitdiff_plain;h=dba4b69bf5aba76b340c586f42c8162c69ba7a7a;p=motioneye-debian implemented server side current picture caching based on a sequence number --- diff --git a/settings_default.py b/settings_default.py index 399720b..1109f51 100644 --- a/settings_default.py +++ b/settings_default.py @@ -43,3 +43,6 @@ REMOTE_REQUEST_TIMEOUT = 10 # timeout in seconds to wait for an access to a mjpg client before removing it MJPG_CLIENT_TIMEOUT = 10 + +# the maximal number of entries per camera in the current pictures cache +PICTURE_CACHE_SIZE = 8 diff --git a/src/handlers.py b/src/handlers.py index 0bbbb50..b285aa2 100644 --- a/src/handlers.py +++ b/src/handlers.py @@ -541,16 +541,31 @@ class PictureHandler(BaseHandler): def current(self, camera_id): self.set_header('Content-Type', 'image/jpeg') + sequence = self.get_argument('seq', None) + if sequence: + sequence = int(sequence) + + picture = sequence and mediafiles.get_picture_cache(camera_id, sequence) or None + + if picture is not None: + return self.finish(picture) + camera_config = config.get_camera(camera_id) if camera_config['@proto'] == 'v4l2': picture = mediafiles.get_current_picture(camera_config, width=self.get_argument('width', None), height=self.get_argument('height', None)) + + if sequence and picture: + mediafiles.set_picture_cache(camera_id, sequence, picture) self.finish(picture) else: def on_response(picture): + if sequence and picture: + mediafiles.set_picture_cache(camera_id, sequence, picture) + self.finish(picture) remote.get_current_picture( diff --git a/src/mediafiles.py b/src/mediafiles.py index 5d2ecca..aa0b2e5 100644 --- a/src/mediafiles.py +++ b/src/mediafiles.py @@ -25,12 +25,17 @@ from PIL import Image import config import mjpgclient +import settings import utils _PICTURE_EXTS = ['.jpg'] _MOVIE_EXTS = ['.avi', '.mp4'] +# a dictionary indexed by camera_id containing +# tuples of (sequence, content) +_current_pictures_cache = {} + def _list_media_files(dir, exts, prefix=None): full_paths = [] @@ -302,3 +307,29 @@ def get_current_picture(camera_config, width, height): image.save(sio, format='JPEG') return sio.getvalue() + + +def set_picture_cache(camera_id, sequence, content): + global _current_pictures_cache + + if not content: + return + + cache = _current_pictures_cache.setdefault(camera_id, []) + + if len(cache) >= settings.PICTURE_CACHE_SIZE: + cache.pop(0) # drop the first item + + cache.append((sequence, content)) + + +def get_picture_cache(camera_id, sequence): + global _current_pictures_cache + + cache = _current_pictures_cache.setdefault(camera_id, []) + + for (seq, content) in cache: + if seq >= sequence: + return content + + return None diff --git a/src/remote.py b/src/remote.py index 83536f1..c62bbe0 100644 --- a/src/remote.py +++ b/src/remote.py @@ -22,6 +22,7 @@ from tornado.httpclient import AsyncHTTPClient, HTTPClient, HTTPRequest import settings + _snapshot_cache = {} diff --git a/static/js/main.js b/static/js/main.js index ff5248f..b42b55b 100644 --- a/static/js/main.js +++ b/static/js/main.js @@ -1857,7 +1857,7 @@ function refreshCameraFrames() { timestamp /= 500; } timestamp = Math.round(timestamp); - img.src = '/picture/' + cameraId + '/current/?_=' + timestamp + '&width=' + img.width; + img.src = '/picture/' + cameraId + '/current/?seq=' + timestamp + '&width=' + img.width; img.loading = true; }