cros_codecs/decoder/stateless/vp9/
vaapi.rs

1// Copyright 2022 The ChromiumOS Authors
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use std::rc::Rc;
6
7use anyhow::anyhow;
8use anyhow::Context;
9use libva::Display;
10use libva::Picture as VaPicture;
11use libva::SegmentParameterVP9;
12use libva::SurfaceMemoryDescriptor;
13
14use crate::backend::vaapi::decoder::va_surface_id;
15use crate::backend::vaapi::decoder::PoolCreationMode;
16use crate::backend::vaapi::decoder::VaStreamInfo;
17use crate::backend::vaapi::decoder::VaapiBackend;
18use crate::backend::vaapi::decoder::VaapiPicture;
19use crate::codec::vp9::parser::BitDepth;
20use crate::codec::vp9::parser::Header;
21use crate::codec::vp9::parser::Profile;
22use crate::codec::vp9::parser::ALTREF_FRAME;
23use crate::codec::vp9::parser::GOLDEN_FRAME;
24use crate::codec::vp9::parser::LAST_FRAME;
25use crate::codec::vp9::parser::MAX_SEGMENTS;
26use crate::codec::vp9::parser::NUM_REF_FRAMES;
27use crate::decoder::stateless::vp9::Segmentation;
28use crate::decoder::stateless::vp9::StatelessVp9DecoderBackend;
29use crate::decoder::stateless::vp9::Vp9;
30use crate::decoder::stateless::NewPictureError;
31use crate::decoder::stateless::NewPictureResult;
32use crate::decoder::stateless::NewStatelessDecoderError;
33use crate::decoder::stateless::StatelessBackendResult;
34use crate::decoder::stateless::StatelessDecoder;
35use crate::decoder::stateless::StatelessDecoderBackendPicture;
36use crate::decoder::BlockingMode;
37
38/// The number of surfaces to allocate for this codec.
39const NUM_SURFACES: usize = 12;
40
41/// Returns the RT format matching the input parameters.
42fn get_rt_format(
43    profile: Profile,
44    bit_depth: BitDepth,
45    subsampling_x: bool,
46    subsampling_y: bool,
47) -> anyhow::Result<u32> {
48    match profile {
49        Profile::Profile0 => Ok(libva::constants::VA_RT_FORMAT_YUV420),
50        Profile::Profile1 => {
51            if subsampling_x && !subsampling_y {
52                Ok(libva::constants::VA_RT_FORMAT_YUV422)
53            } else if !subsampling_x && !subsampling_y {
54                Ok(libva::constants::VA_RT_FORMAT_YUV444)
55            } else {
56                Err(anyhow!(
57                    "Unsupported subsampling for profile 1: X: {:?} Y: {:?}",
58                    subsampling_x,
59                    subsampling_y
60                ))
61            }
62        }
63        Profile::Profile2 => match bit_depth {
64            BitDepth::Depth8 => Err(anyhow!(
65                "Unsupported bit depth for profile 2: {:?}",
66                bit_depth
67            )),
68            BitDepth::Depth10 => Ok(libva::constants::VA_RT_FORMAT_YUV420_10),
69            BitDepth::Depth12 => Ok(libva::constants::VA_RT_FORMAT_YUV420_12),
70        },
71        Profile::Profile3 => {
72            if subsampling_x && !subsampling_y {
73                match bit_depth {
74                        BitDepth::Depth8 => Err(anyhow!(
75                            "Unsupported (subsampling_x, subsampling_y, bit depth) combination for profile 3: ({:?}, {:?}, {:?})",
76                            subsampling_x,
77                            subsampling_y,
78                            bit_depth
79                        )),
80                        BitDepth::Depth10 => Ok(libva::constants::VA_RT_FORMAT_YUV422_10),
81                        BitDepth::Depth12 => Ok(libva::constants::VA_RT_FORMAT_YUV422_12),
82                    }
83            } else if !subsampling_x && !subsampling_y {
84                match bit_depth {
85                        BitDepth::Depth8 => Err(anyhow!(
86                            "Unsupported (subsampling_x, subsampling_y, bit depth) combination for profile 3: ({:?}, {:?}, {:?})",
87                            subsampling_x,
88                            subsampling_y,
89                            bit_depth
90                        )),
91                        BitDepth::Depth10 => Ok(libva::constants::VA_RT_FORMAT_YUV444_10),
92                        BitDepth::Depth12 => Ok(libva::constants::VA_RT_FORMAT_YUV444_12),
93                    }
94            } else {
95                Err(anyhow!(
96                            "Unsupported (subsampling_x, subsampling_y, bit depth) combination for profile 3: ({:?}, {:?}, {:?})",
97                            subsampling_x,
98                            subsampling_y,
99                            bit_depth
100                        ))
101            }
102        }
103    }
104}
105
106impl VaStreamInfo for &Header {
107    fn va_profile(&self) -> anyhow::Result<i32> {
108        Ok(match self.profile {
109            Profile::Profile0 => libva::VAProfile::VAProfileVP9Profile0,
110            Profile::Profile1 => libva::VAProfile::VAProfileVP9Profile1,
111            Profile::Profile2 => libva::VAProfile::VAProfileVP9Profile2,
112            Profile::Profile3 => libva::VAProfile::VAProfileVP9Profile3,
113        })
114    }
115
116    fn rt_format(&self) -> anyhow::Result<u32> {
117        get_rt_format(
118            self.profile,
119            self.bit_depth,
120            self.subsampling_x,
121            self.subsampling_y,
122        )
123    }
124
125    fn min_num_surfaces(&self) -> usize {
126        NUM_SURFACES
127    }
128
129    fn coded_size(&self) -> (u32, u32) {
130        (self.width, self.height)
131    }
132
133    fn visible_rect(&self) -> ((u32, u32), (u32, u32)) {
134        ((0, 0), self.coded_size())
135    }
136}
137
138fn build_pic_param(
139    hdr: &Header,
140    reference_frames: [u32; NUM_REF_FRAMES],
141) -> anyhow::Result<libva::BufferType> {
142    let pic_fields = libva::VP9PicFields::new(
143        hdr.subsampling_x as u32,
144        hdr.subsampling_y as u32,
145        hdr.frame_type as u32,
146        hdr.show_frame as u32,
147        hdr.error_resilient_mode as u32,
148        hdr.intra_only as u32,
149        hdr.allow_high_precision_mv as u32,
150        hdr.interpolation_filter as u32,
151        hdr.frame_parallel_decoding_mode as u32,
152        hdr.reset_frame_context as u32,
153        hdr.refresh_frame_context as u32,
154        hdr.frame_context_idx as u32,
155        hdr.seg.enabled as u32,
156        hdr.seg.temporal_update as u32,
157        hdr.seg.update_map as u32,
158        hdr.ref_frame_idx[LAST_FRAME - 1] as u32,
159        hdr.ref_frame_sign_bias[LAST_FRAME] as u32,
160        hdr.ref_frame_idx[GOLDEN_FRAME - 1] as u32,
161        hdr.ref_frame_sign_bias[GOLDEN_FRAME] as u32,
162        hdr.ref_frame_idx[ALTREF_FRAME - 1] as u32,
163        hdr.ref_frame_sign_bias[ALTREF_FRAME] as u32,
164        hdr.lossless as u32,
165    );
166
167    let lf = &hdr.lf;
168    let seg = &hdr.seg;
169
170    let seg_pred_prob = if seg.temporal_update {
171        seg.pred_probs
172    } else {
173        [0xff, 0xff, 0xff]
174    };
175
176    let pic_param = libva::PictureParameterBufferVP9::new(
177        hdr.width.try_into().unwrap(),
178        hdr.height.try_into().unwrap(),
179        reference_frames,
180        &pic_fields,
181        lf.level,
182        lf.sharpness,
183        hdr.tile_rows_log2,
184        hdr.tile_cols_log2,
185        hdr.uncompressed_header_size_in_bytes.try_into().unwrap(),
186        hdr.header_size_in_bytes,
187        seg.tree_probs,
188        seg_pred_prob,
189        hdr.profile as u8,
190        hdr.bit_depth as u8,
191    );
192
193    Ok(libva::BufferType::PictureParameter(
194        libva::PictureParameter::VP9(pic_param),
195    ))
196}
197
198fn build_slice_param(
199    seg: &[Segmentation; MAX_SEGMENTS],
200    slice_size: usize,
201) -> anyhow::Result<libva::BufferType> {
202    let seg_params: std::result::Result<[SegmentParameterVP9; MAX_SEGMENTS], _> = seg
203        .iter()
204        .map(|s| {
205            let seg_flags = libva::VP9SegmentFlags::new(
206                s.reference_frame_enabled as u16,
207                s.reference_frame as u16,
208                s.reference_skip_enabled as u16,
209            );
210
211            libva::SegmentParameterVP9::new(
212                &seg_flags,
213                s.lvl_lookup,
214                s.luma_ac_quant_scale,
215                s.luma_dc_quant_scale,
216                s.chroma_ac_quant_scale,
217                s.chroma_dc_quant_scale,
218            )
219        })
220        .collect::<Vec<_>>()
221        .try_into();
222
223    let seg_params = match seg_params {
224        Ok(seg_params) => seg_params,
225
226        // Impossible, this is just a detour to collect into a fixed-size
227        // array whose size is the same size of the `seg` argument.
228        Err(_) => panic!("Invalid segment parameters"),
229    };
230
231    Ok(libva::BufferType::SliceParameter(
232        libva::SliceParameter::VP9(libva::SliceParameterBufferVP9::new(
233            slice_size as u32,
234            0,
235            libva::constants::VA_SLICE_DATA_FLAG_ALL,
236            seg_params,
237        )),
238    ))
239}
240
241impl<M: SurfaceMemoryDescriptor + 'static> StatelessDecoderBackendPicture<Vp9> for VaapiBackend<M> {
242    type Picture = VaapiPicture<M>;
243}
244
245impl<M: SurfaceMemoryDescriptor + 'static> StatelessVp9DecoderBackend for VaapiBackend<M> {
246    fn new_sequence(&mut self, header: &Header) -> StatelessBackendResult<()> {
247        self.new_sequence(header, PoolCreationMode::Highest)
248    }
249
250    fn new_picture(&mut self, timestamp: u64) -> NewPictureResult<Self::Picture> {
251        let highest_pool = self.highest_pool();
252        let surface = highest_pool
253            .get_surface()
254            .ok_or(NewPictureError::OutOfOutputBuffers)?;
255        let metadata = self.metadata_state.get_parsed()?;
256        let context = &metadata.context;
257
258        Ok(VaPicture::new(timestamp, Rc::clone(context), surface))
259    }
260
261    fn submit_picture(
262        &mut self,
263        mut picture: Self::Picture,
264        hdr: &Header,
265        reference_frames: &[Option<Self::Handle>; NUM_REF_FRAMES],
266        bitstream: &[u8],
267        segmentation: &[Segmentation; MAX_SEGMENTS],
268    ) -> StatelessBackendResult<Self::Handle> {
269        let metadata = self.metadata_state.get_parsed()?;
270        let context = &metadata.context;
271
272        let reference_frames: [u32; NUM_REF_FRAMES] = reference_frames
273            .iter()
274            .map(va_surface_id)
275            .collect::<Vec<_>>()
276            .try_into()
277            .unwrap();
278
279        let pic_param = context
280            .create_buffer(build_pic_param(hdr, reference_frames)?)
281            .context("while creating pic params buffer")?;
282
283        let slice_param = context
284            .create_buffer(build_slice_param(segmentation, bitstream.len())?)
285            .context("while creating slice params buffer")?;
286
287        let slice_data = context
288            .create_buffer(libva::BufferType::SliceData(Vec::from(bitstream)))
289            .context("while creating slice data buffer")?;
290
291        // Add buffers with the parsed data.
292        picture.add_buffer(pic_param);
293        picture.add_buffer(slice_param);
294        picture.add_buffer(slice_data);
295
296        self.process_picture::<Vp9>(picture)
297    }
298}
299
300impl<M: SurfaceMemoryDescriptor + 'static> StatelessDecoder<Vp9, VaapiBackend<M>> {
301    // Creates a new instance of the decoder using the VAAPI backend.
302    pub fn new_vaapi<S>(
303        display: Rc<Display>,
304        blocking_mode: BlockingMode,
305    ) -> Result<Self, NewStatelessDecoderError>
306    where
307        M: From<S>,
308        S: From<M>,
309    {
310        Self::new(VaapiBackend::new(display, true), blocking_mode)
311    }
312}
313
314#[cfg(test)]
315mod tests {
316    use libva::BufferType;
317    use libva::Display;
318    use libva::PictureParameter;
319    use libva::SliceParameter;
320
321    use crate::codec::vp9::parser::Parser;
322    use crate::codec::vp9::parser::MAX_SEGMENTS;
323    use crate::codec::vp9::parser::NUM_REF_FRAMES;
324    use crate::decoder::stateless::tests::test_decode_stream;
325    use crate::decoder::stateless::tests::TestStream;
326    use crate::decoder::stateless::vp9::Segmentation;
327    use crate::decoder::BlockingMode;
328    use crate::utils::simple_playback_loop;
329    use crate::utils::simple_playback_loop_owned_frames;
330    use crate::utils::IvfIterator;
331    use crate::DecodedFormat;
332
333    use super::*;
334
335    /// Run `test` using the vaapi decoder, in both blocking and non-blocking modes.
336    fn test_decoder_vaapi(
337        test: &TestStream,
338        output_format: DecodedFormat,
339        blocking_mode: BlockingMode,
340    ) {
341        let display = Display::open().unwrap();
342        let decoder = StatelessDecoder::<Vp9, _>::new_vaapi::<()>(display, blocking_mode).unwrap();
343
344        test_decode_stream(
345            |d, s, c| {
346                simple_playback_loop(
347                    d,
348                    IvfIterator::new(s),
349                    c,
350                    &mut simple_playback_loop_owned_frames,
351                    output_format,
352                    blocking_mode,
353                )
354            },
355            decoder,
356            test,
357            true,
358            false,
359        );
360    }
361
362    #[test]
363    // Ignore this test by default as it requires libva-compatible hardware.
364    #[ignore]
365    fn test_25fps_block() {
366        use crate::decoder::stateless::vp9::tests::DECODE_TEST_25FPS;
367        test_decoder_vaapi(
368            &DECODE_TEST_25FPS,
369            DecodedFormat::NV12,
370            BlockingMode::Blocking,
371        );
372    }
373
374    #[test]
375    // Ignore this test by default as it requires libva-compatible hardware.
376    #[ignore]
377    fn test_25fps_nonblock() {
378        use crate::decoder::stateless::vp9::tests::DECODE_TEST_25FPS;
379        test_decoder_vaapi(
380            &DECODE_TEST_25FPS,
381            DecodedFormat::NV12,
382            BlockingMode::NonBlocking,
383        );
384    }
385
386    #[test]
387    // Ignore this test by default as it requires libva-compatible hardware.
388    #[ignore]
389    fn show_existing_frame_block() {
390        use crate::decoder::stateless::vp9::tests::DECODE_TEST_25FPS_SHOW_EXISTING_FRAME;
391        test_decoder_vaapi(
392            &DECODE_TEST_25FPS_SHOW_EXISTING_FRAME,
393            DecodedFormat::NV12,
394            BlockingMode::Blocking,
395        );
396    }
397
398    #[test]
399    // Ignore this test by default as it requires libva-compatible hardware.
400    #[ignore]
401    fn show_existing_frame_nonblock() {
402        use crate::decoder::stateless::vp9::tests::DECODE_TEST_25FPS_SHOW_EXISTING_FRAME;
403        test_decoder_vaapi(
404            &DECODE_TEST_25FPS_SHOW_EXISTING_FRAME,
405            DecodedFormat::NV12,
406            BlockingMode::NonBlocking,
407        );
408    }
409
410    #[test]
411    // Ignore this test by default as it requires libva-compatible hardware.
412    #[ignore]
413    fn show_existing_frame2_block() {
414        use crate::decoder::stateless::vp9::tests::DECODE_TEST_25FPS_SHOW_EXISTING_FRAME2;
415        test_decoder_vaapi(
416            &DECODE_TEST_25FPS_SHOW_EXISTING_FRAME2,
417            DecodedFormat::NV12,
418            BlockingMode::Blocking,
419        );
420    }
421
422    #[test]
423    // Ignore this test by default as it requires libva-compatible hardware.
424    #[ignore]
425    fn show_existing_frame2_nonblock() {
426        use crate::decoder::stateless::vp9::tests::DECODE_TEST_25FPS_SHOW_EXISTING_FRAME2;
427        test_decoder_vaapi(
428            &DECODE_TEST_25FPS_SHOW_EXISTING_FRAME2,
429            DecodedFormat::NV12,
430            BlockingMode::NonBlocking,
431        );
432    }
433
434    #[test]
435    // Ignore this test by default as it requires libva-compatible hardware.
436    #[ignore]
437    fn test_resolution_change_500frames_block() {
438        use crate::decoder::stateless::vp9::tests::DECODE_RESOLUTION_CHANGE_500FRAMES;
439        let display = Display::open().unwrap();
440        let decoder =
441            StatelessDecoder::<Vp9, _>::new_vaapi::<()>(display, BlockingMode::Blocking).unwrap();
442
443        // Skip CRC checking as they have not been generated properly?
444        test_decode_stream(
445            |d, s, c| {
446                simple_playback_loop(
447                    d,
448                    IvfIterator::new(s),
449                    c,
450                    &mut simple_playback_loop_owned_frames,
451                    DecodedFormat::NV12,
452                    BlockingMode::Blocking,
453                )
454            },
455            decoder,
456            &DECODE_RESOLUTION_CHANGE_500FRAMES,
457            false,
458            false,
459        );
460    }
461
462    #[test]
463    // Ignore this test by default as it requires libva-compatible hardware.
464    #[ignore]
465    fn test_resolution_change_500frames_nonblock() {
466        use crate::decoder::stateless::vp9::tests::DECODE_RESOLUTION_CHANGE_500FRAMES;
467        let display = Display::open().unwrap();
468        let decoder =
469            StatelessDecoder::<Vp9, _>::new_vaapi::<()>(display, BlockingMode::Blocking).unwrap();
470
471        // Skip CRC checking as they have not been generated properly?
472        test_decode_stream(
473            |d, s, c| {
474                simple_playback_loop(
475                    d,
476                    IvfIterator::new(s),
477                    c,
478                    &mut simple_playback_loop_owned_frames,
479                    DecodedFormat::NV12,
480                    BlockingMode::NonBlocking,
481                )
482            },
483            decoder,
484            &DECODE_RESOLUTION_CHANGE_500FRAMES,
485            false,
486            false,
487        );
488    }
489
490    #[test]
491    /// Check that we are able to build the VA picture parameters from the stream properly.
492    fn build_pic_params() {
493        const TEST_STREAM: &[u8] = include_bytes!("../../../codec/vp9/test_data/test-25fps.vp9");
494        let mut parser: Parser = Default::default();
495        let mut segmentation: [Segmentation; MAX_SEGMENTS] = Default::default();
496        let mut ivf_iter = IvfIterator::new(TEST_STREAM);
497
498        // FRAME 0
499
500        let packet = ivf_iter.next().unwrap();
501        let mut frames = parser.parse_chunk(packet).unwrap();
502        assert_eq!(frames.len(), 1);
503        let frame = frames.remove(0);
504
505        assert_eq!(frame.as_ref().len(), 10674);
506
507        let pic_param = build_pic_param(
508            &frame.header,
509            [libva::constants::VA_INVALID_SURFACE; NUM_REF_FRAMES],
510        )
511        .unwrap();
512        let pic_param = match pic_param {
513            BufferType::PictureParameter(PictureParameter::VP9(pic_param)) => pic_param,
514            _ => panic!(),
515        };
516
517        Segmentation::update_segmentation(&mut segmentation, &frame.header);
518        let slice_param = build_slice_param(&segmentation, frame.as_ref().len()).unwrap();
519        let slice_param = match slice_param {
520            BufferType::SliceParameter(SliceParameter::VP9(slice_param)) => slice_param,
521            _ => panic!(),
522        };
523
524        assert_eq!(pic_param.inner().frame_width, 320);
525        assert_eq!(pic_param.inner().frame_height, 240);
526        assert_eq!(
527            pic_param.inner().reference_frames,
528            [libva::constants::VA_INVALID_SURFACE; NUM_REF_FRAMES]
529        );
530
531        // Safe because this bitfield is initialized by the decoder.
532        assert_eq!(unsafe { pic_param.inner().pic_fields.value }, unsafe {
533            libva::VP9PicFields::new(
534                1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
535            )
536            .inner()
537            .value
538        });
539
540        assert_eq!(pic_param.inner().filter_level, 9);
541        assert_eq!(pic_param.inner().sharpness_level, 0);
542        assert_eq!(pic_param.inner().log2_tile_rows, 0);
543        assert_eq!(pic_param.inner().log2_tile_columns, 0);
544        assert_eq!(pic_param.inner().frame_header_length_in_bytes, 18);
545        assert_eq!(pic_param.inner().first_partition_size, 120);
546        assert_eq!(pic_param.inner().mb_segment_tree_probs, [0; 7]);
547        assert_eq!(pic_param.inner().segment_pred_probs, [0xff; 3]);
548        assert_eq!(pic_param.inner().profile, 0);
549        assert_eq!(pic_param.inner().bit_depth, 8);
550
551        assert_eq!(slice_param.inner().slice_data_size, 10674);
552        assert_eq!(slice_param.inner().slice_data_offset, 0);
553        assert_eq!(
554            slice_param.inner().slice_data_flag,
555            libva::constants::VA_SLICE_DATA_FLAG_ALL
556        );
557
558        for seg_param in &slice_param.inner().seg_param {
559            // Safe because this bitfield is initialized by the decoder.
560            assert_eq!(unsafe { seg_param.segment_flags.value }, 0);
561            assert_eq!(seg_param.filter_level, [[10, 0], [9, 9], [8, 8], [8, 8]]);
562            assert_eq!(seg_param.luma_ac_quant_scale, 72);
563            assert_eq!(seg_param.luma_dc_quant_scale, 62);
564            assert_eq!(seg_param.chroma_ac_quant_scale, 72);
565            assert_eq!(seg_param.chroma_dc_quant_scale, 62);
566        }
567
568        // FRAME 1
569
570        let packet = ivf_iter.next().unwrap();
571        let mut frames = parser.parse_chunk(packet).unwrap();
572        assert_eq!(frames.len(), 2);
573        let frame = frames.remove(0);
574        assert_eq!(frame.as_ref().len(), 2390);
575
576        let pic_param = build_pic_param(&frame.header, [0; NUM_REF_FRAMES]).unwrap();
577        let pic_param = match pic_param {
578            BufferType::PictureParameter(PictureParameter::VP9(pic_param)) => pic_param,
579            _ => panic!(),
580        };
581
582        Segmentation::update_segmentation(&mut segmentation, &frame.header);
583        let slice_param = build_slice_param(&segmentation, frame.as_ref().len()).unwrap();
584        let slice_param = match slice_param {
585            BufferType::SliceParameter(SliceParameter::VP9(slice_param)) => slice_param,
586            _ => panic!(),
587        };
588
589        assert_eq!(pic_param.inner().frame_width, 320);
590        assert_eq!(pic_param.inner().frame_height, 240);
591        assert_eq!(pic_param.inner().reference_frames, [0; NUM_REF_FRAMES]);
592        // Safe because this bitfield is initialized by the decoder.
593        assert_eq!(unsafe { pic_param.inner().pic_fields.value }, unsafe {
594            libva::VP9PicFields::new(
595                1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0,
596            )
597            .inner()
598            .value
599        });
600
601        assert_eq!(pic_param.inner().filter_level, 15);
602        assert_eq!(pic_param.inner().sharpness_level, 0);
603        assert_eq!(pic_param.inner().log2_tile_rows, 0);
604        assert_eq!(pic_param.inner().log2_tile_columns, 0);
605        assert_eq!(pic_param.inner().frame_header_length_in_bytes, 11);
606        assert_eq!(pic_param.inner().first_partition_size, 48);
607        assert_eq!(pic_param.inner().mb_segment_tree_probs, [0; 7]);
608        assert_eq!(pic_param.inner().segment_pred_probs, [0xff; 3]);
609        assert_eq!(pic_param.inner().profile, 0);
610        assert_eq!(pic_param.inner().bit_depth, 8);
611
612        assert_eq!(slice_param.inner().slice_data_size, 2390);
613        assert_eq!(slice_param.inner().slice_data_offset, 0);
614        assert_eq!(
615            slice_param.inner().slice_data_flag,
616            libva::constants::VA_SLICE_DATA_FLAG_ALL
617        );
618
619        for seg_param in &slice_param.inner().seg_param {
620            // Safe because this bitfield is initialized by the decoder.
621            assert_eq!(unsafe { seg_param.segment_flags.value }, 0);
622            assert_eq!(
623                seg_param.filter_level,
624                [[16, 0], [15, 15], [14, 14], [14, 14]]
625            );
626            assert_eq!(seg_param.luma_ac_quant_scale, 136);
627            assert_eq!(seg_param.luma_dc_quant_scale, 111);
628            assert_eq!(seg_param.chroma_ac_quant_scale, 136);
629            assert_eq!(seg_param.chroma_dc_quant_scale, 111);
630        }
631
632        // FRAME 2
633
634        let frame = frames.remove(0);
635        assert_eq!(frame.as_ref().len(), 108);
636
637        let pic_param = build_pic_param(&frame.header, [0, 0, 1, 0, 0, 0, 0, 0]).unwrap();
638        let pic_param = match pic_param {
639            BufferType::PictureParameter(PictureParameter::VP9(pic_param)) => pic_param,
640            _ => panic!(),
641        };
642
643        Segmentation::update_segmentation(&mut segmentation, &frame.header);
644        let slice_param = build_slice_param(&segmentation, frame.as_ref().len()).unwrap();
645        let slice_param = match slice_param {
646            BufferType::SliceParameter(SliceParameter::VP9(slice_param)) => slice_param,
647            _ => panic!(),
648        };
649
650        assert_eq!(pic_param.inner().frame_width, 320);
651        assert_eq!(pic_param.inner().frame_height, 240);
652        assert_eq!(pic_param.inner().reference_frames, [0, 0, 1, 0, 0, 0, 0, 0]);
653
654        // Safe because this bitfield is initialized by the decoder.
655        assert_eq!(unsafe { pic_param.inner().pic_fields.value }, unsafe {
656            libva::VP9PicFields::new(
657                1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 2, 1, 0,
658            )
659            .inner()
660            .value
661        });
662
663        assert_eq!(pic_param.inner().filter_level, 36);
664        assert_eq!(pic_param.inner().sharpness_level, 0);
665        assert_eq!(pic_param.inner().log2_tile_rows, 0);
666        assert_eq!(pic_param.inner().log2_tile_columns, 0);
667        assert_eq!(pic_param.inner().frame_header_length_in_bytes, 10);
668        assert_eq!(pic_param.inner().first_partition_size, 9);
669        assert_eq!(pic_param.inner().mb_segment_tree_probs, [0; 7]);
670        assert_eq!(pic_param.inner().segment_pred_probs, [0xff; 3]);
671        assert_eq!(pic_param.inner().profile, 0);
672        assert_eq!(pic_param.inner().bit_depth, 8);
673
674        assert_eq!(slice_param.inner().slice_data_size, 108);
675        assert_eq!(slice_param.inner().slice_data_offset, 0);
676        assert_eq!(
677            slice_param.inner().slice_data_flag,
678            libva::constants::VA_SLICE_DATA_FLAG_ALL
679        );
680
681        for seg_param in &slice_param.inner().seg_param {
682            // Safe because this bitfield is initialized by the decoder.
683            assert_eq!(unsafe { seg_param.segment_flags.value }, 0);
684            assert_eq!(
685                seg_param.filter_level,
686                [[38, 0], [36, 36], [34, 34], [34, 34]]
687            );
688            assert_eq!(seg_param.luma_ac_quant_scale, 864);
689            assert_eq!(seg_param.luma_dc_quant_scale, 489);
690            assert_eq!(seg_param.chroma_ac_quant_scale, 864);
691            assert_eq!(seg_param.chroma_dc_quant_scale, 489);
692        }
693    }
694}