Closed dmak closed 1 year ago
As documentation says - http://avisynth.nl/index.php/Levels Note in AVS+, the parameters input_low, input_high, output_low and output_high
are float instead of int. are not autoscaling ā they are relative to the current bit depth:
So for 10bit you need to use Levels(10_x_4, 1, 240_x_4, 0, 255_x_4)
where 10x4=40, 240x4=960, 255x4=1020
are not autoscaling ā they are relative to the current bit depth
Thanks, that indeed explains the behavior. Basically your explanation renders the issue invalid, however I still cannot get why the video passed through AVS looks more dim / pale (on the left) than original video (on the right). I didn't observe the issue with 8-bit video. Is it an issue with ffms2.dll
? I tried DirectShowSource()
instead of FFmpegSource2()
but it results the same negative effect. So I wonder if there is an alternative / better way to feed 10-bit HEVC video to AviSynth?
You work with PQ transfer, BT.2020 primaries and matrix - at any conversion stage you can fail with SDR/SCG display (also it is not known which display do you use for converting digital domain encoding into physical image). So it looks you simply fall into new-age HDR/WCG nighmare. Also all your attempt to show such files via internet may be invalid because internet may still run on 'old' sRGB colour image data encoding.
Better start to switch your video camera to SDR and 601/709 colour primaries and matrix and look for result. Next start to switch each param from 'old standard' and see where what happens.
AVS typically not change transfer/matrix/primaries but it is responsibility of enduser to track image encoding domain and use correct display or conversion tools. For example your software player may make auto-conversion for you at .mp4 file playback and AVS output do not have required metadata or your display/player do not understand it and so on. Lots of points to fail.
The only visible via internet - your player render to OS display surface .mp4 file and AVS file somehow differently. There may be tons of different reasons. Also you may ask player developer. Also that player-wrapper may use tons of internal conversion tools from other developers.
As some possible quick solution you may try to encode AVS output into .mp4 file with ffmpeg and provide manually all required HDR/WCG metadata (so MediaInfo of your source and encoded file at least in the fields of Color range : Limited Color primaries : BT.2020 Transfer characteristics : PQ Matrix coefficients : BT.2020 non-constant Mastering display color primaries : Display P3 Mastering display luminance : min: 0.0050 cd/m2, max: 1000 cd/m2
must match). And try to render encoded file with same player software.
You're right, the simplest way is to disable HDR10+ video in the Camera app settings:
The player I use is MPC-HC v1.9.8.65 (ee997206c), let me know if there is a better player that can take AVS as input and is also feature-rich.
What about downgrading the 10-bit video using
ConvertBits(8)
? Should AviSynth adapt video stream and meta information in that case?
Well, I am not sure I can correctly translate HDR metadata from MediaInfo input into ffmpeg
arguments, but I found this article which describes how to encode HDR10+ video using H.265 codec. Let's hope it works with AVS input š¤
"What about downgrading the 10-bit video using ConvertBits(8)?"
It not save from using different digital domain data encoding. If you need to run at SDR/SCG displays you need to convert transfer/matrix/primaries to the SDR/SCG system. There are several tools available in AVS. You can look into thread https://forum.doom9.org/showthread.php?t=183224&page=3 about possible conversion tools and issues.
"Should AviSynth adapt video stream and meta information in that case?"
No - AVS do not have internal tools for transfer/matrix/primaries conversions.
" if there is a better player that can take AVS as input and is also feature-rich."
I read ffmpeg can read AVS metadata (if you set it manually or your source plugin do ?). So may be ffplay can display somehow good (with proper conversion to your display). But you may not like simple command-line player software.
Well, you're right with that I need to pass the metadata to ffmpeg
and it generally worked fine:
ffmpeg.exe -i 20230407_160742.avs -c:v libx265 -x265-params "colorprim=bt2020:transfer=smpte2084:colormatrix=bt2020nc" -crf 28 -preset medium "output.mkv"
I also had to ask ChatGPT for help so somebody could use it for providing more explanations the same way:
P.S. Returning to original trap: would be great if AviSynth provides the function e.g.
Levels2()
which is bit-aware (and more difficult to mess up).
AVS have completely different levels mapping to number values in different samples values modes. For example float32 samples are not simply 16.0f..235.0f but 0.0f to 1.0f. That is very non-natural but programmers take this way. So Levels for floats have 0 to 1 black and nominal white levels. Also it is not single mapping rule - the black may be shifted and so on. I also suggest to add clip/frame property for levels mapping for floats :) .
FFplay does not tonemap HDR content on playback, for that you need mpv. VLC can probably do it too, but I wouldn't know how its settings might differ.
The remaining part of the problem is that the frame properties support in FFmpeg's AviSynth demuxer does not pass through dynamic metadata such as Dolby Vision or whatever other sorts of HDR+ formats there are, it only looks at the kinds of metadata that remain static throughout the clip (which is enough for 'standard' HDR10). For [most(?) types of] Dolby Vision you need to use a plugin like DoViBaker.
If/when the FFmpeg AviSynth demuxer can read RPU-related frame properties and set them for output, then all it would take is something that uses libplacebo (again, mpv) to detect and correctly reintegrate it on playback.
Also do documentation at http://avisynth.nl/index.php/Levels really correct for float32:
Nominal black and white 'limited/narrow' (from 8bits) mapped to 16/256 and 235/256 or to 0.0f and 1.0f ? Or depend on plugin and/or may be switched of ConvertBits() ? Or 'full' 0..255 8bit mapped to 0.0f and 255/256 ?
Video was created by Samsung mobile running Android 13.
AVS file demonstrating the issue:
Workaround:
The issue does not occur if
ConvertBits(8)
is called beforeLevels()
. Also when I removeLevels()
, the playback is just fine.Video description by MediaInfo:
ffmpeg report:
Side-by-side result (left is AVS, right is original MP4):
AviSynth+ v3.7.2-7290a6f
ffms2 v3.0.1.0 1325+16 6ad7738