From 53926976f64093ee46e5e8baa56e032ce331d3f3 Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Thu, 23 Mar 2023 13:16:22 -0400 Subject: [PATCH] MT#56447 add tests for mute/unmute Change-Id: If184df025eef6d9a398fb9d946111e95ffa8d4ea --- t/auto-daemon-tests-websocket.py | 491 +++++++++++++++++++++++++++++++ 1 file changed, 491 insertions(+) diff --git a/t/auto-daemon-tests-websocket.py b/t/auto-daemon-tests-websocket.py index 4385124bc..a4e9f7983 100644 --- a/t/auto-daemon-tests-websocket.py +++ b/t/auto-daemon-tests-websocket.py @@ -2777,6 +2777,497 @@ class TestVideoroom(unittest.TestCase): pub_sock_2.close() self.destroyVideoroom(token, session_1, control_handle, room) + def testVideoroomMute(self): + (token, session, control_handle, room) = self.startVideoroom() + + pub_handle_1 = self.createHandle(token, session) + self.assertNotEqual(pub_handle_1, control_handle) + + # create feed for publisher #1 + feed_1 = self.createPublisher(token, session, room, pub_handle_1) + self.assertNotEqual(feed_1, control_handle) + + pub_sock_audio = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + pub_sock_audio.settimeout(0.1) + pub_sock_audio.bind(("203.0.113.2", 31000)) + + pub_sock_video = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + pub_sock_video.settimeout(0.1) + pub_sock_video.bind(("203.0.113.2", 31100)) + + # configure publisher feed #1 + eventloop.run_until_complete( + testIOJanus( + self, + { + "janus": "message", + "body": { + "request": "configure", + "room": room, + "feed": feed_1, + "data": False, + "audio": True, + "video": True, + }, + "jsep": { + "type": "offer", + "sdp": ( + "v=0\r\n" + "o=x 123 123 IN IP4 203.0.113.2\r\n" + "c=IN IP4 203.0.113.2\r\n" + "s=foobar\r\n" + "t=0 0\r\n" + "m=audio 31000 RTP/AVP 96 8 0\r\n" + "a=rtpmap:96 opus/48000/2\r\n" + "a=sendonly\r\n" + "a=mid:a\r\n" + "m=video 31100 RTP/AVP 97\r\n" + "a=rtpmap:97 VP9/90000\r\n" + "a=sendonly\r\n" + "a=mid:v\r\n" + ), + }, + "handle_id": pub_handle_1, + "session_id": session, + "token": token, + }, + ) + ) + # ack is received first + self.assertEqual(self._res, {"janus": "ack", "session_id": session}) + # followed by the event notification + eventloop.run_until_complete(testIJanus(self)) + sdp = self._res["jsep"]["sdp"] + self.assertIsInstance(sdp, str) + + match_re = re.compile( + "^v=0\r\n" + "o=- \d+ \d+ IN IP4 203.0.113.1\r\n" + "s=rtpengine.*?\r\n" + "t=0 0\r\n" + "m=audio (\d+) RTP/AVP 96\r\n" + "c=IN IP4 203.0.113.1\r\n" + "a=mid:a\r\n" + "a=rtpmap:96 opus/48000/2\r\n" + "a=recvonly\r\n" + "a=rtcp:\d+\r\n" + "m=video (\d+) RTP/AVP 97\r\n" + "c=IN IP4 203.0.113.1\r\n" + "a=mid:v\r\n" + "a=rtpmap:97 VP9/90000\r\n" + "a=recvonly\r\n" + "a=rtcp:\d+\r\n$", + re.DOTALL, + ) + self.assertRegex(sdp, match_re) + matches = match_re.search(sdp) + pub_port_audio = int(matches.group(1)) + pub_port_video = int(matches.group(2)) + + self.assertEqual( + self._res, + { + "janus": "event", + "session_id": session, + "sender": pub_handle_1, + "plugindata": { + "plugin": "janus.plugin.videoroom", + "data": { + "videoroom": "event", + "room": room, + "configured": "ok", + "audio_codec": "opus", + "video_codec": "VP9", + "streams": [ + { + "codec": "opus", + "mid": "a", + "mindex": 0, + "type": "audio", + }, + { + "codec": "VP9", + "mid": "v", + "mindex": 1, + "type": "video", + }, + ], + }, + }, + "jsep": {"type": "answer", "sdp": sdp}, + }, + ) + + pub_sock_audio.connect(("203.0.113.1", pub_port_audio)) + pub_sock_video.connect(("203.0.113.1", pub_port_video)) + + # send fake RTP to trigger event + m = pub_sock_audio.send( + b"\x80\x60\x12\x34\x43\x32\x12\x45\x65\x45\x34\x23\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + ) + + # wait for webrtcup event + eventloop.run_until_complete(testIJson(self)) + self.assertEqual( + self._res, + {"janus": "webrtcup", "session_id": session, "sender": pub_handle_1}, + ) + + # wait for audio media + eventloop.run_until_complete(testIJson(self)) + self.assertEqual( + self._res, + { + "janus": "media", + "session_id": session, + "sender": pub_handle_1, + "type": "audio", + "mid": "a", + "receiving": True, + }, + ) + + # repeat for video + m = pub_sock_video.send( + b"\x80\x61\x12\x34\x43\x32\x12\x45\x65\x45\x34\x23\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + ) + + eventloop.run_until_complete(testIJson(self)) + self.assertEqual( + self._res, + { + "janus": "media", + "session_id": session, + "sender": pub_handle_1, + "type": "video", + "mid": "v", + "receiving": True, + }, + ) + + sub_sock_audio = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + sub_sock_audio.settimeout(0.1) + sub_sock_audio.bind(("203.0.113.3", 31010)) + + sub_sock_video = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + sub_sock_video.settimeout(0.1) + sub_sock_video.bind(("203.0.113.3", 31110)) + + sub_handle_1 = self.createHandle(token, session) + self.assertNotEqual(sub_handle_1, pub_handle_1) + self.assertNotEqual(sub_handle_1, control_handle) + + # subscriber #1 joins publisher #1 + eventloop.run_until_complete( + testIOJanus( + self, + { + "janus": "message", + "body": { + "request": "join", + "ptype": "subscriber", + "plain": True, + "room": room, + "feed": feed_1, + }, + "handle_id": sub_handle_1, + "session_id": session, + "token": token, + }, + ) + ) + # ack is received first + self.assertEqual(self._res, {"janus": "ack", "session_id": session}) + # followed by the attached event + eventloop.run_until_complete(testIJanus(self)) + self.assertEqual(feed_1, self._res["plugindata"]["data"]["id"]) + self.assertNotEqual(feed_1, control_handle) + self.assertNotEqual(feed_1, session) + self.assertNotEqual(feed_1, room) + self.assertNotEqual(feed_1, pub_handle_1) + self.assertNotEqual(feed_1, sub_handle_1) + sdp = self._res["jsep"]["sdp"] + self.assertIsInstance(sdp, str) + + match_re = re.compile( + "^v=0\r\n" + "o=x 123 123 IN IP4 203.0.113.2\r\n" + "c=IN IP4 203.0.113.1\r\n" + "s=foobar\r\n" + "t=0 0\r\n" + "m=audio (\d+) RTP/AVP 96\r\n" + "a=mid:a\r\n" + "a=rtpmap:96 opus/48000/2\r\n" + "a=sendonly\r\n" + "a=rtcp:\d+\r\n" + "m=video (\d+) RTP/AVP 97\r\n" + "a=mid:v\r\n" + "a=rtpmap:97 VP9/90000\r\n" + "a=sendonly\r\n" + "a=rtcp:\d+\r\n$", + re.DOTALL, + ) + self.assertRegex(sdp, match_re) + matches = match_re.search(sdp) + sub_port_audio = int(matches.group(1)) + sub_port_video = int(matches.group(2)) + + self.assertEqual( + self._res, + { + "janus": "event", + "session_id": session, + "sender": sub_handle_1, + "plugindata": { + "plugin": "janus.plugin.videoroom", + "data": { + "videoroom": "attached", + "room": room, + "id": feed_1, + }, + }, + "jsep": {"type": "offer", "sdp": sdp}, + }, + ) + + # subscriber #1 answer + eventloop.run_until_complete( + testIOJanus( + self, + { + "janus": "message", + "body": {"request": "start", "room": room, "feed": feed_1}, + "jsep": { + "type": "answer", + "sdp": ( + "v=0\r\n" + "o=x 123 123 IN IP4 203.0.113.2\r\n" + "c=IN IP4 203.0.113.3\r\n" + "s=foobar\r\n" + "t=0 0\r\n" + "m=audio 31010 RTP/AVP 96\r\n" + "a=rtpmap:96 opus/48000/2\r\n" + "a=mid:a\r\n" + "a=recvonly\r\n" + "m=video 31110 RTP/AVP 97\r\n" + "a=rtpmap:97 VP9/90000\r\n" + "a=mid:v\r\n" + "a=recvonly\r\n" + ), + }, + "handle_id": sub_handle_1, + "session_id": session, + "token": token, + }, + ) + ) + # ack is received first + self.assertEqual(self._res, {"janus": "ack", "session_id": session}) + # followed by the attached event + eventloop.run_until_complete(testIJanus(self)) + self.assertEqual( + self._res, + { + "janus": "event", + "session_id": session, + "sender": sub_handle_1, + "plugindata": { + "plugin": "janus.plugin.videoroom", + "data": { + "videoroom": "event", + "started": "ok", + "room": room, + }, + }, + }, + ) + + sub_sock_audio.connect(("203.0.113.1", sub_port_audio)) + sub_sock_video.connect(("203.0.113.1", sub_port_video)) + + # check forwarding + m = pub_sock_audio.send( + b"\x80\x60\x12\x34\x43\x32\x12\x45\x65\x45\x34\x23\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + ) + m = pub_sock_video.send( + b"\x80\x61\x12\x34\x43\x32\x12\x45\x65\x45\x34\x23\x00\x00\x20\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + ) + + m = sub_sock_audio.recv(1000) + self.assertEqual( + m, + b"\x80\x60\x12\x34\x43\x32\x12\x45\x65\x45\x34\x23\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + ) + + m = sub_sock_video.recv(1000) + self.assertEqual( + m, + b"\x80\x61\x12\x34\x43\x32\x12\x45\x65\x45\x34\x23\x00\x00\x20\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + ) + + # mute audio + eventloop.run_until_complete( + testIOJanus( + self, + { + "janus": "message", + "body": { + "request": "configure", + "room": room, + "feed": feed_1, + "data": False, + "audio": False, + "video": True, + }, + "handle_id": pub_handle_1, + "session_id": session, + "token": token, + }, + ) + ) + # ack is received first + self.assertEqual(self._res, {"janus": "ack", "session_id": session}) + # followed by the event notification + eventloop.run_until_complete(testIJanus(self)) + + self.assertEqual( + self._res, + { + "janus": "event", + "session_id": session, + "sender": pub_handle_1, + "plugindata": { + "plugin": "janus.plugin.videoroom", + "data": { + "videoroom": "event", + "room": room, + "configured": "ok", + "audio_codec": "opus", + "video_codec": "VP9", + "streams": [ + { + "codec": "opus", + "mid": "a", + "mindex": 0, + "type": "audio", + }, + { + "codec": "VP9", + "mid": "v", + "mindex": 1, + "type": "video", + }, + ], + }, + }, + }, + ) + + # check forwarding + m = pub_sock_audio.send( + b"\x80\x60\x12\x34\x43\x32\x12\x45\x65\x45\x34\x23\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + ) + m = pub_sock_video.send( + b"\x80\x61\x12\x34\x43\x32\x12\x45\x65\x45\x34\x23\x00\x00\x20\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + ) + + m = None + try: + m = sub_sock_audio.recv(1000) + except (TimeoutError, socket.timeout): + pass + self.assertIsNone(m) + + m = sub_sock_video.recv(1000) + self.assertEqual( + m, + b"\x80\x61\x12\x34\x43\x32\x12\x45\x65\x45\x34\x23\x00\x00\x20\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + ) + + # unmute audio + eventloop.run_until_complete( + testIOJanus( + self, + { + "janus": "message", + "body": { + "request": "configure", + "room": room, + "feed": feed_1, + "data": False, + "audio": True, + "video": True, + }, + "handle_id": pub_handle_1, + "session_id": session, + "token": token, + }, + ) + ) + # ack is received first + self.assertEqual(self._res, {"janus": "ack", "session_id": session}) + # followed by the event notification + eventloop.run_until_complete(testIJanus(self)) + + self.assertEqual( + self._res, + { + "janus": "event", + "session_id": session, + "sender": pub_handle_1, + "plugindata": { + "plugin": "janus.plugin.videoroom", + "data": { + "videoroom": "event", + "room": room, + "configured": "ok", + "audio_codec": "opus", + "video_codec": "VP9", + "streams": [ + { + "codec": "opus", + "mid": "a", + "mindex": 0, + "type": "audio", + }, + { + "codec": "VP9", + "mid": "v", + "mindex": 1, + "type": "video", + }, + ], + }, + }, + }, + ) + + # check forwarding + m = pub_sock_audio.send( + b"\x80\x60\x12\x34\x43\x32\x12\x45\x65\x45\x34\x23\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + ) + m = pub_sock_video.send( + b"\x80\x61\x12\x34\x43\x32\x12\x45\x65\x45\x34\x23\x00\x00\x20\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + ) + + m = sub_sock_audio.recv(1000) + self.assertEqual( + m, + b"\x80\x60\x12\x34\x43\x32\x12\x45\x65\x45\x34\x23\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + ) + + m = sub_sock_video.recv(1000) + self.assertEqual( + m, + b"\x80\x61\x12\x34\x43\x32\x12\x45\x65\x45\x34\x23\x00\x00\x20\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + ) + + self.destroyVideoroom(token, session, control_handle, room) + pub_sock_audio.close() + pub_sock_video.close() + sub_sock_audio.close() + sub_sock_video.close() + if __name__ == "__main__": eventloop = asyncio.new_event_loop()