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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
//! Strict-tier verified-encoder registry: the single source of truth for
//! the video encoders a packet-sink output accepts.
//!
//! # Why admission is a registry, not a runtime check
//!
//! Every other strict-tier promise is enforced per packet on the delivery
//! path (NAL framing, timestamp ordering, in-band parameter-set rejection,
//! configuration fingerprinting — see `strict.rs`). The one property that
//! cannot be verified there is **one packet == one access unit**: detecting
//! an access-unit boundary inside a packet requires decoding slice headers
//! against the active parameter sets, which the Trusted delivery path
//! deliberately does not do. That property is therefore established per
//! encoder wrapper ahead of time, and the result is recorded here.
//!
//! # Admission requirements
//!
//! A video encoder enters [`STRICT_TIER_VIDEO_ENCODERS`] only with all of:
//!
//! 1. **Wrapper audit** against both FFmpeg versions CI pins (currently 7.1
//! and 8.1): exactly one `AVPacket` per encoded picture, honors
//! `AV_CODEC_FLAG_GLOBAL_HEADER` (parameter sets in extradata at open
//! time, none in-band), monotonically increasing dts.
//! 2. **Emission-shape fixtures** in the strict-tier unit suite covering the
//! wrapper's packet shapes, so CI pins acceptance without the hardware.
//! 3. **A hardware acceptance line**: a skip-guarded integration test plus a
//! machine that actually runs it (maintainer or requesting consumer).
//! 4. A note in the module rustdoc documenting the verified scope.
//!
//! Admission is not availability. A name on this list only lifts the
//! build-time rejection; the linked FFmpeg build must still contain the
//! encoder, and any required hardware must still open.
//!
//! # Verified entries
//!
//! * `libx264` — the v1 baseline; software encoder, exercised end-to-end in
//! CI. With `GLOBAL_HEADER` it emits avcC extradata and length-prefixed
//! packets (FFmpeg `libx264.c` `set_avcc_extradata`; older releases emit
//! Annex-B extradata, which the sink normalizes). Explicit non-zero `bf`
//! / `max_b_frames` is rejected at build. Unset `bf` keeps FFmpeg's
//! libx264 default (typically 3 B-frames); runtime still requires
//! `pts >= dts`. Set `bf=0` for the verified `dts == pts` scope.
//! * `h264_nvenc` — audited against FFmpeg 7.1/8.1 `libavcodec/nvenc.c`:
//! one `NvEncLockBitstream` per picture becomes one packet
//! (`process_output_surface`); `GLOBAL_HEADER` sets `disableSPSPPS = 1`
//! and populates Annex-B extradata at init (`nvenc_setup_extradata`);
//! with `bf=0` the reorder-delay path is bypassed and `dts == pts`;
//! forced keyframes are IDR under `forced-idr=1`; `aud` defaults off.
//! Packets are Annex-B (normalized by the sink) and may carry SEI
//! prefixes and, under CBR padding, filler NAL units — all inside the
//! same access unit. Availability still depends on the linked FFmpeg
//! build and NVIDIA hardware at open time; admission only lifts the
//! build-time rejection.
//! * `h264_videotoolbox` — audited against FFmpeg 7.1/8.1
//! `libavcodec/videotoolboxenc.c`: one compression callback sample is
//! converted into one packet (`vtenc_cm_to_avpacket`); `GLOBAL_HEADER`
//! obtains Annex-B SPS/PPS during open (`vtenc_populate_extradata`) and
//! omits parameter sets from key packets. **Verified scope is `bf=0`
//! only**: frame reordering is disabled and `dts == pts`. Enabling B
//! frames can produce `pts < dts`, which the existing timestamp contract
//! rejects. The explicit-B-frame build gate is **VideoToolbox-only**:
//! `"0"` / `"00"` / `" 0"` are admitted; `"3"`, `"0.0"`, `"1b"`, empty
//! are rejected. Unset keys keep the wrapper default (VideoToolbox: no
//! B-frames). `libx264` / `h264_nvenc` / `libopenh264` keep runtime
//! `pts >= dts` enforcement for explicit B-frames. This crate does
//! **not** rewrite the user's options.
//! VideoToolbox may emit SEI and may preserve AUD/filler NAL units inside
//! the same access unit. Availability still depends on the Apple platform
//! and encoder hardware; Linux/Windows builds do not have this wrapper.
//! * `libopenh264` — audited against FFmpeg 7.1/8.1
//! `libavcodec/libopenh264enc.c`: one `EncodeFrame` result, including all
//! slices, is copied into one packet; `GLOBAL_HEADER` copies Annex-B
//! parameter sets into extradata and skips the IDR parameter-set layer.
//! OpenH264 does not encode B-frames, so the no-delay path yields
//! `dts == pts`. Availability requires an FFmpeg build configured with
//! `--enable-libopenh264`; that flag does not require `--enable-gpl` or
//! `--enable-nonfree`. OpenH264's source copyright license is BSD-2-Clause;
//! that is a **copyright** fact, not a patent grant. Cisco's patent
//! arrangement covers its official binary module under its own terms —
//! a distro-built or self-built `libopenh264` does not inherit that
//! coverage. This crate does not claim H.264 patent safety.
//!
//! # Future direction
//!
//! A per-packet access-unit-boundary verifier lives in
//! `codec::avc::au_boundary` as a test-backed prototype. It is **not**
//! wired into the Trusted delivery path: audited wrappers keep zero extra
//! per-NAL work. The correct simplified check (H.264 7.4.1.2.3 / 7.4.1.2.4)
//! counts `first_mb_in_slice == 0` **order-independently** (ASO may delay
//! the macroblock-0 slice), treats AUD/SEI/SPS/PPS after VCL as the start
//! of the next AU, and fail-closes on redundant coded pictures, separate
//! colour planes, and VCL extension types 20/21. A "second VCL with
//! `first_mb == 0`" detector would mis-reject ASO and is not the algorithm.
//! Unaudited H.264 wrappers stay build-time rejected until that verifier
//! is enforced on a `ValidateBoundaries` path.
use HashMap;
use CString;
/// Video encoders verified to satisfy the strict-tier delivery contract.
///
/// Order is cosmetic (it is rendered into the whitelist error message);
/// membership is the contract. Keep [`STRICT_TIER_VIDEO_ALLOWED`] in sync —
/// a unit test enforces it.
pub const STRICT_TIER_VIDEO_ENCODERS: & =
&;
/// The comma-joined registry, rendered into the typed whitelist error
/// (`PacketSinkError::EncoderNotWhitelisted::allowed`).
pub const STRICT_TIER_VIDEO_ALLOWED: &str =
"libx264, h264_nvenc, h264_videotoolbox, libopenh264";
/// Whether `name` (an `AVCodec.name`) is admitted for strict-tier video.
pub
/// Packet-sink B-frame admission for VideoToolbox.
///
/// Verified VideoToolbox scope is `bf=0` (`dts == pts`). For keys `bf` and
/// `max_b_frames`, the value is ASCII-trimmed and parsed as `i32`: missing
/// keys are admitted, parsed `0` is admitted, any other integer or
/// unparseable value is rejected at build. Other registry entries are not
/// gated here — their B-frames still have to satisfy runtime `pts >= dts`.
/// `max_b_frames` is a **policy-recognized admission key only** — it is
/// *not* an FFmpeg `AVOption` alias of `bf`, so a leftover
/// `max_b_frames=0` does not set the encoder's `bf` field and does not by
/// itself guarantee `dts == pts`; only `bf` reaches the encoder. This helper
/// never rewrites `opts`. Unset keys therefore keep the wrapper default:
/// VideoToolbox / NVENC / OpenH264 default to no B-frames, but **libx264's
/// FFmpeg default is B-frames** (`bf` unset is typically 3).
///
/// Pass the **effective** option table (per-map keys overlay per-type keys).
pub
/// True iff `value` is an ASCII-trimmed `i32` equal to 0.
///
/// Unparseable input (empty, `"0.0"`, `"1b"`, non-UTF-8) returns false so
/// admission fail-closes. The option table is not mutated.