@@ -30,6 +30,7 @@ import '../track/local/local.dart';
3030import '../track/remote/remote.dart' ;
3131import '../track/remote/video.dart' ;
3232import '../types/other.dart' ;
33+ import '../types/video_dimensions.dart' ;
3334import '../utils.dart' ;
3435import 'track_publication.dart' ;
3536
@@ -47,8 +48,11 @@ class RemoteTrackPublication<T extends RemoteTrack> extends TrackPublication<T>
4748 int ? _fps;
4849 int get fps => _fps ?? 0 ;
4950
50- VideoQuality _videoQuality = VideoQuality .HIGH ;
51- VideoQuality get videoQuality => _videoQuality;
51+ VideoQuality ? _videoQuality = VideoQuality .HIGH ;
52+ VideoQuality get videoQuality => _videoQuality ?? VideoQuality .HIGH ;
53+
54+ VideoDimensions ? _videoDimensions;
55+ VideoDimensions ? get videoDimensions => _videoDimensions;
5256
5357 /// The server may pause the track when they are bandwidth limitations and resume
5458 /// when there is more capacity. This property will be updated when the track is
@@ -225,16 +229,52 @@ class RemoteTrackPublication<T extends RemoteTrack> extends TrackPublication<T>
225229 return didUpdate;
226230 }
227231
232+ bool _canUpdateManualVideoSettings () {
233+ if (kind != TrackType .VIDEO ) {
234+ logger.warning ('Manual video setting updates are only supported for video tracks' );
235+ return false ;
236+ }
237+
238+ if (! subscribed) {
239+ logger.warning ('Manual video setting update ignored because the publication is not subscribed' );
240+ return false ;
241+ }
242+
243+ if (participant.room.roomOptions.adaptiveStream) {
244+ logger.warning ('Manual video setting update ignored because adaptive stream is enabled' );
245+ return false ;
246+ }
247+
248+ return true ;
249+ }
250+
228251 Future <void > setVideoQuality (VideoQuality newValue) async {
229252 if (newValue == _videoQuality) return ;
253+ if (! _canUpdateManualVideoSettings ()) return ;
230254 _videoQuality = newValue;
255+ _videoDimensions = null ;
256+ sendUpdateTrackSettings ();
257+ }
258+
259+ /// Set preferred video dimensions for this track.
260+ ///
261+ /// Server will choose the appropriate layer based on these dimensions.
262+ /// Will override previous calls to [setVideoQuality] .
263+ Future <void > setVideoDimensions (VideoDimensions newValue) async {
264+ if (newValue.width == _videoDimensions? .width && newValue.height == _videoDimensions? .height) {
265+ return ;
266+ }
267+ if (! _canUpdateManualVideoSettings ()) return ;
268+ _videoDimensions = newValue;
269+ _videoQuality = null ;
231270 sendUpdateTrackSettings ();
232271 }
233272
234273 /// Set desired FPS, server will do its best to return FPS close to this.
235274 /// It's only supported for video codecs that support SVC currently.
236275 Future <void > setVideoFPS (int newValue) async {
237276 if (newValue == _fps) return ;
277+ if (! _canUpdateManualVideoSettings ()) return ;
238278 _fps = newValue;
239279 sendUpdateTrackSettings ();
240280 }
@@ -300,7 +340,14 @@ class RemoteTrackPublication<T extends RemoteTrack> extends TrackPublication<T>
300340 disabled: ! _enabled,
301341 );
302342 if (kind == TrackType .VIDEO ) {
303- settings.quality = _videoQuality.toPBType ();
343+ if (_videoDimensions != null ) {
344+ settings.width = _videoDimensions! .width;
345+ settings.height = _videoDimensions! .height;
346+ } else if (_videoQuality != null ) {
347+ settings.quality = _videoQuality! .toPBType ();
348+ } else {
349+ settings.quality = VideoQuality .HIGH .toPBType ();
350+ }
304351 if (_fps != null ) settings.fps = _fps! ;
305352 }
306353 participant.room.engine.signalClient.sendUpdateTrackSettings (settings);
0 commit comments