Coverage Report

Created: 2025-12-11 07:11

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}