Commit | Line | Data |
---|---|---|
cf64af13 KS |
1 | use std::mem; |
2 | use std::ops::Add; | |
3 | use super::*; | |
4 | use super::blockdsp; | |
5 | use super::h263code::*; | |
6 | use formats; | |
7 | ||
8 | #[derive(Debug,Clone,Copy,PartialEq)] | |
9 | pub enum Type { | |
10 | I, P, Skip, Special | |
11 | } | |
12 | ||
13 | #[allow(dead_code)] | |
14 | #[derive(Debug,Clone,Copy)] | |
15 | pub struct PicInfo { | |
16 | w: usize, | |
17 | h: usize, | |
18 | mode: Type, | |
19 | quant: u8, | |
20 | apm: bool, | |
21 | umv: bool, | |
22 | pb: bool, | |
23 | ts: u8, | |
24 | } | |
25 | ||
26 | #[allow(dead_code)] | |
27 | impl PicInfo { | |
28 | pub fn new(w: usize, h: usize, mode: Type, quant: u8, apm: bool, umv: bool, pb: bool, ts: u8) -> Self { | |
29 | PicInfo{ w: w, h: h, mode: mode, quant: quant, apm: apm, umv: umv, pb: pb, ts: ts } | |
30 | } | |
31 | pub fn get_width(&self) -> usize { self.w } | |
32 | pub fn get_height(&self) -> usize { self.h } | |
33 | pub fn get_mode(&self) -> Type { self.mode } | |
34 | pub fn get_quant(&self) -> u8 { self.quant } | |
35 | pub fn get_apm(&self) -> bool { self.apm } | |
36 | pub fn get_umv(&self) -> bool { self.umv } | |
37 | pub fn is_pb(&self) -> bool { self.pb } | |
38 | pub fn get_ts(&self) -> u8 { self.ts } | |
39 | } | |
40 | ||
41 | #[derive(Debug,Clone,Copy)] | |
42 | pub struct Slice { | |
43 | mb_x: usize, | |
44 | mb_y: usize, | |
45 | quant: u8, | |
46 | } | |
47 | ||
48 | impl Slice { | |
49 | pub fn new(mb_x: usize, mb_y: usize, quant: u8) -> Self { | |
50 | Slice{ mb_x: mb_x, mb_y: mb_y, quant: quant } | |
51 | } | |
52 | pub fn get_default_slice(pinfo: &PicInfo) -> Self { | |
53 | Slice{ mb_x: 0, mb_y: 0, quant: pinfo.get_quant() } | |
54 | } | |
55 | pub fn get_quant(&self) -> u8 { self.quant } | |
56 | } | |
57 | ||
58 | #[derive(Debug,Clone,Copy)] | |
59 | pub struct MV { | |
60 | x: i16, | |
61 | y: i16, | |
62 | } | |
63 | ||
64 | impl MV { | |
65 | pub fn new(x: i16, y: i16) -> Self { MV{ x: x, y: y } } | |
66 | pub fn pred(a: MV, b: MV, c: MV) -> Self { | |
67 | let x; | |
68 | if a.x < b.x { | |
69 | if b.x < c.x { | |
70 | x = b.x; | |
71 | } else { | |
72 | if a.x < c.x { x = c.x; } else { x = a.x; } | |
73 | } | |
74 | } else { | |
75 | if b.x < c.x { | |
76 | if a.x < c.x { x = a.x; } else { x = c.x; } | |
77 | } else { | |
78 | x = b.x; | |
79 | } | |
80 | } | |
81 | let y; | |
82 | if a.y < b.y { | |
83 | if b.y < c.y { | |
84 | y = b.y; | |
85 | } else { | |
86 | if a.y < c.y { y = c.y; } else { y = a.y; } | |
87 | } | |
88 | } else { | |
89 | if b.y < c.y { | |
90 | if a.y < c.y { y = a.y; } else { y = c.y; } | |
91 | } else { | |
92 | y = b.y; | |
93 | } | |
94 | } | |
95 | MV { x: x, y: y } | |
96 | } | |
97 | fn add_umv(pred_mv: MV, add: MV, umv: bool) -> Self { | |
98 | let mut new_mv = pred_mv + add; | |
99 | if umv { | |
100 | if pred_mv.x > 32 && new_mv.x > 63 { new_mv.x -= 64; } | |
101 | if pred_mv.x < -31 && new_mv.x < -63 { new_mv.x += 64; } | |
102 | if pred_mv.y > 32 && new_mv.y > 63 { new_mv.y -= 64; } | |
103 | if pred_mv.y < -31 && new_mv.y < -63 { new_mv.y += 64; } | |
104 | } else { | |
105 | if new_mv.x > 31 { new_mv.x -= 64; } | |
106 | else if new_mv.x < -32 { new_mv.x += 64; } | |
107 | if new_mv.y > 31 { new_mv.y -= 64; } | |
108 | else if new_mv.y < -32 { new_mv.y += 64; } | |
109 | } | |
110 | new_mv | |
111 | } | |
112 | } | |
113 | ||
114 | pub const ZERO_MV: MV = MV { x: 0, y: 0 }; | |
115 | ||
116 | impl Add for MV { | |
117 | type Output = MV; | |
118 | fn add(self, other: MV) -> MV { MV { x: self.x + other.x, y: self.y + other.y } } | |
119 | } | |
120 | ||
121 | #[derive(Debug,Clone,Copy)] | |
122 | pub struct BlockInfo { | |
123 | intra: bool, | |
124 | skip: bool, | |
125 | mode: Type, | |
126 | cbp: u8, | |
127 | q: u8, | |
128 | mv: [MV; 4], | |
129 | num_mv: usize, | |
130 | bpart: bool, | |
131 | b_cbp: u8, | |
132 | mv2: [MV; 4], | |
133 | num_mv2: usize, | |
134 | } | |
135 | ||
136 | #[allow(dead_code)] | |
137 | impl BlockInfo { | |
138 | pub fn new(mode: Type, cbp: u8, q: u8) -> Self { | |
139 | BlockInfo { | |
140 | intra: mode == Type::I, | |
141 | skip: (cbp == 0) && (mode != Type::I), | |
142 | mode: mode, | |
143 | cbp: cbp, | |
144 | q: q, | |
145 | mv: [MV::new(0, 0), MV::new(0, 0), MV::new(0, 0), MV::new(0, 0)], | |
146 | num_mv: 0, | |
147 | bpart: false, | |
148 | b_cbp: 0, | |
149 | mv2: [MV::new(0, 0), MV::new(0, 0), MV::new(0, 0), MV::new(0, 0)], | |
150 | num_mv2: 0, | |
151 | } | |
152 | } | |
153 | pub fn is_intra(&self) -> bool { self.intra } | |
154 | pub fn is_skipped(&self) -> bool { self.skip } | |
155 | pub fn get_mode(&self) -> Type { self.mode } | |
156 | pub fn get_cbp(&self) -> u8 { self.cbp } | |
157 | pub fn get_q(&self) -> u8 { self.q } | |
158 | pub fn get_num_mvs(&self) -> usize { self.num_mv } | |
159 | pub fn get_mv(&self, idx: usize) -> MV { self.mv[idx] } | |
160 | pub fn has_b_part(&self) -> bool { self.bpart } | |
161 | pub fn get_cbp_b(&self) -> u8 { self.b_cbp } | |
162 | pub fn get_num_mvs2(&self) -> usize { self.num_mv2 } | |
163 | pub fn get_mv2(&self, idx: usize) -> MV { self.mv2[idx] } | |
164 | pub fn set_mv(&mut self, mvs: &[MV]) { | |
165 | if mvs.len() > 0 { self.skip = false; } | |
166 | self.bpart = true; | |
167 | let mut mv_arr: [MV; 4] = [MV::new(0, 0), MV::new(0, 0), MV::new(0, 0), MV::new(0, 0)]; | |
168 | for i in 0..mvs.len() { mv_arr[i] = mvs[i]; } | |
169 | self.mv = mv_arr; | |
170 | self.num_mv = mvs.len(); | |
171 | } | |
172 | pub fn set_mv2(&mut self, cbp: u8, mvs: &[MV]) { | |
173 | self.bpart = true; | |
174 | self.b_cbp = cbp; | |
175 | let mut mv_arr: [MV; 4] = [MV::new(0, 0), MV::new(0, 0), MV::new(0, 0), MV::new(0, 0)]; | |
176 | for i in 0..mvs.len() { mv_arr[i] = mvs[i]; } | |
177 | self.mv2 = mv_arr; | |
178 | self.num_mv2 = mvs.len(); | |
179 | } | |
180 | } | |
181 | ||
182 | pub trait BlockDecoder { | |
183 | fn decode_pichdr(&mut self) -> DecoderResult<PicInfo>; | |
184 | fn decode_slice_header(&mut self, pinfo: &PicInfo) -> DecoderResult<Slice>; | |
185 | fn decode_block_header(&mut self, pinfo: &PicInfo, sinfo: &Slice) -> DecoderResult<BlockInfo>; | |
186 | fn decode_block_intra(&mut self, info: &BlockInfo, no: usize, coded: bool, blk: &mut [i16; 64]) -> DecoderResult<()>; | |
187 | fn decode_block_inter(&mut self, info: &BlockInfo, no: usize, coded: bool, blk: &mut [i16; 64]) -> DecoderResult<()>; | |
188 | fn calc_mv(&mut self, vec: MV); | |
189 | fn is_slice_end(&mut self) -> bool; | |
190 | } | |
191 | ||
192 | #[allow(dead_code)] | |
193 | struct MVInfo { | |
194 | mv: Vec<MV>, | |
195 | mb_w: usize, | |
196 | mb_stride: usize, | |
197 | mb_start: usize, | |
198 | top: bool, | |
199 | umv: bool, | |
200 | } | |
201 | ||
202 | impl MVInfo { | |
203 | fn new() -> Self { MVInfo{ mv: Vec::new(), mb_w: 0, mb_stride: 0, mb_start: 0, top: true, umv: false } } | |
204 | fn reset(&mut self, mb_w: usize, mb_start: usize, umv: bool) { | |
205 | self.mb_start = mb_start; | |
206 | self.mb_w = mb_w; | |
207 | self.mb_stride = mb_w * 2; | |
208 | self.top = true; | |
209 | self.mv.resize(self.mb_stride * 3, ZERO_MV); | |
210 | self.umv = umv; | |
211 | } | |
212 | fn update_row(&mut self) { | |
213 | self.mb_start = self.mb_w + 1; | |
214 | self.top = false; | |
215 | for i in 0..self.mb_stride { | |
216 | self.mv[i] = self.mv[self.mb_stride * 2 + i]; | |
217 | } | |
218 | } | |
219 | #[allow(non_snake_case)] | |
220 | fn predict(&mut self, mb_x: usize, blk_no: usize, use4: bool, diff: MV) -> MV { | |
221 | let A; | |
222 | let B; | |
223 | let C; | |
224 | let last = mb_x == self.mb_w - 1; | |
225 | //println!(" pred from {}.{} blk {}.{}/{} top {}", diff.x, diff.y, mb_x, blk_no,self.mb_start,self.top); | |
226 | match blk_no { | |
227 | 0 => { | |
228 | if mb_x != self.mb_start { | |
229 | A = if mb_x != 0 { self.mv[self.mb_stride + mb_x * 2 - 1] } else { ZERO_MV }; | |
230 | B = if !self.top { self.mv[ mb_x * 2] } else { A }; | |
231 | C = if !self.top && !last { self.mv[mb_x * 2 + 2] } else { ZERO_MV }; | |
232 | } else { | |
233 | A = ZERO_MV; B = ZERO_MV; C = ZERO_MV; | |
234 | } | |
235 | }, | |
236 | 1 => { | |
237 | A = self.mv[self.mb_stride + mb_x * 2]; | |
238 | B = if !self.top { self.mv[mb_x * 2 + 1] } else { A }; | |
239 | C = if !self.top && !last { self.mv[mb_x * 2 + 2] } else { A }; | |
240 | }, | |
241 | 2 => { | |
242 | A = if mb_x != self.mb_start { self.mv[self.mb_stride * 2 + mb_x * 2 - 1] } else { ZERO_MV }; | |
243 | B = self.mv[self.mb_stride + mb_x * 2]; | |
244 | C = self.mv[self.mb_stride + mb_x * 2 + 1]; | |
245 | }, | |
246 | 3 => { | |
247 | A = self.mv[self.mb_stride * 2 + mb_x * 2]; | |
248 | B = self.mv[self.mb_stride * 1 + mb_x * 2 + 1]; | |
249 | C = self.mv[self.mb_stride * 1 + mb_x * 2]; | |
250 | }, | |
251 | _ => { return ZERO_MV; } | |
252 | } | |
253 | //println!(" A = {}.{} B = {}.{} C = {}.{}", A.x,A.y,B.x,B.y,C.x,C.y); | |
254 | let pred_mv = MV::pred(A, B, C); | |
255 | let new_mv = MV::add_umv(pred_mv, diff, self.umv); | |
256 | if !use4 { | |
257 | self.mv[self.mb_stride * 1 + mb_x * 2 + 0] = new_mv; | |
258 | self.mv[self.mb_stride * 1 + mb_x * 2 + 1] = new_mv; | |
259 | self.mv[self.mb_stride * 2 + mb_x * 2 + 0] = new_mv; | |
260 | self.mv[self.mb_stride * 2 + mb_x * 2 + 1] = new_mv; | |
261 | } else { | |
262 | match blk_no { | |
263 | 0 => { self.mv[self.mb_stride * 1 + mb_x * 2 + 0] = new_mv; }, | |
264 | 1 => { self.mv[self.mb_stride * 1 + mb_x * 2 + 1] = new_mv; }, | |
265 | 2 => { self.mv[self.mb_stride * 2 + mb_x * 2 + 0] = new_mv; }, | |
266 | 3 => { self.mv[self.mb_stride * 2 + mb_x * 2 + 1] = new_mv; }, | |
267 | _ => {}, | |
268 | }; | |
269 | } | |
270 | ||
271 | new_mv | |
272 | } | |
273 | fn set_zero_mv(&mut self, mb_x: usize) { | |
274 | self.mv[self.mb_stride * 1 + mb_x * 2 + 0] = ZERO_MV; | |
275 | self.mv[self.mb_stride * 1 + mb_x * 2 + 1] = ZERO_MV; | |
276 | self.mv[self.mb_stride * 2 + mb_x * 2 + 0] = ZERO_MV; | |
277 | self.mv[self.mb_stride * 2 + mb_x * 2 + 1] = ZERO_MV; | |
278 | } | |
279 | } | |
280 | ||
281 | fn copy_blocks(dst: &mut NAVideoBuffer<u8>, src: &NAVideoBuffer<u8>, xpos: usize, ypos: usize, w: usize, h: usize, mv: MV) { | |
282 | let srcx = ((mv.x >> 1) as isize) + (xpos as isize); | |
283 | let srcy = ((mv.y >> 1) as isize) + (ypos as isize); | |
284 | let mode = ((mv.x & 1) + (mv.y & 1) * 2) as usize; | |
285 | ||
286 | blockdsp::copy_blocks(dst, src, xpos, ypos, srcx, srcy, w, h, 0, 1, mode, H263_INTERP_FUNCS); | |
287 | } | |
288 | ||
289 | pub struct DCT8x8VideoDecoder { | |
290 | w: usize, | |
291 | h: usize, | |
292 | mb_w: usize, | |
293 | mb_h: usize, | |
294 | num_mb: usize, | |
295 | ftype: Type, | |
296 | prev_frm: Option<NAVideoBuffer<u8>>, | |
297 | cur_frm: Option<NAVideoBuffer<u8>>, | |
298 | } | |
299 | ||
300 | #[allow(dead_code)] | |
301 | impl DCT8x8VideoDecoder { | |
302 | pub fn new() -> Self { | |
303 | DCT8x8VideoDecoder{ | |
304 | w: 0, h: 0, mb_w: 0, mb_h: 0, num_mb: 0, | |
305 | ftype: Type::Special, | |
306 | prev_frm: None, cur_frm: None, | |
307 | } | |
308 | } | |
309 | ||
310 | pub fn is_intra(&self) -> bool { self.ftype == Type::I } | |
311 | pub fn get_dimensions(&self) -> (usize, usize) { (self.w, self.h) } | |
312 | ||
313 | pub fn parse_frame(&mut self, bd: &mut BlockDecoder) -> DecoderResult<NABufferType> { | |
314 | let pinfo = bd.decode_pichdr()?; | |
315 | let mut mvi = MVInfo::new(); | |
316 | ||
317 | //todo handle res change | |
318 | self.w = pinfo.w; | |
319 | self.h = pinfo.h; | |
320 | self.mb_w = (pinfo.w + 15) >> 4; | |
321 | self.mb_h = (pinfo.h + 15) >> 4; | |
322 | self.num_mb = self.mb_w * self.mb_h; | |
323 | self.ftype = pinfo.mode; | |
324 | ||
325 | mem::swap(&mut self.cur_frm, &mut self.prev_frm); | |
326 | // if self.ftype == Type::I && !pinfo.is_pb() { self.prev_frm = None; } | |
327 | ||
328 | let fmt = formats::YUV420_FORMAT; | |
329 | let vinfo = NAVideoInfo::new(self.w, self.h, false, fmt); | |
330 | let bufret = alloc_video_buffer(vinfo, 4); | |
331 | if let Err(_) = bufret { return Err(DecoderError::InvalidData); } | |
332 | let mut bufinfo = bufret.unwrap(); | |
333 | let mut buf = bufinfo.get_vbuf().unwrap(); | |
334 | ||
335 | let mut bbuf; | |
336 | ||
337 | if self.prev_frm.is_some() && pinfo.is_pb() { | |
338 | let bufret = alloc_video_buffer(vinfo, 4); | |
339 | if let Err(_) = bufret { return Err(DecoderError::InvalidData); } | |
340 | let mut bbufinfo = bufret.unwrap(); | |
341 | bbuf = Some(bbufinfo.get_vbuf().unwrap()); | |
342 | } else { | |
343 | bbuf = None; | |
344 | } | |
345 | ||
346 | let mut slice = Slice::get_default_slice(&pinfo); | |
347 | mvi.reset(self.mb_w, 0, pinfo.get_umv()); | |
348 | ||
349 | let mut blk: [[i16; 64]; 6] = [[0; 64]; 6]; | |
350 | for mb_y in 0..self.mb_h { | |
351 | for mb_x in 0..self.mb_w { | |
352 | for i in 0..6 { for j in 0..64 { blk[i][j] = 0; } } | |
353 | ||
354 | if ((mb_x != 0) || (mb_y != 0)) && bd.is_slice_end() { | |
355 | //println!("new slice @{}.{}!",mb_x,mb_y); | |
356 | slice = bd.decode_slice_header(&pinfo)?; | |
357 | mvi.reset(self.mb_w, mb_x, pinfo.get_umv()); | |
358 | } | |
359 | ||
360 | let binfo = bd.decode_block_header(&pinfo, &slice)?; | |
361 | let cbp = binfo.get_cbp(); | |
362 | //println!("mb {}.{} CBP {:X} type {:?}, {} mvs skip {}", mb_x,mb_y, cbp, binfo.get_mode(), binfo.get_num_mvs(),binfo.is_skipped()); | |
363 | if binfo.is_intra() { | |
364 | for i in 0..6 { | |
365 | bd.decode_block_intra(&binfo, i, (cbp & (1 << (5 - i))) != 0, &mut blk[i])?; | |
366 | h263_idct(&mut blk[i]); | |
367 | } | |
368 | blockdsp::put_blocks(&mut buf, mb_x, mb_y, &blk); | |
369 | mvi.set_zero_mv(mb_x); | |
370 | } else if !binfo.is_skipped() { | |
371 | if binfo.get_num_mvs() == 1 { | |
372 | let mv = mvi.predict(mb_x, 0, false, binfo.get_mv(0)); | |
373 | //println!(" 1MV {}.{}", mv.x, mv.y); | |
374 | if let Some(ref srcbuf) = self.prev_frm { | |
375 | copy_blocks(&mut buf, srcbuf, mb_x * 16, mb_y * 16, 16, 16, mv); | |
376 | } | |
377 | } else { | |
378 | for blk_no in 0..4 { | |
379 | let mv = mvi.predict(mb_x, blk_no, true, binfo.get_mv(blk_no)); | |
380 | //print!(" MV {}.{}", mv.x, mv.y); | |
381 | if let Some(ref srcbuf) = self.prev_frm { | |
382 | copy_blocks(&mut buf, srcbuf, | |
383 | mb_x * 16 + (blk_no & 1) * 8, | |
384 | mb_y * 16 + (blk_no & 2) * 4, 8, 8, mv); | |
385 | } | |
386 | } | |
387 | //println!(""); | |
388 | } | |
389 | for i in 0..6 { | |
390 | bd.decode_block_inter(&binfo, i, ((cbp >> (5 - i)) & 1) != 0, &mut blk[i])?; | |
391 | h263_idct(&mut blk[i]); | |
392 | } | |
393 | blockdsp::add_blocks(&mut buf, mb_x, mb_y, &blk); | |
394 | } else { | |
395 | mvi.set_zero_mv(mb_x); | |
396 | if let Some(ref srcbuf) = self.prev_frm { | |
397 | copy_blocks(&mut buf, srcbuf, mb_x * 16, mb_y * 16, 16, 16, ZERO_MV); | |
398 | } | |
399 | } | |
400 | if pinfo.is_pb() && binfo.has_b_part() { | |
401 | let mut blk: [[i16; 64]; 6] = [[0; 64]; 6]; | |
402 | let cbp = binfo.get_cbp_b(); | |
403 | for i in 0..6 { | |
404 | bd.decode_block_inter(&binfo, i, (cbp & (1 << (5 - i))) != 0, &mut blk[i])?; | |
405 | h263_idct(&mut blk[i]); | |
406 | } | |
407 | if let Some(ref mut b_buf) = bbuf { | |
408 | /* let is_fwd = false; | |
409 | if binfo.get_num_mvs() == 1 { //todo scale | |
410 | let mv_f = MV::add_umv(binfo.get_mv(0), binfo.get_mv2(0), pinfo.get_umv()); | |
411 | let mv_b = ZERO_MV//if component = 0 then scaled else mv_f - component | |
412 | } else { | |
413 | }*/ | |
414 | if let Some(ref srcbuf) = self.prev_frm { | |
415 | copy_blocks(b_buf, srcbuf, mb_x * 16, mb_y * 16, 16, 16, ZERO_MV); | |
416 | blockdsp::add_blocks(b_buf, mb_x, mb_y, &blk); | |
417 | } | |
418 | } | |
419 | } | |
420 | ||
421 | } | |
422 | mvi.update_row(); | |
423 | } | |
424 | self.cur_frm = Some(buf); | |
425 | if pinfo.is_pb() { | |
426 | return Ok(NABufferType::Video(bbuf.unwrap())); | |
427 | } | |
428 | println!("unpacked all"); | |
429 | Ok(bufinfo) | |
430 | } | |
431 | ||
432 | pub fn get_stored_pframe(&mut self) -> DecoderResult<NABufferType> { | |
433 | if let Some(_) = self.cur_frm { | |
434 | let buf = self.cur_frm.clone().unwrap(); | |
435 | Ok(NABufferType::Video(buf)) | |
436 | } else { | |
437 | Err(DecoderError::MissingReference) | |
438 | } | |
439 | } | |
440 | } |