diff --git a/python-webrtc/cpp/src/interfaces/rtc_peer_connection.cpp b/python-webrtc/cpp/src/interfaces/rtc_peer_connection.cpp index 1ea15b8..07562cc 100644 --- a/python-webrtc/cpp/src/interfaces/rtc_peer_connection.cpp +++ b/python-webrtc/cpp/src/interfaces/rtc_peer_connection.cpp @@ -81,6 +81,9 @@ namespace python_webrtc { .def("getTransceivers", &RTCPeerConnection::GetTransceivers) .def("getSenders", &RTCPeerConnection::GetSenders) .def("getReceivers", &RTCPeerConnection::GetReceivers) + .def_property_readonly("sctp", &RTCPeerConnection::GetSctp) + .def("restartIce", &RTCPeerConnection::RestartIce) + .def("removeTrack", &RTCPeerConnection::RemoveTrack) .def("close", &RTCPeerConnection::Close); } @@ -285,6 +288,35 @@ namespace python_webrtc { return receivers; } + std::optional RTCPeerConnection::GetSctp() { + if (_jinglePeerConnection && _jinglePeerConnection->GetSctpTransport()) { + return RTCSctpTransport::holder()->GetOrCreate(_factory, _jinglePeerConnection->GetSctpTransport()); + } + + return {}; + } + + void RTCPeerConnection::RestartIce() { + if (_jinglePeerConnection) { + _jinglePeerConnection->RestartIce(); + } + } + + void RTCPeerConnection::RemoveTrack(RTCRtpSender &sender) { + if (!_jinglePeerConnection) { + throw PythonWebRTCException("Cannot remove track; RTCPeerConnection is closed"); + } + + auto senders = _jinglePeerConnection->GetSenders(); + if (std::find(senders.begin(), senders.end(), sender.sender()) == senders.end()) { + throw PythonWebRTCException("Cannot remove track because sender not found in senders of PeerConnection"); + } + + if (!_jinglePeerConnection->RemoveTrack(sender.sender())) { + throw PythonWebRTCException("Cannot remove track"); + } + } + void RTCPeerConnection::Close() { if (_jinglePeerConnection) { _jinglePeerConnection->Close(); diff --git a/python-webrtc/cpp/src/interfaces/rtc_peer_connection.h b/python-webrtc/cpp/src/interfaces/rtc_peer_connection.h index b4e31c5..1161f5a 100644 --- a/python-webrtc/cpp/src/interfaces/rtc_peer_connection.h +++ b/python-webrtc/cpp/src/interfaces/rtc_peer_connection.h @@ -20,6 +20,7 @@ #include "media_stream.h" #include "rtc_rtp_sender.h" #include "rtc_rtp_transceiver.h" +#include "rtc_sctp_transport.h" namespace webrtc { struct PeerConnectionDependencies; @@ -65,6 +66,12 @@ namespace python_webrtc { std::vector GetReceivers(); + std::optional GetSctp(); + + void RestartIce(); + + void RemoveTrack(RTCRtpSender &); + void SaveLastSdp(const RTCSessionDescriptionInit &lastSdp); void Close(); diff --git a/python-webrtc/python/test.py b/python-webrtc/python/test.py index ebb0029..41d7f0e 100644 --- a/python-webrtc/python/test.py +++ b/python-webrtc/python/test.py @@ -59,23 +59,30 @@ async def main(): # transport = sender.transport # transceivers = pc.get_transceivers() - params = webrtc.RtpEncodingParameters( - max_bitrate=1234, max_framerate=20, rid="lolkek", scale_resolution_down_by=2.0 - ) - init = webrtc.RtpTransceiverInit( - direction=webrtc.TransceiverDirection.recvonly, send_encodings=[params], streams=[stream] - ) + # params = webrtc.RtpEncodingParameters( + # max_bitrate=1234, max_framerate=20, rid="lolkek", scale_resolution_down_by=2.0 + # ) + # init = webrtc.RtpTransceiverInit( + # direction=webrtc.TransceiverDirection.recvonly, send_encodings=[params], streams=[stream] + # ) + # + # transceiver = pc.add_transceiver(webrtc.MediaType.audio) + # transceiver_with_params = pc.add_transceiver(webrtc.MediaType.audio, init) + # + # transceiver_by_track = pc.add_transceiver(stream.get_tracks()[0]) + # transceiver_by_track_with_params = pc.add_transceiver(stream.get_tracks()[0], init) + # + # local_sdp = await pc.create_offer() + # await pc.set_local_description(local_sdp) - transceiver = pc.add_transceiver(webrtc.MediaType.audio) - transceiver_with_params = pc.add_transceiver(webrtc.MediaType.audio, init) + transceivers = pc.get_transceivers() - transceiver_by_track = pc.add_transceiver(stream.get_tracks()[0]) - transceiver_by_track_with_params = pc.add_transceiver(stream.get_tracks()[0], init) + pc.restart_ice() - local_sdp = await pc.create_offer() - await pc.set_local_description(local_sdp) + sender = pc.add_track(stream.get_tracks()[0], stream) + pc.remove_track(sender) - transceivers = pc.get_transceivers() + print(pc.sctp) idle() diff --git a/python-webrtc/python/webrtc/interfaces/rtc_peer_connection.py b/python-webrtc/python/webrtc/interfaces/rtc_peer_connection.py index 27ca490..0cf964f 100644 --- a/python-webrtc/python/webrtc/interfaces/rtc_peer_connection.py +++ b/python-webrtc/python/webrtc/interfaces/rtc_peer_connection.py @@ -185,10 +185,35 @@ def get_receivers(self) -> List['webrtc.RTCRtpReceiver']: return RTCRtpReceiver._wrap_many(self._native_obj.getReceivers()) + def remove_track(self, sender: 'webrtc.RTCRtpSender') -> None: + """Tells the local end of the connection to stop sending media from the specified track, without + actually removing the corresponding :obj:`webrtc.RTCRtpSender` from the list of senders as reported + by :attr:`get_senders``. If the track is already stopped, or is not in the connection's senders list, + this method has no effect.""" + return self._native_obj.removeTrack(sender._native_obj) + + def restart_ice(self) -> None: + """Allows to easily request that ICE candidate gathering be redone on both ends of the connection. + This simplifies the process by allowing the same method to be used by either the caller or the receiver + to trigger an ICE restart.""" + return self._native_obj.restartIce() + def close(self): """Closes the current peer connection.""" return self._native_obj.close() + @property + def sctp(self) -> Optional['webrtc.RTCSctpTransport']: + """:obj:`webrtc.RTCSctpTransport`, optional: An object describing the SCTP transport layer over which SCTP + data is being sent and received. If SCTP hasn't been negotiated, this value is :obj:`None`""" + from webrtc import RTCSctpTransport + + sctp = self._native_obj.sctp + if sctp: + return RTCSctpTransport._wrap(sctp) + + return None + #: Alias for :attr:`create_offer` createOffer = create_offer #: Alias for :attr:`create_answer` @@ -207,3 +232,7 @@ def close(self): getSenders = get_senders #: Alias for :attr:`get_receivers` getReceivers = get_receivers + #: Alias for :attr:`remove_track` + removeTrack = remove_track + #: Alias for :attr:`restart_ice` + restartIce = restart_ice