1 use std::time::Instant;
11 pub fn new() -> Self { Self::default() }
12 pub fn toggle(&mut self) {
13 if self.time.is_none() {
14 self.time = Some(Instant::now());
19 pub fn update(&mut self) {
20 if let Some(time) = self.time {
21 if time.elapsed().as_millis() > 3000 {
26 pub fn is_active(&self) -> bool { self.time.is_some() }
27 pub fn prepare(&mut self, ts: u64) {
29 if !self.is_active() {
32 let time_str = format_time(ts);
34 let mut syms = Vec::with_capacity(time_str.len());
35 for chr in time_str.chars() {
36 let sym_idx = OSD_GLYPHS.iter().position(|el| el.sym == chr).unwrap_or(0);
37 w += OSD_GLYPHS[sym_idx].width;
42 self.text.resize(self.text_stride * 16, 0);
44 for &sym_idx in syms.iter() {
45 let glyph = &OSD_GLYPHS[sym_idx];
46 let mut mask = 1 << (glyph.width - 1);
48 for (dline, (bits, mbits)) in self.text.chunks_exact_mut(w).zip(glyph.bits.iter().zip(glyph.mask.iter())) {
49 let wval = (bits & mask) != 0;
50 let bval = (mbits & mask) != 0;
51 dline[pos] = if wval { 2 } else if bval { 1 } else { 0 };
61 pub fn draw_yuv(&self, buffer: &mut [u8], pitch: usize) {
62 if !self.is_active() || self.text_stride == 0 {
65 for (dline, sline) in buffer.chunks_exact_mut(pitch).zip(self.text.chunks_exact(self.text_stride)) {
66 for (dst, &src) in dline.iter_mut().zip(sline.iter()) {
75 pub fn draw_rgb(&self, buffer: &mut [u8], pitch: usize) {
76 if !self.is_active() || self.text_stride == 0 {
79 for (dline, sline) in buffer.chunks_exact_mut(pitch).zip(self.text.chunks_exact(self.text_stride)) {
80 for (dst, &src) in dline.chunks_exact_mut(3).zip(sline.iter()) {
82 2 => dst.copy_from_slice(&[0xFF, 0xFF, 0xFF]),
83 1 => dst.copy_from_slice(&[0x00, 0x00, 0x00]),
91 fn format_time(ms: u64) -> String {
93 let (min, s) = (s / 60, s % 60);
94 let (h, min) = (min / 60, min % 60);
99 format!("{}:{:02}", min, s)
102 format!("{}:{:02}:{:02}", h, min, s)
113 const OSD_GLYPHS: &[Glyph] = &[