master-of-zen / Av1an

Cross-platform command-line AV1 / VP9 / HEVC / H264 encoding framework with per scene quality encoding
GNU General Public License v3.0
1.4k stars 147 forks source link

Implement pipeless scene detection for Vapoursynth inputs #844

Closed shssoichiro closed 1 month ago

shssoichiro commented 1 month ago

See https://github.com/rust-av/av-scenechange/pull/168

By avoiding piping, we gain significant performance improvements. The amount of improvement varies depending on the source video format, as this moves the bottleneck to be on the decoder, but tests showed anywhere from 20-75% improvement on 8-bit for the fast scenechange method, with smaller but still respectable improvements of up to 20% for 10-bit and for the standard scenechange method, compared to piping from vspipe.

Currently, this implementation is limited to Vapoursynth inputs, and does not work when using ffmpeg filters through av1an (this will fall back to using pipes).

redzic commented 1 month ago

Looks good although I believe this isn't fully zero copy. My old branch was using some unsafe trickery to bypass calling copy_from_raw_u8 in av-scenechange when constructing Frame. However this is still a big improvement over the current code. Perhaps an ideal solution would be to have a separate crate outside of rav1e (so it doesn't have frame padding requirements) for scene detection which is able to take references to frame data directly, instead of either owned frames or unsafe trickery.

IIRC the luma planes were never read for scene detection, so another easy improvement would perhaps be to avoid copying the chroma planes in av-scenechange for the purposes of scene detection and just fill those values with empty planes instead.

shssoichiro commented 1 month ago

I'll have to check on that last part, that's a smart idea if true... I'm sure it is for the fast method, I'll have to check if chroma is ignored for the standard method as well.

And yeah, this isn't truly zero copy, but avoiding the pipe is a large improvement. Unfortunately there's not currently a way to do the standard scene change method without padding, because rav1e requires padding to do its motion estimation (part of the inter cost estimation process). We would need to rework rav1e's motion estimation to not require padding, which is something I've looked into before but it's more complicated than it sounds because there's a lot of different pieces to it.

shssoichiro commented 1 month ago

Merging this for now, I'll make a second PR for the chroma planes change if it looks like it'll work.

redzic commented 1 month ago

We would need to rework rav1e's motion estimation to not require padding, which is something I've looked into before but it's more complicated than it sounds because there's a lot of different pieces to it.

The solution I had to this on my old PR with non-VS inputs (ie regular videos) was to configure the padding on the FFmpeg-decoded frames so rav1e has no issue with them. It was actually quite simple to do with FFmpeg, but I never found any documentation to do that with Vapoursynth.