示例#1
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)

        run(receiver.receive(RTCRtpParameters(codecs=[PCMU_CODEC])))

        run(transport.close())
示例#2
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())
    def test_capabilities(self):
        # audio
        capabilities = RTCRtpReceiver.getCapabilities('audio')
        self.assertTrue(isinstance(capabilities, RTCRtpCapabilities))
        self.assertEqual(capabilities.codecs, [
            RTCRtpCodecCapability(
                mimeType='audio/opus', clockRate=48000, channels=2),
            RTCRtpCodecCapability(
                mimeType='audio/PCMU', clockRate=8000, channels=1),
            RTCRtpCodecCapability(
                mimeType='audio/PCMA', clockRate=8000, channels=1),
        ])
        self.assertEqual(capabilities.headerExtensions, [
            RTCRtpHeaderExtensionCapability(
                uri='urn:ietf:params:rtp-hdrext:sdes:mid'),
        ])

        # video
        capabilities = RTCRtpReceiver.getCapabilities('video')
        self.assertTrue(isinstance(capabilities, RTCRtpCapabilities))
        self.assertEqual(capabilities.codecs, [
            RTCRtpCodecCapability(mimeType='video/VP8', clockRate=90000),
            RTCRtpCodecCapability(mimeType='video/rtx', clockRate=90000),
            RTCRtpCodecCapability(mimeType='video/H264',
                                  clockRate=90000,
                                  parameters=OrderedDict(
                                      [('packetization-mode', '1'),
                                       ('level-asymmetry-allowed', '1'),
                                       ('profile-level-id', '42001f')])),
            RTCRtpCodecCapability(mimeType='video/H264',
                                  clockRate=90000,
                                  parameters=OrderedDict(
                                      [('packetization-mode', '1'),
                                       ('level-asymmetry-allowed', '1'),
                                       ('profile-level-id', '42e01f')])),
        ])
        self.assertEqual(
            capabilities.headerExtensions,
            [
                RTCRtpHeaderExtensionCapability(
                    uri='urn:ietf:params:rtp-hdrext:sdes:mid'),
                RTCRtpHeaderExtensionCapability(
                    uri=
                    'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time'
                ),  # noqa
            ])

        # bogus
        capabilities = RTCRtpReceiver.getCapabilities('bogus')
        self.assertIsNone(capabilities)
示例#4
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')
示例#5
0
    def test_rtp_empty_video_packet(self):
        transport, remote = dummy_dtls_transport_pair()

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

        receiver._track = RemoteStreamTrack(kind='audio')
        run(
            receiver.receive(
                RTCRtpParameters(codecs=[
                    RTCRtpCodecParameters(
                        name='VP8', clockRate=90000, payloadType=100),
                ])))

        # receive RTP with empty payload
        packet = RtpPacket(payload_type=100)
        run(receiver._handle_rtp_packet(packet))
示例#6
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())
示例#7
0
    def test_rtp_missing_video_packet(self):
        nacks = []

        async def mock_send_rtcp_nack(*args):
            nacks.append(args)

        receiver = RTCRtpReceiver('video', self.local_transport)
        self.assertEqual(receiver.transport, self.local_transport)

        receiver._send_rtcp_nack = mock_send_rtcp_nack
        receiver._track = RemoteStreamTrack(kind='video')
        run(receiver.receive(RTCRtpReceiveParameters(codecs=[VP8_CODEC])))

        # generate some packets
        packets = create_rtp_video_packets(self, codec=VP8_CODEC, frames=3)

        # receive RTP with a with a gap
        run(receiver._handle_rtp_packet(packets[0], arrival_time_ms=0))
        run(receiver._handle_rtp_packet(packets[2], arrival_time_ms=0))

        # check NACK was triggered
        self.assertEqual(nacks, [(1234, [1])])

        # shutdown
        run(receiver.stop())
    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())
示例#9
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))
示例#10
0
async def create_receiver(kind):
    async with dummy_dtls_transport_pair() as (local_transport, _):
        receiver = RTCRtpReceiver(kind, local_transport)
        assert receiver.transport == local_transport

        try:
            yield receiver
        finally:
            await receiver.stop()
示例#11
0
    def test_send_rtcp_nack(self):
        receiver = RTCRtpReceiver("video", self.local_transport)
        receiver._set_rtcp_ssrc(1234)
        receiver._track = RemoteStreamTrack(kind="video")

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

        # send RTCP feedback NACK
        run(receiver._send_rtcp_nack(5678, [7654]))

        # shutdown
        run(receiver.stop())
示例#12
0
    def test_send_rtcp_pli(self):
        receiver = RTCRtpReceiver('video', self.local_transport)
        receiver._set_rtcp_ssrc(1234)
        receiver._track = RemoteStreamTrack(kind='video')

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

        # send RTCP feedback PLI
        run(receiver._send_rtcp_pli(5678))

        # shutdown
        run(receiver.stop())
示例#13
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
        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 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())
示例#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')
        run(receiver.receive(RTCRtpParameters(codecs=[PCMU_CODEC])))

        # receive RTP
        run(remote.send(load('rtp.bin')))

        # receive RTCP
        run(remote.send(load('rtcp_sr.bin')))

        # receive truncated RTCP
        run(remote.send(b'\x81\xca\x00'))

        # receive garbage
        run(remote.send(b'garbage'))

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

        # shutdown
        run(asyncio.sleep(0.1))
        receiver.stop()
        run(asyncio.sleep(0))
示例#15
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())
示例#16
0
    def test_send_rtcp_pli(self):
        receiver = RTCRtpReceiver('video', self.local_transport)
        receiver._set_rtcp_ssrc(1234)
        receiver._track = RemoteStreamTrack(kind='video')

        run(
            receiver.receive(
                RTCRtpReceiveParameters(codecs=[
                    RTCRtpCodecParameters(
                        name='VP8', clockRate=90000, payloadType=100),
                ])))

        # send RTCP feedback PLI
        run(receiver._send_rtcp_pli(5678))

        # shutdown
        run(receiver.stop())
 def __createTransceiver(self,
                         direction: str,
                         kind: str,
                         sender_track=None) -> RTCRtpTransceiver:
     dtlsTransport = self.__createDtlsTransport()
     transceiver = RTCRtpTransceiver(
         direction=direction,
         kind=kind,
         sender=RTCRtpSender(sender_track or kind, dtlsTransport),
         receiver=RTCRtpReceiver(kind, dtlsTransport),
     )
     transceiver.receiver._set_rtcp_ssrc(transceiver.sender._ssrc)
     transceiver.sender._stream_id = self.__stream_id
     transceiver._bundled = False
     transceiver._transport = dtlsTransport
     self.__transceivers.append(transceiver)
     return transceiver
示例#18
0
    def test_send_rtcp_pli(self):
        transport, remote = dummy_dtls_transport_pair()

        receiver = RTCRtpReceiver('video', transport)
        receiver._ssrc = 1234
        receiver._track = RemoteStreamTrack(kind='video')

        run(receiver.receive(RTCRtpParameters(codecs=[
            RTCRtpCodecParameters(name='VP8', clockRate=90000, payloadType=100),
        ])))

        # send RTCP feedback PLI
        run(receiver._send_rtcp_pli(5678))

        # shutdown
        run(receiver.stop())
示例#19
0
    def test_rtp_unknown_payload_type(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])))

        # receive RTP with unknown payload type
        packet = RtpPacket(payload_type=123)
        run(receiver._handle_rtp_packet(packet, arrival_time_ms=0))

        # shutdown
        run(receiver.stop())
示例#20
0
    def test_rtp_empty_video_packet(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])))

        # receive RTP with empty payload
        packet = RtpPacket(payload_type=100)
        run(receiver._handle_rtp_packet(packet, arrival_time_ms=0))

        # shutdown
        run(receiver.stop())
示例#21
0
    def test_rtp_missing_video_packet(self):
        nacks = []
        pli = []

        async def mock_send_rtcp_nack(*args):
            nacks.append(args)

        async def mock_send_rtcp_pli(*args):
            pli.append(args[0])

        receiver = RTCRtpReceiver("video", self.local_transport)
        self.assertEqual(receiver.transport, self.local_transport)

        receiver._send_rtcp_nack = mock_send_rtcp_nack
        receiver._send_rtcp_pli = mock_send_rtcp_pli
        receiver._track = RemoteStreamTrack(kind="video")
        run(receiver.receive(RTCRtpReceiveParameters(codecs=[VP8_CODEC])))

        # generate some packets
        packets = create_rtp_video_packets(self, codec=VP8_CODEC, frames=129)

        # receive RTP with a with a gap
        run(receiver._handle_rtp_packet(packets[0], arrival_time_ms=0))
        run(receiver._handle_rtp_packet(packets[128], arrival_time_ms=0))

        # check NACK was triggered
        lost_packets = []
        for i in range(127):
            lost_packets.append(i + 1)
        self.assertEqual(nacks[0], (1234, lost_packets))

        # check PLI was triggered
        self.assertEqual(pli, [1234])

        # shutdown
        run(receiver.stop())
示例#22
0
    def test_rtp_empty_video_packet(self):
        receiver = RTCRtpReceiver('video', self.local_transport)
        self.assertEqual(receiver.transport, self.local_transport)

        receiver._track = RemoteStreamTrack(kind='video')
        run(receiver.receive(RTCRtpParameters(codecs=[
            RTCRtpCodecParameters(name='VP8', clockRate=90000, payloadType=100),
        ])))

        # receive RTP with empty payload
        packet = RtpPacket(payload_type=100)
        run(receiver._handle_rtp_packet(packet, arrival_time_ms=0))

        # shutdown
        run(receiver.stop())
示例#23
0
    def test_connection_error(self):
        """
        Close the underlying transport before the receiver.
        """
        receiver = RTCRtpReceiver("audio", self.local_transport)
        self.assertEqual(receiver.transport, self.local_transport)

        receiver._track = RemoteStreamTrack(kind="audio")
        receiver._set_rtcp_ssrc(1234)
        run(receiver.receive(RTCRtpReceiveParameters(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(self.local_transport.stop())

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

        # shutdown
        run(receiver.stop())
示例#24
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=[
                RTCRtpCodecParameters(name='VP8', clockRate=90000, payloadType=100),
                RTCRtpCodecParameters(name='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())
示例#25
0
 def test_invalid_dtls_transport_state(self):
     dtlsTransport = ClosedDtlsTransport()
     with self.assertRaises(InvalidStateError):
         RTCRtpReceiver('audio', dtlsTransport)
示例#26
0
    def test_capabilities(self):
        # audio
        capabilities = RTCRtpReceiver.getCapabilities("audio")
        self.assertTrue(isinstance(capabilities, RTCRtpCapabilities))
        self.assertEqual(
            capabilities.codecs,
            [
                RTCRtpCodecCapability(
                    mimeType="audio/opus", clockRate=48000, channels=2),
                RTCRtpCodecCapability(
                    mimeType="audio/PCMU", clockRate=8000, channels=1),
                RTCRtpCodecCapability(
                    mimeType="audio/PCMA", clockRate=8000, channels=1),
            ],
        )
        self.assertEqual(
            capabilities.headerExtensions,
            [
                RTCRtpHeaderExtensionCapability(
                    uri="urn:ietf:params:rtp-hdrext:sdes:mid")
            ],
        )

        # video
        capabilities = RTCRtpReceiver.getCapabilities("video")
        self.assertTrue(isinstance(capabilities, RTCRtpCapabilities))
        self.assertEqual(
            capabilities.codecs,
            [
                RTCRtpCodecCapability(mimeType="video/VP8", clockRate=90000),
                RTCRtpCodecCapability(mimeType="video/rtx", clockRate=90000),
                RTCRtpCodecCapability(
                    mimeType="video/H264",
                    clockRate=90000,
                    parameters=OrderedDict([
                        ("packetization-mode", "1"),
                        ("level-asymmetry-allowed", "1"),
                        ("profile-level-id", "42001f"),
                    ]),
                ),
                RTCRtpCodecCapability(
                    mimeType="video/H264",
                    clockRate=90000,
                    parameters=OrderedDict([
                        ("packetization-mode", "1"),
                        ("level-asymmetry-allowed", "1"),
                        ("profile-level-id", "42e01f"),
                    ]),
                ),
            ],
        )
        self.assertEqual(
            capabilities.headerExtensions,
            [
                RTCRtpHeaderExtensionCapability(
                    uri="urn:ietf:params:rtp-hdrext:sdes:mid"),
                RTCRtpHeaderExtensionCapability(
                    uri=
                    "http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time"
                ),
            ],
        )

        # bogus
        with self.assertRaises(ValueError):
            RTCRtpReceiver.getCapabilities("bogus")