simple abr with delay
This commit is contained in:
		
							parent
							
								
									0da5c2ec68
								
							
						
					
					
						commit
						a7769da317
					
				| @ -57,23 +57,36 @@ pub struct VideoQoS { | |||||||
|     height: u32, |     height: u32, | ||||||
|     user_image_quality: u32, |     user_image_quality: u32, | ||||||
|     current_image_quality: u32, |     current_image_quality: u32, | ||||||
|     enable_abr: bool, |  | ||||||
| 
 | 
 | ||||||
|     pub current_delay: u32, |     pub current_delay: u32, | ||||||
|     pub fps: u8,             // abr
 |     pub fps: u8,             // abr
 | ||||||
|     pub target_bitrate: u32, // abr
 |     pub target_bitrate: u32, // abr
 | ||||||
|     updated: bool, |  | ||||||
| 
 | 
 | ||||||
|     state: AdaptiveState, |     updated: bool, | ||||||
|     last_delay: u32, |     state: DelayState, | ||||||
|     count: u32, |     debounce_count: u32, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Debug)] | #[derive(PartialEq, Debug)] | ||||||
| enum AdaptiveState { | enum DelayState { | ||||||
|     Normal, |     Normal = 0, | ||||||
|     LowDelay, |     LowDelay = 200, | ||||||
|     HighDelay, |     HighDelay = 500, | ||||||
|  |     Broken = 1000, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl DelayState { | ||||||
|  |     fn from_delay(delay: u32) -> Self { | ||||||
|  |         if delay > DelayState::Broken as u32 { | ||||||
|  |             DelayState::Broken | ||||||
|  |         } else if delay > DelayState::HighDelay as u32 { | ||||||
|  |             DelayState::HighDelay | ||||||
|  |         } else if delay > DelayState::LowDelay as u32 { | ||||||
|  |             DelayState::LowDelay | ||||||
|  |         } else { | ||||||
|  |             DelayState::Normal | ||||||
|  |         } | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl Default for VideoQoS { | impl Default for VideoQoS { | ||||||
| @ -82,24 +95,17 @@ impl Default for VideoQoS { | |||||||
|             fps: FPS, |             fps: FPS, | ||||||
|             user_image_quality: ImageQuality::Balanced.value() as _, |             user_image_quality: ImageQuality::Balanced.value() as _, | ||||||
|             current_image_quality: ImageQuality::Balanced.value() as _, |             current_image_quality: ImageQuality::Balanced.value() as _, | ||||||
|             enable_abr: false, |  | ||||||
|             width: 0, |             width: 0, | ||||||
|             height: 0, |             height: 0, | ||||||
|             current_delay: 0, |             current_delay: 0, | ||||||
|             target_bitrate: 0, |             target_bitrate: 0, | ||||||
|             updated: false, |             updated: false, | ||||||
|             state: AdaptiveState::Normal, |             state: DelayState::Normal, | ||||||
|             last_delay: 0, |             debounce_count: 0, | ||||||
|             count: 0, |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| const THRESHOLD: f32 = 1.2; |  | ||||||
| const MAX_COUNT: u32 = 3; |  | ||||||
| const MAX_DELAY: u32 = 500; |  | ||||||
| const MIN_DELAY: u32 = 50; |  | ||||||
| 
 |  | ||||||
| impl VideoQoS { | impl VideoQoS { | ||||||
|     pub fn set_size(&mut self, width: u32, height: u32) { |     pub fn set_size(&mut self, width: u32, height: u32) { | ||||||
|         if width == 0 || height == 0 { |         if width == 0 || height == 0 { | ||||||
| @ -121,123 +127,52 @@ impl VideoQoS { | |||||||
|             self.current_delay = delay; |             self.current_delay = delay; | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|         let current_delay = self.current_delay as f32; |  | ||||||
| 
 | 
 | ||||||
|         self.current_delay = delay / 2 + self.current_delay / 2; |         self.current_delay = delay / 2 + self.current_delay / 2; | ||||||
|         log::trace!( |         log::trace!( | ||||||
|             "update_network_delay:{}, {}, state:{:?},count:{}", |             "VideoQoS update_network_delay:{}, {}, state:{:?},count:{}", | ||||||
|             self.current_delay, |             self.current_delay, | ||||||
|             delay, |             delay, | ||||||
|             self.state, |             self.state, | ||||||
|             self.count |             self.debounce_count | ||||||
|         ); |         ); | ||||||
| 
 | 
 | ||||||
|         // ABR
 |         // ABR
 | ||||||
|         if !self.enable_abr { |         let current_state = DelayState::from_delay(self.current_delay); | ||||||
|             // return;
 |         if current_state != self.state && self.debounce_count > 5 { | ||||||
|  |             log::debug!( | ||||||
|  |                 "VideoQoS state changed:{:?} -> {:?}", | ||||||
|  |                 self.state, | ||||||
|  |                 current_state | ||||||
|  |             ); | ||||||
|  |             self.state = current_state; | ||||||
|  |             self.debounce_count = 0; | ||||||
|  |             self.update_quality(); | ||||||
|  |         } else { | ||||||
|  |             self.debounce_count += 1; | ||||||
|         } |         } | ||||||
|         if self.current_delay < MIN_DELAY { |     } | ||||||
|             if self.fps != FPS && self.current_image_quality != self.user_image_quality { | 
 | ||||||
|                 log::debug!("current_delay is normal, set to user_image_quality"); |     fn update_quality(&mut self) { | ||||||
|  |         match self.state { | ||||||
|  |             DelayState::Normal => { | ||||||
|                 self.fps = FPS; |                 self.fps = FPS; | ||||||
|                 self.current_image_quality = self.user_image_quality; |                 self.current_image_quality = self.user_image_quality; | ||||||
|                 let _ = self.generate_bitrate().ok(); |  | ||||||
|                 self.updated = true; |  | ||||||
|             } |             } | ||||||
|             self.state = AdaptiveState::Normal; |             DelayState::LowDelay => { | ||||||
|         } else if self.current_delay > MAX_DELAY { |  | ||||||
|             if self.fps != 5 && self.current_image_quality != 25 { |  | ||||||
|                 log::debug!("current_delay is very high, set fps to 5, image_quality to 25"); |  | ||||||
|                 self.fps = 5; |  | ||||||
|                 self.current_image_quality = 25; |  | ||||||
|                 let _ = self.generate_bitrate().ok(); |  | ||||||
|                 self.updated = true; |  | ||||||
|             } |  | ||||||
|         } else { |  | ||||||
|             // MAX_DELAY to Normal
 |  | ||||||
|             if self.fps == 5 && self.current_image_quality == 25 { |  | ||||||
|                 self.fps = FPS; |                 self.fps = FPS; | ||||||
|                 self.current_image_quality = |                 self.current_image_quality = std::cmp::min(self.user_image_quality, 50); | ||||||
|                     std::cmp::min(self.user_image_quality, ImageQuality::Low.value() as _); |  | ||||||
|                 self.last_delay = self.current_delay; |  | ||||||
|                 let _ = self.generate_bitrate().ok(); |  | ||||||
|                 self.updated = true; |  | ||||||
|                 return; |  | ||||||
|             } |             } | ||||||
|             let delay = delay as f32; |             DelayState::HighDelay => { | ||||||
|             let last_delay = self.last_delay as f32; |                 self.fps = FPS / 2; | ||||||
|             match self.state { |                 self.current_image_quality = std::cmp::min(self.user_image_quality, 25); | ||||||
|                 AdaptiveState::Normal => { |             } | ||||||
|                     if delay > current_delay * THRESHOLD { |             DelayState::Broken => { | ||||||
|                         self.state = AdaptiveState::HighDelay; |                 self.fps = FPS / 4; | ||||||
|                     } else if delay < current_delay * THRESHOLD |                 self.current_image_quality = 10; | ||||||
|                         && self.current_image_quality < self.user_image_quality |  | ||||||
|                     { |  | ||||||
|                         self.state = AdaptiveState::LowDelay; |  | ||||||
|                     } |  | ||||||
|                     self.count = 0; |  | ||||||
|                     self.last_delay = self.current_delay |  | ||||||
|                 } |  | ||||||
|                 AdaptiveState::HighDelay => { |  | ||||||
|                     if delay > last_delay { |  | ||||||
|                         if self.count > MAX_COUNT { |  | ||||||
|                             self.decrease_quality(); |  | ||||||
|                             self.reset_state(); |  | ||||||
|                             return; |  | ||||||
|                         } |  | ||||||
|                         self.count += 1; |  | ||||||
|                     } else { |  | ||||||
|                         self.reset_state(); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|                 AdaptiveState::LowDelay => { |  | ||||||
|                     if delay < last_delay * THRESHOLD { |  | ||||||
|                         if self.count > MAX_COUNT { |  | ||||||
|                             self.increase_quality(); |  | ||||||
|                             self.reset_state(); |  | ||||||
|                             return; |  | ||||||
|                         } |  | ||||||
|                         self.count += 1; |  | ||||||
|                     } else { |  | ||||||
|                         self.reset_state(); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |         let _ = self.generate_bitrate().ok(); | ||||||
| 
 |  | ||||||
|     fn reset_state(&mut self) { |  | ||||||
|         self.count = 0; |  | ||||||
|         self.state = AdaptiveState::Normal; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     fn increase_quality(&mut self) { |  | ||||||
|         log::debug!("Adaptive increase quality"); |  | ||||||
|         if self.fps < FPS { |  | ||||||
|             log::debug!("increase fps {} -> {}", self.fps, FPS); |  | ||||||
|             self.fps = FPS; |  | ||||||
|         } else { |  | ||||||
|             self.current_image_quality += self.current_image_quality / 2; |  | ||||||
|             let _ = self.generate_bitrate().ok(); |  | ||||||
|             log::debug!("increase quality:{}", self.current_image_quality); |  | ||||||
|         } |  | ||||||
|         self.updated = true; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     fn decrease_quality(&mut self) { |  | ||||||
|         log::debug!("Adaptive decrease quality"); |  | ||||||
|         if self.fps < 15 { |  | ||||||
|             log::debug!("fps is low enough :{}", self.fps); |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|         if self.current_image_quality < ImageQuality::Low.value() as _ { |  | ||||||
|             self.fps = self.fps / 2; |  | ||||||
|             log::debug!("decrease fps:{}", self.fps); |  | ||||||
|         } else { |  | ||||||
|             self.current_image_quality -= self.current_image_quality / 2; |  | ||||||
|             let _ = self.generate_bitrate().ok(); |  | ||||||
|             log::debug!("decrease quality:{}", self.current_image_quality); |  | ||||||
|         }; |  | ||||||
|         self.updated = true; |         self.updated = true; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -335,7 +335,8 @@ class Header: Reactor.Component { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function handle_custom_image_quality() { | function handle_custom_image_quality() { | ||||||
|     var bitrate = handler.get_custom_image_quality()[0] / 2; |     var tmp = handler.get_custom_image_quality(); | ||||||
|  |     var bitrate = (tmp[0] || 100) / 2; | ||||||
|     msgbox("custom", "Custom Image Quality", "<div .form> \ |     msgbox("custom", "Custom Image Quality", "<div .form> \ | ||||||
|           <div><input type=\"hslider\" style=\"width: 50%\" name=\"bitrate\" max=\"100\" min=\"10\" value=\"" + bitrate + "\"/ buddy=\"bitrate-buddy\"><b #bitrate-buddy>x</b>% Bitrate</div> \ |           <div><input type=\"hslider\" style=\"width: 50%\" name=\"bitrate\" max=\"100\" min=\"10\" value=\"" + bitrate + "\"/ buddy=\"bitrate-buddy\"><b #bitrate-buddy>x</b>% Bitrate</div> \ | ||||||
|       </div>", function(res=null) { |       </div>", function(res=null) { | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user