Log in

View Full Version : Can anyone help with the syntax for this script?


sonic41592
30th August 2020, 13:57
I have a video with many exact duplicate frames, some are combed and others aren't. I'm trying to make a function which first checks if a frame is combed, and if it is combed, counts how many duplicates of that frame there are in that group of duplicates. If there are more than 12 duplicates, it will decomb the frame, and eventually all duplicates in the group. If there are 12 or fewer duplicates or the frame isn't combed, the frames get passed through untouched. Here's a mockup code I was working on:

function DupCount( clip c ) {

a = current_frame
b = current_frame + 1
d = 0
e = current_frame - 1
f = 0

while ( RGBDifference(c.trim(a,-1),c.trim(b,-1)) == 0 ) {
d = d + 1
b = b + 1
}

while ( RGBDifference(c.trim(a,-1),c.trim(e,-1)) == 0 ) {
f = f + 1
e = e - 1
}

g = 1 + d + f

return g
}

function DCIVTC( clip c ){

if ( IsCombedTIVTC(c) == true && DupCount(c) > 12 ) {
final = c.QTGMC( Preset="slow", SourceMatch=3, TR2=1, Lossless=2 ).selecteven
}
else {
final = c
}
return final
}

This doesn't work, stating that IsCombedTIVTC has incorrect parameters. It also gives errors on the DupCount function not knowing what current_frame is. I'm not very knowledgeable on the
AVISynth language, and was wondering if someone could help me get this working. Thanks!

Here's a small sample which has several combed frames with 15 duplicates that need to be decombed, and several combed frames with only 12 duplicates which don't need decombing https://www.sendspace.com/file/6mqh68

StainlessS
30th August 2020, 17:03
Is it gonna be RGB32 or prefer YUV12 ? [your sample is YV12] [EDIT: Dont matter, I will deal with either]

EDIT: Also, you want deinterlace the frame of which the others are a duplicate ? [I'm assuming yes]

What you want is really quite tricky and a somewhat difficult task,
I've done similar before and so am doing it for you.
Will be a little while.

sonic41592
30th August 2020, 20:05
Thank you so much! And yes, the idea is to deinterlace the groups of 13 or more exact duplicate frames that are combed, leaving the combed frames in duplicate groups of 12 or fewer untouched. No big rush on it, I just really appreciate any help!

StainlessS
31st August 2020, 05:12
Can you try this out please. [Updated]

# SuperSonic.avs # https://forum.doom9.org/showthread.php?p=1922294#post1922294
##############
/*
Req RT_Stats v2.0 Beta 12+(@Mediafire in my sig) [And DebugView to view debug stuff ]
If [EXACT] duplicates run length [incl 1st Unique frame] >= RUNCNT, AND dupe run is Combed, then Deinterlace dupe run [incl first unique frame].

Metrics shown when SHOW=True:
First line, "nnnn:ff/cc] UDC * DEINT *"
Where,
nnnn, Is frame number.
'ff/cc', The 'ff'th frame in 'cc' length sequence.
'1/1' would be single unique (non dupe) frame.
'1/15' would be 1st frame of 15 frame dupe run, ie first non dupe of dupe sequence.
'4/15' would be 4th frame of 15 frame dupe run, the 3rd actual duplicate.
'U' If shown, Current frame is Unique, different to its predecessor.
'D' If shown, Current frame is Duplicate, EXACT copy of its predecessor.
'C' If shown, Current frame is Combed.
'* DEINT *' If Shown, Current frame is Deinterlaced. It is both Combed, and part of a duplicate run where length of run >= RUNCOUNT.
2nd line shows difference metric between current frame and its predecessor.

*/

############## CONFIG ##############
FN = ".\Sample.AVI"
FN = RT_GetFullPathName(FN)
RUNCNT = 13 # >= this then deint (Includes Initial Unique Frame)
SHOW = True # Subs
DEBUG = True # Output some stuff to DebugView
STACK = True # Stack window
FINAL = False # Switch off SHOW, STACK, and DEBUG
#
# IsCombedTIVTC args, Defaults are 1st value after comment hash '#'.
CTHRESH = 10 # 10, Area combing threshold.
# Valid settings are from -1 (every pixel will be detected as combed) to 255 (no pixel will be detected as combed).
# This is basically a pixel difference value. A good range is between 8 to 12.
MI = 80 # 80, Number of combed pixels inside any of the blocky by blockx size blocks on the frame for the frame to be detected as combed.
CHROMA = false # False, Whether or not chroma is considered in the combed frame decision
BLOCKX = 16 # 16, X-axis size of the window used during combed frame detection.
BLOCKY = 16 # 16, Y-axis size of the window used during combed frame detection.
METRIC = 0 # 0, Comb detect Method, 0 = OLD, 1 = NEW
#
DEINT_S = """BOB.selecteven""" # Quicker for testing
#DEINT_S = """QTGMC( Preset="slow", SourceMatch=3, TR2=1, Lossless=2 ).selecteven"""

AviSource(FN)

############### END CONFIG ##############

ORG=Last
DB=FN+".DB"
SHOW = (!FINAL) ? SHOW : False
STACK= (!FINAL) ? STACK : False
DEBUG= (!FINAL) ? DEBUG : False
###
BELL = Chr(7) # ASCII Bell code, RT_Subtitle Color CTRL code preamble.
S_Hi = BELL + "!" # RT_Subtitle Hi-lite switch
S_Lo = BELL + "M" # RT_Subtitle Lo-lite switch
S_Wht = BELL + "-" # RT_Subtitle normal switch (white text)

TypeStr ="bfbbiii" # Field types:- 0)=Bool Valid, 1)=Float Difference to Prev frame, 2)=Bool Combed, 3)=Bool Deint, 4)=Int StartFrame, 5)=Int EndFrame, 6)=Int Count
FLD_VALID = 0 # True, then all fields are valid/set.
FLD_PDIF = 1 # 0.0 = Duplicate, Difference to previous frame.
FLD_COMB = 2 # True Combed
FLD_DEINT = 3 # True Deinterlace
FLD_START = 4 # Start of duplicate frames. Start Includes frame of which the dupes are a copy. [ie duplicates at START+1]
FLD_END = 5 # End of duplicate frames
FLD_COUNT = 6 # Count of duplicate frames. Count includes frame of which the dupes are a copy.
RT_DBaseAlloc(DB,FrameCount,TypeStr) # Create DBase with Framecount records of 7 fields. [Defaults on init are bool=false, Int=0, Float=0.0]
#
Dclip = Eval(DEINT_S) # Make Deinterlace clip only once, not whenever a combed frame encountered.

SSS="""
FrmNo = current_frame # Frame Number Or DB Record number [same]
Valid = RT_DBaseGetField(DB,FrmNo,FLD_VALID) # Record already valid ? [ie visited already]
if(!Valid) {
FC = FrameCount
# Scan from current frame backwards to find frame that is Unique to its predecessor
StartU = 0
for(i=FrmNo,1,-1) { # Exit loop normally with i==0 (i==1 is final loop)
if(!Valid) { # Unknown/Invalid
if(RT_FrameDifference(Last,Last,n=i,n2=i-1,ChromaWeight=1.0/3) > 0.0) {
StartU = i # Non dupe
i = -1 # Break, Exit with i=-2
} Else {
Valid = RT_DBaseGetField(DB,i-1,FLD_VALID) # for next time around (i-1 will not be less than 0, and if it is 0 then this is final loop )
}
} Else { # We found a Valid record prior to FrmNo, it could be final dupe in a run, or a Unique (non dupe) frm.
StartU = (RT_DBaseGetField(DB,i,FLD_PDIF) == 0.0)
\ ? i + 1 [* i was a final dupe, point at non dupe following it *]
\ : i [* i was a non dupe, we got what we wanted *]
i = -2 # Break, Exit with i=-3 :
}
}
# Scan forwards from FrmNo+1 to find next Unique frame [non dupe] (We already tested FrmNo which could be either Unique or dupe)
EndU = FC
for(i=FrmNo+1,FC-1) { #
if(!RT_DBaseGetField(DB,i,FLD_VALID)) { # Unknown/Invalid
if(RT_FrameDifference(Last,Last,n=i,n2=i-1,ChromaWeight=1.0/3) > 0.0) {
EndU = i # Unique
i = FC # Break, Exit with i=FC=+1
}
} Else { # i is Valid [ MUST BE Unique, 1st in run can never be a dupe]
EndU = i # End Unique frame
i = FC+1 # Break, Exit with i=FC+2
}
}
Count = EndU - StartU
Comb = IsCombedTIVTC(cthresh=CTHRESH,mi=MI,chroma=CHROMA,blockx=BLOCKX,blocky=BLOCKY,metric=METRIC) # Combed status of FrmNo, which is same as of StartU and all its dupes[if any].
Deint = (Comb && Count >= RUNCNT)
# We Set records StartU to EndU-1. We cant set EndU, Although Unique, it could be start of new dupe run which is set together with any dupes.
for(i=StartU,EndU-1) {
RT_DBaseSet(DB,i,True,i==0?255.0:RT_FrameDifference(Last,Last,n=i,n2=i-1,ChromaWeight=1.0/3),Comb,Deint,StartU,EndU-1,Count)
}
if(DEBUG && COMB) {
if(Deint) { RT_DebugF("%d,%d # Len=%d : Deinterlace", StartU,EndU-1,Count,name="SuperSonic: ") }
Else { RT_DebugF("#%d,%d # Len=%d : NO Deinterlace",StartU,EndU-1,Count,name="SuperSonic: ") }
}
} else { # Record status is valid
Deint = RT_DBaseGetField(DB,FrmNo,FLD_DEINT)
}
(Deint) ? DClip : Last # Use deinterlaced clip for this frame ?
if(SHOW) {
PDif = RT_DBaseGetField(DB,FrmNo,FLD_PDIF)
StartU = RT_DBaseGetField(DB,FrmNo,FLD_START)
Comb = RT_DBaseGetField(DB,FrmNo,FLD_COMB)
Count = RT_DBaseGetField(DB,FrmNo,FLD_COUNT)
RT_Subtitle("%d:%2d/%2d] %sU%sD%sC %s*DEINT*\a-\nDif=%8f",
\ FrmNo,FrmNo-StartU+1,Count,
\ (FrmNo==StartU) ? S_Wht:S_Lo, [* U Unique flag *]
\ (FrmNo!=StartU&&Count>1) ? S_Wht:S_Lo, [* D Dupe flag *]
\ (Comb) ? S_Wht:S_Lo, [* C Comb flag *]
\ (Deint) ? S_Hi :S_Lo, [* DEINT hilite *]
\ PDif
\ )
}
Return Last
"""

ScriptClip(SSS)

(STACK) ? StackHorizontal(ORG,Last) : Last


to DebugView [Only outputs duplicate runs, len shown incl first Unique frame]

00000100 20:25:46 [3092] SuperSonic: 15,29 # Len=15 : Deinterlace
00000101 20:25:46 [3092] SuperSonic: 30,44 # Len=15 : Deinterlace
00000102 20:25:46 [3092] SuperSonic: 45,59 # Len=15 : Deinterlace
00000103 20:25:46 [3092] SuperSonic: #60,71 # Len=12 : NO Deinterlace
00000104 20:25:46 [3092] SuperSonic: #72,83 # Len=12 : NO Deinterlace


It should (I hope) allow for jumping about in the clip, or even going backwards [and still show correct metrics].
Source filter needs be frame accurate.
Left Source, right bob()'ed [top of left cloud is combed, click in image twice for zoom]
https://i.postimg.cc/wBCKXfyB/Super-Sonic-00.jpg (https://postimg.cc/wtQbHkkK)
We Used BOB() for test speed, change to QTGMC option.

StainlessS
31st August 2020, 17:32
Post 4 updated. Mostly, change in metrics, as shown in prev post image.

Metrics shown when SHOW=True:
First line, "nnnn:ff/cc] UDC * DEINT *"
Where,
nnnn, Is frame number.
'ff/cc', The 'ff'th frame in 'cc' length sequence.
'1/1' would be single unique (non dupe) frame.
'1/15' would be 1st frame of 15 frame dupe run, ie first non dupe of dupe sequence.
'4/15' would be 4th frame of 15 frame dupe run, the 3rd actual duplicate.
'U' If shown, Current frame is Unique, different to its predecessor.
'D' If shown, Current frame is Duplicate, EXACT copy of its predecessor.
'C' If shown, Current frame is Combed.
'* DEINT *' If Shown, Current frame is Deinterlaced. It is both Combed, and part of a duplicate run where length of run >= RUNCOUNT.
2nd line shows difference metric between current frame and its predecessor.

StainlessS
31st August 2020, 20:23
Oops, bugfix in post #4.

if(DEBUG && COMB) {
if(Deint) { RT_DebugF("%d,%d # Len=%d : Deinterlace", StartU,EndU-1,Count,name="SuperSonic: ") }
Else { RT_DebugF("#%d,%d # Len=%d : NO Deinterlace",StartU,EndU-1,Count,name="SuperSonic: ") }
}

Was EndU, fixed EndU-1. Only affected DEBUG option output.

output now as so, eg was SuperSonic: 15,30 # Len=15 : Deinterlace NOW SuperSonic: 15,29 # Len=15 : Deinterlace

00000100 20:25:46 [3092] SuperSonic: 15,29 # Len=15 : Deinterlace
00000101 20:25:46 [3092] SuperSonic: 30,44 # Len=15 : Deinterlace
00000102 20:25:46 [3092] SuperSonic: 45,59 # Len=15 : Deinterlace
00000103 20:25:46 [3092] SuperSonic: #60,71 # Len=12 : NO Deinterlace
00000104 20:25:46 [3092] SuperSonic: #72,83 # Len=12 : NO Deinterlace

sonic41592
1st September 2020, 00:35
Unbelievable! This works EXACTLY the way I wanted it to. I really can't thank you enough for doing this! Seriously, I'm blown away with your coding abilities and level of commitment, and just want you to know you're awesome!