@@ -54,6 +54,25 @@ private enum ConnectionState {
5454 }
5555}
5656
57+ private enum GatheringState {
58+ case new
59+ case inProgress
60+ case complete
61+
62+ init ? ( cValue: rtcGatheringState ) {
63+ switch cValue {
64+ case RTC_GATHERING_NEW:
65+ self = . new
66+ case RTC_GATHERING_INPROGRESS:
67+ self = . inProgress
68+ case RTC_GATHERING_COMPLETE:
69+ self = . complete
70+ default :
71+ return nil
72+ }
73+ }
74+ }
75+
5776private func makeEndpointUrl( url: String ) -> URL ? {
5877 guard var components = URLComponents ( string: url) else {
5978 return nil
@@ -361,6 +380,7 @@ private struct RtcTrackConfig {
361380
362381private protocol PeerConnectionDelegate : AnyObject {
363382 func peerConnectionOnConnectionStateChanged( state: ConnectionState )
383+ func peerConnectionOnGatheringStateChanged( state: GatheringState )
364384}
365385
366386private func toPeerConnection( pointer: UnsafeMutableRawPointer ? ) -> PeerConnection ? {
@@ -388,6 +408,9 @@ private final class PeerConnection {
388408 try checkOk ( rtcSetStateChangeCallback ( peerConnectionId) { _, state, pointer in
389409 toPeerConnection ( pointer: pointer) ? . handleStateChange ( state: state)
390410 } )
411+ try checkOk ( rtcSetGatheringStateChangeCallback ( peerConnectionId) { _, state, pointer in
412+ toPeerConnection ( pointer: pointer) ? . handleGatheringStateChange ( state: state)
413+ } )
391414 } catch {
392415 rtcDeletePeerConnection ( peerConnectionId)
393416 throw error
@@ -449,6 +472,13 @@ private final class PeerConnection {
449472 }
450473 delegate? . peerConnectionOnConnectionStateChanged ( state: state)
451474 }
475+
476+ private func handleGatheringStateChange( state: rtcGatheringState ) {
477+ guard let state = GatheringState ( cValue: state) else {
478+ return
479+ }
480+ delegate? . peerConnectionOnGatheringStateChanged ( state: state)
481+ }
452482}
453483
454484protocol WhipStreamDelegate : AnyObject {
@@ -528,8 +558,6 @@ final class WhipStream {
528558 )
529559 self . peerConnection = peerConnection
530560 try peerConnection. setLocalDescriptionOffer ( )
531- let offer = try peerConnection. createOffer ( )
532- sendOffer ( endpointUrl: endpointUrl, offer: offer)
533561 } catch {
534562 stopInternal ( reason: " WHIP start failed " )
535563 }
@@ -573,6 +601,28 @@ final class WhipStream {
573601 }
574602 }
575603
604+ private func handleGatheringStateChanged( state: GatheringState ) {
605+ guard let peerConnection, let endpointUrl else {
606+ return
607+ }
608+ logger. info ( " whip: Gathering state \( state) " )
609+ switch state {
610+ case . complete:
611+ guard !offerSent else {
612+ return
613+ }
614+ do {
615+ let offer = try peerConnection. createOffer ( )
616+ sendOffer ( endpointUrl: endpointUrl, offer: offer)
617+ offerSent = true
618+ } catch {
619+ stopInternal ( reason: " WHIP set offer failed " )
620+ }
621+ case . new, . inProgress:
622+ break
623+ }
624+ }
625+
576626 private func sendOffer( endpointUrl: URL , offer: String ) {
577627 var request = URLRequest ( url: endpointUrl)
578628 request. httpMethod = " POST "
@@ -706,6 +756,12 @@ extension WhipStream: PeerConnectionDelegate {
706756 self . handleConnectionStateChanged ( state: state)
707757 }
708758 }
759+
760+ fileprivate func peerConnectionOnGatheringStateChanged( state: GatheringState ) {
761+ whipQueue. async {
762+ self . handleGatheringStateChanged ( state: state)
763+ }
764+ }
709765}
710766
711767extension WhipStream : AudioEncoderDelegate {
0 commit comments