Coverage Report

Created: 2025-07-11 07:25

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