/rust/registry/src/index.crates.io-6f17d22bba15001f/rav1e-0.7.1/src/header.rs
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright (c) 2018-2022, The rav1e contributors. All rights reserved |
2 | | // |
3 | | // This source code is subject to the terms of the BSD 2 Clause License and |
4 | | // the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License |
5 | | // was not distributed with this source code in the LICENSE file, you can |
6 | | // obtain it at www.aomedia.org/license/software. If the Alliance for Open |
7 | | // Media Patent License 1.0 was not distributed with this source code in the |
8 | | // PATENTS file, you can obtain it at www.aomedia.org/license/patent. |
9 | | |
10 | | use crate::api::*; |
11 | | use crate::context::*; |
12 | | use crate::ec::*; |
13 | | use crate::lrf::*; |
14 | | use crate::partition::*; |
15 | | use crate::tiling::MAX_TILE_WIDTH; |
16 | | use crate::util::Fixed; |
17 | | use crate::util::Pixel; |
18 | | |
19 | | use crate::DeblockState; |
20 | | use crate::FrameInvariants; |
21 | | use crate::FrameState; |
22 | | use crate::SegmentationState; |
23 | | use crate::Sequence; |
24 | | |
25 | | use arrayvec::ArrayVec; |
26 | | use bitstream_io::{BigEndian, BitWrite, BitWriter, LittleEndian}; |
27 | | |
28 | | use std::io; |
29 | | |
30 | | pub const PRIMARY_REF_NONE: u32 = 7; |
31 | | pub const ALL_REF_FRAMES_MASK: u32 = (1 << REF_FRAMES) - 1; |
32 | | |
33 | | const PRIMARY_REF_BITS: u32 = 3; |
34 | | |
35 | | #[allow(unused)] |
36 | | const OP_POINTS_IDC_BITS: usize = 12; |
37 | | #[allow(unused)] |
38 | | const LEVEL_MAJOR_MIN: usize = 2; |
39 | | #[allow(unused)] |
40 | | const LEVEL_MAJOR_BITS: usize = 3; |
41 | | #[allow(unused)] |
42 | | const LEVEL_MINOR_BITS: usize = 2; |
43 | | #[allow(unused)] |
44 | | const LEVEL_BITS: usize = LEVEL_MAJOR_BITS + LEVEL_MINOR_BITS; |
45 | | |
46 | | #[allow(dead_code, non_camel_case_types)] |
47 | | #[derive(Debug, Clone, Copy, PartialEq, Eq)] |
48 | | pub enum ReferenceMode { |
49 | | SINGLE = 0, |
50 | | COMPOUND = 1, |
51 | | SELECT = 2, |
52 | | } |
53 | | |
54 | | #[allow(non_camel_case_types)] |
55 | | #[allow(unused)] |
56 | | pub enum ObuType { |
57 | | OBU_SEQUENCE_HEADER = 1, |
58 | | OBU_TEMPORAL_DELIMITER = 2, |
59 | | OBU_FRAME_HEADER = 3, |
60 | | OBU_TILE_GROUP = 4, |
61 | | OBU_METADATA = 5, |
62 | | OBU_FRAME = 6, |
63 | | OBU_REDUNDANT_FRAME_HEADER = 7, |
64 | | OBU_TILE_LIST = 8, |
65 | | OBU_PADDING = 15, |
66 | | } |
67 | | |
68 | | #[derive(Clone, Copy)] |
69 | | #[allow(non_camel_case_types)] |
70 | | #[allow(unused)] |
71 | | pub enum ObuMetaType { |
72 | | OBU_META_HDR_CLL = 1, |
73 | | OBU_META_HDR_MDCV = 2, |
74 | | OBU_META_SCALABILITY = 3, |
75 | | OBU_META_ITUT_T35 = 4, |
76 | | OBU_META_TIMECODE = 5, |
77 | | } |
78 | | |
79 | | impl ObuMetaType { |
80 | 0 | const fn size(self) -> u64 { |
81 | | use self::ObuMetaType::*; |
82 | 0 | match self { |
83 | 0 | OBU_META_HDR_CLL => 4, |
84 | 0 | OBU_META_HDR_MDCV => 24, |
85 | 0 | _ => 0, |
86 | | } |
87 | 0 | } |
88 | | } |
89 | | |
90 | | pub trait ULEB128Writer { |
91 | | fn write_uleb128(&mut self, payload: u64) -> io::Result<()>; |
92 | | } |
93 | | |
94 | | impl<W: io::Write> ULEB128Writer for BitWriter<W, BigEndian> { |
95 | 0 | fn write_uleb128(&mut self, payload: u64) -> io::Result<()> { |
96 | 0 | // NOTE from libaom: |
97 | 0 | // Disallow values larger than 32-bits to ensure consistent behavior on 32 and |
98 | 0 | // 64 bit targets: value is typically used to determine buffer allocation size |
99 | 0 | // when decoded. |
100 | 0 | let mut coded_value: ArrayVec<u8, 8> = ArrayVec::new(); |
101 | 0 |
|
102 | 0 | let mut value = payload as u32; |
103 | | loop { |
104 | 0 | let mut byte = (value & 0x7f) as u8; |
105 | 0 | value >>= 7u8; |
106 | 0 | if value != 0 { |
107 | 0 | // Signal that more bytes follow. |
108 | 0 | byte |= 0x80; |
109 | 0 | } |
110 | 0 | coded_value.push(byte); |
111 | 0 |
|
112 | 0 | if value == 0 { |
113 | | // We have to break at the end of the loop |
114 | | // because there must be at least one byte written. |
115 | 0 | break; |
116 | 0 | } |
117 | | } |
118 | | |
119 | 0 | for byte in coded_value { |
120 | 0 | self.write(8, byte)?; |
121 | | } |
122 | 0 | Ok(()) |
123 | 0 | } |
124 | | } |
125 | | |
126 | | pub trait LEWriter { |
127 | | fn write_le(&mut self, bytes: u32, payload: u64) -> io::Result<()>; |
128 | | } |
129 | | |
130 | | // to write little endian values in a globally big-endian BitWriter |
131 | | impl<W: io::Write> LEWriter for BitWriter<W, BigEndian> { |
132 | 0 | fn write_le(&mut self, bytes: u32, value: u64) -> io::Result<()> { |
133 | 0 | let mut data = Vec::new(); |
134 | 0 | let mut bwle = BitWriter::endian(&mut data, LittleEndian); |
135 | 0 | bwle.write(bytes * 8, value)?; |
136 | 0 | self.write_bytes(&data) |
137 | 0 | } |
138 | | } |
139 | | |
140 | | pub trait UncompressedHeader { |
141 | | // Start of OBU Headers |
142 | | fn write_obu_header( |
143 | | &mut self, obu_type: ObuType, obu_extension: u32, |
144 | | ) -> io::Result<()>; |
145 | | fn write_sequence_metadata_obu( |
146 | | &mut self, obu_meta_type: ObuMetaType, seq: &Sequence, |
147 | | ) -> io::Result<()>; |
148 | | fn write_sequence_header_obu<T: Pixel>( |
149 | | &mut self, fi: &FrameInvariants<T>, |
150 | | ) -> io::Result<()>; |
151 | | fn write_frame_header_obu<T: Pixel>( |
152 | | &mut self, fi: &FrameInvariants<T>, fs: &FrameState<T>, |
153 | | inter_cfg: &InterConfig, |
154 | | ) -> io::Result<()>; |
155 | | fn write_sequence_header<T: Pixel>( |
156 | | &mut self, fi: &FrameInvariants<T>, |
157 | | ) -> io::Result<()>; |
158 | | fn write_color_config(&mut self, seq: &Sequence) -> io::Result<()>; |
159 | | fn write_t35_metadata_obu(&mut self, t35: &T35) -> io::Result<()>; |
160 | | // End of OBU Headers |
161 | | |
162 | | fn write_max_frame_size<T: Pixel>( |
163 | | &mut self, fi: &FrameInvariants<T>, |
164 | | ) -> io::Result<()>; |
165 | | fn write_frame_size<T: Pixel>( |
166 | | &mut self, fi: &FrameInvariants<T>, |
167 | | ) -> io::Result<()>; |
168 | | fn write_render_size<T: Pixel>( |
169 | | &mut self, fi: &FrameInvariants<T>, |
170 | | ) -> io::Result<()>; |
171 | | fn write_frame_size_with_refs<T: Pixel>( |
172 | | &mut self, fi: &FrameInvariants<T>, |
173 | | ) -> io::Result<()>; |
174 | | fn write_deblock_filter_a<T: Pixel>( |
175 | | &mut self, fi: &FrameInvariants<T>, deblock: &DeblockState, |
176 | | ) -> io::Result<()>; |
177 | | fn write_deblock_filter_b<T: Pixel>( |
178 | | &mut self, fi: &FrameInvariants<T>, deblock: &DeblockState, |
179 | | ) -> io::Result<()>; |
180 | | fn write_frame_cdef<T: Pixel>( |
181 | | &mut self, fi: &FrameInvariants<T>, |
182 | | ) -> io::Result<()>; |
183 | | fn write_frame_lrf<T: Pixel>( |
184 | | &mut self, fi: &FrameInvariants<T>, rs: &RestorationState, |
185 | | ) -> io::Result<()>; |
186 | | fn write_segment_data<T: Pixel>( |
187 | | &mut self, fi: &FrameInvariants<T>, segmentation: &SegmentationState, |
188 | | ) -> io::Result<()>; |
189 | | fn write_delta_q(&mut self, delta_q: i8) -> io::Result<()>; |
190 | | } |
191 | | |
192 | | impl<W: io::Write> UncompressedHeader for BitWriter<W, BigEndian> { |
193 | | // Start of OBU Headers |
194 | | // Write OBU Header syntax |
195 | 0 | fn write_obu_header( |
196 | 0 | &mut self, obu_type: ObuType, obu_extension: u32, |
197 | 0 | ) -> io::Result<()> { |
198 | 0 | self.write_bit(false)?; // forbidden bit. |
199 | 0 | self.write(4, obu_type as u32)?; |
200 | 0 | self.write_bit(obu_extension != 0)?; |
201 | 0 | self.write_bit(true)?; // obu_has_payload_length_field |
202 | 0 | self.write_bit(false)?; // reserved |
203 | | |
204 | 0 | if obu_extension != 0 { |
205 | 0 | unimplemented!(); |
206 | | //self.write(8, obu_extension & 0xFF)?; size += 8; |
207 | 0 | } |
208 | 0 |
|
209 | 0 | Ok(()) |
210 | 0 | } |
211 | | |
212 | 0 | fn write_sequence_metadata_obu( |
213 | 0 | &mut self, obu_meta_type: ObuMetaType, seq: &Sequence, |
214 | 0 | ) -> io::Result<()> { |
215 | 0 | // header |
216 | 0 | self.write_obu_header(ObuType::OBU_METADATA, 0)?; |
217 | | |
218 | | // uleb128() - length |
219 | | // we use a constant value to avoid computing the OBU size every time |
220 | | // since it is fixed (depending on the metadata) |
221 | | // +2 is for the metadata_type field and the trailing bits byte |
222 | 0 | self.write_uleb128(obu_meta_type.size() + 2)?; |
223 | | |
224 | | // uleb128() - metadata_type (1 byte) |
225 | 0 | self.write_uleb128(obu_meta_type as u64)?; |
226 | | |
227 | 0 | match obu_meta_type { |
228 | | ObuMetaType::OBU_META_HDR_CLL => { |
229 | 0 | let cll = seq.content_light.unwrap(); |
230 | 0 | self.write(16, cll.max_content_light_level)?; |
231 | 0 | self.write(16, cll.max_frame_average_light_level)?; |
232 | | } |
233 | | ObuMetaType::OBU_META_HDR_MDCV => { |
234 | 0 | let mdcv = seq.mastering_display.unwrap(); |
235 | 0 | for i in 0..3 { |
236 | 0 | self.write(16, mdcv.primaries[i].x)?; |
237 | 0 | self.write(16, mdcv.primaries[i].y)?; |
238 | | } |
239 | | |
240 | 0 | self.write(16, mdcv.white_point.x)?; |
241 | 0 | self.write(16, mdcv.white_point.y)?; |
242 | | |
243 | 0 | self.write(32, mdcv.max_luminance)?; |
244 | 0 | self.write(32, mdcv.min_luminance)?; |
245 | | } |
246 | 0 | _ => {} |
247 | | } |
248 | | |
249 | | // trailing bits (1 byte) |
250 | 0 | self.write_bit(true)?; |
251 | 0 | self.byte_align()?; |
252 | | |
253 | 0 | Ok(()) |
254 | 0 | } |
255 | | |
256 | 0 | fn write_t35_metadata_obu(&mut self, t35: &T35) -> io::Result<()> { |
257 | 0 | self.write_obu_header(ObuType::OBU_METADATA, 0)?; |
258 | | |
259 | | // metadata type + country code + optional extension + trailing bits |
260 | 0 | self.write_uleb128( |
261 | 0 | t35.data.len() as u64 + if t35.country_code == 0xFF { 4 } else { 3 }, |
262 | 0 | )?; |
263 | | |
264 | 0 | self.write_uleb128(ObuMetaType::OBU_META_ITUT_T35 as u64)?; |
265 | | |
266 | 0 | self.write(8, t35.country_code)?; |
267 | 0 | if t35.country_code == 0xFF { |
268 | 0 | self.write(8, t35.country_code_extension_byte)?; |
269 | 0 | } |
270 | 0 | self.write_bytes(&t35.data)?; |
271 | | |
272 | | // trailing bits (1 byte) |
273 | 0 | self.write_bit(true)?; |
274 | 0 | self.byte_align()?; |
275 | | |
276 | 0 | Ok(()) |
277 | 0 | } |
278 | | |
279 | 0 | fn write_sequence_header_obu<T: Pixel>( |
280 | 0 | &mut self, fi: &FrameInvariants<T>, |
281 | 0 | ) -> io::Result<()> { |
282 | 0 | assert!( |
283 | 0 | !fi.sequence.reduced_still_picture_hdr || fi.sequence.still_picture |
284 | | ); |
285 | | |
286 | 0 | self.write(3, fi.sequence.profile)?; // profile |
287 | 0 | self.write_bit(fi.sequence.still_picture)?; // still_picture |
288 | 0 | self.write_bit(fi.sequence.reduced_still_picture_hdr)?; // reduced_still_picture_header |
289 | | |
290 | 0 | assert!(fi.sequence.level_idx[0] <= 31); |
291 | 0 | if fi.sequence.reduced_still_picture_hdr { |
292 | 0 | assert!(!fi.sequence.timing_info_present); |
293 | 0 | assert!(!fi.sequence.decoder_model_info_present_flag); |
294 | 0 | assert_eq!(fi.sequence.operating_points_cnt_minus_1, 0); |
295 | 0 | assert_eq!(fi.sequence.operating_point_idc[0], 0); |
296 | 0 | self.write(5, fi.sequence.level_idx[0])?; // level |
297 | 0 | assert_eq!(fi.sequence.tier[0], 0); |
298 | | } else { |
299 | 0 | self.write_bit(fi.sequence.timing_info_present)?; // timing info present |
300 | | |
301 | 0 | if fi.sequence.timing_info_present { |
302 | 0 | self.write(32, fi.sequence.time_base.num)?; |
303 | 0 | self.write(32, fi.sequence.time_base.den)?; |
304 | | |
305 | 0 | self.write_bit(true)?; // equal picture interval |
306 | 0 | self.write_bit(true)?; // zero interval |
307 | 0 | self.write_bit(false)?; // decoder model info present flag |
308 | 0 | } |
309 | | |
310 | 0 | self.write_bit(false)?; // initial display delay present flag |
311 | 0 | self.write(5, 0)?; // one operating point |
312 | 0 | self.write(12, 0)?; // idc |
313 | 0 | self.write(5, fi.sequence.level_idx[0])?; // level |
314 | 0 | if fi.sequence.level_idx[0] > 7 { |
315 | 0 | self.write(1, 0)?; // tier |
316 | 0 | } |
317 | | } |
318 | | |
319 | 0 | self.write_sequence_header(fi)?; |
320 | | |
321 | 0 | self.write_color_config(&fi.sequence)?; |
322 | | |
323 | 0 | self.write_bit(fi.sequence.film_grain_params_present)?; |
324 | | |
325 | 0 | Ok(()) |
326 | 0 | } Unexecuted instantiation: <bitstream_io::write::BitWriter<&mut alloc::vec::Vec<u8>, bitstream_io::BigEndian> as rav1e::header::UncompressedHeader>::write_sequence_header_obu::<u16> Unexecuted instantiation: <bitstream_io::write::BitWriter<&mut alloc::vec::Vec<u8>, bitstream_io::BigEndian> as rav1e::header::UncompressedHeader>::write_sequence_header_obu::<u8> |
327 | | |
328 | 0 | fn write_sequence_header<T: Pixel>( |
329 | 0 | &mut self, fi: &FrameInvariants<T>, |
330 | 0 | ) -> io::Result<()> { |
331 | 0 | self.write_max_frame_size(fi)?; |
332 | | |
333 | 0 | let seq = &fi.sequence; |
334 | 0 |
|
335 | 0 | if seq.reduced_still_picture_hdr { |
336 | 0 | assert!(!seq.frame_id_numbers_present_flag); |
337 | | } else { |
338 | 0 | self.write_bit(seq.frame_id_numbers_present_flag)?; |
339 | | } |
340 | | |
341 | 0 | if seq.frame_id_numbers_present_flag { |
342 | | // We must always have delta_frame_id_length < frame_id_length, |
343 | | // in order for a frame to be referenced with a unique delta. |
344 | | // Avoid wasting bits by using a coding that enforces this restriction. |
345 | 0 | self.write(4, seq.delta_frame_id_length - 2)?; |
346 | 0 | self.write(3, seq.frame_id_length - seq.delta_frame_id_length - 1)?; |
347 | 0 | } |
348 | | |
349 | 0 | self.write_bit(seq.use_128x128_superblock)?; |
350 | 0 | self.write_bit(seq.enable_filter_intra)?; |
351 | 0 | self.write_bit(seq.enable_intra_edge_filter)?; |
352 | | |
353 | 0 | if seq.reduced_still_picture_hdr { |
354 | 0 | assert!(!seq.enable_interintra_compound); |
355 | 0 | assert!(!seq.enable_masked_compound); |
356 | 0 | assert!(!seq.enable_warped_motion); |
357 | 0 | assert!(!seq.enable_dual_filter); |
358 | 0 | assert!(!seq.enable_order_hint); |
359 | 0 | assert!(!seq.enable_jnt_comp); |
360 | 0 | assert!(!seq.enable_ref_frame_mvs); |
361 | 0 | assert!(seq.force_screen_content_tools == 2); |
362 | 0 | assert!(seq.force_integer_mv == 2); |
363 | | } else { |
364 | 0 | self.write_bit(seq.enable_interintra_compound)?; |
365 | 0 | self.write_bit(seq.enable_masked_compound)?; |
366 | 0 | self.write_bit(seq.enable_warped_motion)?; |
367 | 0 | self.write_bit(seq.enable_dual_filter)?; |
368 | 0 | self.write_bit(seq.enable_order_hint)?; |
369 | | |
370 | 0 | if seq.enable_order_hint { |
371 | 0 | self.write_bit(seq.enable_jnt_comp)?; |
372 | 0 | self.write_bit(seq.enable_ref_frame_mvs)?; |
373 | 0 | } |
374 | | |
375 | 0 | if seq.force_screen_content_tools == 2 { |
376 | 0 | self.write_bit(true)?; |
377 | | } else { |
378 | 0 | self.write_bit(false)?; |
379 | 0 | self.write_bit(seq.force_screen_content_tools != 0)?; |
380 | | } |
381 | 0 | if seq.force_screen_content_tools > 0 { |
382 | 0 | if seq.force_integer_mv == 2 { |
383 | 0 | self.write_bit(true)?; |
384 | | } else { |
385 | 0 | self.write_bit(false)?; |
386 | 0 | self.write_bit(seq.force_integer_mv != 0)?; |
387 | | } |
388 | | } else { |
389 | 0 | assert!(seq.force_integer_mv == 2); |
390 | | } |
391 | 0 | if seq.enable_order_hint { |
392 | 0 | self.write(3, seq.order_hint_bits_minus_1)?; |
393 | 0 | } |
394 | | } |
395 | | |
396 | 0 | self.write_bit(seq.enable_superres)?; |
397 | 0 | self.write_bit(seq.enable_cdef)?; |
398 | 0 | self.write_bit(seq.enable_restoration)?; |
399 | | |
400 | 0 | Ok(()) |
401 | 0 | } Unexecuted instantiation: <bitstream_io::write::BitWriter<&mut alloc::vec::Vec<u8>, bitstream_io::BigEndian> as rav1e::header::UncompressedHeader>::write_sequence_header::<u16> Unexecuted instantiation: <bitstream_io::write::BitWriter<&mut alloc::vec::Vec<u8>, bitstream_io::BigEndian> as rav1e::header::UncompressedHeader>::write_sequence_header::<u8> |
402 | | |
403 | | // <https://aomediacodec.github.io/av1-spec/#color-config-syntax> |
404 | 0 | fn write_color_config(&mut self, seq: &Sequence) -> io::Result<()> { |
405 | 0 | let high_bitdepth = seq.bit_depth > 8; |
406 | 0 | self.write_bit(high_bitdepth)?; |
407 | 0 | if seq.profile == 2 && high_bitdepth { |
408 | 0 | self.write_bit(seq.bit_depth == 12)?; // twelve_bit |
409 | 0 | } |
410 | | |
411 | 0 | let monochrome = seq.chroma_sampling == ChromaSampling::Cs400; |
412 | 0 | if seq.profile == 1 { |
413 | 0 | assert!(!monochrome); |
414 | | } else { |
415 | 0 | self.write_bit(monochrome)?; // mono_chrome |
416 | | } |
417 | | |
418 | | // color_description_present_flag |
419 | 0 | self.write_bit(seq.color_description.is_some())?; |
420 | 0 | let mut srgb_triple = false; |
421 | 0 | if let Some(color_description) = seq.color_description { |
422 | 0 | self.write(8, color_description.color_primaries as u8)?; |
423 | 0 | self.write(8, color_description.transfer_characteristics as u8)?; |
424 | 0 | self.write(8, color_description.matrix_coefficients as u8)?; |
425 | 0 | srgb_triple = color_description.is_srgb_triple(); |
426 | 0 | } |
427 | | |
428 | 0 | if monochrome || !srgb_triple { |
429 | 0 | self.write_bit(seq.pixel_range == PixelRange::Full)?; // color_range |
430 | 0 | } |
431 | 0 | if monochrome { |
432 | 0 | return Ok(()); |
433 | 0 | } else if srgb_triple { |
434 | 0 | assert!(seq.pixel_range == PixelRange::Full); |
435 | 0 | assert!(seq.chroma_sampling == ChromaSampling::Cs444); |
436 | | } else { |
437 | 0 | if seq.profile == 0 { |
438 | 0 | assert!(seq.chroma_sampling == ChromaSampling::Cs420); |
439 | 0 | } else if seq.profile == 1 { |
440 | 0 | assert!(seq.chroma_sampling == ChromaSampling::Cs444); |
441 | 0 | } else if seq.bit_depth == 12 { |
442 | 0 | let subsampling_x = seq.chroma_sampling != ChromaSampling::Cs444; |
443 | 0 | let subsampling_y = seq.chroma_sampling == ChromaSampling::Cs420; |
444 | 0 | self.write_bit(subsampling_x)?; |
445 | 0 | if subsampling_x { |
446 | 0 | self.write_bit(subsampling_y)?; |
447 | 0 | } |
448 | | } else { |
449 | 0 | assert!(seq.chroma_sampling == ChromaSampling::Cs422); |
450 | | } |
451 | 0 | if seq.chroma_sampling == ChromaSampling::Cs420 { |
452 | 0 | self.write(2, seq.chroma_sample_position as u32)?; |
453 | 0 | } |
454 | | } |
455 | 0 | self.write_bit(true)?; // separate_uv_delta_q |
456 | | |
457 | 0 | Ok(()) |
458 | 0 | } |
459 | | |
460 | | #[allow(unused)] |
461 | 0 | fn write_frame_header_obu<T: Pixel>( |
462 | 0 | &mut self, fi: &FrameInvariants<T>, fs: &FrameState<T>, |
463 | 0 | inter_cfg: &InterConfig, |
464 | 0 | ) -> io::Result<()> { |
465 | 0 | if fi.sequence.reduced_still_picture_hdr { |
466 | 0 | assert!(!fi.is_show_existing_frame()); |
467 | 0 | assert!(fi.frame_type == FrameType::KEY); |
468 | 0 | assert!(fi.show_frame); |
469 | 0 | assert!(!fi.showable_frame); |
470 | | } else { |
471 | 0 | self.write_bit(fi.is_show_existing_frame())?; |
472 | | |
473 | 0 | if fi.is_show_existing_frame() { |
474 | 0 | self.write(3, fi.frame_to_show_map_idx)?; |
475 | | |
476 | | //TODO: |
477 | | /* temporal_point_info(); |
478 | | if fi.sequence.decoder_model_info_present_flag && |
479 | | timing_info.equal_picture_interval == 0 { |
480 | | // write frame_presentation_delay; |
481 | | } |
482 | | if fi.sequence.frame_id_numbers_present_flag { |
483 | | // write display_frame_id; |
484 | | }*/ |
485 | | |
486 | 0 | self.write_bit(true)?; // trailing bit |
487 | 0 | self.byte_align()?; |
488 | 0 | return Ok(()); |
489 | 0 | } |
490 | 0 |
|
491 | 0 | self.write(2, fi.frame_type as u32)?; |
492 | 0 | self.write_bit(fi.show_frame)?; // show frame |
493 | | |
494 | 0 | if fi.show_frame { |
495 | 0 | //TODO: |
496 | 0 | /* temporal_point_info(); |
497 | 0 | if fi.sequence.decoder_model_info_present_flag && |
498 | 0 | timing_info.equal_picture_interval == 0 { |
499 | 0 | // write frame_presentation_delay; |
500 | 0 | }*/ |
501 | 0 | } else { |
502 | 0 | self.write_bit(fi.showable_frame)?; |
503 | | } |
504 | | |
505 | 0 | if fi.error_resilient { |
506 | 0 | assert!(fi.primary_ref_frame == PRIMARY_REF_NONE); |
507 | 0 | } |
508 | 0 | if fi.frame_type == FrameType::SWITCH { |
509 | 0 | assert!(fi.error_resilient); |
510 | 0 | } else if !(fi.frame_type == FrameType::KEY && fi.show_frame) { |
511 | 0 | self.write_bit(fi.error_resilient)?; // error resilient |
512 | 0 | } |
513 | | } |
514 | | |
515 | 0 | self.write_bit(fi.disable_cdf_update)?; |
516 | | |
517 | 0 | if fi.sequence.force_screen_content_tools == 2 { |
518 | 0 | self.write_bit(fi.allow_screen_content_tools != 0)?; |
519 | | } else { |
520 | 0 | assert!( |
521 | 0 | fi.allow_screen_content_tools |
522 | 0 | == fi.sequence.force_screen_content_tools |
523 | 0 | ); |
524 | | } |
525 | | |
526 | 0 | if fi.allow_screen_content_tools > 0 { |
527 | 0 | if fi.sequence.force_integer_mv == 2 { |
528 | 0 | self.write_bit(fi.force_integer_mv != 0)?; |
529 | | } else { |
530 | 0 | assert!(fi.force_integer_mv == fi.sequence.force_integer_mv); |
531 | | } |
532 | 0 | } |
533 | | |
534 | 0 | assert!( |
535 | 0 | fi.force_integer_mv |
536 | 0 | == u32::from(fi.frame_type == FrameType::KEY || fi.intra_only) |
537 | | ); |
538 | | |
539 | 0 | if fi.sequence.frame_id_numbers_present_flag { |
540 | 0 | unimplemented!(); |
541 | | |
542 | | //TODO: |
543 | | //let frame_id_len = fi.sequence.frame_id_length; |
544 | | //self.write(frame_id_len, fi.current_frame_id); |
545 | 0 | } |
546 | 0 |
|
547 | 0 | if fi.frame_type != FrameType::SWITCH |
548 | 0 | && !fi.sequence.reduced_still_picture_hdr |
549 | | { |
550 | 0 | self.write_bit(fi.frame_size_override_flag)?; // frame size overhead flag |
551 | 0 | } |
552 | | |
553 | 0 | if fi.sequence.enable_order_hint { |
554 | 0 | let n = fi.sequence.order_hint_bits_minus_1 + 1; |
555 | 0 | let mask = (1 << n) - 1; |
556 | 0 | self.write(n, fi.order_hint & mask)?; |
557 | 0 | } |
558 | | |
559 | 0 | if !fi.error_resilient && !fi.intra_only { |
560 | 0 | self.write(PRIMARY_REF_BITS, fi.primary_ref_frame)?; |
561 | 0 | } |
562 | | |
563 | 0 | if fi.sequence.decoder_model_info_present_flag { |
564 | 0 | unimplemented!(); |
565 | 0 | } |
566 | 0 |
|
567 | 0 | if fi.frame_type == FrameType::KEY { |
568 | 0 | if !fi.show_frame { |
569 | | // unshown keyframe (forward keyframe) |
570 | 0 | unimplemented!(); |
571 | | self.write(REF_FRAMES as u32, fi.refresh_frame_flags)?; |
572 | | } else { |
573 | 0 | assert!(fi.refresh_frame_flags == ALL_REF_FRAMES_MASK); |
574 | | } |
575 | 0 | } else if fi.frame_type == FrameType::SWITCH { |
576 | 0 | assert!(fi.refresh_frame_flags == ALL_REF_FRAMES_MASK); |
577 | | } else { |
578 | | // Inter frame info goes here |
579 | 0 | if fi.intra_only { |
580 | 0 | assert!(fi.refresh_frame_flags != ALL_REF_FRAMES_MASK); |
581 | 0 | } else { |
582 | 0 | // TODO: This should be set once inter mode is used |
583 | 0 | } |
584 | 0 | self.write(REF_FRAMES as u32, fi.refresh_frame_flags)?; |
585 | | }; |
586 | | |
587 | 0 | if (!fi.intra_only || fi.refresh_frame_flags != ALL_REF_FRAMES_MASK) { |
588 | | // Write all ref frame order hints if error_resilient_mode == 1 |
589 | 0 | if (fi.error_resilient && fi.sequence.enable_order_hint) { |
590 | 0 | for i in 0..REF_FRAMES { |
591 | 0 | let n = fi.sequence.order_hint_bits_minus_1 + 1; |
592 | 0 | let mask = (1 << n) - 1; |
593 | 0 | if let Some(ref rec) = fi.rec_buffer.frames[i] { |
594 | 0 | let ref_hint = rec.order_hint; |
595 | 0 | self.write(n, ref_hint & mask)?; |
596 | | } else { |
597 | 0 | self.write(n, 0)?; |
598 | | } |
599 | | } |
600 | 0 | } |
601 | 0 | } |
602 | | |
603 | | // if KEY or INTRA_ONLY frame |
604 | 0 | if fi.intra_only { |
605 | 0 | self.write_frame_size(fi)?; |
606 | 0 | self.write_render_size(fi)?; |
607 | 0 | if fi.allow_screen_content_tools != 0 { |
608 | | // TODO: && UpscaledWidth == FrameWidth. |
609 | 0 | self.write_bit(fi.allow_intrabc)?; |
610 | 0 | } |
611 | 0 | } |
612 | | |
613 | 0 | let frame_refs_short_signaling = false; |
614 | 0 | if fi.frame_type == FrameType::KEY || fi.intra_only { |
615 | 0 | // Done by above |
616 | 0 | } else { |
617 | 0 | if fi.sequence.enable_order_hint { |
618 | 0 | self.write_bit(frame_refs_short_signaling)?; |
619 | 0 | if frame_refs_short_signaling { |
620 | 0 | unimplemented!(); |
621 | 0 | } |
622 | 0 | } |
623 | | |
624 | 0 | for i in 0..INTER_REFS_PER_FRAME { |
625 | 0 | if !frame_refs_short_signaling { |
626 | 0 | self.write(REF_FRAMES_LOG2 as u32, fi.ref_frames[i])?; |
627 | 0 | } |
628 | 0 | if fi.sequence.frame_id_numbers_present_flag { |
629 | 0 | unimplemented!(); |
630 | 0 | } |
631 | | } |
632 | | |
633 | 0 | if !fi.error_resilient && fi.frame_size_override_flag { |
634 | 0 | self.write_frame_size_with_refs(fi)?; |
635 | | } else { |
636 | 0 | self.write_frame_size(fi)?; |
637 | 0 | self.write_render_size(fi)?; |
638 | | } |
639 | | |
640 | 0 | if fi.force_integer_mv == 0 { |
641 | 0 | self.write_bit(fi.allow_high_precision_mv); |
642 | 0 | } |
643 | | |
644 | 0 | self.write_bit(fi.is_filter_switchable)?; |
645 | 0 | if !fi.is_filter_switchable { |
646 | 0 | self.write(2, fi.default_filter as u8)?; |
647 | 0 | } |
648 | 0 | self.write_bit(fi.is_motion_mode_switchable)?; |
649 | | |
650 | 0 | if (!fi.error_resilient && fi.sequence.enable_ref_frame_mvs) { |
651 | 0 | self.write_bit(fi.use_ref_frame_mvs)?; |
652 | 0 | } |
653 | | } |
654 | | |
655 | 0 | if fi.sequence.reduced_still_picture_hdr || fi.disable_cdf_update { |
656 | 0 | assert!(fi.disable_frame_end_update_cdf); |
657 | | } else { |
658 | 0 | self.write_bit(fi.disable_frame_end_update_cdf)?; |
659 | | } |
660 | | |
661 | | // tile |
662 | | // <https://aomediacodec.github.io/av1-spec/#tile-info-syntax> |
663 | | |
664 | | // Can we use the uniform spacing tile syntax? 'Uniform spacing' |
665 | | // is a slight misnomer; it's more constrained than just a uniform |
666 | | // spacing. |
667 | 0 | let ti = &fi.sequence.tiling; |
668 | 0 |
|
669 | 0 | if fi.sb_width.align_power_of_two_and_shift(ti.tile_cols_log2) |
670 | 0 | == ti.tile_width_sb |
671 | 0 | && fi.sb_height.align_power_of_two_and_shift(ti.tile_rows_log2) |
672 | 0 | == ti.tile_height_sb |
673 | | { |
674 | | // yes; our actual tile width/height setting (which is always |
675 | | // currently uniform) also matches the constrained width/height |
676 | | // calculation implicit in the uniform spacing flag. |
677 | | |
678 | 0 | self.write_bit(true)?; // uniform_tile_spacing_flag |
679 | | |
680 | 0 | let cols_ones = ti.tile_cols_log2 - ti.min_tile_cols_log2; |
681 | 0 | for _ in 0..cols_ones { |
682 | 0 | self.write_bit(true); |
683 | 0 | } |
684 | 0 | if ti.tile_cols_log2 < ti.max_tile_cols_log2 { |
685 | 0 | self.write_bit(false); |
686 | 0 | } |
687 | | |
688 | 0 | let rows_ones = ti.tile_rows_log2 - ti.min_tile_rows_log2; |
689 | 0 | for _ in 0..rows_ones { |
690 | 0 | self.write_bit(true); |
691 | 0 | } |
692 | 0 | if ti.tile_rows_log2 < ti.max_tile_rows_log2 { |
693 | 0 | self.write_bit(false); |
694 | 0 | } |
695 | | } else { |
696 | 0 | self.write_bit(false)?; // uniform_tile_spacing_flag |
697 | 0 | let mut sofar = 0; |
698 | 0 | let mut widest_tile_sb = 0; |
699 | 0 | for _ in 0..ti.cols { |
700 | 0 | let max = (MAX_TILE_WIDTH |
701 | 0 | >> if fi.sequence.use_128x128_superblock { 7 } else { 6 }) |
702 | 0 | .min(fi.sb_width - sofar) as u16; |
703 | 0 | let this_sb_width = ti.tile_width_sb.min(fi.sb_width - sofar); |
704 | 0 | self.write_quniform(max, (this_sb_width - 1) as u16); |
705 | 0 | sofar += this_sb_width; |
706 | 0 | widest_tile_sb = widest_tile_sb.max(this_sb_width); |
707 | | } |
708 | | |
709 | 0 | let max_tile_area_sb = if ti.min_tiles_log2 > 0 { |
710 | 0 | (fi.sb_height * fi.sb_width) >> (ti.min_tiles_log2 + 1) |
711 | | } else { |
712 | 0 | fi.sb_height * fi.sb_width |
713 | | }; |
714 | | |
715 | 0 | let max_tile_height_sb = (max_tile_area_sb / widest_tile_sb).max(1); |
716 | 0 |
|
717 | 0 | sofar = 0; |
718 | 0 | for i in 0..ti.rows { |
719 | 0 | let max = max_tile_height_sb.min(fi.sb_height - sofar) as u16; |
720 | 0 | let this_sb_height = ti.tile_height_sb.min(fi.sb_height - sofar); |
721 | 0 |
|
722 | 0 | self.write_quniform(max, (this_sb_height - 1) as u16); |
723 | 0 | sofar += this_sb_height; |
724 | 0 | } |
725 | | } |
726 | | |
727 | 0 | let tiles_log2 = ti.tile_cols_log2 + ti.tile_rows_log2; |
728 | 0 | if tiles_log2 > 0 { |
729 | | // context_update_tile_id |
730 | | // for now, always use the first tile CDF |
731 | 0 | self.write(tiles_log2 as u32, fs.context_update_tile_id as u32)?; |
732 | | |
733 | | // tile_size_bytes_minus_1 |
734 | 0 | self.write(2, fs.max_tile_size_bytes - 1); |
735 | 0 | } |
736 | | |
737 | | // quantization |
738 | 0 | assert!(fi.base_q_idx > 0); |
739 | 0 | self.write(8, fi.base_q_idx)?; // base_q_idx |
740 | 0 | self.write_delta_q(fi.dc_delta_q[0])?; |
741 | 0 | if fi.sequence.chroma_sampling != ChromaSampling::Cs400 { |
742 | 0 | assert!(fi.ac_delta_q[0] == 0); |
743 | 0 | let diff_uv_delta = fi.dc_delta_q[1] != fi.dc_delta_q[2] |
744 | 0 | || fi.ac_delta_q[1] != fi.ac_delta_q[2]; |
745 | 0 | self.write_bit(diff_uv_delta)?; |
746 | 0 | self.write_delta_q(fi.dc_delta_q[1])?; |
747 | 0 | self.write_delta_q(fi.ac_delta_q[1])?; |
748 | 0 | if diff_uv_delta { |
749 | 0 | self.write_delta_q(fi.dc_delta_q[2])?; |
750 | 0 | self.write_delta_q(fi.ac_delta_q[2])?; |
751 | 0 | } |
752 | 0 | } |
753 | 0 | self.write_bit(false)?; // no qm |
754 | | |
755 | | // segmentation |
756 | 0 | self.write_segment_data(fi, &fs.segmentation)?; |
757 | | |
758 | | // delta_q |
759 | 0 | self.write_bit(false)?; // delta_q_present_flag: no delta q |
760 | | |
761 | | // delta_lf_params in the spec |
762 | 0 | self.write_deblock_filter_a(fi, &fs.deblock)?; |
763 | | |
764 | | // code for features not yet implemented.... |
765 | | |
766 | | // loop_filter_params in the spec |
767 | 0 | self.write_deblock_filter_b(fi, &fs.deblock)?; |
768 | | |
769 | | // cdef |
770 | 0 | self.write_frame_cdef(fi)?; |
771 | | |
772 | | // loop restoration |
773 | 0 | self.write_frame_lrf(fi, &fs.restoration)?; |
774 | | |
775 | 0 | self.write_bit(fi.tx_mode_select)?; // tx mode |
776 | | |
777 | 0 | let mut reference_select = false; |
778 | 0 | if !fi.intra_only { |
779 | 0 | reference_select = fi.reference_mode != ReferenceMode::SINGLE; |
780 | 0 | self.write_bit(reference_select)?; |
781 | 0 | } |
782 | | |
783 | 0 | let skip_mode_allowed = |
784 | 0 | fi.sequence.get_skip_mode_allowed(fi, inter_cfg, reference_select); |
785 | 0 | if skip_mode_allowed { |
786 | 0 | self.write_bit(false)?; // skip_mode_present |
787 | 0 | } |
788 | | |
789 | 0 | if fi.intra_only || fi.error_resilient || !fi.sequence.enable_warped_motion |
790 | 0 | { |
791 | 0 | } else { |
792 | 0 | self.write_bit(fi.allow_warped_motion)?; // allow_warped_motion |
793 | | } |
794 | | |
795 | 0 | self.write_bit(fi.use_reduced_tx_set)?; // reduced tx |
796 | | |
797 | | // global motion |
798 | 0 | if !fi.intra_only { |
799 | 0 | for i in 0..7 { |
800 | 0 | let mode = fi.globalmv_transformation_type[i]; |
801 | 0 | self.write_bit(mode != GlobalMVMode::IDENTITY)?; |
802 | 0 | if mode != GlobalMVMode::IDENTITY { |
803 | 0 | self.write_bit(mode == GlobalMVMode::ROTZOOM)?; |
804 | 0 | if mode != GlobalMVMode::ROTZOOM { |
805 | 0 | self.write_bit(mode == GlobalMVMode::TRANSLATION)?; |
806 | 0 | } |
807 | 0 | } |
808 | 0 | match mode { |
809 | 0 | GlobalMVMode::IDENTITY => { /* Nothing to do */ } |
810 | | GlobalMVMode::TRANSLATION => { |
811 | 0 | let mv_x = 0; |
812 | 0 | let mv_x_ref = 0; |
813 | 0 | let mv_y = 0; |
814 | 0 | let mv_y_ref = 0; |
815 | 0 | let bits = 12 - 6 + 3 - !fi.allow_high_precision_mv as u8; |
816 | 0 | let bits_diff = 12 - 3 + fi.allow_high_precision_mv as u8; |
817 | 0 | BCodeWriter::write_s_refsubexpfin( |
818 | 0 | self, |
819 | 0 | (1 << bits) + 1, |
820 | 0 | 3, |
821 | 0 | mv_x_ref >> bits_diff, |
822 | 0 | mv_x >> bits_diff, |
823 | 0 | )?; |
824 | 0 | BCodeWriter::write_s_refsubexpfin( |
825 | 0 | self, |
826 | 0 | (1 << bits) + 1, |
827 | 0 | 3, |
828 | 0 | mv_y_ref >> bits_diff, |
829 | 0 | mv_y >> bits_diff, |
830 | 0 | )?; |
831 | | } |
832 | 0 | GlobalMVMode::ROTZOOM => unimplemented!(), |
833 | 0 | GlobalMVMode::AFFINE => unimplemented!(), |
834 | | }; |
835 | | } |
836 | 0 | } |
837 | | |
838 | 0 | if fi.sequence.film_grain_params_present { |
839 | 0 | if let Some(grain_params) = fi.film_grain_params() { |
840 | | // Apply grain |
841 | 0 | self.write_bit(true)?; |
842 | 0 | self.write(16, grain_params.random_seed)?; |
843 | 0 | if fi.frame_type == FrameType::INTER { |
844 | | // For the purposes of photon noise, |
845 | | // it's simpler to always update the params, |
846 | | // and the output will be the same. |
847 | 0 | self.write_bit(true)?; |
848 | 0 | } |
849 | | |
850 | 0 | self.write(4, grain_params.scaling_points_y.len() as u8)?; |
851 | 0 | for point in &grain_params.scaling_points_y { |
852 | 0 | self.write(8, point[0])?; |
853 | 0 | self.write(8, point[1])?; |
854 | | } |
855 | | |
856 | 0 | let chroma_scaling_from_luma = |
857 | 0 | if fi.sequence.chroma_sampling != ChromaSampling::Cs400 { |
858 | 0 | self.write_bit(grain_params.chroma_scaling_from_luma)?; |
859 | 0 | grain_params.chroma_scaling_from_luma |
860 | | } else { |
861 | 0 | false |
862 | | }; |
863 | 0 | if !(fi.sequence.chroma_sampling == ChromaSampling::Cs400 |
864 | 0 | || chroma_scaling_from_luma |
865 | 0 | || (fi.sequence.chroma_sampling == ChromaSampling::Cs420 |
866 | 0 | && grain_params.scaling_points_y.is_empty())) |
867 | | { |
868 | 0 | self.write(4, grain_params.scaling_points_cb.len() as u8)?; |
869 | 0 | for point in &grain_params.scaling_points_cb { |
870 | 0 | self.write(8, point[0])?; |
871 | 0 | self.write(8, point[1])?; |
872 | | } |
873 | 0 | self.write(4, grain_params.scaling_points_cr.len() as u8)?; |
874 | 0 | for point in &grain_params.scaling_points_cr { |
875 | 0 | self.write(8, point[0])?; |
876 | 0 | self.write(8, point[1])?; |
877 | | } |
878 | 0 | } |
879 | | |
880 | 0 | self.write(2, grain_params.scaling_shift - 8)?; |
881 | 0 | self.write(2, grain_params.ar_coeff_lag)?; |
882 | | |
883 | 0 | let mut num_pos_luma = |
884 | 0 | (2 * grain_params.ar_coeff_lag * (grain_params.ar_coeff_lag + 1)) |
885 | 0 | as usize; |
886 | 0 | let mut num_pos_chroma; |
887 | 0 | if !grain_params.scaling_points_y.is_empty() { |
888 | 0 | num_pos_chroma = num_pos_luma + 1; |
889 | 0 | for i in 0..num_pos_luma { |
890 | 0 | self.write(8, grain_params.ar_coeffs_y[i] as i16 + 128)?; |
891 | | } |
892 | 0 | } else { |
893 | 0 | num_pos_chroma = num_pos_luma; |
894 | 0 | } |
895 | | |
896 | 0 | if chroma_scaling_from_luma |
897 | 0 | || !grain_params.scaling_points_cb.is_empty() |
898 | | { |
899 | 0 | for i in 0..num_pos_chroma { |
900 | 0 | self.write(8, grain_params.ar_coeffs_cb[i] as i16 + 128)?; |
901 | | } |
902 | 0 | } |
903 | 0 | if chroma_scaling_from_luma |
904 | 0 | || !grain_params.scaling_points_cr.is_empty() |
905 | | { |
906 | 0 | for i in 0..num_pos_chroma { |
907 | 0 | self.write(8, grain_params.ar_coeffs_cr[i] as i16 + 128)?; |
908 | | } |
909 | 0 | } |
910 | | |
911 | 0 | self.write(2, grain_params.ar_coeff_shift - 6)?; |
912 | 0 | self.write(2, grain_params.grain_scale_shift)?; |
913 | 0 | if !grain_params.scaling_points_cb.is_empty() { |
914 | 0 | self.write(8, grain_params.cb_mult)?; |
915 | 0 | self.write(8, grain_params.cb_luma_mult)?; |
916 | 0 | self.write(9, grain_params.cb_offset)?; |
917 | 0 | } |
918 | 0 | if !grain_params.scaling_points_cr.is_empty() { |
919 | 0 | self.write(8, grain_params.cr_mult)?; |
920 | 0 | self.write(8, grain_params.cr_luma_mult)?; |
921 | 0 | self.write(9, grain_params.cr_offset)?; |
922 | 0 | } |
923 | 0 | self.write_bit(grain_params.overlap_flag)?; |
924 | 0 | self.write_bit(fi.sequence.pixel_range == PixelRange::Limited)?; |
925 | | } else { |
926 | | // No film grain for this frame |
927 | 0 | self.write_bit(false)?; |
928 | | } |
929 | 0 | } |
930 | | |
931 | 0 | if fi.large_scale_tile { |
932 | 0 | unimplemented!(); |
933 | 0 | } |
934 | 0 | self.byte_align()?; |
935 | | |
936 | 0 | Ok(()) |
937 | 0 | } Unexecuted instantiation: <bitstream_io::write::BitWriter<&mut alloc::vec::Vec<u8>, bitstream_io::BigEndian> as rav1e::header::UncompressedHeader>::write_frame_header_obu::<u16> Unexecuted instantiation: <bitstream_io::write::BitWriter<&mut alloc::vec::Vec<u8>, bitstream_io::BigEndian> as rav1e::header::UncompressedHeader>::write_frame_header_obu::<u8> |
938 | | // End of OBU Headers |
939 | | |
940 | 0 | fn write_max_frame_size<T: Pixel>( |
941 | 0 | &mut self, fi: &FrameInvariants<T>, |
942 | 0 | ) -> io::Result<()> { |
943 | 0 | // width_bits and height_bits will have to be moved to the sequence header OBU |
944 | 0 | // when we add support for it. |
945 | 0 | let width = fi.width - 1; |
946 | 0 | let height = fi.height - 1; |
947 | 0 | let width_bits = log_in_base_2(width as u32) as u32 + 1; |
948 | 0 | let height_bits = log_in_base_2(height as u32) as u32 + 1; |
949 | 0 | assert!(width_bits <= 16); |
950 | 0 | assert!(height_bits <= 16); |
951 | 0 | self.write(4, width_bits - 1)?; |
952 | 0 | self.write(4, height_bits - 1)?; |
953 | 0 | self.write(width_bits, width as u16)?; |
954 | 0 | self.write(height_bits, height as u16)?; |
955 | 0 | Ok(()) |
956 | 0 | } Unexecuted instantiation: <bitstream_io::write::BitWriter<&mut alloc::vec::Vec<u8>, bitstream_io::BigEndian> as rav1e::header::UncompressedHeader>::write_max_frame_size::<u16> Unexecuted instantiation: <bitstream_io::write::BitWriter<&mut alloc::vec::Vec<u8>, bitstream_io::BigEndian> as rav1e::header::UncompressedHeader>::write_max_frame_size::<u8> |
957 | | |
958 | 0 | fn write_frame_size<T: Pixel>( |
959 | 0 | &mut self, fi: &FrameInvariants<T>, |
960 | 0 | ) -> io::Result<()> { |
961 | 0 | // width_bits and height_bits will have to be moved to the sequence header OBU |
962 | 0 | // when we add support for it. |
963 | 0 | if fi.frame_size_override_flag { |
964 | 0 | let width = fi.width - 1; |
965 | 0 | let height = fi.height - 1; |
966 | 0 | let width_bits = log_in_base_2(width as u32) as u32 + 1; |
967 | 0 | let height_bits = log_in_base_2(height as u32) as u32 + 1; |
968 | 0 | assert!(width_bits <= 16); |
969 | 0 | assert!(height_bits <= 16); |
970 | 0 | self.write(width_bits, width as u16)?; |
971 | 0 | self.write(height_bits, height as u16)?; |
972 | 0 | } |
973 | 0 | if fi.sequence.enable_superres { |
974 | 0 | unimplemented!(); |
975 | 0 | } |
976 | 0 | Ok(()) |
977 | 0 | } Unexecuted instantiation: <bitstream_io::write::BitWriter<&mut alloc::vec::Vec<u8>, bitstream_io::BigEndian> as rav1e::header::UncompressedHeader>::write_frame_size::<u16> Unexecuted instantiation: <bitstream_io::write::BitWriter<&mut alloc::vec::Vec<u8>, bitstream_io::BigEndian> as rav1e::header::UncompressedHeader>::write_frame_size::<u8> |
978 | | |
979 | 0 | fn write_render_size<T: Pixel>( |
980 | 0 | &mut self, fi: &FrameInvariants<T>, |
981 | 0 | ) -> io::Result<()> { |
982 | 0 | self.write_bit(fi.render_and_frame_size_different)?; |
983 | 0 | if fi.render_and_frame_size_different { |
984 | 0 | self.write(16, fi.render_width - 1)?; |
985 | 0 | self.write(16, fi.render_height - 1)?; |
986 | 0 | } |
987 | 0 | Ok(()) |
988 | 0 | } Unexecuted instantiation: <bitstream_io::write::BitWriter<&mut alloc::vec::Vec<u8>, bitstream_io::BigEndian> as rav1e::header::UncompressedHeader>::write_render_size::<u16> Unexecuted instantiation: <bitstream_io::write::BitWriter<&mut alloc::vec::Vec<u8>, bitstream_io::BigEndian> as rav1e::header::UncompressedHeader>::write_render_size::<u8> |
989 | | |
990 | 0 | fn write_frame_size_with_refs<T: Pixel>( |
991 | 0 | &mut self, fi: &FrameInvariants<T>, |
992 | 0 | ) -> io::Result<()> { |
993 | 0 | let mut found_ref = false; |
994 | 0 | for i in 0..INTER_REFS_PER_FRAME { |
995 | 0 | if let Some(ref rec) = fi.rec_buffer.frames[fi.ref_frames[i] as usize] { |
996 | 0 | if rec.width == fi.width as u32 |
997 | 0 | && rec.height == fi.height as u32 |
998 | 0 | && rec.render_width == fi.render_width |
999 | 0 | && rec.render_height == fi.render_height |
1000 | | { |
1001 | 0 | self.write_bit(true)?; |
1002 | 0 | found_ref = true; |
1003 | 0 | break; |
1004 | | } else { |
1005 | 0 | self.write_bit(false)?; |
1006 | | } |
1007 | | } else { |
1008 | 0 | self.write_bit(false)?; |
1009 | | } |
1010 | | } |
1011 | 0 | if !found_ref { |
1012 | 0 | self.write_frame_size(fi)?; |
1013 | 0 | self.write_render_size(fi)?; |
1014 | 0 | } else if fi.sequence.enable_superres { |
1015 | 0 | unimplemented!(); |
1016 | 0 | } |
1017 | 0 | Ok(()) |
1018 | 0 | } Unexecuted instantiation: <bitstream_io::write::BitWriter<&mut alloc::vec::Vec<u8>, bitstream_io::BigEndian> as rav1e::header::UncompressedHeader>::write_frame_size_with_refs::<u16> Unexecuted instantiation: <bitstream_io::write::BitWriter<&mut alloc::vec::Vec<u8>, bitstream_io::BigEndian> as rav1e::header::UncompressedHeader>::write_frame_size_with_refs::<u8> |
1019 | | |
1020 | 0 | fn write_deblock_filter_a<T: Pixel>( |
1021 | 0 | &mut self, fi: &FrameInvariants<T>, deblock: &DeblockState, |
1022 | 0 | ) -> io::Result<()> { |
1023 | 0 | if fi.delta_q_present { |
1024 | 0 | if !fi.allow_intrabc { |
1025 | 0 | self.write_bit(deblock.block_deltas_enabled)?; |
1026 | 0 | } |
1027 | 0 | if deblock.block_deltas_enabled { |
1028 | 0 | self.write(2, deblock.block_delta_shift)?; |
1029 | 0 | self.write_bit(deblock.block_delta_multi)?; |
1030 | 0 | } |
1031 | 0 | } |
1032 | 0 | Ok(()) |
1033 | 0 | } Unexecuted instantiation: <bitstream_io::write::BitWriter<&mut alloc::vec::Vec<u8>, bitstream_io::BigEndian> as rav1e::header::UncompressedHeader>::write_deblock_filter_a::<u16> Unexecuted instantiation: <bitstream_io::write::BitWriter<&mut alloc::vec::Vec<u8>, bitstream_io::BigEndian> as rav1e::header::UncompressedHeader>::write_deblock_filter_a::<u8> |
1034 | | |
1035 | 0 | fn write_deblock_filter_b<T: Pixel>( |
1036 | 0 | &mut self, fi: &FrameInvariants<T>, deblock: &DeblockState, |
1037 | 0 | ) -> io::Result<()> { |
1038 | 0 | let planes = if fi.sequence.chroma_sampling == ChromaSampling::Cs400 { |
1039 | 0 | 1 |
1040 | | } else { |
1041 | 0 | MAX_PLANES |
1042 | | }; |
1043 | 0 | assert!(deblock.levels[0] < 64); |
1044 | 0 | self.write(6, deblock.levels[0])?; // loop deblocking filter level 0 |
1045 | 0 | assert!(deblock.levels[1] < 64); |
1046 | 0 | self.write(6, deblock.levels[1])?; // loop deblocking filter level 1 |
1047 | 0 | if planes > 1 && (deblock.levels[0] > 0 || deblock.levels[1] > 0) { |
1048 | 0 | assert!(deblock.levels[2] < 64); |
1049 | 0 | self.write(6, deblock.levels[2])?; // loop deblocking filter level 2 |
1050 | 0 | assert!(deblock.levels[3] < 64); |
1051 | 0 | self.write(6, deblock.levels[3])?; // loop deblocking filter level 3 |
1052 | 0 | } |
1053 | 0 | self.write(3, deblock.sharpness)?; // deblocking filter sharpness |
1054 | 0 | self.write_bit(deblock.deltas_enabled)?; // loop deblocking filter deltas enabled |
1055 | 0 | if deblock.deltas_enabled { |
1056 | 0 | self.write_bit(deblock.delta_updates_enabled)?; // deltas updates enabled |
1057 | 0 | if deblock.delta_updates_enabled { |
1058 | | // conditionally write ref delta updates |
1059 | 0 | let prev_ref_deltas = if fi.primary_ref_frame == PRIMARY_REF_NONE { |
1060 | 0 | [1, 0, 0, 0, 0, -1, -1, -1] |
1061 | | } else { |
1062 | 0 | fi.rec_buffer.deblock |
1063 | 0 | [fi.ref_frames[fi.primary_ref_frame as usize] as usize] |
1064 | 0 | .ref_deltas |
1065 | | }; |
1066 | 0 | for i in 0..REF_FRAMES { |
1067 | 0 | let update = deblock.ref_deltas[i] != prev_ref_deltas[i]; |
1068 | 0 | self.write_bit(update)?; |
1069 | 0 | if update { |
1070 | 0 | self.write_signed(7, deblock.ref_deltas[i])?; |
1071 | 0 | } |
1072 | | } |
1073 | | // conditionally write mode delta updates |
1074 | 0 | let prev_mode_deltas = if fi.primary_ref_frame == PRIMARY_REF_NONE { |
1075 | 0 | [0, 0] |
1076 | | } else { |
1077 | 0 | fi.rec_buffer.deblock |
1078 | 0 | [fi.ref_frames[fi.primary_ref_frame as usize] as usize] |
1079 | 0 | .mode_deltas |
1080 | | }; |
1081 | 0 | for i in 0..2 { |
1082 | 0 | let update = deblock.mode_deltas[i] != prev_mode_deltas[i]; |
1083 | 0 | self.write_bit(update)?; |
1084 | 0 | if update { |
1085 | 0 | self.write_signed(7, deblock.mode_deltas[i])?; |
1086 | 0 | } |
1087 | | } |
1088 | 0 | } |
1089 | 0 | } |
1090 | 0 | Ok(()) |
1091 | 0 | } Unexecuted instantiation: <bitstream_io::write::BitWriter<&mut alloc::vec::Vec<u8>, bitstream_io::BigEndian> as rav1e::header::UncompressedHeader>::write_deblock_filter_b::<u16> Unexecuted instantiation: <bitstream_io::write::BitWriter<&mut alloc::vec::Vec<u8>, bitstream_io::BigEndian> as rav1e::header::UncompressedHeader>::write_deblock_filter_b::<u8> |
1092 | | |
1093 | 0 | fn write_frame_cdef<T: Pixel>( |
1094 | 0 | &mut self, fi: &FrameInvariants<T>, |
1095 | 0 | ) -> io::Result<()> { |
1096 | 0 | if fi.sequence.enable_cdef && !fi.allow_intrabc { |
1097 | 0 | assert!(fi.cdef_damping >= 3); |
1098 | 0 | assert!(fi.cdef_damping <= 6); |
1099 | 0 | self.write(2, fi.cdef_damping - 3)?; |
1100 | 0 | assert!(fi.cdef_bits < 4); |
1101 | 0 | self.write(2, fi.cdef_bits)?; // cdef bits |
1102 | 0 | for i in 0..(1 << fi.cdef_bits) { |
1103 | 0 | assert!(fi.cdef_y_strengths[i] < 64); |
1104 | 0 | assert!(fi.cdef_uv_strengths[i] < 64); |
1105 | 0 | self.write(6, fi.cdef_y_strengths[i])?; // cdef y strength |
1106 | 0 | if fi.sequence.chroma_sampling != ChromaSampling::Cs400 { |
1107 | 0 | self.write(6, fi.cdef_uv_strengths[i])?; // cdef uv strength |
1108 | 0 | } |
1109 | | } |
1110 | 0 | } |
1111 | 0 | Ok(()) |
1112 | 0 | } Unexecuted instantiation: <bitstream_io::write::BitWriter<&mut alloc::vec::Vec<u8>, bitstream_io::BigEndian> as rav1e::header::UncompressedHeader>::write_frame_cdef::<u16> Unexecuted instantiation: <bitstream_io::write::BitWriter<&mut alloc::vec::Vec<u8>, bitstream_io::BigEndian> as rav1e::header::UncompressedHeader>::write_frame_cdef::<u8> |
1113 | | |
1114 | 0 | fn write_frame_lrf<T: Pixel>( |
1115 | 0 | &mut self, fi: &FrameInvariants<T>, rs: &RestorationState, |
1116 | 0 | ) -> io::Result<()> { |
1117 | 0 | if fi.sequence.enable_restoration && !fi.allow_intrabc { |
1118 | | // && !self.lossless |
1119 | 0 | let planes = if fi.sequence.chroma_sampling == ChromaSampling::Cs400 { |
1120 | 0 | 1 |
1121 | | } else { |
1122 | 0 | MAX_PLANES |
1123 | | }; |
1124 | 0 | let mut use_lrf = false; |
1125 | 0 | let mut use_chroma_lrf = false; |
1126 | 0 | for i in 0..planes { |
1127 | 0 | self.write(2, rs.planes[i].cfg.lrf_type)?; // filter type by plane |
1128 | 0 | if rs.planes[i].cfg.lrf_type != RESTORE_NONE { |
1129 | 0 | use_lrf = true; |
1130 | 0 | if i > 0 { |
1131 | 0 | use_chroma_lrf = true; |
1132 | 0 | } |
1133 | 0 | } |
1134 | | } |
1135 | 0 | if use_lrf { |
1136 | | // The Y shift value written here indicates shift up from superblock size |
1137 | 0 | if !fi.sequence.use_128x128_superblock { |
1138 | 0 | self.write(1, u8::from(rs.planes[0].cfg.unit_size > 64))?; |
1139 | 0 | } |
1140 | | |
1141 | 0 | if rs.planes[0].cfg.unit_size > 64 { |
1142 | 0 | self.write(1, u8::from(rs.planes[0].cfg.unit_size > 128))?; |
1143 | 0 | } |
1144 | | |
1145 | 0 | if use_chroma_lrf |
1146 | 0 | && fi.sequence.chroma_sampling == ChromaSampling::Cs420 |
1147 | | { |
1148 | 0 | self.write( |
1149 | 0 | 1, |
1150 | 0 | u8::from(rs.planes[0].cfg.unit_size > rs.planes[1].cfg.unit_size), |
1151 | 0 | )?; |
1152 | 0 | } |
1153 | 0 | } |
1154 | 0 | } |
1155 | 0 | Ok(()) |
1156 | 0 | } Unexecuted instantiation: <bitstream_io::write::BitWriter<&mut alloc::vec::Vec<u8>, bitstream_io::BigEndian> as rav1e::header::UncompressedHeader>::write_frame_lrf::<u16> Unexecuted instantiation: <bitstream_io::write::BitWriter<&mut alloc::vec::Vec<u8>, bitstream_io::BigEndian> as rav1e::header::UncompressedHeader>::write_frame_lrf::<u8> |
1157 | | |
1158 | 0 | fn write_segment_data<T: Pixel>( |
1159 | 0 | &mut self, fi: &FrameInvariants<T>, segmentation: &SegmentationState, |
1160 | 0 | ) -> io::Result<()> { |
1161 | 0 | assert_eq!(fi.enable_segmentation, segmentation.enabled); |
1162 | 0 | self.write_bit(fi.enable_segmentation)?; |
1163 | | |
1164 | 0 | if segmentation.enabled { |
1165 | 0 | if fi.primary_ref_frame == PRIMARY_REF_NONE { |
1166 | 0 | assert!(segmentation.update_map); |
1167 | 0 | assert!(segmentation.update_data); |
1168 | | } else { |
1169 | 0 | self.write_bit(segmentation.update_map)?; |
1170 | 0 | if segmentation.update_map { |
1171 | 0 | self.write_bit(false)?; /* Without using temporal prediction */ |
1172 | 0 | } |
1173 | 0 | self.write_bit(segmentation.update_data)?; |
1174 | | } |
1175 | 0 | if segmentation.update_data { |
1176 | 0 | for i in 0..8 { |
1177 | 0 | for j in 0..SegLvl::SEG_LVL_MAX as usize { |
1178 | 0 | self.write_bit(segmentation.features[i][j])?; |
1179 | 0 | if segmentation.features[i][j] { |
1180 | 0 | let bits = seg_feature_bits[j]; |
1181 | 0 | let data = segmentation.data[i][j]; |
1182 | 0 | if seg_feature_is_signed[j] { |
1183 | 0 | self.write_signed(bits + 1, data)?; |
1184 | | } else { |
1185 | 0 | self.write(bits, data)?; |
1186 | | } |
1187 | 0 | } |
1188 | | } |
1189 | | } |
1190 | 0 | } |
1191 | 0 | } |
1192 | 0 | Ok(()) |
1193 | 0 | } Unexecuted instantiation: <bitstream_io::write::BitWriter<&mut alloc::vec::Vec<u8>, bitstream_io::BigEndian> as rav1e::header::UncompressedHeader>::write_segment_data::<u16> Unexecuted instantiation: <bitstream_io::write::BitWriter<&mut alloc::vec::Vec<u8>, bitstream_io::BigEndian> as rav1e::header::UncompressedHeader>::write_segment_data::<u8> |
1194 | | |
1195 | 0 | fn write_delta_q(&mut self, delta_q: i8) -> io::Result<()> { |
1196 | 0 | self.write_bit(delta_q != 0)?; |
1197 | 0 | if delta_q != 0 { |
1198 | 0 | assert!((-63..=63).contains(&delta_q)); |
1199 | 0 | self.write_signed(6 + 1, delta_q)?; |
1200 | 0 | } |
1201 | 0 | Ok(()) |
1202 | 0 | } |
1203 | | } |
1204 | | |
1205 | | #[cfg(test)] |
1206 | | mod tests { |
1207 | | use super::ULEB128Writer; |
1208 | | use bitstream_io::{BigEndian, BitWriter}; |
1209 | | use nom::error::Error; |
1210 | | use nom::IResult; |
1211 | | use quickcheck::quickcheck; |
1212 | | |
1213 | | fn leb128(mut input: &[u8]) -> IResult<&[u8], u64, Error<&[u8]>> { |
1214 | | use nom::bytes::complete::take; |
1215 | | |
1216 | | let mut value = 0u64; |
1217 | | for i in 0..8u8 { |
1218 | | let result = take(1usize)(input)?; |
1219 | | input = result.0; |
1220 | | let leb128_byte = result.1[0]; |
1221 | | value |= u64::from(leb128_byte & 0x7f) << (i * 7); |
1222 | | if (leb128_byte & 0x80) == 0 { |
1223 | | break; |
1224 | | } |
1225 | | } |
1226 | | Ok((input, value)) |
1227 | | } |
1228 | | |
1229 | | quickcheck! { |
1230 | | fn validate_leb128_write(val: u32) -> bool { |
1231 | | let mut buf1 = Vec::new(); |
1232 | | let mut bw1 = BitWriter::endian(&mut buf1, BigEndian); |
1233 | | bw1.write_uleb128(val as u64).unwrap(); |
1234 | | let result = leb128(&buf1).unwrap(); |
1235 | | u64::from(val) == result.1 && result.0.is_empty() |
1236 | | } |
1237 | | } |
1238 | | } |