96 lines
3.5 KiB
Python
96 lines
3.5 KiB
Python
import asyncio
|
|
import os
|
|
|
|
import pytest
|
|
|
|
from iqpilot.system.webrtc.rtc import WebRTCOfferBuilder
|
|
from iqpilot.system.webrtc.rtc.stream import RTCSessionDescription
|
|
from iqpilot.system.webrtc.session import StreamSession
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_native_video_audio_and_data_channel():
|
|
if not os.environ.get("CI"):
|
|
return
|
|
|
|
answer_session = None
|
|
video_received = asyncio.Event()
|
|
audio_received = asyncio.Event()
|
|
|
|
async def connect(offer):
|
|
nonlocal answer_session
|
|
browser_offer = offer.sdp.replace("profile-level-id=42e01f", "profile-level-id=640c1f", 1)
|
|
audio_offset = browser_offer.index("m=audio")
|
|
browser_offer = browser_offer[:audio_offset] + browser_offer[audio_offset:].replace(
|
|
"a=recvonly",
|
|
"a=sendrecv\r\na=msid:ios-microphone ios-audio-track\r\na=ssrc:123456 cname:ios-audio\r\na=ssrc:123456 msid:ios-microphone ios-audio-track",
|
|
1,
|
|
)
|
|
answer_session = StreamSession(browser_offer, offer.video, [], [], [], debug_mode=True)
|
|
answer = await answer_session.get_answer()
|
|
assert not any(line.startswith("m=video 0 ") for line in answer.sdp.splitlines())
|
|
assert answer_session.stream._track_state[0][0] is answer_session.stream._negotiated_tracks["road"]
|
|
answer_session.start()
|
|
return RTCSessionDescription(answer.sdp, answer.type)
|
|
|
|
builder = WebRTCOfferBuilder(connect, ice_servers=[])
|
|
builder.offer_to_receive_video_stream("road")
|
|
builder.offer_to_receive_audio_stream()
|
|
builder.add_messaging()
|
|
stream = builder.stream()
|
|
|
|
try:
|
|
await asyncio.wait_for(stream.start(), 10)
|
|
stream.get_incoming_video_track("road").on_frame(lambda *_: video_received.set())
|
|
stream.get_incoming_audio_track().on_frame(lambda *_: audio_received.set())
|
|
await asyncio.wait_for(stream.wait_for_connection(), 10)
|
|
await asyncio.wait_for(video_received.wait(), 10)
|
|
await asyncio.wait_for(audio_received.wait(), 10)
|
|
stream.get_messaging_channel().send('{"type":"timingSei","enabled":true}')
|
|
await asyncio.sleep(0.1)
|
|
assert answer_session is not None
|
|
assert answer_session.video_tracks[0].timing_sei_enabled
|
|
finally:
|
|
await stream.stop()
|
|
if answer_session is not None:
|
|
await answer_session.stop_async()
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_native_duplex_audio_negotiation():
|
|
if not os.environ.get("CI"):
|
|
return
|
|
|
|
answer_session = None
|
|
|
|
async def connect(offer):
|
|
nonlocal answer_session
|
|
sendrecv_offer = offer.sdp.replace(
|
|
"a=recvonly",
|
|
"a=sendrecv\r\na=msid:ios-microphone ios-audio-track\r\na=ssrc:123456 cname:ios-audio\r\na=ssrc:123456 msid:ios-microphone ios-audio-track",
|
|
1,
|
|
)
|
|
answer_session = StreamSession(sendrecv_offer, offer.video, [], [], [], debug_mode=True)
|
|
answer = await answer_session.get_answer()
|
|
assert "ios-microphone" not in answer.sdp
|
|
assert "ios-audio-track" not in answer.sdp
|
|
assert answer.sdp.count("a=msid:audio audio") == 1
|
|
answer_session.start()
|
|
return RTCSessionDescription(answer.sdp, answer.type)
|
|
|
|
builder = WebRTCOfferBuilder(connect, ice_servers=[])
|
|
builder.offer_to_receive_audio_stream()
|
|
stream = builder.stream()
|
|
|
|
try:
|
|
await asyncio.wait_for(stream.start(), 10)
|
|
await asyncio.wait_for(stream.wait_for_connection(), 10)
|
|
assert stream.has_incoming_audio_track()
|
|
assert answer_session is not None
|
|
assert answer_session.audio_recv_requested
|
|
assert answer_session.audio_output is not None
|
|
finally:
|
|
await stream.stop()
|
|
if answer_session is not None:
|
|
await answer_session.stop_async()
|