Beispiel #1
0
    def sendData(self, data, timestamp):
        c = self.channel

        if timestamp < c.timestamp:
            relTimestamp = timestamp
        else:
            relTimestamp = timestamp - c.timestamp

        h = header.Header(c.channelId, relTimestamp, self.type, len(data), self.streamId)

        if self._lastHeader is None:
            h.full = True

        c.setHeader(h)
        c.append(data)

        header.encode(self.stream, h, self._lastHeader)
        self._lastHeader = h

        c.marshallOneFrame()

        while not c.complete():
            self.stream.write(self._continuationHeader)
            c.marshallOneFrame()

        c.reset()
        s = self.stream.getvalue()
        self.output.write(s)
        self.encoder.bytes += len(s)

        self.stream.consume()
Beispiel #2
0
    def __init__(self, encoder, streamId, output):
        self.encoder = encoder

        self.channel = self.encoder.acquireChannel()

        if self.channel is None:
            # todo: make this better
            raise RuntimeError('No streaming channel available')


        self.type = None
        self.streamId = streamId
        self.output = output
        self.stream = BufferedByteStream()

        self._lastHeader = None
        self._oldStream = self.channel.stream
        self.channel.stream = self.stream

        h = header.Header(self.channel.channelId)

        # encode a continuation header for speed
        header.encode(self.stream, h, h)

        self._continuationHeader = self.stream.getvalue()
        self.stream.consume()
Beispiel #3
0
    def test_simple(self):
        """
        Do a sanity check for a simple 4 frame 1 channel rtmp stream.
        """
        def check_meta(meta, timestamp=10):
            self.assertEqual(meta.channelId, 3)
            self.assertEqual(meta.streamId, 1)
            self.assertEqual(meta.datatype, 2)
            self.assertEqual(meta.bodyLength, 500)
            self.assertEqual(meta.timestamp, timestamp)

        size = self.reader.frameSize

        full = header.Header(3,
                             datatype=2,
                             bodyLength=500,
                             streamId=1,
                             timestamp=10)

        header.encode(self.stream, full)
        self.stream.write('a' * size)

        header.encode(self.stream, full, full)
        self.stream.write('b' * size)

        header.encode(self.stream, full, full)
        self.stream.write('c' * size)

        header.encode(self.stream, full, full)
        self.stream.write('d' * (size - 12))

        self.stream.seek(0)
        bytes, complete, meta = self.reader.readFrame()

        self.assertEqual(bytes, 'a' * self.reader.frameSize)
        self.assertFalse(complete)
        check_meta(meta)

        bytes, complete, meta = self.reader.readFrame()

        self.assertEqual(bytes, 'b' * self.reader.frameSize)
        self.assertFalse(complete)
        check_meta(meta, 10)

        bytes, complete, meta = self.reader.readFrame()

        self.assertEqual(bytes, 'c' * self.reader.frameSize)
        self.assertFalse(complete)
        check_meta(meta, 10)

        bytes, complete, meta = self.reader.readFrame()

        self.assertEqual(bytes, 'd' * (size - 12))
        self.assertTrue(complete)
        check_meta(meta, 10)

        self.assertRaises(IOError, self.reader.readFrame)
Beispiel #4
0
    def send(self, data, datatype, streamId, timestamp, whenDone=None):
        """
        Queues an RTMP message to be encoded. Call C{next} to do the encoding.

        @param data: The raw data that will be marshalled into RTMP frames and
            sent to the peer.
        @type data: C{str}
        @param datatype: The type of data. See C{message} for a list of known
            RTMP types.
        @type datatype: C{int}
        @param streamId: The C{NetStream} id that this message is intended for.
        @type streamId: C{int}
        @param timestamp: The current timestamp for the stream that this message
            was sent.
        @type timestamp: C{int}
        """
        if is_command_type(datatype):
            # we have to special case command types because a channel only be
            # busy with one message at a time. Command messages are always
            # written right away
            channel = self.getChannel(COMMAND_CHANNEL_ID)
        else:
            channel = self.acquireChannel()

            if not channel:
                self.pending.append((data, datatype, streamId, timestamp, whenDone))

                return

        h = header.Header(
            channel.channelId,
            timestamp - channel.timestamp,
            datatype,
            len(data),
            streamId)

        if whenDone is not None:
            channel.setCallback(whenDone)

        channel.append(data)
        self.nextHeaders[channel] = h

        if channel.channelId == COMMAND_CHANNEL_ID:
            while not self._encodeOneFrame(channel):
                pass

            channel.reset()
            self.flush()

            return

        self.activeChannels[channel] = channel.channelId
Beispiel #5
0
    def test_repr(self):
        h = header.Header(3)

        self.assertEquals(
            repr(h), '<rtmpy.protocol.rtmp.header.Header '
            'streamId=None datatype=None timestamp=None bodyLength=None '
            'channelId=3 full=False continuation=False at 0x%x>' % (id(h), ))

        d = {
            'channelId': 1,
            'timestamp': 50,
            'datatype': 20,
            'bodyLength': 2000,
            'streamId': 98,
        }

        h = header.Header(**d)

        self.assertEquals(
            repr(h), '<rtmpy.protocol.rtmp.header.Header '
            'streamId=98 datatype=20 timestamp=50 bodyLength=2000 channelId=1 '
            'full=False continuation=False at 0x%x>' % (id(h), ))
Beispiel #6
0
    def test_kwargs(self):
        d = {
            'channelId': 1,
            'timestamp': 50,
            'datatype': 20,
            'bodyLength': 2000,
            'streamId': 98,
        }

        h = header.Header(**d)

        for k, v in d.items():
            self.assertEqual(getattr(h, k), v)
Beispiel #7
0
    def test_init(self):
        h = header.Header(3)

        expected_attrs = {
            'channelId': 3,
            'timestamp': -1,
            'datatype': -1,
            'bodyLength': -1,
            'streamId': -1
        }

        for k, v in expected_attrs.items():
            self.assertEqual(getattr(h, k), v)
Beispiel #8
0
    def test_reassign(self):
        """
        Ensure that when a channel is complete it can be repurposed via a relative
        header.
        """
        full_header = header.Header(52,
                                    datatype=2,
                                    timestamp=55,
                                    bodyLength=256,
                                    streamId=4)

        # only change the bodyLength and timestamp
        relative_header = header.Header(52,
                                        datatype=2,
                                        streamId=4,
                                        bodyLength=256,
                                        timestamp=45)

        header.encode(self.stream, full_header)
        self.stream.write('a' * self.reader.frameSize)
        header.encode(self.stream, relative_header, full_header)
        self.stream.write('b' * self.reader.frameSize)

        self.stream.seek(0)

        bytes, complete, meta = self.reader.readFrame()

        self.assertEqual(bytes, 'a' * 128)
        self.assertFalse(complete)
        self.assertEqual(meta.timestamp, 55)

        bytes, complete, meta = self.reader.readFrame()

        self.assertEqual(bytes, 'b' * 128)
        self.assertTrue(complete)
        self.assertEqual(meta.timestamp, 100)
Beispiel #9
0
    def test_reset(self):
        full = header.Header(3,
                             datatype=2,
                             bodyLength=2,
                             streamId=1,
                             timestamp=10)

        header.encode(self.stream, full)
        self.stream.write('a' * 2)

        self.stream.seek(0)

        self.reader.readFrame()
        channel = self.channels[3]

        self.assertEqual(channel.bytes, 0)
Beispiel #10
0
 def reset(self):
     self.old = header.Header(0, 3, 4, 5, 6)
     self.new = header.Header(0, 3, 4, 5, 6)
Beispiel #11
0
 def setUp(self):
     self.absolute = header.Header(3,
                                   timestamp=1000,
                                   bodyLength=2000,
                                   datatype=3,
                                   streamId=243)