Skip to main content

D3d11NvencEncoder

Struct D3d11NvencEncoder 

Source
pub struct D3d11NvencEncoder { /* private fields */ }
Available on Windows and crate feature 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 D3d11DownloadScalerSwEncoder 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

Source

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.

Source

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

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

fn pin_drop(self: Pin<&mut Self>)

🔬This is a nightly-only experimental API. (pin_ergonomics)
Execute the destructor for this type, but different to Drop::drop, it requires self to be pinned. Read more
Source§

impl Element for D3d11NvencEncoder

Source§

fn name(&self) -> Arc<str>

Returns a cheap clone (refcount bump, not a deep copy) of this element’s name — 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

Source§

fn pp_log(&self) -> &PpLog

This element’s identity for 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

Mutable access to the same field 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.
Source§

fn graph_id(&self) -> Option<ElementId>

A pre-reserved graph identity for elements that expose dynamic attachment handles. Most elements receive an ID from ChainBuilder and keep the default None implementation.
Source§

impl Send for D3d11NvencEncoder

Source§

impl Sink for D3d11NvencEncoder

Source§

fn consume(&mut self, buf: MediaBuffer) -> Result<()>

Source§

fn control(&mut self, msg: ControlMsg) -> Result<()>

Reacts to a 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.
Source§

impl Source for D3d11NvencEncoder

Source§

fn src_pads(&mut self) -> &mut [SrcPad]

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> Filter for T
where T: Source + Sink,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more