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())
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))
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())
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())
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))
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')
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_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())
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())
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())
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())
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())
def test_send_rtcp_pli(self): receiver = RTCRtpReceiver('video', self.local_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())
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())
def test_send_rtcp_nack(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 NACK run(receiver._send_rtcp_nack(5678, [7654])) # shutdown run(receiver.stop())
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))
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())
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())
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())