media-pp 0.2.0

A small, GStreamer-flavored media pipeline library built on FFmpeg. Capture, composite and encode without leaving the GPU, on D3D11 and CUDA.
Documentation
// D3D11 chroma-key shader for D3d11ChromaKey — draws one BGRA input
// texture as a screen-covering triangle (the same vertex trick as
// composite_bgra.hlsl, and for the same reason: a full-target draw needs
// no vertex buffer) into an equally sized BGRA render target, passing RGB
// through untouched and replacing alpha with the keyed value.
//
// The band is handed over already resolved into `band_low`/
// `inv_band_width` rather than as the `threshold`/`smoothing` the caller
// set. That keeps the per-pixel work to one subtract, one multiply and a
// saturate, and — because a hard key arrives as an effectively infinite
// `inv_band_width` — reproduces SwChromaKey's un-feathered step exactly
// without a per-pixel branch or a division by zero. See
// `ChromaKeyConstants::new` for how the two are derived.

struct VertexOutput
{
    float4 position : SV_Position;
    float2 uv : TEXCOORD0;
};

VertexOutput vs_main(uint vertex_id : SV_VertexID)
{
    VertexOutput output;
    output.uv = float2((vertex_id << 1) & 2, vertex_id & 2);
    output.position = float4(
        output.uv.x * 2.0 - 1.0,
        1.0 - output.uv.y * 2.0,
        0.0,
        1.0
    );
    return output;
}

cbuffer ChromaKeyBuffer : register(b0)
{
    float3 key_color;
    float band_low;
    float inv_band_width;
    float3 _padding;
    // The visible fraction of the input texture, for the same reason
    // composite_bgra.hlsl has one: a decoder pads its surfaces up to its
    // own alignment and that padding is not part of the picture.
    float2 uv_scale;
    float2 _uv_padding;
};

Texture2D<float4> bgra_texture : register(t0);
SamplerState key_sampler : register(s0);

float4 ps_chroma_key(VertexOutput input) : SV_Target
{
    float4 color = bgra_texture.Sample(key_sampler, input.uv * uv_scale);
    // Euclidean RGB distance to the key color, scaled so opposite corners
    // of the color cube are 1.0 — the same measure SwChromaKey's
    // `color_distance` computes on the CPU, so one ChromaKeyOptions means
    // the same thing to both backends.
    float distance = length(color.rgb - key_color) / sqrt(3.0);
    float alpha = saturate((distance - band_low) * inv_band_width);
    return float4(color.rgb, alpha);
}