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 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