Welcome to Doom9's Forum, THE in-place to be for everyone interested in DVD conversion.

Before you start posting please read the forum rules. By posting to this forum you agree to abide by the rules.

 

Go Back   Doom9's Forum > Video Encoding > VP9 and AV1

Reply
 
Thread Tools Search this Thread Display Modes
Old 20th May 2022, 21:08   #1  |  Link
BuccoBruce
Registered User
 
Join Date: Apr 2022
Posts: 25
Potentially stupid aomenc grain synthesis questions...

Is there any way to "trick" aomenc, or preferably aom-av1-psy, into utilizing grain synthesis by analyzing a grainy, untouched source but actually encoding video that was de-grained or de-noised externally?

I use --enable-dnl-denoising=0 with aom-av1-psy, per BlueSwordM and many others' suggestions, because the encoder's own denoising is a bit much, and having only 1 parameter to tune for it isn't enough. It leaves a lot to be desired.

Something like SMDegrain with a KNLMeansCL pre-filter pass, and appropriate parameters for both, can output a de-grained/DNR video that is vastly superior to what sometimes seems like either completely automated or excessive "professionally done" smeary and waxy DNR present in finished Blu-Rays. Adding some dither noise back in after working in 16-bit color and optionally de-banding if needed can help prevent new banding, with any number of decent AVS/VapourSynth debanding filters.

If I take video processed in this manner and pass it on through to aomenc with --enable-dnl-denoising=0, the grain synthesis function seems like it only acts on that dither noise, if it even acts at all. It doesn't know about the grain that I removed, because...well, how could it? It never saw the grain. If I try to crank --denoise-noise-level up, it starts to look like x265 does at slower presets with --psy-rdoq turned up too high: ugly artificial noise.

Does the encoder make the grain synthesis "decisions" - or at least the pattern and strength, exclusively during the 1st pass? If so, would it be feasible to conduct the first pass pointed at an AVISynth/VapourSynth script that has all the de-band/de-grain processing commented out, and then pull the old switcheroo and actually encode the 2nd pass pointing at a fully pre-processed source?

If that could work, would actually using --enable-dnl-denoising=1 during this jape of a first pass help it make better rate control decisions? Can --enable-dnl-denoising even be set differently on pass 1 and pass 2? I wouldn't want to actually encode the 2nd pass with it set to anything but =0, especially if I'm doing my own external filtering. If it can't be switched, forcing SMDegrain or KNLMeansCL to run with lower spatial filtering might leave a "static" grain "texture", albeit likely pretty blotchy, in the source that it could use?

I hope that makes sense. I also thought of an alternative, ridiculous strategy, but it involves:
  1. Fully encoding the video twice, once with no external filtering and --enable-dnl-denoising=1, once with the external filtering and --enable-dnl-denoising=0, both with the same --denoise-noise-level,
  2. Using a likely non-existent tool to check the AV1 bitstream of both,
  3. Hack the frame level grain synthesis data from the former encode into the latter.
So uh, unlikely, if not impossible. And also excessively time consuming.

I tried searching for an answer, and all I could find was excitement about using photon grain synthesis. That doesn't seem to help with the idea of encoding externally filtered video but trying to use grain synthesis to mimic the original grain pattern and strength, unless I just can't make the connection there.
BuccoBruce is offline   Reply With Quote
Old 27th May 2022, 18:06   #2  |  Link
Beelzebubu
Registered User
 
Join Date: Feb 2003
Location: New York, NY (USA)
Posts: 98
Quote:
Originally Posted by BuccoBruce View Post
Is there any way to "trick" aomenc, or preferably aom-av1-psy, into utilizing grain synthesis by analyzing a grainy, untouched source but actually encoding video that was de-grained or de-noised externally?
Check examples/noise_model, it can create a grain table which represents the difference between a "noisy" and "denoised" source, and the resulting grain table can be input into aomenc using the --film-grain-table argument.
Beelzebubu is offline   Reply With Quote
Old 28th May 2022, 01:59   #3  |  Link
BuccoBruce
Registered User
 
Join Date: Apr 2022
Posts: 25
Quote:
Originally Posted by Beelzebubu View Post
Check examples/noise_model, it can create a grain table which represents the difference between a "noisy" and "denoised" source, and the resulting grain table can be input into aomenc using the --film-grain-table argument.
Thank you for pointing me in the right direction!

"/examples/noise_model.c"? Oh God, it's code!

All joking aside, looking at the comments in the code (wow, this is really well documented...) this looks like exactly what I described! If I'm reading CMakeLists.txt correctly, I just need to make sure to add -DENABLE_EXAMPLES=1 to my cmake command. cmake .. -G "Visual Studio 16 2019" -DENABLE_EXAMPLES=1 and then cmake --build .. Easy enough, I'll have a noise_model.exe waiting for me in an "examples" subfolder in my build directory, right?

Needing two .yuv inputs is definitely going to limit what I can do with this. Using ffmpeg itself to pipe .yuv is easy enough, but even then I'd still need to hog ~60 GB up (at least for what I want to test out) somewhere for keeping the degrained output around as raw .yuv. Normally if I needed to access filtered output twice I'd just use FFV1 or something, and it would save time to filter once and then re-use that same output for grain analysis and encoding, but that doesn't help me much. I'd still need a way to pipe FFV1 -> YUV to the grain analysis alongside source -> YUV.

Now I can see why those x264/x265 mods that can read AviSynth input directly exist.
BuccoBruce is offline   Reply With Quote
Old 28th May 2022, 03:04   #4  |  Link
benwaggoner
Moderator
 
Join Date: Jan 2006
Location: Portland, OR
Posts: 4,218
Yes, this should absolutely work. The grain synthesis model is really sidecar metadata and a post-decode renderer. It's nothing encoding or AV1 specific.
__________________
Ben Waggoner
Principal Video Specialist, Amazon Prime Video

My Compression Book
benwaggoner is offline   Reply With Quote
Old 29th May 2022, 04:53   #5  |  Link
BuccoBruce
Registered User
 
Join Date: Apr 2022
Posts: 25
Mods, if my choice of sample is problematic, please let me know. I deliberately chose a clip that Warner Bros has uploaded on one of their YouTube channels. https://youtu.be/bSDzrTgulms?t=6 It's a ~90 second excerpt of "Baseball Bugs" from 1946 - I might have included less than 1 second extra, as I cut the m2ts on a keyframe + scene-change before starting.



Source Video
Do note that there are several instances of what I thought was my DNR being too strong present in the source, like the screenshot above. I spent more time than I had to tweaking my script before I thought to check what it actually looked like, and I probably could've filtered more strongly as a result.
It is very grainy on the Blu-Ray, and 20 Mbps seems like it wasn't enough, because at times it looks like grainy artifacts rather than grain. The YouTube clip is a good enough example for checking what a much higher level of compression does to video this grainy - the grain texture is gone entirely and it's just strobing artifacts.
Perhaps they de-grained it before uploading it, but the few shorts I checked on Boomerang/Amazon Prime seemed to be from the same masters without any significant DNR, albeit at 25 fps. Probably an EU broadcast master. This is untouched from a Blu-Ray, other than AC3->AAC for the audio.

Filtered + noise_model.exe generated table AV1 output
It's not perfect, and I think noise_model might have latched onto some of the encoding artifacts instead of the grain itself at times, but it looks a lot better than I thought it would! If you pause, it falls apart rather quickly because you can easily see how/where the grain pattern repeats, whereas a still frame with the "actual" grain is far less offensive.
4 Mbps is a bit much though, q18 was probably too high. Seems like it would work better with a higher quality source. Debug output from noise_model is unfortunately only possible with 8pp. MEGA mirror.

Filtered output (~1.5 GB FFV1)
I am far from an expert with video filtering, and I'd rather not share my AVISynth script (because it's embarrassing, not because I think highly of it) but if you want to reproduce this, tweak SMDegrain, pre-filter with KNLMeansCL.your spatial smoother of choice, make use of "CClip" in SMDegrain, and maybe mfilter pointing at your prefiltered_clip.DFTTest/neo, with a very high sigma and a tbsize of 1. It ran like molasses, and feeding this script directly to AOMEnc would've actually had me waiting on the frame server rather than the encoder.

noise_model.exe can't read from stdin, so no piping is possible at all. It ran at about 1.5-2 FPS (~20 minutes for 1m18sec, I didn't time it, stderr output showed time in seconds * 10000000) and is definitely single threaded. The noise table .tbl file looks like a bunch of arrays/matrices, you can open it just fine in a text editor. Command line plus the first two sets of sample output, and then the whole file:
PHP Code:
noise_model.exe --fps=24000/1001 --width=1440 --height=1080 --i420 --bit-depth=10
--output-grain-table=00095-m2ts-Baseball_Bugs.tbl
--input-denoised=P:\00095-m2ts-Baseball_Bugs_out.yuv
--input=00095-m2ts-Baseball_Bugs_cropped.yuv

filmgrn1
E 0 417083 1 7391 1
    p 3 7 0 10 0 1 128 192 256 128 192 256
    sY 8  0 85 27 86 94 124 121 135 202 139 215 128 242 112 255 112
    sCb 4 0 14 108 20 215 29 255 27
    sCr 3 0 18 188 27 255 23
    cY 
-4 9 -15 22 4 1 -2 7 -21 38 -53 -12 2 3 -14 43 -78 92 12 --2 25 -70 109
    cCb 2 
--1 2 1 0 --2 8 4 -13 -7 2 1 2 7 -61 93 6 -2 1 3 -20 92 -5
    cCr 3 
--3 5 1 1 1 -3 7 9 -17 -7 2 1 0 7 -63 94 8 -2 0 3 -19 93 -5
E 417083 834166 1 0 1
    p 3 7 0 10 0 1 128 192 256 128 192 256
    sY 10  0 94 27 95 67 114 94 132 148 154 188 150 202 142 215 129 229 111 255 109
    sCb 4 0 14 108 19 242 26 255 26
    sCr 3 0 18 148 23 255 19
    cY 
-1 7 -10 17 4 0 1 6 -20 36 -53 -6 1 1 -11 38 -67 90 7 -4 0 19 -59 97
    cCb 0 
-1 2 -2 1 1 --2 6 ---7 2 1 2 --42 78 10 0 1 1 -10 83 -1
    cCr 0 
-2 5 -3 1 1 0 -1 7 ---7 0 1 3 --43 82 12 1 ---9 84 -
00095-m2ts-Baseball_Bugs.tbl

aom-av1-psy command line:

PHP Code:
aom-av1-psy.exe --limit=1889 --passes=--pass=--fps=24000/1001 --width=1440 --height=1080 --end-usage=--cq-level=18
--sharpness=--good --verbose --bit-depth=10 --input-bit-depth=10 --webm --threads=24 --sb-size=64
--enable-fwd-kf=--kf-min-dist=12 --kf-max-dist=240 --cpu-used=--auto-alt-ref=--tile-columns=--enable-tpl-model=1
--arnr-strength=--lag-in-frames=64 --enable-qm=--qm-min=--quant-b-adapt=--enable-keyframe-filtering=--enable-chroma-deltaq=0
--aq-mode=--deltaq-mode=--enable-dnl-denoising=--film-grain-table=00095-m2ts-Baseball_Bugs.tbl --disable-trellis-quant=0
--frame-boost=--coeff-cost-upd-freq=--mode-cost-upd-freq=--mv-cost-upd-freq=--tune-content=animation
--color-primaries=bt709 --transfer-characteristics=bt709 --matrix-coefficients=bt709 --fpf=00095-m2ts-Baseball_Bugs.fpf
-o 00095-m2ts-Baseball_Bugs_out.webm P:\00095-m2ts-Baseball_Bugs_out.yuv 
noise_model.exe and aomenc.exe were built from full-aom-av1-psy-0.1.4-alpha using Visual Studio 2019.

Quote:
Originally Posted by benwaggoner View Post
Yes, this should absolutely work. The grain synthesis model is really sidecar metadata and a post-decode renderer. It's nothing encoding or AV1 specific.
It works!

Last edited by BuccoBruce; 29th May 2022 at 05:03. Reason: MEGA can't hotlink AV1...
BuccoBruce is offline   Reply With Quote
Old 29th May 2022, 13:21   #6  |  Link
Beelzebubu
Registered User
 
Join Date: Feb 2003
Location: New York, NY (USA)
Posts: 98
Quote:
Originally Posted by BuccoBruce View Post
Needing two .yuv inputs is definitely going to limit what I can do with this.
It's because you use Windows. On Mac/Linux, people use FIFOs for this (mkfifo).

[edit] But nice to hear you got it working! The output will indeed rely a lot on the quality of the filtering, so it'll never be quite perfect, but it has some significant advantages over R/D encoding of the grain.
Beelzebubu is offline   Reply With Quote
Old 29th May 2022, 18:09   #7  |  Link
BuccoBruce
Registered User
 
Join Date: Apr 2022
Posts: 25
Quote:
Originally Posted by Beelzebubu View Post
It's because you use Windows. On Mac/Linux, people use FIFOs for this (mkfifo).

[edit] But nice to hear you got it working! The output will indeed rely a lot on the quality of the filtering, so it'll never be quite perfect, but it has some significant advantages over R/D encoding of the grain.
A Windows program that used Win32 "Named Pipes" could work but it's probably not worth the effort vs. just using Linux.
BuccoBruce is offline   Reply With Quote
Reply

Tags
aomenc, av1, enable-dnl-denoising, grain, grain synthesis

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +1. The time now is 21:11.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2022, vBulletin Solutions Inc.