pub struct D3d11NvencEncoder { /* private fields */ }d3d11 only.Expand description
Encodes GPU-resident Pixel::D3D11 Video frames into Packets on the
GPU’s dedicated NVENC block — the hardware counterpart to
crate::elements::SwEncoder, for a pipeline built entirely on one
shared ID3D11Device (see crate::elements::D3d11Renderer’s own docs
on why that means no explicit fence/sync is needed anywhere in this
stack). A Filter: receives via Sink, pushes what it produces into
its own single src pad.
§Why the input texture is copied rather than handed over directly
NVENC needs AVCodecContext.hw_frames_ctx set before avcodec_open2,
and every frame passed to send_frame must come from that context’s
own pool. The Pixel::D3D11 frames flowing through this crate don’t:
crate::elements::D3d11Upload,
crate::elements::DxgiCaptureSource’s GPU mode and
crate::elements::D3d11VideoCompositor all build their textures with
plain windows-rs calls and wrap them via
d3d11va_decoder::wrap_d3d11_texture, deliberately bypassing FFmpeg’s
frames-context machinery altogether (that function’s own docs explain
why: driving it from a hand-mirrored AVD3D11VAFramesContext* corrupted
memory badly enough to trip /GS).
So consume takes the other route: it lets libavutil allocate and own
the encoder’s input pool through the ordinary, publicly documented
av_hwframe_ctx_alloc/av_hwframe_ctx_init/av_hwframe_get_buffer
API — touching only bindgen-generated AVHWFramesContext fields, never
the D3D11VA-specific struct that has no binding — and copies each
incoming texture into a pool texture with CopySubresourceRegion.
That copy never leaves the GPU. It replaces the
D3d11Download → Scaler → SwEncoder chain that was previously the
only way to record a GPU-resident stream, which read every frame back
over PCIe, converted it on the CPU, and encoded it on the CPU.
§Frame delay
One frame can turn into zero or one packets per send_frame — NVENC’s
lookahead and B-frame reordering delay some packets until later frames
arrive, or until Eos flushes what’s left. consume drains
receive_packet in a loop after every send_frame/send_eof, the same
shape as crate::elements::SwEncoder’s own drain loop.
Implementations§
Source§impl D3d11NvencEncoder
impl D3d11NvencEncoder
Sourcepub fn new(
name: impl Into<String>,
device: &ID3D11Device,
context: Arc<Mutex<ID3D11DeviceContext>>,
options: D3d11NvencEncoderOptions,
) -> Result<Self, D3d11NvencEncoderError>
pub fn new( name: impl Into<String>, device: &ID3D11Device, context: Arc<Mutex<ID3D11DeviceContext>>, options: D3d11NvencEncoderOptions, ) -> Result<Self, D3d11NvencEncoderError>
device must be the same ID3D11Device, and context the same
shared immediate context, every other D3D11 element in this pipeline
uses — see this type’s own docs on why.
Opens the encoder eagerly, so a missing h264_nvenc/hevc_nvenc, a
driver too old for the linked ffmpeg’s NVENC API version, or a
resolution this GPU’s encode block rejects all surface here as a
typed error rather than at the first frame.
Sourcepub fn parameters(&self) -> Parameters
pub fn parameters(&self) -> Parameters
This encoder’s own codec parameters — what a
crate::elements::Mp4Muxer track needs when there’s no
container/demuxer in the loop to get them from, same as
crate::elements::SwEncoder::parameters.
Trait Implementations§
Source§impl Drop for D3d11NvencEncoder
impl Drop for D3d11NvencEncoder
Source§impl Element for D3d11NvencEncoder
impl Element for D3d11NvencEncoder
Source§fn name(&self) -> Arc<str> ⓘ
fn name(&self) -> Arc<str> ⓘ
crate::bus::BusEvent stores names as
Arc<str> for exactly this reason: a hot path like
crate::queue::Queue posting BusEvent::Dropped once per
overflowed buffer shouldn’t pay for a fresh heap allocation every
time it wants to report which element it is.Source§fn element_type(&self) -> ElementType
fn element_type(&self) -> ElementType
ElementType.Source§fn pp_log(&self) -> &PpLog
fn pp_log(&self) -> &PpLog
crate::bus::Bus::post — same
id/name as Element::name, just already wrapped as the
crate::pp_log::PpLog its pp_info!/pp_warn!/pp_error! macros need. A
stored private field, not built fresh per call, for the same reason
name() returns a cheap Arc<str> clone instead of a fresh String
— see its own docs.Source§fn pp_log_mut(&mut self) -> &mut PpLog
fn pp_log_mut(&mut self) -> &mut PpLog
Element::pp_log reads — used by
crate::pipeline::ChainBuilder to stamp the owning
crate::pipeline::Pipeline’s id onto every element that
passes through it, via element_pp_log. Not meant to be called
from anywhere else.impl Send for D3d11NvencEncoder
Source§impl Sink for D3d11NvencEncoder
impl Sink for D3d11NvencEncoder
fn consume(&mut self, buf: MediaBuffer) -> Result<()>
Source§fn control(&mut self, msg: ControlMsg) -> Result<()>
fn control(&mut self, msg: ControlMsg) -> Result<()>
ControlMsg (pause/resume/stop) and, for anything
with a downstream of its own, forwards it on — same shape as
consume, just a separate channel from MediaBuffer so it can
reach every element (not just ones that already know how to
interpret a data buffer) and, at a crate::queue::Queue, jump
ahead of whatever data is backed up instead of waiting behind it.
No default: every Sink has to consciously decide what this means
for it, rather than silently dropping it.