mirror of
https://github.com/kunkundi/crossdesk.git
synced 2026-10-19 18:33:00 +08:00
[feat] add video adaptation preference setting
This commit is contained in:
@@ -35,6 +35,12 @@ typedef NS_ENUM(NSInteger, CrossDeskPointerAction) {
|
||||
CrossDeskPointerActionMiddleUp,
|
||||
};
|
||||
|
||||
typedef NS_ENUM(NSInteger, CrossDeskVideoAdaptationPolicy) {
|
||||
CrossDeskVideoAdaptationPolicyFrameRatePriority = 0,
|
||||
CrossDeskVideoAdaptationPolicyQualityPriority,
|
||||
CrossDeskVideoAdaptationPolicyBalanced,
|
||||
};
|
||||
|
||||
@class CrossDeskRTCBridge;
|
||||
|
||||
@protocol CrossDeskRTCBridgeDelegate <NSObject>
|
||||
@@ -96,6 +102,7 @@ typedef NS_ENUM(NSInteger, CrossDeskPointerAction) {
|
||||
turnPort:(NSInteger)turnPort
|
||||
enableSRTP:(BOOL)enableSRTP;
|
||||
- (void)setHardwareAccelerationEnabled:(BOOL)enabled;
|
||||
- (void)setVideoAdaptationPolicy:(CrossDeskVideoAdaptationPolicy)policy;
|
||||
- (void)requestPresenceForRemoteIDs:(NSArray<NSString *> *)remoteIDs
|
||||
NS_SWIFT_NAME(requestPresence(remoteIDs:));
|
||||
|
||||
|
||||
@@ -72,6 +72,8 @@ struct RTCState {
|
||||
int turn_port = 0;
|
||||
bool enable_srtp = false;
|
||||
bool hardware_acceleration = true;
|
||||
VideoDegradationPreference video_adaptation_policy =
|
||||
VideoDegradationPreference::MaintainResolution;
|
||||
bool identity_ready = false;
|
||||
bool identity_recovery_attempted = false;
|
||||
std::string identity_with_password;
|
||||
@@ -334,8 +336,7 @@ Params MakeParams(const RTCState &state, const std::string &user_id,
|
||||
params.video_content_type = VideoContentType::ScreenContent;
|
||||
params.video_quality = VideoQuality::QualityHigh;
|
||||
params.video_frame_rate = 60;
|
||||
params.video_degradation_preference =
|
||||
VideoDegradationPreference::MaintainResolution;
|
||||
params.video_degradation_preference = state.video_adaptation_policy;
|
||||
params.on_receive_video_buffer = nullptr;
|
||||
params.on_receive_audio_buffer = OnAudioBuffer;
|
||||
params.on_receive_data_buffer = OnDataBuffer;
|
||||
@@ -496,6 +497,26 @@ Params MakeParams(const RTCState &state, const std::string &user_id,
|
||||
});
|
||||
}
|
||||
|
||||
- (void)setVideoAdaptationPolicy:(CrossDeskVideoAdaptationPolicy)policy {
|
||||
dispatch_async(_rtcQueue, ^{
|
||||
switch (policy) {
|
||||
case CrossDeskVideoAdaptationPolicyFrameRatePriority:
|
||||
self->_state->video_adaptation_policy =
|
||||
VideoDegradationPreference::MaintainFrameRate;
|
||||
break;
|
||||
case CrossDeskVideoAdaptationPolicyBalanced:
|
||||
self->_state->video_adaptation_policy =
|
||||
VideoDegradationPreference::Balanced;
|
||||
break;
|
||||
case CrossDeskVideoAdaptationPolicyQualityPriority:
|
||||
default:
|
||||
self->_state->video_adaptation_policy =
|
||||
VideoDegradationPreference::MaintainResolution;
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
- (void)requestPresenceForRemoteIDs:(NSArray<NSString *> *)remoteIDs {
|
||||
NSArray<NSString *> *owned_ids = [remoteIDs copy];
|
||||
dispatch_async(_rtcQueue, ^{
|
||||
|
||||
@@ -689,6 +689,22 @@ private struct ServerSettingsView: View {
|
||||
.font(.caption)
|
||||
.foregroundStyle(.tertiary)
|
||||
}
|
||||
Section("画面偏好") {
|
||||
Picker("偏好模式", selection: $session.videoAdaptationPolicy) {
|
||||
ForEach(VideoAdaptationPolicy.allCases) { policy in
|
||||
Text(policy.title).tag(policy)
|
||||
}
|
||||
}
|
||||
.pickerStyle(.segmented)
|
||||
|
||||
Text(session.videoAdaptationPolicy.detail)
|
||||
.font(.footnote)
|
||||
.foregroundStyle(.secondary)
|
||||
|
||||
Text("修改后从下一次连接开始生效。")
|
||||
.font(.caption)
|
||||
.foregroundStyle(.tertiary)
|
||||
}
|
||||
Section("服务器") {
|
||||
TextField("信令服务器", text: $session.signalHost)
|
||||
.textInputAutocapitalization(.never)
|
||||
|
||||
@@ -79,6 +79,55 @@ enum VideoCodecMode: String, CaseIterable, Identifiable {
|
||||
}
|
||||
}
|
||||
|
||||
enum VideoAdaptationPolicy: String, CaseIterable, Identifiable {
|
||||
case frameRatePriority
|
||||
case qualityPriority
|
||||
case balanced
|
||||
|
||||
private static let defaultsKey = "crossdesk.mobile.video-adaptation-policy"
|
||||
|
||||
var id: String { rawValue }
|
||||
|
||||
var title: String {
|
||||
switch self {
|
||||
case .frameRatePriority: return "帧率优先"
|
||||
case .qualityPriority: return "画质优先"
|
||||
case .balanced: return "平衡"
|
||||
}
|
||||
}
|
||||
|
||||
var detail: String {
|
||||
switch self {
|
||||
case .frameRatePriority:
|
||||
return "优先保持画面流畅,带宽或编码压力较大时会更积极地降低分辨率。"
|
||||
case .qualityPriority:
|
||||
return "始终保持较高分辨率,带宽不足时通过降低帧率来保证画面清晰度。"
|
||||
case .balanced:
|
||||
return "兼顾清晰度和流畅度,只在持续压力下逐步降低分辨率。"
|
||||
}
|
||||
}
|
||||
|
||||
var bridgeValue: CrossDeskVideoAdaptationPolicy {
|
||||
switch self {
|
||||
case .frameRatePriority: return .frameRatePriority
|
||||
case .qualityPriority: return .qualityPriority
|
||||
case .balanced: return .balanced
|
||||
}
|
||||
}
|
||||
|
||||
static var saved: VideoAdaptationPolicy {
|
||||
guard let rawValue = UserDefaults.standard.string(forKey: defaultsKey),
|
||||
let policy = VideoAdaptationPolicy(rawValue: rawValue) else {
|
||||
return .qualityPriority
|
||||
}
|
||||
return policy
|
||||
}
|
||||
|
||||
func save() {
|
||||
UserDefaults.standard.set(rawValue, forKey: Self.defaultsKey)
|
||||
}
|
||||
}
|
||||
|
||||
private struct RemoteVideoFrame {
|
||||
let pixelBuffer: CVPixelBuffer
|
||||
let encodedSize: CGSize
|
||||
@@ -317,6 +366,9 @@ final class RemoteSessionModel: NSObject, ObservableObject, CrossDeskRTCBridgeDe
|
||||
@Published var videoCodecMode = VideoCodecMode.saved {
|
||||
didSet { videoCodecMode.save() }
|
||||
}
|
||||
@Published var videoAdaptationPolicy = VideoAdaptationPolicy.saved {
|
||||
didSet { videoAdaptationPolicy.save() }
|
||||
}
|
||||
@Published var remoteID = ""
|
||||
@Published var password = ""
|
||||
@Published private(set) var signalStatus = "正在连接信令服务"
|
||||
@@ -381,6 +433,7 @@ final class RemoteSessionModel: NSObject, ObservableObject, CrossDeskRTCBridgeDe
|
||||
return
|
||||
}
|
||||
bridge.setHardwareAccelerationEnabled(videoCodecMode == .hardware)
|
||||
bridge.setVideoAdaptationPolicy(videoAdaptationPolicy.bridgeValue)
|
||||
bridge.configure(withSignalHost: signalHost,
|
||||
signalPort: signal,
|
||||
turnPort: turn,
|
||||
|
||||
Reference in New Issue
Block a user