aac: clear M/S flags
[nihav.git] / nihav-acorn / src / codecs / wss_packetisers.rs
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 }