Skip to content

Commit

Permalink
Codec negotiation (#606)
Browse files Browse the repository at this point in the history
  • Loading branch information
ipavlidakis authored Jan 14, 2025
1 parent a8008c0 commit 86f2afb
Show file tree
Hide file tree
Showing 193 changed files with 12,087 additions and 4,591 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
### ✅ Added
- CallKit availability policies allows you to control wether `Callkit` should be enabled/disabled based on different rules [#611](https://github.com/GetStream/stream-video-swift/pull/611)
- Support for setting a ringtone for CallKit calls [#628](https://github.com/GetStream/stream-video-swift/pull/628)
- Codec negotiation during calls (#606)(https://github.com/GetStream/stream-video-swift/pull/606)
- When moving to background/foreground while your video is active, if the device doesn't support [AVCaptureSession.isMultitaskingCameraAccessSupported](https://developer.apple.com/documentation/avfoundation/avcapturesession/ismultitaskingcameraaccesssupported) the SDK will mute/unmute the track to ensure that other participants have some feedback from your track. [#633](https://github.com/GetStream/stream-video-swift/pull/633)

### 🐞 Fixed
- By observing the `CallKitPushNotificationAdapter.deviceToken` you will be notified with an empty `deviceToken` value, once the object unregister push notifications. [#608](https://github.com/GetStream/stream-video-swift/pull/608)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,10 @@ final class OSLogDestination: BaseLogDestination {
extendedDetails += "[\(logDetails.functionName)] "
}

let extendedMessage = "\(extendedDetails)> \(logDetails.message)"
var extendedMessage = "\(extendedDetails)> \(logDetails.message)"
if let error = logDetails.error {
extendedMessage += "[Error: \(error)]"
}
let formattedMessage = LogConfig
.formatters
.reduce(extendedMessage) { $1.format(logDetails: logDetails, message: $0) }
Expand Down
4 changes: 1 addition & 3 deletions DemoApp/Sources/Controls/DemoControls.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,7 @@ struct AppControlsWithChat: View {

var body: some View {
HStack {
if viewModel.callParticipants.count > 1 {
MoreControlsIconView(viewModel: viewModel)
}
MoreControlsIconView(viewModel: viewModel)

#if !targetEnvironment(simulator)
if !ProcessInfo.processInfo.isiOSAppOnMac {
Expand Down
31 changes: 20 additions & 11 deletions DemoApp/Sources/Views/StatsView/DemoStatsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -85,17 +85,7 @@ struct DemoStatsView: View {
viewModel,
title: "PUBLISH RESOLUTION",
value: "none",
titleTransformer: { report in
let codec = report?
.publisherBaseStats
.last?
.codec
if let codec = codec?.split(separator: "/").last {
return "PUBLISH RESOLUTION(\(codec))"
} else {
return "PUBLISH RESOLUTION"
}
},
titleTransformer: { publishQualityFormatter($0) },
valueTransformer: { resolutionFormatter(from: $0?.publisherStats) }
)
} _: {
Expand Down Expand Up @@ -164,6 +154,25 @@ struct DemoStatsView: View {
}
}

private func publishQualityFormatter(
_ report: CallStatsReport?
) -> String {
let activeCodecs = report?
.publisherBaseStats
.filter { $0.framesPerSecond > 0 }
.compactMap(\.codec)

Check failure on line 163 in DemoApp/Sources/Views/StatsView/DemoStatsView.swift

View workflow job for this annotation

GitHub Actions / Start new release

key path value type 'String' cannot be converted to contextual type 'String?'
.compactMap { $0.split(separator: "/").last }
let uniqueActiveCodecs = Set(activeCodecs ?? [])
.sorted()
.joined(separator: ",")

guard !uniqueActiveCodecs.isEmpty else {
return "PUBLISH RESOLUTION"
}

return "PUBLISH RESOLUTION(\(uniqueActiveCodecs))"
}

private func resolutionFormatter(
from report: AggregatedStatsReport?
) -> String {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ struct DemoWaitingLocalUserView<Factory: DemoAppViewFactory>: View {
.navigationViewStyle(.stack)
}
}
.presentsMoreControls(viewModel: viewModel)
.alignedToReadableContentGuide()
.padding(.bottom)
} else {
Expand Down
58 changes: 58 additions & 0 deletions Sources/StreamVideo/Models/AudioCodec.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
//
// Copyright © 2025 Stream.io Inc. All rights reserved.
//

import Foundation
import StreamWebRTC

/// Represents different audio codecs.
public enum AudioCodec: String, CustomStringConvertible, Sendable {
case opus
case red
case unknown

/// Returns the raw value of the codec, which corresponds to its name.
public var description: String {
rawValue
}

/// Initializes an `AudioCodec` instance from WebRTC codec parameters.
///
/// This initializer maps a WebRTC codec (`RTCRtpCodecParameters`) to the
/// corresponding `AudioCodec` value. If the codec name matches `opus` or
/// `red`, the respective case is assigned; otherwise, it defaults to
/// `.unknown`.
///
/// - Parameter source: The `RTCRtpCodecParameters` object containing codec
/// details such as the codec name.
init(_ source: RTCRtpCodecParameters) {
switch source.name.lowercased() {
case AudioCodec.opus.rawValue:
self = .opus
case AudioCodec.red.rawValue:
self = .red
default:
self = .unknown
}
}

/// Initializes an `AudioCodec` instance from SFU codec model parameters.
///
/// This initializer maps an SFU codec model (`Stream_Video_Sfu_Models_Codec`)
/// to the corresponding `AudioCodec` value. If the codec name matches `opus`
/// or `red`, the respective case is assigned; otherwise, it defaults to
/// `.unknown`.
///
/// - Parameter source: The `Stream_Video_Sfu_Models_Codec` object containing
/// codec details such as the codec name.
init(_ source: Stream_Video_Sfu_Models_Codec) {
switch source.name.lowercased() {
case AudioCodec.opus.rawValue:
self = .opus
case AudioCodec.red.rawValue:
self = .red
default:
self = .unknown
}
}
}
26 changes: 26 additions & 0 deletions Sources/StreamVideo/Models/CallParticipant.swift
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,32 @@ public struct CallParticipant: Identifiable, Sendable, Hashable {
)
}

public func withUpdated(trackLookupPrefix: String) -> CallParticipant {
CallParticipant(
id: id,
userId: userId,
roles: roles,
name: name,
profileImageURL: profileImageURL,
trackLookupPrefix: trackLookupPrefix,
hasVideo: hasVideo,
hasAudio: hasAudio,
isScreenSharing: isScreensharing,
showTrack: showTrack,
track: track,
trackSize: trackSize,
screenshareTrack: screenshareTrack,
isSpeaking: isSpeaking,
isDominantSpeaker: isDominantSpeaker,
sessionId: sessionId,
connectionQuality: connectionQuality,
joinedAt: joinedAt,
audioLevel: audioLevel,
audioLevels: audioLevels,
pin: pin
)
}

public func withUpdated(
isSpeaking: Bool,
audioLevel: Float
Expand Down
Loading

0 comments on commit 86f2afb

Please sign in to comment.