scuffle_av1/obu/
seq.rs

1//! Sequence Header
2
3use std::io;
4
5use byteorder::{BigEndian, ReadBytesExt};
6use scuffle_bytes_util::BitReader;
7
8use super::ObuHeader;
9use crate::obu::utils::read_uvlc;
10
11/// Sequence Header OBU
12///
13/// AV1-Spec-2 - 5.5
14#[derive(Debug, Clone, PartialEq, Eq)]
15pub struct SequenceHeaderObu {
16    /// The OBU header that precedes the sequence header
17    pub header: ObuHeader,
18    /// `seq_profile`
19    ///
20    /// 3 bits
21    pub seq_profile: u8,
22    /// `still_picture`
23    ///
24    /// 1 bit
25    pub still_picture: bool,
26    /// `reduced_still_picture_header`
27    ///
28    /// 1 bit
29    pub reduced_still_picture_header: bool,
30    /// `timing_info` if `reduced_still_picture_header` is 0 and `timing_info_present_flag` is 1
31    pub timing_info: Option<TimingInfo>,
32    /// `decoder_model_info` if
33    /// - `reduced_still_picture_header` is 0
34    /// - `timing_info_present_flag` is 1
35    /// - `decoder_model_info_present_flag` is 1
36    pub decoder_model_info: Option<DecoderModelInfo>,
37    /// All operating points
38    pub operating_points: Vec<OperatingPoint>,
39    /// `max_frame_width_minus_1 + 1`
40    pub max_frame_width: u64,
41    /// `max_frame_height_minus_1 + 1`
42    pub max_frame_height: u64,
43    /// The [`FrameIds`] if `reduced_still_picture_header` is 0 and `frame_id_numbers_present_flag` is 1
44    pub frame_ids: Option<FrameIds>,
45    /// `use_128x128_superblock`
46    ///
47    /// 1 bit
48    pub use_128x128_superblock: bool,
49    /// `enable_filter_intra`
50    ///
51    /// 1 bit
52    pub enable_filter_intra: bool,
53    /// `enable_intra_edge_filter`
54    ///
55    /// 1 bit
56    pub enable_intra_edge_filter: bool,
57    /// `enable_interintra_compound`
58    ///
59    /// 1 bit
60    pub enable_interintra_compound: bool,
61    /// `enable_masked_compound`
62    ///
63    /// 1 bit
64    pub enable_masked_compound: bool,
65    /// `enable_warped_motion`
66    ///
67    /// 1 bit
68    pub enable_warped_motion: bool,
69    /// `enable_dual_filter`
70    ///
71    /// 1 bit
72    pub enable_dual_filter: bool,
73    /// `enable_order_hint`
74    ///
75    /// 1 bit
76    pub enable_order_hint: bool,
77    /// `enable_jnt_comp`
78    ///
79    /// 1 bit
80    pub enable_jnt_comp: bool,
81    /// `enable_ref_frame_mvs`
82    ///
83    /// 1 bit
84    pub enable_ref_frame_mvs: bool,
85    /// `seq_force_screen_content_tools`
86    pub seq_force_screen_content_tools: u8,
87    /// `seq_force_integer_mv`
88    pub seq_force_integer_mv: u8,
89    /// `OrderHintBits`
90    ///
91    /// 3 bits
92    pub order_hint_bits: u8,
93    /// `enable_superres`
94    ///
95    /// 1 bit
96    pub enable_superres: bool,
97    /// `enable_cdef`
98    ///
99    /// 1 bit
100    pub enable_cdef: bool,
101    /// `enable_restoration`
102    ///
103    /// 1 bit
104    pub enable_restoration: bool,
105    /// `color_config()`
106    pub color_config: ColorConfig,
107    /// `film_grain_params_present`
108    pub film_grain_params_present: bool,
109}
110
111/// Frame IDs
112///
113/// Can be part of the [`SequenceHeaderObu`].
114#[derive(Debug, Clone, PartialEq, Eq, Copy)]
115pub struct FrameIds {
116    /// `delta_frame_id_length_minus_2 + 2`
117    ///
118    /// 4 bits
119    pub delta_frame_id_length: u8,
120    /// `additional_frame_id_length_minus_1 + 1`
121    ///
122    /// 3 bits
123    pub additional_frame_id_length: u8,
124}
125
126/// Operating Point
127///
128/// Part of the [`SequenceHeaderObu`].
129#[derive(Debug, Clone, PartialEq, Eq, Copy)]
130pub struct OperatingPoint {
131    /// `operating_point_idc`
132    ///
133    /// 12 bits
134    pub idc: u16,
135    /// `seq_level_idx`
136    ///
137    /// 5 bits
138    pub seq_level_idx: u8,
139    /// `seq_tier`
140    ///
141    /// 1 bit
142    pub seq_tier: bool,
143    /// `operating_parameters_info` if `decoder_model_info_present_flag` is 1
144    pub operating_parameters_info: Option<OperatingParametersInfo>,
145    /// `initial_display_delay_minus_1 + 1` if `initial_display_delay_present_flag` is 1 and `initial_display_delay_present_for_this_op` is 1
146    ///
147    /// 4 bits
148    pub initial_display_delay: Option<u8>,
149}
150
151/// Timing info
152///
153/// AV1-Spec-2 - 5.5.3
154#[derive(Debug, Clone, PartialEq, Eq, Copy)]
155pub struct TimingInfo {
156    /// `num_units_in_display_tick`
157    ///
158    /// 32 bits
159    pub num_units_in_display_tick: u32,
160    /// `time_scale`
161    ///
162    /// 32 bits
163    pub time_scale: u32,
164    /// `num_ticks_per_picture_minus_1 + 1` if `equal_picture_interval` is 1
165    ///
166    /// uvlc()
167    pub num_ticks_per_picture: Option<u64>,
168}
169
170impl TimingInfo {
171    /// Parses the timing info from the given reader.
172    pub fn parse(bit_reader: &mut BitReader<impl io::Read>) -> io::Result<Self> {
173        let num_units_in_display_tick = bit_reader.read_u32::<BigEndian>()?;
174        let time_scale = bit_reader.read_u32::<BigEndian>()?;
175        let num_ticks_per_picture = if bit_reader.read_bit()? {
176            Some(read_uvlc(bit_reader)? + 1)
177        } else {
178            None
179        };
180        Ok(Self {
181            num_units_in_display_tick,
182            time_scale,
183            num_ticks_per_picture,
184        })
185    }
186}
187
188/// Decoder model info
189///
190/// AV1-Spec-2 - 5.5.4
191#[derive(Debug, Clone, PartialEq, Eq, Copy)]
192pub struct DecoderModelInfo {
193    /// `buffer_delay_length_minus_1 + 1`
194    ///
195    /// 5 bits
196    pub buffer_delay_length: u8,
197    /// `num_units_in_decoding_tick`
198    ///
199    /// 32 bits
200    pub num_units_in_decoding_tick: u32,
201    /// `buffer_removal_time_length_minus_1 + 1`
202    ///
203    /// 5 bits
204    pub buffer_removal_time_length: u8,
205    /// `frame_presentation_time_length_minus_1 + 1`
206    ///
207    /// 5 bits
208    pub frame_presentation_time_length: u8,
209}
210
211impl DecoderModelInfo {
212    /// Parses the decoder model info from the given reader.
213    pub fn parse(bit_reader: &mut BitReader<impl io::Read>) -> io::Result<Self> {
214        let buffer_delay_length = bit_reader.read_bits(5)? as u8 + 1;
215        let num_units_in_decoding_tick = bit_reader.read_u32::<BigEndian>()?;
216        let buffer_removal_time_length = bit_reader.read_bits(5)? as u8 + 1;
217        let frame_presentation_time_length = bit_reader.read_bits(5)? as u8 + 1;
218        Ok(Self {
219            buffer_delay_length,
220            num_units_in_decoding_tick,
221            buffer_removal_time_length,
222            frame_presentation_time_length,
223        })
224    }
225}
226
227/// Operating parameters info
228///
229///  AV1-Spec-2 - 5.5.5
230#[derive(Debug, Clone, PartialEq, Eq, Copy)]
231pub struct OperatingParametersInfo {
232    /// `decoder_buffer_delay`
233    pub decoder_buffer_delay: u64,
234    /// `encoder_buffer_delay`
235    pub encoder_buffer_delay: u64,
236    /// `low_delay_mode_flag`
237    ///
238    /// 1 bit
239    pub low_delay_mode_flag: bool,
240}
241
242impl OperatingParametersInfo {
243    /// Parses the operating parameters info from the given reader.
244    pub fn parse(delay_bit_length: u8, bit_reader: &mut BitReader<impl io::Read>) -> io::Result<Self> {
245        let decoder_buffer_delay = bit_reader.read_bits(delay_bit_length)?;
246        let encoder_buffer_delay = bit_reader.read_bits(delay_bit_length)?;
247        let low_delay_mode_flag = bit_reader.read_bit()?;
248
249        Ok(Self {
250            decoder_buffer_delay,
251            encoder_buffer_delay,
252            low_delay_mode_flag,
253        })
254    }
255}
256
257/// Color config
258///
259/// AV1-Spec-2 - 5.5.2
260#[derive(Debug, Clone, PartialEq, Eq, Copy)]
261pub struct ColorConfig {
262    /// `BitDepth`
263    pub bit_depth: i32,
264    /// `mono_chrome`
265    ///
266    /// 1 bit
267    pub mono_chrome: bool,
268    /// `NumPlanes`
269    pub num_planes: u8,
270    /// `color_primaries`
271    ///
272    /// 8 bits
273    pub color_primaries: u8,
274    /// `transfer_characteristics`
275    ///
276    /// 8 bits
277    pub transfer_characteristics: u8,
278    /// `matrix_coefficients`
279    ///
280    /// 8 bits
281    pub matrix_coefficients: u8,
282    /// `color_range`
283    ///
284    /// 1 bit
285    pub full_color_range: bool,
286    /// `subsampling_x`
287    ///
288    /// 1 bit
289    pub subsampling_x: bool,
290    /// `subsampling_y`
291    ///
292    /// 1 bit
293    pub subsampling_y: bool,
294    /// `chroma_sample_position`
295    ///
296    /// 2 bits
297    pub chroma_sample_position: u8,
298    /// `separate_uv_delta_q`
299    ///
300    /// 1 bit
301    pub separate_uv_delta_q: bool,
302}
303
304#[derive(Debug, Clone, PartialEq, Eq, Copy)]
305struct ColorRangeAndSubsampling {
306    color_range: bool,
307    subsampling_x: bool,
308    subsampling_y: bool,
309}
310
311impl ColorConfig {
312    fn parse_color_range_and_subsampling(
313        bit_reader: &mut BitReader<impl io::Read>,
314        seq_profile: u8,
315        color_primaries: u8,
316        transfer_characteristics: u8,
317        matrix_coefficients: u8,
318        bit_depth: i32,
319    ) -> io::Result<ColorRangeAndSubsampling> {
320        let color_range;
321        let subsampling_x;
322        let subsampling_y;
323
324        const CP_BT_709: u8 = 1;
325        const TC_SRGB: u8 = 13;
326        const MC_IDENTITY: u8 = 0;
327
328        if color_primaries == CP_BT_709 && transfer_characteristics == TC_SRGB && matrix_coefficients == MC_IDENTITY {
329            color_range = true;
330            subsampling_x = false;
331            subsampling_y = false;
332        } else {
333            color_range = bit_reader.read_bit()?;
334            if seq_profile == 0 {
335                subsampling_x = true;
336                subsampling_y = true;
337            } else if seq_profile == 1 {
338                subsampling_x = false;
339                subsampling_y = false;
340            } else if bit_depth == 12 {
341                subsampling_x = bit_reader.read_bit()?;
342                if subsampling_x {
343                    subsampling_y = bit_reader.read_bit()?;
344                } else {
345                    subsampling_y = false;
346                }
347            } else {
348                subsampling_x = true;
349                subsampling_y = false;
350            }
351        }
352
353        Ok(ColorRangeAndSubsampling {
354            color_range,
355            subsampling_x,
356            subsampling_y,
357        })
358    }
359
360    /// Parses the color config from the given reader.
361    pub fn parse(seq_profile: u8, bit_reader: &mut BitReader<impl io::Read>) -> io::Result<Self> {
362        let high_bitdepth = bit_reader.read_bit()?;
363        let bit_depth = match (seq_profile, high_bitdepth) {
364            (2, true) if bit_reader.read_bit()? => 12,
365            (_, true) => 10,
366            (_, false) => 8,
367        };
368
369        let mono_chrome = if seq_profile == 1 { false } else { bit_reader.read_bit()? };
370
371        let color_primaries;
372        let transfer_characteristics;
373        let matrix_coefficients;
374
375        let color_description_present_flag = bit_reader.read_bit()?;
376        if color_description_present_flag {
377            color_primaries = bit_reader.read_bits(8)? as u8;
378            transfer_characteristics = bit_reader.read_bits(8)? as u8;
379            matrix_coefficients = bit_reader.read_bits(8)? as u8;
380        } else {
381            color_primaries = 2; // CP_UNSPECIFIED
382            transfer_characteristics = 2; // TC_UNSPECIFIED
383            matrix_coefficients = 2; // MC_UNSPECIFIED
384        }
385
386        let num_planes = if mono_chrome { 1 } else { 3 };
387
388        if mono_chrome {
389            Ok(ColorConfig {
390                bit_depth,
391                color_primaries,
392                transfer_characteristics,
393                matrix_coefficients,
394                full_color_range: bit_reader.read_bit()?,
395                subsampling_x: true,
396                subsampling_y: true,
397                mono_chrome,
398                separate_uv_delta_q: false,
399                chroma_sample_position: 0, // CSP_UNKNOWN
400                num_planes,
401            })
402        } else {
403            let ColorRangeAndSubsampling {
404                color_range,
405                subsampling_x,
406                subsampling_y,
407            } = Self::parse_color_range_and_subsampling(
408                bit_reader,
409                seq_profile,
410                color_primaries,
411                transfer_characteristics,
412                matrix_coefficients,
413                bit_depth,
414            )?;
415
416            let chroma_sample_position = if subsampling_x && subsampling_y {
417                bit_reader.read_bits(2)? as u8
418            } else {
419                0 // CSP_UNKNOWN
420            };
421
422            let separate_uv_delta_q = bit_reader.read_bit()?;
423            Ok(ColorConfig {
424                bit_depth,
425                mono_chrome,
426                color_primaries,
427                transfer_characteristics,
428                matrix_coefficients,
429                full_color_range: color_range,
430                subsampling_x,
431                subsampling_y,
432                chroma_sample_position,
433                separate_uv_delta_q,
434                num_planes,
435            })
436        }
437    }
438}
439
440impl SequenceHeaderObu {
441    /// Returns a reference to the header of the OBU.
442    pub const fn header(&self) -> &ObuHeader {
443        &self.header
444    }
445
446    /// Parses the sequence header from the given reader.
447    ///
448    /// The given header will be part of the returned struct and can be accessed through the [`SequenceHeaderObu::header`] function.
449    pub fn parse(header: ObuHeader, reader: &mut impl io::Read) -> io::Result<Self> {
450        let mut bit_reader = BitReader::new(reader);
451
452        let seq_profile = bit_reader.read_bits(3)? as u8;
453        let still_picture = bit_reader.read_bit()?;
454        let reduced_still_picture_header = bit_reader.read_bit()?;
455
456        if !still_picture && reduced_still_picture_header {
457            return Err(io::Error::new(
458                io::ErrorKind::InvalidData,
459                "reduced_still_picture_header is true but still_picture is false",
460            ));
461        }
462
463        let mut timing_info = None;
464        let mut decoder_model_info = None;
465        let mut operating_points = Vec::new();
466
467        if reduced_still_picture_header {
468            operating_points.push(OperatingPoint {
469                idc: 0,
470                seq_level_idx: bit_reader.read_bits(5)? as u8,
471                seq_tier: false,
472                operating_parameters_info: None,
473                initial_display_delay: None,
474            });
475        } else {
476            let timing_info_present_flag = bit_reader.read_bit()?;
477            if timing_info_present_flag {
478                timing_info = Some(TimingInfo::parse(&mut bit_reader)?);
479
480                let decoder_model_info_present_flag = bit_reader.read_bit()?;
481                if decoder_model_info_present_flag {
482                    decoder_model_info = Some(DecoderModelInfo::parse(&mut bit_reader)?);
483                }
484            }
485
486            let initial_display_delay_present_flag = bit_reader.read_bit()?;
487            let operating_points_cnt_minus_1 = bit_reader.read_bits(5)? as u8;
488            for _ in 0..operating_points_cnt_minus_1 + 1 {
489                let idc = bit_reader.read_bits(12)? as u16;
490                let seq_level_idx = bit_reader.read_bits(5)? as u8;
491                let seq_tier = if seq_level_idx > 7 { bit_reader.read_bit()? } else { false };
492                let decoder_model_present_for_this_op = if let Some(decoder_model_info) = decoder_model_info {
493                    bit_reader.read_bit()?.then_some(decoder_model_info.buffer_delay_length)
494                } else {
495                    None
496                };
497
498                let operating_parameters_info = if let Some(delay_bit_length) = decoder_model_present_for_this_op {
499                    Some(OperatingParametersInfo::parse(delay_bit_length, &mut bit_reader)?)
500                } else {
501                    None
502                };
503
504                let initial_display_delay = if initial_display_delay_present_flag {
505                    if bit_reader.read_bit()? {
506                        // initial_display_delay_present_for_this_op
507                        Some(bit_reader.read_bits(4)? as u8 + 1) // initial_display_delay_minus_1
508                    } else {
509                        None
510                    }
511                } else {
512                    None
513                };
514
515                operating_points.push(OperatingPoint {
516                    idc,
517                    seq_level_idx,
518                    seq_tier,
519                    operating_parameters_info,
520                    initial_display_delay,
521                });
522            }
523        }
524
525        let frame_width_bits = bit_reader.read_bits(4)? as u8 + 1;
526        let frame_height_bits = bit_reader.read_bits(4)? as u8 + 1;
527
528        let max_frame_width = bit_reader.read_bits(frame_width_bits)? + 1;
529        let max_frame_height = bit_reader.read_bits(frame_height_bits)? + 1;
530
531        let frame_id_numbers_present_flag = if reduced_still_picture_header {
532            false
533        } else {
534            bit_reader.read_bit()?
535        };
536        let frame_ids = if frame_id_numbers_present_flag {
537            let delta_frame_id_length = bit_reader.read_bits(4)? as u8 + 2;
538            let additional_frame_id_length = bit_reader.read_bits(3)? as u8 + 1;
539            Some(FrameIds {
540                delta_frame_id_length,
541                additional_frame_id_length,
542            })
543        } else {
544            None
545        };
546
547        let use_128x128_superblock = bit_reader.read_bit()?;
548        let enable_filter_intra = bit_reader.read_bit()?;
549        let enable_intra_edge_filter = bit_reader.read_bit()?;
550
551        let enable_interintra_compound;
552        let enable_masked_compound;
553        let enable_warped_motion;
554        let enable_dual_filter;
555        let enable_order_hint;
556        let enable_jnt_comp;
557        let enable_ref_frame_mvs;
558        let order_hint_bits;
559        let seq_force_integer_mv;
560
561        let seq_force_screen_content_tools;
562
563        if !reduced_still_picture_header {
564            enable_interintra_compound = bit_reader.read_bit()?;
565            enable_masked_compound = bit_reader.read_bit()?;
566            enable_warped_motion = bit_reader.read_bit()?;
567            enable_dual_filter = bit_reader.read_bit()?;
568            enable_order_hint = bit_reader.read_bit()?;
569            if enable_order_hint {
570                enable_jnt_comp = bit_reader.read_bit()?;
571                enable_ref_frame_mvs = bit_reader.read_bit()?;
572            } else {
573                enable_jnt_comp = false;
574                enable_ref_frame_mvs = false;
575            }
576            if bit_reader.read_bit()? {
577                // seq_choose_screen_content_tools
578                seq_force_screen_content_tools = 2; // SELECT_SCREEN_CONTENT_TOOLS
579            } else {
580                seq_force_screen_content_tools = bit_reader.read_bits(1)? as u8;
581            }
582
583            // If seq_force_screen_content_tools is 0, then seq_force_integer_mv must be 2.
584            // Or if the next bit is 0, then seq_force_integer_mv must be 2.
585            if seq_force_screen_content_tools == 0 || bit_reader.read_bit()? {
586                seq_force_integer_mv = 2; // SELECT_INTEGER_MV
587            } else {
588                seq_force_integer_mv = bit_reader.read_bits(1)? as u8;
589            }
590
591            if enable_order_hint {
592                order_hint_bits = bit_reader.read_bits(3)? as u8 + 1;
593            } else {
594                order_hint_bits = 0;
595            }
596        } else {
597            enable_interintra_compound = false;
598            enable_masked_compound = false;
599            enable_warped_motion = false;
600            enable_dual_filter = false;
601            enable_order_hint = false;
602            enable_jnt_comp = false;
603            enable_ref_frame_mvs = false;
604            seq_force_screen_content_tools = 2; // SELECT_SCREEN_CONTENT_TOOLS
605            seq_force_integer_mv = 2; // SELECT_INTEGER_MV
606            order_hint_bits = 0;
607        }
608
609        let enable_superres = bit_reader.read_bit()?;
610        let enable_cdef = bit_reader.read_bit()?;
611        let enable_restoration = bit_reader.read_bit()?;
612
613        let color_config = ColorConfig::parse(seq_profile, &mut bit_reader)?;
614
615        let film_grain_params_present = bit_reader.read_bit()?;
616
617        Ok(Self {
618            header,
619            seq_profile,
620            still_picture,
621            reduced_still_picture_header,
622            operating_points,
623            decoder_model_info,
624            max_frame_width,
625            max_frame_height,
626            frame_ids,
627            use_128x128_superblock,
628            enable_filter_intra,
629            enable_intra_edge_filter,
630            enable_interintra_compound,
631            enable_masked_compound,
632            enable_warped_motion,
633            enable_dual_filter,
634            enable_order_hint,
635            enable_jnt_comp,
636            enable_ref_frame_mvs,
637            seq_force_screen_content_tools,
638            seq_force_integer_mv,
639            order_hint_bits,
640            enable_superres,
641            enable_cdef,
642            enable_restoration,
643            timing_info,
644            color_config,
645            film_grain_params_present,
646        })
647    }
648}
649
650#[cfg(test)]
651#[cfg_attr(all(coverage_nightly, test), coverage(off))]
652mod tests {
653    use byteorder::WriteBytesExt;
654    use scuffle_bytes_util::BitWriter;
655
656    use super::*;
657    use crate::ObuType;
658
659    #[test]
660    fn test_seq_obu_parse() {
661        let obu = b"\0\0\0j\xef\xbf\xe1\xbc\x02\x19\x90\x10\x10\x10@";
662
663        let header = ObuHeader {
664            obu_type: ObuType::SequenceHeader,
665            size: None,
666            extension_header: None,
667        };
668
669        let seq_header = SequenceHeaderObu::parse(header, &mut io::Cursor::new(obu)).unwrap();
670
671        insta::assert_debug_snapshot!(seq_header, @r"
672        SequenceHeaderObu {
673            header: ObuHeader {
674                obu_type: SequenceHeader,
675                size: None,
676                extension_header: None,
677            },
678            seq_profile: 0,
679            still_picture: false,
680            reduced_still_picture_header: false,
681            timing_info: None,
682            decoder_model_info: None,
683            operating_points: [
684                OperatingPoint {
685                    idc: 0,
686                    seq_level_idx: 13,
687                    seq_tier: false,
688                    operating_parameters_info: None,
689                    initial_display_delay: None,
690                },
691            ],
692            max_frame_width: 3840,
693            max_frame_height: 2160,
694            frame_ids: None,
695            use_128x128_superblock: false,
696            enable_filter_intra: false,
697            enable_intra_edge_filter: false,
698            enable_interintra_compound: false,
699            enable_masked_compound: false,
700            enable_warped_motion: false,
701            enable_dual_filter: false,
702            enable_order_hint: true,
703            enable_jnt_comp: false,
704            enable_ref_frame_mvs: false,
705            seq_force_screen_content_tools: 0,
706            seq_force_integer_mv: 2,
707            order_hint_bits: 7,
708            enable_superres: false,
709            enable_cdef: true,
710            enable_restoration: true,
711            color_config: ColorConfig {
712                bit_depth: 8,
713                mono_chrome: false,
714                num_planes: 3,
715                color_primaries: 1,
716                transfer_characteristics: 1,
717                matrix_coefficients: 1,
718                full_color_range: false,
719                subsampling_x: true,
720                subsampling_y: true,
721                chroma_sample_position: 0,
722                separate_uv_delta_q: false,
723            },
724            film_grain_params_present: false,
725        }
726        ");
727
728        assert_eq!(seq_header.header(), &header);
729    }
730
731    #[test]
732    fn test_seq_obu_parse_reduced_still_picture() {
733        let mut bits = BitWriter::new(Vec::new());
734
735        bits.write_bits(0b010, 3).unwrap(); // seq_profile (2)
736        bits.write_bit(true).unwrap(); // still_picture
737        bits.write_bit(true).unwrap(); // reduced_still_picture_header
738        bits.write_bits(11, 5).unwrap(); // seq_lvl_idx
739
740        bits.write_bits(15, 4).unwrap();
741        bits.write_bits(15, 4).unwrap();
742        bits.write_bits(1919, 16).unwrap();
743        bits.write_bits(1079, 16).unwrap();
744
745        bits.write_bit(false).unwrap(); // use_128x128_superblock
746        bits.write_bit(false).unwrap(); // enable_filter_intra
747        bits.write_bit(false).unwrap(); // enable_intra_edge_filter
748        bits.write_bit(false).unwrap(); // enable_superres
749        bits.write_bit(false).unwrap(); // enable_cdef
750        bits.write_bit(false).unwrap(); // enable_restoration
751
752        bits.write_bit(false).unwrap(); // high_bitdepth
753        bits.write_bit(true).unwrap(); // mono_chrome
754        bits.write_bit(false).unwrap(); // color_description_present_flag
755        bits.write_bit(true).unwrap(); // color_range
756        bits.write_bit(true).unwrap(); // separate_uv_delta_q
757
758        bits.write_bit(true).unwrap(); // film_grain_params_present
759
760        let obu_header = SequenceHeaderObu::parse(
761            ObuHeader {
762                obu_type: ObuType::SequenceHeader,
763                size: None,
764                extension_header: None,
765            },
766            &mut io::Cursor::new(bits.finish().unwrap()),
767        )
768        .unwrap();
769
770        insta::assert_debug_snapshot!(obu_header, @r"
771        SequenceHeaderObu {
772            header: ObuHeader {
773                obu_type: SequenceHeader,
774                size: None,
775                extension_header: None,
776            },
777            seq_profile: 2,
778            still_picture: true,
779            reduced_still_picture_header: true,
780            timing_info: None,
781            decoder_model_info: None,
782            operating_points: [
783                OperatingPoint {
784                    idc: 0,
785                    seq_level_idx: 11,
786                    seq_tier: false,
787                    operating_parameters_info: None,
788                    initial_display_delay: None,
789                },
790            ],
791            max_frame_width: 1920,
792            max_frame_height: 1080,
793            frame_ids: None,
794            use_128x128_superblock: false,
795            enable_filter_intra: false,
796            enable_intra_edge_filter: false,
797            enable_interintra_compound: false,
798            enable_masked_compound: false,
799            enable_warped_motion: false,
800            enable_dual_filter: false,
801            enable_order_hint: false,
802            enable_jnt_comp: false,
803            enable_ref_frame_mvs: false,
804            seq_force_screen_content_tools: 2,
805            seq_force_integer_mv: 2,
806            order_hint_bits: 0,
807            enable_superres: false,
808            enable_cdef: false,
809            enable_restoration: false,
810            color_config: ColorConfig {
811                bit_depth: 8,
812                mono_chrome: true,
813                num_planes: 1,
814                color_primaries: 2,
815                transfer_characteristics: 2,
816                matrix_coefficients: 2,
817                full_color_range: true,
818                subsampling_x: true,
819                subsampling_y: true,
820                chroma_sample_position: 0,
821                separate_uv_delta_q: false,
822            },
823            film_grain_params_present: true,
824        }
825        ");
826    }
827
828    #[test]
829    fn test_seq_obu_parse_timing_info_decoder_model_preset() {
830        let mut bits = BitWriter::new(Vec::new());
831
832        bits.write_bits(0b010, 3).unwrap(); // seq_profile (2)
833        bits.write_bit(false).unwrap(); // still_picture
834        bits.write_bit(false).unwrap(); // reduced_still_picture_header
835        bits.write_bit(true).unwrap(); // timing_info_present_flag
836
837        bits.write_u32::<BigEndian>(1).unwrap(); // num_units_in_display_tick
838        bits.write_u32::<BigEndian>(1).unwrap(); // time_scale
839        bits.write_bit(false).unwrap(); // num_ticks_per_picture
840
841        bits.write_bit(true).unwrap(); // decoder_model_info_present_flag
842        bits.write_bits(4, 5).unwrap(); // buffer_delay_length
843        bits.write_u32::<BigEndian>(1).unwrap(); // num_units_in_decoding_tick
844        bits.write_bits(4, 5).unwrap(); // buffer_removal_time_length
845        bits.write_bits(4, 5).unwrap(); // frame_presentation_time_length
846
847        bits.write_bit(true).unwrap(); // initial_display_delay_present_flag
848        bits.write_bits(0, 5).unwrap(); // operating_points_cnt_minus_1
849
850        bits.write_bits(0, 12).unwrap(); // idc
851        bits.write_bits(1, 5).unwrap(); // seq_lvl_idx
852        bits.write_bit(true).unwrap(); // seq_tier
853
854        bits.write_bits(0b1010, 5).unwrap(); // decoder_buffer_delay
855        bits.write_bits(0b0101, 5).unwrap(); // encoder_buffer_delay
856        bits.write_bit(false).unwrap(); // low_delay_mode_flag
857
858        bits.write_bit(true).unwrap(); // film_grain_params_present
859        bits.write_bits(15, 4).unwrap(); // initial_display_delay_minus_1
860
861        bits.write_bits(15, 4).unwrap(); // operating_points_cnt_minus_1
862        bits.write_bits(15, 4).unwrap(); // operating_points_cnt_minus_1
863        bits.write_bits(1919, 16).unwrap(); // operating_points_cnt_minus_1
864        bits.write_bits(1079, 16).unwrap(); // operating_points_cnt_minus_1
865
866        bits.write_bit(true).unwrap(); // frame_id_numbers_present_flag
867        bits.write_bits(0b1101, 4).unwrap(); // delta_frame_id_length
868        bits.write_bits(0b101, 3).unwrap(); // additional_frame_id_length
869
870        bits.write_bit(false).unwrap(); // use_128x128_superblock
871        bits.write_bit(false).unwrap(); // enable_filter_intra
872        bits.write_bit(false).unwrap(); // enable_intra_edge_filter
873
874        bits.write_bit(false).unwrap(); // enable_interintra_compound
875        bits.write_bit(false).unwrap(); // enable_masked_compound
876        bits.write_bit(false).unwrap(); // enable_warped_motion
877        bits.write_bit(false).unwrap(); // enable_dual_filter
878        bits.write_bit(true).unwrap(); // enable_order_hint
879        bits.write_bit(false).unwrap(); // enable_jnt_comp
880        bits.write_bit(false).unwrap(); // enable_ref_frame_mvs
881
882        bits.write_bit(false).unwrap();
883        bits.write_bit(true).unwrap();
884        bits.write_bit(false).unwrap();
885        bits.write_bit(false).unwrap();
886
887        bits.write_bits(0b100, 3).unwrap();
888
889        bits.write_bit(false).unwrap(); // enable_superres
890        bits.write_bit(false).unwrap(); // enable_cdef
891        bits.write_bit(false).unwrap(); // enable_restoration
892
893        bits.write_bit(false).unwrap(); // high_bitdepth
894        bits.write_bit(true).unwrap(); // mono_chrome
895        bits.write_bit(false).unwrap(); // color_description_present_flag
896        bits.write_bit(true).unwrap(); // color_range
897        bits.write_bit(true).unwrap(); // separate_uv_delta_q
898
899        bits.write_bit(true).unwrap(); // film_grain_params_present
900
901        let obu_header = SequenceHeaderObu::parse(
902            ObuHeader {
903                obu_type: ObuType::SequenceHeader,
904                size: None,
905                extension_header: None,
906            },
907            &mut io::Cursor::new(bits.finish().unwrap()),
908        )
909        .unwrap();
910
911        insta::assert_debug_snapshot!(obu_header, @r"
912        SequenceHeaderObu {
913            header: ObuHeader {
914                obu_type: SequenceHeader,
915                size: None,
916                extension_header: None,
917            },
918            seq_profile: 2,
919            still_picture: false,
920            reduced_still_picture_header: false,
921            timing_info: Some(
922                TimingInfo {
923                    num_units_in_display_tick: 1,
924                    time_scale: 1,
925                    num_ticks_per_picture: None,
926                },
927            ),
928            decoder_model_info: Some(
929                DecoderModelInfo {
930                    buffer_delay_length: 5,
931                    num_units_in_decoding_tick: 1,
932                    buffer_removal_time_length: 5,
933                    frame_presentation_time_length: 5,
934                },
935            ),
936            operating_points: [
937                OperatingPoint {
938                    idc: 0,
939                    seq_level_idx: 1,
940                    seq_tier: false,
941                    operating_parameters_info: Some(
942                        OperatingParametersInfo {
943                            decoder_buffer_delay: 10,
944                            encoder_buffer_delay: 5,
945                            low_delay_mode_flag: false,
946                        },
947                    ),
948                    initial_display_delay: Some(
949                        16,
950                    ),
951                },
952            ],
953            max_frame_width: 1920,
954            max_frame_height: 1080,
955            frame_ids: Some(
956                FrameIds {
957                    delta_frame_id_length: 15,
958                    additional_frame_id_length: 6,
959                },
960            ),
961            use_128x128_superblock: false,
962            enable_filter_intra: false,
963            enable_intra_edge_filter: false,
964            enable_interintra_compound: false,
965            enable_masked_compound: false,
966            enable_warped_motion: false,
967            enable_dual_filter: false,
968            enable_order_hint: true,
969            enable_jnt_comp: false,
970            enable_ref_frame_mvs: false,
971            seq_force_screen_content_tools: 1,
972            seq_force_integer_mv: 0,
973            order_hint_bits: 5,
974            enable_superres: false,
975            enable_cdef: false,
976            enable_restoration: false,
977            color_config: ColorConfig {
978                bit_depth: 8,
979                mono_chrome: true,
980                num_planes: 1,
981                color_primaries: 2,
982                transfer_characteristics: 2,
983                matrix_coefficients: 2,
984                full_color_range: true,
985                subsampling_x: true,
986                subsampling_y: true,
987                chroma_sample_position: 0,
988                separate_uv_delta_q: false,
989            },
990            film_grain_params_present: true,
991        }
992        ");
993    }
994
995    #[test]
996    fn test_seq_obu_parse_num_ticks_per_picture() {
997        let mut bits = BitWriter::new(Vec::new());
998
999        bits.write_bits(0b010, 3).unwrap(); // seq_profile (2)
1000        bits.write_bit(false).unwrap(); // still_picture
1001        bits.write_bit(false).unwrap(); // reduced_still_picture_header
1002        bits.write_bit(true).unwrap(); // timing_info_present_flag
1003
1004        bits.write_u32::<BigEndian>(1).unwrap(); // num_units_in_display_tick
1005        bits.write_u32::<BigEndian>(1).unwrap(); // time_scale
1006        bits.write_bit(true).unwrap(); // num_ticks_per_picture
1007        bits.write_bits(0b01, 1).unwrap(); // read_uvlc
1008
1009        bits.write_bit(true).unwrap(); // decoder_model_info_present_flag
1010        bits.write_bits(4, 5).unwrap(); // buffer_delay_length
1011        bits.write_u32::<BigEndian>(1).unwrap(); // num_units_in_decoding_tick
1012        bits.write_bits(4, 5).unwrap(); // buffer_removal_time_length
1013        bits.write_bits(4, 5).unwrap(); // frame_presentation_time_length
1014
1015        bits.write_bit(true).unwrap(); // initial_display_delay_present_flag
1016        bits.write_bits(0, 5).unwrap(); // operating_points_cnt_minus_1
1017
1018        bits.write_bits(0, 12).unwrap(); // idc
1019        bits.write_bits(1, 5).unwrap(); // seq_lvl_idx
1020        bits.write_bit(true).unwrap(); // seq_tier
1021
1022        bits.write_bits(0b1010, 5).unwrap(); // decoder_buffer_delay
1023        bits.write_bits(0b0101, 5).unwrap(); // encoder_buffer_delay
1024        bits.write_bit(false).unwrap(); // low_delay_mode_flag
1025
1026        bits.write_bit(true).unwrap(); // film_grain_params_present
1027        bits.write_bits(15, 4).unwrap(); // initial_display_delay_minus_1
1028
1029        bits.write_bits(15, 4).unwrap(); // operating_points_cnt_minus_1
1030        bits.write_bits(15, 4).unwrap(); // operating_points_cnt_minus_1
1031        bits.write_bits(1919, 16).unwrap(); // operating_points_cnt_minus_1
1032        bits.write_bits(1079, 16).unwrap(); // operating_points_cnt_minus_1
1033
1034        bits.write_bit(true).unwrap(); // frame_id_numbers_present_flag
1035        bits.write_bits(0b1101, 4).unwrap(); // delta_frame_id_length
1036        bits.write_bits(0b101, 3).unwrap(); // additional_frame_id_length
1037
1038        bits.write_bit(false).unwrap(); // use_128x128_superblock
1039        bits.write_bit(false).unwrap(); // enable_filter_intra
1040        bits.write_bit(false).unwrap(); // enable_intra_edge_filter
1041
1042        bits.write_bit(false).unwrap(); // enable_interintra_compound
1043        bits.write_bit(false).unwrap(); // enable_masked_compound
1044        bits.write_bit(false).unwrap(); // enable_warped_motion
1045        bits.write_bit(false).unwrap(); // enable_dual_filter
1046        bits.write_bit(true).unwrap(); // enable_order_hint
1047        bits.write_bit(false).unwrap(); // enable_jnt_comp
1048        bits.write_bit(false).unwrap(); // enable_ref_frame_mvs
1049
1050        bits.write_bit(false).unwrap();
1051        bits.write_bit(true).unwrap();
1052        bits.write_bit(false).unwrap();
1053        bits.write_bit(false).unwrap();
1054
1055        bits.write_bits(0b100, 3).unwrap();
1056
1057        bits.write_bit(false).unwrap(); // enable_superres
1058        bits.write_bit(false).unwrap(); // enable_cdef
1059        bits.write_bit(false).unwrap(); // enable_restoration
1060
1061        bits.write_bit(false).unwrap(); // high_bitdepth
1062        bits.write_bit(true).unwrap(); // mono_chrome
1063        bits.write_bit(false).unwrap(); // color_description_present_flag
1064        bits.write_bit(true).unwrap(); // color_range
1065        bits.write_bit(true).unwrap(); // separate_uv_delta_q
1066
1067        bits.write_bit(true).unwrap(); // film_grain_params_present
1068
1069        let obu_header = SequenceHeaderObu::parse(
1070            ObuHeader {
1071                obu_type: ObuType::SequenceHeader,
1072                size: None,
1073                extension_header: None,
1074            },
1075            &mut io::Cursor::new(bits.finish().unwrap()),
1076        )
1077        .unwrap();
1078
1079        insta::assert_debug_snapshot!(obu_header, @r"
1080        SequenceHeaderObu {
1081            header: ObuHeader {
1082                obu_type: SequenceHeader,
1083                size: None,
1084                extension_header: None,
1085            },
1086            seq_profile: 2,
1087            still_picture: false,
1088            reduced_still_picture_header: false,
1089            timing_info: Some(
1090                TimingInfo {
1091                    num_units_in_display_tick: 1,
1092                    time_scale: 1,
1093                    num_ticks_per_picture: Some(
1094                        1,
1095                    ),
1096                },
1097            ),
1098            decoder_model_info: Some(
1099                DecoderModelInfo {
1100                    buffer_delay_length: 5,
1101                    num_units_in_decoding_tick: 1,
1102                    buffer_removal_time_length: 5,
1103                    frame_presentation_time_length: 5,
1104                },
1105            ),
1106            operating_points: [
1107                OperatingPoint {
1108                    idc: 0,
1109                    seq_level_idx: 1,
1110                    seq_tier: false,
1111                    operating_parameters_info: Some(
1112                        OperatingParametersInfo {
1113                            decoder_buffer_delay: 10,
1114                            encoder_buffer_delay: 5,
1115                            low_delay_mode_flag: false,
1116                        },
1117                    ),
1118                    initial_display_delay: Some(
1119                        16,
1120                    ),
1121                },
1122            ],
1123            max_frame_width: 1920,
1124            max_frame_height: 1080,
1125            frame_ids: Some(
1126                FrameIds {
1127                    delta_frame_id_length: 15,
1128                    additional_frame_id_length: 6,
1129                },
1130            ),
1131            use_128x128_superblock: false,
1132            enable_filter_intra: false,
1133            enable_intra_edge_filter: false,
1134            enable_interintra_compound: false,
1135            enable_masked_compound: false,
1136            enable_warped_motion: false,
1137            enable_dual_filter: false,
1138            enable_order_hint: true,
1139            enable_jnt_comp: false,
1140            enable_ref_frame_mvs: false,
1141            seq_force_screen_content_tools: 1,
1142            seq_force_integer_mv: 0,
1143            order_hint_bits: 5,
1144            enable_superres: false,
1145            enable_cdef: false,
1146            enable_restoration: false,
1147            color_config: ColorConfig {
1148                bit_depth: 8,
1149                mono_chrome: true,
1150                num_planes: 1,
1151                color_primaries: 2,
1152                transfer_characteristics: 2,
1153                matrix_coefficients: 2,
1154                full_color_range: true,
1155                subsampling_x: true,
1156                subsampling_y: true,
1157                chroma_sample_position: 0,
1158                separate_uv_delta_q: false,
1159            },
1160            film_grain_params_present: true,
1161        }
1162        ");
1163    }
1164
1165    #[test]
1166    fn test_seq_obu_parse_initial_display_delay_is_none() {
1167        let mut bits = BitWriter::new(Vec::new());
1168
1169        bits.write_bits(0b010, 3).unwrap(); // seq_profile (2)
1170        bits.write_bit(false).unwrap(); // still_picture
1171        bits.write_bit(false).unwrap(); // reduced_still_picture_header
1172        bits.write_bit(true).unwrap(); // timing_info_present_flag
1173
1174        bits.write_u32::<BigEndian>(1).unwrap(); // num_units_in_display_tick
1175        bits.write_u32::<BigEndian>(1).unwrap(); // time_scale
1176        bits.write_bit(false).unwrap(); // num_ticks_per_picture
1177
1178        bits.write_bit(true).unwrap(); // decoder_model_info_present_flag
1179        bits.write_bits(4, 5).unwrap(); // buffer_delay_length
1180        bits.write_u32::<BigEndian>(1).unwrap(); // num_units_in_decoding_tick
1181        bits.write_bits(4, 5).unwrap(); // buffer_removal_time_length
1182        bits.write_bits(4, 5).unwrap(); // frame_presentation_time_length
1183
1184        bits.write_bit(true).unwrap(); // initial_display_delay_present_flag
1185        bits.write_bits(0, 5).unwrap(); // operating_points_cnt_minus_1
1186
1187        bits.write_bits(0, 12).unwrap(); // idc
1188        bits.write_bits(1, 5).unwrap(); // seq_lvl_idx
1189        bits.write_bit(true).unwrap(); // seq_tier
1190
1191        bits.write_bits(0b1010, 5).unwrap(); // decoder_buffer_delay
1192        bits.write_bits(0b0101, 5).unwrap(); // encoder_buffer_delay
1193        bits.write_bit(false).unwrap(); // low_delay_mode_flag
1194
1195        bits.write_bit(false).unwrap(); // initial_display_delay_present_for_this_op
1196
1197        bits.write_bits(11, 4).unwrap(); // frame_width_bits
1198        bits.write_bits(11, 4).unwrap(); // frame_height_bits
1199        bits.write_bits(1919, 12).unwrap(); // max_frame_width
1200        bits.write_bits(1079, 12).unwrap(); // max_frame_height
1201
1202        bits.write_bit(true).unwrap(); // frame_id_numbers_present_flag
1203        bits.write_bits(0b1101, 4).unwrap(); // delta_frame_id_length
1204        bits.write_bits(0b101, 3).unwrap(); // additional_frame_id_length
1205
1206        bits.write_bit(false).unwrap(); // use_128x128_superblock
1207        bits.write_bit(false).unwrap(); // enable_filter_intra
1208        bits.write_bit(false).unwrap(); // enable_intra_edge_filter
1209
1210        bits.write_bit(false).unwrap(); // enable_interintra_compound
1211        bits.write_bit(false).unwrap(); // enable_masked_compound
1212        bits.write_bit(false).unwrap(); // enable_warped_motion
1213        bits.write_bit(false).unwrap(); // enable_dual_filter
1214        bits.write_bit(true).unwrap(); // enable_order_hint
1215        bits.write_bit(false).unwrap(); // enable_jnt_comp
1216        bits.write_bit(false).unwrap(); // enable_ref_frame_mvs
1217
1218        bits.write_bit(false).unwrap();
1219        bits.write_bit(true).unwrap();
1220        bits.write_bit(false).unwrap();
1221        bits.write_bit(false).unwrap();
1222
1223        bits.write_bits(0b100, 3).unwrap();
1224
1225        bits.write_bit(false).unwrap(); // enable_superres
1226        bits.write_bit(false).unwrap(); // enable_cdef
1227        bits.write_bit(false).unwrap(); // enable_restoration
1228
1229        bits.write_bit(false).unwrap(); // high_bitdepth
1230        bits.write_bit(true).unwrap(); // mono_chrome
1231        bits.write_bit(false).unwrap(); // color_description_present_flag
1232        bits.write_bit(true).unwrap(); // color_range
1233        bits.write_bit(true).unwrap(); // separate_uv_delta_q
1234
1235        bits.write_bit(true).unwrap(); // film_grain_params_present
1236
1237        let obu_header = SequenceHeaderObu::parse(
1238            ObuHeader {
1239                obu_type: ObuType::SequenceHeader,
1240                size: None,
1241                extension_header: None,
1242            },
1243            &mut io::Cursor::new(bits.finish().unwrap()),
1244        )
1245        .unwrap();
1246
1247        insta::assert_debug_snapshot!(obu_header, @r"
1248        SequenceHeaderObu {
1249            header: ObuHeader {
1250                obu_type: SequenceHeader,
1251                size: None,
1252                extension_header: None,
1253            },
1254            seq_profile: 2,
1255            still_picture: false,
1256            reduced_still_picture_header: false,
1257            timing_info: Some(
1258                TimingInfo {
1259                    num_units_in_display_tick: 1,
1260                    time_scale: 1,
1261                    num_ticks_per_picture: None,
1262                },
1263            ),
1264            decoder_model_info: Some(
1265                DecoderModelInfo {
1266                    buffer_delay_length: 5,
1267                    num_units_in_decoding_tick: 1,
1268                    buffer_removal_time_length: 5,
1269                    frame_presentation_time_length: 5,
1270                },
1271            ),
1272            operating_points: [
1273                OperatingPoint {
1274                    idc: 0,
1275                    seq_level_idx: 1,
1276                    seq_tier: false,
1277                    operating_parameters_info: Some(
1278                        OperatingParametersInfo {
1279                            decoder_buffer_delay: 10,
1280                            encoder_buffer_delay: 5,
1281                            low_delay_mode_flag: false,
1282                        },
1283                    ),
1284                    initial_display_delay: None,
1285                },
1286            ],
1287            max_frame_width: 1920,
1288            max_frame_height: 1080,
1289            frame_ids: Some(
1290                FrameIds {
1291                    delta_frame_id_length: 15,
1292                    additional_frame_id_length: 6,
1293                },
1294            ),
1295            use_128x128_superblock: false,
1296            enable_filter_intra: false,
1297            enable_intra_edge_filter: false,
1298            enable_interintra_compound: false,
1299            enable_masked_compound: false,
1300            enable_warped_motion: false,
1301            enable_dual_filter: false,
1302            enable_order_hint: true,
1303            enable_jnt_comp: false,
1304            enable_ref_frame_mvs: false,
1305            seq_force_screen_content_tools: 1,
1306            seq_force_integer_mv: 0,
1307            order_hint_bits: 5,
1308            enable_superres: false,
1309            enable_cdef: false,
1310            enable_restoration: false,
1311            color_config: ColorConfig {
1312                bit_depth: 8,
1313                mono_chrome: true,
1314                num_planes: 1,
1315                color_primaries: 2,
1316                transfer_characteristics: 2,
1317                matrix_coefficients: 2,
1318                full_color_range: true,
1319                subsampling_x: true,
1320                subsampling_y: true,
1321                chroma_sample_position: 0,
1322                separate_uv_delta_q: false,
1323            },
1324            film_grain_params_present: true,
1325        }
1326        ");
1327    }
1328
1329    #[test]
1330    fn test_seq_obu_parse_enable_order_hint_is_false() {
1331        let mut bits = BitWriter::new(Vec::new());
1332
1333        bits.write_bits(0b010, 3).unwrap(); // seq_profile (2)
1334        bits.write_bit(false).unwrap(); // still_picture
1335        bits.write_bit(false).unwrap(); // reduced_still_picture_header
1336        bits.write_bit(true).unwrap(); // timing_info_present_flag
1337
1338        bits.write_u32::<BigEndian>(1).unwrap(); // num_units_in_display_tick
1339        bits.write_u32::<BigEndian>(1).unwrap(); // time_scale
1340        bits.write_bit(false).unwrap(); // num_ticks_per_picture
1341
1342        bits.write_bit(true).unwrap(); // decoder_model_info_present_flag
1343        bits.write_bits(4, 5).unwrap(); // buffer_delay_length
1344        bits.write_u32::<BigEndian>(1).unwrap(); // num_units_in_decoding_tick
1345        bits.write_bits(4, 5).unwrap(); // buffer_removal_time_length
1346        bits.write_bits(4, 5).unwrap(); // frame_presentation_time_length
1347
1348        bits.write_bit(true).unwrap(); // initial_display_delay_present_flag
1349        bits.write_bits(0, 5).unwrap(); // operating_points_cnt_minus_1
1350
1351        bits.write_bits(0, 12).unwrap(); // idc
1352        bits.write_bits(1, 5).unwrap(); // seq_lvl_idx
1353        bits.write_bit(true).unwrap(); // seq_tier
1354
1355        bits.write_bits(0b1010, 5).unwrap(); // decoder_buffer_delay
1356        bits.write_bits(0b0101, 5).unwrap(); // encoder_buffer_delay
1357        bits.write_bit(false).unwrap(); // low_delay_mode_flag
1358
1359        bits.write_bit(false).unwrap(); // initial_display_delay_present_for_this_op
1360
1361        bits.write_bits(11, 4).unwrap(); // frame_width_bits
1362        bits.write_bits(11, 4).unwrap(); // frame_height_bits
1363        bits.write_bits(1919, 12).unwrap(); // max_frame_width
1364        bits.write_bits(1079, 12).unwrap(); // max_frame_height
1365
1366        bits.write_bit(true).unwrap(); // frame_id_numbers_present_flag
1367        bits.write_bits(0b1101, 4).unwrap(); // delta_frame_id_length
1368        bits.write_bits(0b101, 3).unwrap(); // additional_frame_id_length
1369
1370        bits.write_bit(false).unwrap(); // use_128x128_superblock
1371        bits.write_bit(false).unwrap(); // enable_filter_intra
1372        bits.write_bit(false).unwrap(); // enable_intra_edge_filter
1373
1374        bits.write_bit(false).unwrap(); // enable_interintra_compound
1375        bits.write_bit(false).unwrap(); // enable_masked_compound
1376        bits.write_bit(false).unwrap(); // enable_warped_motion
1377        bits.write_bit(false).unwrap(); // enable_dual_filter
1378        bits.write_bit(false).unwrap(); // enable_order_hint
1379
1380        bits.write_bit(true).unwrap(); // seq_choose_screen_content_tools
1381        bits.write_bit(true).unwrap(); // sets seq_force_integer_mv to be 2
1382
1383        bits.write_bit(false).unwrap(); // enable_superres
1384        bits.write_bit(false).unwrap(); // enable_cdef
1385        bits.write_bit(false).unwrap(); // enable_restoration
1386
1387        bits.write_bit(false).unwrap(); // high_bitdepth
1388        bits.write_bit(true).unwrap(); // mono_chrome
1389        bits.write_bit(false).unwrap(); // color_description_present_flag
1390        bits.write_bit(true).unwrap(); // color_range
1391        bits.write_bit(true).unwrap(); // separate_uv_delta_q
1392
1393        bits.write_bit(true).unwrap(); // film_grain_params_present
1394
1395        let obu_header = SequenceHeaderObu::parse(
1396            ObuHeader {
1397                obu_type: ObuType::SequenceHeader,
1398                size: None,
1399                extension_header: None,
1400            },
1401            &mut io::Cursor::new(bits.finish().unwrap()),
1402        )
1403        .unwrap();
1404
1405        insta::assert_debug_snapshot!(obu_header, @r"
1406        SequenceHeaderObu {
1407            header: ObuHeader {
1408                obu_type: SequenceHeader,
1409                size: None,
1410                extension_header: None,
1411            },
1412            seq_profile: 2,
1413            still_picture: false,
1414            reduced_still_picture_header: false,
1415            timing_info: Some(
1416                TimingInfo {
1417                    num_units_in_display_tick: 1,
1418                    time_scale: 1,
1419                    num_ticks_per_picture: None,
1420                },
1421            ),
1422            decoder_model_info: Some(
1423                DecoderModelInfo {
1424                    buffer_delay_length: 5,
1425                    num_units_in_decoding_tick: 1,
1426                    buffer_removal_time_length: 5,
1427                    frame_presentation_time_length: 5,
1428                },
1429            ),
1430            operating_points: [
1431                OperatingPoint {
1432                    idc: 0,
1433                    seq_level_idx: 1,
1434                    seq_tier: false,
1435                    operating_parameters_info: Some(
1436                        OperatingParametersInfo {
1437                            decoder_buffer_delay: 10,
1438                            encoder_buffer_delay: 5,
1439                            low_delay_mode_flag: false,
1440                        },
1441                    ),
1442                    initial_display_delay: None,
1443                },
1444            ],
1445            max_frame_width: 1920,
1446            max_frame_height: 1080,
1447            frame_ids: Some(
1448                FrameIds {
1449                    delta_frame_id_length: 15,
1450                    additional_frame_id_length: 6,
1451                },
1452            ),
1453            use_128x128_superblock: false,
1454            enable_filter_intra: false,
1455            enable_intra_edge_filter: false,
1456            enable_interintra_compound: false,
1457            enable_masked_compound: false,
1458            enable_warped_motion: false,
1459            enable_dual_filter: false,
1460            enable_order_hint: false,
1461            enable_jnt_comp: false,
1462            enable_ref_frame_mvs: false,
1463            seq_force_screen_content_tools: 2,
1464            seq_force_integer_mv: 2,
1465            order_hint_bits: 0,
1466            enable_superres: false,
1467            enable_cdef: false,
1468            enable_restoration: false,
1469            color_config: ColorConfig {
1470                bit_depth: 8,
1471                mono_chrome: true,
1472                num_planes: 1,
1473                color_primaries: 2,
1474                transfer_characteristics: 2,
1475                matrix_coefficients: 2,
1476                full_color_range: true,
1477                subsampling_x: true,
1478                subsampling_y: true,
1479                chroma_sample_position: 0,
1480                separate_uv_delta_q: false,
1481            },
1482            film_grain_params_present: true,
1483        }
1484        ");
1485    }
1486
1487    #[test]
1488    fn test_seq_obu_parse_decoder_model_info_present_is_false() {
1489        let mut bits = BitWriter::new(Vec::new());
1490
1491        bits.write_bits(0b010, 3).unwrap(); // seq_profile (2)
1492        bits.write_bit(false).unwrap(); // still_picture
1493        bits.write_bit(false).unwrap(); // reduced_still_picture_header
1494        bits.write_bit(true).unwrap(); // timing_info_present_flag
1495
1496        bits.write_u32::<BigEndian>(1).unwrap(); // num_units_in_display_tick
1497        bits.write_u32::<BigEndian>(1).unwrap(); // time_scale
1498        bits.write_bit(false).unwrap(); // num_ticks_per_picture
1499
1500        bits.write_bit(false).unwrap(); // decoder_model_info_present_flag
1501
1502        bits.write_bit(true).unwrap(); // initial_display_delay_present_flag
1503        bits.write_bits(0, 5).unwrap(); // operating_points_cnt_minus_1
1504
1505        bits.write_bits(0, 12).unwrap(); // idc
1506        bits.write_bits(1, 5).unwrap(); // seq_lvl_idx
1507
1508        bits.write_bit(false).unwrap(); // initial_display_delay_present_for_this_op
1509
1510        bits.write_bits(11, 4).unwrap(); // frame_width_bits
1511        bits.write_bits(11, 4).unwrap(); // frame_height_bits
1512        bits.write_bits(1919, 12).unwrap(); // max_frame_width
1513        bits.write_bits(1079, 12).unwrap(); // max_frame_height
1514
1515        bits.write_bit(true).unwrap(); // frame_id_numbers_present_flag
1516        bits.write_bits(0b1101, 4).unwrap(); // delta_frame_id_length
1517        bits.write_bits(0b101, 3).unwrap(); // additional_frame_id_length
1518
1519        bits.write_bit(false).unwrap(); // use_128x128_superblock
1520        bits.write_bit(false).unwrap(); // enable_filter_intra
1521        bits.write_bit(false).unwrap(); // enable_intra_edge_filter
1522
1523        bits.write_bit(false).unwrap(); // enable_interintra_compound
1524        bits.write_bit(false).unwrap(); // enable_masked_compound
1525        bits.write_bit(false).unwrap(); // enable_warped_motion
1526        bits.write_bit(false).unwrap(); // enable_dual_filter
1527        bits.write_bit(false).unwrap(); // enable_order_hint
1528
1529        bits.write_bit(true).unwrap(); // seq_choose_screen_content_tools
1530        bits.write_bit(true).unwrap(); // sets seq_force_integer_mv to be 2
1531
1532        bits.write_bit(false).unwrap(); // enable_superres
1533        bits.write_bit(false).unwrap(); // enable_cdef
1534        bits.write_bit(false).unwrap(); // enable_restoration
1535
1536        bits.write_bit(false).unwrap(); // high_bitdepth
1537        bits.write_bit(true).unwrap(); // mono_chrome
1538        bits.write_bit(false).unwrap(); // color_description_present_flag
1539        bits.write_bit(true).unwrap(); // color_range
1540        bits.write_bit(true).unwrap(); // separate_uv_delta_q
1541
1542        bits.write_bit(true).unwrap(); // film_grain_params_present
1543
1544        let obu_header = SequenceHeaderObu::parse(
1545            ObuHeader {
1546                obu_type: ObuType::SequenceHeader,
1547                size: None,
1548                extension_header: None,
1549            },
1550            &mut io::Cursor::new(bits.finish().unwrap()),
1551        )
1552        .unwrap();
1553
1554        insta::assert_debug_snapshot!(obu_header, @r"
1555        SequenceHeaderObu {
1556            header: ObuHeader {
1557                obu_type: SequenceHeader,
1558                size: None,
1559                extension_header: None,
1560            },
1561            seq_profile: 2,
1562            still_picture: false,
1563            reduced_still_picture_header: false,
1564            timing_info: Some(
1565                TimingInfo {
1566                    num_units_in_display_tick: 1,
1567                    time_scale: 1,
1568                    num_ticks_per_picture: None,
1569                },
1570            ),
1571            decoder_model_info: None,
1572            operating_points: [
1573                OperatingPoint {
1574                    idc: 0,
1575                    seq_level_idx: 1,
1576                    seq_tier: false,
1577                    operating_parameters_info: None,
1578                    initial_display_delay: None,
1579                },
1580            ],
1581            max_frame_width: 1920,
1582            max_frame_height: 1080,
1583            frame_ids: Some(
1584                FrameIds {
1585                    delta_frame_id_length: 15,
1586                    additional_frame_id_length: 6,
1587                },
1588            ),
1589            use_128x128_superblock: false,
1590            enable_filter_intra: false,
1591            enable_intra_edge_filter: false,
1592            enable_interintra_compound: false,
1593            enable_masked_compound: false,
1594            enable_warped_motion: false,
1595            enable_dual_filter: false,
1596            enable_order_hint: false,
1597            enable_jnt_comp: false,
1598            enable_ref_frame_mvs: false,
1599            seq_force_screen_content_tools: 2,
1600            seq_force_integer_mv: 2,
1601            order_hint_bits: 0,
1602            enable_superres: false,
1603            enable_cdef: false,
1604            enable_restoration: false,
1605            color_config: ColorConfig {
1606                bit_depth: 8,
1607                mono_chrome: true,
1608                num_planes: 1,
1609                color_primaries: 2,
1610                transfer_characteristics: 2,
1611                matrix_coefficients: 2,
1612                full_color_range: true,
1613                subsampling_x: true,
1614                subsampling_y: true,
1615                chroma_sample_position: 0,
1616                separate_uv_delta_q: false,
1617            },
1618            film_grain_params_present: true,
1619        }
1620        ");
1621    }
1622
1623    #[test]
1624    fn test_seq_obu_parse_color_range_and_subsampling() {
1625        let mut bits = BitWriter::new(Vec::new());
1626
1627        bits.write_bit(false).unwrap(); // color_range
1628        bits.write_bit(false).unwrap(); // subsampling_x
1629        bits.write_bit(false).unwrap(); // subsampling_y
1630
1631        let color_range_and_subsampling = ColorConfig::parse_color_range_and_subsampling(
1632            &mut BitReader::new(std::io::Cursor::new(Vec::new())),
1633            0,
1634            1,
1635            13,
1636            0,
1637            8,
1638        )
1639        .unwrap();
1640
1641        assert_eq!(
1642            color_range_and_subsampling,
1643            ColorRangeAndSubsampling {
1644                color_range: true,
1645                subsampling_x: false,
1646                subsampling_y: false,
1647            }
1648        );
1649
1650        let color_range_and_subsampling = ColorConfig::parse_color_range_and_subsampling(
1651            &mut BitReader::new(std::io::Cursor::new(&[0b10000000])),
1652            0,
1653            1,
1654            0,
1655            0,
1656            8,
1657        )
1658        .unwrap();
1659
1660        assert_eq!(
1661            color_range_and_subsampling,
1662            ColorRangeAndSubsampling {
1663                color_range: true,
1664                subsampling_x: true,
1665                subsampling_y: true,
1666            }
1667        );
1668
1669        let color_range_and_subsampling = ColorConfig::parse_color_range_and_subsampling(
1670            &mut BitReader::new(std::io::Cursor::new(&[0b10000000])),
1671            1,
1672            1,
1673            0,
1674            0,
1675            8,
1676        )
1677        .unwrap();
1678
1679        assert_eq!(
1680            color_range_and_subsampling,
1681            ColorRangeAndSubsampling {
1682                color_range: true,
1683                subsampling_x: false,
1684                subsampling_y: false,
1685            }
1686        );
1687
1688        let color_range_and_subsampling = ColorConfig::parse_color_range_and_subsampling(
1689            &mut BitReader::new(std::io::Cursor::new(&[0b11100000])),
1690            2,
1691            1,
1692            0,
1693            0,
1694            12,
1695        )
1696        .unwrap();
1697
1698        assert_eq!(
1699            color_range_and_subsampling,
1700            ColorRangeAndSubsampling {
1701                color_range: true,
1702                subsampling_x: true,
1703                subsampling_y: true,
1704            }
1705        );
1706
1707        let color_range_and_subsampling = ColorConfig::parse_color_range_and_subsampling(
1708            &mut BitReader::new(std::io::Cursor::new(&[0b11000000])),
1709            2,
1710            1,
1711            0,
1712            0,
1713            12,
1714        )
1715        .unwrap();
1716
1717        assert_eq!(
1718            color_range_and_subsampling,
1719            ColorRangeAndSubsampling {
1720                color_range: true,
1721                subsampling_x: true,
1722                subsampling_y: false,
1723            }
1724        );
1725
1726        let color_range_and_subsampling = ColorConfig::parse_color_range_and_subsampling(
1727            &mut BitReader::new(std::io::Cursor::new(&[0b10100000])),
1728            2,
1729            1,
1730            0,
1731            0,
1732            12,
1733        )
1734        .unwrap();
1735
1736        assert_eq!(
1737            color_range_and_subsampling,
1738            ColorRangeAndSubsampling {
1739                color_range: true,
1740                subsampling_x: false,
1741                subsampling_y: false,
1742            }
1743        );
1744
1745        let color_range_and_subsampling = ColorConfig::parse_color_range_and_subsampling(
1746            &mut BitReader::new(std::io::Cursor::new(&[0b11100000])),
1747            2,
1748            1,
1749            0,
1750            0,
1751            8,
1752        )
1753        .unwrap();
1754
1755        assert_eq!(
1756            color_range_and_subsampling,
1757            ColorRangeAndSubsampling {
1758                color_range: true,
1759                subsampling_x: true,
1760                subsampling_y: false,
1761            }
1762        );
1763    }
1764
1765    #[test]
1766    fn test_color_config_parse_bit_depth_12() {
1767        let mut bits = BitWriter::new(Vec::new());
1768
1769        bits.write_bits(0b010, 3).unwrap(); // seq_profile (2)
1770        bits.write_bit(true).unwrap(); // still_picture
1771        bits.write_bit(true).unwrap(); // reduced_still_picture_header
1772        bits.write_bits(11, 5).unwrap(); // seq_lvl_idx
1773
1774        bits.write_bits(15, 4).unwrap();
1775        bits.write_bits(15, 4).unwrap();
1776        bits.write_bits(1919, 16).unwrap();
1777        bits.write_bits(1079, 16).unwrap();
1778
1779        bits.write_bit(false).unwrap(); // use_128x128_superblock
1780        bits.write_bit(false).unwrap(); // enable_filter_intra
1781        bits.write_bit(false).unwrap(); // enable_intra_edge_filter
1782        bits.write_bit(false).unwrap(); // enable_superres
1783        bits.write_bit(false).unwrap(); // enable_cdef
1784        bits.write_bit(false).unwrap(); // enable_restoration
1785
1786        bits.write_bit(true).unwrap(); // high_bitdepth
1787        bits.write_bit(true).unwrap(); // sets bitdepth to 12 instead of 10
1788        bits.write_bit(true).unwrap(); // mono_chrome
1789        bits.write_bit(false).unwrap(); // color_description_present_flag
1790        bits.write_bit(true).unwrap(); // color_range
1791        bits.write_bit(true).unwrap(); // separate_uv_delta_q
1792
1793        bits.write_bit(true).unwrap(); // film_grain_params_present
1794
1795        let obu_header = SequenceHeaderObu::parse(
1796            ObuHeader {
1797                obu_type: ObuType::SequenceHeader,
1798                size: None,
1799                extension_header: None,
1800            },
1801            &mut io::Cursor::new(bits.finish().unwrap()),
1802        )
1803        .unwrap();
1804
1805        insta::assert_debug_snapshot!(obu_header, @r"
1806        SequenceHeaderObu {
1807            header: ObuHeader {
1808                obu_type: SequenceHeader,
1809                size: None,
1810                extension_header: None,
1811            },
1812            seq_profile: 2,
1813            still_picture: true,
1814            reduced_still_picture_header: true,
1815            timing_info: None,
1816            decoder_model_info: None,
1817            operating_points: [
1818                OperatingPoint {
1819                    idc: 0,
1820                    seq_level_idx: 11,
1821                    seq_tier: false,
1822                    operating_parameters_info: None,
1823                    initial_display_delay: None,
1824                },
1825            ],
1826            max_frame_width: 1920,
1827            max_frame_height: 1080,
1828            frame_ids: None,
1829            use_128x128_superblock: false,
1830            enable_filter_intra: false,
1831            enable_intra_edge_filter: false,
1832            enable_interintra_compound: false,
1833            enable_masked_compound: false,
1834            enable_warped_motion: false,
1835            enable_dual_filter: false,
1836            enable_order_hint: false,
1837            enable_jnt_comp: false,
1838            enable_ref_frame_mvs: false,
1839            seq_force_screen_content_tools: 2,
1840            seq_force_integer_mv: 2,
1841            order_hint_bits: 0,
1842            enable_superres: false,
1843            enable_cdef: false,
1844            enable_restoration: false,
1845            color_config: ColorConfig {
1846                bit_depth: 12,
1847                mono_chrome: true,
1848                num_planes: 1,
1849                color_primaries: 2,
1850                transfer_characteristics: 2,
1851                matrix_coefficients: 2,
1852                full_color_range: true,
1853                subsampling_x: true,
1854                subsampling_y: true,
1855                chroma_sample_position: 0,
1856                separate_uv_delta_q: false,
1857            },
1858            film_grain_params_present: true,
1859        }
1860        ");
1861    }
1862
1863    #[test]
1864    fn test_color_config_parse_bit_depth_10() {
1865        let mut bits = BitWriter::new(Vec::new());
1866
1867        bits.write_bits(0b010, 3).unwrap(); // seq_profile (2)
1868        bits.write_bit(true).unwrap(); // still_picture
1869        bits.write_bit(true).unwrap(); // reduced_still_picture_header
1870        bits.write_bits(11, 5).unwrap(); // seq_lvl_idx
1871
1872        bits.write_bits(15, 4).unwrap();
1873        bits.write_bits(15, 4).unwrap();
1874        bits.write_bits(1919, 16).unwrap();
1875        bits.write_bits(1079, 16).unwrap();
1876
1877        bits.write_bit(false).unwrap(); // use_128x128_superblock
1878        bits.write_bit(false).unwrap(); // enable_filter_intra
1879        bits.write_bit(false).unwrap(); // enable_intra_edge_filter
1880        bits.write_bit(false).unwrap(); // enable_superres
1881        bits.write_bit(false).unwrap(); // enable_cdef
1882        bits.write_bit(false).unwrap(); // enable_restoration
1883
1884        bits.write_bit(true).unwrap(); // high_bitdepth
1885        bits.write_bit(false).unwrap(); // sets bitdepth to 10 instead of 12
1886        bits.write_bit(true).unwrap(); // mono_chrome
1887        bits.write_bit(false).unwrap(); // color_description_present_flag
1888        bits.write_bit(true).unwrap(); // color_range
1889        bits.write_bit(true).unwrap(); // separate_uv_delta_q
1890
1891        bits.write_bit(true).unwrap(); // film_grain_params_present
1892
1893        let obu_header = SequenceHeaderObu::parse(
1894            ObuHeader {
1895                obu_type: ObuType::SequenceHeader,
1896                size: None,
1897                extension_header: None,
1898            },
1899            &mut io::Cursor::new(bits.finish().unwrap()),
1900        )
1901        .unwrap();
1902
1903        insta::assert_debug_snapshot!(obu_header, @r"
1904        SequenceHeaderObu {
1905            header: ObuHeader {
1906                obu_type: SequenceHeader,
1907                size: None,
1908                extension_header: None,
1909            },
1910            seq_profile: 2,
1911            still_picture: true,
1912            reduced_still_picture_header: true,
1913            timing_info: None,
1914            decoder_model_info: None,
1915            operating_points: [
1916                OperatingPoint {
1917                    idc: 0,
1918                    seq_level_idx: 11,
1919                    seq_tier: false,
1920                    operating_parameters_info: None,
1921                    initial_display_delay: None,
1922                },
1923            ],
1924            max_frame_width: 1920,
1925            max_frame_height: 1080,
1926            frame_ids: None,
1927            use_128x128_superblock: false,
1928            enable_filter_intra: false,
1929            enable_intra_edge_filter: false,
1930            enable_interintra_compound: false,
1931            enable_masked_compound: false,
1932            enable_warped_motion: false,
1933            enable_dual_filter: false,
1934            enable_order_hint: false,
1935            enable_jnt_comp: false,
1936            enable_ref_frame_mvs: false,
1937            seq_force_screen_content_tools: 2,
1938            seq_force_integer_mv: 2,
1939            order_hint_bits: 0,
1940            enable_superres: false,
1941            enable_cdef: false,
1942            enable_restoration: false,
1943            color_config: ColorConfig {
1944                bit_depth: 10,
1945                mono_chrome: true,
1946                num_planes: 1,
1947                color_primaries: 2,
1948                transfer_characteristics: 2,
1949                matrix_coefficients: 2,
1950                full_color_range: true,
1951                subsampling_x: true,
1952                subsampling_y: true,
1953                chroma_sample_position: 0,
1954                separate_uv_delta_q: false,
1955            },
1956            film_grain_params_present: true,
1957        }
1958        ");
1959    }
1960
1961    #[test]
1962    fn test_color_config_parse_csp_unknown() {
1963        let mut bits = BitWriter::new(Vec::new());
1964
1965        bits.write_bits(0b001, 3).unwrap(); // seq_profile (1)
1966        bits.write_bit(true).unwrap(); // still_picture
1967        bits.write_bit(true).unwrap(); // reduced_still_picture_header
1968        bits.write_bits(11, 5).unwrap(); // seq_lvl_idx
1969
1970        bits.write_bits(15, 4).unwrap();
1971        bits.write_bits(15, 4).unwrap();
1972        bits.write_bits(1919, 16).unwrap();
1973        bits.write_bits(1079, 16).unwrap();
1974
1975        bits.write_bit(false).unwrap(); // use_128x128_superblock
1976        bits.write_bit(false).unwrap(); // enable_filter_intra
1977        bits.write_bit(false).unwrap(); // enable_intra_edge_filter
1978        bits.write_bit(false).unwrap(); // enable_superres
1979        bits.write_bit(false).unwrap(); // enable_cdef
1980        bits.write_bit(false).unwrap(); // enable_restoration
1981
1982        bits.write_bit(false).unwrap(); // high_bitdepth
1983        bits.write_bit(false).unwrap(); // mono_chrome
1984        bits.write_bit(false).unwrap(); // color_description_present_flag
1985        bits.write_bit(true).unwrap(); // separate_uv_delta_q
1986
1987        bits.write_bit(true).unwrap(); // film_grain_params_present
1988
1989        let obu_header = SequenceHeaderObu::parse(
1990            ObuHeader {
1991                obu_type: ObuType::SequenceHeader,
1992                size: None,
1993                extension_header: None,
1994            },
1995            &mut io::Cursor::new(bits.finish().unwrap()),
1996        )
1997        .unwrap();
1998
1999        insta::assert_debug_snapshot!(obu_header, @r"
2000        SequenceHeaderObu {
2001            header: ObuHeader {
2002                obu_type: SequenceHeader,
2003                size: None,
2004                extension_header: None,
2005            },
2006            seq_profile: 1,
2007            still_picture: true,
2008            reduced_still_picture_header: true,
2009            timing_info: None,
2010            decoder_model_info: None,
2011            operating_points: [
2012                OperatingPoint {
2013                    idc: 0,
2014                    seq_level_idx: 11,
2015                    seq_tier: false,
2016                    operating_parameters_info: None,
2017                    initial_display_delay: None,
2018                },
2019            ],
2020            max_frame_width: 1920,
2021            max_frame_height: 1080,
2022            frame_ids: None,
2023            use_128x128_superblock: false,
2024            enable_filter_intra: false,
2025            enable_intra_edge_filter: false,
2026            enable_interintra_compound: false,
2027            enable_masked_compound: false,
2028            enable_warped_motion: false,
2029            enable_dual_filter: false,
2030            enable_order_hint: false,
2031            enable_jnt_comp: false,
2032            enable_ref_frame_mvs: false,
2033            seq_force_screen_content_tools: 2,
2034            seq_force_integer_mv: 2,
2035            order_hint_bits: 0,
2036            enable_superres: false,
2037            enable_cdef: false,
2038            enable_restoration: false,
2039            color_config: ColorConfig {
2040                bit_depth: 8,
2041                mono_chrome: false,
2042                num_planes: 3,
2043                color_primaries: 2,
2044                transfer_characteristics: 2,
2045                matrix_coefficients: 2,
2046                full_color_range: false,
2047                subsampling_x: false,
2048                subsampling_y: false,
2049                chroma_sample_position: 0,
2050                separate_uv_delta_q: true,
2051            },
2052            film_grain_params_present: true,
2053        }
2054        ");
2055    }
2056}