1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
//! VP9's persistent 8-slot reference-frame shadow table — this ADR's own central finding (see
//! `adr/linux/0004-vaapi-vp9-key-frame-and-inter-decode.md` § "A second, independent finding")
//! that VP9 decode needs only a **two-field**-per-slot metadata table (`width`/`height`, for
//! `frame_size_with_refs()`), not AV1's twelve-field `RefFrameWidth[]`/`RefFrameType[]`/... set.
//!
//! Logical VP9 reference slots (`0..8`, spec-fixed, never stream-derived) are decoupled from
//! *physical* VA-API `Surface` pool indices: a single `refresh_frame_flags` byte can legally name
//! several logical slots for one freshly-decoded picture at once (this crate's own encoder
//! sibling's ping-pong output does exactly this — `refresh_frame_flags = (1 << slot) | 0xfc`
//! refreshes 7 of the 8 logical slots on every `INTER_FRAME`). Rather than physically duplicating
//! surface content, multiple logical slots may share the same physical pool index — this table
//! stores that pool index per logical slot (a plain, `Copy`, sans-io integer), while
//! `super::Vp9Pipeline::surfaces` (VA-API-calling code, not this module) owns the actual
//! `Surface` objects.
//!
//! [`RefTable::free_pool_index`]'s pigeonhole guarantee (`POOL_SIZE = VP9_REF_SLOTS + 1`) is
//! pure, sans-io logic — unit-tested here without any VA-API device.
/// VP9's spec-fixed logical reference-frame slot count — never stream-derived (unlike H.264's
/// `max_num_ref_frames`), so this crate needs no per-session sizing computation at all.
pub const VP9_REF_SLOTS: usize = 8;
/// Physical `Surface` pool capacity: `VP9_REF_SLOTS + 1`. By pigeonhole, at most `VP9_REF_SLOTS`
/// distinct pool indices can be referenced across the 8 logical slots at any one time, so a pool
/// of `VP9_REF_SLOTS + 1` always has at least one index free for the current decode target —
/// see [`RefTable::free_pool_index`].
pub const POOL_SIZE: usize = VP9_REF_SLOTS + 1;
/// One logical slot's shadow metadata: which physical pool index currently backs it, and that
/// picture's own coded `width`/`height` (needed by `frame_size_with_refs()` — this crate's own
/// finding that VP9 decode needs nothing more per slot than this).
pub
/// The persistent 8-logical-slot table. Owned by the caller (`VaapiVp9Decoder`), outlives any
/// single `Vp9Pipeline` the same way `VaapiAv1Decoder::seq` outlives `Av1Pipeline` — a fresh
/// session with no pipeline yet still has a well-defined (all-empty) table, so an `INTER_FRAME`
/// arriving before any `KEY_FRAME` fails cleanly at `frame_size_with_refs()`'s own lookup rather
/// than needing a separate "have we seen a key frame" flag.
pub