cros_codecs/codec/av1/
synthesizer.rs

1// Copyright 2024 The ChromiumOS Authors
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use std::io::Write;
6use std::num::TryFromIntError;
7
8use thiserror::Error;
9
10use crate::codec::av1::helpers::clip3;
11use crate::codec::av1::parser::BitDepth;
12use crate::codec::av1::parser::ChromaSamplePosition;
13use crate::codec::av1::parser::ColorPrimaries;
14use crate::codec::av1::parser::FrameHeaderObu;
15use crate::codec::av1::parser::FrameRestorationType;
16use crate::codec::av1::parser::FrameType;
17use crate::codec::av1::parser::InterpolationFilter;
18use crate::codec::av1::parser::MatrixCoefficients;
19use crate::codec::av1::parser::ObuHeader;
20use crate::codec::av1::parser::ObuType;
21use crate::codec::av1::parser::Profile;
22use crate::codec::av1::parser::ReferenceFrameType;
23use crate::codec::av1::parser::SequenceHeaderObu;
24use crate::codec::av1::parser::TemporalDelimiterObu;
25use crate::codec::av1::parser::TransferCharacteristics;
26use crate::codec::av1::parser::TxMode;
27use crate::codec::av1::parser::WarpModelType;
28use crate::codec::av1::parser::FEATURE_BITS;
29use crate::codec::av1::parser::FEATURE_MAX;
30use crate::codec::av1::parser::FEATURE_SIGNED;
31use crate::codec::av1::parser::MAX_NUM_OPERATING_POINTS;
32use crate::codec::av1::parser::MAX_NUM_PLANES;
33use crate::codec::av1::parser::MAX_SEGMENTS;
34use crate::codec::av1::parser::NUM_REF_FRAMES;
35use crate::codec::av1::parser::PRIMARY_REF_NONE;
36use crate::codec::av1::parser::REFS_PER_FRAME;
37use crate::codec::av1::parser::SEG_LVL_MAX;
38use crate::codec::av1::parser::SELECT_INTEGER_MV;
39use crate::codec::av1::parser::SELECT_SCREEN_CONTENT_TOOLS;
40use crate::codec::av1::parser::SUPERRES_DENOM_BITS;
41use crate::codec::av1::parser::SUPERRES_DENOM_MIN;
42use crate::codec::av1::parser::SUPERRES_NUM;
43use crate::codec::av1::parser::TOTAL_REFS_PER_FRAME;
44use crate::codec::av1::writer::ObuWriter;
45use crate::codec::av1::writer::ObuWriterError;
46
47mod private {
48    pub trait ObuStruct {}
49}
50
51impl private::ObuStruct for SequenceHeaderObu {}
52
53impl private::ObuStruct for TemporalDelimiterObu {}
54
55impl private::ObuStruct for FrameHeaderObu {}
56
57#[derive(Error, Debug)]
58pub enum SynthesizerError {
59    #[error("tried to synthesize unsupported settings")]
60    Unsupported,
61    #[error("invalid syntax element value {0}")]
62    InvalidSyntaxElementValue(&'static str),
63    #[error(transparent)]
64    ConversionError(#[from] TryFromIntError),
65    #[error(transparent)]
66    ObuWriter(#[from] ObuWriterError),
67    #[error(transparent)]
68    Io(#[from] std::io::Error),
69}
70
71pub type SynthesizerResult<T> = Result<T, SynthesizerError>;
72
73pub struct Synthesizer<'o, O: private::ObuStruct, W: Write> {
74    writer: ObuWriter<W>,
75    obu: &'o O,
76}
77
78impl<'o, O, W> Synthesizer<'o, O, W>
79where
80    O: private::ObuStruct,
81    W: Write,
82{
83    fn new(writer: W, obu: &'o O) -> Self {
84        Self {
85            writer: ObuWriter::new(writer),
86            obu,
87        }
88    }
89
90    fn f<T: Into<u32>>(&mut self, bits: usize, value: T) -> SynthesizerResult<()> {
91        let value: u32 = value.into();
92        self.writer.write_f(bits, value)?;
93        Ok(())
94    }
95
96    fn leb128<T: Into<u32>>(&mut self, value: T) -> SynthesizerResult<()> {
97        let value: u32 = value.into();
98        self.writer.write_leb128(value, 0)?;
99        Ok(())
100    }
101
102    fn uvlc<T: Into<u32>>(&mut self, value: T) -> SynthesizerResult<()> {
103        self.writer.write_uvlc(value)?;
104        Ok(())
105    }
106
107    fn su<T: Into<i32>>(&mut self, bits: usize, value: T) -> SynthesizerResult<()> {
108        self.writer.write_su(bits, value)?;
109        Ok(())
110    }
111
112    #[cfg(any(test, debug_assertions))]
113    fn invalid_element_value(&mut self, element: &'static str) -> SynthesizerResult<()> {
114        Err(SynthesizerError::InvalidSyntaxElementValue(element))
115    }
116
117    #[cfg(not(any(test, debug_assertions)))]
118    fn invalid_element_value(&mut self, element: &'static str) -> SynthesizerResult<()> {
119        log::error!("Invalid syntax element value: '{element}', expect corrupted bitstream");
120        Ok(())
121    }
122
123    /// Writes 5.3.2. OBU header syntax
124    fn obu_header(&mut self, obu: &ObuHeader) -> SynthesizerResult<()> {
125        self.f(1, /* obu_forbidden_bit */ 0u32)?;
126        self.f(4, obu.obu_type as u32)?;
127        self.f(1, obu.extension_flag)?;
128        self.f(1, obu.has_size_field)?;
129        self.f(1, /* obu_reserved_1bit */ 0u32)?;
130
131        if obu.extension_flag {
132            self.obu_extension_header(obu)?;
133        }
134
135        Ok(())
136    }
137
138    /// Writes AV1 5.3.3. OBU extension header syntax
139    fn obu_extension_header(&mut self, obu: &ObuHeader) -> SynthesizerResult<()> {
140        // AV1 5.3.3
141        self.f(3, obu.temporal_id)?;
142        self.f(2, obu.spatial_id)?;
143        self.f(3, /* extension_header_reserved_3bits */ 0u32)?;
144
145        Ok(())
146    }
147
148    fn obu_size(&mut self, size: u32) -> SynthesizerResult<()> {
149        self.leb128(size)
150    }
151
152    /// Writes AV1 5.3.4. Trailing bits syntax
153    fn trailing_bits(&mut self) -> SynthesizerResult<()> {
154        self.f(1, /* trailing_one_bit */ 1u32)?;
155        while !self.writer.aligned() {
156            self.f(1, /* trailing_zero_bit */ 0u32)?;
157        }
158
159        Ok(())
160    }
161}
162
163impl<'o, W> Synthesizer<'o, TemporalDelimiterObu, W>
164where
165    W: Write,
166{
167    pub fn synthesize(obu: &'o TemporalDelimiterObu, writer: W) -> SynthesizerResult<()> {
168        let mut s = Self::new(writer, obu);
169
170        if obu.obu_header.obu_type != ObuType::TemporalDelimiter {
171            s.invalid_element_value("obu_type")?;
172        }
173
174        s.obu_header(&obu.obu_header)?;
175
176        if obu.obu_header.has_size_field {
177            s.obu_size(0u32)?;
178        }
179
180        Ok(())
181    }
182}
183
184impl<'o, W> Synthesizer<'o, SequenceHeaderObu, W>
185where
186    W: Write,
187{
188    pub fn synthesize(obu: &'o SequenceHeaderObu, mut writer: W) -> SynthesizerResult<()> {
189        let mut s = Synthesizer::new(&mut writer, obu);
190
191        if obu.obu_header.obu_type != ObuType::SequenceHeader {
192            s.invalid_element_value("obu_type")?;
193        }
194
195        s.obu_header(&obu.obu_header)?;
196
197        if !obu.obu_header.has_size_field {
198            s.sequence_header_obu()?;
199            s.trailing_bits()?;
200            return Ok(());
201        }
202
203        let mut buf = Vec::<u8>::new();
204        let mut buffered = Synthesizer::new(&mut buf, obu);
205        buffered.sequence_header_obu()?;
206        buffered.trailing_bits()?;
207        drop(buffered);
208
209        s.obu_size(buf.len() as u32)?;
210        drop(s);
211
212        writer.write_all(&buf)?;
213
214        Ok(())
215    }
216
217    /// Writes AV1 5.5.1. General sequence header OBU syntax
218    fn sequence_header_obu(&mut self) -> SynthesizerResult<()> {
219        self.f(3, self.obu.seq_profile as u32)?;
220        self.f(1, self.obu.still_picture)?;
221        self.f(1, self.obu.reduced_still_picture_header)?;
222
223        if self.obu.reduced_still_picture_header {
224            if self.obu.timing_info_present_flag {
225                self.invalid_element_value("reduced_still_picture_header")?
226            }
227            if self.obu.timing_info_present_flag {
228                self.invalid_element_value("timing_info_present_flag")?
229            }
230            if self.obu.initial_display_delay_present_flag {
231                self.invalid_element_value("initial_display_delay_present_flag")?
232            }
233            if self.obu.operating_points_cnt_minus_1 != 0 {
234                self.invalid_element_value("operating_points_cnt_minus_1")?
235            }
236            if self.obu.operating_points[0].idc != 0 {
237                self.invalid_element_value("operating_point_idc")?
238            }
239
240            self.f(5, self.obu.operating_points[0].seq_level_idx)?;
241
242            if self.obu.operating_points[0].decoder_model_present_for_this_op {
243                self.invalid_element_value("decoder_model_present_for_this_op")?
244            }
245            if self.obu.operating_points[0].initial_display_delay_present_for_this_op {
246                self.invalid_element_value("initial_display_delay_present_for_this_op")?
247            }
248        } else {
249            self.f(1, self.obu.timing_info_present_flag)?;
250            if self.obu.timing_info_present_flag {
251                self.timing_info()?;
252                self.f(1, self.obu.decoder_model_info_present_flag)?;
253                if self.obu.decoder_model_info_present_flag {
254                    self.decoder_model_info()?;
255                }
256            } else if self.obu.decoder_model_info_present_flag {
257                self.invalid_element_value("decoder_model_info_present_flag")?;
258            }
259
260            self.f(1, self.obu.initial_display_delay_present_flag)?;
261
262            if self.obu.operating_points_cnt_minus_1 > MAX_NUM_OPERATING_POINTS as u32 {
263                self.invalid_element_value("operating_points_cnt_minus_1")?;
264            }
265            self.f(5, self.obu.operating_points_cnt_minus_1)?;
266            for i in 0..=self.obu.operating_points_cnt_minus_1 {
267                let op = &self.obu.operating_points[i as usize];
268
269                self.f(12, op.idc)?;
270                self.f(5, op.seq_level_idx)?;
271                if op.seq_level_idx > 7 {
272                    self.f(1, op.seq_tier)?;
273                } else if op.seq_tier != 0 {
274                    self.invalid_element_value("seq_tier")?;
275                }
276
277                if self.obu.decoder_model_info_present_flag {
278                    self.f(1, op.decoder_model_present_for_this_op)?;
279                    if op.decoder_model_present_for_this_op {
280                        self.operating_parameters_info(i as usize)?;
281                    }
282                } else if op.decoder_model_present_for_this_op {
283                    self.invalid_element_value("decoder_model_present_for_this_op")?;
284                }
285
286                if self.obu.initial_display_delay_present_flag {
287                    self.f(1, op.initial_display_delay_present_for_this_op)?;
288                    if op.initial_display_delay_present_for_this_op {
289                        self.f(4, op.initial_display_delay_minus_1)?;
290                    }
291                }
292            }
293        }
294
295        let bits = u16::BITS - self.obu.max_frame_width_minus_1.leading_zeros();
296        if self.obu.frame_width_bits_minus_1 as u32 + 1 < bits {
297            self.invalid_element_value("frame_width_bits_minus_1")?;
298        }
299
300        let bits = u16::BITS - self.obu.max_frame_height_minus_1.leading_zeros();
301        if self.obu.frame_height_bits_minus_1 as u32 + 1 < bits {
302            self.invalid_element_value("frame_height_bits_minus_1")?;
303        }
304
305        self.f(4, self.obu.frame_width_bits_minus_1)?;
306        self.f(4, self.obu.frame_height_bits_minus_1)?;
307
308        let n = self.obu.frame_width_bits_minus_1 as usize + 1;
309        if (n as u32) < u16::BITS - self.obu.max_frame_width_minus_1.leading_zeros() {
310            self.invalid_element_value("max_frame_width_minus_1")?;
311        }
312        self.f(n, self.obu.max_frame_width_minus_1)?;
313
314        let n = self.obu.frame_height_bits_minus_1 as usize + 1;
315        if (n as u32) < u16::BITS - self.obu.max_frame_height_minus_1.leading_zeros() {
316            self.invalid_element_value("max_frame_height_minus_1")?;
317        }
318        self.f(n, self.obu.max_frame_height_minus_1)?;
319
320        if self.obu.reduced_still_picture_header {
321            if self.obu.frame_id_numbers_present_flag {
322                self.invalid_element_value("frame_id_numbers_present_flag")?;
323            }
324        } else {
325            self.f(1, self.obu.frame_id_numbers_present_flag)?;
326        }
327
328        if self.obu.frame_id_numbers_present_flag {
329            self.f(4, self.obu.delta_frame_id_length_minus_2)?;
330            self.f(3, self.obu.additional_frame_id_length_minus_1)?;
331        }
332
333        self.f(1, self.obu.use_128x128_superblock)?;
334        self.f(1, self.obu.enable_filter_intra)?;
335        self.f(1, self.obu.enable_intra_edge_filter)?;
336
337        if self.obu.reduced_still_picture_header {
338            if self.obu.enable_interintra_compound {
339                self.invalid_element_value("enable_interintra_compound")?;
340            }
341            if self.obu.enable_masked_compound {
342                self.invalid_element_value("enable_masked_compound")?;
343            }
344            if self.obu.enable_warped_motion {
345                self.invalid_element_value("enable_warped_motion")?;
346            }
347            if self.obu.enable_dual_filter {
348                self.invalid_element_value("enable_dual_filter")?;
349            }
350            if self.obu.enable_order_hint {
351                self.invalid_element_value("enable_order_hint")?;
352            }
353            if self.obu.enable_jnt_comp {
354                self.invalid_element_value("enable_jnt_comp")?;
355            }
356            if self.obu.enable_ref_frame_mvs {
357                self.invalid_element_value("enable_ref_frame_mvs")?;
358            }
359            if self.obu.seq_force_screen_content_tools != SELECT_SCREEN_CONTENT_TOOLS as u32 {
360                self.invalid_element_value("seq_force_screen_content_tools")?;
361            }
362            if self.obu.seq_force_integer_mv != SELECT_INTEGER_MV as u32 {
363                self.invalid_element_value("seq_force_integer_mv")?;
364            }
365            if self.obu.order_hint_bits != 0 {
366                self.invalid_element_value("OrderHintBits")?;
367            }
368        } else {
369            self.f(1, self.obu.enable_interintra_compound)?;
370            self.f(1, self.obu.enable_masked_compound)?;
371            self.f(1, self.obu.enable_warped_motion)?;
372            self.f(1, self.obu.enable_dual_filter)?;
373            self.f(1, self.obu.enable_order_hint)?;
374
375            if self.obu.enable_order_hint {
376                self.f(1, self.obu.enable_jnt_comp)?;
377                self.f(1, self.obu.enable_ref_frame_mvs)?;
378            } else {
379                if self.obu.enable_jnt_comp {
380                    self.invalid_element_value("enable_jnt_comp")?;
381                }
382                if self.obu.enable_ref_frame_mvs {
383                    self.invalid_element_value("enable_ref_frame_mvs")?;
384                }
385            }
386
387            self.f(1, self.obu.seq_choose_screen_content_tools)?;
388            if self.obu.seq_choose_screen_content_tools {
389                if self.obu.seq_force_screen_content_tools != SELECT_SCREEN_CONTENT_TOOLS as u32 {
390                    self.invalid_element_value("seq_force_screen_content_tools")?;
391                }
392            } else {
393                self.f(1, self.obu.seq_force_screen_content_tools)?;
394            }
395
396            if self.obu.seq_force_screen_content_tools > 0 {
397                self.f(1, self.obu.seq_choose_integer_mv)?;
398                if self.obu.seq_choose_integer_mv {
399                    if self.obu.seq_force_integer_mv != SELECT_INTEGER_MV as u32 {
400                        self.invalid_element_value("seq_force_integer_mv")?;
401                    }
402                } else {
403                    self.f(1, self.obu.seq_force_integer_mv)?;
404                }
405            } else if self.obu.seq_force_integer_mv != SELECT_INTEGER_MV as u32 {
406                self.invalid_element_value("seq_force_integer_mv")?;
407            }
408
409            if self.obu.enable_order_hint {
410                self.f(3, self.obu.order_hint_bits_minus_1 as u32)?;
411                if self.obu.order_hint_bits != self.obu.order_hint_bits_minus_1 + 1 {
412                    self.invalid_element_value("OrderHintBits")?;
413                }
414            } else if self.obu.order_hint_bits != 0 {
415                self.invalid_element_value("OrderHintBits")?;
416            }
417        }
418
419        self.f(1, self.obu.enable_superres)?;
420        self.f(1, self.obu.enable_cdef)?;
421        self.f(1, self.obu.enable_restoration)?;
422        self.color_config()?;
423        self.f(1, self.obu.film_grain_params_present)?;
424
425        Ok(())
426    }
427
428    /// Writes AV1 5.5.2. Color config syntax
429    fn color_config(&mut self) -> SynthesizerResult<()> {
430        let cc = &self.obu.color_config;
431
432        self.f(1, cc.high_bitdepth)?;
433        if matches!(self.obu.seq_profile, Profile::Profile2) && cc.high_bitdepth {
434            self.f(1, cc.twelve_bit)?;
435
436            if (cc.twelve_bit && self.obu.bit_depth != BitDepth::Depth12)
437                || (!cc.twelve_bit && self.obu.bit_depth != BitDepth::Depth10)
438            {
439                self.invalid_element_value("BitDepth")?;
440            }
441        } else if self.obu.seq_profile <= Profile::Profile2
442            && ((cc.high_bitdepth && self.obu.bit_depth != BitDepth::Depth10)
443                || (!cc.high_bitdepth && self.obu.bit_depth != BitDepth::Depth8))
444        {
445            self.invalid_element_value("BitDepth")?;
446        }
447
448        if matches!(self.obu.seq_profile, Profile::Profile1) {
449            if cc.mono_chrome {
450                self.invalid_element_value("mono_chrome")?;
451            }
452        } else {
453            self.f(1, cc.mono_chrome)?;
454        }
455
456        if (cc.mono_chrome && self.obu.num_planes != 1)
457            || (!cc.mono_chrome && self.obu.num_planes != 3)
458        {
459            self.invalid_element_value("NumPlanes")?;
460        }
461
462        self.f(1, cc.color_description_present_flag)?;
463        if cc.color_description_present_flag {
464            self.f(8, cc.color_primaries as u32)?;
465            self.f(8, cc.transfer_characteristics as u32)?;
466            self.f(8, cc.matrix_coefficients as u32)?;
467        } else {
468            if !matches!(cc.color_primaries, ColorPrimaries::Unspecified) {
469                self.invalid_element_value("color_primaries")?;
470            }
471            if !matches!(
472                cc.transfer_characteristics,
473                TransferCharacteristics::Unspecified
474            ) {
475                self.invalid_element_value("transfer_characteristics")?;
476            }
477            if !matches!(cc.matrix_coefficients, MatrixCoefficients::Unspecified) {
478                self.invalid_element_value("matrix_coefficients")?;
479            }
480        }
481
482        if cc.mono_chrome {
483            self.f(1, cc.color_range)?;
484
485            if !cc.subsampling_x {
486                self.invalid_element_value("subsampling_x")?;
487            }
488            if !cc.subsampling_y {
489                self.invalid_element_value("subsampling_y")?;
490            }
491            if !matches!(cc.chroma_sample_position, ChromaSamplePosition::Unknown) {
492                self.invalid_element_value("chroma_sample_position")?;
493            }
494            if !matches!(cc.chroma_sample_position, ChromaSamplePosition::Unknown) {
495                self.invalid_element_value("chroma_sample_position")?;
496            }
497            if cc.separate_uv_delta_q {
498                self.invalid_element_value("separate_uv_delta_q")?;
499            }
500
501            return Ok(());
502        } else if matches!(cc.color_primaries, ColorPrimaries::Bt709)
503            && matches!(cc.transfer_characteristics, TransferCharacteristics::Srgb)
504            && matches!(cc.matrix_coefficients, MatrixCoefficients::Identity)
505        {
506            if !cc.color_range {
507                self.invalid_element_value("color_range")?;
508            }
509            if cc.subsampling_x {
510                self.invalid_element_value("subsampling_x")?;
511            }
512            if cc.subsampling_y {
513                self.invalid_element_value("subsampling_y")?;
514            }
515        } else {
516            self.f(1, cc.color_range)?;
517
518            match self.obu.seq_profile {
519                Profile::Profile0 => {
520                    if !cc.subsampling_x {
521                        self.invalid_element_value("subsampling_x")?;
522                    }
523                    if !cc.subsampling_y {
524                        self.invalid_element_value("subsampling_y")?;
525                    }
526                }
527                Profile::Profile1 => {
528                    if cc.subsampling_x {
529                        self.invalid_element_value("subsampling_x")?;
530                    }
531                    if cc.subsampling_y {
532                        self.invalid_element_value("subsampling_y")?;
533                    }
534                }
535                _ => {
536                    if matches!(self.obu.bit_depth, BitDepth::Depth12) {
537                        self.f(1, cc.subsampling_x)?;
538                        if cc.subsampling_x {
539                            self.f(1, cc.subsampling_y)?;
540                        } else if cc.subsampling_y {
541                            self.invalid_element_value("subsampling_y")?;
542                        }
543                    } else {
544                        if !cc.subsampling_x {
545                            self.invalid_element_value("subsampling_x")?;
546                        }
547                        if cc.subsampling_y {
548                            self.invalid_element_value("subsampling_y")?;
549                        }
550                    }
551                }
552            }
553
554            if cc.subsampling_x && cc.subsampling_y {
555                self.f(2, cc.chroma_sample_position as u32)?;
556            }
557        }
558
559        self.f(1, cc.separate_uv_delta_q)?;
560
561        Ok(())
562    }
563
564    /// Writes AV1 5.5.3. Timing info syntax
565    fn timing_info(&mut self) -> SynthesizerResult<()> {
566        // AV1 5.5.3
567        let ti = &self.obu.timing_info;
568
569        self.f(32, ti.num_units_in_display_tick)?;
570        self.f(32, ti.time_scale)?;
571        self.f(1, ti.equal_picture_interval)?;
572        if ti.equal_picture_interval {
573            self.uvlc(ti.num_ticks_per_picture_minus_1)?;
574        }
575
576        Ok(())
577    }
578
579    /// Writes AV1 5.5.4. Decoder model info syntax
580    fn decoder_model_info(&mut self) -> SynthesizerResult<()> {
581        let dm = &self.obu.decoder_model_info;
582
583        self.f(5, dm.buffer_delay_length_minus_1)?;
584        self.f(32, dm.num_units_in_decoding_tick)?;
585        self.f(5, dm.buffer_removal_time_length_minus_1)?;
586        self.f(5, dm.frame_presentation_time_length_minus_1)?;
587
588        Ok(())
589    }
590
591    /// Writes AV1 5.5.5. Operating parameters info syntax
592    fn operating_parameters_info(&mut self, i: usize) -> SynthesizerResult<()> {
593        let op = &self.obu.operating_points[i];
594
595        let n = usize::from(self.obu.decoder_model_info.buffer_delay_length_minus_1) + 1;
596        self.f(n, op.decoder_buffer_delay)?;
597        self.f(n, op.encoder_buffer_delay)?;
598        self.f(1, op.low_delay_mode_flag)?;
599
600        Ok(())
601    }
602}
603
604impl<'o, W> Synthesizer<'o, FrameHeaderObu, W>
605where
606    W: Write,
607{
608    pub fn synthesize(
609        obu: &'o FrameHeaderObu,
610        sequence: &'o SequenceHeaderObu,
611        mut writer: W,
612    ) -> SynthesizerResult<()> {
613        let mut s = Synthesizer::new(&mut writer, obu);
614
615        if obu.obu_header.obu_type != ObuType::FrameHeader {
616            s.invalid_element_value("obu_type")?;
617        }
618
619        s.obu_header(&obu.obu_header)?;
620
621        if !obu.obu_header.has_size_field {
622            s.frame_header_obu(sequence)?;
623            s.trailing_bits()?;
624            return Ok(());
625        }
626
627        let mut buf = Vec::<u8>::new();
628        let mut buffered = Synthesizer::new(&mut buf, obu);
629        buffered.frame_header_obu(sequence)?;
630        buffered.trailing_bits()?;
631        drop(buffered);
632
633        s.obu_size(buf.len() as u32)?;
634        drop(s);
635
636        writer.write_all(&buf)?;
637
638        Ok(())
639    }
640
641    /// Writes AV1 5.9.1. General frame header OBU syntax
642    fn frame_header_obu(&mut self, sequence: &'o SequenceHeaderObu) -> SynthesizerResult<()> {
643        self.uncompressed_header(sequence)
644    }
645
646    /// Writes AV1 5.9.2. Uncompressed header syntax
647    fn uncompressed_header(&mut self, sequence: &'o SequenceHeaderObu) -> SynthesizerResult<()> {
648        const ALL_FRAMES: u32 = (1 << NUM_REF_FRAMES) - 1;
649
650        // idLen
651        let id_len = usize::try_from(
652            sequence.additional_frame_id_length_minus_1
653                + sequence.delta_frame_id_length_minus_2
654                + 3,
655        )?;
656
657        if sequence.reduced_still_picture_header {
658            if !self.obu.show_existing_frame {
659                self.invalid_element_value("show_existing_frame")?;
660            }
661            if !matches!(self.obu.frame_type, FrameType::KeyFrame) {
662                self.invalid_element_value("frame_type")?;
663            }
664            if !self.obu.show_frame {
665                self.invalid_element_value("show_frame")?;
666            }
667            if !self.obu.showable_frame {
668                self.invalid_element_value("showable_frame")?;
669            }
670            if !self.obu.frame_is_intra {
671                self.invalid_element_value("FrameIsIntra")?;
672            }
673        } else {
674            self.f(1, self.obu.show_existing_frame)?;
675            if self.obu.show_existing_frame {
676                self.f(3, self.obu.frame_to_show_map_idx)?;
677
678                if sequence.decoder_model_info_present_flag
679                    && !sequence.timing_info.equal_picture_interval
680                {
681                    self.temporal_point_info(sequence)?;
682                }
683
684                if sequence.frame_id_numbers_present_flag {
685                    self.f(id_len, self.obu.display_frame_id)?;
686                }
687                return Ok(());
688            }
689
690            self.f(2, self.obu.frame_type as u32)?;
691            if self.obu.frame_is_intra
692                ^ matches!(
693                    self.obu.frame_type,
694                    FrameType::IntraOnlyFrame | FrameType::KeyFrame
695                )
696            {
697                self.invalid_element_value("FrameIsIntra")?;
698            }
699
700            self.f(1, self.obu.show_frame)?;
701            if self.obu.show_frame
702                && sequence.decoder_model_info_present_flag
703                && !sequence.timing_info.equal_picture_interval
704            {
705                self.temporal_point_info(sequence)?;
706            }
707
708            if self.obu.show_frame {
709                if self.obu.showable_frame ^ !matches!(self.obu.frame_type, FrameType::KeyFrame) {
710                    self.invalid_element_value("showable_frame")?;
711                }
712            } else {
713                self.f(1, self.obu.showable_frame)?;
714            }
715
716            if matches!(self.obu.frame_type, FrameType::SwitchFrame)
717                || (matches!(self.obu.frame_type, FrameType::KeyFrame) && self.obu.show_frame)
718            {
719                if !self.obu.error_resilient_mode {
720                    self.invalid_element_value("error_resilient_mode")?;
721                }
722            } else {
723                self.f(1, self.obu.error_resilient_mode)?;
724            }
725        }
726
727        self.f(1, self.obu.disable_cdf_update)?;
728        if sequence.seq_force_screen_content_tools == SELECT_SCREEN_CONTENT_TOOLS as u32 {
729            self.f(1, self.obu.allow_screen_content_tools)?;
730        } else if self.obu.allow_screen_content_tools != sequence.seq_force_screen_content_tools {
731            self.invalid_element_value("allow_screen_content_tools")?;
732        }
733
734        if self.obu.allow_screen_content_tools != 0 {
735            if sequence.seq_force_integer_mv == SELECT_INTEGER_MV as u32 {
736                self.f(1, self.obu.force_integer_mv)?;
737            } else if self.obu.force_integer_mv != sequence.seq_force_integer_mv {
738                self.invalid_element_value("force_integer_mv")?;
739            }
740        } else if self.obu.force_integer_mv != 0
741            && !(self.obu.frame_is_intra && self.obu.force_integer_mv != 1)
742        {
743            self.invalid_element_value("force_integer_mv")?;
744        }
745
746        if sequence.frame_id_numbers_present_flag {
747            self.f(id_len, self.obu.current_frame_id)?;
748        } else if self.obu.current_frame_id != 0 {
749            self.invalid_element_value("current_frame_id")?;
750        }
751
752        if matches!(self.obu.frame_type, FrameType::SwitchFrame) {
753            if !self.obu.frame_size_override_flag {
754                self.invalid_element_value("frame_size_override_flag")?;
755            }
756        } else if sequence.reduced_still_picture_header {
757            if self.obu.frame_size_override_flag {
758                self.invalid_element_value("frame_size_override_flag")?;
759            }
760        } else {
761            self.f(1, self.obu.frame_size_override_flag)?;
762        }
763
764        if sequence.order_hint_bits != 0 {
765            if sequence.order_hint_bits != sequence.order_hint_bits_minus_1 + 1 {
766                self.invalid_element_value("order_hint_bits_minus_1")?;
767            }
768
769            self.f(sequence.order_hint_bits as usize, self.obu.order_hint)?;
770        }
771
772        if self.obu.frame_is_intra || self.obu.error_resilient_mode {
773            if self.obu.primary_ref_frame != PRIMARY_REF_NONE {
774                self.invalid_element_value("primary_ref_frame")?;
775            }
776        } else {
777            self.f(3, self.obu.primary_ref_frame)?;
778        }
779
780        if sequence.decoder_model_info_present_flag {
781            self.f(1, self.obu.buffer_removal_time_present_flag)?;
782
783            for op_num in 0..=sequence.operating_points_cnt_minus_1 {
784                let op = &sequence.operating_points[op_num as usize];
785                if op.decoder_model_present_for_this_op {
786                    let in_temporal_layer = (op.idc >> self.obu.obu_header.temporal_id) & 1 != 0;
787                    let in_spatial_layer =
788                        (op.idc >> (self.obu.obu_header.spatial_id + 8)) & 1 != 0;
789
790                    if op.idc == 0 || (in_temporal_layer && in_spatial_layer) {
791                        let n = usize::from(
792                            sequence
793                                .decoder_model_info
794                                .buffer_removal_time_length_minus_1
795                                + 1,
796                        );
797
798                        self.f(n, op.decoder_buffer_delay)?;
799                    }
800                }
801            }
802        }
803
804        if matches!(self.obu.frame_type, FrameType::SwitchFrame)
805            || (matches!(self.obu.frame_type, FrameType::KeyFrame) && self.obu.show_frame)
806        {
807            if self.obu.refresh_frame_flags != ALL_FRAMES {
808                self.invalid_element_value("refresh_frame_flags")?;
809            }
810        } else {
811            self.f(8, self.obu.refresh_frame_flags)?;
812        }
813
814        if (!self.obu.frame_is_intra || self.obu.refresh_frame_flags != ALL_FRAMES)
815            && self.obu.error_resilient_mode
816            && sequence.enable_order_hint
817        {
818            for i in 0..NUM_REF_FRAMES {
819                self.f(
820                    sequence.order_hint_bits as usize,
821                    self.obu.ref_order_hint[i],
822                )?;
823            }
824        }
825
826        if self.obu.frame_is_intra {
827            self.frame_size(sequence)?;
828            self.render_size()?;
829
830            if self.obu.allow_screen_content_tools != 0
831                && self.obu.upscaled_width == self.obu.frame_width
832            {
833                self.f(1, self.obu.allow_intrabc)?;
834            }
835        } else {
836            if !sequence.enable_order_hint {
837                if self.obu.frame_refs_short_signaling {
838                    self.invalid_element_value("frame_refs_short_signaling")?;
839                }
840            } else {
841                self.f(1, self.obu.frame_refs_short_signaling)?;
842                if self.obu.frame_refs_short_signaling {
843                    self.f(3, self.obu.last_frame_idx)?;
844                    self.f(3, self.obu.gold_frame_idx)?;
845                }
846            }
847
848            for i in 0..REFS_PER_FRAME {
849                let ref_frame_idx = self.obu.ref_frame_idx[i] as u32;
850                if !self.obu.frame_refs_short_signaling {
851                    self.f(3, ref_frame_idx)?;
852                }
853
854                if sequence.frame_id_numbers_present_flag {
855                    let n = usize::try_from(sequence.delta_frame_id_length_minus_2 + 2)?;
856
857                    let delta_frame_id_minus_1 = ((self.obu.current_frame_id - ref_frame_idx
858                        + (1 << id_len))
859                        % (1 << id_len))
860                        - 1;
861
862                    self.f(n, delta_frame_id_minus_1)?;
863                }
864            }
865
866            if self.obu.frame_size_override_flag && !self.obu.error_resilient_mode {
867                self.frame_size_with_refs()?;
868            } else {
869                self.frame_size(sequence)?;
870                self.render_size()?;
871            }
872
873            if self.obu.force_integer_mv != 0 {
874                if !self.obu.allow_high_precision_mv {
875                    self.invalid_element_value("allow_high_precision_mv")?;
876                }
877            } else {
878                self.f(1, self.obu.allow_high_precision_mv)?;
879            }
880
881            self.read_interpolation_filter()?;
882            self.f(1, self.obu.is_motion_mode_switchable)?;
883
884            if self.obu.error_resilient_mode || !sequence.enable_ref_frame_mvs {
885                if self.obu.use_ref_frame_mvs {
886                    self.invalid_element_value("use_ref_frame_mvs")?;
887                }
888            } else {
889                self.f(1, self.obu.use_ref_frame_mvs)?;
890            }
891        }
892
893        if sequence.reduced_still_picture_header || self.obu.disable_cdf_update {
894            if !self.obu.disable_frame_end_update_cdf {
895                self.invalid_element_value("disable_frame_end_update_cdf")?
896            }
897        } else {
898            self.f(1, self.obu.disable_frame_end_update_cdf)?;
899        }
900
901        self.tile_info()?;
902        self.quantization_params(sequence)?;
903        self.segmentation_params()?;
904
905        self.delta_q_params()?;
906        self.delta_lf_params()?;
907
908        if self.obu.coded_lossless && self.obu.lossless_array != [true; MAX_SEGMENTS] {
909            self.invalid_element_value("CodedLossless")?;
910        }
911
912        if self.obu.all_lossless
913            ^ (self.obu.coded_lossless && self.obu.frame_width == self.obu.upscaled_width)
914        {
915            self.invalid_element_value("AllLossless")?;
916        }
917
918        self.loop_filter_params(sequence)?;
919        self.cdef_params(sequence)?;
920        self.lr_params(sequence)?;
921        self.read_tx_mode()?;
922        self.frame_reference_mode()?;
923        self.skip_mode_params()?;
924
925        if self.obu.frame_is_intra
926            || self.obu.error_resilient_mode
927            || !sequence.enable_warped_motion
928        {
929            if self.obu.allow_warped_motion {
930                self.invalid_element_value("allow_warped_motion")?;
931            }
932        } else {
933            self.f(1, self.obu.allow_warped_motion)?;
934        }
935
936        self.f(1, self.obu.reduced_tx_set)?;
937
938        self.global_motion_params()?;
939        self.film_grain_params(sequence)?;
940
941        Ok(())
942    }
943
944    /// Writes AV1 5.9.31. Temporal point info syntax
945    fn temporal_point_info(&mut self, sequence: &'o SequenceHeaderObu) -> SynthesizerResult<()> {
946        let n = usize::try_from(
947            sequence
948                .decoder_model_info
949                .frame_presentation_time_length_minus_1
950                + 1,
951        )?;
952
953        self.f(n, self.obu.frame_presentation_time)?;
954
955        Ok(())
956    }
957
958    /// Writes AV1 5.9.5. Frame size syntax
959    fn frame_size(&mut self, sequence: &'o SequenceHeaderObu) -> SynthesizerResult<()> {
960        if self.obu.frame_size_override_flag {
961            let n = sequence.frame_width_bits_minus_1 as usize + 1;
962            self.f(n, self.obu.frame_width - 1)?;
963            let n = sequence.frame_height_bits_minus_1 as usize + 1;
964            self.f(n, self.obu.frame_height - 1)?;
965        } else {
966            if self.obu.frame_width != sequence.max_frame_width_minus_1 as u32 + 1 {
967                self.invalid_element_value("FrameWidth")?;
968            }
969            if self.obu.frame_height != sequence.max_frame_height_minus_1 as u32 + 1 {
970                self.invalid_element_value("FrameHeight")?;
971            }
972
973            self.superres_params(sequence)?;
974        }
975
976        Ok(())
977    }
978
979    /// Writes AV1 5.9.6. Render size syntax
980    fn render_size(&mut self) -> SynthesizerResult<()> {
981        self.f(1, self.obu.render_and_frame_size_different)?;
982
983        if self.obu.render_and_frame_size_different {
984            self.f(16, self.obu.render_width - 1)?;
985            self.f(16, self.obu.render_height - 1)?;
986        } else {
987            if self.obu.render_width != self.obu.upscaled_width {
988                self.invalid_element_value("RenderWidth")?;
989            }
990            if self.obu.render_height != self.obu.frame_height {
991                self.invalid_element_value("RenderHeight")?;
992            }
993        }
994
995        Ok(())
996    }
997
998    /// Writes AV1 5.9.7. Frame size with refs syntax
999    fn frame_size_with_refs(&mut self) -> SynthesizerResult<()> {
1000        log::error!("Syntax element frame_size_with_refs is unsupported");
1001        Err(SynthesizerError::Unsupported)
1002    }
1003
1004    /// Writes AV1 5.9.8. Superres params syntax
1005    fn superres_params(&mut self, sequence: &'o SequenceHeaderObu) -> SynthesizerResult<()> {
1006        if sequence.enable_superres {
1007            self.f(1, self.obu.use_superres)?;
1008        } else if self.obu.use_superres {
1009            self.invalid_element_value("use_superres")?;
1010        }
1011
1012        if self.obu.use_superres {
1013            let coded_denom = self.obu.superres_denom - SUPERRES_DENOM_MIN as u32;
1014
1015            self.f(SUPERRES_DENOM_BITS, coded_denom)?;
1016        } else if self.obu.superres_denom != SUPERRES_NUM as u32 {
1017            self.invalid_element_value("superres_denom")?;
1018        }
1019
1020        Ok(())
1021    }
1022
1023    /// Writes AV1 5.9.10. Interpolation filter syntax
1024    fn read_interpolation_filter(&mut self) -> SynthesizerResult<()> {
1025        self.f(1, self.obu.is_filter_switchable)?;
1026        if self.obu.is_filter_switchable {
1027            if !matches!(
1028                self.obu.interpolation_filter,
1029                InterpolationFilter::Switchable
1030            ) {
1031                self.invalid_element_value("interpolation_filter")?;
1032            }
1033        } else {
1034            self.f(2, self.obu.interpolation_filter as u32)?;
1035        }
1036
1037        Ok(())
1038    }
1039
1040    /// Writes AV1 5.9.11. Loop filter params syntax
1041    fn loop_filter_params(&mut self, sequence: &'o SequenceHeaderObu) -> SynthesizerResult<()> {
1042        if self.obu.coded_lossless || self.obu.allow_intrabc {
1043            if !matches!(self.obu.loop_filter_params.loop_filter_level, [0, 0, _, _]) {
1044                self.invalid_element_value("loop_filter_level")?;
1045            }
1046            if self.obu.loop_filter_params.loop_filter_ref_deltas != [1, 0, 0, 0, 0, -1, -1, -1] {
1047                self.invalid_element_value("loop_filter_ref_deltas")?;
1048            }
1049            if self.obu.loop_filter_params.loop_filter_mode_deltas != [0, 0] {
1050                self.invalid_element_value("loop_filter_mode_deltas")?;
1051            }
1052            return Ok(());
1053        }
1054
1055        self.f(6, self.obu.loop_filter_params.loop_filter_level[0])?;
1056        self.f(6, self.obu.loop_filter_params.loop_filter_level[1])?;
1057        if sequence.num_planes > 1
1058            && self.obu.loop_filter_params.loop_filter_level[0] != 0
1059            && self.obu.loop_filter_params.loop_filter_level[1] != 0
1060        {
1061            self.f(6, self.obu.loop_filter_params.loop_filter_level[2])?;
1062            self.f(6, self.obu.loop_filter_params.loop_filter_level[3])?;
1063        }
1064
1065        self.f(3, self.obu.loop_filter_params.loop_filter_sharpness)?;
1066        self.f(1, self.obu.loop_filter_params.loop_filter_delta_enabled)?;
1067        if self.obu.loop_filter_params.loop_filter_delta_enabled {
1068            self.f(1, self.obu.loop_filter_params.loop_filter_delta_update)?;
1069            if self.obu.loop_filter_params.loop_filter_delta_update {
1070                for i in 0..TOTAL_REFS_PER_FRAME {
1071                    // NOTE: Currently we have no way of checking if the value changed between
1072                    // frames, always update the value to make sure the decoder will recreate
1073                    // the same state.
1074                    const UPDATE_REF_DELTA: bool = true;
1075                    if UPDATE_REF_DELTA {
1076                        self.su(1 + 6, self.obu.loop_filter_params.loop_filter_ref_deltas[i])?;
1077                    }
1078                }
1079
1080                for i in 0..2 {
1081                    // NOTE: Same as above
1082                    const UPDATE_MODE_DELTA: bool = true;
1083                    if UPDATE_MODE_DELTA {
1084                        self.su(
1085                            1 + 6,
1086                            self.obu.loop_filter_params.loop_filter_mode_deltas[i],
1087                        )?;
1088                    }
1089                }
1090            }
1091        }
1092
1093        Ok(())
1094    }
1095
1096    /// Writes AV1 5.9.12. Quantization params syntax
1097    fn quantization_params(&mut self, sequence: &'o SequenceHeaderObu) -> SynthesizerResult<()> {
1098        self.f(8, self.obu.quantization_params.base_q_idx)?;
1099        self.read_delta_q(self.obu.quantization_params.delta_q_y_dc)?;
1100        if sequence.num_planes > 1 {
1101            if sequence.color_config.separate_uv_delta_q {
1102                self.f(1, self.obu.quantization_params.diff_uv_delta)?;
1103            } else if self.obu.quantization_params.diff_uv_delta {
1104                self.invalid_element_value("diff_uv_delta")?;
1105            };
1106
1107            self.read_delta_q(self.obu.quantization_params.delta_q_u_dc)?;
1108            self.read_delta_q(self.obu.quantization_params.delta_q_u_ac)?;
1109
1110            if self.obu.quantization_params.diff_uv_delta {
1111                self.read_delta_q(self.obu.quantization_params.delta_q_v_dc)?;
1112                self.read_delta_q(self.obu.quantization_params.delta_q_v_ac)?;
1113            } else {
1114                if self.obu.quantization_params.delta_q_v_dc != 0 {
1115                    self.invalid_element_value("delta_q_v_dc")?;
1116                }
1117                if self.obu.quantization_params.delta_q_v_ac != 0 {
1118                    self.invalid_element_value("delta_q_v_ac")?;
1119                }
1120            }
1121        } else {
1122            if self.obu.quantization_params.delta_q_u_dc != 0 {
1123                self.invalid_element_value("delta_q_u_dc")?;
1124            }
1125            if self.obu.quantization_params.delta_q_u_ac != 0 {
1126                self.invalid_element_value("delta_q_u_ac")?;
1127            }
1128            if self.obu.quantization_params.delta_q_v_dc != 0 {
1129                self.invalid_element_value("delta_q_v_dc")?;
1130            }
1131            if self.obu.quantization_params.delta_q_v_ac != 0 {
1132                self.invalid_element_value("delta_q_v_ac")?;
1133            }
1134        }
1135
1136        self.f(1, self.obu.quantization_params.using_qmatrix)?;
1137        if self.obu.quantization_params.using_qmatrix {
1138            self.f(4, self.obu.quantization_params.qm_y)?;
1139            self.f(4, self.obu.quantization_params.qm_u)?;
1140
1141            if !sequence.color_config.separate_uv_delta_q {
1142                if self.obu.quantization_params.qm_v != self.obu.quantization_params.qm_u {
1143                    self.invalid_element_value("qm_v")?;
1144                }
1145            } else {
1146                self.f(4, self.obu.quantization_params.qm_v)?;
1147            }
1148        }
1149
1150        Ok(())
1151    }
1152
1153    /// Writes AV1 5.9.13. Delta quantizer syntax
1154    fn read_delta_q(&mut self, delta_q: i32) -> SynthesizerResult<()> {
1155        self.f(1, delta_q != 0)?;
1156        if delta_q != 0 {
1157            self.su(1 + 6, delta_q)?;
1158        }
1159        Ok(())
1160    }
1161
1162    /// Writes AV1 5.9.14. Segmentation params syntax
1163    fn segmentation_params(&mut self) -> SynthesizerResult<()> {
1164        self.f(1, self.obu.segmentation_params.segmentation_enabled)?;
1165        if self.obu.segmentation_params.segmentation_enabled {
1166            if self.obu.primary_ref_frame == PRIMARY_REF_NONE {
1167                if !self.obu.segmentation_params.segmentation_update_map {
1168                    self.invalid_element_value("segmentation_update_map")?;
1169                }
1170
1171                if self.obu.segmentation_params.segmentation_temporal_update {
1172                    self.invalid_element_value("segmentation_temporal_update")?;
1173                }
1174
1175                if !self.obu.segmentation_params.segmentation_update_data {
1176                    self.invalid_element_value("segmentation_update_data")?;
1177                }
1178            } else {
1179                self.f(1, self.obu.segmentation_params.segmentation_update_map)?;
1180                if self.obu.segmentation_params.segmentation_update_map {
1181                    self.f(1, self.obu.segmentation_params.segmentation_temporal_update)?;
1182                }
1183                self.f(1, self.obu.segmentation_params.segmentation_temporal_update)?;
1184            }
1185
1186            if self.obu.segmentation_params.segmentation_update_data {
1187                for i in 0..MAX_SEGMENTS {
1188                    for j in 0..SEG_LVL_MAX {
1189                        let feature_enabled = self.obu.segmentation_params.feature_enabled[i][j];
1190                        self.f(1, feature_enabled)?;
1191
1192                        if feature_enabled {
1193                            let bits_to_read = FEATURE_BITS[j] as usize;
1194                            let limit = FEATURE_MAX[j];
1195                            let signed = FEATURE_SIGNED[j];
1196
1197                            let value = i32::from(self.obu.segmentation_params.feature_data[i][j]);
1198                            if signed {
1199                                let clipped_value = clip3(-limit, limit, value);
1200                                self.su(bits_to_read + 1, clipped_value)?;
1201                            } else {
1202                                let clipped_value = clip3(0, limit, value);
1203                                self.f(bits_to_read, u32::try_from(clipped_value)?)?;
1204                            }
1205                        }
1206                    }
1207                }
1208            } else {
1209                if self.obu.segmentation_params.feature_enabled
1210                    != [[false; SEG_LVL_MAX]; MAX_SEGMENTS]
1211                {
1212                    self.invalid_element_value("feature_enabled")?;
1213                }
1214                if self.obu.segmentation_params.feature_data != [[0; SEG_LVL_MAX]; MAX_SEGMENTS] {
1215                    self.invalid_element_value("feature_data")?;
1216                }
1217            }
1218        }
1219
1220        Ok(())
1221    }
1222
1223    /// Writes AV1 5.9.15. Tile info syntax
1224    fn tile_info(&mut self) -> SynthesizerResult<()> {
1225        // From AV1 5.9.9. Compute image size function
1226        self.f(1, self.obu.tile_info.uniform_tile_spacing_flag)?;
1227        if self.obu.tile_info.uniform_tile_spacing_flag {
1228            if self.obu.tile_info.tile_cols != 1
1229                && self.obu.tile_info.tile_cols_log2 != 0
1230                && self.obu.tile_info.tile_rows != 1
1231                && self.obu.tile_info.tile_rows_log2 != 0
1232            {
1233                // TODO: Allow more then single tile
1234                log::error!("Only 1x1 tiles frame is currently supported");
1235                return Err(SynthesizerError::Unsupported);
1236            }
1237
1238            const INCREMENT_TILE_COLS_LOG2: u32 = 0;
1239            const INCREMENT_TILE_ROWS_LOG2: u32 = 0;
1240
1241            self.f(1, INCREMENT_TILE_COLS_LOG2)?;
1242            self.f(1, INCREMENT_TILE_ROWS_LOG2)?;
1243        } else {
1244            // TODO
1245            log::error!("Only uniformly sized tiles are currently supported");
1246            return Err(SynthesizerError::Unsupported);
1247        }
1248
1249        Ok(())
1250    }
1251
1252    /// Writes AV1 5.9.17. Quantizer index delta parameters syntax
1253    fn delta_q_params(&mut self) -> SynthesizerResult<()> {
1254        if self.obu.quantization_params.base_q_idx > 0 {
1255            self.f(1, self.obu.quantization_params.delta_q_present)?;
1256
1257            if self.obu.quantization_params.delta_q_present {
1258                self.f(2, self.obu.quantization_params.delta_q_res)?;
1259            }
1260        } else if self.obu.quantization_params.delta_q_present {
1261            self.invalid_element_value("delta_q_present")?;
1262        }
1263
1264        Ok(())
1265    }
1266
1267    /// Writes AV1 5.9.18. Loop filter delta parameters syntax
1268    fn delta_lf_params(&mut self) -> SynthesizerResult<()> {
1269        if self.obu.quantization_params.delta_q_present {
1270            if self.obu.allow_intrabc {
1271                self.f(1, self.obu.loop_filter_params.delta_lf_present)?;
1272
1273                if self.obu.loop_filter_params.delta_lf_present {
1274                    self.f(2, self.obu.loop_filter_params.delta_lf_res)?;
1275                    self.f(1, self.obu.loop_filter_params.delta_lf_multi)?;
1276                }
1277            } else if self.obu.loop_filter_params.delta_lf_present {
1278                self.invalid_element_value("delta_lf_present")?;
1279            }
1280        }
1281
1282        Ok(())
1283    }
1284
1285    /// Writes AV1 5.9.19. CDEF params syntax
1286    fn cdef_params(&mut self, sequence: &'o SequenceHeaderObu) -> SynthesizerResult<()> {
1287        if self.obu.coded_lossless || self.obu.allow_intrabc || !sequence.enable_cdef {
1288            if self.obu.cdef_params.cdef_bits != 0 {
1289                self.invalid_element_value("cdef_bits")?;
1290            }
1291
1292            if self.obu.cdef_params.cdef_y_pri_strength[0] != 0 {
1293                self.invalid_element_value("cdef_y_pri_strength")?;
1294            }
1295
1296            if self.obu.cdef_params.cdef_y_sec_strength[0] != 0 {
1297                self.invalid_element_value("cdef_y_sec_strength")?;
1298            }
1299
1300            if self.obu.cdef_params.cdef_uv_pri_strength[0] != 0 {
1301                self.invalid_element_value("cdef_uv_pri_strength")?;
1302            }
1303
1304            if self.obu.cdef_params.cdef_uv_sec_strength[0] != 0 {
1305                self.invalid_element_value("cdef_uv_sec_strength")?;
1306            }
1307
1308            if self.obu.cdef_params.cdef_damping != 3 {
1309                self.invalid_element_value("cdef_damping")?;
1310            }
1311
1312            return Ok(());
1313        }
1314
1315        self.f(2, self.obu.cdef_params.cdef_damping - 3)?;
1316        self.f(2, self.obu.cdef_params.cdef_bits)?;
1317
1318        for i in 0..(1 << self.obu.cdef_params.cdef_bits) {
1319            self.f(4, self.obu.cdef_params.cdef_y_pri_strength[i])?;
1320
1321            let mut cdef_y_sec_strength = self.obu.cdef_params.cdef_y_sec_strength[i];
1322            if cdef_y_sec_strength == 4 {
1323                cdef_y_sec_strength -= 1;
1324            }
1325
1326            self.f(2, cdef_y_sec_strength)?;
1327
1328            if sequence.num_planes > 1 {
1329                self.f(4, self.obu.cdef_params.cdef_uv_pri_strength[i])?;
1330
1331                let mut cdef_uv_sec_strength = self.obu.cdef_params.cdef_uv_sec_strength[i];
1332                if cdef_uv_sec_strength == 4 {
1333                    cdef_uv_sec_strength -= 1;
1334                }
1335
1336                self.f(2, cdef_uv_sec_strength)?;
1337            }
1338        }
1339
1340        Ok(())
1341    }
1342
1343    /// Writes AV1 5.9.20. Loop restoration params syntax
1344    fn lr_params(&mut self, sequence: &'o SequenceHeaderObu) -> SynthesizerResult<()> {
1345        if self.obu.all_lossless || self.obu.allow_intrabc || !sequence.enable_restoration {
1346            if self.obu.loop_restoration_params.frame_restoration_type
1347                != [FrameRestorationType::None; MAX_NUM_PLANES]
1348            {
1349                self.invalid_element_value("frame_restoration_type")?;
1350            }
1351
1352            if self.obu.loop_restoration_params.uses_lr {
1353                self.invalid_element_value("uses_lr")?;
1354            }
1355
1356            return Ok(());
1357        }
1358
1359        let mut uses_lr = false;
1360        let mut uses_chroma_lr = false;
1361        for i in 0..MAX_NUM_PLANES {
1362            let lr_type = self.obu.loop_restoration_params.frame_restoration_type[i];
1363            self.f(2, lr_type as u32)?;
1364
1365            if lr_type != FrameRestorationType::None {
1366                uses_lr = true;
1367
1368                if i > 0 {
1369                    uses_chroma_lr = true;
1370                }
1371            }
1372        }
1373
1374        if uses_lr ^ self.obu.loop_restoration_params.uses_lr {
1375            self.invalid_element_value("uses_lr")?;
1376        }
1377        if uses_chroma_lr ^ self.obu.loop_restoration_params.uses_chroma_lr {
1378            self.invalid_element_value("uses_chroma_lr")?;
1379        }
1380
1381        if uses_lr {
1382            if sequence.use_128x128_superblock {
1383                if self.obu.loop_restoration_params.lr_unit_shift == 0 {
1384                    self.invalid_element_value("lr_unit_shift")?;
1385                }
1386
1387                self.f(1, self.obu.loop_restoration_params.lr_unit_shift - 1)?;
1388            } else {
1389                self.f(1, self.obu.loop_restoration_params.lr_unit_shift)?;
1390                if self.obu.loop_restoration_params.lr_unit_shift != 0 {
1391                    self.f(1, self.obu.loop_restoration_params.lr_unit_shift > 1)?;
1392                }
1393            }
1394
1395            if sequence.color_config.subsampling_x
1396                && sequence.color_config.subsampling_y
1397                && uses_chroma_lr
1398            {
1399                self.f(1, self.obu.loop_restoration_params.lr_uv_shift)?;
1400            } else if self.obu.loop_restoration_params.lr_uv_shift != 0 {
1401                self.invalid_element_value("lr_uv_shift")?;
1402            }
1403        }
1404
1405        Ok(())
1406    }
1407
1408    /// Writes AV1 5.9.21. TX mode syntax
1409    fn read_tx_mode(&mut self) -> SynthesizerResult<()> {
1410        if self.obu.coded_lossless {
1411            if self.obu.tx_mode != TxMode::Only4x4 {
1412                self.invalid_element_value("TxMode")?;
1413            }
1414        } else {
1415            self.f(1, self.obu.tx_mode_select)?;
1416
1417            if (self.obu.tx_mode_select != 0 && self.obu.tx_mode != TxMode::Select)
1418                || (self.obu.tx_mode_select == 0 && self.obu.tx_mode != TxMode::Largest)
1419            {
1420                self.invalid_element_value("TxMode")?;
1421            }
1422        }
1423
1424        Ok(())
1425    }
1426
1427    /// Writes AV1 5.9.22. Skip mode params syntax
1428    fn skip_mode_params(&mut self) -> SynthesizerResult<()> {
1429        // TODO: Implement if needed
1430        Ok(())
1431    }
1432
1433    /// Writes AV1 5.9.23. Frame reference mode syntax
1434    fn frame_reference_mode(&mut self) -> SynthesizerResult<()> {
1435        if self.obu.frame_is_intra {
1436            if self.obu.reference_select {
1437                self.invalid_element_value("reference_select")?;
1438            }
1439        } else {
1440            self.f(1, self.obu.reference_select)?;
1441        }
1442
1443        Ok(())
1444    }
1445
1446    /// Writes AV1 5.9.23. Frame reference mode syntax
1447    fn global_motion_params(&mut self) -> SynthesizerResult<()> {
1448        if self.obu.frame_is_intra {
1449            return Ok(());
1450        }
1451
1452        for ref_ in ReferenceFrameType::Last as usize..=ReferenceFrameType::AltRef as usize {
1453            let is_global = self.obu.global_motion_params.is_global[ref_];
1454            let is_rot_zoom = self.obu.global_motion_params.is_rot_zoom[ref_];
1455            let is_translation = self.obu.global_motion_params.is_translation[ref_];
1456            let gm_type = self.obu.global_motion_params.gm_type[ref_];
1457
1458            let expected_type = match (is_global, is_rot_zoom, is_translation) {
1459                (false, _, _) => WarpModelType::Identity,
1460                (true, true, _) => WarpModelType::RotZoom,
1461                (true, false, true) => WarpModelType::Translation,
1462                (true, false, false) => WarpModelType::Affine,
1463            };
1464
1465            if expected_type != gm_type {
1466                self.invalid_element_value("GmType")?;
1467            }
1468
1469            self.f(1, is_global)?;
1470            if is_global {
1471                self.f(1, is_rot_zoom)?;
1472                if is_rot_zoom {
1473                } else {
1474                    self.f(1, is_translation)?;
1475                }
1476            }
1477
1478            if gm_type >= WarpModelType::RotZoom {
1479                self.read_global_param(gm_type, ref_, 2)?;
1480                self.read_global_param(gm_type, ref_, 3)?;
1481                if gm_type == WarpModelType::Affine {
1482                    self.read_global_param(gm_type, ref_, 4)?;
1483                    self.read_global_param(gm_type, ref_, 5)?;
1484                }
1485            }
1486
1487            if gm_type >= WarpModelType::Translation {
1488                self.read_global_param(gm_type, ref_, 0)?;
1489                self.read_global_param(gm_type, ref_, 1)?;
1490            }
1491        }
1492
1493        Ok(())
1494    }
1495
1496    /// Writes AV1 5.9.25. Global param syntax
1497    fn read_global_param(
1498        &mut self,
1499        _gm_type: WarpModelType,
1500        _ref_: usize,
1501        _idx: u32,
1502    ) -> SynthesizerResult<()> {
1503        // TODO
1504        log::warn!(
1505            "Syntax element read_global_param() is not currently supported. Use GmType=IDENTITY"
1506        );
1507        Err(SynthesizerError::Unsupported)
1508    }
1509
1510    /// Writes AV1 5.9.30. Film grain params syntax
1511    fn film_grain_params(&mut self, sequence: &'o SequenceHeaderObu) -> SynthesizerResult<()> {
1512        if !sequence.film_grain_params_present || (!self.obu.show_frame && !self.obu.showable_frame)
1513        {
1514            return Ok(());
1515        }
1516
1517        self.f(1, self.obu.film_grain_params.apply_grain)?;
1518        if !self.obu.film_grain_params.apply_grain {
1519            return Ok(());
1520        }
1521
1522        Err(SynthesizerError::Unsupported)
1523    }
1524}
1525
1526#[cfg(test)]
1527mod tests {
1528
1529    use super::*;
1530    use crate::codec::av1::parser::CdefParams;
1531    use crate::codec::av1::parser::ChromaSamplePosition;
1532    use crate::codec::av1::parser::ColorConfig;
1533    use crate::codec::av1::parser::TileInfo;
1534    use crate::codec::av1::parser::MAX_TILE_COLS;
1535    use crate::codec::av1::parser::MAX_TILE_ROWS;
1536
1537    #[test]
1538    fn sequence_header_obu_test25fps() {
1539        // Extraced from ./src/codec/av1/test_data/test-25fps.ivf.av1
1540        const SEQ_HDR_RAW: [u8; 13] = [
1541            0x0a, 0x0b, 0x00, 0x00, 0x00, 0x04, 0x3c, 0xff, 0xbd, 0xff, 0xf9, 0x80, 0x40,
1542        ];
1543
1544        let seq_hdr = SequenceHeaderObu {
1545            obu_header: ObuHeader {
1546                obu_type: ObuType::SequenceHeader,
1547                extension_flag: false,
1548                has_size_field: true,
1549                temporal_id: 0,
1550                spatial_id: 0,
1551            },
1552
1553            seq_profile: Profile::Profile0,
1554            num_planes: 3,
1555            still_picture: false,
1556            reduced_still_picture_header: false,
1557            timing_info_present_flag: false,
1558            initial_display_delay_present_flag: false,
1559            operating_points_cnt_minus_1: 0,
1560            frame_width_bits_minus_1: 8,
1561            frame_height_bits_minus_1: 7,
1562            max_frame_width_minus_1: 319,
1563            max_frame_height_minus_1: 239,
1564            frame_id_numbers_present_flag: false,
1565            use_128x128_superblock: true,
1566            enable_filter_intra: true,
1567            enable_intra_edge_filter: true,
1568            enable_interintra_compound: true,
1569            enable_masked_compound: true,
1570            enable_warped_motion: true,
1571            enable_dual_filter: true,
1572            enable_order_hint: true,
1573            enable_jnt_comp: true,
1574            enable_ref_frame_mvs: true,
1575            seq_choose_screen_content_tools: true,
1576            seq_force_screen_content_tools: SELECT_SCREEN_CONTENT_TOOLS as u32,
1577            seq_choose_integer_mv: true,
1578            seq_force_integer_mv: SELECT_INTEGER_MV as u32,
1579            order_hint_bits_minus_1: 6,
1580            order_hint_bits: 7,
1581            enable_superres: false,
1582            enable_cdef: true,
1583            enable_restoration: true,
1584            color_config: ColorConfig {
1585                high_bitdepth: false,
1586                mono_chrome: false,
1587                color_description_present_flag: false,
1588                color_range: false,
1589                subsampling_x: true,
1590                subsampling_y: true,
1591                chroma_sample_position: ChromaSamplePosition::Unknown,
1592                separate_uv_delta_q: false,
1593                ..Default::default()
1594            },
1595            film_grain_params_present: false,
1596
1597            ..Default::default()
1598        };
1599
1600        let mut buf = Vec::<u8>::new();
1601        Synthesizer::<'_, SequenceHeaderObu, _>::synthesize(&seq_hdr, &mut buf).unwrap();
1602        assert_eq!(buf, SEQ_HDR_RAW);
1603    }
1604
1605    #[test]
1606    fn sequence_header_obu_av1_annexb() {
1607        // Extraced from: ./src/codec/av1/test_data/av1-annexb.ivf.av1
1608        const SEQ_HDR_RAW: [u8; 12] = [
1609            0x0a, 0x0a, 0x00, 0x00, 0x00, 0x02, 0xaf, 0xff, 0xbf, 0xff, 0x30, 0x08,
1610        ];
1611
1612        let seq_hdr = SequenceHeaderObu {
1613            obu_header: ObuHeader {
1614                obu_type: ObuType::SequenceHeader,
1615                extension_flag: false,
1616                has_size_field: true,
1617                temporal_id: 0,
1618                spatial_id: 0,
1619            },
1620
1621            seq_profile: Profile::Profile0,
1622            num_planes: 3,
1623            still_picture: false,
1624            reduced_still_picture_header: false,
1625            timing_info_present_flag: false,
1626            initial_display_delay_present_flag: false,
1627            operating_points_cnt_minus_1: 0,
1628            frame_width_bits_minus_1: 5,
1629            frame_height_bits_minus_1: 5,
1630            max_frame_width_minus_1: 63,
1631            max_frame_height_minus_1: 63,
1632            frame_id_numbers_present_flag: false,
1633            use_128x128_superblock: true,
1634            enable_filter_intra: true,
1635            enable_intra_edge_filter: true,
1636            enable_interintra_compound: true,
1637            enable_masked_compound: true,
1638            enable_warped_motion: true,
1639            enable_dual_filter: true,
1640            enable_order_hint: true,
1641            enable_jnt_comp: true,
1642            enable_ref_frame_mvs: true,
1643            seq_choose_screen_content_tools: true,
1644            seq_force_screen_content_tools: SELECT_SCREEN_CONTENT_TOOLS as u32,
1645            seq_choose_integer_mv: true,
1646            seq_force_integer_mv: SELECT_INTEGER_MV as u32,
1647            order_hint_bits_minus_1: 6,
1648            order_hint_bits: 7,
1649            enable_superres: false,
1650            enable_cdef: true,
1651            enable_restoration: true,
1652            color_config: ColorConfig {
1653                high_bitdepth: false,
1654                mono_chrome: false,
1655                color_description_present_flag: false,
1656                color_range: false,
1657                subsampling_x: true,
1658                subsampling_y: true,
1659                chroma_sample_position: ChromaSamplePosition::Unknown,
1660                separate_uv_delta_q: false,
1661                ..Default::default()
1662            },
1663            film_grain_params_present: false,
1664
1665            ..Default::default()
1666        };
1667
1668        let mut buf = Vec::<u8>::new();
1669        Synthesizer::<'_, SequenceHeaderObu, _>::synthesize(&seq_hdr, &mut buf).unwrap();
1670        assert_eq!(buf, SEQ_HDR_RAW);
1671    }
1672
1673    #[test]
1674    fn temporal_delim_obu() {
1675        const TD_RAW: [u8; 2] = [0x12, 0x00];
1676
1677        let td = TemporalDelimiterObu {
1678            obu_header: ObuHeader {
1679                obu_type: ObuType::TemporalDelimiter,
1680                extension_flag: false,
1681                has_size_field: true,
1682                temporal_id: 0,
1683                spatial_id: 0,
1684            },
1685        };
1686
1687        let mut buf = Vec::<u8>::new();
1688        Synthesizer::<'_, TemporalDelimiterObu, _>::synthesize(&td, &mut buf).unwrap();
1689
1690        assert_eq!(buf, TD_RAW);
1691    }
1692
1693    #[test]
1694    fn frame_header_obu() {
1695        let _ = env_logger::try_init();
1696
1697        const WIDTH: u32 = 512;
1698        const HEIGHT: u32 = 512;
1699
1700        let seq = SequenceHeaderObu {
1701            obu_header: ObuHeader {
1702                obu_type: ObuType::SequenceHeader,
1703                extension_flag: false,
1704                has_size_field: true,
1705                temporal_id: 0,
1706                spatial_id: 0,
1707            },
1708
1709            seq_profile: Profile::Profile0,
1710
1711            frame_width_bits_minus_1: 16 - 1,
1712            frame_height_bits_minus_1: 16 - 1,
1713            max_frame_width_minus_1: (WIDTH - 1) as u16,
1714            max_frame_height_minus_1: (HEIGHT - 1) as u16,
1715
1716            seq_force_integer_mv: SELECT_INTEGER_MV as u32,
1717
1718            enable_order_hint: true,
1719            order_hint_bits: 8,
1720            order_hint_bits_minus_1: 7,
1721            num_planes: 3,
1722
1723            color_config: ColorConfig {
1724                subsampling_x: true,
1725                subsampling_y: true,
1726                ..Default::default()
1727            },
1728
1729            ..Default::default()
1730        };
1731
1732        let frame = FrameHeaderObu {
1733            obu_header: ObuHeader {
1734                obu_type: ObuType::FrameHeader,
1735                extension_flag: false,
1736                has_size_field: true,
1737                temporal_id: 0,
1738                spatial_id: 0,
1739            },
1740
1741            frame_type: FrameType::KeyFrame,
1742            frame_is_intra: true,
1743            primary_ref_frame: PRIMARY_REF_NONE,
1744            refresh_frame_flags: 0xff,
1745            error_resilient_mode: true,
1746
1747            reduced_tx_set: true,
1748            tx_mode_select: 1,
1749            tx_mode: TxMode::Select,
1750
1751            tile_info: TileInfo {
1752                uniform_tile_spacing_flag: true,
1753                tile_cols: 1,
1754                tile_rows: 1,
1755                tile_cols_log2: 0,
1756                tile_rows_log2: 0,
1757                width_in_sbs_minus_1: {
1758                    let mut value = [0u32; MAX_TILE_COLS];
1759                    value[0] = WIDTH / 64 - 1;
1760                    value
1761                },
1762                height_in_sbs_minus_1: {
1763                    let mut value = [0u32; MAX_TILE_ROWS];
1764                    value[0] = HEIGHT / 64 - 1;
1765                    value
1766                },
1767                ..Default::default()
1768            },
1769
1770            cdef_params: CdefParams {
1771                cdef_damping: 3,
1772                ..Default::default()
1773            },
1774
1775            superres_denom: SUPERRES_NUM as u32,
1776            upscaled_width: WIDTH,
1777            frame_width: WIDTH,
1778            frame_height: HEIGHT,
1779            render_width: WIDTH,
1780            render_height: HEIGHT,
1781
1782            ..Default::default()
1783        };
1784
1785        let mut buf = Vec::<u8>::new();
1786        Synthesizer::<'_, SequenceHeaderObu, _>::synthesize(&seq, &mut buf).unwrap();
1787
1788        Synthesizer::<'_, FrameHeaderObu, _>::synthesize(&frame, &seq, &mut buf).unwrap();
1789
1790        // TODO actual test
1791
1792        let write_to_file = std::option_env!("CROS_CODECS_TEST_WRITE_TO_FILE") == Some("true");
1793        if write_to_file {
1794            let mut out = std::fs::File::create("frame_header_obu.av1").unwrap();
1795            out.write_all(&buf).unwrap();
1796            out.flush().unwrap();
1797        }
1798    }
1799}