示例#1
0
 def test_with_csrc_truncated(self):
     data = load("rtp_with_csrc.bin")
     for length in range(12, 20):
         with self.assertRaises(ValueError) as cm:
             RtpPacket.parse(data[0:length])
         self.assertEqual(str(cm.exception),
                          "RTP packet has truncated CSRC")
    def test_rtp_rtx(self):
        receiver = RTCRtpReceiver('video', self.local_transport)
        self.assertEqual(receiver.transport, self.local_transport)

        receiver._track = RemoteStreamTrack(kind='video')
        run(
            receiver.receive(
                RTCRtpReceiveParameters(
                    codecs=[
                        VP8_CODEC,
                        RTCRtpCodecParameters(mimeType='video/rtx',
                                              clockRate=90000,
                                              payloadType=101,
                                              parameters={'apt': 100}),
                    ],
                    encodings=[
                        RTCRtpEncodingParameters(
                            ssrc=1234,
                            payloadType=100,
                            rtx=RTCRtpRtxParameters(ssrc=2345))
                    ])))

        # receive RTX with payload
        packet = RtpPacket(payload_type=101, ssrc=2345, payload=b'\x00\x00')
        run(receiver._handle_rtp_packet(packet, arrival_time_ms=0))

        # receive RTX without payload
        packet = RtpPacket(payload_type=101, ssrc=2345)
        run(receiver._handle_rtp_packet(packet, arrival_time_ms=0))

        # shutdown
        run(receiver.stop())
示例#3
0
    async def test_rtp_rtx(self):
        async with create_receiver("video") as receiver:
            receiver._track = RemoteStreamTrack(kind="video")

            await receiver.receive(
                RTCRtpReceiveParameters(
                    codecs=[
                        VP8_CODEC,
                        RTCRtpCodecParameters(
                            mimeType="video/rtx",
                            clockRate=90000,
                            payloadType=101,
                            parameters={"apt": 100},
                        ),
                    ],
                    encodings=[
                        RTCRtpEncodingParameters(
                            ssrc=1234,
                            payloadType=100,
                            rtx=RTCRtpRtxParameters(ssrc=2345),
                        )
                    ],
                )
            )

            # receive RTX with payload
            packet = RtpPacket(payload_type=101, ssrc=2345, payload=b"\x00\x00")
            await receiver._handle_rtp_packet(packet, arrival_time_ms=0)

            # receive RTX without payload
            packet = RtpPacket(payload_type=101, ssrc=2345)
            await receiver._handle_rtp_packet(packet, arrival_time_ms=0)
示例#4
0
    def test_add_ordered(self):
        jbuffer = JitterBuffer(capacity=4)

        pli_flag, frame = jbuffer.add(
            RtpPacket(sequence_number=0, timestamp=1234))
        self.assertIsNone(frame)
        self.assertPackets(jbuffer, [0, None, None, None])
        self.assertEqual(jbuffer._origin, 0)
        self.assertFalse(pli_flag)

        pli_flag, frame = jbuffer.add(
            RtpPacket(sequence_number=1, timestamp=1234))
        self.assertIsNone(frame)
        self.assertPackets(jbuffer, [0, 1, None, None])
        self.assertEqual(jbuffer._origin, 0)
        self.assertFalse(pli_flag)

        pli_flag, frame = jbuffer.add(
            RtpPacket(sequence_number=2, timestamp=1234))
        self.assertIsNone(frame)
        self.assertPackets(jbuffer, [0, 1, 2, None])
        self.assertEqual(jbuffer._origin, 0)
        self.assertFalse(pli_flag)

        pli_flag, frame = jbuffer.add(
            RtpPacket(sequence_number=3, timestamp=1234))
        self.assertIsNone(frame)
        self.assertPackets(jbuffer, [0, 1, 2, 3])
        self.assertEqual(jbuffer._origin, 0)
        self.assertFalse(pli_flag)
示例#5
0
    def test_add_seq_too_high_reset(self):
        jbuffer = JitterBuffer(capacity=4)

        jbuffer.add(RtpPacket(sequence_number=0, timestamp=1234))
        self.assertEqual(jbuffer._origin, 0)
        self.assertPackets(jbuffer, [0, None, None, None])

        jbuffer.add(RtpPacket(sequence_number=3000, timestamp=1234))
        self.assertEqual(jbuffer._origin, 3000)
        self.assertPackets(jbuffer, [3000, None, None, None])
示例#6
0
    def test_add_seq_too_low_reset(self):
        jbuffer = JitterBuffer(capacity=4)

        frame = jbuffer.add(RtpPacket(sequence_number=2000, timestamp=1234))
        self.assertIsNone(frame)
        self.assertPackets(jbuffer, [2000, None, None, None])
        self.assertEqual(jbuffer._origin, 2000)

        frame = jbuffer.add(RtpPacket(sequence_number=1, timestamp=1234))
        self.assertIsNone(frame)
        self.assertPackets(jbuffer, [None, 1, None, None])
        self.assertEqual(jbuffer._origin, 1)
示例#7
0
    def test_with_sdes_mid_truncated(self):
        data = load('rtp_with_sdes_mid.bin')

        for length in range(12, 16):
            with self.assertRaises(ValueError) as cm:
                RtpPacket.parse(data[0:length])
            self.assertEqual(str(cm.exception),
                             'RTP packet has truncated extension profile / length')

        for length in range(16, 20):
            with self.assertRaises(ValueError) as cm:
                RtpPacket.parse(data[0:length])
            self.assertEqual(str(cm.exception), 'RTP packet has truncated extension value')
示例#8
0
    def test_smart_remove(self):
        jbuffer = JitterBuffer(capacity=4)

        jbuffer.add(RtpPacket(sequence_number=0, timestamp=1234))
        jbuffer.add(RtpPacket(sequence_number=1, timestamp=1234))
        jbuffer.add(RtpPacket(sequence_number=3, timestamp=1235))
        self.assertEqual(jbuffer._origin, 0)
        self.assertPackets(jbuffer, [0, 1, None, 3])

        # remove 1 packet
        jbuffer.smart_remove(1)
        self.assertEqual(jbuffer._origin, 3)
        self.assertPackets(jbuffer, [None, None, None, 3])
示例#9
0
    def test_get_header_extensions(self):
        packet = RtpPacket()

        # none
        self.assertEqual(get_header_extensions(packet), [])

        # one-byte, single value
        packet.extension_profile = 0xBEDE
        packet.extension_value = b'\x900\x00\x00'
        self.assertEqual(get_header_extensions(packet), [
            (9, b'0'),
        ])

        # one-byte, two values
        packet.extension_profile = 0xBEDE
        packet.extension_value = b'\x10\xc18sdparta_0'
        self.assertEqual(get_header_extensions(packet), [
            (1, b'\xc1'),
            (3, b'sdparta_0'),
        ])

        # two-byte, single value
        packet.extension_profile = 0x1000
        packet.extension_value = b'\xff\x010\x00'
        self.assertEqual(get_header_extensions(packet), [
            (255, b'0'),
        ])
示例#10
0
    def test_add_seq_too_low_drop(self):
        jbuffer = JitterBuffer(capacity=4)

        pli_flag, frame = jbuffer.add(
            RtpPacket(sequence_number=2, timestamp=1234))
        self.assertIsNone(frame)
        self.assertPackets(jbuffer, [None, None, 2, None])
        self.assertEqual(jbuffer._origin, 2)
        self.assertFalse(pli_flag)

        pli_flag, frame = jbuffer.add(
            RtpPacket(sequence_number=1, timestamp=1234))
        self.assertIsNone(frame)
        self.assertPackets(jbuffer, [None, None, 2, None])
        self.assertEqual(jbuffer._origin, 2)
        self.assertFalse(pli_flag)
示例#11
0
    def test_add_seq_too_high_discard_four(self):
        jbuffer = JitterBuffer(capacity=4)

        jbuffer.add(RtpPacket(sequence_number=0, timestamp=1234))
        self.assertEqual(jbuffer._origin, 0)

        jbuffer.add(RtpPacket(sequence_number=1, timestamp=1234))
        self.assertEqual(jbuffer._origin, 0)

        jbuffer.add(RtpPacket(sequence_number=3, timestamp=1234))
        self.assertEqual(jbuffer._origin, 0)

        jbuffer.add(RtpPacket(sequence_number=7, timestamp=1235))
        self.assertEqual(jbuffer._origin, 7)

        self.assertPackets(jbuffer, [None, None, None, 7])
示例#12
0
    def test_add_seq_too_high_discard_one_v2(self):
        jbuffer = JitterBuffer(capacity=4)

        jbuffer.add(RtpPacket(sequence_number=0, timestamp=1234))
        self.assertEqual(jbuffer._origin, 0)

        jbuffer.add(RtpPacket(sequence_number=2, timestamp=1234))
        self.assertEqual(jbuffer._origin, 0)

        jbuffer.add(RtpPacket(sequence_number=3, timestamp=1235))
        self.assertEqual(jbuffer._origin, 0)

        jbuffer.add(RtpPacket(sequence_number=4, timestamp=1235))
        self.assertEqual(jbuffer._origin, 3)

        self.assertPackets(jbuffer, [4, None, None, 3])
示例#13
0
    def test_rtp_rtx_unknown_ssrc(self):
        receiver = RTCRtpReceiver("video", self.local_transport)
        self.assertEqual(receiver.transport, self.local_transport)

        receiver._track = RemoteStreamTrack(kind="video")
        run(
            receiver.receive(
                RTCRtpReceiveParameters(
                    codecs=[
                        VP8_CODEC,
                        RTCRtpCodecParameters(
                            mimeType="video/rtx",
                            clockRate=90000,
                            payloadType=101,
                            parameters={"apt": 100},
                        ),
                    ]
                )
            )
        )

        # receive RTX with unknown SSRC
        packet = RtpPacket(payload_type=101, ssrc=1234)
        run(receiver._handle_rtp_packet(packet, arrival_time_ms=0))

        # shutdown
        run(receiver.stop())
示例#14
0
    def test_rtp_and_rtcp(self):
        transport, remote = dummy_dtls_transport_pair()

        receiver = RTCRtpReceiver('audio', transport)
        self.assertEqual(receiver.transport, transport)

        receiver._track = RemoteStreamTrack(kind='audio')
        self.assertEqual(receiver._track.readyState, 'live')
        run(receiver.receive(RTCRtpParameters(codecs=[PCMU_CODEC])))

        # receive RTP
        packet = RtpPacket.parse(load('rtp.bin'))
        run(receiver._handle_rtp_packet(packet, arrival_time_ms=0))

        # receive RTCP SR
        for packet in RtcpPacket.parse(load('rtcp_sr.bin')):
            run(receiver._handle_rtcp_packet(packet))

        # check stats
        report = run(receiver.getStats())
        self.assertTrue(isinstance(report, RTCStatsReport))
        self.assertEqual(sorted(report.keys()), ['inbound-rtp', 'remote-outbound-rtp'])

        # check remote track
        frame = run(receiver._track.recv())
        self.assertTrue(isinstance(frame, AudioFrame))

        # shutdown
        run(receiver.stop())
        self.assertEqual(receiver._track.readyState, 'ended')
示例#15
0
    def test_rtp_and_rtcp(self):
        transport, remote = dummy_dtls_transport_pair()

        receiver = RTCRtpReceiver('audio', transport)
        self.assertEqual(receiver.transport, transport)

        receiver._track = RemoteStreamTrack(kind='audio')
        run(receiver.receive(RTCRtpParameters(codecs=[PCMU_CODEC])))

        # receive RTP
        packet = RtpPacket.parse(load('rtp.bin'))
        run(receiver._handle_rtp_packet(packet))

        # receive RTCP
        for packet in RtcpPacket.parse(load('rtcp_sr.bin')):
            run(receiver._handle_rtcp_packet(packet))
        self.assertEqual(sorted(receiver._stats.keys()),
                         ['remote-inbound-rtp', 'remote-outbound-rtp'])

        # check remote track
        frame = run(receiver._track.recv())
        self.assertTrue(isinstance(frame, AudioFrame))

        # shutdown
        run(receiver.stop())
        run(asyncio.sleep(0))
示例#16
0
    def test_rtx(self):
        extensions_map = rtp.HeaderExtensionsMap()
        extensions_map.configure(
            RTCRtpParameters(headerExtensions=[
                RTCRtpHeaderExtensionParameters(
                    id=9, uri="urn:ietf:params:rtp-hdrext:sdes:mid")
            ]))

        data = load("rtp_with_sdes_mid.bin")
        packet = RtpPacket.parse(data, extensions_map)

        # wrap / unwrap RTX
        rtx = wrap_rtx(packet,
                       payload_type=112,
                       sequence_number=12345,
                       ssrc=1234)
        recovered = unwrap_rtx(rtx, payload_type=111, ssrc=4084547440)

        # check roundtrip
        self.assertEqual(recovered.version, packet.version)
        self.assertEqual(recovered.marker, packet.marker)
        self.assertEqual(recovered.payload_type, packet.payload_type)
        self.assertEqual(recovered.sequence_number, packet.sequence_number)
        self.assertEqual(recovered.timestamp, packet.timestamp)
        self.assertEqual(recovered.ssrc, packet.ssrc)
        self.assertEqual(recovered.csrc, packet.csrc)
        self.assertEqual(recovered.extensions, packet.extensions)
        self.assertEqual(recovered.payload, packet.payload)
示例#17
0
    def test_connection_error(self):
        """
        Close the underlying transport before the receiver.
        """
        transport, _ = dummy_dtls_transport_pair()

        receiver = RTCRtpReceiver('audio', transport)
        self.assertEqual(receiver.transport, transport)

        receiver._track = RemoteStreamTrack(kind='audio')
        receiver._ssrc = 1234
        run(receiver.receive(RTCRtpParameters(codecs=[PCMU_CODEC])))

        # receive a packet to prime RTCP
        packet = RtpPacket.parse(load('rtp.bin'))
        run(receiver._handle_rtp_packet(packet, arrival_time_ms=0))

        # break connection
        run(transport.stop())

        # give RTCP time to send a report
        run(asyncio.sleep(2))

        # shutdown
        run(receiver.stop())
示例#18
0
    def test_set_header_extensions(self):
        packet = RtpPacket()

        # none
        set_header_extensions(packet, {})
        self.assertEqual(packet.extension_profile, 0)
        self.assertEqual(packet.extension_value, None)

        # one-byte, single value
        set_header_extensions(packet, [
            (9, b'0'),
        ])
        self.assertEqual(packet.extension_profile, 0xBEDE)
        self.assertEqual(packet.extension_value, b'\x900\x00\x00')

        # one-byte, two values
        set_header_extensions(packet, [
            (1, b'\xc1'),
            (3, b'sdparta_0'),
        ])
        self.assertEqual(packet.extension_profile, 0xBEDE)
        self.assertEqual(packet.extension_value, b'\x10\xc18sdparta_0')

        # two-byte, single value
        set_header_extensions(packet, [
            (255, b'0'),
        ])
        self.assertEqual(packet.extension_profile, 0x1000)
        self.assertEqual(packet.extension_value, b'\xff\x010\x00')
示例#19
0
    def test_padding_only_with_header_extensions(self):
        extensions_map = rtp.HeaderExtensionsMap()
        extensions_map.configure(
            RTCRtpParameters(headerExtensions=[
                RTCRtpHeaderExtensionParameters(
                    id=2,
                    uri=
                    "http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time",
                )
            ]))

        data = load("rtp_only_padding_with_header_extensions.bin")
        packet = RtpPacket.parse(data, extensions_map)
        self.assertEqual(packet.version, 2)
        self.assertEqual(packet.marker, 0)
        self.assertEqual(packet.payload_type, 98)
        self.assertEqual(packet.sequence_number, 22138)
        self.assertEqual(packet.timestamp, 3171065731)
        self.assertEqual(packet.csrc, [])
        self.assertEqual(packet.extensions,
                         rtp.HeaderExtensions(abs_send_time=15846540))
        self.assertEqual(len(packet.payload), 0)
        self.assertEqual(packet.padding_size, 224)

        serialized = packet.serialize(extensions_map)
        self.assertEqual(len(serialized), len(data))
        self.assertEqual(serialized[0:20], data[0:20])
        self.assertEqual(serialized[-1], data[-1])
示例#20
0
def create_rtp_video_packets(self, codec, frames, seq=0):
    encoder = get_encoder(codec)
    packets = []
    for frame in self.create_video_frames(width=640, height=480, count=frames):
        payloads, timestamp = encoder.encode(frame)
        self.assertEqual(len(payloads), 1)
        packet = RtpPacket(payload_type=codec.payloadType,
                           sequence_number=seq,
                           ssrc=1234,
                           timestamp=timestamp)
        packet.payload = payloads[0]
        packet.marker = 1
        packets.append(packet)

        seq = uint16_add(seq, 1)
    return packets
示例#21
0
 def create_packets(self, count, seq=0):
     packets = []
     for i in range(count):
         packets.append(
             RtpPacket(payload_type=0,
                       sequence_number=(seq + i) % RTP_SEQ_MODULO,
                       timestamp=i * 160))
     return packets
示例#22
0
    def test_add_unordered(self):
        jbuffer = JitterBuffer(capacity=4)

        frame = jbuffer.add(RtpPacket(sequence_number=1, timestamp=1234))
        self.assertIsNone(frame)
        self.assertPackets(jbuffer, [None, 1, None, None])
        self.assertEqual(jbuffer._origin, 1)

        frame = jbuffer.add(RtpPacket(sequence_number=3, timestamp=1234))
        self.assertIsNone(frame)
        self.assertPackets(jbuffer, [None, 1, None, 3])
        self.assertEqual(jbuffer._origin, 1)

        frame = jbuffer.add(RtpPacket(sequence_number=2, timestamp=1234))
        self.assertIsNone(frame)
        self.assertPackets(jbuffer, [None, 1, 2, 3])
        self.assertEqual(jbuffer._origin, 1)
示例#23
0
def create_rtp_packets(count, seq=0):
    packets = []
    for i in range(count):
        packets.append(RtpPacket(
            payload_type=0,
            sequence_number=uint16_add(seq, i),
            ssrc=1234,
            timestamp=i * 160))
    return packets
示例#24
0
    async def test_rtp_unknown_payload_type(self):
        async with create_receiver("video") as receiver:
            receiver._track = RemoteStreamTrack(kind="video")

            await receiver.receive(RTCRtpReceiveParameters(codecs=[VP8_CODEC]))

            # receive RTP with unknown payload type
            packet = RtpPacket(payload_type=123)
            await receiver._handle_rtp_packet(packet, arrival_time_ms=0)
示例#25
0
    def test_rtp_and_rtcp(self):
        receiver = RTCRtpReceiver("audio", self.local_transport)
        self.assertEqual(receiver.transport, self.local_transport)

        receiver._track = RemoteStreamTrack(kind="audio")
        self.assertEqual(receiver._track.readyState, "live")
        run(receiver.receive(RTCRtpReceiveParameters(codecs=[PCMU_CODEC])))

        # receive RTP
        for i in range(10):
            packet = RtpPacket.parse(load("rtp.bin"))
            packet.sequence_number += i
            packet.timestamp += i * 160
            run(receiver._handle_rtp_packet(packet, arrival_time_ms=i * 20))

        # receive RTCP SR
        for packet in RtcpPacket.parse(load("rtcp_sr.bin")):
            run(receiver._handle_rtcp_packet(packet))

        # check stats
        report = run(receiver.getStats())
        self.assertTrue(isinstance(report, RTCStatsReport))
        self.assertEqual(
            sorted([s.type for s in report.values()]),
            ["inbound-rtp", "remote-outbound-rtp", "transport"],
        )

        # check sources
        sources = receiver.getSynchronizationSources()
        self.assertEqual(len(sources), 1)
        self.assertTrue(isinstance(sources[0], RTCRtpSynchronizationSource))
        self.assertEqual(sources[0].source, 4028317929)

        # check remote track
        frame = run(receiver._track.recv())
        self.assertEqual(frame.pts, 0)
        self.assertEqual(frame.sample_rate, 8000)
        self.assertEqual(frame.time_base, fractions.Fraction(1, 8000))

        frame = run(receiver._track.recv())
        self.assertEqual(frame.pts, 160)
        self.assertEqual(frame.sample_rate, 8000)
        self.assertEqual(frame.time_base, fractions.Fraction(1, 8000))

        # shutdown
        run(receiver.stop())

        # read until end
        with self.assertRaises(MediaStreamError):
            while True:
                run(receiver._track.recv())
        self.assertEqual(receiver._track.readyState, "ended")

        # try reading again
        with self.assertRaises(MediaStreamError):
            run(receiver._track.recv())
示例#26
0
    def test_add_seq_too_high_discard_more(self):
        jbuffer = JitterBuffer(capacity=4)

        jbuffer.add(RtpPacket(sequence_number=0, timestamp=1234))
        self.assertEqual(jbuffer._origin, 0)

        jbuffer.add(RtpPacket(sequence_number=1, timestamp=1234))
        self.assertEqual(jbuffer._origin, 0)

        jbuffer.add(RtpPacket(sequence_number=2, timestamp=1234))
        self.assertEqual(jbuffer._origin, 0)

        jbuffer.add(RtpPacket(sequence_number=3, timestamp=1234))
        self.assertEqual(jbuffer._origin, 0)

        jbuffer.add(RtpPacket(sequence_number=8, timestamp=1234))
        self.assertEqual(jbuffer._origin, 8)

        self.assertPackets(jbuffer, [8, None, None, None])
示例#27
0
 def test_with_csrc(self):
     data = load('rtp_with_csrc.bin')
     packet = RtpPacket.parse(data)
     self.assertEqual(packet.version, 2)
     self.assertEqual(packet.extension, 0)
     self.assertEqual(packet.marker, 0)
     self.assertEqual(packet.payload_type, 0)
     self.assertEqual(packet.sequence_number, 16082)
     self.assertEqual(packet.timestamp, 144)
     self.assertEqual(packet.csrc, [2882400001, 3735928559])
     self.assertEqual(len(packet.payload), 160)
     self.assertEqual(bytes(packet), data)
示例#28
0
 def test_padding_only(self):
     data = load('rtp_only_padding.bin')
     packet = RtpPacket.parse(data)
     self.assertEqual(packet.version, 2)
     self.assertEqual(packet.extension, 0)
     self.assertEqual(packet.marker, 0)
     self.assertEqual(packet.payload_type, 120)
     self.assertEqual(packet.sequence_number, 27759)
     self.assertEqual(packet.timestamp, 4044047131)
     self.assertEqual(packet.csrc, [])
     self.assertEqual(len(packet.payload), 0)
     self.assertEqual(bytes(packet), b'\x80' + data[1:12])
示例#29
0
 def test_dtmf(self):
     data = load('rtp_dtmf.bin')
     packet = RtpPacket.parse(data)
     self.assertEqual(packet.version, 2)
     self.assertEqual(packet.extension, 0)
     self.assertEqual(packet.marker, 1)
     self.assertEqual(packet.payload_type, 101)
     self.assertEqual(packet.sequence_number, 24152)
     self.assertEqual(packet.timestamp, 4021352124)
     self.assertEqual(packet.csrc, [])
     self.assertEqual(len(packet.payload), 4)
     self.assertEqual(bytes(packet), data)
示例#30
0
 def test_with_csrc(self):
     data = load("rtp_with_csrc.bin")
     packet = RtpPacket.parse(data)
     self.assertEqual(packet.version, 2)
     self.assertEqual(packet.marker, 0)
     self.assertEqual(packet.payload_type, 0)
     self.assertEqual(packet.sequence_number, 16082)
     self.assertEqual(packet.timestamp, 144)
     self.assertEqual(packet.csrc, [2882400001, 3735928559])
     self.assertEqual(packet.extensions, rtp.HeaderExtensions())
     self.assertEqual(len(packet.payload), 160)
     self.assertEqual(packet.serialize(), data)