1use 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 fn obu_header(&mut self, obu: &ObuHeader) -> SynthesizerResult<()> {
148 self.f(1, 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, 0u32)?;
153
154 if obu.extension_flag {
155 self.obu_extension_header(obu)?;
156 }
157
158 Ok(())
159 }
160
161 fn obu_extension_header(&mut self, obu: &ObuHeader) -> SynthesizerResult<()> {
163 self.f(3, obu.temporal_id)?;
165 self.f(2, obu.spatial_id)?;
166 self.f(3, 0u32)?;
167
168 Ok(())
169 }
170
171 fn obu_size(&mut self, size: u32) -> SynthesizerResult<()> {
172 self.leb128(size)
173 }
174
175 fn trailing_bits(&mut self) -> SynthesizerResult<()> {
177 self.f(1, 1u32)?;
178 while !self.writer.aligned() {
179 self.f(1, 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 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 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 fn timing_info(&mut self) -> SynthesizerResult<()> {
586 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 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 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 fn frame_header_obu(&mut self, sequence: &'o SequenceHeaderObu) -> SynthesizerResult<()> {
663 self.uncompressed_header(sequence)
664 }
665
666 fn uncompressed_header(&mut self, sequence: &'o SequenceHeaderObu) -> SynthesizerResult<()> {
668 const ALL_FRAMES: u32 = (1 << NUM_REF_FRAMES) - 1;
669
670 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 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 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 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 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 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 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 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 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 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 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 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 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 fn tile_info(&mut self) -> SynthesizerResult<()> {
1227 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 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 log::error!("Only uniformly sized tiles are currently supported");
1248 return Err(SynthesizerError::Unsupported);
1249 }
1250
1251 Ok(())
1252 }
1253
1254 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 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 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 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 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 fn skip_mode_params(&mut self) -> SynthesizerResult<()> {
1431 Ok(())
1433 }
1434
1435 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 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 fn read_global_param(
1500 &mut self,
1501 _gm_type: WarpModelType,
1502 _ref_: usize,
1503 _idx: u32,
1504 ) -> SynthesizerResult<()> {
1505 log::warn!(
1507 "Syntax element read_global_param() is not currently supported. Use GmType=IDENTITY"
1508 );
1509 Err(SynthesizerError::Unsupported)
1510 }
1511
1512 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 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 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 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}