1use 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 fn obu_header(&mut self, obu: &ObuHeader) -> SynthesizerResult<()> {
125 self.f(1, 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, 0u32)?;
130
131 if obu.extension_flag {
132 self.obu_extension_header(obu)?;
133 }
134
135 Ok(())
136 }
137
138 fn obu_extension_header(&mut self, obu: &ObuHeader) -> SynthesizerResult<()> {
140 self.f(3, obu.temporal_id)?;
142 self.f(2, obu.spatial_id)?;
143 self.f(3, 0u32)?;
144
145 Ok(())
146 }
147
148 fn obu_size(&mut self, size: u32) -> SynthesizerResult<()> {
149 self.leb128(size)
150 }
151
152 fn trailing_bits(&mut self) -> SynthesizerResult<()> {
154 self.f(1, 1u32)?;
155 while !self.writer.aligned() {
156 self.f(1, 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 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 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 fn timing_info(&mut self) -> SynthesizerResult<()> {
566 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 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 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 fn frame_header_obu(&mut self, sequence: &'o SequenceHeaderObu) -> SynthesizerResult<()> {
643 self.uncompressed_header(sequence)
644 }
645
646 fn uncompressed_header(&mut self, sequence: &'o SequenceHeaderObu) -> SynthesizerResult<()> {
648 const ALL_FRAMES: u32 = (1 << NUM_REF_FRAMES) - 1;
649
650 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 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 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 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 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 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 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 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 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 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 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 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 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 fn tile_info(&mut self) -> SynthesizerResult<()> {
1225 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 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 log::error!("Only uniformly sized tiles are currently supported");
1246 return Err(SynthesizerError::Unsupported);
1247 }
1248
1249 Ok(())
1250 }
1251
1252 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 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 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 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 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 fn skip_mode_params(&mut self) -> SynthesizerResult<()> {
1429 Ok(())
1431 }
1432
1433 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 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 fn read_global_param(
1498 &mut self,
1499 _gm_type: WarpModelType,
1500 _ref_: usize,
1501 _idx: u32,
1502 ) -> SynthesizerResult<()> {
1503 log::warn!(
1505 "Syntax element read_global_param() is not currently supported. Use GmType=IDENTITY"
1506 );
1507 Err(SynthesizerError::Unsupported)
1508 }
1509
1510 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 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 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 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}