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