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