Trees | Indices | Help |
---|
|
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 import gst 19 import urlparse 20 21 from twisted.internet import reactor 22 23 from flumotion.common import gstreamer 24 from flumotion.common.i18n import gettexter 25 from flumotion.component.base import http 26 from flumotion.component.component import moods 27 from flumotion.component.common.streamer.fragmentedstreamer import\ 28 FragmentedStreamer, Stats 29 from flumotion.component.consumers.hlsstreamer.resources import \ 30 HTTPLiveStreamingResource 31 from flumotion.component.consumers.hlsstreamer.hlsring import HLSRing 32 from flumotion.component.consumers.hlsstreamer import hlssink 33 34 __all__ = ['HLSStreamer'] 35 __version__ = "" 36 T_ = gettexter() 37 3840 DEFAULT_SESSION_TIMEOUT = 30 41 DEFAULT_FRAGMENT_PREFIX = 'fragment' 42 DEFAULT_MAIN_PLAYLIST = 'main.m3u8' 43 DEFAULT_STREAM_PLAYLIST = 'stream.m3u8' 44 DEFAULT_STREAM_BITRATE = 300000 45 DEFAULT_KEYFRAMES_PER_SEGMENT = 10 46 47 logCategory = 'hls-streamer' 48 52 55154 155 ### END OF THREAD-AWARE CODE 15657 # Check of the hlssink is available or use the python one 58 if not gstreamer.element_factory_exists('hlssink'): 59 hlssink.register() 60 return "hlssink name=sink sync=false"6163 self.httpauth = http.HTTPAuthentication(self) 64 self.resource = HTTPLiveStreamingResource(self, self.httpauth, 65 self.secret_key, self.session_timeout)6668 return self.hlsring6971 self.hlsring = HLSRing( 72 props.get('main-playlist', self.DEFAULT_MAIN_PLAYLIST), 73 props.get('stream-playlist', self.DEFAULT_STREAM_PLAYLIST), 74 props.get('stream-bitrate', self.DEFAULT_STREAM_BITRATE), 75 self.description, 76 props.get('fragment-prefix', self.DEFAULT_FRAGMENT_PREFIX), 77 props.get('new-fragment-tolerance', 0), 78 props.get('max-window', self.DEFAULT_MAX_WINDOW), 79 props.get('max-extra-buffers', None), 80 props.get('key-rotation', 0), 81 props.get('keys-uri', None)) 82 83 # Call the base class after initializing the ring and getting 84 # the secret key and the session timeout 85 FragmentedStreamer.configure_pipeline(self, pipeline, props) 86 87 self.hls_url = props.get('hls-url', None) 88 if self.hls_url: 89 if not self.hls_url.endswith('/'): 90 self.hls_url += '/' 91 if self.mountPoint.startswith('/'): 92 mp = self.mountPoint[1:] 93 else: 94 mp = self.mountPoint 95 self.hls_url = urlparse.urljoin(self.hls_url, mp) 96 else: 97 self.hls_url = self.getUrl() 98 99 self.hlsring.setHostname(self.hls_url) 100 self.soft_restart()101103 """Stops serving fragments, resets the playlist and starts 104 waiting for new segments to become happy again 105 """ 106 self.info("Soft restart, resetting playlist and waiting to fill " 107 "the initial fragments window") 108 self._ready = False 109 self._fragmentsCount = 0 110 self._last_index = 0 111 self.hlsring.reset()112114 self.sink.set_property('write-to-disk', False) 115 self.sink.set_property('playlist-max-window', 5)116118 FragmentedStreamer._connect_sink_signals(self) 119 self.sink.connect("new-fragment", self._new_fragment)120122 self._fragmentsCount = self._fragmentsCount + 1 123 124 # Wait hls-min-window fragments to set the component 'happy' 125 if self._fragmentsCount == self._minWindow: 126 self.info("%d fragments received. Changing mood to 'happy'", 127 self._fragmentsCount) 128 self.setMood(moods.happy) 129 self._ready = True 130 131 b = fragment.get_property('buffer') 132 index = fragment.get_property('index') 133 duration = fragment.get_property('duration') 134 135 if index < self._last_index: 136 self.warning("Found a discontinuity last index is %s but current " 137 "one is %s", self._last_index, index) 138 self.soft_restart() 139 140 fragName = self.hlsring.addFragment(b.data, index, 141 round(duration / float(gst.SECOND))) 142 self.info('Added fragment "%s", index=%s, duration=%s', 143 fragName, index, gst.TIME_ARGS(duration))144 145 ### START OF THREAD-AWARE CODE (called from non-reactor threads) 146148 self.log("hlsink created a new fragment") 149 try: 150 fragment = hlssink.get_property('fragment') 151 except: 152 fragment = hlssink.emit('pull-fragment') 153 reactor.callFromThread(self._process_fragment, fragment)
Trees | Indices | Help |
---|
Generated by Epydoc 3.0.1 on Tue Aug 13 06:17:36 2013 | http://epydoc.sourceforge.net |