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