aac: clear M/S flags
[nihav.git] / nihav-acorn / src / codecs / movinglines.rs
1 use nihav_core::codecs::*;
2 use nihav_core::io::byteio::*;
3
4 use super::RGB555_FORMAT;
5 use super::yuvtab::YUV2RGB;
6
7 const END_CODE: u16 = 0x7300;
8
9 #[derive(Default)]
10 struct MLDecoder {
11 info: NACodecInfoRef,
12 cur_frm: Vec<u16>,
13 prev_frm: Vec<u16>,
14 width: usize,
15 is_yuv: bool,
16 }
17
18 impl MLDecoder {
19 fn new() -> Self { Self::default() }
20 }
21
22 impl NADecoder for MLDecoder {
23 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
24 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
25 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(vinfo.get_width(), vinfo.get_height(), false, RGB555_FORMAT));
26 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
27 self.cur_frm = vec![0; vinfo.get_width() * vinfo.get_height()];
28 self.prev_frm = vec![0; vinfo.get_width() * vinfo.get_height()];
29 self.width = vinfo.get_width();
30 if let Some(edata) = info.get_extradata() {
31 for triplet in edata.windows(3) {
32 if triplet == b"YUV" {
33 self.is_yuv = true;
34 break;
35 }
36 }
37 }
38 Ok(())
39 } else {
40 Err(DecoderError::InvalidData)
41 }
42 }
43 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
44 let src = pkt.get_buffer();
45 validate!(src.len() > 2 && (src.len() & 1) == 0);
46 let mut mr = MemoryReader::new_read(&src);
47 let mut br = ByteReader::new(&mut mr);
48
49 let mut is_intra = true;
50 let mut dpos = 0;
51 while dpos < self.cur_frm.len() {
52 let op = br.read_u16le()?;
53 let raw_flag = (op & 1) == 0;
54 let val = op >> 1;
55 if raw_flag {
56 self.cur_frm[dpos] = val;
57 dpos += 1;
58 } else {
59 match val {
60 0..=0x47FF => { // copy prev
61 let len = ((val & 0x3F) + 2) as usize;
62 validate!(dpos + len <= self.cur_frm.len());
63
64 let mut idx = (val >> 6) as isize;
65 if idx >= 144 { // skip (0,0)
66 idx += 1;
67 }
68 let dy = idx / 17 - 8;
69 let dx = idx % 17 - 8;
70 let spos = dpos as isize + dx + dy * (self.width as isize);
71 validate!(spos >= 0);
72 let mut spos = spos as usize;
73 validate!(spos + len <= self.prev_frm.len());
74
75 for _ in 0..len {
76 self.cur_frm[dpos] = self.prev_frm[spos];
77 dpos += 1;
78 spos += 1;
79 }
80
81 is_intra = false;
82 },
83 0x4800..=0x72FF => { // copy cur
84 let len = ((val & 0x3F) + 2) as usize;
85 validate!(dpos + len <= self.cur_frm.len());
86
87 let idx = ((val >> 6) as usize) - 0x120;
88 let dx = idx % 19;
89 let dy = 9 - (idx / 19);
90 validate!(dpos + dx >= dy * self.width + 9);
91 let mut spos = dpos + dx - 9 - dy * self.width;
92
93 for _ in 0..len {
94 self.cur_frm[dpos] = self.cur_frm[spos];
95 dpos += 1;
96 spos += 1;
97 }
98 },
99 END_CODE => break, // end of frame
100 0x7301..=0x77FF => { // run
101 let len = ((val & 0x3F) + 2) as usize;
102 let pix = br.read_u16le()?;
103 validate!(dpos + len <= self.cur_frm.len());
104 for _ in 0..len {
105 self.cur_frm[dpos] = pix;
106 dpos += 1;
107 }
108 },
109 0x7800..=0x7BFF => { // skip
110 let len = ((val & 0x3FF) + 1) as usize;
111 validate!(dpos + len <= self.cur_frm.len());
112 for _ in 0..len {
113 self.cur_frm[dpos] = self.prev_frm[dpos];
114 dpos += 1;
115 }
116 is_intra = false;
117 },
118 0x7C00.. => { // raw
119 let len = ((val & 0x3FF) + 1) as usize;
120 validate!(dpos + len <= self.cur_frm.len());
121 let mut bitbuf = u32::from(br.read_u16le()?);
122 let mut bits = 16;
123 for _ in 0..len {
124 if bits < 15 {
125 bitbuf |= u32::from(br.read_u16le()?) << bits;
126 bits += 16;
127 }
128 self.cur_frm[dpos] = (bitbuf & 0x7FFF) as u16;
129 bitbuf >>= 15;
130 bits -= 15;
131 dpos += 1;
132 }
133 },
134 }
135 }
136 }
137 validate!(br.left() == 2 && br.read_u16le()? == (END_CODE * 2 + 1));
138
139 let bufinfo = alloc_video_buffer(self.info.get_properties().get_video_info().unwrap(), 0)?;
140 let mut buf = bufinfo.get_vbuf16().unwrap();
141 let stride = buf.get_stride(0);
142 let data = buf.get_data_mut().unwrap();
143
144 for (dline, sline) in data.chunks_exact_mut(stride)
145 .zip(self.cur_frm.chunks_exact(self.width)) {
146 dline[..self.width].copy_from_slice(sline);
147 }
148 if self.is_yuv {
149 for el in data.iter_mut() {
150 *el = YUV2RGB[(*el as usize) & 0x7FFF];
151 }
152 }
153
154 std::mem::swap(&mut self.cur_frm, &mut self.prev_frm);
155
156 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo);
157 frm.set_keyframe(is_intra);
158 frm.set_frame_type(if is_intra { FrameType::I } else { FrameType::P });
159 Ok(frm.into_ref())
160 }
161 fn flush(&mut self) {
162 for el in self.cur_frm.iter_mut() {
163 *el = 0;
164 }
165 for el in self.prev_frm.iter_mut() {
166 *el = 0;
167 }
168 }
169 }
170
171 impl NAOptionHandler for MLDecoder {
172 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
173 fn set_options(&mut self, _options: &[NAOption]) { }
174 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
175 }
176
177 pub fn get_decoder() -> Box<dyn NADecoder + Send> {
178 Box::new(MLDecoder::new())
179 }
180
181 #[derive(Default)]
182 struct MLPacketiser {
183 stream: Option<NAStreamRef>,
184 buf: Vec<u8>,
185 end: usize,
186 frameno: u32,
187 intra: bool,
188 }
189
190 impl MLPacketiser {
191 fn new() -> Self { Self::default() }
192 }
193
194 impl NAPacketiser for MLPacketiser {
195 fn attach_stream(&mut self, stream: NAStreamRef) {
196 self.stream = Some(stream);
197 }
198 fn add_data(&mut self, src: &[u8]) -> bool {
199 self.buf.extend_from_slice(src);
200 self.buf.len() < (1 << 10)
201 }
202 fn parse_stream(&mut self, id: u32) -> DecoderResult<NAStreamRef> {
203 if let Some(ref stream) = self.stream {
204 let mut stream = NAStream::clone(stream);
205 stream.id = id;
206 Ok(stream.into_ref())
207 } else {
208 Err(DecoderError::MissingReference)
209 }
210 }
211 fn skip_junk(&mut self) -> DecoderResult<usize> {
212 Err(DecoderError::NotImplemented)
213 }
214 fn get_packet(&mut self, stream: NAStreamRef) -> DecoderResult<Option<NAPacket>> {
215 if self.buf.len() < self.end {
216 return Ok(None);
217 }
218
219 if self.end == 0 {
220 self.intra = true;
221 }
222
223 let mut found = false;
224 while self.end + 2 <= self.buf.len() {
225 let op = u16::from(self.buf[self.end + 1]) * 256 + u16::from(self.buf[self.end]);
226 self.end += 2;
227
228 if op == (END_CODE * 2 + 1) {
229 found = true;
230 break;
231 }
232 // run
233 if ((op & 1) == 1) && (0xE603..=0xEFFF).contains(&op) {
234 self.end += 2;
235 }
236 // raw data
237 if ((op & 1) == 1) && (op > 0xF800) {
238 let raw_size = (((op >> 1) & 0x3FF) + 1) as usize;
239 self.end += ((raw_size * 15 + 15) & !15) >> 3;
240 }
241 // copy from previous frame
242 if ((op & 1) == 1) && ((op < 0x9000) || (0xF001..=0xF7FF).contains(&op)) {
243 self.intra = false;
244 }
245 }
246
247 if found {
248 let mut data = Vec::with_capacity(self.end);
249 data.extend_from_slice(&self.buf[..self.end]);
250 self.buf.drain(..self.end);
251 let ts = NATimeInfo::new(Some(u64::from(self.frameno)), None, None, stream.tb_num, stream.tb_den);
252 self.end = 0;
253 self.frameno += 1;
254
255 return Ok(Some(NAPacket::new(stream, ts, self.intra, data)));
256 }
257
258 Ok(None)
259 }
260 fn reset(&mut self) {
261 self.buf.clear();
262 self.end = 0;
263 }
264 fn bytes_left(&self) -> usize { self.buf.len() }
265 }
266
267 pub fn get_packetiser() -> Box<dyn NAPacketiser + Send> {
268 Box::new(MLPacketiser::new())
269 }
270
271 #[cfg(test)]
272 mod test {
273 use nihav_core::codecs::{RegisteredDecoders, RegisteredPacketisers};
274 use nihav_core::demuxers::RegisteredRawDemuxers;
275 use nihav_codec_support::test::dec_video::*;
276 use crate::*;
277 #[test]
278 fn test_movinglines() {
279 let mut dmx_reg = RegisteredRawDemuxers::new();
280 acorn_register_all_raw_demuxers(&mut dmx_reg);
281 let mut pkt_reg = RegisteredPacketisers::new();
282 acorn_register_all_packetisers(&mut pkt_reg);
283 let mut dec_reg = RegisteredDecoders::new();
284 acorn_register_all_decoders(&mut dec_reg);
285
286 // a sample from Acorn Replay Demonstration Disc 2
287 test_decoding_raw("armovie", "movinglines", "assets/Acorn/CHEMSET2", Some(3),
288 &dmx_reg, &pkt_reg, &dec_reg,
289 ExpectedTestResult::MD5Frames(vec![
290 [0x2ba85570, 0x339ddc8f, 0x2e9ea4ba, 0xec6fa25c],
291 [0x17a5dd38, 0xab99b869, 0x63936887, 0x0cb05673],
292 [0x81d920cf, 0x57155044, 0xe13d1b8b, 0xb029e645],
293 [0x7dc1a826, 0xea3c8e29, 0x13398b07, 0xa9a647de]]));
294 }
295 }