示例#1
0
 def __init__(self, stream):
     self._stream = RtmpStreamReader(stream)
     self._skip_meta = self._skip_head = self._skip_magic_head = False
     #self._skip_audio_tag = self._skip_video_tag = False
     self._skip_audio_tag = True
     self._skip_video_tag = False
     self._buf = []
     self.onMetaData = None
示例#2
0
 def __init__(self, fn, mode=True):
     stream = file(fn)
     self._fd = os.open(fn, os.O_RDONLY)
     self._reader = RtmpStreamReader(stream)
     self._pre_pos = 0
     self._skip_first_video_tag = False
     self._first_video_tag = None
     self._head = None
     self._keyframes = []
     self._skip_video_tag = False
     self._skip_first_audio_tag = False
     self._first_audio_tag = None
     self._head_dead_line = 0
     super(FlvFragment, self).__init__(mode=mode)
     self._swig = 0
示例#3
0
 def __init__(self, stream):
     self._stream = RtmpStreamReader(stream)
     self._skip_meta = self._skip_head = self._skip_magic_head = False
     #self._skip_audio_tag = self._skip_video_tag = False
     self._skip_audio_tag = True
     self._skip_video_tag = False
     self._buf = []
     self.onMetaData = None
示例#4
0
    def __init__(self, data_in=None, step_length=1, channel=None, start_chunk_id='-0x1', delay_seconds = 0, enable_backswing=0):
        """
        @data_in: Data source.
        @step_length: The max length of time slices can play.
        @channel: The name of the data source.
        @start_chunk_id: Number of the starting chunk, starting from the current time by default.
        """
        if not channel:
            raise FragmentError('Channenl is required.')
        self._channel = channel
        if not data_in:
            data_in = sys.stdin
        elif data_in.startswith("rtmp://"):
            import librtmp
            conn = librtmp.RTMP(data_in, live=True)
            # Attempt to connect
            conn.connect()
            # Get a file-like object to access to the stream
            stream = conn.create_stream()
            # Read 1024 bytes of data
            data_in = stream

        self._buf = [] #store tag temporary.
        self._id_generator = id_generator(int(start_chunk_id, 16))

        self._stream = RtmpStreamReader(data_in) #data source reader.
        self._step_length = step_length

        self.delay_seconds = delay_seconds

        self._seq = 0 #sequence number of tag.
        self._chunk_seq = 0 #sequence number of chunk.
        self._skip_meta = self._skip_head = self._skip_magic_head = False
        self._flv_head_no = 0

        self._swing = 0 # swing
        self._head  = None
        
        self._skip_audio_tag = self._skip_video_tag = False
        self._enable_backswing = enable_backswing

        self._do_sleep = False

        self._has_head = False
        self._meta_tag = None
示例#5
0
 def __init__(self, fn, mode=True):
     stream = file(fn)
     self._fd = os.open(fn, os.O_RDONLY)
     self._reader = RtmpStreamReader(stream)
     self._pre_pos = 0
     self._skip_first_video_tag = False 
     self._first_video_tag = None
     self._head = None 
     self._keyframes = []
     self._skip_video_tag = False
     self._skip_first_audio_tag = False 
     self._first_audio_tag = None
     self._head_dead_line = 0
     super(FlvFragment, self).__init__(mode=mode)
     self._swig = 0
示例#6
0
class VodFragment(object):

    def __init__(self, stream):
        self._stream = RtmpStreamReader(stream)
        self._skip_meta = self._skip_head = self._skip_magic_head = False
        #self._skip_audio_tag = self._skip_video_tag = False
        self._skip_audio_tag = True
        self._skip_video_tag = False
        self._buf = []
        self.onMetaData = None

    def handle_magic_head(self, tag):
        """
        Catch the first audio tag and video tag in the stream.
        """
        if not self._skip_video_tag and tag.type == VIDEO_TAG:
            self._first_video_tag = tag
            self._skip_video_tag = True
        if not self._skip_audio_tag and tag.type == AUDIO_TAG:
            self._first_audio_tag = tag
            self._skip_audio_tag = True
        return (not(self._skip_audio_tag and self._skip_video_tag))
        #return (not(self._skip_audio_tag or self._skip_video_tag))
    
    def slice_head(self):
        for tag in self._stream:
            last_position = self._stream.position()
            self._buf.append(tag)
            if isinstance(tag, Tag):
                if tag.type == 18 and self.onMetaData:
                    self.onMetaData(tag)
                if not self.handle_magic_head(tag):
                    return last_position
        return last_position

    def flush(self):
        buf = ''
        for tag in self._buf:
            if isinstance(tag, Head):
                buf += pack_head(tag)
            else:
                buf += tag.pack()
        return buf
示例#7
0
class VodFragment(object):
    def __init__(self, stream):
        self._stream = RtmpStreamReader(stream)
        self._skip_meta = self._skip_head = self._skip_magic_head = False
        #self._skip_audio_tag = self._skip_video_tag = False
        self._skip_audio_tag = True
        self._skip_video_tag = False
        self._buf = []
        self.onMetaData = None

    def handle_magic_head(self, tag):
        """
        Catch the first audio tag and video tag in the stream.
        """
        if not self._skip_video_tag and tag.type == VIDEO_TAG:
            self._first_video_tag = tag
            self._skip_video_tag = True
        if not self._skip_audio_tag and tag.type == AUDIO_TAG:
            self._first_audio_tag = tag
            self._skip_audio_tag = True
        return (not (self._skip_audio_tag and self._skip_video_tag))
        #return (not(self._skip_audio_tag or self._skip_video_tag))

    def slice_head(self):
        for tag in self._stream:
            last_position = self._stream.position()
            self._buf.append(tag)
            if isinstance(tag, Tag):
                if tag.type == 18 and self.onMetaData:
                    self.onMetaData(tag)
                if not self.handle_magic_head(tag):
                    return last_position
        return last_position

    def flush(self):
        buf = ''
        for tag in self._buf:
            if isinstance(tag, Head):
                buf += pack_head(tag)
            else:
                buf += tag.pack()
        return buf
示例#8
0
class FlvFragment(Fragment):
    def __init__(self, fn, mode=True):
        stream = file(fn)
        self._fd = os.open(fn, os.O_RDONLY)
        self._reader = RtmpStreamReader(stream)
        self._pre_pos = 0
        self._skip_first_video_tag = False
        self._first_video_tag = None
        self._head = None
        self._keyframes = []
        self._skip_video_tag = False
        self._skip_first_audio_tag = False
        self._first_audio_tag = None
        self._head_dead_line = 0
        super(FlvFragment, self).__init__(mode=mode)
        self._swig = 0

    def position(self):
        return self._reader.position()

    def get_keyframes(self):
        return self._keyframes

    keyframes = property(get_keyframes)

    def size(self):
        return len(self._keyframes)

    def append_keyframe(self, tag):
        self._keyframes.append((self._pre_pos, tag.timestamp))
        self._ptr = len(self._keyframes) - 1
        self._swig = 0  #init loop

    def incr(self, step):
        if self.pointer == self.size() - 1:
            self._ptr += 1
            self._swig = 0
        else:
            self._swig += step
            span = self.span()
            print 'cacle %d' % (span, )
            if self._swig > span:
                self._ptr += 1
                print "increase ptr %d" % self._ptr
                self._swig -= span

    def span(self):
        if self.pointer >= self.size() - 1:
            return 0
        p = self.pointer
        a = self._keyframes[p][1]
        b = self._keyframes[p + 1][1]
        return ((b - a) / 1000)

    def advance(self):
        """
        Get a slice of CPU time to run.
        """
        in_bytes = self._pre_pos
        for tag in self._reader:
            if isinstance(tag, Tag):
                # skip the Metadata in flv stream.
                if not self.handle_magic_head(tag):
                    if tag.type == VIDEO_TAG and tag.is_keyframe:
                        self.append_keyframe(tag)
                self._pre_pos = self.position()
        in_bytes = self._pre_pos - in_bytes
        if in_bytes > 0:
            self.active()
        else:
            self.inactive()

    def handle_magic_head(self, tag):
        """
        Catch the first audio tag and video tag in the stream.
        """
        if not self._skip_video_tag and tag.type == VIDEO_TAG:
            self._first_video_tag = tag
            self._head_dead_line = self.position()
            self._skip_video_tag = True
        if not self._skip_first_audio_tag and tag.type == AUDIO_TAG:
            self._first_audio_tag = tag
            self._head_dead_line = self.position()
            self._skip_first_audio_tag = True
        return (not (self._skip_video_tag and self._skip_first_audio_tag))

    def do(self, start=-1, offset=None, flag=False, keyIndex=None):
        begin = end = 0
        current = keyIndex and keyIndex or self.pointer
        if start < 0:  #从关键帧开始取数据
            begin = self._keyframes[current][0]
        else:
            begin = start
        end = offset and min(begin + offset,
                             self.position()) or self.position()
        data_length = end - begin
        data = ''
        if data_length > 0:
            os.lseek(self._fd, begin, os.SEEK_SET)
            data = os.read(self._fd, data_length)
        else:
            raise OSError("Reach file end.")

        body = ''
        if flag:
            if not self._head and self._head_dead_line:
                os.lseek(self._fd, 0, os.SEEK_SET)
                self._head = os.read(self._fd, self._head_dead_line)
            body += struct.pack('>H%ds' % (len(self._head), ), len(self._head),
                                self._head)
        else:
            body += struct.pack('>H', 0)
        body += struct.pack('>QIH', begin, data_length,
                            config.NEXT_REQ_DELAY_TIME)
        #filepositions
        temp = ''
        for (k, t) in self._keyframes:
            if k >= begin:
                temp += struct.pack('>QI', k, t)
            if k > end:
                break
        body += struct.pack('>I', len(temp) / 12) + temp
        # insert head length
        body = struct.pack('>I', len(body)) + body + data
        return body

    def close(self):
        os.close(self._fd)
        self._reader.close()
示例#9
0
class Fragment(object):
    """
    Slice flv data stream into pieces.
    """

    def __init__(self, data_in=None, step_length=1, channel=None, start_chunk_id='-0x1', delay_seconds = 0, enable_backswing=0):
        """
        @data_in: Data source.
        @step_length: The max length of time slices can play.
        @channel: The name of the data source.
        @start_chunk_id: Number of the starting chunk, starting from the current time by default.
        """
        if not channel:
            raise FragmentError('Channenl is required.')
        self._channel = channel
        if not data_in:
            data_in = sys.stdin
        elif data_in.startswith("rtmp://"):
            import librtmp
            conn = librtmp.RTMP(data_in, live=True)
            # Attempt to connect
            conn.connect()
            # Get a file-like object to access to the stream
            stream = conn.create_stream()
            # Read 1024 bytes of data
            data_in = stream

        self._buf = [] #store tag temporary.
        self._id_generator = id_generator(int(start_chunk_id, 16))

        self._stream = RtmpStreamReader(data_in) #data source reader.
        self._step_length = step_length

        self.delay_seconds = delay_seconds

        self._seq = 0 #sequence number of tag.
        self._chunk_seq = 0 #sequence number of chunk.
        self._skip_meta = self._skip_head = self._skip_magic_head = False
        self._flv_head_no = 0

        self._swing = 0 # swing
        self._head  = None
        
        self._skip_audio_tag = self._skip_video_tag = False
        self._enable_backswing = enable_backswing

        self._do_sleep = False

        self._has_head = False
        self._meta_tag = None

    def get_sleep_mode(self):
        return self._do_sleep

    def set_sleep_mode(self, value):
        self._do_sleep = value

    sleep_mode = property(get_sleep_mode, set_sleep_mode)

    def get_enable_backswing(self):
        return self._enable_backswing
        
    def set_enable_backswing(self, value):
        self._enable_backswing = value

    enable_backswing = property(get_enable_backswing, set_enable_backswing)

    def get_channel(self):
        """
        Return the channel name.
        """
        return self._channel

    channel = property(get_channel)

    def get_auto_step_length(self):
        """
        Return the step length in 微秒.
        """
        return (self._step_length * 1000) + self.backswing

    auto_step_length = property(get_auto_step_length)

    def get_backswing(self):
        """
        反向摆动值.
        """
        return (self._swing * (-1))
    
    backswing = property(get_backswing)

    def get_length_of_play_time(self):
        """
        Caculate the length of play time avilable in temporary cache.
        """
        if len(self._buf) > 1:
            return self._buf[-1].timestamp - self._buf[0].timestamp
        return 0

    length_of_play_time = property(get_length_of_play_time)

    def get_stream_time(self):
        """
        Get the time of play stream.
        """
        return self._start_time + (self._chunk_seq * self._step_length)

    stream_time = property(get_stream_time)

    def measure(self):
        """
        Determine whether chunk generated at this time. If does, call method cut.
        """
        if self.length_of_play_time > self.auto_step_length:
            self._cut()

    def _cut(self):
        """
        Do generate a chunk from the temporary cache array. And then, clear the cache.
        """
        now = time.time() # Get time of now in seconds.
        chunk_id = self._id_generator() #Generate a number of chunk from the growth.
        self._chunk_seq += 1 #Increase the number of chunk sequence.
        self.on_chunk_generated(chunk_id, self._buf)
        self._clear()
        if self.enable_backswing:
            self._swing = now - self.stream_time #Compute the value of deference between the current time and the stream time.

    def _clear(self):
        """
        Clear the temporary cache.
        """
        self._buf = []

    def handle_magic_head(self, tag):
        """
        Catch the first audio tag and video tag in the stream.
        """
        #print("skip_audio_tag:%s  skip_video_tab:%s" % (self._skip_audio_tag, self._skip_video_tag))
        if self._has_head:
            return False

            
        if not self._skip_video_tag and tag.type == VIDEO_TAG:
            self._first_video_tag = tag
            self._skip_video_tag = True
            
        if not self._skip_audio_tag and tag.type == AUDIO_TAG:
            self._first_audio_tag = tag
            self._skip_audio_tag = True

        #return (not(self._skip_audio_tag or self._skip_video_tag))

        if self._head.audio_flag == 0:
            if self._skip_video_tag:
                self._has_head = True
                return False
        else:
            if self._skip_audio_tag and self._skip_video_tag:
                self._has_head = True
                return False
        return True

    def advance(self):
        """
        Get a slice of CPU time to run.
        """
        self._start_time = time.time() #Start time in seconds.
        
        if not self._skip_head: #First read from stream.
            try:
                tag = self._stream.next()
                if not isinstance(tag, Head):
                    raise FragmentError('Flv stream head not found!')
                self._head = tag
                self._skip_head = True
            except StopIteration:
                return
         
        for tag in self._stream:
            self._seq += 1 # Increase the number of Tag sequence.
            if isinstance(tag, Tag):
                # skip the Metadata in flv stream.
                if tag.type == META_DATA:
                    self._meta_tag = tag
                    #print(tag) <Tag(type:meta data,size:121,ext:0,ts:0)>  121 + 11 = 132
                    continue
                if not self.handle_magic_head(tag):
                    self._buf.append(tag)
                    self.measure() # Judge slice chunk.
            else: #todo: May be ingored
                raise FragmentError('Receive another flv head from stream!')
            if self._do_sleep: time.sleep(0.01)

    def on_chunk_generated(self, chunk_id, tag_array):
        """
        Implemented by subclass.
        """
        raise NotImplementedError('on_chunk_generated')
示例#10
0
class FlvFragment(Fragment):
    def __init__(self, fn, mode=True):
        stream = file(fn)
        self._fd = os.open(fn, os.O_RDONLY)
        self._reader = RtmpStreamReader(stream)
        self._pre_pos = 0
        self._skip_first_video_tag = False 
        self._first_video_tag = None
        self._head = None 
        self._keyframes = []
        self._skip_video_tag = False
        self._skip_first_audio_tag = False 
        self._first_audio_tag = None
        self._head_dead_line = 0
        super(FlvFragment, self).__init__(mode=mode)
        self._swig = 0
    def position(self):
        return self._reader.position()
    def get_keyframes(self):
        return self._keyframes
    keyframes = property(get_keyframes)
    def size(self):
        return len(self._keyframes)
    def append_keyframe(self, tag):
        self._keyframes.append((self._pre_pos, tag.timestamp))
        self._ptr = len(self._keyframes) - 1
        self._swig = 0 #init loop
    def incr(self, step):
        if self.pointer == self.size() - 1:
            self._ptr += 1
            self._swig = 0
        else:
            self._swig += step
            span = self.span()
            print 'cacle %d' % (span,)
            if self._swig > span:
                self._ptr += 1 
                print "increase ptr %d" % self._ptr
                self._swig -= span
    def span(self):
        if self.pointer >= self.size() - 1:
            return 0
        p = self.pointer
        a = self._keyframes[p][1]
        b = self._keyframes[p+1][1]
        return ((b - a)/1000)
        
    def advance(self):
        """
        Get a slice of CPU time to run.
        """
        in_bytes = self._pre_pos
        for tag in self._reader:
            if isinstance(tag, Tag):
                # skip the Metadata in flv stream.
                if not self.handle_magic_head(tag):
                    if tag.type == VIDEO_TAG and tag.is_keyframe:
                        self.append_keyframe(tag)
                self._pre_pos = self.position()
        in_bytes = self._pre_pos - in_bytes
        if in_bytes > 0:
            self.active()
        else:
            self.inactive()
    def handle_magic_head(self, tag):
        """
        Catch the first audio tag and video tag in the stream.
        """
        if not self._skip_video_tag and tag.type == VIDEO_TAG:
            self._first_video_tag = tag
            self._head_dead_line = self.position()
            self._skip_video_tag = True
        if not self._skip_first_audio_tag and tag.type == AUDIO_TAG:
            self._first_audio_tag = tag
            self._head_dead_line = self.position()
            self._skip_first_audio_tag = True
        return (not(self._skip_video_tag and self._skip_first_audio_tag))

    def do(self, start=-1, offset=None, flag=False, keyIndex=None):
        begin = end = 0
        current = keyIndex and keyIndex or self.pointer
        if start < 0: #从关键帧开始取数据
            begin = self._keyframes[current][0]
        else:
            begin = start
        end = offset and min(begin + offset, self.position()) or self.position()
        data_length = end - begin
        data = ''
        if data_length > 0:
            os.lseek(self._fd, begin, os.SEEK_SET)
            data = os.read(self._fd, data_length)
        else:
            raise OSError("Reach file end.")

        body = ''
        if flag:
            if not self._head and self._head_dead_line:
                os.lseek(self._fd, 0, os.SEEK_SET)
                self._head = os.read(self._fd, self._head_dead_line)
            body += struct.pack('>H%ds'%(len(self._head),), len(self._head), self._head)
        else:
            body += struct.pack('>H', 0)
        body += struct.pack('>QIH', begin, data_length, config.NEXT_REQ_DELAY_TIME)
        #filepositions
        temp = ''
        for (k,t) in self._keyframes:
            if k >= begin:
                temp += struct.pack('>QI', k, t)
            if k > end:
                break
        body += struct.pack('>I', len(temp)/12) + temp
        # insert head length
        body = struct.pack('>I', len(body)) + body + data
        return body

    def close(self):
        os.close(self._fd)
        self._reader.close()