| 
									
										
										
										
											2022-05-12 17:35:25 +08:00
										 |  |  | use crate::android::ffi::*;
 | 
					
						
							|  |  |  | use crate::rgba_to_i420;
 | 
					
						
							|  |  |  | use lazy_static::lazy_static;
 | 
					
						
							| 
									
										
										
										
											2022-06-01 17:52:21 +08:00
										 |  |  | use serde_json::Value;
 | 
					
						
							|  |  |  | use std::collections::HashMap;
 | 
					
						
							| 
									
										
										
										
											2022-05-12 17:35:25 +08:00
										 |  |  | use std::sync::Mutex;
 | 
					
						
							| 
									
										
										
										
											2022-06-23 17:42:30 +08:00
										 |  |  | use std::{io, time::Duration};
 | 
					
						
							| 
									
										
										
										
											2022-05-12 17:35:25 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | lazy_static! {
 | 
					
						
							| 
									
										
										
										
											2022-06-01 17:52:21 +08:00
										 |  |  |     static ref SCREEN_SIZE: Mutex<(u16, u16, u16)> = Mutex::new((0, 0, 0)); // (width, height, scale)
 | 
					
						
							| 
									
										
										
										
											2022-05-12 17:35:25 +08:00
										 |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | pub struct Capturer {
 | 
					
						
							|  |  |  |     display: Display,
 | 
					
						
							|  |  |  |     bgra: Vec<u8>,
 | 
					
						
							|  |  |  |     saved_raw_data: Vec<u128>, // for faster compare and copy
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | impl Capturer {
 | 
					
						
							|  |  |  |     pub fn new(display: Display, _yuv: bool) -> io::Result<Capturer> {
 | 
					
						
							|  |  |  |         Ok(Capturer {
 | 
					
						
							|  |  |  |             display,
 | 
					
						
							|  |  |  |             bgra: Vec::new(),
 | 
					
						
							|  |  |  |             saved_raw_data: Vec::new(),
 | 
					
						
							|  |  |  |         })
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     pub fn width(&self) -> usize {
 | 
					
						
							|  |  |  |         self.display.width() as usize
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     pub fn height(&self) -> usize {
 | 
					
						
							|  |  |  |         self.display.height() as usize
 | 
					
						
							|  |  |  |     }
 | 
					
						
							| 
									
										
										
										
											2022-07-21 20:04:39 +08:00
										 |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-21 22:29:26 +08:00
										 |  |  | impl crate::TraitCapturer for Capturer {
 | 
					
						
							| 
									
										
										
										
											2022-07-21 20:04:39 +08:00
										 |  |  |     fn set_use_yuv(&mut self, _use_yuv: bool) {}
 | 
					
						
							| 
									
										
										
										
											2022-05-12 17:35:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-21 20:04:39 +08:00
										 |  |  |     fn frame<'a>(&'a mut self, _timeout: Duration) -> io::Result<Frame<'a>> {
 | 
					
						
							| 
									
										
										
										
											2022-05-12 17:35:25 +08:00
										 |  |  |         if let Some(buf) = get_video_raw() {
 | 
					
						
							|  |  |  |             crate::would_block_if_equal(&mut self.saved_raw_data, buf)?;
 | 
					
						
							|  |  |  |             rgba_to_i420(self.width(), self.height(), buf, &mut self.bgra);
 | 
					
						
							|  |  |  |             Ok(Frame::RAW(&self.bgra))
 | 
					
						
							|  |  |  |         } else {
 | 
					
						
							|  |  |  |             return Err(io::ErrorKind::WouldBlock.into());
 | 
					
						
							|  |  |  |         }
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | pub enum Frame<'a> {
 | 
					
						
							|  |  |  |     RAW(&'a [u8]),
 | 
					
						
							|  |  |  |     VP9(&'a [u8]),
 | 
					
						
							|  |  |  |     Empty,
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | pub struct Display {
 | 
					
						
							|  |  |  |     default: bool,
 | 
					
						
							|  |  |  |     rect: Rect,
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
 | 
					
						
							|  |  |  | struct Rect {
 | 
					
						
							|  |  |  |     pub x: i16,
 | 
					
						
							|  |  |  |     pub y: i16,
 | 
					
						
							|  |  |  |     pub w: u16,
 | 
					
						
							|  |  |  |     pub h: u16,
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | impl Display {
 | 
					
						
							|  |  |  |     pub fn primary() -> io::Result<Display> {
 | 
					
						
							|  |  |  |         let mut size = SCREEN_SIZE.lock().unwrap();
 | 
					
						
							|  |  |  |         if size.0 == 0 || size.1 == 0 {
 | 
					
						
							| 
									
										
										
										
											2022-06-01 17:52:21 +08:00
										 |  |  |             *size = get_size().unwrap_or_default();
 | 
					
						
							| 
									
										
										
										
											2022-05-12 17:35:25 +08:00
										 |  |  |         }
 | 
					
						
							|  |  |  |         Ok(Display {
 | 
					
						
							|  |  |  |             default: true,
 | 
					
						
							|  |  |  |             rect: Rect {
 | 
					
						
							|  |  |  |                 x: 0,
 | 
					
						
							|  |  |  |                 y: 0,
 | 
					
						
							|  |  |  |                 w: size.0,
 | 
					
						
							|  |  |  |                 h: size.1,
 | 
					
						
							|  |  |  |             },
 | 
					
						
							|  |  |  |         })
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     pub fn all() -> io::Result<Vec<Display>> {
 | 
					
						
							|  |  |  |         Ok(vec![Display::primary()?])
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     pub fn width(&self) -> usize {
 | 
					
						
							|  |  |  |         self.rect.w as usize
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     pub fn height(&self) -> usize {
 | 
					
						
							|  |  |  |         self.rect.h as usize
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     pub fn origin(&self) -> (i32, i32) {
 | 
					
						
							|  |  |  |         let r = self.rect;
 | 
					
						
							|  |  |  |         (r.x as _, r.y as _)
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     pub fn is_online(&self) -> bool {
 | 
					
						
							|  |  |  |         true
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     pub fn is_primary(&self) -> bool {
 | 
					
						
							|  |  |  |         self.default
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     pub fn name(&self) -> String {
 | 
					
						
							|  |  |  |         "Android".into()
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     pub fn refresh_size() {
 | 
					
						
							|  |  |  |         let mut size = SCREEN_SIZE.lock().unwrap();
 | 
					
						
							| 
									
										
										
										
											2022-06-01 17:52:21 +08:00
										 |  |  |         *size = get_size().unwrap_or_default();
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Big android screen size will be shrinked, to improve performance when screen-capturing and encoding
 | 
					
						
							|  |  |  |     // e.g 2280x1080 size will be set to 1140x540, and `scale` is 2
 | 
					
						
							|  |  |  |     // need to multiply by `4` (2*2) when compute the bitrate
 | 
					
						
							|  |  |  |     pub fn fix_quality() -> u16 {
 | 
					
						
							|  |  |  |         let scale = SCREEN_SIZE.lock().unwrap().2;
 | 
					
						
							|  |  |  |         if scale <= 0 {
 | 
					
						
							|  |  |  |             1
 | 
					
						
							|  |  |  |         } else {
 | 
					
						
							|  |  |  |             scale * scale
 | 
					
						
							|  |  |  |         }
 | 
					
						
							| 
									
										
										
										
											2022-05-12 17:35:25 +08:00
										 |  |  |     }
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-01 17:52:21 +08:00
										 |  |  | fn get_size() -> Option<(u16, u16, u16)> {
 | 
					
						
							| 
									
										
										
										
											2022-05-12 17:35:25 +08:00
										 |  |  |     let res = call_main_service_get_by_name("screen_size").ok()?;
 | 
					
						
							| 
									
										
										
										
											2022-06-01 17:52:21 +08:00
										 |  |  |     if let Ok(json) = serde_json::from_str::<HashMap<String, Value>>(&res) {
 | 
					
						
							|  |  |  |         if let (Some(Value::Number(w)), Some(Value::Number(h)), Some(Value::Number(scale))) =
 | 
					
						
							|  |  |  |             (json.get("width"), json.get("height"), json.get("scale"))
 | 
					
						
							|  |  |  |         {
 | 
					
						
							|  |  |  |             let w = w.as_i64()? as _;
 | 
					
						
							|  |  |  |             let h = h.as_i64()? as _;
 | 
					
						
							|  |  |  |             let scale = scale.as_i64()? as _;
 | 
					
						
							|  |  |  |             return Some((w, h, scale));
 | 
					
						
							|  |  |  |         }
 | 
					
						
							| 
									
										
										
										
											2022-05-12 17:35:25 +08:00
										 |  |  |     }
 | 
					
						
							|  |  |  |     None
 | 
					
						
							|  |  |  | }
 |