]>
Commit | Line | Data |
---|---|---|
4965a5e5 KS |
1 | use nihav_core::frame::FrameType; |
2 | use nihav_core::io::bitwriter::*; | |
3 | use nihav_core::io::intcode::*; | |
4 | use nihav_codec_support::codecs::MV; | |
5 | use super::types::*; | |
6 | use super::super::rv34codes::*; | |
7 | use super::super::rv40data::*; | |
8 | ||
9 | pub fn write_slice_header(bw: &mut BitWriter, ftype: FrameType, q: usize, set_idx: usize, deblock: bool, pts: u32) { | |
10 | bw.write0(); | |
11 | match ftype { | |
12 | FrameType::I => bw.write(0, 2), | |
13 | FrameType::P => bw.write(2, 2), | |
14 | FrameType::B => bw.write(3, 2), | |
15 | _ => unreachable!(), | |
16 | }; | |
17 | bw.write(q as u32, 5); | |
18 | bw.write(0, 2); // unknown | |
19 | bw.write(set_idx as u32, 2); | |
20 | bw.write(!deblock as u32, 1); | |
21 | bw.write(pts, 13); | |
22 | } | |
23 | ||
24 | pub fn write_slice_dimensions(bw: &mut BitWriter, width: usize, height: usize) { | |
25 | let wcode = match width { | |
26 | 160 => 0, | |
27 | 176 => 1, | |
28 | 240 => 2, | |
29 | 320 => 3, | |
30 | 352 => 4, | |
31 | 640 => 5, | |
32 | 704 => 6, | |
33 | _ => 7, | |
34 | }; | |
35 | bw.write(wcode, 3); | |
36 | if wcode == 7 { | |
37 | let mut w = width >> 2; | |
38 | while w >= 255 { | |
39 | bw.write(255, 8); | |
40 | w -= 255; | |
41 | } | |
42 | bw.write(w as u32, 8); | |
43 | } | |
44 | ||
45 | let hcode = match height { | |
46 | 120 => 0, | |
47 | 132 => 1, | |
48 | 144 => 2, | |
49 | 240 => 3, | |
50 | 288 => 4, | |
51 | 480 => 5, | |
52 | 180 => 6, | |
53 | 360 => 7, | |
54 | 576 => 8, | |
55 | _ => 9, | |
56 | }; | |
57 | if hcode < 6 { | |
58 | bw.write(hcode, 3); | |
59 | } else { | |
60 | bw.write(hcode + 6, 4); | |
61 | if hcode == 9 { | |
62 | let mut h = height >> 2; | |
63 | while h >= 255 { | |
64 | bw.write(255, 8); | |
65 | h -= 255; | |
66 | } | |
67 | bw.write(h as u32, 8); | |
68 | } | |
69 | } | |
70 | } | |
71 | ||
72 | pub fn write_slice_mb_idx(bw: &mut BitWriter, mb_idx: usize, num_mbs: usize) { | |
73 | let mba_bits = match num_mbs - 1 { | |
74 | 0..= 47 => 6, | |
75 | 48..= 98 => 7, | |
76 | 99..= 395 => 9, | |
77 | 396..=1583 => 11, | |
78 | 1584..=6335 => 13, | |
79 | 6336..=9215 => 14, | |
80 | _ => unreachable!(), | |
81 | }; | |
82 | bw.write(mb_idx as u32, mba_bits); | |
83 | } | |
84 | ||
85 | pub fn write_skip_count(bw: &mut BitWriter, skip_count: u32) { | |
86 | bw.write_code(UintCodeType::Gamma, skip_count); | |
87 | } | |
88 | ||
89 | fn write_mv(bw: &mut BitWriter, mv: MV) { | |
90 | let xcode = if mv.x > 0 { (mv.x - 1) * 2 + 1 } else { -mv.x * 2 } as u32; | |
91 | let ycode = if mv.y > 0 { (mv.y - 1) * 2 + 1 } else { -mv.y * 2 } as u32; | |
92 | ||
93 | bw.write_code(UintCodeType::Gamma, xcode); | |
94 | bw.write_code(UintCodeType::Gamma, ycode); | |
95 | } | |
96 | ||
97 | pub fn write_mb_header(bw: &mut BitWriter, ftype: FrameType, sstate: &SliceState, mbstate: &MBState) { | |
98 | let mb_idx = mbstate.get_mb_idx(sstate.mb_x, sstate.mb_y); | |
99 | let pred_mbt = mbstate.get_pred_mbtype(sstate, ftype == FrameType::B); | |
100 | ||
101 | let set_id = pred_mbt.to_code(); | |
102 | ||
103 | if ftype != FrameType::I { | |
104 | let (codes, lens) = if ftype == FrameType::P { | |
105 | (&RV40_PTYPE_CODES[set_id][..], &RV40_PTYPE_BITS[set_id][..]) | |
106 | } else { | |
107 | (&RV40_BTYPE_CODES[set_id][..], &RV40_BTYPE_BITS[set_id][..]) | |
108 | }; | |
109 | let idx = mbstate.mb_type[mb_idx].to_code(); | |
110 | bw.write(codes[idx].into(), lens[idx]); | |
111 | } | |
112 | match mbstate.mb_type[mb_idx] { | |
113 | MBType::Intra16 => { | |
114 | if ftype == FrameType::I { | |
115 | bw.write1(); | |
116 | } | |
117 | bw.write(mbstate.ipred[mbstate.get_blk4_idx(sstate.mb_x, sstate.mb_y)] as u32, 2); | |
118 | }, | |
119 | MBType::Intra => { | |
120 | if ftype == FrameType::I { | |
121 | bw.write0(); | |
122 | bw.write1(); //dquant | |
123 | } | |
124 | let ystart = if sstate.has_t { 0 } else { 1 }; | |
125 | let mut blk4_idx = mbstate.get_blk4_idx(sstate.mb_x, sstate.mb_y); | |
126 | ||
127 | if !sstate.has_t { | |
128 | let mut code = 0; | |
129 | for &el in mbstate.ipred[blk4_idx..][..4].iter() { | |
130 | code = code * 2 + if el == 0 { 0 } else { 1 }; | |
131 | } | |
132 | bw.write(RV40_AIC_TOP_CODES[code].into(), RV40_AIC_TOP_BITS[code]); | |
133 | blk4_idx += mbstate.blk4_stride; | |
134 | } | |
135 | for y in ystart..4 { | |
136 | let mut x = 0; | |
137 | while x < 4 { | |
138 | let (lctx, tctx, trctx) = mbstate.get_ipred4x4_ctx(sstate.mb_x, sstate.mb_y, x, y); | |
139 | let mode = mbstate.ipred[blk4_idx + x]; | |
140 | let ctx_word = if x < 3 { | |
141 | ((trctx & 0xF) as u16) + (((tctx & 0xF) as u16) << 4) + (((lctx & 0xF) as u16) << 8) | |
142 | } else { 0xFFF }; | |
143 | if let Some(idx) = RV40_AIC_PATTERNS.iter().position(|&x| x == ctx_word) { | |
144 | let mode1 = mbstate.ipred[blk4_idx + x + 1]; | |
145 | let code = mode * 9 + mode1; | |
146 | bw.write(RV40_AIC_MODE2_CODES[idx][code as usize].into(), | |
147 | RV40_AIC_MODE2_BITS[idx][code as usize]); | |
148 | x += 2; | |
149 | } else if tctx != -1 && lctx != -1 { | |
150 | let idx = (tctx + lctx * 10) as usize; | |
151 | let code = mode as usize; | |
152 | bw.write(RV40_AIC_MODE1_CODES[idx][code].into(), | |
153 | RV40_AIC_MODE1_BITS[idx][code]); | |
154 | x += 1; | |
155 | } else { | |
156 | match lctx { | |
157 | -1 if tctx < 2 => { | |
158 | if mode == 0 { | |
159 | bw.write1(); | |
160 | } else { | |
161 | assert_eq!(mode, 1); | |
162 | bw.write0(); | |
163 | } | |
164 | }, | |
165 | 0 | 2 => { | |
166 | if mode == 0 { | |
167 | bw.write1(); | |
168 | } else { | |
169 | assert_eq!(mode, 2); | |
170 | bw.write0(); | |
171 | } | |
172 | }, | |
173 | _ => { | |
174 | assert_eq!(mode, 0); | |
175 | }, | |
176 | }; | |
177 | x += 1; | |
178 | } | |
179 | } | |
180 | blk4_idx += mbstate.blk4_stride; | |
181 | } | |
182 | }, | |
183 | MBType::P16x16 | MBType::P16x16Mix => { | |
184 | let diff_mv = mbstate.get_diff_mv(sstate, true, 0, 0); | |
185 | write_mv(bw, diff_mv); | |
186 | }, | |
187 | MBType::P16x8 => { | |
188 | let diff_mv = mbstate.get_diff_mv(sstate, true, 0, 0); | |
189 | write_mv(bw, diff_mv); | |
190 | let diff_mv = mbstate.get_diff_mv(sstate, true, 0, 1); | |
191 | write_mv(bw, diff_mv); | |
192 | }, | |
193 | MBType::P8x16 => { | |
194 | let diff_mv = mbstate.get_diff_mv(sstate, false, 0, 0); | |
195 | write_mv(bw, diff_mv); | |
196 | let diff_mv = mbstate.get_diff_mv(sstate, false, 1, 0); | |
197 | write_mv(bw, diff_mv); | |
198 | }, | |
199 | MBType::P8x8 => { | |
200 | for i in 0..4 { | |
201 | let diff_mv = mbstate.get_diff_mv(sstate, false, i & 1, i >> 1); | |
202 | write_mv(bw, diff_mv); | |
203 | } | |
204 | }, | |
205 | MBType::Forward => { | |
206 | let fwd_diff = mbstate.get_diff_mv_b(sstate, true); | |
207 | write_mv(bw, fwd_diff); | |
208 | }, | |
209 | MBType::Backward => { | |
210 | let bwd_diff = mbstate.get_diff_mv_b(sstate, false); | |
211 | write_mv(bw, bwd_diff); | |
212 | }, | |
213 | MBType::Bidir => { | |
214 | let fwd_diff = mbstate.get_diff_mv_b(sstate, true); | |
215 | let bwd_diff = mbstate.get_diff_mv_b(sstate, false); | |
216 | write_mv(bw, fwd_diff); | |
217 | write_mv(bw, bwd_diff); | |
218 | }, | |
219 | MBType::Invalid => unreachable!(), | |
220 | _ => unimplemented!(), | |
221 | }; | |
222 | } | |
223 | ||
224 | trait CodeWriter { | |
225 | fn write(&self, bw: &mut BitWriter, code: u16); | |
226 | } | |
227 | ||
228 | impl CodeWriter for RV34CodeReader { | |
229 | fn write(&self, bw: &mut BitWriter, to_write: u16) { | |
230 | for (&sym, (&code, &bits)) in self.syms.iter().zip(self.codes.iter().zip(self.lengths.iter())) { | |
231 | if sym == to_write { | |
232 | bw.write(code, bits); | |
233 | return; | |
234 | } | |
235 | } | |
236 | unreachable!(); | |
237 | } | |
238 | } | |
239 | ||
240 | impl CodeWriter for RV34CBPCodeReader { | |
241 | fn write(&self, bw: &mut BitWriter, to_write: u16) { | |
242 | for (&sym, (&code, &bits)) in self.syms.iter().zip(self.codes.iter().zip(self.lengths.iter())) { | |
243 | if u16::from(sym) == to_write { | |
244 | bw.write(code, bits); | |
245 | return; | |
246 | } | |
247 | } | |
248 | unreachable!(); | |
249 | } | |
250 | } | |
251 | ||
252 | struct CBPSet { | |
253 | cbp_pattern: RV34CodeReader, | |
254 | cbp: [RV34CBPCodeReader; 4] | |
255 | } | |
256 | ||
257 | impl CBPSet { | |
258 | fn new(intra: bool, set: usize, subset: usize) -> Self { | |
259 | if intra { | |
260 | let cbp_pat = RV34CodeReader::new(&RV34_INTRA_CBPPAT[set][subset]); | |
261 | let cbp0 = RV34CBPCodeReader::new(&RV34_INTRA_CBP[set][subset]); | |
262 | let cbp1 = RV34CBPCodeReader::new(&RV34_INTRA_CBP[set][subset + 1*2]); | |
263 | let cbp2 = RV34CBPCodeReader::new(&RV34_INTRA_CBP[set][subset + 2*2]); | |
264 | let cbp3 = RV34CBPCodeReader::new(&RV34_INTRA_CBP[set][subset + 3*2]); | |
265 | CBPSet { cbp_pattern: cbp_pat, cbp: [cbp0, cbp1, cbp2, cbp3] } | |
266 | } else { | |
267 | let cbp_pat = RV34CodeReader::new(&RV34_INTER_CBPPAT[set]); | |
268 | let cbp0 = RV34CBPCodeReader::new(&RV34_INTER_CBP[set][0]); | |
269 | let cbp1 = RV34CBPCodeReader::new(&RV34_INTER_CBP[set][1]); | |
270 | let cbp2 = RV34CBPCodeReader::new(&RV34_INTER_CBP[set][2]); | |
271 | let cbp3 = RV34CBPCodeReader::new(&RV34_INTER_CBP[set][3]); | |
272 | CBPSet { cbp_pattern: cbp_pat, cbp: [cbp0, cbp1, cbp2, cbp3] } | |
273 | } | |
274 | } | |
275 | } | |
276 | ||
277 | struct CoefSet { | |
278 | pat0: Vec<RV34CodeReader>, | |
279 | pat1: Vec<RV34CodeReader>, | |
280 | pat2: Vec<RV34CodeReader>, | |
281 | } | |
282 | ||
283 | impl CoefSet { | |
284 | fn new(intra: bool, set: usize) -> Self { | |
285 | if intra { | |
286 | let first0 = RV34CodeReader::new(&RV34_INTRA_FIRSTPAT[set][0]); | |
287 | let first1 = RV34CodeReader::new(&RV34_INTRA_FIRSTPAT[set][1]); | |
288 | let first2 = RV34CodeReader::new(&RV34_INTRA_FIRSTPAT[set][2]); | |
289 | let first3 = RV34CodeReader::new(&RV34_INTRA_FIRSTPAT[set][3]); | |
290 | let firsts = vec![first0, first1, first2, first3]; | |
291 | ||
292 | let second0 = RV34CodeReader::new(&RV34_INTRA_SECONDPAT[set][0]); | |
293 | let second1 = RV34CodeReader::new(&RV34_INTRA_SECONDPAT[set][1]); | |
294 | let seconds = vec![second0, second1]; | |
295 | ||
296 | let third0 = RV34CodeReader::new(&RV34_INTRA_THIRDPAT[set][0]); | |
297 | let third1 = RV34CodeReader::new(&RV34_INTRA_THIRDPAT[set][1]); | |
298 | let thirds = vec![third0, third1]; | |
299 | ||
300 | CoefSet { pat0: firsts, pat1: seconds, pat2: thirds } | |
301 | } else { | |
302 | let first0 = RV34CodeReader::new(&RV34_INTER_FIRSTPAT[set][0]); | |
303 | let first1 = RV34CodeReader::new(&RV34_INTER_FIRSTPAT[set][1]); | |
304 | let firsts = vec![first0, first1]; | |
305 | ||
306 | let second0 = RV34CodeReader::new(&RV34_INTER_SECONDPAT[set][0]); | |
307 | let second1 = RV34CodeReader::new(&RV34_INTER_SECONDPAT[set][1]); | |
308 | let seconds = vec![second0, second1]; | |
309 | ||
310 | let third0 = RV34CodeReader::new(&RV34_INTER_THIRDPAT[set][0]); | |
311 | let third1 = RV34CodeReader::new(&RV34_INTER_THIRDPAT[set][1]); | |
312 | let thirds = vec![third0, third1]; | |
313 | ||
314 | CoefSet { pat0: firsts, pat1: seconds, pat2: thirds } | |
315 | } | |
316 | } | |
317 | } | |
318 | ||
319 | struct FullSet { | |
320 | cbp: Vec<CBPSet>, | |
321 | cset: CoefSet, | |
322 | coeffs: RV34CodeReader, | |
323 | } | |
324 | ||
325 | impl FullSet { | |
326 | fn new(intra: bool, set: usize) -> Self { | |
327 | if intra { | |
328 | let cbp0 = CBPSet::new(intra, set, 0); | |
329 | let cbp1 = CBPSet::new(intra, set, 1); | |
330 | let cbp: Vec<CBPSet> = vec![cbp0, cbp1]; | |
331 | let cset = CoefSet::new(intra, set); | |
332 | let coeffs = RV34CodeReader::new(&RV34_INTRA_COEFFS[set]); | |
333 | FullSet { cbp, cset, coeffs } | |
334 | } else { | |
335 | let cbp0 = CBPSet::new(intra, set, 0); | |
336 | let cbp: Vec<CBPSet> = vec![cbp0]; | |
337 | let cset = CoefSet::new(intra, set); | |
338 | let coeffs = RV34CodeReader::new(&RV34_INTER_COEFFS[set]); | |
339 | FullSet { cbp, cset, coeffs } | |
340 | } | |
341 | } | |
342 | fn write_block(&self, bw: &mut BitWriter, blk: &Block, subset_idx: usize, luma: bool) { | |
343 | let sblk0 = [blk.coeffs[0], blk.coeffs[1], blk.coeffs[4], blk.coeffs[5]]; | |
344 | let sblk1 = [blk.coeffs[2], blk.coeffs[3], blk.coeffs[6], blk.coeffs[7]]; | |
345 | let sblk2 = [blk.coeffs[8], blk.coeffs[12], blk.coeffs[9], blk.coeffs[13]]; // sub-block 2 has different order | |
346 | let sblk3 = [blk.coeffs[10], blk.coeffs[11], blk.coeffs[14], blk.coeffs[15]]; | |
347 | ||
348 | let idx0 = get_subblock_index(&sblk0); | |
349 | let idx1 = get_subblock_index(&sblk1); | |
350 | let idx2 = get_subblock_index(&sblk2); | |
351 | let idx3 = get_subblock_index(&sblk3); | |
352 | ||
353 | let mut cflags = idx0; | |
354 | cflags = (cflags << 1) | ((idx1 != 0) as u16); | |
355 | cflags = (cflags << 1) | ((idx2 != 0) as u16); | |
356 | cflags = (cflags << 1) | ((idx3 != 0) as u16); | |
357 | ||
358 | self.cset.pat0[subset_idx].write(bw, cflags); | |
359 | ||
360 | if matches!(idx0, 0 | 27 | 54 | 81) { // only first coefficient is set | |
361 | write_single_coeff(bw, &self.coeffs, sblk0[0], 3); | |
362 | } else { | |
363 | write_coeffs(bw, &self.coeffs, &sblk0); | |
364 | } | |
365 | if idx1 != 0 { | |
366 | self.cset.pat1[!luma as usize].write(bw, idx1); | |
367 | write_coeffs(bw, &self.coeffs, &sblk1); | |
368 | } | |
369 | if idx2 != 0 { | |
370 | self.cset.pat1[!luma as usize].write(bw, idx2); | |
371 | write_coeffs(bw, &self.coeffs, &sblk2); | |
372 | } | |
373 | if idx3 != 0 { | |
374 | self.cset.pat2[!luma as usize].write(bw, idx3); | |
375 | write_coeffs(bw, &self.coeffs, &sblk3); | |
376 | } | |
377 | } | |
378 | } | |
379 | ||
380 | fn write_coeffs(bw: &mut BitWriter, coeffs: &RV34CodeReader, blk: &[i16; 4]) { | |
381 | for (&val, &limit) in blk.iter().zip([3i16, 2, 2, 2].iter()) { | |
382 | write_single_coeff(bw, coeffs, val, limit); | |
383 | } | |
384 | } | |
385 | ||
386 | fn write_single_coeff(bw: &mut BitWriter, coeffs: &RV34CodeReader, val: i16, limit: i16) { | |
387 | if val != 0 { | |
388 | if val.abs() >= limit { | |
389 | let mut val = (val.abs() - limit) as u16; | |
390 | if val > 23 { | |
391 | val -= 22; | |
392 | let bits = (15 - val.leading_zeros()) as u16; | |
393 | coeffs.write(bw, bits + 23); | |
394 | bw.write(u32::from(val - (1 << bits)), bits as u8); | |
395 | } else { | |
396 | coeffs.write(bw, val); | |
397 | } | |
398 | } | |
399 | if val > 0 { | |
400 | bw.write0(); | |
401 | } else { | |
402 | bw.write1(); | |
403 | } | |
404 | } | |
405 | } | |
406 | ||
407 | pub struct CodeSets { | |
408 | super_idx: usize, | |
409 | set_idx: usize, | |
410 | intra: bool, | |
411 | is16: bool, | |
412 | is_p16: bool, | |
413 | ||
414 | iset: Vec<FullSet>, | |
415 | pset: Vec<FullSet>, | |
416 | } | |
417 | ||
418 | impl CodeSets { | |
419 | pub fn new() -> Self { | |
420 | let mut iset: Vec<FullSet> = Vec::with_capacity(5); | |
421 | for set in 0..5 { iset.push(FullSet::new(true, set)); } | |
422 | let mut pset: Vec<FullSet> = Vec::with_capacity(7); | |
423 | for set in 0..7 { pset.push(FullSet::new(false, set)); } | |
424 | ||
425 | Self { | |
426 | iset, pset, | |
427 | super_idx: 0, | |
428 | set_idx: 0, | |
429 | intra: false, | |
430 | is16: false, | |
431 | is_p16: false, | |
432 | } | |
433 | } | |
434 | pub fn init(&mut self, quant: usize, subset: usize) { | |
435 | let mut idx = quant as usize; | |
436 | if (subset == 2) && (idx < 19) { | |
437 | idx += 10; | |
438 | } else if (subset != 0) && (idx < 26) { | |
439 | idx += 5; | |
440 | } | |
441 | if idx > 30 { | |
442 | idx = 30; | |
443 | } | |
444 | self.super_idx = idx; | |
445 | } | |
446 | pub fn set_params(&mut self, mbtype: &MacroblockType) { | |
447 | self.is_p16 = matches!(*mbtype, MacroblockType::InterMix(_)); | |
448 | self.intra = mbtype.is_intra() || self.is_p16; | |
449 | self.is16 = mbtype.is_16(); | |
450 | self.set_idx = if self.intra { | |
451 | RV34_SET_IDX_INTRA[self.super_idx] | |
452 | } else { | |
453 | RV34_SET_IDX_INTER[self.super_idx] | |
454 | }; | |
455 | } | |
456 | fn write_cbp(&self, bw: &mut BitWriter, coded_pat: [bool; 24], cbp_code: &CBPSet) { | |
457 | let mut cbp_pat = 0u16; | |
458 | for i in 16..20 { | |
459 | cbp_pat = cbp_pat * 3 + (coded_pat[i] as u16) + (coded_pat[i + 4] as u16); | |
460 | } | |
461 | let mut nnz = 0usize; | |
462 | for blk4 in coded_pat[..16].chunks(4) { | |
463 | let cur_nz = blk4.contains(&true); | |
464 | if cur_nz { | |
465 | nnz += 1; | |
466 | } | |
467 | cbp_pat = cbp_pat * 2 + (cur_nz as u16); | |
468 | } | |
469 | nnz = nnz.saturating_sub(1); | |
470 | ||
471 | cbp_code.cbp_pattern.write(bw, cbp_pat); | |
472 | for blk4 in coded_pat[..16].chunks(4) { | |
473 | let pat = (blk4[3] as u16) * 32 + (blk4[2] as u16) * 16 + (blk4[1] as u16) * 2 + (blk4[0] as u16); | |
474 | if pat != 0 { | |
475 | cbp_code.cbp[nnz].write(bw, pat); | |
476 | } | |
477 | } | |
478 | for i in 16..20 { | |
479 | if coded_pat[i] ^ coded_pat[i + 4] { | |
480 | if coded_pat[i] { | |
481 | bw.write1(); | |
482 | } else { | |
483 | bw.write0(); | |
484 | } | |
485 | } | |
486 | } | |
487 | } | |
488 | pub fn write_coeffs(&mut self, bw: &mut BitWriter, coeffs: &[Block; 25]) { | |
489 | let mut fset = if self.intra { &self.iset[self.set_idx] } else { &self.pset[self.set_idx] }; | |
490 | ||
491 | const CODED_ORDER: [usize; 24] = [0, 1, 4, 5, 2, 3, 6, 7, 8, 9, 12, 13, 10, 11, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23]; | |
492 | let cbp_code = &fset.cbp[if self.is16 { 1 } else { 0 }]; | |
493 | let mut coded_blk = [false; 24]; | |
494 | let mut coded_pat = [false; 24]; | |
495 | for (i, ((cpat, cblk), &seq)) in coded_pat.iter_mut().zip(coded_blk.iter_mut()) | |
496 | .zip(CODED_ORDER.iter()).enumerate() { | |
497 | *cpat = !coeffs[seq].is_empty(); | |
498 | *cblk = !coeffs[i].is_empty(); | |
499 | } | |
500 | self.write_cbp(bw, coded_pat, cbp_code); | |
501 | ||
502 | if self.is16 { | |
503 | fset.write_block(bw, &coeffs[24], 3, true); | |
504 | } | |
505 | let (luma_set, chroma_set) = if self.intra { | |
506 | (if self.is16 { 2 } else { 1 }, if !self.is_p16 { 0 } else { 1 }) | |
507 | } else { | |
508 | (0, 1) | |
509 | }; | |
510 | let mut citer = coded_blk.iter(); | |
511 | for blk in coeffs[..16].iter() { | |
512 | if let Some(true) = citer.next() { | |
513 | fset.write_block(bw, blk, luma_set, true); | |
514 | } | |
515 | } | |
516 | if self.is_p16 { | |
517 | self.set_idx = RV34_SET_IDX_INTER[self.super_idx]; | |
518 | fset = &self.pset[self.set_idx]; | |
519 | } | |
520 | for blk in coeffs[16..24].iter() { | |
521 | if let Some(true) = citer.next() { | |
522 | fset.write_block(bw, blk, chroma_set, false); | |
523 | } | |
524 | } | |
525 | } | |
526 | } | |
527 | ||
528 | fn get_subblock_index(blk: &[i16; 4]) -> u16 { | |
529 | let mut idx = blk[0].abs().min(3) as u16; | |
530 | idx = idx * 3 + (blk[1].abs().min(2) as u16); | |
531 | idx = idx * 3 + (blk[2].abs().min(2) as u16); | |
532 | idx = idx * 3 + (blk[3].abs().min(2) as u16); | |
533 | idx | |
534 | } |