1 use std::iter::FromIterator;
2
3 use webrtc_constraints::{
4 algorithms::{
5 select_settings_candidates, ClosestToIdealPolicy, DeviceInformationExposureMode,
6 TieBreakingPolicy,
7 },
8 property::all::name::*,
9 AdvancedMediaTrackConstraints, MandatoryMediaTrackConstraints, MediaTrackConstraintSet,
10 MediaTrackConstraints, MediaTrackSettings, MediaTrackSupportedConstraints, ResizeMode,
11 ResolvedValueConstraint, ResolvedValueRangeConstraint, ValueConstraint, ValueRangeConstraint,
12 };
13
main()14 fn main() {
15 let supported_constraints =
16 MediaTrackSupportedConstraints::from_iter(vec![&DEVICE_ID, &HEIGHT, &WIDTH, &RESIZE_MODE]);
17
18 let possible_settings = vec![
19 MediaTrackSettings::from_iter([
20 (&DEVICE_ID, "480p".into()),
21 (&HEIGHT, 480.into()),
22 (&WIDTH, 720.into()),
23 (&RESIZE_MODE, ResizeMode::crop_and_scale().into()),
24 ]),
25 MediaTrackSettings::from_iter([
26 (&DEVICE_ID, "720p".into()),
27 (&HEIGHT, 720.into()),
28 (&WIDTH, 1280.into()),
29 (&RESIZE_MODE, ResizeMode::crop_and_scale().into()),
30 ]),
31 MediaTrackSettings::from_iter([
32 (&DEVICE_ID, "1080p".into()),
33 (&HEIGHT, 1080.into()),
34 (&WIDTH, 1920.into()),
35 (&RESIZE_MODE, ResizeMode::none().into()),
36 ]),
37 MediaTrackSettings::from_iter([
38 (&DEVICE_ID, "1440p".into()),
39 (&HEIGHT, 1440.into()),
40 (&WIDTH, 2560.into()),
41 (&RESIZE_MODE, ResizeMode::none().into()),
42 ]),
43 MediaTrackSettings::from_iter([
44 (&DEVICE_ID, "2160p".into()),
45 (&HEIGHT, 2160.into()),
46 (&WIDTH, 3840.into()),
47 (&RESIZE_MODE, ResizeMode::none().into()),
48 ]),
49 ];
50
51 let constraints = MediaTrackConstraints {
52 mandatory: MandatoryMediaTrackConstraints::from_iter([
53 (
54 &WIDTH,
55 ValueRangeConstraint::Constraint(ResolvedValueRangeConstraint::default().max(2560))
56 .into(),
57 ),
58 (
59 &HEIGHT,
60 ValueRangeConstraint::Constraint(ResolvedValueRangeConstraint::default().max(1440))
61 .into(),
62 ),
63 // Unsupported constraint, which should thus get ignored:
64 (
65 &FRAME_RATE,
66 ValueRangeConstraint::Constraint(
67 ResolvedValueRangeConstraint::default().exact(30.0),
68 )
69 .into(),
70 ),
71 ]),
72 advanced: AdvancedMediaTrackConstraints::from_iter([
73 // The first advanced constraint set of "exact 800p" does not match
74 // any candidate and should thus get ignored by the algorithm:
75 MediaTrackConstraintSet::from_iter([(
76 &HEIGHT,
77 ValueRangeConstraint::Constraint(
78 ResolvedValueRangeConstraint::default().exact(800),
79 )
80 .into(),
81 )]),
82 // The second advanced constraint set of "no resizing" does match
83 // candidates and should thus be applied by the algorithm:
84 MediaTrackConstraintSet::from_iter([(
85 &RESIZE_MODE,
86 ValueConstraint::Constraint(
87 ResolvedValueConstraint::default().exact(ResizeMode::none()),
88 )
89 .into(),
90 )]),
91 ]),
92 };
93
94 // Resolve bare values to proper constraints:
95 let resolved_constraints = constraints.into_resolved();
96
97 // Sanitize constraints, removing empty and unsupported constraints:
98 let sanitized_constraints = resolved_constraints.to_sanitized(&supported_constraints);
99
100 let candidates = select_settings_candidates(
101 &possible_settings,
102 &sanitized_constraints,
103 DeviceInformationExposureMode::Exposed,
104 )
105 .unwrap();
106
107 // Specify a tie-breaking policy
108 //
109 // A couple of basic policies are provided batteries-included,
110 // but for more sophisticated needs you can implement your own `TieBreakingPolicy`:
111 let tie_breaking_policy =
112 ClosestToIdealPolicy::new(possible_settings[2].clone(), &supported_constraints);
113
114 let actual = tie_breaking_policy.select_candidate(candidates);
115
116 let expected = &possible_settings[2];
117
118 assert_eq!(actual, expected);
119 }
120