FrameSurgeon.avs (Excluding above posted text extracted from FrameSurgeon)
Code:
Function FrameSurgeon(clip c, String "Scmd",String "Cmd",bool "Show",Int "ShowMode",int "dv",
\ clip "FX1",clip "FX2",clip "FX3",clip "FX4",clip "FX5",clip "FX6",clip "FX7",clip "FX8",clip "FX9",
\ int "pel",int "sharp",int "rfilter",Float "ml",Bool "Final",Bool "NoErr") {
myName="FrameSurgeon: "
IsAvsPlus=FindStr(UCase(versionString),"AVISYNTH+")!=0 HasGScript=RT_FunctionExist("GScript")
Assert(IsAvsPlus || HasGSCript, RT_String("%sNeed either GScript or AVS+",myName))
Scmd = Default(Scmd,"") # User supplied list of newline separated commands.
Cmd = Default(Cmd,"") # User supplied Filename containing newline separated commands.
Show = Default(Show,false) # Show Info on frame
ShowMode= Default(ShowMode,0) # 0 = ClipClop (pre Delete frames), 1 = Prune/FrameSel (Post Delete Frames).
dv = Default(dv,0) # ClipClop DebugView level (0 - 4, Need DebugView utility)
Final = Default(Final,True) # Do Real Deletes if true
NoErr = Default(NoErr,false) # If true, Ingore FXd commands for undefined FXd clips.
############
Cmd = (Cmd!="") ? RT_GetFullPathName(Cmd) : ""
FuncS="""
Function FrameSurgeonRejectRanges(clip c,String "Cmd",Bool "Show",int "dv") {
PruneCmd = RT_GetFullPathName("~Prune_"+RT_LocalTimeString+".txt")
FrameSel_CmdReWrite(c,PruneCmd,cmd=Cmd,reject=true,Prune=True,range=true)
Prune(c,Cmd=PruneCmd,FadeIn=True,FadeSplice=True,FadeOut=True,Fade=1.0,show=Show,dv=dv)
RT_FileDelete(PruneCmd)
Return Last
}
Function FSIsDigit(String S) {return (RT_Ord(S)>=48&&RT_Ord(S)<=57)}
Function FSIsComma(String S) {return RT_Ord(S)==44}
Function FSIsHyphen(String S) {return RT_Ord(S)==45}
Function FSEatWhite(String S) {pos=1 While(RT_Ord(S,pos=pos)==32||RT_Ord(S,pos=pos)==9){pos=pos+1} return(pos>1)?MidStr(S,pos):S}
Function FSEatDigits(String S) {pos=1 While(RT_Ord(S,pos=pos)>=48&&RT_Ord(S,pos=pos)<=57){pos=pos+1} return(pos>1)?MidStr(S,pos):S}
Function FSEatOSep(String S) {pos=1 While(RT_Ord(S,pos=pos)==40||RT_Ord(S,pos=pos)==44){pos=pos+1} return(pos>1)?MidStr(S,pos):S}
Function FrameSurgeonSplitCommands(String CmdS,String ClopCmdFN,String DelCmdFN,Bool Final,String RetName) {
# Separate commands in CmdS into ClipClop, and FrameSel Reject frame commands
myName="FrameSurgeonSplitCommands: "
fxUsed=0
IdStat=False
Lines = RT_TxtQueryLines(CmdS)
For(i=0,Lines-1) {
SSS=RT_TxtGetLine(CmdS,i).FSEatWhite
if(SSS!="" && RT_Ord(SSS)!=35) { # NOT Empty line or Hash (#) ALL Comment
if(RT_FindStr(SSS,"DEL",Sig=False)==1) { # 'DEL' delete command
S=MidStr(SSS,4).FSEatWhite
Assert(FSIsDigit(S),RT_String("%sLINE_%d Expecting frame number after 'DEL'\n'%s'",myName,i+1,SSS))
if(Final) {
RT_WriteFile(DelCmdFN,"%s",S,Append=True) # Copy remainder of line (FrameSel/Prune parses Range)
} else {
RT_WriteFile(DelCmdFN,"DUMMYDELETE %s",S,Append=True) # Copy remainder of line
}
} else if(RT_Ord(SSS)==45) { # '-' delete command
S=MidStr(SSS,2).FSEatWhite
Assert(FSIsDigit(S),RT_String("%sLINE_%d Expecting frame number after '-'\n'%s'",myName,i+1,SSS))
if(Final) {
RT_WriteFile(DelCmdFN,"%s",S,Append=True) # Copy remainder of line (FrameSel/Prune parses Range)
} else {
RT_WriteFile(DelCmdFN,"DUMMYDELETE %s",S,Append=True) # Copy remainder of line
}
} else if(FSIsDigit(SSS)){
Assert(false,RT_String("%sLINE_%d Cannot use clip index in FrameSurgeon\nMUST use Command Mnemonic\n'%s'",myName,i+1,SSS))
} else {
if(RT_Ord(SSS)==73||RT_Ord(SSS)==105) { # 'I?' or 'i?' Command used ?
IdStat=true # We got at least 1 Interpolate command
if(RT_Ord(SSS,2)<48||RT_Ord(SSS,2)>57) { # IF NOT 'Id' nor 'id' Command
STEM=SSS.MidStr(2).FSEatWhite.FSEatOSep # Eat 'I' and white space and separators ['(' or ',']
Assert(STEM.FSIsDigit,RT_String("%sLINE_%d Expecting Interpolate Start frame\n'%s'",myName,i+1,SSS))
SFrm=RT_NumberValue(STEM)
EFrm=SFrm
STEM=STEM.FSEatDigits.FSEatWhite
HasComma=STEM.FSIsComma
STEM=(HasComma)?STEM.MidStr(2):STEM
STEM=STEM.FSEatWhite
HasNeg=STEM.FSIsHyphen
STEM=(HasNeg)?STEM.MidStr(2):STEM
STEM=STEM.FSEatWhite
HasDigit=STEM.FSIsDigit
Assert(HasDigit||!HasComma,RT_String("%sLINE_%d Expecting Interpolate End frame\n'%s'",myName,i+1,SSS))
Assert(HasDigit||!HasNeg,RT_String("%sLINE_%d Expecting Interpolate -ve Frame Count\n'%s'",myName,i+1,SSS))
EFrm=(HasDigit) ? RT_NumberValue(STEM) : EFrm
STEM=STEM.FSEatDigits
Frms= (HasNeg) ? EFrm : EFrm-SFrm+1
Assert(Frms>=1 && Frms<=9,RT_String("%sLINE_%d Interpolate Frame Count 1 to 9 ONLY\n'%s'",myName,i+1,SSS))
SSS=RT_String("I%d %d%s",Frms,SFrm,STEM) # Simulate ClipClop Id Command
}
} else if((RT_Ord(SSS)==70||RT_Ord(SSS)==102)&&(RT_Ord(SSS,2)==88||RT_Ord(SSS,2)==120)) { # 'FX' or 'fx' Command used ?
num=RT_Ord(SSS,3)-48
if(num>=1 && num<=9) {
fxUsed=RT_BitSet(fxUsed,num)
}
}
RT_WriteFile(ClopCmdFN,"%s",SSS,Append=True) # Copy ClipClop Commands (ClipClop parses Range)
}
}
}
Eval(RT_String("Global %s=%d",retName,fxUsed)) # Set Return Global for client
Return IdStat
}
# Temp file Names
ClopCmdFN = RT_GetFullPathName("~ClipClop_" + RT_LocalTimeString(file=True)+".txt")
DelCmdFN = RT_GetFullPathName("~Delete_" + RT_LocalTimeString(file=True)+".txt")
# Init to zero, one-time Globals, for returning which FXd clips used in commands
retNameC="G_FS_FxUsedC_"+RT_LocalTimeString(file=True) Eval(RT_String("Global %s=0",retNameC))
retNameS="G_FS_FxUsedS_"+RT_LocalTimeString(file=True) Eval(RT_String("Global %s=0",retNameS))
# Separate into Replace(ClipClop) and Delete(FrameSel/Prune) Commands, Cmd File Processed first
UseMvTools=(Cmd!=""&&Exist(Cmd)) ? FrameSurgeonSplitCommands(RT_ReadTxtFromFile(Cmd),ClopCmdFN,DelCmdFN,Final,retNameC) : False
UseMvTools=(SCmd!="") ? FrameSurgeonSplitCommands(SCmd,ClopCmdFN,DelCmdFN,Final,retNameS)||UseMvTools : UseMvTools
Assert(c.IsPlanar||c.IsYUY2||!UseMvTools,"FrameSurgeon: Id Interpolation commands Planar and YUY2 ONLY")
# Get FrameSurgeonSplitCommands results from one-time Globals
Eval(RT_String("fxUsedC=%s",retNameC)) Eval(RT_String("fxUsedS=%s",retNameS))
# find FXd commands used for undefined FXd clips
FXErr=0 E_C_Str="" E_S_Str=""
for(i=1,9) {
Eval(RT_string("Fxdef=FX%d.Defined",i))
if(!fxDef) {
if(RT_BitTst(fxUsedC,i) || RT_BitTst(fxUsedS,i)) {
FXErr=FXErr+1
if(RT_BitTst(fxUsedC,i)) {
STemp=RT_String("*** WARNING *** FX%d Used in CMD but not supplied as clip\n",i)
E_C_Str=E_C_Str+STemp
}
if(RT_BitTst(fxUsedS,i)) {
STemp=RT_String("*** WARNING *** FX%d Used in SCMD but not supplied as clip\n",i)
E_S_Str=E_S_Str+STemp
}
}
}
}
if(FXErr!=0) {
# FXd clip is used in SCMD or CMD, BUT NOT supplied by client script
RT_DebugF("\n%s%s",E_C_Str,E_S_Str,name=myName)
Assert(NoErr || SHOW || !FINAL,RT_String("%sFINAL=True (Set NoErr=True to Ignore below commands, src will be used)\n%s%s",myName,E_C_Str,E_S_Str))
}
############
BSZ = c.Height/(40*2)*2 FSZ=c.Height/(5*2)*2
LBOX = c.LetterBox(BSZ,BSZ,BSZ,BSZ,$0000FF)
SYNTH = (Show||!FINAL) # If SHOW or FINAL=False then synthesize UnDefined FXd clips (subtitled), Otherwise use src clip c.
FX1 = Default(FX1,(SYNTH)?LBOX.Subtitle("FX1",Align=5,Size=FSZ,Text_Color=$0000FF):c)
FX2 = Default(FX2,(SYNTH)?LBOX.Subtitle("FX2",Align=5,Size=FSZ,Text_Color=$0000FF):c)
FX3 = Default(FX3,(SYNTH)?LBOX.Subtitle("FX3",Align=5,Size=FSZ,Text_Color=$0000FF):c)
FX4 = Default(FX4,(SYNTH)?LBOX.Subtitle("FX4",Align=5,Size=FSZ,Text_Color=$0000FF):c)
FX5 = Default(FX5,(SYNTH)?LBOX.Subtitle("FX5",Align=5,Size=FSZ,Text_Color=$0000FF):c)
FX6 = Default(FX6,(SYNTH)?LBOX.Subtitle("FX6",Align=5,Size=FSZ,Text_Color=$0000FF):c)
FX7 = Default(FX7,(SYNTH)?LBOX.Subtitle("FX7",Align=5,Size=FSZ,Text_Color=$0000FF):c)
FX8 = Default(FX8,(SYNTH)?LBOX.Subtitle("FX8",Align=5,Size=FSZ,Text_Color=$0000FF):c)
FX9 = Default(FX9,(SYNTH)?LBOX.Subtitle("FX9",Align=5,Size=FSZ,Text_Color=$0000FF):c)
###
###
DUMMYDELETE = c.LetterBox(BSZ,BSZ,BSZ,BSZ,$FF0000).Subtitle("DUMMY DELETE",Align=5,Size=FSZ/2,Text_Color=$FF0000)
CP = c.DeleteFrame(c.Framecount()-1).DuplicateFrame(0)
CN = c.DuplicateFrame(c.Framecount()-1).DeleteFrame(0)
###
NICKNAME=(" # Define ClipClop Command mnemonics allowed in command string and file.
DUMMYDELETE=1 # PRIVATE COMMAND, for FINAL=False
CP =2 # CopyFromPrevious (frame n replaced with frame n-1)
CN =3 # CopyFromNext (frame n replaced with frame n+1)
FX1 =4 # FX1 (User replacement FXd clips)
FX2 =5 # FX2
FX3 =6 # FX3
FX4 =7 # FX4
FX5 =8 # FX5
FX6 =9 # FX6
FX7 =10 # FX7
FX8 =11 # FX8
FX9 =12 # FX9
")
if(!FINAL && Exist(DelCmdFN)) {
RT_WriteFile(ClopCmdFN,"%s",RT_ReadTxtFromFile(DelCmdFN),Append=True) # Append Delete Prune commands to ClipClop command file
RT_FileDelete(DelCmdFN) # DONT PRUNE
ShowMode=0 # Force ClipClop ShowMode
}
if(!UseMvTools) {
Clopped = (Exist(ClopCmdFN)) ? c.ClipClop(
\ DUMMYDELETE,
\ CP,
\ CN,
\ FX1,FX2,FX3,FX4,FX5,FX6,FX7,FX8,FX9,
\ cmd=ClopCmdFN,sCmd="",show=(SHOW&&ShowMode==0),ver=False,dv=DV,NoErr=False,nickname=NICKNAME,Purge=True
\) : c
} else {
pel = Default(pel,2) # Default as for MSuper(), ie 2, range=1 or 2 or 4
sharp = Default(sharp,2) # Default as for MSuper(), ie 2, range=0 -> 2
rfilter = Default(rfilter,2) # Default as for MSuper(), ie 2, range=0 -> 4
ml = Float(default(ml,100.0)) # Default as for MFlowInter(), ie 100.0, range=greater than 0.0.
###
thSCD1=(8*8)*255 thSCD2=255 BLEND=False bs=(CP.width>960) ? 16 : 8
supFilt = CP.Blur(0.6).MSuper(pel=2,sharp=sharp,rfilter=rfilter,hpad=16, vpad=16)
sup = CP.MSuper(pel=2,sharp=sharp,rfilter=rfilter,hpad=16, vpad=16, levels=1)
For(Bad=1,9) {
Eval(RT_String("I%0.2d_bv=supFilt.MAnalyse(isb=true, delta=%d,blksize=bs,overlap=bs/2)",Bad,Bad+1))
Eval(RT_String("I%0.2d_fv=supFilt.MAnalyse(isb=false,delta=%d,blksize=bs,overlap=bs/2)",Bad,Bad+1))
Eval(RT_String("I%0.2d_bv=MRecalculate(sup,I%0.2d_bv,blksize=bs/2,overlap=2,thSAD=100)",Bad,Bad))
Eval(RT_String("I%0.2d_fv=MRecalculate(sup,I%0.2d_fv,blksize=bs/2,overlap=2,thSAD=100)",Bad,Bad))
for(i=1,Bad) {
Eval(RT_String("I%0.2d_%0.2d=CP.MFlowInter(sup,I%0.2d_bv,I%0.2d_fv,time=100.0*%d/%d,ml=ml,Blend=BLEND,thSCD1=thSCD1,thSCD2=thSCD2)",
\ Bad,i,Bad,Bad,i,Bad+1))
}
}
###
NICKNAME=NICKNAME+("
I1 =13:1 # Interpolate 1
I2 =14:2 # Interpolate 2
I3 =16:3 # Interpolate 3
I4 =19:4 # Interpolate 4
I5 =23:5 # Interpolate 5
I6 =28:6 # Interpolate 6
I7 =34:7 # Interpolate 7
I8 =41:8 # Interpolate 8
I9 =49:9 # Interpolate 9
")
###
Clopped = (Exist(ClopCmdFN)) ? c.ClipClop(
\ DUMMYDELETE,
\ CP,
\ CN,
\ FX1,FX2,FX3,FX4,FX5,FX6,FX7,FX8,FX9,
\ I01_01,
\ I02_01,I02_02,
\ I03_01,I03_02,I03_03,
\ I04_01,I04_02,I04_03,I04_04,
\ I05_01,I05_02,I05_03,I05_04,I05_05,
\ I06_01,I06_02,I06_03,I06_04,I06_05,I06_06,
\ I07_01,I07_02,I07_03,I07_04,I07_05,I07_06,I07_07,
\ I08_01,I08_02,I08_03,I08_04,I08_05,I08_06,I08_07,I08_08,
\ I09_01,I09_02,I09_03,I09_04,I09_05,I09_06,I09_07,I09_08,I09_09,
\ cmd=ClopCmdFN,sCmd="",show=(SHOW&&ShowMode==0),ver=False,dv=DV,NoErr=False,nickname=NICKNAME,Purge=True
\) : c
}
"""
IsAvsPlus?Eval(FuncS):GScript(FuncS)
Result = (Exist(DelCmdFN)) ? FrameSurgeonRejectRanges(clopped,Cmd=DelCmdFN,show=(SHOW&&ShowMode==1),dv=dv) : Clopped
RT_FileDelete(ClopCmdFN) RT_FileDelete(DelCmdFN) # Delete Temps
Return Result
}