Beispiel #1
0
    def startDownload(self, url, byterange=''):
        '''
        Starts the segment download and set the timestamp of start segment download

        :param url: segment url
        :param byterange: segment byterange (logical segmentation of video level)
        '''
        debug(DEBUG + 1, '%s startDownload %s (byterange %s)', self, url,
              byterange)
        # start download
        if self.use_persistent_connection:
            # start a new connection
            if not self.connection:
                self._initConnection(url)
                return
            if not self.connection.client:
                return
            _, _, path = parse_url(url)
            self.connection.makeRequest(path, byterange)
        else:
            if byterange == '':
                d = getPage(url, agent=USER_AGENT)
            else:
                d = getPage(url,
                            agent=USER_AGENT,
                            headers=dict(range='bytes=' + byterange))
            d.deferred.addCallback(self.playNextGotRequest, d)
            d.deferred.addErrback(self.playNextGotError, d)
        self.start_segment_request = time.time()
Beispiel #2
0
    def startDownload(self, url, byterange=''):
        '''
        Starts the segment download and set the timestamp of start segment download

        :param url: segment url
        :param byterange: segment byterange (logical segmentation of video level)
        '''
        debug(DEBUG+1, '%s startDownload %s (byterange %s)', self, url, byterange)
        # start download
        if self.use_persistent_connection:
            # start a new connection
            if not self.connection:
                self._initConnection(url)
                return
            if not self.connection.client:
                return
            _, _, path = parse_url(url)
            self.connection.makeRequest(path, byterange)
        else:
            if byterange == '':
                d = getPage(url, agent=USER_AGENT)
            else:
                d = getPage(url, agent=USER_AGENT, headers=dict(range='bytes='+byterange))
            d.deferred.addCallback(self.playNextGotRequest, d)
            d.deferred.addErrback(self.playNextGotError, d)
        self.start_segment_request = time.time()
    def updateLevelSegmentsList(self, level):
        '''Updater playlist for current level'''
        playlist = self.playlists[level]
        playlist = self.deletePlaylist(playlist)    #Only for VOD and Live. Not for Live+REC 
        c = defer.Deferred()
        debug(DEBUG-1, '%s updateLevelSegmentsList: %s', self, playlist['url'])
        # page callback
        def got_playlist(data, factory):
            debug(DEBUG+1, 'updateLevelSegmentsList: %s', data)
            cur_index = start_index = 0
	    segment_duration=4
            # FIXME for live streams
            #cur_index = playlist.get('end_index', -1) + 1
            for line in data.split('\n'):
                line = line.strip()
                if not line:
                    continue
                if line.startswith('#EXT-X-TARGETDURATION:'):
                    self.fragment_duration = 4
                    #setIdleDuration(fragment_duration)
                elif line.startswith('#EXTINF:'):
                    line = line.replace('#EXTINF:', '')
                    segment_duration = 4
                elif line.startswith('#EXT-X-MEDIA-SEQUENCE:'):
                    line = line.replace('#EXT-X-MEDIA-SEQUENCE:', '')
                    cur_index = start_index = 1
                elif not line.startswith('#'):
                    try:
                        index = hasGetIndex(line)
                    except Exception:
                        index = cur_index
                        cur_index += 1
                    # first segments, set start_time
                    if len(playlist['segments']) == 0:
                        playlist['start_index'] = index
                        self.start_time = max(self.start_time, index*self.fragment_duration)
                        #playlist['duration'] = self.start_time
                    if index > playlist['end_index']:
                        if not line.startswith('http'):
                            line = os.path.join(os.path.dirname(factory.url), line)
                        _c = dict(url=line,byterange='',dur=segment_duration)
                        playlist['segments'][index] = _c
                        playlist['end_index'] = index
                        playlist['duration'] += segment_duration
                elif line.startswith('#EXT-X-ENDLIST'):
                    duration = playlist['duration']
                    playlist['is_live'] = True
            #print pformat(playlist)
            self.playlists[level] = playlist
            c.callback(1)
        # error handling
        def got_error(e, factory):
            debug(0, '%s updateLevelSegmentsList url: %s error: %s', self, factory.url, e)
            reactor.callLater(self.fragment_duration*0.5, 
                self.updateLevelSegmentsList, level)
        d = getPage(playlist['url'], agent=USER_AGENT)
        d.deferred.addCallback(got_playlist, d)
        d.deferred.addErrback(got_error, d)
        return c
Beispiel #4
0
    def loadPlaylist(self):
        self.levels = []
        self.playlists = []
        self.caps_demuxer = []

        def got_page(data, factory):
            debug(DEBUG, '%s loadHlsPlaylist from %s:\n%s', self, factory.url,
                  data)
            cur = None
            for line in data.split('\n'):
                line = line.strip()
                line = line.replace(", ", ",")
                #print line
                if line.startswith('#EXT-X-STREAM-INF:'):
                    line = line.replace('#EXT-X-STREAM-INF:', '')
                    vr = None
                    res = None
                    for field in line.split(','):
                        if field.startswith('BANDWIDTH='):
                            field = field.replace('BANDWIDTH=', '')
                            vr = int(field) / 8.  #in B/s
                        elif field.startswith('RESOLUTION='):
                            field = field.replace('RESOLUTION=', '')
                            res = field
                    self.levels.append(dict(rate=vr, resolution=res))
                    cur = dict(url='',
                               is_live=False,
                               segments=[],
                               start_index=-1,
                               end_index=-1,
                               duration=0.0)
                    continue
                elif cur:
                    if not line.startswith('http'):
                        line = os.path.join(os.path.dirname(factory.url), line)
                    cur['url'] = line
                    self.playlists.append(cur)
                    cur = None
            #if self.cur_level >= len(self.playlists):
            #    self.cur_level = max(self.cur_level, len(self.playlists)-1)
            deferredList = []
            for i in range(len(self.playlists)):
                deferredList.append(self.updateLevelSegmentsList(i))
            dl = defer.DeferredList(deferredList)

            def _on_done(res):
                self.deferred.callback(True)

            dl.addCallback(_on_done)

        # error handling
        def got_error(e):
            debug(0, '%s loadHlsPlaylist error: %s', self, e)
            self.loadPlaylist()

        #
        d = getPage(self.url, agent=USER_AGENT)
        d.deferred.addCallback(got_page, d)
        d.deferred.addErrback(got_error)
Beispiel #5
0
 def updateLevelSegmentsList(self, level):
     '''Updater playlist for current level'''
     playlist = self.playlists[level]
     playlist = self.deletePlaylist(playlist)    #Only for VOD and Live. Not for Live+REC 
     c = defer.Deferred()
     debug(DEBUG-1, '%s updateLevelSegmentsList: %s', self, playlist['url'])
     # page callback
     def got_playlist(data, factory):
         debug(DEBUG+1, 'updateLevelSegmentsList: %s', data)
         cur_index = start_index = 0
         # FIXME for live streams
         #cur_index = playlist.get('end_index', -1) + 1
         for line in data.split('\n'):
             line = line.strip()
             if not line:
                 continue
             if line.startswith('#EXT-X-TARGETDURATION:'):
                 self.fragment_duration = float(line.replace('#EXT-X-TARGETDURATION:', ''))
                 #setIdleDuration(fragment_duration)
             elif line.startswith('#EXTINF:'):
                 line = line.replace('#EXTINF:', '')
                 segment_duration = float(line.split(',')[0])
             elif line.startswith('#EXT-X-MEDIA-SEQUENCE:'):
                 line = line.replace('#EXT-X-MEDIA-SEQUENCE:', '')
                 cur_index = start_index = int(line)
             elif not line.startswith('#'):
                 try:
                     index = hasGetIndex(line)
                 except Exception:
                     index = cur_index
                     cur_index += 1
                 # first segments, set start_time
                 if len(playlist['segments']) == 0:
                     playlist['start_index'] = index
                     self.start_time = max(self.start_time, index*self.fragment_duration)
                     #playlist['duration'] = self.start_time
                 if index > playlist['end_index']:
                     if not line.startswith('http'):
                         line = os.path.join(os.path.dirname(factory.url), line)
                     _c = dict(url=line,byterange='',dur=segment_duration)
                     playlist['segments'][index] = _c
                     playlist['end_index'] = index
                     playlist['duration'] += segment_duration
             elif line.startswith('#EXT-X-ENDLIST'):
                 duration = playlist['duration']
                 playlist['is_live'] = True
         #print pformat(playlist)
         self.playlists[level] = playlist
         c.callback(1)
     # error handling
     def got_error(e, factory):
         debug(0, '%s updateLevelSegmentsList url: %s error: %s', self, factory.url, e)
         reactor.callLater(self.fragment_duration*0.5, 
             self.updateLevelSegmentsList, level)
     d = getPage(playlist['url'], agent=USER_AGENT)
     d.deferred.addCallback(got_playlist, d)
     d.deferred.addErrback(got_error, d)
     return c
Beispiel #6
0
    def startDownload(self, url, byterange=''):
        '''
        Starts the segment download and set the timestamp of start segment download

        :param url: segment url
        :param byterange: segment byterange (logical segmentation of video level)
        '''
        debug(DEBUG + 1, '%s startDownload %s (byterange %s)', self, url,
              byterange)
        # start download
        if self.use_persistent_connection:
            # start a new connection
            if not self.connection:
                self._initConnection(url)
                return
            if not self.connection.client:
                return

            _, _, path = parse_url(url)
            print("~~~> now requesting new segment")
            self.connection.makeRequest(path, byterange)

        else:
            if byterange == '':
                d = getPage(url, agent=USER_AGENT)
            else:
                d = getPage(url,
                            agent=USER_AGENT,
                            headers=dict(range='bytes=' + byterange))
            d.deferred.addCallback(self.playNextGotRequest, d)
            d.deferred.addErrback(self.playNextGotError, d)
        self.start_segment_request = time.time()
        print colored("in startDownload", 'red')
        print colored("[5] get request performed", 'blue')
        print colored(
            "current buffer: " + str(self.media_engine.getQueuedTime()),
            'yellow')
        print colored(
            '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~...Downloading...~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~',
            'yellow')
Beispiel #7
0
 def loadPlaylist(self):
     self.levels = []
     self.playlists = []
     self.caps_demuxer = []
     def got_page(data, factory):
         debug(DEBUG, '%s loadHlsPlaylist from %s:\n%s', self, factory.url, data)
         cur = None
         for line in data.split('\n'):
             line = line.strip()
             line = line.replace(", ",",");
             #print line
             if line.startswith('#EXT-X-STREAM-INF:'):
                 line = line.replace('#EXT-X-STREAM-INF:', '')
                 vr = None
                 res = None
                 for field in line.split(','):
                     if field.startswith('BANDWIDTH='):
                         field = field.replace('BANDWIDTH=', '')
                         vr = int(field)/8.  #in B/s
                     elif field.startswith('RESOLUTION='):
                         field = field.replace('RESOLUTION=', '')
                         res = field
                 self.levels.append(dict(rate=vr,resolution=res))
                 cur = dict(url='', 
                     is_live=True,
                     segments=[], 
                     start_index=-1, end_index=-1, 
                     duration=0.0)
                 continue
             elif cur:
                 if not line.startswith('http'):
                     line = os.path.join(os.path.dirname(factory.url), line)
                 cur['url'] = line
                 self.playlists.append(cur)
                 cur = None
         #if self.cur_level >= len(self.playlists):
         #    self.cur_level = max(self.cur_level, len(self.playlists)-1)
         deferredList = []
         for i in range(len(self.playlists)):
             deferredList.append(self.updateLevelSegmentsList(i))
         dl = defer.DeferredList(deferredList)
         def _on_done(res):
             self.deferred.callback(True)    
         dl.addCallback(_on_done)
     # error handling
     def got_error(e):
         debug(0, '%s loadHlsPlaylist error: %s', self, e)
     #
     d = getPage(self.url, agent=USER_AGENT)
     d.deferred.addCallback(got_page, d)
     d.deferred.addErrback(got_error)
Beispiel #8
0
    def startDownload(self, url, byterange=''):
        '''
        Starts the segment download and set the timestamp of start segment download

        :param url: segment url
        :param byterange: segment byterange (logical segmentation of video level)
        '''
        debug(DEBUG + 1, '%s startDownload %s (byterange %s)', self, url,
              byterange)
        # start download
        if self.use_persistent_connection:
            # start a new connection
            if not self.connection:
                self._initConnection(url)
                return
            if not self.connection.client:
                return

            _, _, path = parse_url(url)
            segSize = float(float(self.getLastFragmentBytes() * 8)) / 1000
            self.connection.makeRequest(
                path + "?buffer=" + str(self.media_engine.getQueuedTime()) +
                "?bwestim=" + str(self.getBandwidth()) + "?SegmentDur=" +
                str(self.parser.getFragmentDuration()) + "?SegmentSizeLa=" +
                str(segSize) + "?quali=" + str(self.getCurrentRate()) +
                "?pid=" + str(os.getpid()), byterange)

        else:
            if byterange == '':
                d = getPage(url, agent=USER_AGENT)
            else:
                d = getPage(url,
                            agent=USER_AGENT,
                            headers=dict(range='bytes=' + byterange))
            d.deferred.addCallback(self.playNextGotRequest, d)
            d.deferred.addErrback(self.playNextGotError, d)
        print("CURRENT BUFFER IS " + str(self.media_engine.getQueuedTime()))
        self.start_segment_request = time.time()
Beispiel #9
0
    def loadPlaylist(self):
        self.levels         = []
        self.playlists      = []
        self.caps_demuxer   = []
        
        def got_page(data, factory):
            debug(DEBUG, '%s loadHlsPlaylist from %s:\n%s', self, factory.url, data)
            view_flag   = False
            is_live     = False
            urls        = []
            id_level    = 0
            id_view     = 0
            i           = 0
            j           = 0
            playlist    = None
            data        = data.replace("\n\n","")


            for line in data.split('\n'):
                line = line.strip()
                line = line.replace(", ",",")
                url  = None

                #print line
                if line.startswith('#EXT-X-STREAM-INF:'):
                    id_view = 0
                    line    = line.replace('#EXT-X-STREAM-INF:', '')
                    vr      = None
                    res     = None
                    for field in line.split(','):
                        if field.startswith('BANDWIDTH='):
                            field = field.replace('BANDWIDTH=', '')
                            vr = int(field)/8.  #in B/s
                        elif field.startswith('RESOLUTION='):
                            field = field.replace('RESOLUTION=', '')
                            res = field
                    self.levels.append(dict(rate=vr,resolution=res))
                    continue

                    # Case of view playlist
                elif line.startswith('#EXT-X-MEDIA:'):
                    view_flag = True
                    line = line.replace('#EXT-X-STREAM-INF:', '')
                    for field in line.split(','):
                        if field.startswith('URI='):
                            field = str(field.replace('URI=', '')).replace('"','')
                            url = os.path.join(os.path.dirname(factory.url), field)
                            """ elif field.startswith('DEFAULT='):
                            #TODO
                            print "TODO" """
                            cur  = dict(url = url,
                                is_live = is_live,
                                segments    = [], 
                                start_index = -1, 
                                end_index   = -1,
                                type        = "level", 
                                duration    = 0.0, 
                                view        = id_view, 
                                level       = id_level)
                            self.playlists.append(cur)
                            id_view = id_view + 1
                            self.views = max(self.views, id_view)
                            continue

                elif not line.startswith('#'):
                    """ if len(urls) != 0: """
                    if not view_flag:
                        if not line.startswith('http') and line != '':
                            url = os.path.join(os.path.dirname(factory.url), line)
                            cur  = dict(url = url,
                                is_live = is_live,
                                segments    = [], 
                                start_index = -1, 
                                end_index   = -1,
                                type        = "level", 
                                duration    = 0.0, 
                                view        = id_view, 
                                level       = id_level)
                            self.playlists.append(cur)
                            id_level = id_level + 1
                            continue
                        else:
                            id_level = id_level + 1
                            continue
                    else:
                        id_level = id_level + 1
                        continue
                else:
                    continue
                
            #if self.cur_level >= len(self.playlists):
            #    self.cur_level = max(self.cur_level, len(self.playlists)-1)
            deferredList = []
            for i in range(0, len(self.levels)):
                for j in range(0, self.views):
                    print("i: ", i, "j: ", j)
                    deferredList.append(self.updateLevelSegmentsList(i,j))
            dl = defer.DeferredList(deferredList)
            def _on_done(res):
                self.deferred.callback(True)    
            dl.addCallback(_on_done)
        # error handling
        def got_error(e):
            debug(0, '%s loadHlsPlaylist error: %s', self, e)
        #
        d = getPage(self.url, agent=USER_AGENT)
        d.deferred.addCallback(got_page, d)
        d.deferred.addErrback(got_error)
Beispiel #10
0
 def got_playlist(data, factory):
     debug(DEBUG+1, 'updateLevelSegmentsList: %s', data)
     cur_index = start_index = 0
     # FIXME for live streams
     #cur_index = playlist.get('end_index', -1) + 1
     for line in data.split('\n'):
         line = line.strip()
         if not line:
             continue
         
         if line.startswith('#EXT-X-TARGETDURATION:'):
             # FIXME: WRONG INTERPRETATION, THIS LABEL MEANS MAXIMUM SEGMENT DURATION, EQUALS TO THE FOLLOWING IN CBR CASE
             self.fragment_duration = float(line.replace('#EXT-X-TARGETDURATION:', ''))
             #setIdleDuration(fragment_duration)
         
         elif line.startswith('#EXTINF:'):
             line = line.replace('#EXTINF:', '')
             segment_duration = float(line.split(',')[0])
             # FIXME: WRONG INTERPRETATION, THIS LABEL MEANS SEGMENT DURATION, EQUALS TO THE PREVIOUS IN CBR CASE
             self.fragment_duration = segment_duration
             
         elif line.startswith('#EXT-X-MEDIA-SEQUENCE:'):
             line = line.replace('#EXT-X-MEDIA-SEQUENCE:', '')
             cur_index = start_index = int(line)
             
         elif line.startswith('#EXT-X-MAP:'):
             # FIXME: SFOSADHFOGSHGOLHAGLHALG
             line = line.replace('#EXT-X-MAP:', '')
             for field in line.split(','):
                 if field.startswith('URI='):
                     field               = str(field.replace('URI=', '')).replace('"','')
                     url                 = os.path.join(os.path.dirname(factory.url), field)
                     playlist["initURL"] = url
                     #print("initURL PLAYLIST: " + str(playlist))
                     
                     # fetch init segment data
                     d = getPage(url, agent=USER_AGENT)
                     d.deferred.addCallback(got_init, d)
                     d.deferred.addErrback(got_error, d)
                     
         elif not line.startswith('#'):
             try:
                 index       = hasGetIndex(line)
             except Exception:
                 index       = cur_index
                 cur_index   += 1
                 
             # first segments, set start_time
             if len(playlist['segments']) == 0:
                 playlist['start_index'] = index
                 self.start_time = max(self.start_time, index*self.fragment_duration)
                 #playlist['duration'] = self.start_time
             if index > playlist['end_index']:
                 if not line.startswith('http'):
                     line = os.path.join(os.path.dirname(factory.url), line)
                     
                 _c = dict(url = line, byterange = '', dur = segment_duration)
                 playlist['segments'][index] = _c
                 playlist['end_index']       = index
                 playlist['duration']        += segment_duration
         elif line.startswith('#EXT-X-ENDLIST'):
             """
             You can't remove anything from the playlist when using the EVENT tag; 
             you may only append new segments to the end of the file. 
             New segments are added to the end of the file until the event has concluded, 
             at which time the EXT-X-ENDLIST tag is appended. 
             """
             duration = playlist['duration']
             #playlist['is_live'] = True 
             playlist['is_live'] = False
             
     self.playlists.append(playlist)
     #print(">>>>>>>>< PLAYLIST", self.playlists)
     #self.playlists[level] = playlist
     c.callback(1)
Beispiel #11
0
    def updateLevelSegmentsList(self, level, view):
        '''Updater playlist for current level'''
        playlist = self.getSinglePlaylist(level, view)
        self.playlists.remove(playlist)

        playlist = self.createEmptyPlaylist(
            playlist)  #Only for VOD and Live. Not for Live+REC
        c = defer.Deferred()
        debug(DEBUG - 1, '%s updateLevelSegmentsList: %s', self,
              playlist['url'])

        def got_init(data, factory):
            debug(DEBUG + 1, 'updateLevelSegmentsList: %s', data)
            #print str(playlist)
            playlist["initSegment"] = data

        # page callback
        def got_playlist(data, factory):
            debug(DEBUG + 1, 'updateLevelSegmentsList: %s', data)
            cur_index = start_index = 0
            # FIXME for live streams
            #cur_index = playlist.get('end_index', -1) + 1
            for line in data.decode('utf-8').split('\n'):
                line = line.strip()
                if not line:
                    continue

                if line.startswith('#EXT-X-TARGETDURATION:'):
                    # FIXME: THIS LABEL MEANS MAXIMUM SEGMENT DURATION, EQUALS TO THE FOLLOWING IN CBR CASE
                    self.fragment_duration = float(
                        line.replace('#EXT-X-TARGETDURATION:', ''))
                    #setIdleDuration(fragment_duration)

                elif line.startswith('#EXTINF:'):
                    line = line.replace('#EXTINF:', '')
                    segment_duration = float(line.split(',')[0])
                    # FIXME: THIS LABEL MEANS SEGMENT DURATION, EQUALS TO THE PREVIOUS IN CBR CASE
                    self.fragment_duration = segment_duration

                elif line.startswith('#EXT-X-MEDIA-SEQUENCE:'):
                    line = line.replace('#EXT-X-MEDIA-SEQUENCE:', '')
                    cur_index = start_index = int(line)

                elif line.startswith('#EXT-X-MAP:'):
                    # line pointing to init file in fmp4 hls
                    line = line.replace('#EXT-X-MAP:', '')
                    for field in line.split(','):
                        if field.startswith('URI='):
                            # hls mp4
                            self.video_container = 'MP4'

                            field = str(field.replace('URI=',
                                                      '')).replace('"', '')
                            url = os.path.join(
                                os.path.dirname(factory.url.decode('utf-8')),
                                field)
                            playlist["initURL"] = url
                            #print("initURL PLAYLIST: " + str(playlist))

                            # fetch init segment data
                            d = getPage(url, agent=USER_AGENT)
                            d.deferred.addCallback(got_init, d)
                            d.deferred.addErrback(got_error, d)

                elif not line.startswith('#'):
                    try:
                        index = hasGetIndex(line)
                    except Exception:
                        index = cur_index
                        cur_index += 1

                    # first segments, set start_time
                    if len(playlist['segments']) == 0:
                        playlist['start_index'] = index
                        self.start_time = max(self.start_time,
                                              index * self.fragment_duration)
                        #playlist['duration'] = self.start_time
                    if index > playlist['end_index']:
                        if not line.startswith('http'):
                            line = os.path.join(
                                os.path.dirname(factory.url.decode('utf-8')),
                                line)

                        _c = dict(url=line, byterange='', dur=segment_duration)
                        playlist['segments'][index] = _c
                        playlist['end_index'] = index
                        playlist['duration'] += segment_duration
                elif line.startswith('#EXT-X-ENDLIST'):
                    """
                    You can't remove anything from the playlist when using the EVENT tag; 
                    you may only append new segments to the end of the file. 
                    New segments are added to the end of the file until the event has concluded, 
                    at which time the EXT-X-ENDLIST tag is appended. 
                    """
                    duration = playlist['duration']
                    #playlist['is_live'] = True
                    playlist['is_live'] = False

            self.playlists.append(playlist)
            #self.playlists[level] = playlist
            c.callback(1)

        # error handling
        def got_error(e, factory):
            debug(0, '%s updateLevelSegmentsList url: %s error: %s', self,
                  factory.url.decode('utf-8'), e)
            reactor.callLater(self.fragment_duration * 0.5,
                              self.updateLevelSegmentsList, level)

        d = getPage(playlist['url'], agent=USER_AGENT)
        d.deferred.addCallback(got_playlist, d)
        d.deferred.addErrback(got_error, d)
        return c