mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-11-08 13:33:42 +08:00
22a8575199
Keep official openpilot ancestry and dependency licenses. Store resources directly in Git, remove LFS setup requirements, and leave the downloadable big model outside the source tree.
234 lines
6.5 KiB
Python
Executable File
234 lines
6.5 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
import contextlib
|
|
|
|
import pytest
|
|
|
|
from libdatachannel import Description
|
|
|
|
from teleoprtc.builder import WebRTCOfferBuilder, WebRTCAnswerBuilder
|
|
from teleoprtc.info import parse_info_from_offer
|
|
from teleoprtc.tracks import TiciVideoStreamTrack
|
|
|
|
|
|
class OfferCapture:
|
|
def __init__(self):
|
|
self.offer = None
|
|
|
|
async def __call__(self, offer):
|
|
self.offer = offer
|
|
raise Exception("Offer captured")
|
|
|
|
|
|
class DummyH264VideoStreamTrack(TiciVideoStreamTrack):
|
|
kind = "video"
|
|
|
|
async def recv(self):
|
|
raise NotImplementedError()
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
class TestOfferStream:
|
|
async def test_offer_stream_sdp_recvonly_audio(self):
|
|
capture = OfferCapture()
|
|
builder = WebRTCOfferBuilder(capture)
|
|
builder.offer_to_receive_audio_stream()
|
|
stream = builder.stream()
|
|
|
|
try:
|
|
_ = await stream.start()
|
|
except Exception:
|
|
pass
|
|
finally:
|
|
await stream.stop()
|
|
|
|
info = parse_info_from_offer(capture.offer.sdp)
|
|
assert info.expected_audio_track
|
|
assert not info.incoming_audio_track
|
|
|
|
async def test_offer_stream_sdp_channel(self):
|
|
capture = OfferCapture()
|
|
builder = WebRTCOfferBuilder(capture)
|
|
builder.add_messaging()
|
|
stream = builder.stream()
|
|
|
|
try:
|
|
_ = await stream.start()
|
|
except Exception:
|
|
pass
|
|
finally:
|
|
await stream.stop()
|
|
|
|
info = parse_info_from_offer(capture.offer.sdp)
|
|
assert info.incoming_datachannel
|
|
|
|
async def test_answer_side_messaging_channel_wrapper_retained_after_stop(self):
|
|
stream = WebRTCOfferBuilder(OfferCapture()).stream()
|
|
stream._retain_messaging_channel_on_close = True
|
|
channel = stream.peer_connection.create_data_channel("data")
|
|
stream.messaging_channel = channel
|
|
stream.messaging_channel_ready_event.set()
|
|
|
|
try:
|
|
await stream.stop()
|
|
assert stream.messaging_channel is None
|
|
assert stream._retained_messaging_channels[-1] is channel
|
|
finally:
|
|
stream._retained_messaging_channels.pop()
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
class TestAnswerStream:
|
|
async def test_codec_preference(self):
|
|
offer_sdp = """v=0
|
|
o=- 3910274679 3910274679 IN IP4 0.0.0.0
|
|
s=-
|
|
t=0 0
|
|
a=group:BUNDLE 0
|
|
a=msid-semantic:WMS *
|
|
m=video 1337 UDP/TLS/RTP/SAVPF 97 98 99 100 101 102
|
|
c=IN IP4 0.0.0.0
|
|
a=recvonly
|
|
a=mid:0
|
|
a=msid:34803878-98f8-4245-b45c-f773e5f926df 881dbc20-356a-499c-b4e8-695303bb901d
|
|
a=rtcp:9 IN IP4 0.0.0.0
|
|
a=rtcp-mux
|
|
a=ssrc-group:FID 1303546896 3784011659
|
|
a=ssrc:1303546896 cname:a59185ac-c115-48d3-b39b-db7d615a6966
|
|
a=ssrc:3784011659 cname:a59185ac-c115-48d3-b39b-db7d615a6966
|
|
a=rtpmap:97 VP8/90000
|
|
a=rtcp-fb:97 nack
|
|
a=rtcp-fb:97 nack pli
|
|
a=rtcp-fb:97 goog-remb
|
|
a=rtpmap:99 H264/90000
|
|
a=rtcp-fb:99 nack
|
|
a=rtcp-fb:99 nack pli
|
|
a=rtcp-fb:99 goog-remb
|
|
a=fmtp:99 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f
|
|
a=ice-ufrag:1234
|
|
a=ice-pwd:1234
|
|
a=fingerprint:sha-256 15:F3:F0:23:67:44:EE:2C:AA:8C:D9:50:95:26:42:7C:67:EA:1F:D2:92:C5:97:01:7B:2E:57:C9:A3:13:00:4A
|
|
a=setup:actpass"""
|
|
|
|
builder = WebRTCAnswerBuilder(offer_sdp)
|
|
builder.add_video_stream("road", DummyH264VideoStreamTrack("road", 0.05))
|
|
stream = builder.stream()
|
|
try:
|
|
answer = await stream.start()
|
|
|
|
sdp_desc = Description(answer.sdp, Description.Type.Answer)
|
|
video_desc = next(sdp_desc.media(i) for i in range(sdp_desc.media_count()) if sdp_desc.media(i).type() == "video")
|
|
codecs = []
|
|
for pt in video_desc.payload_types():
|
|
with contextlib.suppress(ValueError):
|
|
codecs.append(video_desc.rtp_map(pt).format)
|
|
assert codecs[0] == "H264"
|
|
finally:
|
|
await stream.stop()
|
|
|
|
async def test_fail_if_preferred_codec_not_in_offer(self):
|
|
offer_sdp = """v=0
|
|
o=- 3910274679 3910274679 IN IP4 0.0.0.0
|
|
s=-
|
|
t=0 0
|
|
a=group:BUNDLE 0
|
|
a=msid-semantic:WMS *
|
|
m=video 1337 UDP/TLS/RTP/SAVPF 97 98 99 100 101 102
|
|
c=IN IP4 0.0.0.0
|
|
a=recvonly
|
|
a=mid:0
|
|
a=msid:34803878-98f8-4245-b45c-f773e5f926df 881dbc20-356a-499c-b4e8-695303bb901d
|
|
a=rtcp:9 IN IP4 0.0.0.0
|
|
a=rtcp-mux
|
|
a=ssrc-group:FID 1303546896 3784011659
|
|
a=ssrc:1303546896 cname:a59185ac-c115-48d3-b39b-db7d615a6966
|
|
a=ssrc:3784011659 cname:a59185ac-c115-48d3-b39b-db7d615a6966
|
|
a=rtpmap:97 VP8/90000
|
|
a=rtcp-fb:97 nack
|
|
a=rtcp-fb:97 nack pli
|
|
a=rtcp-fb:97 goog-remb
|
|
a=ice-ufrag:1234
|
|
a=ice-pwd:1234
|
|
a=fingerprint:sha-256 15:F3:F0:23:67:44:EE:2C:AA:8C:D9:50:95:26:42:7C:67:EA:1F:D2:92:C5:97:01:7B:2E:57:C9:A3:13:00:4A
|
|
a=setup:actpass"""
|
|
|
|
builder = WebRTCAnswerBuilder(offer_sdp)
|
|
builder.add_video_stream("road", DummyH264VideoStreamTrack("road", 0.05))
|
|
stream = builder.stream()
|
|
|
|
try:
|
|
with pytest.raises(ValueError):
|
|
_ = await stream.start()
|
|
finally:
|
|
await stream.stop()
|
|
|
|
async def test_multi_track(self):
|
|
offer_sdp = """v=0
|
|
o=- 1 1 IN IP4 0.0.0.0
|
|
s=-
|
|
t=0 0
|
|
a=group:BUNDLE 0 1
|
|
m=video 9 UDP/TLS/RTP/SAVPF 99
|
|
c=IN IP4 0.0.0.0
|
|
a=recvonly
|
|
a=mid:0
|
|
a=rtpmap:99 H264/90000
|
|
a=ice-ufrag:1234
|
|
a=ice-pwd:1234
|
|
a=fingerprint:sha-256 15:F3:F0:23:67:44:EE:2C:AA:8C:D9:50:95:26:42:7C:67:EA:1F:D2:92:C5:97:01:7B:2E:57:C9:A3:13:00:4A
|
|
a=setup:actpass
|
|
m=video 9 UDP/TLS/RTP/SAVPF 99
|
|
c=IN IP4 0.0.0.0
|
|
a=recvonly
|
|
a=mid:1
|
|
a=rtpmap:99 H264/90000
|
|
a=ice-ufrag:1234
|
|
a=ice-pwd:1234
|
|
a=fingerprint:sha-256 15:F3:F0:23:67:44:EE:2C:AA:8C:D9:50:95:26:42:7C:67:EA:1F:D2:92:C5:97:01:7B:2E:57:C9:A3:13:00:4A
|
|
a=setup:actpass"""
|
|
|
|
builder = WebRTCAnswerBuilder(offer_sdp)
|
|
builder.add_video_stream("road", DummyH264VideoStreamTrack("road", 0.05))
|
|
builder.add_video_stream("wideRoad", DummyH264VideoStreamTrack("wideRoad", 0.05))
|
|
stream = builder.stream()
|
|
try:
|
|
answer = await stream.start()
|
|
|
|
sdp_desc = Description(answer.sdp, Description.Type.Answer)
|
|
video_ssrcs = []
|
|
for i in range(sdp_desc.media_count()):
|
|
media = sdp_desc.media(i)
|
|
if media and media.type() == "video":
|
|
video_ssrcs.extend(media.get_ssrcs())
|
|
assert len(video_ssrcs) == 2
|
|
assert len(set(video_ssrcs)) == 2
|
|
finally:
|
|
await stream.stop()
|
|
|
|
async def test_parse_incoming_streams_datachannel_counting(self):
|
|
offer_sdp = """v=0
|
|
o=- 3910274679 3910274679 IN IP4 0.0.0.0
|
|
s=-
|
|
t=0 0
|
|
a=group:BUNDLE 0 1
|
|
m=video 9 UDP/TLS/RTP/SAVPF 97
|
|
c=IN IP4 0.0.0.0
|
|
a=recvonly
|
|
a=mid:0
|
|
a=ice-ufrag:1234
|
|
a=ice-pwd:1234
|
|
a=fingerprint:sha-256 15:F3:F0:23:67:44:EE:2C:AA:8C:D9:50:95:26:42:7C:67:EA:1F:D2:92:C5:97:01:7B:2E:57:C9:A3:13:00:4A
|
|
a=setup:actpass
|
|
m=application 9 UDP/DTLS/SCTP webrtc-datachannel
|
|
c=IN IP4 0.0.0.0
|
|
a=sendrecv
|
|
a=mid:1
|
|
a=sctp-port:5000"""
|
|
|
|
builder = WebRTCAnswerBuilder(offer_sdp)
|
|
stream = builder.stream()
|
|
stream._parse_incoming_streams(builder.offer_sdp)
|
|
|
|
assert stream.expected_number_of_incoming_media == 1
|
|
await stream.stop()
|