Example #1
0
    def configure_pipeline(self, pipeline, props):
        self.hlsring = HLSRing(
            props.get('main-playlist', self.DEFAULT_MAIN_PLAYLIST),
            props.get('stream-playlist', self.DEFAULT_STREAM_PLAYLIST),
            props.get('stream-bitrate', self.DEFAULT_STREAM_BITRATE),
            self.description,
            props.get('fragment-prefix', self.DEFAULT_FRAGMENT_PREFIX),
            props.get('new-fragment-tolerance', 0),
            props.get('max-window', self.DEFAULT_MAX_WINDOW),
            props.get('max-extra-buffers', None), props.get('key-rotation', 0),
            props.get('keys-uri', None))

        # Call the base class after initializing the ring and getting
        # the secret key and the session timeout
        FragmentedStreamer.configure_pipeline(self, pipeline, props)

        self.hls_url = props.get('hls-url', None)
        if self.hls_url:
            if not self.hls_url.endswith('/'):
                self.hls_url += '/'
            if self.mountPoint.startswith('/'):
                mp = self.mountPoint[1:]
            else:
                mp = self.mountPoint
            self.hls_url = urlparse.urljoin(self.hls_url, mp)
        else:
            self.hls_url = self.getUrl()

        self.hlsring.setHostname(self.hls_url)
        self.soft_restart()
Example #2
0
    def configure_pipeline(self, pipeline, props):
        self.hlsring = HLSRing(
            props.get('main-playlist', self.DEFAULT_MAIN_PLAYLIST),
            props.get('stream-playlist', self.DEFAULT_STREAM_PLAYLIST),
            props.get('stream-bitrate', self.DEFAULT_STREAM_BITRATE),
            self.description,
            props.get('fragment-prefix', self.DEFAULT_FRAGMENT_PREFIX),
            props.get('new-fragment-tolerance', 0),
            props.get('max-window', self.DEFAULT_MAX_WINDOW),
            props.get('max-extra-buffers', None),
            props.get('key-rotation', 0),
            props.get('keys-uri', None))

        # Call the base class after initializing the ring and getting
        # the secret key and the session timeout
        FragmentedStreamer.configure_pipeline(self, pipeline, props)

        self.hls_url = props.get('hls-url', None)
        if self.hls_url:
            if not self.hls_url.endswith('/'):
                self.hls_url += '/'
            if self.mountPoint.startswith('/'):
                mp = self.mountPoint[1:]
            else:
                mp = self.mountPoint
            self.hls_url = urlparse.urljoin(self.hls_url, mp)
        else:
            self.hls_url = self.getUrl()

        self.hlsring.setHostname(self.hls_url)
        self.soft_restart()
Example #3
0
class HLSStreamer(FragmentedStreamer, Stats):
    DEFAULT_SESSION_TIMEOUT = 30
    DEFAULT_FRAGMENT_PREFIX = 'fragment'
    DEFAULT_MAIN_PLAYLIST = 'main.m3u8'
    DEFAULT_STREAM_PLAYLIST = 'stream.m3u8'
    DEFAULT_STREAM_BITRATE = 300000
    DEFAULT_KEYFRAMES_PER_SEGMENT = 10

    logCategory = 'hls-streamer'

    _mime_type = None
    _content_type = None
    _stream_setup = False

    def init(self):
        self.debug("HTTP live streamer initialising")
        self.hlsring = None

    def get_mime(self):
        return self._mime_type

    def get_content_type(self):
        return self._content_type

    def get_pipeline_string(self, properties):
        # Check of the hlssink is available or use the python one
        if not gstreamer.element_factory_exists('hlssink'):
            hlssink.register()
        return "hlssink name=sink sync=false"

    def configure_auth_and_resource(self):
        self.httpauth = http.HTTPAuthentication(self)
        self.resource = HTTPLiveStreamingResource(self, self.httpauth,
                self.secret_key, self.session_timeout)

    def getRing(self):
        return self.hlsring

    def configure_pipeline(self, pipeline, props):
        self.hlsring = HLSRing(
            props.get('main-playlist', self.DEFAULT_MAIN_PLAYLIST),
            props.get('stream-playlist', self.DEFAULT_STREAM_PLAYLIST),
            props.get('stream-bitrate', self.DEFAULT_STREAM_BITRATE),
            self.description,
            props.get('fragment-prefix', self.DEFAULT_FRAGMENT_PREFIX),
            props.get('new-fragment-tolerance', 0),
            props.get('max-window', self.DEFAULT_MAX_WINDOW),
            props.get('max-extra-buffers', None),
            props.get('key-rotation', 0),
            props.get('keys-uri', None))

        # Call the base class after initializing the ring and getting
        # the secret key and the session timeout
        FragmentedStreamer.configure_pipeline(self, pipeline, props)

        self.hls_url = props.get('hls-url', None)
        if self.hls_url:
            if not self.hls_url.endswith('/'):
                self.hls_url += '/'
            if self.mountPoint.startswith('/'):
                mp = self.mountPoint[1:]
            else:
                mp = self.mountPoint
            self.hls_url = urlparse.urljoin(self.hls_url, mp)
        else:
            self.hls_url = self.getUrl()

        self.hlsring.setHostname(self.hls_url)
        self.soft_restart()

    def soft_restart(self):
        """Stops serving fragments, resets the playlist and starts
        waiting for new segments to become happy again
        """
        self.info("Soft restart, resetting playlist and waiting to fill "
                  "the initial fragments window")
        self._ready = False
        self._fragmentsCount = 0
        self._last_index = 0
        self.hlsring.reset()

    def _setup_stream_type(self, stream_type):
        self.info("Setting up streamer for stream type %s", stream_type)
        mime_type, content_type, frag_ext = SUPPORTED_FORMATS[stream_type]
        self._mime_type = mime_type
        self._content_type = content_type
        self.hlsring.filenameExt = frag_ext
        self._stream_setup = True

    def _configure_sink(self):
        self.sink.set_property('write-to-disk', False)
        self.sink.set_property('playlist-max-window', 5)

    def _connect_sink_signals(self):
        FragmentedStreamer._connect_sink_signals(self)
        self.sink.connect("new-fragment", self._new_fragment)

    def _process_fragment(self, fragment):

        if not self._stream_setup:
            sink = self.get_element("sink")
            pad = sink.get_pad("sink")
            caps = pad.get_negotiated_caps()
            name = caps.get_structure(0).get_name()
            self._setup_stream_type(name)

        self._fragmentsCount = self._fragmentsCount + 1

        # Wait hls-min-window fragments to set the component 'happy'
        if self._fragmentsCount == self._minWindow:
            self.info("%d fragments received. Changing mood to 'happy'",
                    self._fragmentsCount)
            self.setMood(moods.happy)
            self._ready = True

        b = fragment.get_property('buffer')
        index = fragment.get_property('index')
        duration = fragment.get_property('duration')

        if index < self._last_index:
            self.warning("Found a discontinuity last index is %s but current "
                         "one is %s", self._last_index, index)
            self.soft_restart()

        fragName = self.hlsring.addFragment(b.data, index,
                round(duration / float(gst.SECOND)))
        self.info('Added fragment "%s", index=%s, duration=%s',
                  fragName, index, gst.TIME_ARGS(duration))

    ### START OF THREAD-AWARE CODE (called from non-reactor threads)

    def _new_fragment(self, hlssink):
        self.log("hlsink created a new fragment")
        try:
            fragment = hlssink.get_property('fragment')
        except:
            fragment = hlssink.emit('pull-fragment')
        reactor.callFromThread(self._process_fragment, fragment)
Example #4
0
class HLSStreamer(FragmentedStreamer, Stats):
    DEFAULT_SESSION_TIMEOUT = 30
    DEFAULT_FRAGMENT_PREFIX = 'fragment'
    DEFAULT_MAIN_PLAYLIST = 'main.m3u8'
    DEFAULT_STREAM_PLAYLIST = 'stream.m3u8'
    DEFAULT_STREAM_BITRATE = 300000
    DEFAULT_KEYFRAMES_PER_SEGMENT = 10

    logCategory = 'hls-streamer'

    _mime_type = None
    _content_type = None
    _stream_setup = False

    def init(self):
        self.debug("HTTP live streamer initialising")
        self.hlsring = None

    def get_mime(self):
        return self._mime_type

    def get_content_type(self):
        return self._content_type

    def get_pipeline_string(self, properties):
        # Always use the python element for now. The C element will be used
        # when it is mature enough.
        # if not gstreamer.element_factory_exists('hlssink'):
        hlssink.register()
        return "hlssink name=sink sync=false"

    def configure_auth_and_resource(self):
        self.httpauth = http.HTTPAuthentication(self)
        self.resource = HTTPLiveStreamingResource(self, self.httpauth,
                                                  self.secret_key,
                                                  self.session_timeout)

    def getRing(self):
        return self.hlsring

    def configure_pipeline(self, pipeline, props):
        self.hlsring = HLSRing(
            props.get('main-playlist', self.DEFAULT_MAIN_PLAYLIST),
            props.get('stream-playlist', self.DEFAULT_STREAM_PLAYLIST),
            props.get('stream-bitrate', self.DEFAULT_STREAM_BITRATE),
            self.description,
            props.get('fragment-prefix', self.DEFAULT_FRAGMENT_PREFIX),
            props.get('new-fragment-tolerance', 0),
            props.get('max-window', self.DEFAULT_MAX_WINDOW),
            props.get('max-extra-buffers', None), props.get('key-rotation', 0),
            props.get('keys-uri', None))

        # Call the base class after initializing the ring and getting
        # the secret key and the session timeout
        FragmentedStreamer.configure_pipeline(self, pipeline, props)

        self.hls_url = props.get('hls-url', None)
        if self.hls_url:
            if not self.hls_url.endswith('/'):
                self.hls_url += '/'
            if self.mountPoint.startswith('/'):
                mp = self.mountPoint[1:]
            else:
                mp = self.mountPoint
            self.hls_url = urlparse.urljoin(self.hls_url, mp)
        else:
            self.hls_url = self.getUrl()

        self.hlsring.setHostname(self.hls_url)
        self.soft_restart()

    def soft_restart(self):
        """Stops serving fragments, resets the playlist and starts
        waiting for new segments to become happy again
        """
        self.info("Soft restart, resetting playlist and waiting to fill "
                  "the initial fragments window")
        self._ready = False
        self._fragmentsCount = 0
        self._last_index = 0
        self.hlsring.reset()

    def _setup_stream_type(self, stream_type):
        self.info("Setting up streamer for stream type %s", stream_type)
        mime_type, content_type, frag_ext = SUPPORTED_FORMATS[stream_type]
        self._mime_type = mime_type
        self._content_type = content_type
        self.hlsring.filenameExt = frag_ext
        self._stream_setup = True

    def _configure_sink(self):
        self.sink.set_property('write-to-disk', False)
        self.sink.set_property('playlist-max-window', 5)

    def _connect_sink_signals(self):
        FragmentedStreamer._connect_sink_signals(self)
        self.sink.connect("new-fragment", self._new_fragment)

    def _process_fragment(self, fragment):

        if not self._stream_setup:
            sink = self.get_element("sink")
            pad = sink.get_pad("sink")
            caps = pad.get_negotiated_caps()
            name = caps.get_structure(0).get_name()
            self._setup_stream_type(name)

        self._fragmentsCount = self._fragmentsCount + 1

        # Wait hls-min-window fragments to set the component 'happy'
        if self._fragmentsCount == self._minWindow:
            self.info("%d fragments received. Changing mood to 'happy'",
                      self._fragmentsCount)
            self.setMood(moods.happy)
            self._ready = True

        b = fragment.get_property('buffer')
        index = fragment.get_property('index')
        duration = fragment.get_property('duration')

        if index < self._last_index:
            self.warning(
                "Found a discontinuity last index is %s but current "
                "one is %s", self._last_index, index)
            self.soft_restart()

        fragName = self.hlsring.addFragment(
            b.data, index, round(duration / float(gst.SECOND)))
        self.info('Added fragment "%s", index=%s, duration=%s', fragName,
                  index, gst.TIME_ARGS(duration))

    ### START OF THREAD-AWARE CODE (called from non-reactor threads)

    def _new_fragment(self, hlssink):
        self.log("hlsink created a new fragment")
        try:
            fragment = hlssink.get_property('fragment')
        except:
            fragment = hlssink.emit('pull-fragment')
        reactor.callFromThread(self._process_fragment, fragment)