View Single Post
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