1#![allow(dead_code)]
8
9pub mod decode;
10pub mod framebuffer;
11pub mod player;
12
13use alloc::{vec, vec::Vec};
14use core::sync::atomic::{AtomicBool, Ordering};
15
16use crate::{error::KernelError, graphics::PixelFormat};
17
18#[derive(Debug, Clone)]
24pub(crate) struct VideoFrame {
25 pub(crate) width: u32,
27 pub(crate) height: u32,
29 pub(crate) format: PixelFormat,
31 data: Vec<u8>,
33 pub(crate) stride: u32,
35}
36
37impl VideoFrame {
38 pub(crate) fn new(width: u32, height: u32, format: PixelFormat) -> Self {
40 let bpp = format.bytes_per_pixel() as u32;
41 let stride = width * bpp;
42 let size = (stride as usize) * (height as usize);
43 Self {
44 width,
45 height,
46 format,
47 data: vec![0u8; size],
48 stride,
49 }
50 }
51
52 #[inline]
54 pub(crate) fn pixel_offset(&self, x: u32, y: u32) -> usize {
55 (y as usize) * (self.stride as usize) + (x as usize) * self.format.bytes_per_pixel()
56 }
57
58 pub(crate) fn set_pixel(&mut self, x: u32, y: u32, r: u8, g: u8, b: u8, a: u8) {
60 if x >= self.width || y >= self.height {
61 return;
62 }
63 let off = self.pixel_offset(x, y);
64 match self.format {
65 PixelFormat::Xrgb8888 => {
66 if off + 3 < self.data.len() {
67 self.data[off] = b;
68 self.data[off + 1] = g;
69 self.data[off + 2] = r;
70 self.data[off + 3] = 0xFF;
71 }
72 }
73 PixelFormat::Argb8888 => {
74 if off + 3 < self.data.len() {
75 self.data[off] = b;
76 self.data[off + 1] = g;
77 self.data[off + 2] = r;
78 self.data[off + 3] = a;
79 }
80 }
81 PixelFormat::Rgb888 => {
82 if off + 2 < self.data.len() {
83 self.data[off] = r;
84 self.data[off + 1] = g;
85 self.data[off + 2] = b;
86 }
87 }
88 PixelFormat::Rgb565 => {
89 if off + 1 < self.data.len() {
90 let val: u16 =
91 ((r as u16 & 0xF8) << 8) | ((g as u16 & 0xFC) << 3) | (b as u16 >> 3);
92 self.data[off] = (val & 0xFF) as u8;
93 self.data[off + 1] = (val >> 8) as u8;
94 }
95 }
96 PixelFormat::Bgr888 => {
97 if off + 2 < self.data.len() {
98 self.data[off] = b;
99 self.data[off + 1] = g;
100 self.data[off + 2] = r;
101 }
102 }
103 PixelFormat::Bgrx8888 => {
104 if off + 3 < self.data.len() {
105 self.data[off] = b;
106 self.data[off + 1] = g;
107 self.data[off + 2] = r;
108 self.data[off + 3] = 0xFF;
109 }
110 }
111 PixelFormat::Rgba8888 => {
112 if off + 3 < self.data.len() {
113 self.data[off] = r;
114 self.data[off + 1] = g;
115 self.data[off + 2] = b;
116 self.data[off + 3] = a;
117 }
118 }
119 PixelFormat::Bgra8888 => {
120 if off + 3 < self.data.len() {
121 self.data[off] = b;
122 self.data[off + 1] = g;
123 self.data[off + 2] = r;
124 self.data[off + 3] = a;
125 }
126 }
127 PixelFormat::Xbgr8888 => {
128 if off + 3 < self.data.len() {
129 self.data[off] = 0xFF;
130 self.data[off + 1] = b;
131 self.data[off + 2] = g;
132 self.data[off + 3] = r;
133 }
134 }
135 PixelFormat::Abgr8888 => {
136 if off + 3 < self.data.len() {
137 self.data[off] = a;
138 self.data[off + 1] = b;
139 self.data[off + 2] = g;
140 self.data[off + 3] = r;
141 }
142 }
143 PixelFormat::Gray8 => {
144 if off < self.data.len() {
145 self.data[off] = ((r as u32 * 77 + g as u32 * 150 + b as u32 * 29) >> 8) as u8;
147 }
148 }
149 }
150 }
151
152 pub(crate) fn get_pixel(&self, x: u32, y: u32) -> (u8, u8, u8, u8) {
155 if x >= self.width || y >= self.height {
156 return (0, 0, 0, 0);
157 }
158 let off = self.pixel_offset(x, y);
159 match self.format {
160 PixelFormat::Xrgb8888 => {
161 if off + 3 < self.data.len() {
162 (self.data[off + 2], self.data[off + 1], self.data[off], 0xFF)
163 } else {
164 (0, 0, 0, 0)
165 }
166 }
167 PixelFormat::Argb8888 => {
168 if off + 3 < self.data.len() {
169 (
170 self.data[off + 2],
171 self.data[off + 1],
172 self.data[off],
173 self.data[off + 3],
174 )
175 } else {
176 (0, 0, 0, 0)
177 }
178 }
179 PixelFormat::Rgb888 => {
180 if off + 2 < self.data.len() {
181 (self.data[off], self.data[off + 1], self.data[off + 2], 0xFF)
182 } else {
183 (0, 0, 0, 0)
184 }
185 }
186 PixelFormat::Rgb565 => {
187 if off + 1 < self.data.len() {
188 let val = (self.data[off] as u16) | ((self.data[off + 1] as u16) << 8);
189 let r = ((val >> 11) & 0x1F) as u8;
190 let g = ((val >> 5) & 0x3F) as u8;
191 let b = (val & 0x1F) as u8;
192 (
194 (r << 3) | (r >> 2),
195 (g << 2) | (g >> 4),
196 (b << 3) | (b >> 2),
197 0xFF,
198 )
199 } else {
200 (0, 0, 0, 0)
201 }
202 }
203 PixelFormat::Bgr888 => {
204 if off + 2 < self.data.len() {
205 (self.data[off + 2], self.data[off + 1], self.data[off], 0xFF)
206 } else {
207 (0, 0, 0, 0)
208 }
209 }
210 PixelFormat::Bgrx8888 => {
211 if off + 3 < self.data.len() {
212 (self.data[off + 2], self.data[off + 1], self.data[off], 0xFF)
213 } else {
214 (0, 0, 0, 0)
215 }
216 }
217 PixelFormat::Rgba8888 => {
218 if off + 3 < self.data.len() {
219 (
220 self.data[off],
221 self.data[off + 1],
222 self.data[off + 2],
223 self.data[off + 3],
224 )
225 } else {
226 (0, 0, 0, 0)
227 }
228 }
229 PixelFormat::Bgra8888 => {
230 if off + 3 < self.data.len() {
231 (
232 self.data[off + 2],
233 self.data[off + 1],
234 self.data[off],
235 self.data[off + 3],
236 )
237 } else {
238 (0, 0, 0, 0)
239 }
240 }
241 PixelFormat::Xbgr8888 => {
242 if off + 3 < self.data.len() {
243 (
244 self.data[off + 3],
245 self.data[off + 2],
246 self.data[off + 1],
247 0xFF,
248 )
249 } else {
250 (0, 0, 0, 0)
251 }
252 }
253 PixelFormat::Abgr8888 => {
254 if off + 3 < self.data.len() {
255 (
256 self.data[off + 3],
257 self.data[off + 2],
258 self.data[off + 1],
259 self.data[off],
260 )
261 } else {
262 (0, 0, 0, 0)
263 }
264 }
265 PixelFormat::Gray8 => {
266 if off < self.data.len() {
267 let v = self.data[off];
268 (v, v, v, 0xFF)
269 } else {
270 (0, 0, 0, 0)
271 }
272 }
273 }
274 }
275
276 pub(crate) fn clear(&mut self, r: u8, g: u8, b: u8) {
278 for y in 0..self.height {
279 for x in 0..self.width {
280 self.set_pixel(x, y, r, g, b, 0xFF);
281 }
282 }
283 }
284
285 pub(crate) fn data(&self) -> &[u8] {
287 &self.data
288 }
289
290 pub(crate) fn data_mut(&mut self) -> &mut [u8] {
292 &mut self.data
293 }
294}
295
296#[derive(Debug, Clone, Copy)]
302pub(crate) struct VideoInfo {
303 pub(crate) width: u32,
304 pub(crate) height: u32,
305 pub(crate) format: PixelFormat,
306 pub(crate) frame_rate_num: u32,
308 pub(crate) frame_rate_den: u32,
310}
311
312static INITIALIZED: AtomicBool = AtomicBool::new(false);
317
318pub(crate) fn init() -> Result<(), KernelError> {
320 if INITIALIZED.load(Ordering::Acquire) {
321 return Ok(());
322 }
323
324 println!("[VIDEO] Initializing video subsystem...");
325
326 player::init()?;
327
328 INITIALIZED.store(true, Ordering::Release);
329 println!("[VIDEO] Video subsystem initialized");
330 Ok(())
331}
332
333#[cfg(test)]
334mod tests {
335 use super::*;
336
337 #[test]
338 fn test_pixel_format_bpp() {
339 assert_eq!(PixelFormat::Xrgb8888.bytes_per_pixel(), 4);
340 assert_eq!(PixelFormat::Argb8888.bytes_per_pixel(), 4);
341 assert_eq!(PixelFormat::Rgb888.bytes_per_pixel(), 3);
342 assert_eq!(PixelFormat::Rgb565.bytes_per_pixel(), 2);
343 assert_eq!(PixelFormat::Gray8.bytes_per_pixel(), 1);
344 assert_eq!(PixelFormat::Bgr888.bytes_per_pixel(), 3);
345 assert_eq!(PixelFormat::Bgrx8888.bytes_per_pixel(), 4);
346 }
347
348 #[test]
349 fn test_pixel_format_alpha() {
350 assert!(!PixelFormat::Xrgb8888.has_alpha());
351 assert!(PixelFormat::Argb8888.has_alpha());
352 assert!(!PixelFormat::Rgb888.has_alpha());
353 assert!(!PixelFormat::Gray8.has_alpha());
354 }
355
356 #[test]
357 fn test_video_frame_new() {
358 let f = VideoFrame::new(320, 240, PixelFormat::Xrgb8888);
359 assert_eq!(f.width, 320);
360 assert_eq!(f.height, 240);
361 assert_eq!(f.stride, 320 * 4);
362 assert_eq!(f.data.len(), 320 * 240 * 4);
363 }
364
365 #[test]
366 fn test_video_frame_set_get_pixel() {
367 let mut f = VideoFrame::new(4, 4, PixelFormat::Argb8888);
368 f.set_pixel(1, 2, 0xAA, 0xBB, 0xCC, 0xDD);
369 let (r, g, b, a) = f.get_pixel(1, 2);
370 assert_eq!((r, g, b, a), (0xAA, 0xBB, 0xCC, 0xDD));
371 }
372
373 #[test]
374 fn test_video_frame_out_of_bounds() {
375 let mut f = VideoFrame::new(2, 2, PixelFormat::Rgb888);
376 f.set_pixel(10, 10, 255, 0, 0, 255);
378 let px = f.get_pixel(10, 10);
379 assert_eq!(px, (0, 0, 0, 0));
380 }
381}