1use byteorder::{BigEndian, ReadBytesExt};
4use std::io::{Cursor, Read};
5
6pub struct BigEndianReader<'a> {
8 cursor: Cursor<&'a [u8]>,
9}
10
11impl<'a> BigEndianReader<'a> {
12 pub fn new(data: &'a [u8]) -> Self {
13 Self {
14 cursor: Cursor::new(data),
15 }
16 }
17
18 #[inline]
19 pub fn position(&self) -> usize {
20 self.cursor.position() as usize
21 }
22
23 #[inline]
24 pub fn set_position(&mut self, pos: usize) {
25 self.cursor.set_position(pos as u64);
26 }
27
28 #[inline]
29 pub fn remaining(&self) -> usize {
30 self.cursor.get_ref().len() - self.position()
31 }
32
33 #[inline]
34 pub fn read_u8(&mut self) -> Option<u8> {
35 self.cursor.read_u8().ok()
36 }
37
38 #[inline]
39 pub fn read_u16(&mut self) -> Option<u16> {
40 self.cursor.read_u16::<BigEndian>().ok()
41 }
42
43 #[inline]
44 pub fn read_u24(&mut self) -> Option<u32> {
45 let mut buf = [0u8; 3];
46 self.cursor.read_exact(&mut buf).ok()?;
47 Some(((buf[0] as u32) << 16) | ((buf[1] as u32) << 8) | (buf[2] as u32))
48 }
49
50 #[inline]
51 pub fn read_u32(&mut self) -> Option<u32> {
52 self.cursor.read_u32::<BigEndian>().ok()
53 }
54
55 #[inline]
56 pub fn read_bytes(&mut self, len: usize) -> Option<Vec<u8>> {
57 let mut buf = vec![0u8; len];
58 self.cursor.read_exact(&mut buf).ok()?;
59 Some(buf)
60 }
61
62 #[inline]
63 pub fn skip(&mut self, len: usize) -> bool {
64 let new_pos = self.position() + len;
65 if new_pos <= self.cursor.get_ref().len() {
66 self.cursor.set_position(new_pos as u64);
67 true
68 } else {
69 false
70 }
71 }
72}
73
74#[inline]
77pub fn ycbcr_to_rgba(y: u8, cb: u8, cr: u8, a: u8) -> u32 {
78 let y = y as f32;
79 let cb = (cb as f32) - 128.0;
80 let cr = (cr as f32) - 128.0;
81
82 let r = clamp((y + 1.40200 * cr).round() as i32, 0, 255) as u8;
83 let g = clamp((y - 0.34414 * cb - 0.71414 * cr).round() as i32, 0, 255) as u8;
84 let b = clamp((y + 1.77200 * cb).round() as i32, 0, 255) as u8;
85
86 u32::from_le_bytes([r, g, b, a])
89}
90
91#[inline]
93pub fn rgb_to_rgba(r: u8, g: u8, b: u8, a: u8) -> u32 {
94 u32::from_le_bytes([r, g, b, a])
95}
96
97#[inline]
98pub fn clamp<T: Ord>(value: T, min: T, max: T) -> T {
99 if value < min {
100 min
101 } else if value > max {
102 max
103 } else {
104 value
105 }
106}
107
108pub fn binary_search_timestamp(timestamps: &[u32], target: u32) -> usize {
110 if timestamps.is_empty() {
111 return 0;
112 }
113
114 let mut low = 0;
115 let mut high = timestamps.len();
116
117 while low < high {
118 let mid = low + (high - low) / 2;
119 if timestamps[mid] <= target {
120 low = mid + 1;
121 } else {
122 high = mid;
123 }
124 }
125
126 if low > 0 { low - 1 } else { 0 }
127}
128
129#[cfg(test)]
130mod tests {
131 use super::*;
132
133 #[test]
134 fn test_binary_search_timestamp() {
135 let timestamps = vec![0, 1000, 2000, 3000, 4000];
136
137 assert_eq!(binary_search_timestamp(×tamps, 0), 0);
138 assert_eq!(binary_search_timestamp(×tamps, 500), 0);
139 assert_eq!(binary_search_timestamp(×tamps, 1000), 1);
140 assert_eq!(binary_search_timestamp(×tamps, 1500), 1);
141 assert_eq!(binary_search_timestamp(×tamps, 4500), 4);
142 }
143
144 #[test]
145 fn test_ycbcr_to_rgba() {
146 let white = ycbcr_to_rgba(255, 128, 128, 255);
148 let bytes = white.to_le_bytes();
149 assert_eq!(bytes[0], 255); assert_eq!(bytes[1], 255); assert_eq!(bytes[2], 255); assert_eq!(bytes[3], 255); }
154}