Skip to content

Commit 43d3d44

Browse files
Fix WebRTC Streaming Issue in Home Assistant App (WebView Beta 143) (#1206)
* apply answer sdp fix for chromium as well * Split the firefox and chrome tests Split the SDP checks for firefox and chrome into separate tests. --------- Co-authored-by: Allen Porter <[email protected]>
1 parent 89ab1ac commit 43d3d44

File tree

3 files changed

+81
-32
lines changed

3 files changed

+81
-32
lines changed

google_nest_sdm/camera_traits.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
EventType,
2525
)
2626
from .traits import CommandDataClass, TraitType
27-
from .webrtc_util import fix_mozilla_sdp_answer
27+
from .webrtc_util import fix_sdp_answer
2828

2929
__all__ = [
3030
"CameraImageTrait",
@@ -280,7 +280,7 @@ async def generate_web_rtc_stream(self, offer_sdp: str) -> WebRtcStream:
280280
obj = WebRtcStream.from_dict(results)
281281
obj._cmd = self.cmd
282282
_LOGGER.debug("Received answer_sdp: %s", obj.answer_sdp)
283-
obj.answer_sdp = fix_mozilla_sdp_answer(offer_sdp, obj.answer_sdp)
283+
obj.answer_sdp = fix_sdp_answer(offer_sdp, obj.answer_sdp)
284284
_LOGGER.debug("Return answer_sdp: %s", obj.answer_sdp)
285285
return obj
286286

google_nest_sdm/webrtc_util.py

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -79,32 +79,36 @@ def _add_foundation_to_candidates(sdp: str) -> str:
7979
return "\r\n".join(updated_sdp_lines)
8080

8181

82-
def fix_mozilla_sdp_answer(offer_sdp: str, answer_sdp: str) -> str:
83-
"""Fix the answer SDP which is rejected by Firefox.
82+
def fix_sdp_answer(offer_sdp: str, answer_sdp: str) -> str:
83+
"""Fix the answer SDP which is rejected by the browser
8484
85+
For both firefox and chromium >= 143
8586
1. If offer SDP is recvonly, the direction of answer SDP must not be sendrecv.
86-
2. If the ICE candidates in answer SDP must contain "foundation" field.
87+
88+
For firefox only
89+
1. If the ICE candidates in answer SDP must contain "foundation" field.
8790
"""
91+
92+
if (
93+
_get_media_direction(sdp=offer_sdp, kind=SDPMediaKind.VIDEO)
94+
== SDPDirection.RECVONLY
95+
):
96+
answer_sdp = _update_direction_in_answer(
97+
answer_sdp=answer_sdp,
98+
kind=SDPMediaKind.VIDEO,
99+
old_direction=SDPDirection.SENDRECV,
100+
new_direction=SDPDirection.SENDONLY,
101+
)
102+
if (
103+
_get_media_direction(sdp=offer_sdp, kind=SDPMediaKind.AUDIO)
104+
== SDPDirection.RECVONLY
105+
):
106+
answer_sdp = _update_direction_in_answer(
107+
answer_sdp=answer_sdp,
108+
kind=SDPMediaKind.AUDIO,
109+
old_direction=SDPDirection.SENDRECV,
110+
new_direction=SDPDirection.SENDONLY,
111+
)
88112
if "mozilla" in offer_sdp:
89-
if (
90-
_get_media_direction(sdp=offer_sdp, kind=SDPMediaKind.VIDEO)
91-
== SDPDirection.RECVONLY
92-
):
93-
answer_sdp = _update_direction_in_answer(
94-
answer_sdp=answer_sdp,
95-
kind=SDPMediaKind.VIDEO,
96-
old_direction=SDPDirection.SENDRECV,
97-
new_direction=SDPDirection.SENDONLY,
98-
)
99-
if (
100-
_get_media_direction(sdp=offer_sdp, kind=SDPMediaKind.AUDIO)
101-
== SDPDirection.RECVONLY
102-
):
103-
answer_sdp = _update_direction_in_answer(
104-
answer_sdp=answer_sdp,
105-
kind=SDPMediaKind.AUDIO,
106-
old_direction=SDPDirection.SENDRECV,
107-
new_direction=SDPDirection.SENDONLY,
108-
)
109113
return _add_foundation_to_candidates(answer_sdp)
110114
return answer_sdp

tests/test_webrtc_util.py

Lines changed: 52 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@
66
_add_foundation_to_candidates,
77
_get_media_direction,
88
_update_direction_in_answer,
9-
fix_mozilla_sdp_answer,
9+
fix_sdp_answer,
1010
)
1111

1212

13-
def test_fix_mozilla_sdp_answer() -> None:
13+
def test_fix_firefox_sdp_answer() -> None:
1414
"""Test the fix in the SDP for Firefox."""
1515
firefox_offer_sdp = (
1616
"v=0\r\n"
@@ -45,7 +45,7 @@ def test_fix_mozilla_sdp_answer() -> None:
4545
"m=application 9 DTLS/SCTP 5000\r\n"
4646
"c=IN IP4 0.0.0.0\r\n"
4747
)
48-
expected_answer_sdp = (
48+
expected_firefox_answer_sdp = (
4949
"v=0\r\n"
5050
"o=- 0 2 IN IP4 127.0.0.1\r\n"
5151
"m=audio 19305 UDP/TLS/RTP/SAVPF 109\r\n"
@@ -65,6 +65,13 @@ def test_fix_mozilla_sdp_answer() -> None:
6565
"m=application 9 DTLS/SCTP 5000\r\n"
6666
"c=IN IP4 0.0.0.0\r\n"
6767
)
68+
69+
fixed_sdp = fix_sdp_answer(firefox_offer_sdp, answer_sdp)
70+
assert fixed_sdp == expected_firefox_answer_sdp
71+
72+
73+
def test_fix_chrome_sdp_answer() -> None:
74+
"""Test the fix in the SDP for Chrome."""
6875
chrome_offer_sdp = (
6976
"v=0\r\n"
7077
"o=- 6714414228100263102 2 IN IP4 127.0.0.1\r\n"
@@ -77,11 +84,49 @@ def test_fix_mozilla_sdp_answer() -> None:
7784
"m=application 9 UDP/DTLS/SCTP webrtc-datachannel\r\n"
7885
"c=IN IP4 0.0.0.0\r\n"
7986
)
80-
fixed_sdp = fix_mozilla_sdp_answer(firefox_offer_sdp, answer_sdp)
81-
assert fixed_sdp == expected_answer_sdp
87+
answer_sdp = (
88+
"v=0\r\n"
89+
"o=- 0 2 IN IP4 127.0.0.1\r\n"
90+
"m=audio 19305 UDP/TLS/RTP/SAVPF 109\r\n"
91+
"c=IN IP4 74.125.247.118\r\n"
92+
"a=rtcp:9 IN IP4 0.0.0.0\r\n"
93+
"a=candidate: 1 udp 2113939711 2001:4860:4864:4::118 19305 typ host generation 0\r\n"
94+
"a=candidate: 1 tcp 2113939710 2001:4860:4864:4::118 19305 typ host tcptype passive generation 0\r\n"
95+
"a=candidate: 1 ssltcp 2113939709 2001:4860:4864:4::118 443 typ host generation 0\r\n"
96+
"a=candidate: 1 udp 2113932031 74.125.247.118 19305 typ host generation 0\r\n"
97+
"a=candidate: 1 tcp 2113932030 74.125.247.118 19305 typ host tcptype passive generation 0\r\n"
98+
"a=candidate: 1 ssltcp 2113932029 74.125.247.118 443 typ host generation 0\r\n"
99+
"a=sendrecv\r\n"
100+
"m=video 9 UDP/TLS/RTP/SAVPF 126 127\r\n"
101+
"c=IN IP4 0.0.0.0\r\n"
102+
"a=rtcp:9 IN IP4 0.0.0.0\r\n"
103+
"a=sendrecv\r\n"
104+
"m=application 9 DTLS/SCTP 5000\r\n"
105+
"c=IN IP4 0.0.0.0\r\n"
106+
)
107+
expected_chrome_answer_sdp = (
108+
"v=0\r\n"
109+
"o=- 0 2 IN IP4 127.0.0.1\r\n"
110+
"m=audio 19305 UDP/TLS/RTP/SAVPF 109\r\n"
111+
"c=IN IP4 74.125.247.118\r\n"
112+
"a=rtcp:9 IN IP4 0.0.0.0\r\n"
113+
"a=candidate: 1 udp 2113939711 2001:4860:4864:4::118 19305 typ host generation 0\r\n"
114+
"a=candidate: 1 tcp 2113939710 2001:4860:4864:4::118 19305 typ host tcptype passive generation 0\r\n"
115+
"a=candidate: 1 ssltcp 2113939709 2001:4860:4864:4::118 443 typ host generation 0\r\n"
116+
"a=candidate: 1 udp 2113932031 74.125.247.118 19305 typ host generation 0\r\n"
117+
"a=candidate: 1 tcp 2113932030 74.125.247.118 19305 typ host tcptype passive generation 0\r\n"
118+
"a=candidate: 1 ssltcp 2113932029 74.125.247.118 443 typ host generation 0\r\n"
119+
"a=sendonly\r\n"
120+
"m=video 9 UDP/TLS/RTP/SAVPF 126 127\r\n"
121+
"c=IN IP4 0.0.0.0\r\n"
122+
"a=rtcp:9 IN IP4 0.0.0.0\r\n"
123+
"a=sendonly\r\n"
124+
"m=application 9 DTLS/SCTP 5000\r\n"
125+
"c=IN IP4 0.0.0.0\r\n"
126+
)
82127

83-
fixed_sdp = fix_mozilla_sdp_answer(chrome_offer_sdp, answer_sdp)
84-
assert fixed_sdp == answer_sdp
128+
fixed_sdp = fix_sdp_answer(chrome_offer_sdp, answer_sdp)
129+
assert fixed_sdp == expected_chrome_answer_sdp
85130

86131

87132
def test_get_media_direction() -> None:

0 commit comments

Comments
 (0)