Skip to content

Refactor VapourSynthDecoder to allow access to any output node - #18

Open
BoatsMcGee wants to merge 2 commits into
rust-av:mainfrom
BoatsMcGee:vapoursynth-get-output
Open

Refactor VapourSynthDecoder to allow access to any output node#18
BoatsMcGee wants to merge 2 commits into
rust-av:mainfrom
BoatsMcGee:vapoursynth-get-output

Conversation

@BoatsMcGee

@BoatsMcGee BoatsMcGee commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Adds a public (not pub(crate) ) method to VapoursynthDecoder to get a VideoNode at the specified index and optionally apply a node modifier. This requires the caller to know which index VapoursynthDecoder was instantiated with and have access to the registered node modifier, so 2 "getter" functions have been added.

The getter functions are the bare minimum to get output nodes exactly like Decoder gets. If Application A passes an already instantiated Decoder to Application B, Application B has no knowledge of what index or node modifier was used so it cannot retrieve the same (modified) output without changing its own API which could introduce unexpected behavior if there's a mismatch. The get_output method is just a convenience function that removes a lot of boilerplate without being restrictive.

Examples

Before:

let vapoursynth_decoder = decoder.get_vapoursynth_impl().expect("Decoder is VapourSynth");
let core = vapoursynth_decoder.env.get_core()?;
let output_node = vapoursynth_decoder.env.get_output(MAGIC_INDEX)?.0; // How does this app know the output index if it didn't instantiate Decoder itself?
let node = MAGIC_MODIFY_NODE(core, output_node)?; // How does this app access the same node_modifier that was consumed when Decoder was instantiated? It can't because Node and Core can't implement Copy so it can't be cloned even if you wanted.

After:

let vapoursynth_decoder = decoder.get_vapoursynth_impl().expect("Decoder is VapourSynth");
let reference_node = vapoursynth_decoder.get_output(vapoursynth_decoder.get_output_index(), vapoursynth_decoder.get_node_modifier())?; // Identical to the existing pub(crate) get_output_node method

PlaneStats:

let Some(vapoursynth_decoder) = decoder.get_vapoursynth_impl() else {
    warnings.push(anyhow::Error::new(NoiseDetectorError::InvalidInput));
    return Ok(((), warnings));
};
let reference_node = vapoursynth_decoder.get_output(
    vapoursynth_decoder.get_output_index(),
    vapoursynth_decoder.get_node_modifier(),
)?;
let denoised_node = vapoursynth_decoder.get_output(1, vapoursynth_decoder.get_node_modifier())?;

let node = PlaneStats::default().call(core, &reference_node, Some(&denoised_node))?;

Quality Comparison:

let Some(vapoursynth_decoder) = decoder.get_vapoursynth_impl() else {
    // Err
};
let reference_node = vapoursynth_decoder.get_output(
    vapoursynth_decoder.get_output_index(),
    vapoursynth_decoder.get_node_modifier(),
)?;
let distorted_node = vapoursynth_decoder.get_output(1, vapoursynth_decoder.get_node_modifier())?;

let node = SSIMULACRA2::default().invoke(core, &reference_node, &distorted_node)?; // Nodes must be in the same Core/Environment, otherwise this doesn't work
SSIMULACRA2::get_scores(&node, None, compare_progress_tx)?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant