View Full Version : Resize Function CAVIStreamSynth Access Violation
Umamio
24th August 2008, 19:34
I am trying to create a general purpose "Resize to PAL-DVD" function that deals with resizing videos that have strange aspect ratios.
My assumptions (based on QuEnc options) are that 4:3, 16:9, 2.21:1 are DVD compliant aspect ratios but that doesn't really matter for now.
What the function is meant to do is: if a video has an aspect ratio between two boundaries (e.g. between 4:3 and 16:9) it calculates which aspect ratio would provide the most active (non black border) pixels when resized to 720x576 and then adds top and bottom or left and right borders accordingly to fill the frame.
Here is my script:
function pillarise(clip v, barsize)
{
barsize = Round(barsize)
v = ((Frac(barsize/2.0) ) == 0) ? v : ConvertToRGB32(v)
return v.AddBorders(barsize,0,barsize,0)
}
function borderise(clip v, barsize)
{
barsize = Round(barsize)
v = ((Frac(barsize/2.0) ) == 0) ? v : ConvertToRGB32(v)
return v.AddBorders(0,barsize,0,barsize)
}
function pixelBattle (clip c,TrueAR, Frame1, Frame2, FinalWidth, FinalHeight)
{
##########Rules##########
#
# Frame1 AR < TrueAR < Frame2 AR
#
#########################
# Height Modifiers Examples, PAL Anamorphic
# 4:3 = 576/540 ,
# 16:9 = 576/405,
# 2.21:1 = 576/326
###Borderise
HeightMod = (FinalHeight / (FinalWidth / Frame1))
#HeightMod = ((Frame1 == (4/3)) ? (576/540) :
# \ (Frame1 == (16/9)) ? (576/405) :
# \ (Frame1 == (2.21/1)) ? (576/326) : 2)
# Width Modifiers Examples, PAL Anamorphic
# 4:3 = 720/768 ,
# 16:9 = 720/1024,
# 2.21:1 = 720/1272
###Pillarise
WidthMod = (FinalWidth / (FinalHeight * Frame2))
#WidthMod = ((Frame1 == (4/3)) ? (720/768) :
# \ (Frame1 == (16/9)) ? (720/1024) :
# \ (Frame1 == (2.21/1)) ? (720/1272) )
ActivePix1 = FinalWidth / TrueAR * (HeightMod) * FinalWidth
ActivePix2 = FinalHeight * TrueAR * (WidthMod) * FinalHeight
c = (ActivePix1 >= ActivePix2) ? c.borderise((float(c.width)/TrueAR - float(c.width)/Frame1) / 2.0) : c.pillarise(c.height*(Frame2 - TrueAR)/2.0)
return c
}
function toPALDVD (clip c, TrueAR)
{
##Aspect Ratio Buffer Percentage
x = 2
#if (TrueAR == 4:3 +- x%) Resize, AR = 4x3
#else if (TrueAR < 4:3) HeightFixed(576)ResizeWidth+SideBorders43
#else if (TrueAR == 16:9 +- x%) Resize AR = 16x9,
#else if (TrueAR < 16:9) WidthFixed(720)ResizeWidth+TopBot43, HeightFixed(576)ResizeWidth+SideBorders169 [ChooseMostActivePixels]
#else if (TrueAR == 2.21 +- x%) Resize, AR = 2.21
#else if (TrueAR < 2.21) WidthFixed(720)ResizeWidth+TopBot169, HeightFixed(576)ResizeWidth+SideBorders221 [ChooseMostActivePixels]
#else if (TrueAR > 2.21) WidthFixed(720)ResizeWidth+TopBot221
c = ( (TrueAR > ((1-(x/100.0))*4.0/3)) && (TrueAR < ((1+(x/100.0))*4.0/3)) ? c:
\ (TrueAR < (4.0/3)) ? c.pillarise(Round((c.height*(4.0/3 - TrueAR))/2)):
\ (TrueAR > ((1-(x/100.0))*16.0/9)) && (TrueAR < ((1+(x/100))*16.0/9)) ? c:
\ (TrueAR < (16.0/9))? c.pixelBattle(TrueAR, 4.0/3, 16.0/9, 720.0 , 576.0):
\ (TrueAR > ((1-(x/100.0))*2.21)) && (TrueAR < ((1+(x/100.0))*2.21)) ? c:
\ (TrueAR < (2.21)) ? c.pixelBattle(TrueAR, 16.0/9, 2.21/1, 720.0 , 576.0) :
\ (TrueAR > (2.21)) ? c.borderise((float(c.width)/TrueAR - float(c.width)/2.21) / 2.0) : c )
return c.Spline36Resize(720,576)
}
AviSource("WeirdAR.avi")
TrueAR = 1.568
toPALDVD(TrueAR)
The function seems to work when adding left and right borders but chokes and throws up exceptions when it's meant to add top and bottom borders
I suspect this line is causing the problem, I have tried replacing the values with random integers instead of variables, and it works then, but I can't seem to make it work with these vars
(float(c.width)/TrueAR - float(c.width)/Frame1)
Any help would be much appreciated!
If anyone has any helpful tips to debug avisynth scripts that would be great too
If it's trying to do integer division again (http://forum.doom9.org/showthread.php?t=140437) somewhere and I haven't realised, I will cry.
Please forgive my ugly code.
Gavino
24th August 2008, 20:49
...
function toPALDVD (clip c, TrueAR)
{ ...
\ (TrueAR > (2.21)) ? c.borderise((float(c.width)/TrueAR - float(c.width)/2.21) / 2.0) : c)
This produces a negative border size.
I haven't worked throught the logic in your other function but I suspect the same thing happens with the line you were worried about.(float(c.width)/TrueAR - float(c.width)/Frame1)
You should add types (eg float) to the parameter names in your functions, otherwise you are losing out on typechecking which can detect errors.
For simple debugging, use Subtitle to show intermediate values on the screen.
Umamio
24th August 2008, 22:31
Thanks again, Gavino. I should have spotted it, I am blind.
Is there a way to print non-string vars using subtitle? Or a toString type function to stringify them. Or some special syntax?
Here is the function as is for anyone interested.
function pillarise(clip v, float barsize)
{
barsize = Abs(Round(barsize))
v = ((Frac(barsize/2.0) ) == 0) ? v : ConvertToRGB32(v)
return v.AddBorders(barsize,0,barsize,0)
}
function borderise(clip v, float barsize)
{
barsize = Abs(Round(barsize))
v = ((Frac(barsize/2.0) ) == 0) ? v : ConvertToRGB32(v)
return v.AddBorders(0,barsize,0,barsize)
}
function pixelBattle (clip c,float TrueAR, float Frame1, float Frame2, float FinalWidth, float FinalHeight)
{
HeightMod = (FinalHeight / (FinalWidth / Frame1))
WidthMod = (FinalWidth / (FinalHeight * Frame2))
ActivePix1 = FinalWidth / TrueAR * (HeightMod) * FinalWidth
ActivePix2 = FinalHeight * TrueAR * (WidthMod) * FinalHeight
Filename = String(FileSource)+".log"
TextSeparator = ": Chosen Frame Aspect: "
c = (ActivePix1 >= ActivePix2) ? c.borderise((float(c.width)/Frame1 - float(c.width)/TrueAR) / 2.0).WriteFileEnd(Filename, "FileSource", "TextSeparator", "Frame1") : c.pillarise(Round(c.height*(Frame2 - TrueAR)/2.0)).WriteFileEnd(Filename, "FileSource", "TextSeparator", "Frame2")
return c
}
function toPALDVD (clip c, float TrueAR)
{
x = 1
c = ( (TrueAR > ((1-(x/100.0))*4.0/3)) && (TrueAR < ((1+(x/100.0))*4.0/3)) ? c:
\ (TrueAR < (4.0/3)) ? c.pillarise(Round((c.height*(4.0/3 - TrueAR))/2)):
\ (TrueAR > ((1-(x/100.0))*16.0/9)) && (TrueAR < ((1+(x/100))*16.0/9)) ? c:
\ (TrueAR < (16.0/9))? c.pixelBattle(TrueAR, 4.0/3, 16.0/9, 720.0 , 576.0):
\ (TrueAR > ((1-(x/100.0))*2.21)) && (TrueAR < ((1+(x/100.0))*2.21)) ? c:
\ (TrueAR < (2.21)) ? c.pixelBattle(TrueAR, 16.0/9, 2.21/1, 720.0 , 576.0) :
\ (TrueAR > (2.21)) ? c.borderise((float(c.width)/2.21 - float(c.width)/TrueAR) / 2.0) : c )
return c.Spline36Resize(720,576).ConvertToYV12
}
global FileSource = "TheBestestVideoInTheWorld.avi"
AviSource(FileSource)
TrueAR = 1.539601
toPALDVD(TrueAR)
Gavino
24th August 2008, 22:41
Is there a way to print non-string vars using subtitle? Or a toString type function to stringify them.
Yes, for example, you can saySubtitle(string(x)) where x is any type except clip.
BTW it seems wrong to me that AddBorders should accept a negative argument, leading to your access violation. I have raised this in the development forum.
Gavino
25th August 2008, 10:40
@Umamio
A further note re debugging with Subtitle/String: I have discovered that the String function is more versatile than the documentation (http://avisynth.org/mediawiki/Internal_functions/Conversion_functions) suggests. You can actually add arbitrary text to the format string, printf-style.
So instead of something like
Subtitle("Value of x is " + String(x) + " after AR calc"))
you can write it alternatively as
Subtitle(String(x, "Value of x is %.3f after AR calc"))
When doing it this way, note that for integers you have to use %.0f not %d, as they are treated internally as float.
Wilbert
25th August 2008, 17:40
A further note re debugging with Subtitle/String: I have discovered that the String function is more versatile than the documentation suggests. You can actually add arbitrary text to the format string, printf-style.
Nice find! If you know how, you may update the online documentation :)
Gavino
25th August 2008, 20:20
Nice find! If you know how, you may update the online documentation :)
OK, Wilbert - now done.
My 'discovery' opens the way to a function like this:
function Printf(clip c, val v, string "format") {
c.Subtitle(string(v, format)) # format optional, OK if undefined
}
#Examples:
Printf(myVar)
Printf(AR, "AR = %.3f after resize")
which could be easily extended with arguments to control subtitle postition, etc
Umamio
27th August 2008, 01:10
Thanks for the string help Gavino! It helped me to realise my border calculations were completely fubar'd.
As film aspect approaches infinity, border approaches film height. Maximum Aspect 2:1? So completely wrong.
I will post a modified version when I stop being an idiot.
This is PseudoCode / algebra I have thought of for top and bottom bordering.
[SIZE="1"]
SourceHeight = SourceWidth / TrueAspect = (W/T)
FrameHeight = SourceWidth / FrameAspect = (W/F)
BorderFillPercentage = ((FrameHeight - SourceHeight) / FrameHeight) = (1 - (SourceHeight/FrameHeight))
BF% = BorderFillPercentage
SourceHeight = k * (1-BF%)
K = SourceHeight / (1-BF%)
TotalBorderHeight = k * BF%
TotalBorderHeight = (SourceHeight / (1-BF%)) * BF%
TotalBorderHeight = (SourceHeight / (1-(1 - (SourceHeight/FrameHeight)))) * (1 - (SourceHeight/FrameHeight))
= ((W/T) / (1-(1 - ((W/T)/(W/F))))) * (1 - ((W/T)/(W/F)))
= ((W/T) / ((W/T)/(W/F))) * (1 - ((W/T)/(W/F)))
Top/BottomBorderHeight = TotalBorderHeight / 2
Edit: Oops, Still wrong
Edit2: SourceHeight = (SourceHeight+TotalBorderHeight) * (1-BF%)
(SourceHeight / (1-BF%) ) - Sourceheight = TotalBorderHeight
TotalborderHeight = (SourceHeight / (1-(1 - (SourceHeight/FrameHeight)))) - SourceHeight
... whaaat
Okay, I will stop algebra spamming now
Gavino
27th August 2008, 22:22
I'm not sure I follow your method of working it out, but doing it myself I reckon the border size should be:
clip.height*(TrueAR/DisplayAR - 1)/2
for TrueAR > DisplayAR (letterbox format), and
clip.width*(DisplayAR/TrueAR - 1)/2
for DisplayAR > TrueAR (pillarbox format).
Umamio
28th August 2008, 17:12
I think what you wrote simplifies to
(Letterbox, fixed width)
Height = clip.width/TrueAR
clip.height*(TrueAR/DisplayAR - 1)/2
= clip.width/TrueAR*(TrueAR/DisplayAR - 1)/2
= (clip.width/DisplayAR - Clip.width/TrueAR)/2
= (W/F - W/T)/2
= W/2 * (1/F - 1/T)
&
(Pillarbox Fixed Height)
(H*F - H*T) / 2
= H/2 * (F-T)
Which is what I coded originally, which appears to be... correct. I think I drank too much crazy juice last night.
Apologies for my confusion.
Gavino
28th August 2008, 19:40
I think what you wrote simplifies to
(Letterbox, fixed width)
Height = clip.width/TrueAR
clip.height*(TrueAR/DisplayAR - 1)/2
= clip.width/TrueAR*(TrueAR/DisplayAR - 1)/2
Only if you assume that TrueAR is the actual AR of the clip (clip.width/clip.height). I thought the whole point was that it could be different - otherwise, what is the point of passing it in as a parameter?
Consider a standard PAL DV clip of 720x576, 'true' AR (if I understand your terminology) is 4:3 (not 5:4), so it should be passed unchanged by your function and have display AR also set to 4:3.
Umamio
28th August 2008, 22:23
Oh yes. You are completely correct.:thanks:
Would you like to check the rest of my code for logical errors? I am sure there are plenty :)
toDelivery.avsi
global finalFrameAspect = 0
function SetFinalFrameAR(clip v, float AR)
{
global finalFrameAspect = AR
return v
}
function letterise(clip v, float DisplayAR, float TrueAR)
{
bars = v.height*(TrueAR/DisplayAR - 1)/2
v.letterMaker(bars)
}
function pillarise(clip v, float DisplayAR, float TrueAR)
{
bars = v.width*(DisplayAR/TrueAR - 1)/2
v.pillarMaker(bars)
}
function pillarMaker(clip v, float barsize)
{
barsize = Abs(Round(barsize))
v = ((Frac(barsize/2.0) ) == 0) ? v : ConvertToRGB32(v)
return v.AddBorders(barsize,0,barsize,0)
}
function letterMaker(clip v, float barsize)
{
barsize = Abs(Round(barsize))
v = ((Frac(barsize/2.0) ) == 0) ? v : ConvertToRGB32(v)
return v.AddBorders(0,barsize,0,barsize)
}
function pixelBattle (clip c,float TrueAR, float Frame1, float Frame2, float "FinalWidth", float "FinalHeight")
{
checkFrameAspects = (Frame1 > Frame2)? Eval("""
Temp = Frame1
Frame1 = Frame2
Frame2 = Temp
return Temp
""") : 0
FinalWidth = Default(FinalWidth, 720.0)
FinalHeight = Default(FinalHeight, 576.0)
HeightMod = FinalHeight / (FinalWidth / Frame1)
WidthMod = FinalWidth / (FinalHeight * Frame2)
ActivePix1 = FinalWidth / TrueAR * HeightMod * FinalWidth
ActivePix2 = FinalHeight * TrueAR * WidthMod * FinalHeight
c = (ActivePix1 >= ActivePix2) ? c.letterise(Frame1, TrueAR).SetFinalFrameAR(Frame1)
\ : c.pillarise(Frame2, TrueAR).SetFinalFrameAR(Frame2)
return c
}
# Output: PAL-DVD, non-compliant framerates allowed.
function toJoost(clip c, float TrueAR, float "ARbuffer", int "widthFinal", int "heightFinal")
{
widthFinal = Default(widthFinal, 720)
heightFinal = Default(heightFinal, 576)
x = Default(ARbuffer, 0.5)
c = ( ((TrueAR >= ((4.0/3)*(1-float(x)/100))) && (TrueAR <= ((4.0/3)*(1+float(x)/100)))) ? c.SetFinalFrameAR(4.0/3) :
\ ((TrueAR >= ((16.0/9)*(1-float(x)/100))) && (TrueAR <= ((16.0/9)*(1+float(x)/100)))) ? c.SetFinalFrameAR(16.0/9):
\ ((TrueAR >= ((2.21)*(1-float(x)/100))) && (TrueAR <= ((2.21)*(1+float(x)/100)))) ? c.SetFinalFrameAR(2.21):
\ (TrueAR < (4.0/3)) ? c.pillarise(4.0/3, TrueAR) :
\ ((TrueAR > (4.0/3)) && (TrueAR<16.0/9)) ? c.pixelBattle(TrueAR, 4.0/3, 16.0/9, widthFinal, heightFinal):
\ ((TrueAR > (16.0/9)) && (TrueAR<2.21)) ? c.pixelBattle(TrueAR, 16.0/9, 2.21, widthFinal, heightFinal):
\ (TrueAR > (2.21)) ? c.letterise(2.21, TrueAR).SetFinalFrameAR(2.21) :
\ c.SetFinalAR(0.0) )
return c.Spline36Resize(widthFinal, heightFinal).ConvertToYV12
}
#Output: 4:3 Frame, 640x480, square pixels
function toBlinkx(clip c, float TrueAR, float "ARbuffer", int "widthFinal", int "heightFinal")
{
widthFinal = Default(widthFinal, 640)
heightFinal = Default(heightFinal, 480)
x = Default(ARbuffer, 0.5)
c = ( ((TrueAR >= ((4.0/3)*(1-float(x)/100))) && (TrueAR <= ((4.0/3)*(1+float(x)/100)))) ? c :
\ ( TrueAR > 4.0/3 ) ? c.letterise(4.0/3, TrueAR):
\ (TrueAR < 4.0/3 ) ? c.pillarise(4.0/3, TrueAR) : c)
return c.Spline36Resize(widthFinal, heightFinal).ConvertToYV12.SetFinalFrameAR(4.0/3)
}
#Output: 640x480 Fullscreen, 854x480 Widescreen, square pixels
function toVuze(clip c, float TrueAR, float "ARbuffer")
{
heightFinal = Default(heightFinal, 480)
x = Default(ARbuffer, 0.5)
c = ( ((TrueAR >= ((4.0/3)*(1-float(x)/100))) && (TrueAR <= ((4.0/3)*(1+float(x)/100)))) ? c.Spline36Resize(640,480).ConvertToYV12.SetFinalFrameAR(4.0/3) :
\ ((TrueAR >= ((16.0/9)*(1-float(x)/100))) && (TrueAR <= ((16.0/9)*(1+float(x)/100))))? c.ConvertToRGB32. Spline36Resize(854,480).SetFinalFrameAR(16.0/9):
\ (TrueAR > 4.0/3 ) && (TrueAR < (16.0/9)) ? c.pillarise(16.0/9, TrueAR).ConvertToRGB32. Spline36Resize(854,480).SetFinalFrameAR(16.0/9):
\ (TrueAR < 4.0/3 ) ? c.pillarise(4.0/3, TrueAR).Spline36Resize(640,480).ConvertToYV12.SetFinalFrameAR(4.0/3) : c)
return c
}
#Output: borders not allowed, mod8 dimensions, width 720, square pixels
function toBlinkBox(clip c, float TrueAR, float "widthFinal")
{
#width fixed
widthFinal = Default(widthFinal, 720)
# mod 8 height
heightFinal = Round((widthFinal/TrueAR)/8)*8
#AR Error = ...
return c.spline36Resize(widthFinal, heightFinal).ConvertToYV12#SetFinalFrameAR(...)
}
#
function toZvue()
{}
# 4:3 Frame, 640x480, 480x360, 320x240 square pixels
function toJalipo()
{}
# 368x288, mod for mobile, square pixels
function toTmob()
{}
LogoFunc.avsi
function Logoise (clip c, int "TruePixel", int "SourcePixel", string "Position", float "ARbuffer")
{
# If unspecified set destination frame as SquarePixel
TruePixel = Default(TruePixel, 1)
SourcePixel = Default(SourcePixel, 1)
Position = Default(Position, "before")
# Source Logo Intro Animation Audio & Video
LogoV = DirectShowSource("C:\Compressionism\_Video\Source\Logos\Logo").ConvertToRGB32
AudioStereo = WavSource("C:\Compressionism\_Video\Source\Logos\Feature-Stereo.wav")
Audio51 = DirectShowSource ("C:\Compressionism\_Video\Source\Logos\Feature-51.ac3")
# Frame duration before which film is classified as "Short"
MaxShortFilmFrames = 53946
# Trim Intro Logo frame constants for short Film
TrimStart=124
TrimEnd=201
# True Source Aspect Ratio, taking into account pixel shape
# e.g Anamorphic Wide: (720/576)*(1024/720)
# e.g Square Pixels: (720/404)*(1/1)
SourceAR = (float(c.width)/c.height)*(float(TruePixel)/SourcePixel)
#Logo Aspect Ratio (Assume Square Pixels Intro Logo)
LogoAR = float(LogoV.width)/LogoV.height
#Acceptable Logo Aspect Ratio error Percentage
ARerror = Default(ARbuffer, 3)
#Acceptable Logo Speedup/Slowdown Percentage
SpeedMod = 5
# Match Audio Channels and Dub
Logo = (c.Audiochannels == 6) ? AudioDub(LogoV,Audio51) : AudioDub(LogoV,AudioStereo)
# Determine Intro Type (Short/Long) & Trim accordingly
Logo = (c.Framecount<MaxShortFilmFrames) ? Logo.Trim(TrimStart,TrimEnd) : Logo
# Match Framerate
#If framerate difference greater than acceptable; change fps (decimate duplicate), otherwise, speedup / slowdown logo to match film.
Logo = ( (c.FramerateNumerator == Logo.FramerateNumerator) && (c.FramerateDenominator == Logo.FramerateDenominator) ? Logo :
\ (c.Framerate > float(c.Framerate*(1+(SpeedMod/100)))) || (c.Framerate < float(c.Framerate*(1-(SpeedMod/100)))) ? Logo.ChangeFPS(c.FramerateNumerator , c.FramerateDenominator, true) : Logo.AssumeFPS(c.FramerateNumerator , c.FramerateDenominator, true))
#Match True Aspect Ratio
LogoModifier = Abs(Round((((Logo.Height)*SourceAR)-(Logo.Width))/2))
Logo = ( (SourceAR < float((1-(ARerror/100))*LogoAR)) ? Logo.Crop(LogoModifier,0,-LogoModifier,0) :
\ (SourceAR > float((1+(ARerror/100))*LogoAR)) ? Logo.AddBorders(LogoModifier,0,LogoModifier,0) : Logo)
#Match Frame Dimensions
Logo = Logo.Spline36Resize(c.width, c.height)
#Match Colourspace
Logo = ( (c.IsYV12) ? ConvertToYV12(Logo) :
\ (c.IsRGB32) ? Logo :
\ (c.IsRGB24) ? ConvertToRGB24(Logo) :
\ (c.IsYUY2) ? ConvertToYUY2(Logo) :
\ (c.IsYUV) ? ConvertToYUV(Logo) :
\ (c.IsRGB) ? ConvertToRGB(Logo) : Logo)
#Match Sample Rate
Logo = (c.Audiorate == Logo.Audiorate) ? Logo : Logo.ResampleAudio(c.Audiorate)
#Match AudioBits
Logo = ( (c.Audiobits == Logo.Audiobits) ? Logo :
\ (c.Audiobits == 16) ? Logo.ConvertAudioTo16bit :
\ (c.Audiobits == 24) ?Logo.ConvertAudioTo24bit :
\ (c.Audiobits == 32) ?Logo.ConvertAudioTo32bit :
\ (c.Audiobits == 8) ?Logo.ConvertAudioTo8bit : Logo )
c = (Position == "after")? c++Logo : Logo++c
return c
}
TestVideo.avs
# Import Delivery Specification Functions
Import("C:\Compressionism\_Video\Source\_EncodingProfiles\toDelivery.avsi")
# Import Logo Join Function
Import("C:\Compressionism\_Video\Source\_EncodingProfiles\LogoFunc.avsi")
# Set Global Location Constants
global fileSource = "C:\Compressionism\_Video\Source\Shorts\998_RFF16"
global logFile = String(FileSource)+".log"
v = DGDecode_mpeg2source("C:\Compressionism\_Video\Source\Shorts\998_RFF16\VTS_01_1.d2v", cpu=0, info=3).ColorMatrix(hints=true)
a = WAVSource("C:\Compressionism\_Video\Source\Shorts\998_RFF16\VTS_01_1 Ta0 48K 16bit 2ch.wav")
#PixelsHigh = ...
#PixelsWide = ...
#PixelShape = ...
#True AR = ...
# Create Final Video Output, Dub/Crop/Deinterlace/Trim/Processing/Sharpen/Deblock/Pan(Animate)/FadeIn/FadeOut/ etc....
#Load_Stdcall_Plugin("C:\Program Files\megui\tools\yadif\yadif.dll")
AudioDub(v,a)#Trim(130,159811).Yadif.ConvertToRGB32.Crop(...
### Set True Video AR ###
# Either use decimal value (eg 1.7777778)
# Or for fractional Ensure Floating Point Division by placing a decimal point in numerator (e.g 16.0/9 )
TrueAR = 15.3/9
### Select Delivery Spec ###
#toJoost(TrueAR, ARbuffer = 2)(any float) to set acceptable aspect error percentage, default = half a percent
#toJoost(TrueAR, TruePixel=1024, SourcePixel=720)
toBlinkx()
#toVuze
#toBlinkbox
# Logoise (768, 720) / (1024, 720) / (1272, 720) etc for anamorphic pixels (Joost!)
# Logoise (1,1) or Logoise() for square pixels (everything not joost)
# Logoise (Position = "after") to place logo after the video
# Logoise (ARbuffer = 2) (any float) to enable acceptable aspect error percentage
Logoise
# Output video specs, Frame Size, Aspect, Framerate, Audio Channels, etc.
# Use WriteFileEnd logfile, ToDo
Gavino
29th August 2008, 20:19
Would you like to check the rest of my code for logical errors? I am sure there are plenty :)
The only obvious error I can see is
function toVuze(clip c, float TrueAR, float "ARbuffer")
{
heightFinal = Default(heightFinal, 480)
where heightFinal does not exist.
As I am not infallible, there may still be others. ;)
It's not an error as such, but you could rewrite
barsize = Abs(Round(barsize))
v = ((Frac(barsize/2.0) ) == 0) ? ....
as
barsize = Abs(Round(barsize))
v = ((barsize%2) == 0) ? ....
since the rounding has already converted barsize to int.
Umamio
2nd September 2008, 13:31
Not as many mistakes as I expected!
I was flirting with the idea of making the height an optional variable in that function but the delivery spec for that company will never change so it's not really worth it.
Now that things seem to be working alright I am thinking of cleaning up my code and setting more globals (TrueAR & Crop values, input PixelShape, output Pixelshape) which can be optionally overridden.
I am not sure of the correct syntax though.
For instance, if I specify global TrueAR and want to make it the default value of a local variable named TrueAR in a function would it be something like:
function dummyFunc(clip v, float "TrueAR")
{
TrueAR = Default(TrueAR, global TrueAR)
}
Or will this variable naming create problems?
Also I would like to output the video information (contents of info() ) to file. Can this be achieved using WriteFileEnd?
Also, most of these functions are just checking video properties to determine what to output, but the properties are constant, so I don't really need the checks happening for every frame.
Is there a way to make them just run once?
Like... on the first frame the functions append a string with the calculated video functions and then I later Eval that string.
Something like that, or whatever works to eliminate unnecessary computation!
Lastly, I am thinking of making a poor man's audio mixer for the Logo audio. Along the lines of:
If source video has 1 audio channel, Merge Stereo -> Mono
If source video has 2 audio channels, Use stereo
If source video has 3 audio channels, Use stereo (left and right) channels + used merged audio on centre channel
if source video has 4 audio channels, use stereo on front 2 and back 2,
if source video has 5 audio channels, use stereo on front 2 and back 2, use merged stereo on centre
if source video has 6 audio channels, use 5.1 source
My problem is I am not sure in which order avisynth numbers the channels and I don't know if nested ifs is the most elegant way to code it. Like... I could use recursion
function AudioMaker(channels)
{
if (channels==6)
audio = 6channelac3audio
else
while channels>0
{
if odd channels
{
if (channels == 1)
audio = MergeStereo
else
audio = StereoChannels+AudioMaker(channels-2)
}
else
{
if (channels == 2)
audio = Stereo
else
audio = StereoChannels+AudioMaker(channels-2)
}
}
return audio
}
But I'm not sure how to implement that exactly, and it's probably not worth the extra computation if it is only handling 1-6 channels anyway.
I am posting my latest iteration here, mainly so I can have a "stable" copy of it between work and home before I start to break it again and run out of undo's.
toDelivery.avsiglobal finalFrameAspect = 0
global AR43 = float(4)/3
global AR169 = float(16)/9
global AR221 = 2.21
function arCalc(clip v, int "left", int "top", int "right", int "bottom", float "pixelShape")
{
pixelShape = Default(pixelShape, 1.0)
return float(v.width) * pixelShape / float(v.height)
}
function checkedCrop(clip v, int "left", int "top", int "right", int "bottom")
{
CrLeft = Default(left, 0)
CrTop = Default(top, 0)
CrRight = Default(right, 0)
CrBottom = Default(bottom, 0)
v = ((CrLeft%2) == 1) || ((CrTop%2) == 1) || ((CrRight%2) == 1) || ((CrBottom%2) == 1) ? v.ConvertToRGB32.Crop(CrLeft, CrTop, -CrRight, -CrBottom) : v.Crop(CrLeft, CrTop, -CrRight, -CrBottom)
return v
}
function plus(float x)
{ return (1+float(x)/100) }
function minus(float x)
{ return (1-float(x)/100) }
function SetFinalFrameAR(clip v, float AR)
{
global finalFrameAspect = AR
return v
}
function letterise(clip v, float DisplayAR, float TrueAR)
{
bars = v.height*(TrueAR/DisplayAR - 1)/2
v.letterMaker(bars)
}
function pillarise(clip v, float DisplayAR, float TrueAR)
{
bars = v.width*(DisplayAR/TrueAR - 1)/2
v.pillarMaker(bars)
}
function pillarMaker(clip v, float barsize)
{
barsize = Abs(Round(barsize))
v = ((barsize%2) == 0) ? v : ConvertToRGB32(v)
return v.AddBorders(barsize,0,barsize,0)
}
function letterMaker(clip v, float barsize)
{
barsize = Abs(Round(barsize))
v = ((barsize%2) == 0) ? v : ConvertToRGB32(v)
return v.AddBorders(0,barsize,0,barsize)
}
function pixelBattle (clip c,float TrueAR, float Frame1, float Frame2, float "FinalWidth", float "FinalHeight")
{
checkFrameAspects = (Frame1 > Frame2)? Eval("""
Temp = Frame1
Frame1 = Frame2
Frame2 = Temp
return Temp
""") : 0
FinalWidth = Default(FinalWidth, 720.0)
FinalHeight = Default(FinalHeight, 576.0)
HeightMod = FinalHeight / (FinalWidth / Frame1)
WidthMod = FinalWidth / (FinalHeight * Frame2)
ActivePix1 = FinalWidth / TrueAR * HeightMod * FinalWidth
ActivePix2 = FinalHeight * TrueAR * WidthMod * FinalHeight
c = (ActivePix1 >= ActivePix2) ? c.letterise(Frame1, TrueAR).SetFinalFrameAR(Frame1)
\ : c.pillarise(Frame2, TrueAR).SetFinalFrameAR(Frame2)
return c
}
# Output: PAL-DVD, non-compliant framerates allowed.
function toJoost(clip c, float TrueAR, float "ARbuffer", int "widthFinal", int "heightFinal")
{
widthFinal = Default(widthFinal, 720)
heightFinal = Default(heightFinal, 576)
x = Default(ARbuffer, 0.5)
c = ( ((TrueAR >= ((AR43)*minus(x))) && (TrueAR <= ((AR43)*plus(x)))) ? c.SetFinalFrameAR(AR43) :
\ ((TrueAR >= ((AR169)*minus(x))) && (TrueAR <= ((AR169)*plus(x)))) ? c.SetFinalFrameAR(AR169):
\ ((TrueAR >= ((AR221)*minus(x))) && (TrueAR <= ((AR221)*plus(x)))) ? c.SetFinalFrameAR(AR221):
\ (TrueAR < (AR43)) ? c.pillarise(AR43, TrueAR) :
\ ((TrueAR > (AR43)) && (TrueAR<AR169)) ? c.pixelBattle(TrueAR, AR43, AR169, widthFinal, heightFinal):
\ ((TrueAR > (AR169)) && (TrueAR<AR221)) ? c.pixelBattle(TrueAR, AR169, AR221, widthFinal, heightFinal):
\ (TrueAR > (AR221)) ? c.letterise(AR221, TrueAR).SetFinalFrameAR(AR221) :
\ c.SetFinalAR(0.0) )
return c.Spline36Resize(widthFinal, heightFinal).ConvertToYV12
}
#Output: 4:3 Frame, 640x480, square pixels
function toBlinkx(clip c, float TrueAR, float "ARbuffer", int "widthFinal", int "heightFinal")
{
widthFinal = Default(widthFinal, 640)
heightFinal = Default(heightFinal, 480)
x = Default(ARbuffer, 0.5)
c = ( ((TrueAR >= ((AR43)*minus(x))) && (TrueAR <= ((AR43)*plus(x)))) ? c :
\ ( TrueAR > AR43 ) ? c.letterise(AR43, TrueAR):
\ (TrueAR < AR43 ) ? c.pillarise(AR43, TrueAR) : c)
return c.Spline36Resize(widthFinal, heightFinal).ConvertToYV12.SetFinalFrameAR(AR43)
}
#Output: 640x480 Fullscreen, 854x480 Widescreen, square pixels
function toVuze(clip c, float TrueAR, float "ARbuffer")
{
heightFinal = Default(heightFinal, 480)
x = Default(ARbuffer, 0.5)
c = ( ((TrueAR >= ((AR43)*minus(x))) && (TrueAR <= ((AR43)*plus(x)))) ? c.Spline36Resize(640,480).ConvertToYV12.SetFinalFrameAR(AR43) :
\ ((TrueAR >= ((AR169)*minus(x))) && (TrueAR <= ((AR169)*plus(x))))? c.ConvertToRGB32. Spline36Resize(854,480).SetFinalFrameAR(AR169):
\ (TrueAR > AR43 ) && (TrueAR < (AR169)) ? c.pillarise(AR169, TrueAR).ConvertToRGB32. Spline36Resize(854,480).SetFinalFrameAR(AR169):
\ (TrueAR < AR43 ) ? c.pillarise(AR43, TrueAR).Spline36Resize(640,480).ConvertToYV12.SetFinalFrameAR(AR43) : c)
return c
}
#Output: borders not allowed, mod8 dimensions, width 720, square pixels
function toBlinkBox(clip c, float TrueAR, float "widthFinal")
{
#width fixed
widthFinal = Default(widthFinal, 720)
# mod 8 height
heightFinal = Round((widthFinal/TrueAR)/8)*8
#AR Error = ...
return c.spline36Resize(widthFinal, heightFinal).ConvertToYV12.SetFinalFrameAR(TrueAR)
}
#
function toZvue()
{}
# 4:3 Frame, 640x480, 480x360, 320x240 square pixels
function toJalipo()
{}
# 368x288, mod for mobile, square pixels
function toTmob()
{}
LogoFunc.avsifunction Logoise (clip c, float "PixelShape", string "Position", float "ARbuffer")
{
# If unspecified set destination frame as SquarePixel
PixelShape = Default(PixelShape, 1.0)
Position = Default(Position, "before")
# Source Logo Intro Animation Audio & Video
LogoV = DirectShowSource("C:\Compressionism\_Video\Source\Logos\Raindance TV Logo").ConvertToRGB32
AudioStereo = WavSource("C:\Compressionism\_Video\Source\Logos\RDTV-Logo-Feature-Stereo.wav")
Audio51 = DirectShowSource ("C:\Compressionism\_Video\Source\Logos\RDTV-Logo-Feature-51.ac3")
# Frame duration before which film is classified as "Short"
MaxShortFilmFrames = 53946
# Trim Intro Logo frame constants for short Film
TrimStart=124
TrimEnd=201
# True Source Aspect Ratio, taking into account pixel shape
# e.g Anamorphic Wide: (720/576)*(1024/720)
# e.g Square Pixels: (720/404)*(1/1)
SourceAR = (float(c.width)/c.height)*(PixelShape)
#Logo Aspect Ratio (Assume Square Pixels Intro Logo)
LogoAR = float(LogoV.width)/LogoV.height
#Acceptable Logo Aspect Ratio error Percentage
ARerror = Default(ARbuffer, 3)
#Acceptable Logo Speedup/Slowdown Percentage
SpeedMod = 5
# Match Audio Channels and Dub
Logo = (c.Audiochannels == 6) ? AudioDub(LogoV,Audio51) : AudioDub(LogoV,AudioStereo)
# Determine Intro Type (Short/Long) & Trim accordingly
Logo = (c.Framecount<MaxShortFilmFrames) ? Logo.Trim(TrimStart,TrimEnd) : Logo
# Match Framerate
#If framerate difference greater than acceptable; change fps (decimate duplicate), otherwise, speedup / slowdown logo to match film.
Logo = ( (c.FramerateNumerator == Logo.FramerateNumerator) && (c.FramerateDenominator == Logo.FramerateDenominator) ? Logo :
\ (c.Framerate > float(c.Framerate*(1+(SpeedMod/100)))) || (c.Framerate < float(c.Framerate*(1-(SpeedMod/100)))) ? Logo.ChangeFPS(c.FramerateNumerator , c.FramerateDenominator, true) : Logo.AssumeFPS(c.FramerateNumerator , c.FramerateDenominator, true))
#Match True Aspect Ratio
LogoModifier = Abs(Round((((Logo.Height)*SourceAR)-(Logo.Width))/2))
Logo = ( (SourceAR < float((1-(ARerror/100))*LogoAR)) ? Logo.Crop(LogoModifier,0,-LogoModifier,0) :
\ (SourceAR > float((1+(ARerror/100))*LogoAR)) ? Logo.AddBorders(LogoModifier,0,LogoModifier,0) : Logo)
#Match Frame Dimensions
Logo = Logo.Spline36Resize(c.width, c.height)
#Match Colourspace
Logo = ( (c.IsYV12) ? ConvertToYV12(Logo) :
\ (c.IsRGB32) ? Logo :
\ (c.IsRGB24) ? ConvertToRGB24(Logo) :
\ (c.IsYUY2) ? ConvertToYUY2(Logo) :
\ (c.IsYUV) ? ConvertToYUV(Logo) :
\ (c.IsRGB) ? ConvertToRGB(Logo) : Logo)
#Match Sample Rate
Logo = (c.Audiorate == Logo.Audiorate) ? Logo : Logo.ResampleAudio(c.Audiorate)
#Match AudioBits
Logo = ( (c.Audiobits == Logo.Audiobits) ? Logo :
\ (c.Audiobits == 16) ? Logo.ConvertAudioTo16bit :
\ (c.Audiobits == 24) ?Logo.ConvertAudioTo24bit :
\ (c.Audiobits == 32) ?Logo.ConvertAudioTo32bit :
\ (c.Audiobits == 8) ?Logo.ConvertAudioTo8bit : Logo )
c = (Position == "after")? c++Logo : Logo++c
return c
}
tester.avs
# Import Delivery Specification Functions
Import("C:\Compressionism\_Video\Source\_EncodingProfiles\Automation\toDelivery.avsi")
# Import Logo Join Function
Import("C:\Compressionism\_Video\Source\_EncodingProfiles\Automation\LogoFunc.avsi")
# Set Global Location Constants
global fileSource = "C:\Compressionism\_Video\Source\Shorts\998_RFF16"
global logFile = String(FileSource)+".log"
v = DGDecode_mpeg2source("C:\Compressionism\_Video\Source\Shorts\998_RFF16\VTS_01_1.d2v", cpu=0, info=3).ColorMatrix(hints=true)
a = WAVSource("C:\Compressionism\_Video\Source\Shorts\998_RFF16\VTS_01_1 Ta0 48K 16bit 2ch.wav")
#Cropping (integer values)
Left = 0
Top = 540
Right = 684
Bottom = 0
v = v.checkedCrop(left = Left, top = Top, right = Right, bottom = Bottom)
# Create Final Video Output, Dub/Crop/Deinterlace/VobSub/Trim/Processing/Sharpen/Deblock/Pan(Animate)/FadeIn/FadeOut/ etc....
#Load_Stdcall_Plugin("C:\Program Files\megui\tools\yadif\yadif.dll")
AudioDub(v,a)#Trim(130,159811).Yadif.ConvertToRGB32.Crop(...
### Set True Video AR ###
#global pixelShap
TrueAR = v.arCalc(pixelShape=float(1024)/720)
#Optionally Override Calculated Value
# Either use decimal value (eg 1.7777778)
# Or for fractional Ensure Floating Point Division by placing a decimal point in numerator (e.g 16.0/9 )
#TrueAR = 16.0/9
### Select Delivery Spec ###
#toJoost(TrueAR, ARbuffer = 2)(any float) to set acceptable aspect error percentage, default = half a percent
#toJoost(TrueAR,)
toBlinkx(TrueAR)
#toVuze
#toBlinkbox
# Logoise (PixelShape=float(768)/720) / (1024/720) / (1272/ 720) etc for anamorphic pixels output frame(Joost!)
# Logoise (1,1) or Logoise() for square pixels output frame(everything not joost)
# Logoise (Position = "after") to place logo after the video
# Logoise (ARbuffer = 2) (any float) to enable acceptable aspect error percentage
Logoise#(PixelShape=float(200)/20)
# Output video specs, Frame Size, Aspect, Framerate, Audio Channels, etc.
# Use WriteFileEnd logfile, ToDo
Edit: I spoke too soon! my arCalc does not love me.
Edit2: Fixed, I am a fool, again.
Gavino
2nd September 2008, 21:33
For instance, if I specify global TrueAR and want to make it the default value of a local variable named TrueAR in a function would it be something like:
function dummyFunc(clip v, float "TrueAR") {
TrueAR = Default(TrueAR, global TrueAR)
}
Or will this variable naming create problems?
You need to use a different name for the local variable. One of the curious features of the Avisynth language is that if you have a local and a global variable with the same name, the global becomes that rarest of animals, a 'write-only' variable, since there is a special syntax for writing to global variables, but not for reading them.
Also I would like to output the video information (contents of info() ) to file. Can this be achieved using WriteFileEnd?
Also, most of these functions are just checking video properties to determine what to output, but the properties are constant, so I don't really need the checks happening for every frame. Is there a way to make them just run once?
...
My problem is I am not sure in which order avisynth numbers the channels and I don't know if nested ifs is the most elegant way to code it.
The attributes reported by Info() can be read in a script using the clip properties (http://avisynth.org/mediawiki/Clip_properties) functions (and these functions can of course be used in the expression strings of WriteFileEnd).
Conditional tests in a script are not done on every frame, but only once when the script is read by the parser and 'compiled' into a filter graph. Unused branches are simply eliminated.
For audio channel numbering, see here (http://avisynth.org/mediawiki/GetChannel).
The Select (http://avisynth.org/mediawiki/Internal_functions/Control_functions) function (like a 'case' statement) can often provide a neater alternative to nested ifs. There is no 'while' function.
BTW your latest arCalc function seems to have several unused parameters.
Returning to the original topic of this thread, I see that Avisynth 2.58 RC4 has fixed AddBorders, so indirectly you have made a small contribution to its development. :)
vBulletin® v3.8.11, Copyright ©2000-2026, vBulletin Solutions Inc.