]>
Commit | Line | Data |
---|---|---|
e3af9911 KS |
1 | use nihav_core::codecs::*; |
2 | use nihav_core::io::byteio::*; | |
3 | ||
4 | struct Palette { | |
5 | data: [u8; 1024], | |
6 | } | |
7 | ||
8 | impl Default for Palette { | |
9 | fn default() -> Self { | |
10 | Self { data: [0; 1024] } | |
11 | } | |
12 | } | |
13 | ||
14 | impl Palette { | |
15 | fn read_data(&mut self, src: &[u8]) { | |
16 | for (dst, src) in self.data.chunks_exact_mut(4).zip(src.chunks_exact(4)) { | |
17 | let clr = read_u32le(src).unwrap(); | |
18 | let r = (clr & 0x1F) as u8; | |
19 | dst[0] = (r << 3) | (r >> 2); | |
20 | let g = ((clr >> 5) & 0x1F) as u8; | |
21 | dst[1] = (g << 3) | (g >> 2); | |
22 | let b = ((clr >> 10) & 0x1F) as u8; | |
23 | dst[2] = (b << 3) | (b >> 2); | |
24 | dst[3] = 0; | |
25 | } | |
26 | } | |
27 | fn get_side_data(&self) -> NASideData { | |
28 | NASideData::Palette(true, Arc::new(self.data)) | |
29 | } | |
30 | } | |
31 | ||
32 | #[derive(Default)] | |
33 | struct WssPacketiser { | |
34 | stream: Option<NAStreamRef>, | |
35 | buf: Vec<u8>, | |
36 | csizes: Vec<usize>, | |
37 | frameno: u32, | |
38 | frame_size: usize, | |
39 | palette: Palette, | |
40 | pal_mode: bool, | |
41 | has_pal: bool, | |
42 | } | |
43 | ||
44 | impl WssPacketiser { | |
45 | fn new() -> Self { Self::default() } | |
46 | fn remove_payload(&mut self, size: usize) { | |
47 | self.buf.drain(..size); | |
48 | if !self.csizes.is_empty() { | |
49 | if self.csizes[0] >= size { | |
50 | self.csizes[0] -= size; | |
51 | // skip possible padding at the end of chunk | |
52 | if self.csizes[0] == 1 { | |
53 | self.buf.remove(0); | |
54 | self.csizes[0] -= 1; | |
55 | } | |
56 | if self.csizes[0] == 0 { | |
57 | self.csizes.remove(0); | |
58 | } | |
59 | } else { | |
60 | println!("ran past input chunk end!"); | |
61 | self.csizes.clear(); | |
62 | } | |
63 | } | |
64 | } | |
65 | } | |
66 | ||
67 | impl NAPacketiser for WssPacketiser { | |
68 | fn attach_stream(&mut self, stream: NAStreamRef) { | |
69 | self.stream = Some(stream); | |
70 | } | |
71 | fn add_data(&mut self, src: &[u8]) -> bool { | |
72 | self.csizes.push(src.len()); | |
73 | self.buf.extend_from_slice(src); | |
74 | self.buf.len() < (1 << 10) | |
75 | } | |
76 | fn parse_stream(&mut self, id: u32) -> DecoderResult<NAStreamRef> { | |
77 | if let Some(ref stream) = self.stream { | |
78 | let mut stream = NAStream::clone(stream); | |
79 | stream.id = id; | |
80 | Ok(stream.into_ref()) | |
81 | } else { | |
82 | Err(DecoderError::MissingReference) | |
83 | } | |
84 | } | |
85 | fn skip_junk(&mut self) -> DecoderResult<usize> { | |
86 | Err(DecoderError::NotImplemented) | |
87 | } | |
88 | fn get_packet(&mut self, stream: NAStreamRef) -> DecoderResult<Option<NAPacket>> { | |
89 | loop { | |
90 | if self.buf.len() < 4 || self.buf.len() < self.frame_size { | |
91 | return Ok(None); | |
92 | } | |
93 | ||
94 | if self.frame_size == 0 { | |
95 | self.frame_size = read_u32le(&self.buf)? as usize; | |
96 | if self.frame_size == 0 { | |
97 | self.remove_payload(4); | |
98 | self.frameno += 1; | |
99 | continue; | |
100 | } | |
101 | if self.frame_size == 0xFFFFFFFF { | |
102 | self.pal_mode = true; | |
103 | self.frame_size = 1024; | |
104 | } | |
105 | self.frame_size += 4; | |
106 | validate!(self.frame_size > 16); | |
107 | if self.buf.len() >= self.frame_size { | |
108 | if self.pal_mode { | |
109 | self.palette.read_data(&self.buf[4..][..1024]); | |
110 | self.remove_payload(self.frame_size); | |
111 | self.pal_mode = false; | |
112 | self.has_pal = true; | |
113 | self.frame_size = 0; | |
114 | continue; | |
115 | } | |
116 | break; | |
117 | } | |
118 | } | |
119 | } | |
120 | ||
121 | let mut data = Vec::with_capacity(self.frame_size); | |
122 | data.extend_from_slice(&self.buf[16..self.frame_size]); | |
123 | self.remove_payload(self.frame_size); | |
124 | ||
125 | let mut is_intra = false; | |
126 | if let Some(ref stream) = self.stream { | |
127 | #[allow(clippy::single_match)] | |
128 | match stream.get_info().get_name() { | |
129 | "cinepak" => is_intra = (data[0] & 1) == 0, | |
130 | _ => {}, | |
131 | }; | |
132 | } | |
133 | ||
134 | let ts = NATimeInfo::new(Some(u64::from(self.frameno)), None, None, stream.tb_num, stream.tb_den); | |
135 | self.frameno += 1; | |
136 | self.frame_size = 0; | |
137 | ||
138 | let mut pkt = NAPacket::new(stream, ts, is_intra, data); | |
139 | if self.has_pal { | |
140 | pkt.add_side_data(self.palette.get_side_data()); | |
141 | } | |
142 | ||
143 | Ok(Some(pkt)) | |
144 | } | |
145 | fn reset(&mut self) { | |
146 | self.buf.clear(); | |
147 | } | |
148 | fn bytes_left(&self) -> usize { self.buf.len() } | |
149 | } | |
150 | ||
151 | #[cfg(feature="packetiser_cinepak")] | |
152 | pub fn get_packetiser_cinepak() -> Box<dyn NAPacketiser + Send> { | |
153 | Box::new(WssPacketiser::new()) | |
154 | } | |
155 | ||
156 | #[cfg(feature="packetiser_msvideo1")] | |
157 | pub fn get_packetiser_msvideo1() -> Box<dyn NAPacketiser + Send> { | |
158 | Box::new(WssPacketiser::new()) | |
159 | } |