]> www.vanbest.org Git - motioneye-debian/commitdiff
Back out full support for HTTP Range.
authorDermot Duffy <dermot.duffy@gmail.com>
Sun, 14 Aug 2016 00:52:20 +0000 (01:52 +0100)
committerDermot Duffy <dermot.duffy@gmail.com>
Sun, 14 Aug 2016 00:52:20 +0000 (01:52 +0100)
Simplify the code by removing Range support. Seeking will thus
not function until the movie has been downloaded.

motioneye/handlers.py
motioneye/remote.py
motioneye/static/js/main.js

index 549d8f4b79f727098e1853ba49600ddcbe1b82f9..f36f745b8d5290967e594468a984e76347d6edcf 100644 (file)
@@ -24,9 +24,8 @@ import re
 import socket
 import subprocess
 
-from tornado import httputil
 from tornado.ioloop import IOLoop
-from tornado.web import RequestHandler, StaticFileHandler, HTTPError, asynchronous
+from tornado.web import RequestHandler, HTTPError, asynchronous
 
 import config
 import mediafiles
@@ -979,7 +978,7 @@ class PictureHandler(BaseHandler):
                 self.set_header('Content-Type', 'image/jpeg')
                 self.set_header('Content-Disposition', 'attachment; filename=' + pretty_filename + ';')
                 
-                self.finish(response.body)
+                self.finish(response)
 
             remote.get_media_content(camera_config, filename=filename, media_type='picture', callback=on_response)
 
@@ -1340,78 +1339,28 @@ class MovieHandler(BaseHandler):
                 'filename': filename, 'id': camera_id})
         
         camera_config = config.get_camera(camera_id)
-
-        # To facilitiate cross-browser HTML5 <video> playback we need
-        # to support HTTP Range requests.
-        # (The below adapted from Tornado's StaticFileHandler)
-        request_range = None
-        range_header = self.request.headers.get("Range")
-        if range_header:
-            request_range = httputil._parse_request_range(range_header)
-
         if utils.local_motion_camera(camera_config):
-            full_path = os.path.join(camera_config.get('target_dir'), filename)
-            size = os.stat(full_path).st_size
-            if request_range:
-                start, end = request_range
-                if (start is not None and start >= size) or end == 0:
-                    raise HTTPError(416, 'Range not satisfiable')
-                if start is not None and start < 0:
-                    start += size
-                if end is not None and end > size:
-                    end = size
-                # Chrome won't allow seeking unless we always return 206 for Range requests,
-                # even if this represents the entire file.
-                self.set_status(206)  # Partial Content
-                self.set_header("Content-Range", httputil._get_content_range(start, end, size))
-            else:
-                start = end = None
-
-            if start is not None and end is not None:
-                content_length = end - start
-            elif end is not None:
-                content_length = end
-            elif start is not None:
-                content_length = size - start
-            else:
-                content_length = size
+            content = mediafiles.get_media_content(camera_config, filename, 'movie')
 
             pretty_filename = camera_config['@name'] + '_' + os.path.basename(filename)
-            self.set_header('Content-Type', mimetypes.guess_type(full_path)[0] or 'video/mpeg')
+            self.set_header('Content-Type', mimetypes.guess_type(filename)[0] or 'video/mpeg')
             self.set_header('Content-Disposition', 'attachment; filename=' + pretty_filename + ';')
-            self.set_header("Content-Length", content_length)
-
-            # Yield the data to the network in chunks.
-            content = StaticFileHandler.get_content(full_path, start, end)
-            if content:           
-                for chunk in content:
-                    try:
-                        self.write(chunk)
-                        self.flush()
-                    except iostream.StreamClosedError:
-                        return
-            self.finish()
+
+            self.finish(content)
 
         elif utils.remote_camera(camera_config):
             def on_response(response=None, error=None):
                 if error:
                     return self.finish_json({'error': 'Failed to download movie from %(url)s: %(msg)s.' % {
                             'url': remote.pretty_camera_url(camera_config), 'msg': error}})
-                # Copy certain critical headers out of the remote response and
-                # into our response. Propogating these headers are necessary to
-                # support in-brower playback of remote movies. Also copy the 
-                # response code which might be 200 or 206 (partial content, for range
-                # requests).
-                self.set_status(response.code)
-                for header in ('Content-Type', 'Content-Range', 'Content-Length', 'Content-Disposition'):
-                    if header in response.headers:
-                        self.set_header(header, response.headers[header])
-                self.finish(response.body)
-
-            start = end = None
-            if request_range:
-                start, end = request_range
-            remote.get_media_content(camera_config, filename=filename, media_type='movie', callback=on_response, start=start, end=end)
+
+                pretty_filename = os.path.basename(filename) # no camera name available w/o additional request
+                self.set_header('Content-Type', 'video/mpeg')
+                self.set_header('Content-Disposition', 'attachment; filename=' + pretty_filename + ';')
+
+                self.finish(response)
+
+            remote.get_media_content(camera_config, filename=filename, media_type='movie', callback=on_response)
 
         else: # assuming simple mjpeg camera
             raise HTTPError(400, 'unknown operation')
index 2d1757bcf37c047e40e052c66320dbb17151a359..74e6217bd2ddde8fc0912c091c63db00f52d77ef 100644 (file)
@@ -379,7 +379,7 @@ def list_media(local_config, media_type, prefix, callback):
     http_client.fetch(request, _callback_wrapper(on_response))
 
 
-def get_media_content(local_config, filename, media_type, callback, start=None, end=None):
+def get_media_content(local_config, filename, media_type, callback):
     scheme, host, port, username, password, path, camera_id = _remote_params(local_config)
     
     logging.debug('downloading file %(filename)s of remote camera %(id)s on %(url)s' % {
@@ -391,18 +391,11 @@ def get_media_content(local_config, filename, media_type, callback, start=None,
             'media_type': media_type,
             'id': camera_id,
             'filename': filename}
+
     # timeout here is 10 times larger than usual - we expect a big delay when fetching the media list
     request = _make_request(scheme, host, port, username, password,
             path, timeout=10 * settings.REMOTE_REQUEST_TIMEOUT)
-   
-    if start is not None or end is not None:
-        end_str = ''
-        start = start or 0
-        if end:
-            end_str = str(end - 1)
-        request.headers['Range'] = 'bytes=%i-%s' % (start, end_str)
+
     def on_response(response):
         if response.error:
             logging.error('failed to download file %(filename)s of remote camera %(id)s on %(url)s: %(msg)s' % {
@@ -413,7 +406,7 @@ def get_media_content(local_config, filename, media_type, callback, start=None,
             
             return callback(error=utils.pretty_http_error(response))
         
-        return callback(response)
+        return callback(response.body)
 
     http_client = AsyncHTTPClient()
     http_client.fetch(request, _callback_wrapper(on_response))
index 98fd6ea7c27dbff45225fd532b7578846c9a6c3b..21f420f11dbaf1da007b04d3fdd255a7945c4cdb 100644 (file)
@@ -2926,11 +2926,11 @@ function runPictureDialog(entries, pos, mediaType) {
     });
     video_container.hide()
     content.append(video_container);
+
     var prevArrow = $('<div class="picture-dialog-prev-arrow button mouse-effect" title="previous picture"></div>');
     content.append(prevArrow);
 
-    var playButton = $('<div class="picture-dialog-play button mouse-effect" title="play"></div>');  
+    var playButton = $('<div class="picture-dialog-play button mouse-effect" title="play"></div>');
     content.append(playButton);
 
     var nextArrow = $('<div class="picture-dialog-next-arrow button mouse-effect" title="next picture"></div>');
@@ -2951,7 +2951,7 @@ function runPictureDialog(entries, pos, mediaType) {
         prevArrow.css('display', 'none');
         nextArrow.css('display', 'none');
 
-        /* Construct a likely mime-type with 'video/' and the file extension, then see if the 
+        /* Construct a likely mime-type with 'video/' and the file extension, then see if the
            browser can play it */
         var playable = video_container.get(0).canPlayType(entry.mimeType) != ''
         playButton.hide();