makepad_platform/
video.rs1use {
2 crate::{
3 makepad_live_id::{LiveId, FromLiveId},
4 }
5};
6
7pub type VideoInputFn = Box<dyn FnMut(VideoBufferRef) + Send + 'static>;
8
9pub const MAX_VIDEO_DEVICE_INDEX: usize = 32;
10
11#[derive(Clone, Debug, Default, Eq, Hash, Copy, PartialEq, FromLiveId)]
12pub struct VideoInputId(pub LiveId);
13
14#[derive(Clone, Debug, Default, Eq, Hash, Copy, PartialEq, FromLiveId)]
15pub struct VideoFormatId(pub LiveId);
16
17#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
18pub enum VideoPixelFormat {
19 RGB24,
20 YUY2,
21 NV12,
22 YUV420,
23 GRAY,
24 MJPEG,
25 Unsupported(u32)
26}
27
28impl VideoPixelFormat{
29 fn quality_priority(&self)->usize{
30 match self{
31 Self::RGB24 => 6,
32 Self::YUY2 => 5,
33 Self::NV12 => 4 ,
34 Self::YUV420=> 3,
35 Self::MJPEG => 2,
36 Self::GRAY => 1,
37 Self::Unsupported(_)=>0
38 }
39 }
40}
41
42pub enum VideoBufferRefData<'a>{
43 U8(&'a [u8]),
44 U32(&'a [u32])
45}
46
47pub struct VideoBufferRef<'a>{
48 pub format: VideoFormat,
49 pub data: VideoBufferRefData<'a>
50}
51
52
53impl<'a> VideoBufferRef<'a>{
54 pub fn to_buffer(&self)->VideoBuffer{
55 VideoBuffer{
56 format: self.format.clone(),
57 data: match self.data{
58 VideoBufferRefData::U8(data)=>VideoBufferData::U8(data.to_vec()),
59 VideoBufferRefData::U32(data)=>VideoBufferData::U32(data.to_vec()),
60 }
61 }
62 }
63
64 pub fn as_slice_u32(&mut self)->Option<&[u32]>{
65 match &mut self.data{
66 VideoBufferRefData::U32(v)=>return Some(v),
67 _=>return None
68 }
69 }
70 pub fn as_slice_u8(&mut self)->Option<&[u8]>{
71 match &mut self.data{
72 VideoBufferRefData::U8(v)=>return Some(v),
73 _=>return None
74 }
75 }
76}
77
78pub enum VideoBufferData{
79 U8(Vec<u8>),
80 U32(Vec<u32>)
81}
82
83pub struct VideoBuffer{
84 pub format:VideoFormat,
85 pub data: VideoBufferData
86}
87
88impl VideoBuffer{
89 pub fn as_vec_u32(&mut self)->Option<&mut Vec<u32>>{
90 match &mut self.data{
91 VideoBufferData::U32(v)=>return Some(v),
92 _=>return None
93 }
94 }
95 pub fn as_vec_u8(&mut self)->Option<&mut Vec<u8>>{
96 match &mut self.data{
97 VideoBufferData::U8(v)=>return Some(v),
98 _=>return None
99 }
100 }
101}
102
103impl VideoBuffer{
104 pub fn into_vec_u32(self)->Option<Vec<u32>>{
105 match self.data{
106 VideoBufferData::U32(v)=>return Some(v),
107 _=>return None
108 }
109 }
110 pub fn into_vec_u8(self)->Option<Vec<u8>>{
111 match self.data{
112 VideoBufferData::U8(v)=>return Some(v),
113 _=>return None
114 }
115 }
116}
117
118
119#[derive(Clone, Copy, Debug)]
120pub struct VideoFormat {
121 pub format_id: VideoFormatId,
122 pub width: usize,
123 pub height: usize,
124 pub frame_rate: Option<f64>,
125 pub pixel_format: VideoPixelFormat
126}
127
128#[derive(Clone, Debug)]
129pub struct VideoInputDesc {
130 pub input_id: VideoInputId,
131 pub name: String,
132 pub formats: Vec<VideoFormat>
133}
134
135#[derive(Clone)]
136pub struct VideoInputsEvent {
137 pub descs: Vec<VideoInputDesc>,
138}
139
140impl VideoInputsEvent {
141 pub fn find_device(&self, name:&str)->usize{
142 if let Some(position) = self.descs.iter().position(|v| v.name == name){
143 return position
144 }
145 return 0
146 }
147
148 pub fn find_highest(&self, device_index:usize) -> Vec<(VideoInputId,VideoFormatId)> {
149 if let Some(device) = self.descs.get(device_index){
150 let mut max_pixels = 0;
151 let mut max_frame_rate = 0.0;
152 let mut max_quality = 0;
153 let mut format_id = None;
154 for format in &device.formats {
155 let pixels = format.width * format.height;
156 if pixels >= max_pixels{
157 max_pixels = pixels
158 }
159 }
160 for format in &device.formats {
161 if let Some(frame_rate) = format.frame_rate{
162 let pixels = format.width * format.height;
163 if pixels == max_pixels && frame_rate >= max_frame_rate {
164 max_frame_rate = frame_rate;
165 }
166 }
167 }
168 for format in &device.formats {
169 let pixels = format.width * format.height;
170 let quality = format.pixel_format.quality_priority();
171 if pixels == max_pixels && format.frame_rate.unwrap_or(0.0) == max_frame_rate && quality >= max_quality{
172 max_quality = quality;
173 format_id = Some(format.format_id)
174 }
175 }
176 if let Some(format_id) = format_id{
177 return vec![(device.input_id, format_id)]
178 }
179 }
180 vec![]
181 }
182
183 pub fn find_highest_at_res(&self, device_index:usize, width:usize, height:usize, max_fps:f64) -> Vec<(VideoInputId,VideoFormatId)> {
184 if let Some(device) = self.descs.get(device_index){
185 let mut max_frame_rate = 0.0;
186 let mut max_quality = 0;
187 let mut format_id = None;
188
189 for format in &device.formats {
190 if let Some(frame_rate) = format.frame_rate{
191 if width == format.width && height == format.height && frame_rate >= max_frame_rate && frame_rate <= max_fps{
192 max_frame_rate = frame_rate;
193 }
194 }
195 }
196 for format in &device.formats {
197 let quality = format.pixel_format.quality_priority();
198 if width == format.width && height == format.height && format.frame_rate.unwrap_or(0.0) == max_frame_rate && quality >= max_quality{
199 max_quality = quality;
200 format_id = Some(format.format_id)
201 }
202 }
203 if let Some(format_id) = format_id{
204 return vec![(device.input_id, format_id)]
205 }
206 }
207 vec![]
208 }
209
210 pub fn find_format(&self, device_index:usize, width:usize, height:usize, pixel_format: VideoPixelFormat) -> Vec<(VideoInputId,VideoFormatId)> {
211 if let Some(device) = self.descs.get(device_index){
212 let mut max_frame_rate = 0.0;
213 let mut format_id = None;
214
215 for format in &device.formats {
216 if let Some(frame_rate) = format.frame_rate{
217 if format.pixel_format == pixel_format && width == format.width && height == format.height && frame_rate >= max_frame_rate {
218 max_frame_rate = frame_rate;
219 }
220 }
221 }
222 for format in &device.formats {
223 if format.pixel_format == pixel_format && width == format.width && height == format.height && format.frame_rate.unwrap_or(0.0) == max_frame_rate {
224 format_id = Some(format.format_id)
225 }
226 }
227 if let Some(format_id) = format_id{
228 return vec![(device.input_id, format_id)]
229 }
230 }
231 vec![]
232 }
233}
234
235
236impl std::fmt::Debug for VideoInputsEvent {
237 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
238 for desc in &self.descs {
239 write!(f, "Capture Device: {}\n", desc.name).unwrap();
240 for format in &desc.formats {
241 write!(f, " format: w:{} h:{} framerate:{:?} pixel:{:?} \n", format.width, format.height, format.frame_rate, format.pixel_format).unwrap();
242 }
243 }
244 Ok(())
245 }
246}