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 > Capturing and Editing Video > Avisynth Usage

Reply
 
Thread Tools Search this Thread Display Modes
Old 24th December 2015, 02:53   #1  |  Link
geometer
Registered User
 
Join Date: Dec 2015
Posts: 59
Removing the Veil, using GeneralConvolution()

To me it seems, that convolution is rarely mentioned, but I found it remarkably powerful for my needs, when I archive DVDs in h264 format.

I would like to share a case study here, to make customized convolution more popular. The GeneralConvolution filter runs in AviSynth, therefor I post it here.

Source material: DVD, NTSC 720x480, mostly interlaced 29.97 fps. Video, not film.
Target: h264 mp4, optionally upsampled to 960x640.

Main technique in this topic is convolution, the primary filtering chain runs in AviSynth.
I will share some asymmetric matrices (kernels) in the script below.

(I also included a code example, for to try out a short sequence of the source with various different kernels.
Probably, only one or two of those will work well, when we are interested in subtle quality.)

This is then embedded in a secondary filtering chain in AviDemux, for its simplicity to adjust parameters.
The chain is constructed so, that it becomes easy to correct typical flaws, plus - which is important part of the case study -
in the complete chain, there is a complex attempt to achieve some synergy with the encoder.

------
In the secondary chain, AviDemux, the following techniques have been added:
- Upsampling, at first to a ~1600x960, on that level we do
-- general sharpening and color sharpening (effectively, we get a smaller sharpening radius, doing it here.)
-- color shift corrections on subpixel level
-- color and contrast corrections
- Final upsampling domain is 960x640, to mitigate influence by the brickwalling filters of the various players, that may not be optimals for CPU speed reasons.
- A final convolutional sharpener (preset of AviDemux), but it should obviously be deleted in case the result looks oversharpened.
- A preset for the x264 encoder is included here, that has been adapted to this project.

Naturally, we can omit the secondary chain and just crop (as the asymmetric matrix will shift the picture and there are borders added for this), and encode directly.
But I recommend to check the special synergies with the full chain.


Result discusson:
I found that without additional work, a direct transcode seems to look a bit blurred, even though a high bitrate is allocated.
There is a convolutional sharpener in AviDemux that is used additionally, but it can't be customized.

What the customized matrix does, is a combined set of adjustments, that were checked out heuristically with hundreds of trial/error attempts.
- we use the 5x5 matrix in an asymmetric way, so this yields us 4 coefficient taps in the filtering, which is a lot more precision than the usual 3x3 symmetric kernel.
- obviously, it does some sharpening
- "deconvolution"; in quotes, as it is done from experience, not with proper math (for we don't have the modeling data).
-- it should mitigate influences starting from the camera lense to postprocessing to encoding and reencoding steps.
- some attempts to soften deinterlacing artifacts, this combines well with the upsampling.

The encoder is being slammed with enhanced detail range, in a way that it should better recognize small structures in the picture, and treat these as moving blocks, further enhancing clarity by averaging those sharp details down to a "normal" level. Otherwise it seems, that the encoder often cannot recognize the structures from noise, as they carry mpeg2 artefacts, and it will blur them.
For the sensitivity of the analyzer on these details, plus for preserving textures, a certain optimization in the x264 encoder is being turned off.


The sum of these techniques makes the video look "different".
It will get extra clarity, smoothness, and a particular shine and gloom, that resembles pop music videos, which even works with sources that may look a bit blurred and pale.
The fine-tuning of course has influence on that "pop look".
(But to completely remove the different looks, I recommend to delete the extra color sharpener, perhaps all color and contrast filters, or even the whole secondary chain.)

So, there are two aspects in the result:
Crisp sharpness, and the smooth "pop look".

Artifacts:
Halo and ringing already in the source might increase, but quite little of such would be added, with the correct choice of the matrix, and avoiding oversharpening (controlled by the optional final sharpener at the end of the secondary chain.)
Sometimes the kernel can even cancel out certain ringing.
Please, note that in linear processing, tuned deconvolution can remove ringing, because the ringing is actually the "Gibb" phenomenon, that comes from non-ideal (finite) filtering of a rectangular signal. If we transmit a digital rectangular signal, its bandwidth must be limited beforehand, i.e. it becomes "rounded". If we don't do this, hoping that things will look sharper, then mathematics will prove us wrong and punish the results with "ringing".

Ugly pixel artifacts on 720px level will disappear, as we are using 960px density, and the resizers will round off anything such.
The "running ants" artifact of the Yadif tends to run with smaller and softer pixels, which is quite a pleasant improvement.

This article does not deal with any other techniques to remove artifacts, as it wants to use only fully linear filters.
When the postprocessing already has used too much of nonlinear filtering, that might create trouble, and need further,
nonlinear removal with techniques mentioned in the many other threads.


Scripts

Here is the AviSynth script:
(plz adjust the file paths to your needs)
Code:
LoadPlugin("F:\programs\AviSynth+\plugins\dgdecode.dll")
MPEG2Source ("F:\workdir\MyProject.d2v",cpu=0,info=2)

# delete this if source is not interlaced. caution - there are sources declared interlaced, that are not. visual check required.
Load_Stdcall_plugin("F:\programs\AviSynth+\plugins\yadif.dll")
Yadif(mode=1) 


AddBorders(4,0,4,4,$7F7F7F)
#AddBorders(clip clip, int left, int top, int right, int bottom [, int color]) 
 
ConvertToRGB32(matrix="PC.709",interlaced=false,chromaresample="lanczos4")
#ConvertToRGB(clip [, string matrix] [, bool interlaced] [, string ChromaInPlacement] [, string chromaresample])

# Remarks: default in this project is PC.709 (= HDTV)
# Though DVD = PC.601 or Rec601, I use 709 always, and correct the colors in the filtering chain.
# The reason is, that too often the decoded video ends up with flawed color space anyway.
# "Rec601" : Use 601 coefficients, scaled to TV range [16,235].
# "PC.601" : Use 601 coefficients, keep full range [0,255]. 



# please, activate only one of the following matrices:
# roughly said, intensity and radius are increasing. differences are still subtle.

 GeneralConvolution(0, "3 -4  8 -10 112 0  0 -0 -4 -15   0  0 -6 -0  15   0  0  0  0 -5   0  0  0  0  0") #C3.1 
#GeneralConvolution(0, "3 -3  9 -13 112 0  0 -0 -4 -15   0  0 -6 -0  15   0  0  0  0 -5   0  0  0  0  0") #C3.2 
#GeneralConvolution(0, "3 -3 10 -15 112 0  0 -0 -4 -12   0  0 -6 -0  14   0  0  0  0 -4   0  0  0  0  0") #C3.3 
#GeneralConvolution(0, "2 -5 12 -20 112 0  0 -0 -4 -10   0  0 -6 -0  12   0  0  0  0 -4   0  0  0  0  0") #C3.4 

#GeneralConvolution(0, "5 -13 15 -20 120  0  0 -0 -4 -10   0  0 -6 -0  12   0  0  0  0 -4   0  0  0  0  0") #a3
#GeneralConvolution(0, "5 -13 18 -21 103  0  0 -0 -4 -10   0  0 -6 -0  12   0  0  0  0 -4   0  0  0  0  0") #a2'

#GeneralConvolution(0, "2 -5 15 -20 96   0  0 -0 -6 -12   0  0 -6 -0  12   0  0  0  0 -4   0  0  0  0  0")  # X7
#GeneralConvolution(0, "2 -6 15 -20 96   0  0 -0 -4 -12   0  0 -6 -0  15   0  0  0  0 -4   0  0  0  0  0")  # X8


#--------------convolution tuning----
#---test start time = minutes*60 + ss.ddd #(seconds)
tpos=0*60+13
rff=29.97*2
fpos=int(tpos*rff)
#--test slice length:
tsl=int(40*rff)
/*
Trim(fpos, -tsl) + blankclip(last,5) \
+Trim(fpos, -tsl).GeneralConvolution(0, "2 -6 15 -20 96   0  0 -0 -4 -12  0 0 -6 -0 15   0 0 0 0 -4  0 0 0 0 0").subtitle("x8") + blankclip(last,15)\
+Trim(fpos, -tsl).GeneralConvolution(0, "3 -4  8 -10 112 0  0 -0 -4 -15   0 0 -6 -0 15   0 0 0 0 -5  0 0 0 0 0").subtitle("C3.1") + blankclip(last,15)\
+Trim(fpos, -tsl).GeneralConvolution(0, "3 -3  9 -13 112 0  0 -0 -4 -15   0 0 -6 -0 15   0 0 0 0 -5  0 0 0 0 0").subtitle("C3.2") + blankclip(last,15)\
+Trim(fpos, -tsl).GeneralConvolution(0, "3 -3 10 -15 112 0  0 -0 -4 -12  0 0 -6 -0 14   0 0 0 0 -4  0 0 0 0 0").subtitle("C3.3") + blankclip(last,15)\
+Trim(fpos, -tsl).GeneralConvolution(0, "2 -5 12 -20 112 0  0 -0 -4 -10  0 0 -6 -0 12   0 0 0 0 -4  0 0 0 0 0").subtitle("C3.4") + blankclip(last,15)\
+Trim(fpos, -tsl).GeneralConvolution(0, "5 -13 18 -21 103  0  0 -0 -4 -10  0 0 -6 -0 12  0 0 0 0 -4  0 0 0 0 0").subtitle("a2'") + blankclip(last,15)

*/ 


#Crop(clip clip, int left, int top, int -right, int -bottom, bool align)
Crop(0,2,-2,-2) # not checking this, cropping will be adjusted in the final step.


ConvertToYV12(matrix="PC.709",interlaced=false,chromaresample="lanczos4")

# this will go to AviDemux with a particular filtering chain.
Here is the AviDemux script (save as MyProject.py)
Open the AVS-Proxy channel first, then run this script.
I hope the line breaks will come out correctly..
Code:
#PY  <- Needed to identify #
#--automatically built--

adm = Avidemux()
adm.loadVideo("::ADM_AVS_PROXY::")
adm.clearSegments()
adm.addSegment(0, 0, 12000000000)
adm.markerA = 0
adm.markerB = 4827930624
adm.videoCodec("x264", "useAdvancedConfiguration=True", "general.params=AQ=22", "general.threads=0"
, "general.preset=ultrafast", "general.tuning=film", "general.profile=baseline", "general.fast_decode=False", "general.zero_latency=False"
, "general.fast_first_pass=True", "level=-1", "vui.sar_height=27", "vui.sar_width=32"
, "MaxRefFrames=5", "MinIdr=25", "MaxIdr=250", "i_scenecut_threshold=40", "intra_refresh=False", "MaxBFrame=5", "i_bframe_adaptive=2"
, "i_bframe_bias=0", "i_bframe_pyramid=2", "b_deblocking_filter=True", "i_deblocking_filter_alphac0=-1"
, "i_deblocking_filter_beta=0", "cabac=True", "interlaced=False", "constrained_intra=False", "tff=True"
, "fake_interlaced=False", "analyze.b_8x8=True", "analyze.b_i4x4=True", "analyze.b_i8x8=True", "analyze.b_p8x8=False"
, "analyze.b_p16x16=True", "analyze.b_b16x16=True", "analyze.weighted_pred=2", "analyze.weighted_bipred=True"
, "analyze.direct_mv_pred=3", "analyze.chroma_offset=1", "analyze.me_method=2", "analyze.me_range=17"
, "analyze.mv_range=-1", "analyze.mv_range_thread=-1", "analyze.subpel_refine=9", "analyze.chroma_me=True"
, "analyze.mixed_references=True", "analyze.trellis=2", "analyze.psy_rd=1.100000", "analyze.psy_trellis=0.000000"
, "analyze.fast_pskip=True", "analyze.dct_decimate=True", "analyze.noise_reduction=0", "analyze.psy=True"
, "analyze.intra_luma=0", "analyze.inter_luma=0", "ratecontrol.rc_method=0", "ratecontrol.qp_constant=0"
, "ratecontrol.qp_min=4", "ratecontrol.qp_max=58", "ratecontrol.qp_step=8", "ratecontrol.bitrate=0"
, "ratecontrol.rate_tolerance=1.000000", "ratecontrol.vbv_max_bitrate=0", "ratecontrol.vbv_buffer_size=0"
, "ratecontrol.vbv_buffer_init=0", "ratecontrol.ip_factor=1.400000", "ratecontrol.pb_factor=1.400000"
, "ratecontrol.aq_mode=1", "ratecontrol.aq_strength=1.400000", "ratecontrol.mb_tree=True", "ratecontrol.lookahead=40")
adm.addVideoFilter("fluxsmooth", "temporal_threshold=17", "spatial_threshold=0")
adm.addVideoFilter("addBorder", "left=0", "right=2", "top=2", "bottom=2")
adm.addVideoFilter("swscale", "width=1600", "height=968", "algo=2", "sourceAR=2", "targetAR=2")
adm.addVideoFilter("chromashift", "u=-1", "v=-1")
adm.addVideoFilter("Sharpen", "luma=True", "chroma=True")
adm.addVideoFilter("contrast", "coef=0.900000", "offset=40", "doLuma=False", "doChromaU=False", "doChromaV=True")
adm.addVideoFilter("colorYuv", "y_gain=0.000000", "y_bright=0.000000", "y_gamma=1.900000"
, "y_contrast=15.000000", "u_gain=0.000000", "u_bright=0.000000", "u_gamma=0.000000"
, "u_contrast=12.000000", "v_gain=0.000000", "v_bright=0.000000"
, "v_gamma=0.000000", "v_contrast=0.000000", "matrix=0", "levels=0", "opt=False"
, "colorbars=0", "analyze=1", "autowhite=False", "autogain=False")
adm.addVideoFilter("Sharpen", "luma=False", "chroma=True")
adm.addVideoFilter("swscale", "width=970", "height=646", "algo=2", "sourceAR=1", "targetAR=1")
adm.addVideoFilter("rotate", "angle=90")
adm.addVideoFilter("chromashift", "u=-1", "v=-1")
adm.addVideoFilter("rotate", "angle=270")
adm.addVideoFilter("crop", "top=4", "bottom=2", "left=6", "right=8")
adm.addVideoFilter("Sharpen", "luma=True", "chroma=True")
adm.audioClearTracks()
adm.setContainer("MP4V2", "optimize=0", "add_itunes_metadata=1")
Crop and resizing width need to be nudged. Check Aspect in the Output section, when there is a 4:3 video. Check video length with the rightmost [>>] button, then set [B].
Compression value recommended as 22-24. File size: 30fps uses > 12MB per minute, 60fps may use up to 20MB/min.
Audio is not covered here. I use DGIndex to create a WAV, and add this as a final step (convert to mp3), when video encoding is complete.

Please, enjoy, and comment about results..
Perhaps someone can figure out additional matrix specimen.
Thanks much for reading and checking out.

Last edited by geometer; 27th December 2015 at 00:48. Reason: line breaks in avidemux script
geometer is offline   Reply With Quote
Old 27th December 2015, 01:55   #2  |  Link
geometer
Registered User
 
Join Date: Dec 2015
Posts: 59
Judgement - hints for the fine tuning.

Most filters mentioned are not ideal, they can create side-effects that need to be compensated for an ideal result.
Temporal Smoother, resizers, and color/contrast adjusters can create an erraneous color shift, also in subpixel range.
Thus, when we delete or change such a filter, we need to recheck the color shift correction.

The asymmetric convolution will shift the picture. Further, not all videos are exactly 720x480, e.g. video width can miss a couple of (then blacked) columns.
The color shifting also changes the video size, every time we change the shift.
For this to compensate, at first we add borders, and as a last step we remove ("crop") any garbage that the filtering chain has created in the regions of those borders.

As we choose to end up with 960x640, original size cannot fully be preserved. But a lot of artifacts disappear from the playback, when we do this, and the video looks smoother.

Example: If we assume that 960x640 results in the correct aspect ratio, and e.g. we have a border of 6 to the right and 2 to the left, we should switch final resizing width to 968, and crop down from there, to 960.
If we don't get the aspect ratio precisely enough, we further need to nudge the resizing width. The problem is that there is a quantizing factor of 4px. Only multiples of 4 work well for the encoder. But in some cases, in the cropping step we can add 2 on one side and remove 2 on the other side to come closer to the original.
Also, the left border/crop can influence the color shift. In some case it may be better to adjust left crop rather than our color shift.


About sharpness, ringing and halo, judgement needs to be very subtle and sensitive.
In theory, the convolutional kernel should fit the video like key and keyhole.
Practically, we are hoping that one of the supplied matrix kernels will do the best job, and this will show up quite clearly.

The names are seen as random, they stem from the testing phase. Still, there is some kind of progression in the listing.

Start from the C3.1 kernel. Without any further processing (maybe temporal smoothener), a direct encode from there should already yield a better result than without convolution, and the h264 version should be almost identical to the MPEG2 source, when it looks blurred previously sans convo. This is, for practical compression rates on the edge of lossy, like 10MB/min.
But it may look a bit harsh, and it may have a color shift (that possibly exists already in the source).
Therefor we have the secondary filtering chain, to correct remaining flaws, and make it look totally smooth.
For this, still we'll have to sacrifice some more disk space, and processing speed. Full chain runs 4fps on a tablet, and perhaps double that on the i7 with 2.6GHz.

Note: C3.1 and C3.3 have something in common about the high frequencies (= small radius sharpening). Similar for C3.2 and C3.4 in the lower frequencies.
This is while overall impact is growing with the number.
The other kernels down the list have bigger radius too, but are of a different breed, in general these are meant for videos with more blur and lower quality, where pixel-sharpness can't be achieved anyway.

In other words, first judgement should not be about final sharpness, but much about the subtle halo and ringing, and about the radius of the sharpening. Further down the list, radius will grow.
A video that suffers from a low bandwidth, has no details to uncover with the small sharpening radius. Its blur has a bigger radius. Also, some videos with good bandwidth still may suffer additionally from a wide-radius blur. So we can go down the list, and try some more kernels with a bigger radius, and different tunings of "ringing" compensation.
When these details have been identified, then we can judge if there is a chance to get it even sharper, with the final preset convolutional sharpener in AviDemux. This might detune the compensation, so when we add that sharpener, perhaps the kernel needs to be changed once more, often with a previous neighbor in the list.

These supplied specimen of kernels don't cover a big range of radius, as they are for commercial videos.
Radius is meant to be ~ 0.7-2.5 px (in relation to the 720px original, with the help of the oversampling and the intermediate sharpeners)
For bigger radius blurs, we need to experiment with longer (or more intense) coefficient tails.


In the end, to me it means to watch or not to watch DVD, as this is a very limited format now when we have 4k and other HD stuff.
With good tuning, it looks really pleasant, most times better than the original.

Last edited by geometer; 27th December 2015 at 02:22.
geometer is offline   Reply With Quote
Old 27th December 2015, 02:28   #3  |  Link
Reel.Deel
Registered User
 
Join Date: Mar 2012
Location: Texas
Posts: 1,664
You can probably get better performance if you use mt_convolution from MaskTools2. It works with planar YUV so there's no need for the YUV-->RGB-->YUV conversion.
Reel.Deel is offline   Reply With Quote
Old 27th December 2015, 02:51   #4  |  Link
geometer
Registered User
 
Join Date: Dec 2015
Posts: 59
Yeah thx, if it really uses the same algorithm. (not formally but the principle. from experimenting, generalconvolution seems to be IIR, not FIR)
It's not a big deal, as the task-manager tells it is AviDemux that eats 80% CPU).

On another note, which is the corresponding filter in AviSynth, for the Convolutional Sharpener preset in AviDemux? Does it exist? Is the kernel known in exact coefficients? (Didn't search for the sources).
Because we could do a matrix multiply then.
geometer is offline   Reply With Quote
Old 1st January 2016, 11:55   #5  |  Link
foxyshadis
ангел смерти
 
foxyshadis's Avatar
 
Join Date: Nov 2004
Location: Lost
Posts: 9,558
Sharpen convolution:
Code:
-1 -2 -1
-2 16 -2 *1/16
-1 -2 -1
It's not implemented through general convolution, it has a custom fast path, but it should work the same in general.
foxyshadis is offline   Reply With Quote
Old 1st January 2016, 12:07   #6  |  Link
wonkey_monkey
Formerly davidh*****
 
wonkey_monkey's Avatar
 
Join Date: Jan 2004
Posts: 2,493
Shouldn't that be *1/4?
__________________
My AviSynth filters / I'm the Doctor

Last edited by wonkey_monkey; 1st January 2016 at 12:09.
wonkey_monkey is offline   Reply With Quote
Old 1st January 2016, 16:16   #7  |  Link
foxyshadis
ангел смерти
 
foxyshadis's Avatar
 
Join Date: Nov 2004
Location: Lost
Posts: 9,558
You'd think so, but no. I just copied the source comment, though, and now that I look closer the comment is inaccurate. (Big surprise.) It should be:
Code:
 0  -3  0
-12 48 -12 *1/12
 0 -12  0
The top is not a typo. This is one exceptionally strange kernel, I get the feeling someone played with the numbers to make it feel sharper. The multiplier should be ~1/8, at the least, but integer truncation will affect it in odd ways.

The actual code, where a/b/c are vertical and 1/2/3 are horizontal, is:
Code:
o=4*b2-a2-c2-b1-b3;
o>>=2;
o+=3*a2;
o=o/3

Last edited by foxyshadis; 1st January 2016 at 16:19.
foxyshadis is offline   Reply With Quote
Old 1st January 2016, 17:40   #8  |  Link
geometer
Registered User
 
Join Date: Dec 2015
Posts: 59
ah that's interesting.

however, if this is a 3x3 kernel only, then the 5x5 is an opportunity for huge improvement.
please, report about results when testing the complex kernels.


for now, I can share a couple of symmetric kernels:
#GeneralConvolution(0, "0 0 3 0 -0 0 -1 -3 -1 0 4 -4 44 -4 4 0 -1 -3 -1 0 0 0 3 0 0")
#GeneralConvolution(0, "-1 0 3 0 -1 0 -1 -3 -1 0 3 -5 56 -5 3 0 -1 -3 -1 0 -1 0 3 0 -1")
#GeneralConvolution(0, "-2 0 7 0 -2 0 -2 -6 -2 0 6 -10 112 -10 6 0 -2 -6 -2 0 -2 0 8 0 -2")
#GeneralConvolution(0, "-2 0 7 0 -2 0 -2 -6 -2 0 5 -8 112 -8 5 0 -2 -6 -2 0 -2 0 6 0 -2")

As they should address multiple issues, the coefficients look heuristical.
For a number of videos, sharpness vs. ringing has a very good efficiency.
All processing is linear, this makes results look very organic and natural.
(yadif and temporal smoother aren't really linear, but behave nicely in this concern.)
It also rewards with scenes that look a bit pale or foggy. The encoder doesn't destroy them anymore.

Last edited by geometer; 13th January 2016 at 20:22.
geometer is offline   Reply With Quote
Old 1st January 2016, 19:25   #9  |  Link
wonkey_monkey
Formerly davidh*****
 
wonkey_monkey's Avatar
 
Join Date: Jan 2004
Posts: 2,493
Quote:
Originally Posted by foxyshadis View Post
The actual code, where a/b/c are vertical and 1/2/3 are horizontal, is:
Code:
o=4*b2-a2-c2-b1-b3;
o>>=2;
o+=3*a2;
o=o/3
I don't think your second try is quite right, either. From that code, I work the matrix out to be:

Code:
 0 -1  0
-4 16 -4    *1/3
 0 -4  0
which is the equivalent of your second try, except that the multiplier on yours should be 1/9.

The multiplier should always be the inverse of the sum of the grid (unless you want the output to be brighter of darker than the inupt).
__________________
My AviSynth filters / I'm the Doctor

Last edited by wonkey_monkey; 1st January 2016 at 19:27.
wonkey_monkey is offline   Reply With Quote
Old 13th January 2016, 19:44   #10  |  Link
geometer
Registered User
 
Join Date: Dec 2015
Posts: 59
Yay, just salvaged another difficult movie, that was totally blurred out by standard x264 processing, unless we allocate insane bit rates.
It became possible with a new convo impulse/kernel. Beautiful result!
Bitrate comes down to 16MB per minute for 60fps, the encoder gracefully optimizes the band-limited 960x640 format!
100 minutes of video took about 10 hours to process. Thus, fine-tuning rewards greatly.
Eventually, the complexity of the task has to go somewhere..
Feel free to optimize for bit-depth and/or speed.
Code:
3   -5   17 -21 112 
0    0   -0  -4 -13   
0    0   -6  -0  15   
0    0    0   0  -4  
0    0    0   0   0
here is the avisynth script:
Code:
LoadPlugin("F:\programs\AviSynth+\plugins\dgdecode.dll")
MPEG2Source ("F:\workdir\MyProject.d2v",cpu=0,info=2)

#-- Deinterlace Yadif -- delete this, when source is not actually interlaced i.e. shows combing without.
Load_Stdcall_plugin("F:\programs\AviSynth+\plugins\yadif.dll")
Yadif(mode=1)

/*
#--- show some still pictures: (correct the audio intro length for this!)
tpos=0*60+10.176  # pics start time = minutes*60 + ss.ddd #(seconds)
rff=29.97*2       # for 60fps
fpos=int(tpos*rff)
tsl=int(1*rff/2)  # duration of one pic
n=fpos+1          # starting frame no. of pic series
Loop(tsl,n2,n+3)  # now show some DVD header pictures for half a second each
Loop(tsl,n,n+1)   # .. use the loop statements in decreasing order of frame position!
*/


AddBorders(4,0,4,4,$7F7F7F)
 
ConvertToRGB32(matrix="PC.709",interlaced=false,chromaresample="lanczos4")
# default for this type of work: PC.709 = HDTV
# though most DVD = Rec601 !
# Rec.709 should be used when your source is HDTV (but fits some DVDs also)
# "Rec601" : Use 601 coefficients, scaled to TV range [16,235].
# "PC.601" : Use 601 coefficients, keep full range [0,255]. 

# -- select one of these kernels, ordered by increasing radius and impact:
#    C3.1 will do for most good quality DVDs with sufficient sharpness
#GeneralConvolution(0, "3 -4  8 -10 112 0  0 -0 -4 -15   0  0 -6 -0  15   0  0  0  0 -5   0  0  0  0  0") #C3.1
#GeneralConvolution(0, "3 -3  9 -13 112 0  0 -0 -4 -15   0  0 -6 -0  15   0  0  0  0 -5   0  0  0  0  0") #C3.2 
#GeneralConvolution(0, "3 -3 10 -15 112 0  0 -0 -4 -12   0  0 -6 -0  14   0  0  0  0 -4   0  0  0  0  0") #C3.3  
#GeneralConvolution(0, "2 -5 12 -20 112 0  0 -0 -4 -10   0  0 -6 -0  12   0  0  0  0 -4   0  0  0  0  0") #C3.4 
 GeneralConvolution(0, "3 -5 17 -21 112 0  0 -0 -4 -13   0  0 -6 -0  15   0  0  0  0 -4   0  0  0  0  0") #C4.0  soft natural look
#GeneralConvolution(0, "3 -8  7 -11 112 0  0 -0 -6 -12   0  0 -3  2  14   0  0  0  0 -4   0  0  0  0  2") #C4.1  natural sharper

# C4.0 has strong halo softening and anti-ringing compensation, but only for DVDs that have correct bandwidth limiting.
#  on pixel-sharp and high-contrast vertical lines it will still show a ringing pattern.
# use C4.0 for sources that would look awkwardly blurred after the x264, when they won't allow the stronger
# sharpening by the other kernels because of noise, grainy lines, and sharp halos/outlines

#these are softer and have a wide radius:
#GeneralConvolution(0, "5 -13 17 -21 100  0  0 -0 -4 -10   0  0 -6 -0  12   0  0  0  0 -4   0  0  0  0  0") #a2
#GeneralConvolution(0, "5 -13 18 -21 103  0  0 -0 -4 -10   0  0 -6 -0  12   0  0  0  0 -4   0  0  0  0  0") #a2'
#GeneralConvolution(0, "5 -13 15 -20 120  0  0 -0 -4 -10   0  0 -6 -0  12   0  0  0  0 -4   0  0  0  0  0") #a3


#--------------convolution tuning----
#---test seq start time = minutes*60 + ss.ddd #(seconds)
tpos=2*60+15
rff=29.97*2 # factor *2 for 60fps
fpos=int(tpos*rff)
#--test slice length in secs:
tsl=int(40*rff)
/*
#Trim(fpos, -tsl) + blankclip(last,5) \
#+Trim(fpos, -tsl).GeneralConvolution(0, "2 -6 15 -20 96   0  0 -0 -4 -12   0  0 -6 -0  15   0  0  0  0 -4   0  0  0  0  0").subtitle("x8") + blankclip(last,15)\
 Trim(fpos, -tsl).GeneralConvolution(0, "3 -4  8 -10 112 0  0 -0 -4 -15   0  0 -6 -0  15   0  0  0  0 -5   0  0  0  0  0").subtitle("C3.1") + blankclip(last,15)\
+Trim(fpos, -tsl).GeneralConvolution(0, "3 -3  9 -13 112 0  0 -0 -4 -15   0  0 -6 -0  15   0  0  0  0 -5   0  0  0  0  0").subtitle("C3.2") + blankclip(last,15)\
+Trim(fpos, -tsl).GeneralConvolution(0, "3 -3 10 -15 112 0  0 -0 -4 -12   0  0 -6 -0  14   0  0  0  0 -4   0  0  0  0  0").subtitle("C3.3") + blankclip(last,15)\
+Trim(fpos, -tsl).GeneralConvolution(0, "2 -5 12 -20 112 0  0 -0 -4 -10   0  0 -6 -0  12   0  0  0  0 -4   0  0  0  0  0").subtitle("C3.4") + blankclip(last,15)\
+Trim(fpos, -tsl).GeneralConvolution(0, "3 -5 17 -21 112 0  0 -0 -4 -13   0  0 -6 -0  15   0  0  0  0 -4   0  0  0  0  0").subtitle("C3.5") + blankclip(last,15)\
+Trim(fpos, -tsl).GeneralConvolution(0, "5 -13 18 -21 103  0  0 -0 -4 -10   0  0 -6 -0  12   0  0  0  0 -4   0  0  0  0  0").subtitle("a2'") + blankclip(last,15)
*/
 

Crop(0,2,-2,-2)

ConvertToYV12(matrix="PC.709",interlaced=false,chromaresample="lanczos4")
here is the corresponding tinypy avidemux script with some comments:
Code:
#PY  <- Needed to identify #
#--automatically built--

adm = Avidemux()
adm.loadVideo("::ADM_AVS_PROXY::")
adm.clearSegments()
adm.addSegment(0, 0, 12000000000) # this is a random number for a longer video, as we use this script as a template for any video DVD.
adm.markerA = 0
adm.markerB = 6600000000 
# open the proxy stream, then press [>>] button (go last frame). pointer will stay there, when you load this script,
# then press [B] after script successfully opened.

adm.videoCodec("x264", "useAdvancedConfiguration=True", "general.params=AQ=21", "general.threads=0", "general.preset=ultrafast", "general.tuning=film"
, "general.profile=baseline", "general.fast_decode=False", "general.zero_latency=False"
, "general.fast_first_pass=True", "level=-1", "vui.sar_height=27", "vui.sar_width=32", "MaxRefFrames=5", "MinIdr=25", "MaxIdr=250", "i_scenecut_threshold=40"
, "intra_refresh=False", "MaxBFrame=5", "i_bframe_adaptive=2"
, "i_bframe_bias=0", "i_bframe_pyramid=2", "b_deblocking_filter=True", "i_deblocking_filter_alphac0=-1", "i_deblocking_filter_beta=0", "cabac=True"
, "interlaced=False", "constrained_intra=False", "tff=True"
, "fake_interlaced=False", "analyze.b_8x8=True", "analyze.b_i4x4=True", "analyze.b_i8x8=True", "analyze.b_p8x8=False", "analyze.b_p16x16=True"
, "analyze.b_b16x16=True", "analyze.weighted_pred=2", "analyze.weighted_bipred=True"
, "analyze.direct_mv_pred=3", "analyze.chroma_offset=1", "analyze.me_method=2", "analyze.me_range=17", "analyze.mv_range=-1", "analyze.mv_range_thread=-1"
, "analyze.subpel_refine=9", "analyze.chroma_me=True"
, "analyze.mixed_references=True", "analyze.trellis=2", "analyze.psy_rd=1.100000", "analyze.psy_trellis=0.000000", "analyze.fast_pskip=True"
, "analyze.dct_decimate=True", "analyze.noise_reduction=0", "analyze.psy=True"
, "analyze.intra_luma=0", "analyze.inter_luma=0", "ratecontrol.rc_method=0", "ratecontrol.qp_constant=0", "ratecontrol.qp_min=4", "ratecontrol.qp_max=58"
, "ratecontrol.qp_step=8", "ratecontrol.bitrate=0"
, "ratecontrol.rate_tolerance=1.000000", "ratecontrol.vbv_max_bitrate=0", "ratecontrol.vbv_buffer_size=0", "ratecontrol.vbv_buffer_init=0"
, "ratecontrol.ip_factor=1.400000", "ratecontrol.pb_factor=1.400000"
, "ratecontrol.aq_mode=1", "ratecontrol.aq_strength=1.400000", "ratecontrol.mb_tree=True", "ratecontrol.lookahead=40")
# reasonable compression rates are from 20-24, normally 21 or 22. (general.params=AQ=21)

adm.addVideoFilter("fluxsmooth", "temporal_threshold=17", "spatial_threshold=0") # avoid spatial because of textures and dithering
adm.addVideoFilter("addBorder", "left=0", "right=2", "top=2", "bottom=2") # added because we may do chroma shift corrections

adm.addVideoFilter("swscale", "width=1600", "height=968", "algo=2", "sourceAR=2", "targetAR=2") 
# 1600 is a compromise for processing speed, should be 1800 or 2160 for some 1/3px shifts.
# initially 1440 was used, but turned out infavorable, because of certain horizontal chroma subsampling corrections, that use factors based on 1/3px.

# adm.addVideoFilter("chromashift", "u=-1", "v=-1") # optional: some videos need a chroma shift here, 1 or 2 px, depends also on what color filters that you insert.
adm.addVideoFilter("Sharpen", "luma=True", "chroma=True")  # HF sharpening with reduced radius, caution: this harmonizes well with our choice of width=1600.
adm.addVideoFilter("Sharpen", "luma=False", "chroma=True") # poor man's makeup for the color subsampling, looks better many times than without.

adm.addVideoFilter("contrast", "coef=0.900000", "offset=40", "doLuma=False", "doChromaU=False", "doChromaV=True") 
# this will optionally mitigate greenish or yellow skin tone in case of color space conflicts.
# deleting this filter might change the chroma shift corrections.

adm.addVideoFilter("colorYuv", "y_gain=0.000000", "y_bright=0.000000", "y_gamma=2.900000", "y_contrast=10.500000", "u_gain=0.000000"
, "u_bright=0.000000", "u_gamma=0.000000", "u_contrast=11.000000", "v_gain=0.000000", "v_bright=0.000000" 
, "v_gamma=0.000000", "v_contrast=0.000000", "matrix=0", "levels=0", "opt=False", "colorbars=0", "analyze=1", "autowhite=False"
, "autogain=False") 
# as we don't do the standard RGB Rec601->PC.709 conversion for the majority of such jobs,
# we fine-tune the black and white luminance limits here, and boost color a tad.

adm.addVideoFilter("swscale", "width=970", "height=646", "algo=2", "sourceAR=1", "targetAR=1") 
# downsampling to the 4/3 target density, also counting for border widths

adm.addVideoFilter("rotate", "angle=90") # prepare for vertical chroma correction
adm.addVideoFilter("chromashift", "u=-1", "v=-1") # correct a vertical chroma shift, that comes from filters not respecting some subsampling schemes
adm.addVideoFilter("rotate", "angle=270")
#  the chroma shift functions may need to be positioned either here in the 640 or above in the 960 lines domain,
#  depending on subsampling schemes and type of error.

adm.addVideoFilter("crop", "top=4", "bottom=2", "left=2", "right=8") 
# final border removal, results in 960x640. depending on actual video width, we also must sometimes nudge the resizing with.

adm.audioClearTracks() # add audio in another remux run, when video is ok already. audio would slow down the processing further.
adm.setContainer("MP4V2", "optimize=0", "add_itunes_metadata=1")

Last edited by geometer; 27th January 2016 at 23:27.
geometer is offline   Reply With Quote
Old 24th January 2016, 20:55   #11  |  Link
geometer
Registered User
 
Join Date: Dec 2015
Posts: 59
Demo picture, MPEG2 ==> MPEG4 using mentioned settings w/ convolution.

These are screenshots with VLC-Player, copied to the clipboard, then resized to double height/width, then cut, and then copied to one image side by side.
The same small block of the video was cut out from both versions, to show the difference.
On the left side, we see the "original" MPEG2, on the right side we see the playback of the converted and re-encoded result.

By this, we can see the result in comparable form, though the MPEG2 is 720*480, and the MPEG4 is 960*640.
The player was set to display both in full-screen. The screen is physically 1600*900.

By resizing the attached png to 50%, you will approximately get the view that the monitor had displayed.


----
What we can observe here, among other effects, is:

* Things are falling in place by the synergy of the processing chain with the encoder. This actually "discovers" fine detail, that normally would get lost. Compression was set to 22, with a lower value even a bit more of detail would be possible. Becomes even more visible with plants in the garden, or a cluttered office table.
(The tested section compressed to 12MB per minute.)

* The pixelized artifacts in slanted small structures, that the player creates at 720*480, are remarkably smoothened and the structures can be displayed more beautifully at 960*640. Any player would have its own filtering methods and flaws, working so closely at Nyquist density. This is practically gone with the upsampled format. The x264 encoder gracefully removes almost all of the redundancy in the upsampled raw signal.

* In relation to the achieved sharpness and clarity, a boost of ringing and halo is very small, but what was there already, will naturally get enhanced. The processing does not use any non-linear (boolean/edgy/saturating) functions,
(besides the relatively transparent Fluxsmooth, especially no adaptive sharpener or "unsharp mask" occurs in the processing).
We see the C3.2 kernel in action, testing of all other kernels for your particular project is recommended. Perhaps the intro and the credits need a different kernel.

* Contrast is enhanced, it approximates to the TV-Level vs. PC-Level value range. I prefer this, and can fine-tune it, and allow some minimal clipping at rare close to full-black and full-white levels. This is a different issue and depends on the data type of the source video.

* The deinterlacing is treated beautifully, and geometric errors are smoothened. Again, some kernels perform better with progressive video, but e.g. C4.0 would be one of the best in dealing with interlacing artifacts.

* Caveat on screen driver influence: On some office power notebook with a 1600x900 display, there is much more ringing visible than on a tablet 1920x1080. Player is VLC. The sharpening may not produce all the ringing in the video data itself, but in the output chain of the player and video drivers.

* Practical efficiency (not discussing code efficiency): Running on classic i7 with a simple Nvidia that isn't game-optimized, the taskmanager shows roughly 80% for AviDemux and 20% for AviSynth. Total CPU utilization is ~95% when the processes are granted task priority "above normal". This results in 8-12 fps with a 2.4G CPU.

I hope this will be seen as quite a good result, at 12-20 MB/minute and ~10 fps processing.
Further improvement might be made with moving all processing to multithreaded AviSynth, plus using the bit-depth upsampling capabilities, but would slow down the conversions remarkably.
Attached Images
 

Last edited by geometer; 29th January 2016 at 15:02.
geometer is offline   Reply With Quote
Old 16th June 2016, 13:51   #12  |  Link
geometer
Registered User
 
Join Date: Dec 2015
Posts: 59
Update:
Deconvolution for ruined material - in terms of oversharpening with halo and clipped outlining.

I used it for a certain DVD, its producer seems to have fell into panicking mode and told his assistant to overuse a nonlinear sharpener.
Problem is, that the reconstruction filter in most players will not digest this well, but will create additional artifacts ("Gibb"..).
Without any digital reconstruction filter, as in the Nineties' GIF era, displaying pixel by pixel 1:1 (akin to some simplified preview window e.g. in AviDemux) it might look quite good with the original source, but...



The idea is based on a spectral perception of the material. We see strong spikes of the sampling frequency, plus harmonics and subharmonics. (digital spectrum of rectangular signal)
Deconvolution can soften some of the faulty spectral lines, but to enhance/restore the frequencies that are close to Nyquist, it takes some oversampling.

The technical approach is a bit primitive, but as a proof-of-concept and strong alternative to nonlinear anti-halo technology, it looks stunningly pleasant and organic.

Procedure:
A particular convolutional impulse was used for the dampening of artifacts, then the material was upsampled to 960x640, and there, a built-in convolutional sharpener was used to restore some detail.
Please note, that the avidemux resizer here uses the bilinear kernel, not like the other examples that use the lanczos4 ! And there is only one level of resizing, not the upsampling and downsampling.

The supplied impulse contains effect on various other issues also, it was not created in a mathematical way. An engineer who computes his impulse exactly, would have to multiply into it some other matrices for the remaining spectral issues in the particular video, after solving and removing the exact rectangular signal.

Unfortunately, with the typical clipping in the value range (when the halos become too bright = digital white) some detail gets lost beyond repair. Spectral anti-clipping techniques may help, but will create their own artifacts, that can harm sharp small objects.


The experimental impulse (for GeneralConvolution) was the following:
Code:
C50  = "4 -4  6  -3 121   0  0 0 -2 -25   0  0 -4 0  30   0  0  0  0 -7   0  0  0  0  5"

 4   -4    6   -3  121
 0    0    0   -2  -25 
 0    0   -4    0   30
 0    0    0    0   -7
 0    0    0    0    5
So far, I tested it only with progressive (fake-interlaced) material. Real interlacing might conflict with this approach from the beginning.

AviSynth.avs script with an updated kernel library:
(check the paths for DLLs and input file)
Code:
# -- initial DVD processing with DGIndex, then use this data reader:
LoadPlugin("F:\programs\AviSynth+\plugins\dgdecode.dll")
MPEG2Source ("F:\wrk\Project1\MyProject.d2v",cpu=0,info=2)


# -- Deinterlace -- delete this, when source is not actually interlaced
#Load_Stdcall_plugin("F:\programs\AviSynth+\plugins\yadif.dll")
#Yadif(mode=1)

# some editing management code would go here..


AddBorders(4,0,4,8,$7F7F7F) # for the shifting in the asymmetric convolution and later chroma processing
 
ConvertToRGB32(matrix="PC.709",interlaced=false,chromaresample="lanczos4")
# default for this type of work (encoding and fine-filtering in AviDemux): PC.709 = HDTV
# although officially DVD = Rec601!


# ------------------------- convolution and library of kernels (impulses) --------------------------------------------------
# -- symmetric kernels (if used, remove some of the border settings and cropping)
C20 = "-2 0 3 0 -2   0 -1 -3 -1 0   2 -6 56 -6 2   0 -1 -3 -1 0   -1 0 3 0 -1"  #C2 entry level
C21 = "-1 0 3 0 -1   0 -1 -3 -1 0   3 -5 56 -5 3   0 -1 -3 -1 0   -1 0 3 0 -1"  #Crystal Outline
C22 = "-1 0 3 0 -1   0 -1 -3 -1 0   3 -6 48 -6 3   0 -1 -3 -1 0   -1 0 3 0 -1"  #was used for progressive DVD
C23 = "-1 0 3 0 -1   0 -1 -3 -1 0   3 -5 48 -5 3   0 -1 -3 -1 0   -1 0 3 0 -1"  #
C24 = " 0 0 3 0 -0   0 -1 -3 -1 0   4 -4 44 -4 4   0 -1 -3 -1 0    0 0 3 0  0"  #base spinoff for C3xx

# -- asymmetric kernels
# -- select one of these kernels, ordered by increasing radius and impact:
#    C3.1 will do for most good quality DVDs with sufficient sharpness
C000 = "0  0  0   0 100   0  0  0  0   0   0  0  0  0   0   0  0  0  0  0   0  0  0  0  0" #asymmetric dummy (to keep the shifting)

CX7  = "2 -5 15 -20  96   0  0 -0 -6 -12   0  0 -6 -0  12   0  0  0  0 -4   0  0  0  0  0" #X7  
 
C31  = "3 -4  8 -10 112   0  0 -0 -4 -15   0  0 -6 -0  15   0  0  0  0 -5   0  0  0  0  0" #C3.1  tight
C32  = "3 -3  9 -13 112   0  0 -0 -4 -15   0  0 -6 -0  15   0  0  0  0 -5   0  0  0  0  0" #C3.2  tight enhanced
C32a = "3 -3  9 -13 140   0  0 -0 -4 -15   0  0 -6 -0  15   0  0  0  0 -5   0  0  0  0  0" #C3.2a
C32c = "3 -3 11 -13 173   0  0 -0 -4 -10   0  0 -6 -0  15   0  0  0  0 -5   0  0  0  0  0" #C3.2c ##ok for many good sources
C33  = "3 -3 10 -15 112   0  0 -0 -4 -12   0  0 -6 -0  14   0  0  0  0 -4   0  0  0  0  0" #C3.3  wider
C331 = "4 -5 14 -15 112   0  0 -0 -4 -12   0  0 -6 -0  14   0  0  0  0 -4   0  0  0  0  0" #C3.31 ## 
C34  = "2 -5 12 -20 112   0  0 -0 -4 -10   0  0 -6 -0  12   0  0  0  0 -4   0  0  0  0  0" #C3.4  wide enhanced for blurred material

C40  = "3 -5 17 -21 112   0  0 -0 -4 -13   0  0 -6 -0  15   0  0  0  0 -4   0  0  0  0  0" #C4.0  fat natural look
C40a = "3 -5 21 -23 112   0  0 -0 -4 -12   0  0 -8 -0  14   0  0  0  0 -4   0  0  0  0  0" #C4.0a more detail if source is better
C40b ="-2 -3 19 -21 112   0  0 -0 -4 -13   0  0 -6 -0  15   0  0  0  0 -4   0  0  0  0  0" #C4.0b (experimental)
C40c = "3 -3 23 -23 112   0  0 -0 -4 -10   0  0 -7 -0  15   0  0  0  0 -5   0  0  0  0  0" #C4.0c (720x480 test)
C40d = "3 -5 23 -25 112   0  0 -0 -4 -10   0  0 -7 -0  15   0  0  0  0 -4   0  0  0  0  0" #C4.0d (720x480 test)
C40e = "3 -5 23 -25 140   0  0 -0 -4 -10   0  0 -6 -0  15   0  0  0  0 -4   0  0  0  0  0" #C4.0e 720x480 ### ok
#                               -10..-15           14..15                        # depends on interlacing properties
C41  = "3 -8  7 -11 112   0  0 -0 -6 -12   0  0 -3  2  14   0  0  0  0 -4   0  0  0  0  2" #C4.1  wide enhanced for extra blurred material
C41c = "3 -8  7 -11 112   0  0 -0 -6 -17   0  0 -3  2  17   0  0  0  0 -9   0  0  0  0  1" #C4.1c wide vertical radius also
# C41c and then C21 (applying two impulses) seems quite good for old amateur film material


# -- Deconvolution if there is oversharpening with strong halo and clipped outlining of shapes: ###########
C50  = "4 -4  6  -3 121 0  0 -0 -2 -25   0  0 -4 -0  30   0  0  0  0 -7   0  0  0  0  5" #C5.0
C50b = "3 -5  3  -4 121 0  0 -0 -3 -15   0  0 -4 -0  15   0  0  0  0 -4   0  0  0  0  0" #C5.0b
C50c = "5 -3  11 -9 121 0  0 -0 -3 -21   0  0 -4 -0  23   0  0  0  0 -9   0  0  0  0  3" #C5.0c 
C50d=  "5 -3  13 -9 121 0  0 -0 -3 -25   0  0 -4 -0  27   0  0  0  0 -4   0  0  0  0  2" #C5.0d
# this class of impulses should be used together with oversampled re-sharpening.
# caution, x and y directions are treated very differently. depends strongly on the type of material.
 

GeneralConvolution(0, C50) # select kernel to use, specify its variable name here

Crop(0,0,-2,-2)

ConvertToYV12(matrix="PC.709",interlaced=false,chromaresample="lanczos4")

# -- in case of problem, optionally specify frame rate:
#AssumeFPS(30000,1001)
#AssumeFPS(60000,1001)

#------------------------------------------- EOF -------------------------------------
AviDemux.py (tinypy script; caution - before loading, connect to avsproxy):
Code:
#PY  <- Needed to identify #
#--automatically built--

adm = Avidemux()
adm.loadVideo("::ADM_AVS_PROXY::")
adm.clearSegments()
adm.addSegment(0, 0, 8000000000)
adm.markerA = 0
adm.markerB = 6770144256
adm.videoCodec("x264", "useAdvancedConfiguration=True", "general.params=AQ=21", "general.threads=0", "general.preset=ultrafast"
, "general.tuning=film", "general.profile=baseline", "general.fast_decode=False", "general.zero_latency=False"
, "general.fast_first_pass=True", "level=-1", "vui.sar_height=27", "vui.sar_width=32", "MaxRefFrames=5", "MinIdr=25", "MaxIdr=250"
, "i_scenecut_threshold=40", "intra_refresh=False", "MaxBFrame=5", "i_bframe_adaptive=2"
, "i_bframe_bias=0", "i_bframe_pyramid=2", "b_deblocking_filter=True", "i_deblocking_filter_alphac0=-1", "i_deblocking_filter_beta=0"
, "cabac=True", "interlaced=False", "constrained_intra=False", "tff=True"
, "fake_interlaced=False", "analyze.b_8x8=True", "analyze.b_i4x4=True", "analyze.b_i8x8=True", "analyze.b_p8x8=False"
, "analyze.b_p16x16=True", "analyze.b_b16x16=True", "analyze.weighted_pred=2", "analyze.weighted_bipred=True"
, "analyze.direct_mv_pred=3", "analyze.chroma_offset=1", "analyze.me_method=2", "analyze.me_range=17", "analyze.mv_range=-1"
, "analyze.mv_range_thread=-1", "analyze.subpel_refine=9", "analyze.chroma_me=True"
, "analyze.mixed_references=True", "analyze.trellis=2", "analyze.psy_rd=1.100000", "analyze.psy_trellis=0.000000", "analyze.fast_pskip=True"
, "analyze.dct_decimate=True", "analyze.noise_reduction=0", "analyze.psy=True"
, "analyze.intra_luma=0", "analyze.inter_luma=0", "ratecontrol.rc_method=0", "ratecontrol.qp_constant=0", "ratecontrol.qp_min=4"
, "ratecontrol.qp_max=58", "ratecontrol.qp_step=8", "ratecontrol.bitrate=0"
, "ratecontrol.rate_tolerance=1.000000", "ratecontrol.vbv_max_bitrate=0", "ratecontrol.vbv_buffer_size=0", "ratecontrol.vbv_buffer_init=0"
, "ratecontrol.ip_factor=1.400000", "ratecontrol.pb_factor=1.400000"
, "ratecontrol.aq_mode=1", "ratecontrol.aq_strength=1.400000", "ratecontrol.mb_tree=True", "ratecontrol.lookahead=40")
adm.addVideoFilter("crop", "top=2", "bottom=4", "left=2", "right=4")
adm.addVideoFilter("swscale", "width=960", "height=640", "algo=0", "sourceAR=1", "targetAR=1")
adm.addVideoFilter("Sharpen", "luma=True", "chroma=True")
adm.addVideoFilter("Sharpen", "luma=True", "chroma=True")
adm.addVideoFilter("contrast", "coef=0.970000", "offset=40", "doLuma=False", "doChromaU=False", "doChromaV=True")
adm.addVideoFilter("colorYuv", "y_gain=0.000000", "y_bright=0.000000", "y_gamma=2.500000", "y_contrast=11.000000"
, "u_gain=0.000000", "u_bright=0.000000", "u_gamma=0.000000", "u_contrast=11.300000", "v_gain=0.000000", "v_bright=0.000000"
, "v_gamma=0.000000", "v_contrast=0.000000", "matrix=0", "levels=0", "opt=False", "colorbars=0", "analyze=1", "autowhite=False", "autogain=False")
adm.addVideoFilter("rotate", "angle=90")
adm.addVideoFilter("chromashift", "u=-1", "v=-1")
adm.addVideoFilter("rotate", "angle=270")
adm.audioClearTracks()
adm.setContainer("AVI", "odmlType=1")
As usual, check actual video duration, and eventually adapt chroma shift, that depends on the color subsampling format.
Chroma subpixel shift correction is an issue anyway, as for many DVDs the built-in resizers, smoothers and color adjusters won't get it right on their own.
The oversampling is a convenient way to adjust chroma-shift and gives a number of choices.


------ addendum
there is an example here:
http://forum.doom9.org/showthread.ph...90#post1771490 - what to look for is mentioned in 2) and especially 3)
see the demo picture in posting #9 of that thread.

Last edited by geometer; 4th July 2016 at 18:41.
geometer is offline   Reply With Quote
Reply

Tags
avidemux, avisynth, convolution, dvd transcode

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 16:55.


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