pixelflux/encoders/vaapi/
vp8.rs1use va_sys::*;
13
14use super::super::reference::SlotRefresh;
15use super::{Buffers, Frame, Negotiated};
16
17const LOOP_FILTER_LEVEL: i8 = 16;
18const SHARPNESS: u8 = 4;
19
20pub(super) struct Arm {
21 sequence: VAEncSequenceParameterBufferVP8,
22}
23
24impl Arm {
25 pub(super) fn new() -> Self {
26 Self {
27 sequence: unsafe { std::mem::zeroed() },
28 }
29 }
30
31 pub(super) fn configure(&mut self, n: &Negotiated) {
32 let s = &mut self.sequence;
33 *s = unsafe { std::mem::zeroed() };
34 s.frame_width = n.width;
35 s.frame_height = n.height;
36 s.error_resilient = 0;
37 s.kf_auto = 0;
38 if n.rc_mode != VA_RC_CQP {
39 s.bits_per_second = n.bits_per_second;
40 s.intra_period = i32::MAX as u32;
41 }
42 }
43
44 pub(super) fn sequence(&mut self, _n: &Negotiated, out: &mut Buffers) {
45 out.push(VAEncSequenceParameterBufferType, &self.sequence);
46 }
47
48 pub(super) fn picture(
49 &mut self,
50 n: &Negotiated,
51 frame: &Frame,
52 out: &mut Buffers,
53 ) -> Result<(), String> {
54 let plan = frame.slots;
55 let mut pic: VAEncPictureParameterBufferVP8 = unsafe { std::mem::zeroed() };
56 pic.reconstructed_frame = frame.recon;
57 pic.coded_buf = frame.coded;
58 if frame.key {
59 pic.ref_last_frame = VA_INVALID_SURFACE;
60 pic.ref_gf_frame = VA_INVALID_SURFACE;
61 pic.ref_arf_frame = VA_INVALID_SURFACE;
62 } else {
63 if plan.predict_from == 0 {
64 return Err("a predicted VP8 picture without a reference".into());
65 }
66 pic.ref_last_frame = frame.slot_surfaces[0];
67 pic.ref_gf_frame = frame.slot_surfaces[1];
68 pic.ref_arf_frame = frame.slot_surfaces[2];
69 }
70 unsafe {
71 let r = &mut pic.ref_flags.bits;
72 r.set_force_kf(u32::from(frame.key));
73 r.set_no_ref_last(u32::from(plan.predict_from != SlotRefresh::LAST));
74 r.set_no_ref_gf(u32::from(plan.predict_from != SlotRefresh::GOLDEN));
75 r.set_no_ref_arf(u32::from(plan.predict_from != SlotRefresh::ALTREF));
76 let p = &mut pic.pic_flags.bits;
77 p.set_frame_type(u32::from(!frame.key));
78 p.set_show_frame(1);
79 p.set_refresh_entropy_probs(0);
80 p.set_refresh_last(u32::from(plan.refresh.refreshes(SlotRefresh::LAST)));
81 p.set_refresh_golden_frame(u32::from(plan.refresh.refreshes(SlotRefresh::GOLDEN)));
82 p.set_refresh_alternate_frame(u32::from(plan.refresh.refreshes(SlotRefresh::ALTREF)));
83 }
84 pic.loop_filter_level = [LOOP_FILTER_LEVEL; 4];
85 pic.sharpness_level = SHARPNESS;
86 pic.clamp_qindex_low = 0;
87 pic.clamp_qindex_high = 127;
88 out.push(VAEncPictureParameterBufferType, &pic);
89
90 let q = if n.rc_mode == VA_RC_CQP {
91 frame.qp.min(127) as u16
92 } else {
93 0
94 };
95 let mut quant: VAQMatrixBufferVP8 = unsafe { std::mem::zeroed() };
96 quant.quantization_index = [q; 4];
97 out.push(VAQMatrixBufferType, &quant);
98 Ok(())
99 }
100}