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