diff --git a/Sources/StreamVideo/WebRTC/v2/SFU/Extensions/Stream_Video_Sfu_Event_SfuEvent.OneOf_EventPayload+Payload.swift b/Sources/StreamVideo/WebRTC/v2/SFU/Extensions/Stream_Video_Sfu_Event_SfuEvent.OneOf_EventPayload+Payload.swift index cec830fb5..d36316b95 100644 --- a/Sources/StreamVideo/WebRTC/v2/SFU/Extensions/Stream_Video_Sfu_Event_SfuEvent.OneOf_EventPayload+Payload.swift +++ b/Sources/StreamVideo/WebRTC/v2/SFU/Extensions/Stream_Video_Sfu_Event_SfuEvent.OneOf_EventPayload+Payload.swift @@ -59,10 +59,10 @@ extension Stream_Video_Sfu_Event_SfuEvent.OneOf_EventPayload { return payload as? T case let .participantMigrationComplete(payload): return payload as? T - case let .codecNegotiationComplete(payload): - return payload as? T case let .changePublishOptions(payload): return payload as? T + case let .changePublishOptionsComplete(payload): + return payload as? T } } } diff --git a/Sources/StreamVideo/WebSockets/Events/Event.swift b/Sources/StreamVideo/WebSockets/Events/Event.swift index 25cc5dc87..97945e0d4 100644 --- a/Sources/StreamVideo/WebSockets/Events/Event.swift +++ b/Sources/StreamVideo/WebSockets/Events/Event.swift @@ -121,8 +121,8 @@ extension Stream_Video_Sfu_Event_SfuEvent.OneOf_EventPayload: Event { case .callEnded: return "callEnded" case .participantUpdated: return "participantUpdated" case .participantMigrationComplete: return "participantMigrationComplete" - case .codecNegotiationComplete: return "codecNegotiationComplete" case .changePublishOptions: return "changePublishOptions" + case .changePublishOptionsComplete: return "changePublishOptionsComplete" } } } diff --git a/Sources/StreamVideo/protobuf/sfu/event/events.pb.swift b/Sources/StreamVideo/protobuf/sfu/event/events.pb.swift index 8cb2f181b..d6aad4020 100644 --- a/Sources/StreamVideo/protobuf/sfu/event/events.pb.swift +++ b/Sources/StreamVideo/protobuf/sfu/event/events.pb.swift @@ -239,14 +239,13 @@ struct Stream_Video_Sfu_Event_SfuEvent { set {eventPayload = .participantMigrationComplete(newValue)} } - /// CodecNegotiationComplete is sent to signal the completion of a codec negotiation. - /// SDKs can safely stop previous transceivers - var codecNegotiationComplete: Stream_Video_Sfu_Event_CodecNegotiationComplete { + /// ChangePublishOptionsComplete is sent to signal the completion of a ChangePublishOptions request. + var changePublishOptionsComplete: Stream_Video_Sfu_Event_ChangePublishOptionsComplete { get { - if case .codecNegotiationComplete(let v)? = eventPayload {return v} - return Stream_Video_Sfu_Event_CodecNegotiationComplete() + if case .changePublishOptionsComplete(let v)? = eventPayload {return v} + return Stream_Video_Sfu_Event_ChangePublishOptionsComplete() } - set {eventPayload = .codecNegotiationComplete(newValue)} + set {eventPayload = .changePublishOptionsComplete(newValue)} } /// ChangePublishOptions is sent to signal the change in publish options such as a new codec or simulcast layers @@ -325,9 +324,8 @@ struct Stream_Video_Sfu_Event_SfuEvent { case participantUpdated(Stream_Video_Sfu_Event_ParticipantUpdated) /// ParticipantMigrationComplete is sent when the participant migration is complete case participantMigrationComplete(Stream_Video_Sfu_Event_ParticipantMigrationComplete) - /// CodecNegotiationComplete is sent to signal the completion of a codec negotiation. - /// SDKs can safely stop previous transceivers - case codecNegotiationComplete(Stream_Video_Sfu_Event_CodecNegotiationComplete) + /// ChangePublishOptionsComplete is sent to signal the completion of a ChangePublishOptions request. + case changePublishOptionsComplete(Stream_Video_Sfu_Event_ChangePublishOptionsComplete) /// ChangePublishOptions is sent to signal the change in publish options such as a new codec or simulcast layers case changePublishOptions(Stream_Video_Sfu_Event_ChangePublishOptions) @@ -421,8 +419,8 @@ struct Stream_Video_Sfu_Event_SfuEvent { guard case .participantMigrationComplete(let l) = lhs, case .participantMigrationComplete(let r) = rhs else { preconditionFailure() } return l == r }() - case (.codecNegotiationComplete, .codecNegotiationComplete): return { - guard case .codecNegotiationComplete(let l) = lhs, case .codecNegotiationComplete(let r) = rhs else { preconditionFailure() } + case (.changePublishOptionsComplete, .changePublishOptionsComplete): return { + guard case .changePublishOptionsComplete(let l) = lhs, case .changePublishOptionsComplete(let r) = rhs else { preconditionFailure() } return l == r }() case (.changePublishOptions, .changePublishOptions): return { @@ -459,7 +457,7 @@ struct Stream_Video_Sfu_Event_ChangePublishOptions { fileprivate var _publishOption: Stream_Video_Sfu_Models_PublishOption? = nil } -struct Stream_Video_Sfu_Event_CodecNegotiationComplete { +struct Stream_Video_Sfu_Event_ChangePublishOptionsComplete { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -1229,7 +1227,7 @@ struct Stream_Video_Sfu_Event_CallEnded { extension Stream_Video_Sfu_Event_SfuEvent: @unchecked Sendable {} extension Stream_Video_Sfu_Event_SfuEvent.OneOf_EventPayload: @unchecked Sendable {} extension Stream_Video_Sfu_Event_ChangePublishOptions: @unchecked Sendable {} -extension Stream_Video_Sfu_Event_CodecNegotiationComplete: @unchecked Sendable {} +extension Stream_Video_Sfu_Event_ChangePublishOptionsComplete: @unchecked Sendable {} extension Stream_Video_Sfu_Event_ParticipantMigrationComplete: @unchecked Sendable {} extension Stream_Video_Sfu_Event_PinsChanged: @unchecked Sendable {} extension Stream_Video_Sfu_Event_Error: @unchecked Sendable {} @@ -1293,7 +1291,7 @@ extension Stream_Video_Sfu_Event_SfuEvent: SwiftProtobuf.Message, SwiftProtobuf. 23: .standard(proto: "call_ended"), 24: .standard(proto: "participant_updated"), 25: .standard(proto: "participant_migration_complete"), - 26: .standard(proto: "codec_negotiation_complete"), + 26: .standard(proto: "change_publish_options_complete"), 27: .standard(proto: "change_publish_options"), ] @@ -1577,16 +1575,16 @@ extension Stream_Video_Sfu_Event_SfuEvent: SwiftProtobuf.Message, SwiftProtobuf. } }() case 26: try { - var v: Stream_Video_Sfu_Event_CodecNegotiationComplete? + var v: Stream_Video_Sfu_Event_ChangePublishOptionsComplete? var hadOneofValue = false if let current = self.eventPayload { hadOneofValue = true - if case .codecNegotiationComplete(let m) = current {v = m} + if case .changePublishOptionsComplete(let m) = current {v = m} } try decoder.decodeSingularMessageField(value: &v) if let v = v { if hadOneofValue {try decoder.handleConflictingOneOf()} - self.eventPayload = .codecNegotiationComplete(v) + self.eventPayload = .changePublishOptionsComplete(v) } }() case 27: try { @@ -1697,8 +1695,8 @@ extension Stream_Video_Sfu_Event_SfuEvent: SwiftProtobuf.Message, SwiftProtobuf. guard case .participantMigrationComplete(let v)? = self.eventPayload else { preconditionFailure() } try visitor.visitSingularMessageField(value: v, fieldNumber: 25) }() - case .codecNegotiationComplete?: try { - guard case .codecNegotiationComplete(let v)? = self.eventPayload else { preconditionFailure() } + case .changePublishOptionsComplete?: try { + guard case .changePublishOptionsComplete(let v)? = self.eventPayload else { preconditionFailure() } try visitor.visitSingularMessageField(value: v, fieldNumber: 26) }() case .changePublishOptions?: try { @@ -1753,8 +1751,8 @@ extension Stream_Video_Sfu_Event_ChangePublishOptions: SwiftProtobuf.Message, Sw } } -extension Stream_Video_Sfu_Event_CodecNegotiationComplete: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { - static let protoMessageName: String = _protobuf_package + ".CodecNegotiationComplete" +extension Stream_Video_Sfu_Event_ChangePublishOptionsComplete: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = _protobuf_package + ".ChangePublishOptionsComplete" static let _protobuf_nameMap = SwiftProtobuf._NameMap() mutating func decodeMessage(decoder: inout D) throws { @@ -1766,7 +1764,7 @@ extension Stream_Video_Sfu_Event_CodecNegotiationComplete: SwiftProtobuf.Message try unknownFields.traverse(visitor: &visitor) } - static func ==(lhs: Stream_Video_Sfu_Event_CodecNegotiationComplete, rhs: Stream_Video_Sfu_Event_CodecNegotiationComplete) -> Bool { + static func ==(lhs: Stream_Video_Sfu_Event_ChangePublishOptionsComplete, rhs: Stream_Video_Sfu_Event_ChangePublishOptionsComplete) -> Bool { if lhs.unknownFields != rhs.unknownFields {return false} return true } diff --git a/Sources/StreamVideo/protobuf/sfu/models/models.pb.swift b/Sources/StreamVideo/protobuf/sfu/models/models.pb.swift index d1bbe6f94..9aeea3a74 100644 --- a/Sources/StreamVideo/protobuf/sfu/models/models.pb.swift +++ b/Sources/StreamVideo/protobuf/sfu/models/models.pb.swift @@ -931,13 +931,16 @@ struct Stream_Video_Sfu_Models_VideoLayer { fileprivate var _videoDimension: Stream_Video_Sfu_Models_VideoDimension? = nil } +/// PublishOption represents the configuration options for publishing a track. struct Stream_Video_Sfu_Models_PublishOption { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. + /// The type of the track being published (e.g., video, screenshare). var trackType: Stream_Video_Sfu_Models_TrackType = .unspecified + /// The codec to be used for encoding the track (e.g., VP8, VP9, H264). var codec: Stream_Video_Sfu_Models_Codec { get {return _codec ?? Stream_Video_Sfu_Models_Codec()} set {_codec = newValue} @@ -947,19 +950,46 @@ struct Stream_Video_Sfu_Models_PublishOption { /// Clears the value of `codec`. Subsequent reads from it will return its default value. mutating func clearCodec() {self._codec = nil} + /// The target bitrate for the published track, in bits per second. var bitrate: Int32 = 0 + /// The target frames per second (FPS) for video encoding. var fps: Int32 = 0 + /// The maximum number of spatial layers to send. + /// - For SVC (e.g., VP9), spatial layers downscale by a factor of 2: + /// - 1 layer: full resolution + /// - 2 layers: full resolution + half resolution + /// - 3 layers: full resolution + half resolution + quarter resolution + /// - For non-SVC codecs (e.g., VP8/H264), this determines the number of + /// encoded resolutions (e.g., quarter, half, full) sent for simulcast. var maxSpatialLayers: Int32 = 0 + /// The maximum number of temporal layers for scalable video coding (SVC). + /// Temporal layers allow varying frame rates for different bandwidths. var maxTemporalLayers: Int32 = 0 + /// The dimensions of the video (e.g., width and height in pixels). + /// Spatial layers are based on this base resolution. For example, if the base + /// resolution is 1280x720: + /// - Full resolution (1 layer) = 1280x720 + /// - Half resolution (2 layers) = 640x360 + /// - Quarter resolution (3 layers) = 320x180 + var videoDimension: Stream_Video_Sfu_Models_VideoDimension { + get {return _videoDimension ?? Stream_Video_Sfu_Models_VideoDimension()} + set {_videoDimension = newValue} + } + /// Returns true if `videoDimension` has been explicitly set. + var hasVideoDimension: Bool {return self._videoDimension != nil} + /// Clears the value of `videoDimension`. Subsequent reads from it will return its default value. + mutating func clearVideoDimension() {self._videoDimension = nil} + var unknownFields = SwiftProtobuf.UnknownStorage() init() {} fileprivate var _codec: Stream_Video_Sfu_Models_Codec? = nil + fileprivate var _videoDimension: Stream_Video_Sfu_Models_VideoDimension? = nil } struct Stream_Video_Sfu_Models_Codec { @@ -1829,6 +1859,7 @@ extension Stream_Video_Sfu_Models_PublishOption: SwiftProtobuf.Message, SwiftPro 4: .same(proto: "fps"), 5: .standard(proto: "max_spatial_layers"), 6: .standard(proto: "max_temporal_layers"), + 7: .standard(proto: "video_dimension"), ] mutating func decodeMessage(decoder: inout D) throws { @@ -1843,6 +1874,7 @@ extension Stream_Video_Sfu_Models_PublishOption: SwiftProtobuf.Message, SwiftPro case 4: try { try decoder.decodeSingularInt32Field(value: &self.fps) }() case 5: try { try decoder.decodeSingularInt32Field(value: &self.maxSpatialLayers) }() case 6: try { try decoder.decodeSingularInt32Field(value: &self.maxTemporalLayers) }() + case 7: try { try decoder.decodeSingularMessageField(value: &self._videoDimension) }() default: break } } @@ -1871,6 +1903,9 @@ extension Stream_Video_Sfu_Models_PublishOption: SwiftProtobuf.Message, SwiftPro if self.maxTemporalLayers != 0 { try visitor.visitSingularInt32Field(value: self.maxTemporalLayers, fieldNumber: 6) } + try { if let v = self._videoDimension { + try visitor.visitSingularMessageField(value: v, fieldNumber: 7) + } }() try unknownFields.traverse(visitor: &visitor) } @@ -1881,6 +1916,7 @@ extension Stream_Video_Sfu_Models_PublishOption: SwiftProtobuf.Message, SwiftPro if lhs.fps != rhs.fps {return false} if lhs.maxSpatialLayers != rhs.maxSpatialLayers {return false} if lhs.maxTemporalLayers != rhs.maxTemporalLayers {return false} + if lhs._videoDimension != rhs._videoDimension {return false} if lhs.unknownFields != rhs.unknownFields {return false} return true }