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
//! Native video capture, encoding, and publishing for Media over QUIC.
//!
//! Counterpart to [`moq-audio`](https://crates.io/crates/moq-audio) for video
//! tracks, and shaped the same way: both split into `capture` / `encode` /
//! `decode` role modules over a shared root [`Error`], with `render` as video's
//! fourth. Sits on top of [`moq_mux`] (and the `hang` catalog) and adds the
//! native pieces a desktop/CLI publisher needs.
//!
//! A raw picture is a [`Frame`] wherever it crosses the API: a timestamp and a
//! [`Surface`] holding the pixels. Capture and [`decode`] produce them, [`encode`]
//! consumes them and hands back the compressed [`encode::Encoded`], and [`Size`]
//! names a resolution. Group boundaries are the encoder's business: it places
//! them per [`encode::Config::gop`], and [`encode::Encoder::cut`] is there for
//! the rarer case where a caller needs one at a specific frame.
//!
//! - `capture` describes a frame source and grabs frames per platform:
//! AVFoundation/ScreenCaptureKit on macOS, native V4L2 on Linux, native Media
//! Foundation (camera), DXGI Desktop Duplication (screen), and GDI (window) on
//! Windows, plus portal/PipeWire on Wayland and X11 capture on Linux. Use
//! `capture::open` for an embeddable raw-frame stream or
//! `encode::publish_capture` for turnkey publication. It requires the opt-in
//! `capture` feature, which costs the build host nothing on any platform.
//! - [`encode`] encodes frames with a native backend and publishes them through
//! the matching `moq_mux::codec` importer, which handles catalog registration
//! and framing. The codec is chosen via [`encode::Codec`]: H.264 (openh264 /
//! VideoToolbox / Media Foundation / NVENC / VAAPI / V4L2) or H.265
//! (VideoToolbox / Media Foundation / NVENC). Two entry points:
//! - `encode::publish_capture` captures a webcam and publishes it (turnkey).
//! It encodes strictly on demand: the track and catalog are advertised up
//! front (the camera opens once at startup so they can be exact), and the
//! encoder runs only while a subscriber is watching. Requires the `capture`
//! feature.
//! - [`encode::Encoder`] encodes [`Frame`]s you supply (from capture, a
//! decoder, or your own pixels via [`Surface::rgba`]) and
//! [`encode::Producer`] publishes the results.
//! - [`decode`] subscribes to an H.264, H.265, or AV1 track and decodes it to
//! raw frames with a native backend (VideoToolbox on macOS, Media Foundation /
//! DXVA on Windows, NVDEC, VAAPI, or an ARM SoC's V4L2 M2M decoder on Linux,
//! with the default `openh264` feature providing software H.264 fallback).
//! [`decode::Consumer`] is the mirror of `moq_audio::decode::Consumer`. An
//! [`decode::Config::output`] picks native surfaces (the default: an NVDEC
//! frame stays in CUDA memory and feeds [`encode::Encoder::encode`]
//! zero-copy, a VAAPI frame is a DMA-BUF the renderer imports) or CPU I420;
//! [`decode::Config::scale_hint`] lets a decoder with a hardware scaler emit
//! the output size directly.
//! - [`convert`] downloads readback-capable [`Surface`]s to owned, tightly packed
//! RGBA pixels for CPU image and UI toolkits, honoring native color metadata.
//! Vulkan/CUDA surfaces deliberately expose no CPU pixel fallback.
//! - `render` draws a [`Frame`] on the GPU and hands back a `wgpu` texture to
//! present, importing a GPU frame's surface directly where the platform
//! allows and uploading I420 otherwise. Behind the opt-in `render` feature,
//! so a codec-only consumer skips the graphics stack.
//!
//! ## API stability
//!
//! The public API is codec-agnostic: no public type, signature, or error
//! variant names a backend (openh264 / VideoToolbox / NVENC / NVDEC / VAAPI / V4L2) or a
//! codec implementation. [`encode::Encoder`] takes a [`Frame`],
//! [`decode::Consumer`] and `capture::Stream` return one (CPU I420 on demand,
//! GPU-resident when hardware decoded). So swapping
//! or bumping any backend crate is not a breaking change for consumers. Config
//! structs are `#[non_exhaustive]`: build them via `default()`/`new()` and set
//! fields, so new options stay additive.
//!
//! The one deliberate exception is [`Surface`], the enum behind every frame.
//! Its variants name platform representations (`CVPixelBuffer`, Direct3D11,
//! CUDA, Vulkan/CUDA, `AHardwareBuffer`) so you can render or re-encode a frame
//! yourself without a CPU round trip, which means a major bump of one of those
//! platform crates is a breaking change here. It is `#[non_exhaustive]` and
//! every variant has a universal fallback in [`Surface::into_i420`] except the
//! explicitly GPU-only `Surface::Vulkan`, so matching stays portable but a
//! CPU-only consumer can receive [`Error::Unsupported`].
// Only the threaded sinks use this, and both are compiled out on macOS, where
// the codecs run inline (no COM apartment to confine). Ungated it is dead code
// there, which `-D warnings` rejects.
pub use Color;
pub use Error;
pub use ;
pub use ;
pub use Output;
pub use ;
pub use Size;
/// The NDK bindings [`frame::android::HardwareBuffer::buffer`] hands back,
/// re-exported for the same reason as the Apple and Windows ones: name the
/// exact version this crate links rather than guessing at a matching one, since a
/// hardware buffer from a different `ndk` build is a different type. A major bump
/// here is a breaking change for this crate.
pub use ndk;
/// The CoreFoundation bindings owning the handle [`Surface::into_pixel_buffer`]
/// returns, re-exported alongside [`objc2_core_video`] for the same reason.
pub use objc2_core_foundation;
/// The CoreVideo bindings [`Surface::into_pixel_buffer`] hands back,
/// re-exported so you name the exact version this crate links rather than guessing
/// at a matching one. A major bump here is a breaking change for this crate.
pub use objc2_core_video;
/// The Direct3D11 bindings [`frame::d3d11::Texture`] hands back, re-exported for
/// the same reason as the Apple ones above: name the exact version this crate
/// links rather than guessing at a matching one, since a device and a texture
/// from a different `windows` build are different types. A major bump here is a
/// breaking change for this crate.
pub use windows;