Package flumotion :: Package component :: Package consumers :: Package hlsstreamer :: Module resources
[hide private]

Source Code for Module flumotion.component.consumers.hlsstreamer.resources

  1  # -*- Mode: Python -*- 
  2  # vi:si:et:sw=4:sts=4:ts=4 
  3   
  4  # Flumotion - a streaming media server 
  5  # Copyright (C) 2004,2005,2006,2007,2008,2009 Fluendo, S.L. 
  6  # Copyright (C) 2010,2011 Flumotion Services, S.A. 
  7  # All rights reserved. 
  8  # 
  9  # This file may be distributed and/or modified under the terms of 
 10  # the GNU Lesser General Public License version 2.1 as published by 
 11  # the Free Software Foundation. 
 12  # This file is distributed without any warranty; without even the implied 
 13  # warranty of merchantability or fitness for a particular purpose. 
 14  # See "LICENSE.LGPL" in the source distribution for more information. 
 15  # 
 16  # Headers in this file shall remain intact. 
 17   
 18  from twisted.internet import defer 
 19  from twisted.web import server 
 20   
 21  from flumotion.component.common.streamer.fragmentedresource import\ 
 22      FragmentedResource 
 23   
 24  __version__ = "$Rev: $" 
 25   
 26  M3U8_CONTENT_TYPE = 'application/vnd.apple.mpegurl' 
 27  PLAYLIST_EXTENSION = '.m3u8' 
 28   
 29  ### the Twisted resource that handles the base URL 
 30   
 31   
32 -class HTTPLiveStreamingResource(FragmentedResource):
33 34 logCategory = 'hls-streamer' 35
36 - def __init__(self, streamer, httpauth, secretKey, sessionTimeout):
37 """ 38 @param streamer: L{HTTPLiveStreamer} 39 """ 40 self.ring = streamer.getRing() 41 FragmentedResource.__init__(self, streamer, httpauth, secretKey, 42 sessionTimeout)
43
44 - def _renderKey(self, res, request):
45 self._writeHeaders(request, 'binary/octect-stream') 46 if request.method == 'GET': 47 key = self.ring.getEncryptionKey(request.args['key'][0]) 48 request.write(key) 49 self.bytesSent += len(key) 50 self._logWrite(request) 51 elif request.method == 'HEAD': 52 self.debug('handling HEAD request') 53 request.finish() 54 return res
55
56 - def _renderPlaylist(self, res, request, resource):
57 self.debug('_render(): asked for playlist %s', resource) 58 request.setHeader("Connection", "Keep-Alive") 59 self._writeHeaders(request, M3U8_CONTENT_TYPE) 60 if request.method == 'GET': 61 playlist = self.ring.renderPlaylist(resource, request.args) 62 request.write(playlist) 63 self.bytesSent += len(playlist) 64 self._logWrite(request) 65 elif request.method == 'HEAD': 66 self.debug('handling HEAD request') 67 request.finish() 68 return res
69
70 - def _renderFragment(self, res, request, resource):
71 self.debug('_render(): asked for fragment %s', resource) 72 request.setHeader('Connection', 'close') 73 self._writeHeaders(request, 'video/mpeg') 74 if request.method == 'GET': 75 data = self.ring.getFragment(resource) 76 request.setHeader('content-length', len(data)) 77 request.write(data) 78 self.bytesSent += len(data) 79 self._logWrite(request) 80 if request.method == 'HEAD': 81 self.debug('handling HEAD request') 82 request.finish() 83 return res
84
85 - def _render(self, request):
86 if not self.isReady(): 87 return self._handleNotReady(request) 88 if self.reachedServerLimits(): 89 return self._handleServerFull(request) 90 91 # A GET request will be like 'mountpoint+resource': 92 # 'GET /iphone/fragment-0.ts' or 'GET /fragment-0.ts' 93 # The mountpoint is surrounded by '/' in setMountPoint() 94 # so we can safely look for the mountpoint and extract the 95 # resource name 96 if not request.path.startswith(self.mountPoint): 97 return self._renderForbidden(request) 98 resource = request.path.replace(self.mountPoint, '', 1) 99 100 d = defer.maybeDeferred(self._checkSession, request) 101 102 # Playlists 103 if resource.endswith(PLAYLIST_EXTENSION): 104 d.addCallback(self._renderPlaylist, request, resource) 105 # Keys 106 elif resource == 'key' and 'key' in request.args: 107 d.addCallback(self._renderKey, request) 108 # Fragments 109 else: 110 d.addCallback(self._renderFragment, request, resource) 111 112 d.addErrback(self._renderNotFoundResponse, request) 113 return server.NOT_DONE_YET
114 115 render_GET = _render 116 render_HEAD = _render
117