defunkt
27th January 2005, 02:14
If my understanding of XVID is correct one thing it will benefit from is a steady stream of consistant information, allowing it to reuse blocks from other frames particularly I-Frames on scene changes.
In which case, one problem with QMF is that it evaluates the first frame of a new scene (presumably an I-Frame) as high motion, which given its intended use will be a frame with less detail than a low motion frame even when the scene that follows is low motion. So I've messed about with the original script to make it detect scene changes (I find a threshold of 24 pretty accurate) and then treat that frame as it would the frame that follows.
I also added another level of motion but think that this is probably fairly gratuitous and unneccesary.
Thoughts?
function Motion() {
global motion_level = 0
global motion_level = (diff > threshold_zm) ? 1 : motion_level
global motion_level = (diff > threshold_lm) ? 2 : motion_level
global motion_level = (diff > threshold_hm) ? 3 : motion_level
global motion_level = (diff > threshold_sc) ? 4 : motion_level
}
function Change() {
global motion_level = (next > threshold_zm && motion_level > 3) ? 5 : motion_level
global motion_level = (next > threshold_lm && motion_level > 3) ? 6 : motion_level
global motion_level = (next > threshold_hm && motion_level > 3) ? 7 : motion_level
}
function QMF(clip c,
float "threshold_zm",
float "threshold_lm",
float "threshold_hm",
float "threshold_sc",
bool "debug") {
global threshold_zm = default(threshold_zm, 3.0)
global threshold_lm = default(threshold_lm, 6.0)
global threshold_hm = default(threshold_hm, 12.0)
global threshold_sc = default(threshold_sc, 24.0)
global motion_level = 0
global clip = c
c = ConditionalFilter(c, Filter_Motion_Nil(c), c, "motion_level", "=", "0")
c = ConditionalFilter(c, Filter_Motion_Min(c), c, "motion_level", "=", "1")
c = ConditionalFilter(c, Filter_Motion_Mid(c), c, "motion_level", "=", "2")
c = ConditionalFilter(c, Filter_Motion_Max(c), c, "motion_level", "=", "3")
c = ConditionalFilter(c, Filter_Motion_Nil(c), c, "motion_level", "=", "4")
c = ConditionalFilter(c, Filter_Motion_Min(c), c, "motion_level", "=", "5")
c = ConditionalFilter(c, Filter_Motion_Mid(c), c, "motion_level", "=", "6")
c = ConditionalFilter(c, Filter_Motion_Max(c), c, "motion_level", "=", "7")
c = (default(debug, false)) == true ? ScriptClip(c, "Debug()") : c
c = FrameEvaluate(c, "Change()")
c = FrameEvaluate(c, "global next =
(0.50 * YDifferenceToNext(clip)) +
(0.25 * UDifferenceToNext(clip)) +
(0.25 * VDifferenceToNext(clip))")
c = FrameEvaluate(c, "Motion()")
c = FrameEvaluate(c, "global diff =
(0.50 * YDifferenceFromPrevious(clip)) +
(0.25 * UDifferenceFromPrevious(clip)) +
(0.25 * VDifferenceFromPrevious(clip))")
return c
}
function Debug(clip c) {
c = Subtitle(c, "Motion Evaluation: " + string(diff),
x=25, y=150, font="courier new", size=24)
c = (motion_level == 0) ? Subtitle(c, "Zero Motion Frame",
x=25, y=200, font="courier new", size=32, text_color=$FFFFFF) : c
c = (motion_level == 1) ? Subtitle(c, "Low Motion Frame",
x=25, y=200, font="courier new", size=32, text_color=$FFFFFF) : c
c = (motion_level == 2) ? Subtitle(c, "Medium Motion Frame",
x=25, y=200, font="courier new", size=32, text_color=$FFFFFF) : c
c = (motion_level == 3) ? Subtitle(c, "High Motion Frame",
x=25, y=200, font="courier new", size=32, text_color=$FFFFFF) : c
c = (motion_level == 4) ? Subtitle(c, "Scene Change (Zero)",
x=25, y=200, font="courier new", size=32, text_color=$FFFFFF) : c
c = (motion_level == 5) ? Subtitle(c, "Scene Change (Low)",
x=25, y=200, font="courier new", size=32, text_color=$FFFFFF) : c
c = (motion_level == 6) ? Subtitle(c, "Scene Change (Medium)",
x=25, y=200, font="courier new", size=32, text_color=$FFFFFF) : c
c = (motion_level == 7) ? Subtitle(c, "Scene Change (High)",
x=25, y=200, font="courier new", size=32, text_color=$FFFFFF) : c
return c
}
In which case, one problem with QMF is that it evaluates the first frame of a new scene (presumably an I-Frame) as high motion, which given its intended use will be a frame with less detail than a low motion frame even when the scene that follows is low motion. So I've messed about with the original script to make it detect scene changes (I find a threshold of 24 pretty accurate) and then treat that frame as it would the frame that follows.
I also added another level of motion but think that this is probably fairly gratuitous and unneccesary.
Thoughts?
function Motion() {
global motion_level = 0
global motion_level = (diff > threshold_zm) ? 1 : motion_level
global motion_level = (diff > threshold_lm) ? 2 : motion_level
global motion_level = (diff > threshold_hm) ? 3 : motion_level
global motion_level = (diff > threshold_sc) ? 4 : motion_level
}
function Change() {
global motion_level = (next > threshold_zm && motion_level > 3) ? 5 : motion_level
global motion_level = (next > threshold_lm && motion_level > 3) ? 6 : motion_level
global motion_level = (next > threshold_hm && motion_level > 3) ? 7 : motion_level
}
function QMF(clip c,
float "threshold_zm",
float "threshold_lm",
float "threshold_hm",
float "threshold_sc",
bool "debug") {
global threshold_zm = default(threshold_zm, 3.0)
global threshold_lm = default(threshold_lm, 6.0)
global threshold_hm = default(threshold_hm, 12.0)
global threshold_sc = default(threshold_sc, 24.0)
global motion_level = 0
global clip = c
c = ConditionalFilter(c, Filter_Motion_Nil(c), c, "motion_level", "=", "0")
c = ConditionalFilter(c, Filter_Motion_Min(c), c, "motion_level", "=", "1")
c = ConditionalFilter(c, Filter_Motion_Mid(c), c, "motion_level", "=", "2")
c = ConditionalFilter(c, Filter_Motion_Max(c), c, "motion_level", "=", "3")
c = ConditionalFilter(c, Filter_Motion_Nil(c), c, "motion_level", "=", "4")
c = ConditionalFilter(c, Filter_Motion_Min(c), c, "motion_level", "=", "5")
c = ConditionalFilter(c, Filter_Motion_Mid(c), c, "motion_level", "=", "6")
c = ConditionalFilter(c, Filter_Motion_Max(c), c, "motion_level", "=", "7")
c = (default(debug, false)) == true ? ScriptClip(c, "Debug()") : c
c = FrameEvaluate(c, "Change()")
c = FrameEvaluate(c, "global next =
(0.50 * YDifferenceToNext(clip)) +
(0.25 * UDifferenceToNext(clip)) +
(0.25 * VDifferenceToNext(clip))")
c = FrameEvaluate(c, "Motion()")
c = FrameEvaluate(c, "global diff =
(0.50 * YDifferenceFromPrevious(clip)) +
(0.25 * UDifferenceFromPrevious(clip)) +
(0.25 * VDifferenceFromPrevious(clip))")
return c
}
function Debug(clip c) {
c = Subtitle(c, "Motion Evaluation: " + string(diff),
x=25, y=150, font="courier new", size=24)
c = (motion_level == 0) ? Subtitle(c, "Zero Motion Frame",
x=25, y=200, font="courier new", size=32, text_color=$FFFFFF) : c
c = (motion_level == 1) ? Subtitle(c, "Low Motion Frame",
x=25, y=200, font="courier new", size=32, text_color=$FFFFFF) : c
c = (motion_level == 2) ? Subtitle(c, "Medium Motion Frame",
x=25, y=200, font="courier new", size=32, text_color=$FFFFFF) : c
c = (motion_level == 3) ? Subtitle(c, "High Motion Frame",
x=25, y=200, font="courier new", size=32, text_color=$FFFFFF) : c
c = (motion_level == 4) ? Subtitle(c, "Scene Change (Zero)",
x=25, y=200, font="courier new", size=32, text_color=$FFFFFF) : c
c = (motion_level == 5) ? Subtitle(c, "Scene Change (Low)",
x=25, y=200, font="courier new", size=32, text_color=$FFFFFF) : c
c = (motion_level == 6) ? Subtitle(c, "Scene Change (Medium)",
x=25, y=200, font="courier new", size=32, text_color=$FFFFFF) : c
c = (motion_level == 7) ? Subtitle(c, "Scene Change (High)",
x=25, y=200, font="courier new", size=32, text_color=$FFFFFF) : c
return c
}