11# Native H.264 codecs for moq-video (drop ffmpeg)
22
33Status: ** phases 2-5 implemented** (openh264, VideoToolbox, NVENC, capture swap +
4- ffmpeg removal). VAAPI (phase 6) is a separate follow-up PR. See "As built"
5- at the bottom for where the implementation diverged from this plan.
4+ ffmpeg removal). Capture is now native on all three platforms (AVFoundation /
5+ ScreenCaptureKit on macOS, V4L2 on Linux, Media Foundation on Windows), so
6+ ** nokhwa is fully removed** . VAAPI (phase 6) stays parked until cros-codecs
7+ builds against modern libva. See "As built" at the bottom for where the
8+ implementation diverged from this plan.
69
710## Goal
811
@@ -329,10 +332,15 @@ Where the implementation differs from the plan above:
329332 negotiated resolution, so capture frames already match the encoder; ` encode_rgba `
330333 now requires input dims == encoder dims (it errors otherwise) instead of
331334 rescaling. This dropped swscale entirely.
332- - ** Capture (nokhwa) yields RGBA.** ` Camera::read ` decodes each frame to RGBA via
333- ` decode_image::<RgbAFormat> ` , uniformly handling MJPEG/YUYV/NV12 sources. Device
334- string is now "bare integer = index, else path/name" (the avfoundation ` :none ` /
335- dshow ` video= ` specifics are gone).
335+ - ** Capture is per-platform native (nokhwa fully removed).** Each platform's
336+ ` Camera::read ` yields a ` Frame ` the encoder can take: macOS hands VideoToolbox a
337+ zero-copy ` CVPixelBuffer ` surface, Linux V4L2 and Windows Media Foundation hand
338+ the software/NVENC path a CPU ` I420 ` . macOS AVFoundation/ScreenCaptureKit and
339+ Linux V4L2 (YUYV resampled, MJPEG via ` zune-jpeg ` ) landed first; Windows uses an
340+ ` IMFSourceReader ` with its video processor enabled to coerce the camera's native
341+ format to NV12, which we deinterleave to I420 (` I420::from_nv12 ` ). The device
342+ string is uniform: "bare integer = index, else path/name" (a friendly-name
343+ substring on Windows).
336344- ** ` Error ` slimmed.** The ffmpeg-specific variants (` Ffmpeg ` , ` NoCaptureBackend ` ,
337345 ` NoVideoStream ` ) and the ` From<ffmpeg_next::Error> ` impl are removed; capture and
338346 encode failures now flow through ` Error::Codec(anyhow) ` .
@@ -350,6 +358,15 @@ Where the implementation differs from the plan above:
350358 default - feature unification here may need tweaking; (2) the flat input-buffer
351359 ` write ` matches NVENC's pitch (safe only for 64-aligned widths; we warn otherwise);
352360 (3) forced-IDR via ` picture_type ` with picture-type-decision enabled.
361+ - ** Windows Media Foundation capture is UNVERIFIED on hardware.** The ` windows `
362+ 0.62 FFI is fully type-checked against the ` x86_64-pc-windows-msvc ` target (the
363+ whole crate can't cross-compile from the dev Mac because openh264's vendored C++
364+ build needs MSVC, but a scratch crate confirms every Media Foundation call), and
365+ the COM/refcount lifecycle is reviewed. Still needs a real Windows + webcam run
366+ to confirm: (1) the source reader's video processor actually delivers NV12 for
367+ common cameras (MJPEG/YUY2 sources); (2) ` IMF2DBuffer::ContiguousCopyTo ` yields
368+ unpadded NV12 so the I420 deinterleave is correct; (3) the on-demand
369+ open/` source.Shutdown() ` cycle releases the camera (LED off) and reopens cleanly.
353370
354371### VAAPI removed (cros-codecs is not buildable on modern libva)
355372
@@ -406,8 +423,9 @@ can carry NVENC and use it only where the driver is present. Upstream the
406423 because its SDK crate has no macOS bindings (see ` rs/justfile ` 's ` ci ` recipe).
407424- Still needed on real hardware: NVENC encode validation on a Linux+GPU box (pitch
408425 alignment, forced-IDR); only synthetic-frame software encode is tested here.
409- - Live camera run (capture needs camera/screen TCC permission, which a headless or
410- agent-spawned process can't obtain; run ` moq-cli ... capture ` from a user terminal).
411- - ` doc/bin/cli.md ` : the ` capture ` device-string semantics changed (index-or-path).
426+ - Live camera run (capture needs camera/screen permission, which a headless or
427+ agent-spawned process can't obtain; run ` moq-cli ... capture ` from a user
428+ terminal). On Windows this is also where the Media Foundation path gets its
429+ first real exercise (see the unverified note above).
412430- Consider reusing NVENC input/output buffers across frames (currently allocated
413431 per frame to sidestep the self-referential Session borrow).
0 commit comments