pub struct Encoder { /* private fields */ }Expand description
Video encoder. Build one with Encoder::new, feed it raw Frames via
encode, and publish the resulting Encoded access units
through a Producer built for the same Codec.
An encoder is bound to the thread that opens it. Use Sink
when the owner can move between threads.
fn move_to_another_thread(encoder: moq_video::encode::Encoder) {
std::thread::spawn(move || drop(encoder));
}Implementations§
Source§impl Encoder
impl Encoder
Sourcepub fn size(&self) -> Size
pub fn size(&self) -> Size
The resolution this encoder emits, which every frame fed to it must match.
Sourcepub fn bitrate(&self) -> Rate
pub fn bitrate(&self) -> Rate
The current target bitrate: what Config::bitrate resolved to at open, or
the last value set_bitrate accepted.
Sourcepub fn set_bitrate(&mut self, bitrate: Rate) -> Result<(), Error>
pub fn set_bitrate(&mut self, bitrate: Rate) -> Result<(), Error>
Retune the live encoder to bitrate, taking effect from roughly the next frame. No IDR is forced, so this is cheap enough to
drive from a congestion controller: pair it with
moq_mux::rate::Control, which decides when the target
is worth moving.
Setting the rate the encoder is already at does nothing and succeeds.
§Errors
Returns Error::BitrateUnsupported if this backend can’t retune while
running. That’s not fatal: the encoder keeps running at its current rate,
so a caller driving a control loop should stop adapting rather than stop
encoding.
Sourcepub fn codec(&self) -> Codec
pub fn codec(&self) -> Codec
The codec this encoder emits. A Producer must be
built for the same codec to publish its packets.
Sourcepub fn cut(&mut self) -> Result<(), Error>
pub fn cut(&mut self) -> Result<(), Error>
Cut a new group at the next frame, on top of the boundaries
Config::gop places on its own. Today that means encoding it as a
keyframe (an IDR), so a subscriber can start decoding there.
Rarely needed: the encoder opens groups automatically, so reach for this only when something outside the encoder needs a boundary at a specific frame. A source group boundary (transcode mirrors the source’s groups) is the usual reason; a scene change or a source switch is another.
The request waits for the next encode rather than applying
at once, so it is safe to call before the frame exists. Calling it repeatedly
before a frame arrives cuts once, not several times.
§Errors
Returns Error::CutUnsupported when this backend cannot force a group
boundary (a V4L2 driver without the force-keyframe control), in which case
nothing is queued: groups keep falling where Config::gop puts them, and
the caller decides whether that layout is acceptable rather than finding
out from the stream.
Sourcepub fn encode(&mut self, frame: &Frame) -> Result<Vec<Encoded>, Error>
pub fn encode(&mut self, frame: &Frame) -> Result<Vec<Encoded>, Error>
Encode one raw Frame, whether it came from capture, a decoder (the
transcode input path), or your own pixels via
Surface::rgba.
Returns zero or more encoded access units, each carrying the timestamp of the raw frame it came from: a backend that buffers hands back an earlier frame’s output, so the two don’t always line up.
A GPU surface feeds a hardware encoder on the same device directly
(NVDEC -> NVENC never leaves the GPU, a CVPixelBuffer goes straight to
VideoToolbox); anything else falls back to a CPU I420 upload. The frame must
already be at the encoder’s resolution: scale it with
Frame::resize, which
decode::Config::scale_hint lets a
hardware decoder make a no-op.
Sourcepub fn flush(&mut self) -> Result<Vec<Encoded>, Error>
pub fn flush(&mut self) -> Result<Vec<Encoded>, Error>
Return every access unit the codec is still holding, leaving the encoder ready for the frames that follow. Each keeps the timestamp of the raw frame it was encoded from, so a drained tail stays in step with what came before it.
Reach for this at a boundary the output has to respect, which for a live broadcast is a group: a hardware codec that pipelines holds the last frames of a group past its end, and they would otherwise be published into the next group ahead of its keyframe, where a consumer joining there cannot decode them. Publishing frame-by-frame with no group structure needs none of this.
Not free: emptying the pipeline gives up the overlap between one frame’s encode and the next frame’s submission, so flush at boundaries rather than per frame.
Sourcepub fn finish(self) -> Result<Vec<Encoded>, Error>
pub fn finish(self) -> Result<Vec<Encoded>, Error>
Flush the encoder, returning any buffered frames. Each keeps the timestamp of the raw frame it was encoded from, so a drained tail stays in step with what was published before it.
Consumes the encoder: nothing can be encoded after a flush, so this is the last call rather than one leaving a drained encoder in your hands.