From 14a662c3187f9d5062aa25d83523b651201d2736 Mon Sep 17 00:00:00 2001 From: Etienne Charland Date: Mon, 24 Apr 2017 18:54:50 -0500 Subject: [PATCH 1/3] Fixed conditional functions for MT --- avs_core/core/parser/expression.cpp | 51 +++-- avs_core/core/parser/expression.h | 8 +- avs_core/core/parser/script.cpp | 2 +- avs_core/core/parser/scriptparser.cpp | 16 +- avs_core/core/parser/scriptparser.h | 7 +- avs_core/filters/conditional/conditional.cpp | 25 +-- .../conditional/conditional_functions.cpp | 190 ++++++++---------- .../conditional/conditional_functions.h | 8 +- 8 files changed, 150 insertions(+), 157 deletions(-) diff --git a/avs_core/core/parser/expression.cpp b/avs_core/core/parser/expression.cpp index 78dfe342b..b339f9286 100644 --- a/avs_core/core/parser/expression.cpp +++ b/avs_core/core/parser/expression.cpp @@ -458,15 +458,20 @@ AVSValue ExpVariableReference::Evaluate(IScriptEnvironment* env) else { // Swap order to match ::Call below -- Gavino Jan 2010 - // next look for an argless function + // look for an argless function if (!env2->Invoke(&result, name, AVSValue(0,0))) { - // finally look for a single-arg function taking implicit "last" + // look for a single-arg function taking implicit "last" AVSValue last; if (!env2->GetVar("last", &last) || !env2->Invoke(&result, name, last)) { - env->ThrowError("I don't know what '%s' means.", name); - return 0; + // look for function taking last and frame_number for per-frame expressions + AVSValue sargs[2] = { last, frame_number }; + const char *nargs[2] = { 0, 0 }; + if (frame_number < 0 || !env2->Invoke(&result, name, AVSValue(sargs, 2), nargs)) { + env->ThrowError("I don't know what '%s' means.", name); + return 0; + } } } } @@ -489,17 +494,18 @@ AVSValue ExpGlobalAssignment::Evaluate(IScriptEnvironment* env) } -ExpFunctionCall::ExpFunctionCall( const char* _name, PExpression* _arg_exprs, - const char** _arg_expr_names, int _arg_expr_count, bool _oop_notation ) - : name(_name), arg_expr_count(_arg_expr_count), oop_notation(_oop_notation) +ExpFunctionCall::ExpFunctionCall(const char* _name, PExpression* _arg_exprs, + const char** _arg_expr_names, int _arg_expr_count, bool _oop_notation, int _frame_number) + : name(_name), arg_expr_count(_arg_expr_count), oop_notation(_oop_notation), frame_number(_frame_number) { + // arg_expr_names has 2 extra item at the beginning, for implicit "last" and for "current_frame" arg_exprs = new PExpression[arg_expr_count]; - // arg_expr_names has an extra elt at the beginning, for implicit "last" - arg_expr_names = new const char*[arg_expr_count+1]; + arg_expr_names = new const char*[arg_expr_count+2]; arg_expr_names[0] = 0; - for (int i=0; i(env); - std::vector args(arg_expr_count+1, AVSValue()); + std::vector args(arg_expr_count+2, AVSValue()); for (int a=0; aEvaluate(env); + args[a+2] = arg_exprs[a]->Evaluate(env); // first try without implicit "last" try { // Invoke can always throw by calling a constructor of a filter that throws - if (env2->Invoke(&result, name, AVSValue(args.data()+1, arg_expr_count), arg_expr_names+1)) + if (env2->Invoke(&result, name, AVSValue(args.data()+2, arg_expr_count), arg_expr_names+2)) return result; } catch(const IScriptEnvironment::NotFound&){} // if that fails, try with implicit "last" (except when OOP notation was used) - if (!oop_notation) + if (!oop_notation && env2->GetVar("last", &args[1])) { try { - if (env2->GetVar("last", args.data()) && env2->Invoke(&result, name, AVSValue(args.data(), arg_expr_count+1), arg_expr_names)) + if (env2->Invoke(&result, name, AVSValue(args.data()+1, arg_expr_count+1), arg_expr_names+1)) return result; } catch(const IScriptEnvironment::NotFound&){} + + // for per-frame expressions, try with implicit "last" and "frame_number" + if (frame_number >= 0) + { + args[0] = args[1]; // "last" + args[1] = AVSValue(frame_number); + try + { + if (env2->Invoke(&result, name, AVSValue(args.data(), arg_expr_count+2), arg_expr_names)) + return result; + } + catch (const IScriptEnvironment::NotFound&) {} + } } env->ThrowError(env->FunctionExists(name) ? diff --git a/avs_core/core/parser/expression.h b/avs_core/core/parser/expression.h index f6b2a6e1d..857de53da 100644 --- a/avs_core/core/parser/expression.h +++ b/avs_core/core/parser/expression.h @@ -373,13 +373,14 @@ class ExpNot : public Expression class ExpVariableReference : public Expression { public: - ExpVariableReference(const char* _name) : name(_name) {} + ExpVariableReference(const char* _name, const int _frame_number) : name(_name), frame_number(_frame_number) {} virtual AVSValue Evaluate(IScriptEnvironment* env); virtual const char* GetLvalue() { return name; } private: const char* const name; + const int frame_number; // for per-frame expressions }; @@ -411,7 +412,7 @@ class ExpFunctionCall : public Expression { public: ExpFunctionCall( const char* _name, PExpression* _arg_exprs, - const char** _arg_expr_names, int _arg_expr_count, bool _oop_notation ); + const char** _arg_expr_names, int _arg_expr_count, bool _oop_notation, int _frame_number ); ~ExpFunctionCall(void); virtual AVSValue Evaluate(IScriptEnvironment* env); @@ -420,8 +421,9 @@ class ExpFunctionCall : public Expression const char* const name; PExpression* arg_exprs; const char** arg_expr_names; - const int arg_expr_count; + int arg_expr_count; const bool oop_notation; + const int frame_number; }; diff --git a/avs_core/core/parser/script.cpp b/avs_core/core/parser/script.cpp index ce9aff383..f725aa79b 100644 --- a/avs_core/core/parser/script.cpp +++ b/avs_core/core/parser/script.cpp @@ -399,7 +399,7 @@ AVSValue Eval(AVSValue args, void*, IScriptEnvironment* env) { const char *filename = args[1].AsString(0); if (filename) filename = env->SaveString(filename); - ScriptParser parser(env, args[0].AsString(), filename); + ScriptParser parser(env, args[0].AsString(), filename, -1); PExpression exp = parser.Parse(); return exp->Evaluate(env); } diff --git a/avs_core/core/parser/scriptparser.cpp b/avs_core/core/parser/scriptparser.cpp index b7bd098e2..797e6b554 100644 --- a/avs_core/core/parser/scriptparser.cpp +++ b/avs_core/core/parser/scriptparser.cpp @@ -41,8 +41,8 @@ *******************************/ -ScriptParser::ScriptParser(IScriptEnvironment* _env, const char* _code, const char* _filename) - : env(static_cast(_env)), tokenizer(_code, _env), code(_code), filename(_filename), loopDepth(0) {} +ScriptParser::ScriptParser(IScriptEnvironment* _env, const char* _code, const char* _filename, int _frame_number) + : env(static_cast(_env)), tokenizer(_code, _env), code(_code), filename(_filename), loopDepth(0), frame_number(_frame_number) {} PExpression ScriptParser::Parse(void) { @@ -525,10 +525,10 @@ PExpression ScriptParser::ParseUnary(void) { PExpression ScriptParser::ParseOOP(void) { #ifndef NEW_AVSVALUE - PExpression left = ParseFunction(0); + PExpression left = ParseFunction(0, frame_number); while (tokenizer.IsOperator('.')) { tokenizer.NextToken(); - left = ParseFunction(left); + left = ParseFunction(left, frame_number); } #else PExpression left = ParseFunction(0, '\0'); @@ -543,9 +543,9 @@ PExpression ScriptParser::ParseOOP(void) } #ifndef NEW_AVSVALUE -PExpression ScriptParser::ParseFunction(PExpression context) +PExpression ScriptParser::ParseFunction(PExpression context, int frame_number) #else -PExpression ScriptParser::ParseFunction(PExpression context, char context_char) +PExpression ScriptParser::ParseFunction(PExpression context, int frame_number, char context_char) #endif { #ifndef NEW_AVSVALUE @@ -585,7 +585,7 @@ PExpression ScriptParser::ParseFunction(PExpression context, char context_char) if (!context && !tokenizer.IsOperator('(') && !isArraySpecifier) { #endif // variable - return new ExpVariableReference(name); + return new ExpVariableReference(name, frame_number); } // function PExpression args[max_args]; @@ -655,7 +655,7 @@ PExpression ScriptParser::ParseFunction(PExpression context, char context_char) env->ThrowError("Script error: array indexing must have at least one index"); } #endif - return new ExpFunctionCall(name, args, arg_names, i, !!context); + return new ExpFunctionCall(name, args, arg_names, i, !!context, frame_number); } PExpression ScriptParser::ParseAtom(void) diff --git a/avs_core/core/parser/scriptparser.h b/avs_core/core/parser/scriptparser.h index 800d396ef..2b0917506 100644 --- a/avs_core/core/parser/scriptparser.h +++ b/avs_core/core/parser/scriptparser.h @@ -52,7 +52,7 @@ class ScriptParser **/ { public: - ScriptParser(IScriptEnvironment* _env, const char* _code, const char* _filename); + ScriptParser(IScriptEnvironment* _env, const char* _code, const char* _filename, int _frame_number); PExpression Parse(void); @@ -64,6 +64,7 @@ class ScriptParser const char* const code; const char* const filename; int loopDepth; // how many loops are we in during parsing + int frame_number; // for per-frame expressions void Expect(int op, const char* msg); @@ -81,9 +82,9 @@ class ScriptParser PExpression ParseUnary(void); PExpression ParseOOP(void); #ifdef NEW_AVSVALUE - PExpression ParseFunction(PExpression context, char context_char); + PExpression ParseFunction(PExpression context, int frame_number, char context_char); #else - PExpression ParseFunction(PExpression context); + PExpression ParseFunction(PExpression context, int frame_number); #endif PExpression ParseAtom(void); diff --git a/avs_core/filters/conditional/conditional.cpp b/avs_core/filters/conditional/conditional.cpp index b43e3ad4e..1f6ead557 100644 --- a/avs_core/filters/conditional/conditional.cpp +++ b/avs_core/filters/conditional/conditional.cpp @@ -102,15 +102,11 @@ int __stdcall ConditionalSelect::SetCacheHints(int cachehints, int frame_range) PVideoFrame __stdcall ConditionalSelect::GetFrame(int n, IScriptEnvironment* env) { AVSValue prev_last = env->GetVarDef("last"); // Store previous last - AVSValue prev_current_frame = env->GetVarDef("current_frame"); // Store previous current_frame - env->SetVar("last", (AVSValue)child); // Set implicit last - env->SetVar("current_frame", (AVSValue)n); // Set frame to be tested by the conditional filters. - AVSValue result; try { - ScriptParser parser(env, expression, "[Conditional Select, Expression]"); + ScriptParser parser(env, expression, "[Conditional Select, Expression]", n); PExpression exp = parser.Parse(); result = exp->Evaluate(env); @@ -119,7 +115,6 @@ PVideoFrame __stdcall ConditionalSelect::GetFrame(int n, IScriptEnvironment* env } catch (const AvisynthError &error) { env->SetVar("last", prev_last); // Restore implicit last - env->SetVar("current_frame", prev_current_frame); // Restore current_frame const int num_frames = child->GetVideoInfo().num_frames; PVideoFrame dst = child->GetFrame(min(num_frames-1, n), env); @@ -131,7 +126,6 @@ PVideoFrame __stdcall ConditionalSelect::GetFrame(int n, IScriptEnvironment* env } env->SetVar("last", prev_last); // Restore implicit last - env->SetVar("current_frame", prev_current_frame); // Restore current_frame const int i = result.AsInt(); @@ -253,19 +247,16 @@ PVideoFrame __stdcall ConditionalFilter::GetFrame(int n, IScriptEnvironment* env VideoInfo vi2 = source2->GetVideoInfo(); AVSValue prev_last = env->GetVarDef("last"); // Store previous last - AVSValue prev_current_frame = env->GetVarDef("current_frame"); // Store previous current_frame - env->SetVar("last",(AVSValue)child); // Set implicit last - env->SetVar("current_frame",(AVSValue)n); // Set frame to be tested by the conditional filters. AVSValue e1_result; AVSValue e2_result; try { - ScriptParser parser(env, eval1.AsString(), "[Conditional Filter, Expresion 1]"); + ScriptParser parser(env, eval1.AsString(), "[Conditional Filter, Expresion 1]", n); PExpression exp = parser.Parse(); e1_result = exp->Evaluate(env); - ScriptParser parser2(env, eval2.AsString(), "[Conditional Filter, Expression 2]"); + ScriptParser parser2(env, eval2.AsString(), "[Conditional Filter, Expression 2]", n); exp = parser2.Parse(); e2_result = exp->Evaluate(env); } catch (const AvisynthError &error) { @@ -275,12 +266,10 @@ PVideoFrame __stdcall ConditionalFilter::GetFrame(int n, IScriptEnvironment* env env->MakeWritable(&dst); env->ApplyMessage(&dst, vi1, error_msg, vi.width/W_DIVISOR, 0xa0a0a0, 0, 0); env->SetVar("last",prev_last); // Restore implicit last - env->SetVar("current_frame",prev_current_frame); // Restore current_frame return dst; } env->SetVar("last",prev_last); // Restore implicit last - env->SetVar("current_frame",prev_current_frame); // Restore current_frame bool test_int=false; bool test_string=false; @@ -442,17 +431,13 @@ int __stdcall ScriptClip::SetCacheHints(int cachehints, int frame_range) PVideoFrame __stdcall ScriptClip::GetFrame(int n, IScriptEnvironment* env) { AVSValue prev_last = env->GetVarDef("last"); // Store previous last - AVSValue prev_current_frame = env->GetVarDef("current_frame"); // Store previous current_frame - env->SetVar("last",(AVSValue)child); // Set explicit last - env->SetVar("current_frame",(AVSValue)n); // Set frame to be tested by the conditional filters. if (show) { PVideoFrame dst = child->GetFrame(n,env); env->MakeWritable(&dst); env->ApplyMessage(&dst, vi, script.AsString(), vi.width/6, 0xa0a0a0, 0, 0); env->SetVar("last",prev_last); // Restore implicit last - env->SetVar("current_frame",prev_current_frame); // Restore current_frame return dst; } @@ -462,7 +447,7 @@ PVideoFrame __stdcall ScriptClip::GetFrame(int n, IScriptEnvironment* env) { if (eval_after) eval_return = child->GetFrame(n,env); try { - ScriptParser parser(env, script.AsString(), "[ScriptClip]"); + ScriptParser parser(env, script.AsString(), "[ScriptClip]", n); PExpression exp = parser.Parse(); result = exp->Evaluate(env); } catch (const AvisynthError &error) { @@ -472,12 +457,10 @@ PVideoFrame __stdcall ScriptClip::GetFrame(int n, IScriptEnvironment* env) { env->MakeWritable(&dst); env->ApplyMessage(&dst, vi, error_msg, vi.width/W_DIVISOR, 0xa0a0a0, 0, 0); env->SetVar("last",prev_last); // Restore implicit last - env->SetVar("current_frame",prev_current_frame); // Restore current_frame return dst; } env->SetVar("last",prev_last); // Restore implicit last - env->SetVar("current_frame",prev_current_frame); // Restore current_frame if (eval_after && only_eval) return eval_return; if (only_eval) return child->GetFrame(n,env); diff --git a/avs_core/filters/conditional/conditional_functions.cpp b/avs_core/filters/conditional/conditional_functions.cpp index eee973ec2..c43c316bc 100644 --- a/avs_core/filters/conditional/conditional_functions.cpp +++ b/avs_core/filters/conditional/conditional_functions.cpp @@ -45,78 +45,78 @@ #include "../focus.h" // sad extern const AVSFunction Conditional_funtions_filters[] = { - { "AverageLuma", BUILTIN_FUNC_PREFIX, "c[offset]i", AveragePlane::Create, (void *)PLANAR_Y }, - { "AverageChromaU", BUILTIN_FUNC_PREFIX, "c[offset]i", AveragePlane::Create, (void *)PLANAR_U }, - { "AverageChromaV", BUILTIN_FUNC_PREFIX, "c[offset]i", AveragePlane::Create, (void *)PLANAR_V }, - { "AverageR", BUILTIN_FUNC_PREFIX, "c[offset]i", AveragePlane::Create, (void *)PLANAR_R }, - { "AverageG", BUILTIN_FUNC_PREFIX, "c[offset]i", AveragePlane::Create, (void *)PLANAR_G }, - { "AverageB", BUILTIN_FUNC_PREFIX, "c[offset]i", AveragePlane::Create, (void *)PLANAR_B }, - //{ "AverageSat","c[offset]i", AverageSat::Create }, Sum(SatLookup[U,V])/N, SatLookup[U,V]=1.4087*sqrt((U-128)**2+(V-128)**2) -//{ "AverageHue","c[offset]i", AverageHue::Create }, Sum(HueLookup[U,V])/N, HueLookup[U,V]=40.5845*Atan2(U-128,V-128) - - { "RGBDifference", BUILTIN_FUNC_PREFIX, "cc", ComparePlane::Create, (void *)-1 }, - { "LumaDifference", BUILTIN_FUNC_PREFIX, "cc", ComparePlane::Create, (void *)PLANAR_Y }, - { "ChromaUDifference", BUILTIN_FUNC_PREFIX, "cc", ComparePlane::Create, (void *)PLANAR_U }, - { "ChromaVDifference", BUILTIN_FUNC_PREFIX, "cc", ComparePlane::Create, (void *)PLANAR_V }, - { "RDifference", BUILTIN_FUNC_PREFIX, "cc", ComparePlane::Create, (void *)PLANAR_R }, - { "GDifference", BUILTIN_FUNC_PREFIX, "cc", ComparePlane::Create, (void *)PLANAR_G }, - { "BDifference", BUILTIN_FUNC_PREFIX, "cc", ComparePlane::Create, (void *)PLANAR_B }, - //{ "SatDifference","cc", CompareSat::Create }, Sum(Abs(SatLookup[U1,V1]-SatLookup[U2,V2]))/N -//{ "HueDifference","cc", CompareHue::Create }, Sum(Abs(HueLookup[U1,V1]-HueLookup[U2,V2]))/N - - { "YDifferenceFromPrevious", BUILTIN_FUNC_PREFIX, "c", ComparePlane::Create_prev, (void *)PLANAR_Y }, - { "UDifferenceFromPrevious", BUILTIN_FUNC_PREFIX, "c", ComparePlane::Create_prev, (void *)PLANAR_U }, - { "VDifferenceFromPrevious", BUILTIN_FUNC_PREFIX, "c", ComparePlane::Create_prev, (void *)PLANAR_V }, - { "RGBDifferenceFromPrevious", BUILTIN_FUNC_PREFIX, "c", ComparePlane::Create_prev, (void *)-1 }, - { "RDifferenceFromPrevious", BUILTIN_FUNC_PREFIX, "c", ComparePlane::Create_prev, (void *)PLANAR_R }, - { "GDifferenceFromPrevious", BUILTIN_FUNC_PREFIX, "c", ComparePlane::Create_prev, (void *)PLANAR_G }, - { "BDifferenceFromPrevious", BUILTIN_FUNC_PREFIX, "c", ComparePlane::Create_prev, (void *)PLANAR_B }, - //{ "SatDifferenceFromPrevious","c", CompareSat::Create_prev }, -//{ "HueDifferenceFromPrevious","c", CompareHue::Create_prev }, - - { "YDifferenceToNext", BUILTIN_FUNC_PREFIX, "c[offset]i", ComparePlane::Create_next, (void *)PLANAR_Y }, - { "UDifferenceToNext", BUILTIN_FUNC_PREFIX, "c[offset]i", ComparePlane::Create_next, (void *)PLANAR_U }, - { "VDifferenceToNext", BUILTIN_FUNC_PREFIX, "c[offset]i", ComparePlane::Create_next, (void *)PLANAR_V }, - { "RGBDifferenceToNext", BUILTIN_FUNC_PREFIX, "c[offset]i", ComparePlane::Create_next, (void *)-1 }, - { "RDifferenceToNext", BUILTIN_FUNC_PREFIX, "c[offset]i", ComparePlane::Create_next, (void *)PLANAR_R }, - { "GDifferenceToNext", BUILTIN_FUNC_PREFIX, "c[offset]i", ComparePlane::Create_next, (void *)PLANAR_G }, - { "BDifferenceToNext", BUILTIN_FUNC_PREFIX, "c[offset]i", ComparePlane::Create_next, (void *)PLANAR_B }, - //{ "SatDifferenceFromNext","c[offset]i", CompareSat::Create_next }, -//{ "HueDifferenceFromNext","c[offset]i", CompareHue::Create_next }, - { "YPlaneMax", BUILTIN_FUNC_PREFIX, "c[threshold]f[offset]i", MinMaxPlane::Create_max, (void *)PLANAR_Y }, - { "YPlaneMin", BUILTIN_FUNC_PREFIX, "c[threshold]f[offset]i", MinMaxPlane::Create_min, (void *)PLANAR_Y }, - { "YPlaneMedian", BUILTIN_FUNC_PREFIX, "c[offset]i", MinMaxPlane::Create_median, (void *)PLANAR_Y }, - { "UPlaneMax", BUILTIN_FUNC_PREFIX, "c[threshold]f[offset]i", MinMaxPlane::Create_max, (void *)PLANAR_U }, - { "UPlaneMin", BUILTIN_FUNC_PREFIX, "c[threshold]f[offset]i", MinMaxPlane::Create_min, (void *)PLANAR_U }, - { "UPlaneMedian", BUILTIN_FUNC_PREFIX, "c[offset]i", MinMaxPlane::Create_median, (void *)PLANAR_U }, - { "VPlaneMax", BUILTIN_FUNC_PREFIX, "c[threshold]f[offset]i", MinMaxPlane::Create_max, (void *)PLANAR_V }, // AVS+! was before: missing offset parameter - { "VPlaneMin", BUILTIN_FUNC_PREFIX, "c[threshold]f[offset]i", MinMaxPlane::Create_min, (void *)PLANAR_V }, // AVS+! was before: missing offset parameter - { "VPlaneMedian", BUILTIN_FUNC_PREFIX, "c[offset]i", MinMaxPlane::Create_median, (void *)PLANAR_V }, - { "RPlaneMax", BUILTIN_FUNC_PREFIX, "c[threshold]f[offset]i", MinMaxPlane::Create_max, (void *)PLANAR_R }, - { "RPlaneMin", BUILTIN_FUNC_PREFIX, "c[threshold]f[offset]i", MinMaxPlane::Create_min, (void *)PLANAR_R }, - { "RPlaneMedian", BUILTIN_FUNC_PREFIX, "c[offset]i", MinMaxPlane::Create_median, (void *)PLANAR_R }, - { "GPlaneMax", BUILTIN_FUNC_PREFIX, "c[threshold]f[offset]i", MinMaxPlane::Create_max, (void *)PLANAR_G }, - { "GPlaneMin", BUILTIN_FUNC_PREFIX, "c[threshold]f[offset]i", MinMaxPlane::Create_min, (void *)PLANAR_G }, - { "GPlaneMedian", BUILTIN_FUNC_PREFIX, "c[offset]i", MinMaxPlane::Create_median, (void *)PLANAR_G }, - { "BPlaneMax", BUILTIN_FUNC_PREFIX, "c[threshold]f[offset]i", MinMaxPlane::Create_max, (void *)PLANAR_B }, - { "BPlaneMin", BUILTIN_FUNC_PREFIX, "c[threshold]f[offset]i", MinMaxPlane::Create_min, (void *)PLANAR_B }, - { "BPlaneMedian", BUILTIN_FUNC_PREFIX, "c[offset]i", MinMaxPlane::Create_median, (void *)PLANAR_B }, - { "YPlaneMinMaxDifference", BUILTIN_FUNC_PREFIX, "c[threshold]f[offset]i", MinMaxPlane::Create_minmax, (void *)PLANAR_Y }, - { "UPlaneMinMaxDifference", BUILTIN_FUNC_PREFIX, "c[threshold]f[offset]i", MinMaxPlane::Create_minmax, (void *)PLANAR_U }, // AVS+! was before: missing offset parameter - { "VPlaneMinMaxDifference", BUILTIN_FUNC_PREFIX, "c[threshold]f[offset]i", MinMaxPlane::Create_minmax, (void *)PLANAR_V }, // AVS+! was before: missing offset parameter - { "RPlaneMinMaxDifference", BUILTIN_FUNC_PREFIX, "c[threshold]f[offset]i", MinMaxPlane::Create_minmax, (void *)PLANAR_R }, - { "GPlaneMinMaxDifference", BUILTIN_FUNC_PREFIX, "c[threshold]f[offset]i", MinMaxPlane::Create_minmax, (void *)PLANAR_G }, - { "BPlaneMinMaxDifference", BUILTIN_FUNC_PREFIX, "c[threshold]f[offset]i", MinMaxPlane::Create_minmax, (void *)PLANAR_B }, - -//{ "SatMax","c[threshold]f[offset]i", MinMaxPlane::Create_maxsat }, ++accum[SatLookup[U,V]] -//{ "SatMin","c[threshold]f[offset]i", MinMaxPlane::Create_minsat }, -//{ "SatMedian","c[offset]i", MinMaxPlane::Create_mediansat }, -//{ "SatMinMaxDifference","c[threshold]f[offset]i", MinMaxPlane::Create_minmaxsat }, - -//{ "HueMax","c[threshold]f[offset]i", MinMaxPlane::Create_maxhue }, ++accum[HueLookup[U,V]] -//{ "HueMin","c[threshold]f[offset]i", MinMaxPlane::Create_minhue }, -//{ "HueMedian","c[offset]i", MinMaxPlane::Create_medianhue }, -//{ "HueMinMaxDifference","c[threshold]f[offset]i", MinMaxPlane::Create_minmaxhue }, + { "AverageLuma", BUILTIN_FUNC_PREFIX, "ci[offset]i", AveragePlane::Create, (void *)PLANAR_Y }, + { "AverageChromaU", BUILTIN_FUNC_PREFIX, "ci[offset]i", AveragePlane::Create, (void *)PLANAR_U }, + { "AverageChromaV", BUILTIN_FUNC_PREFIX, "ci[offset]i", AveragePlane::Create, (void *)PLANAR_V }, + { "AverageR", BUILTIN_FUNC_PREFIX, "ci[offset]i", AveragePlane::Create, (void *)PLANAR_R }, + { "AverageG", BUILTIN_FUNC_PREFIX, "ci[offset]i", AveragePlane::Create, (void *)PLANAR_G }, + { "AverageB", BUILTIN_FUNC_PREFIX, "ci[offset]i", AveragePlane::Create, (void *)PLANAR_B }, + //{ "AverageSat","ci[offset]i", AverageSat::Create }, Sum(SatLookup[U,V])/N, SatLookup[U,V]=1.4087*sqrt((U-128)**2+(V-128)**2) +//{ "AverageHue","ci[offset]i", AverageHue::Create }, Sum(HueLookup[U,V])/N, HueLookup[U,V]=40.5845*Atan2(U-128,V-128) + + { "RGBDifference", BUILTIN_FUNC_PREFIX, "cic", ComparePlane::Create, (void *)-1 }, + { "LumaDifference", BUILTIN_FUNC_PREFIX, "cic", ComparePlane::Create, (void *)PLANAR_Y }, + { "ChromaUDifference", BUILTIN_FUNC_PREFIX, "cic", ComparePlane::Create, (void *)PLANAR_U }, + { "ChromaVDifference", BUILTIN_FUNC_PREFIX, "cic", ComparePlane::Create, (void *)PLANAR_V }, + { "RDifference", BUILTIN_FUNC_PREFIX, "cic", ComparePlane::Create, (void *)PLANAR_R }, + { "GDifference", BUILTIN_FUNC_PREFIX, "cic", ComparePlane::Create, (void *)PLANAR_G }, + { "BDifference", BUILTIN_FUNC_PREFIX, "cic", ComparePlane::Create, (void *)PLANAR_B }, + //{ "SatDifference","cic", CompareSat::Create }, Sum(Abs(SatLookup[U1,V1]-SatLookup[U2,V2]))/N +//{ "HueDifference","cic", CompareHue::Create }, Sum(Abs(HueLookup[U1,V1]-HueLookup[U2,V2]))/N + + { "YDifferenceFromPrevious", BUILTIN_FUNC_PREFIX, "ci", ComparePlane::Create_prev, (void *)PLANAR_Y }, + { "UDifferenceFromPrevious", BUILTIN_FUNC_PREFIX, "ci", ComparePlane::Create_prev, (void *)PLANAR_U }, + { "VDifferenceFromPrevious", BUILTIN_FUNC_PREFIX, "ci", ComparePlane::Create_prev, (void *)PLANAR_V }, + { "RGBDifferenceFromPrevious", BUILTIN_FUNC_PREFIX, "ci", ComparePlane::Create_prev, (void *)-1 }, + { "RDifferenceFromPrevious", BUILTIN_FUNC_PREFIX, "ci", ComparePlane::Create_prev, (void *)PLANAR_R }, + { "GDifferenceFromPrevious", BUILTIN_FUNC_PREFIX, "ci", ComparePlane::Create_prev, (void *)PLANAR_G }, + { "BDifferenceFromPrevious", BUILTIN_FUNC_PREFIX, "ci", ComparePlane::Create_prev, (void *)PLANAR_B }, + //{ "SatDifferenceFromPrevious","ci", CompareSat::Create_prev }, +//{ "HueDifferenceFromPrevious","ci", CompareHue::Create_prev }, + + { "YDifferenceToNext", BUILTIN_FUNC_PREFIX, "ci[offset]i", ComparePlane::Create_next, (void *)PLANAR_Y }, + { "UDifferenceToNext", BUILTIN_FUNC_PREFIX, "ci[offset]i", ComparePlane::Create_next, (void *)PLANAR_U }, + { "VDifferenceToNext", BUILTIN_FUNC_PREFIX, "ci[offset]i", ComparePlane::Create_next, (void *)PLANAR_V }, + { "RGBDifferenceToNext", BUILTIN_FUNC_PREFIX, "ci[offset]i", ComparePlane::Create_next, (void *)-1 }, + { "RDifferenceToNext", BUILTIN_FUNC_PREFIX, "ci[offset]i", ComparePlane::Create_next, (void *)PLANAR_R }, + { "GDifferenceToNext", BUILTIN_FUNC_PREFIX, "ci[offset]i", ComparePlane::Create_next, (void *)PLANAR_G }, + { "BDifferenceToNext", BUILTIN_FUNC_PREFIX, "ci[offset]i", ComparePlane::Create_next, (void *)PLANAR_B }, + //{ "SatDifferenceFromNext","ci[offset]i", CompareSat::Create_next }, +//{ "HueDifferenceFromNext","ci[offset]i", CompareHue::Create_next }, + { "YPlaneMax", BUILTIN_FUNC_PREFIX, "ci[threshold]f[offset]i", MinMaxPlane::Create_max, (void *)PLANAR_Y }, + { "YPlaneMin", BUILTIN_FUNC_PREFIX, "ci[threshold]f[offset]i", MinMaxPlane::Create_min, (void *)PLANAR_Y }, + { "YPlaneMedian", BUILTIN_FUNC_PREFIX, "ci[offset]i", MinMaxPlane::Create_median, (void *)PLANAR_Y }, + { "UPlaneMax", BUILTIN_FUNC_PREFIX, "ci[threshold]f[offset]i", MinMaxPlane::Create_max, (void *)PLANAR_U }, + { "UPlaneMin", BUILTIN_FUNC_PREFIX, "ci[threshold]f[offset]i", MinMaxPlane::Create_min, (void *)PLANAR_U }, + { "UPlaneMedian", BUILTIN_FUNC_PREFIX, "ci[offset]i", MinMaxPlane::Create_median, (void *)PLANAR_U }, + { "VPlaneMax", BUILTIN_FUNC_PREFIX, "ci[threshold]f[offset]i", MinMaxPlane::Create_max, (void *)PLANAR_V }, // AVS+! was before: missing offset parameter + { "VPlaneMin", BUILTIN_FUNC_PREFIX, "ci[threshold]f[offset]i", MinMaxPlane::Create_min, (void *)PLANAR_V }, // AVS+! was before: missing offset parameter + { "VPlaneMedian", BUILTIN_FUNC_PREFIX, "ci[offset]i", MinMaxPlane::Create_median, (void *)PLANAR_V }, + { "RPlaneMax", BUILTIN_FUNC_PREFIX, "ci[threshold]f[offset]i", MinMaxPlane::Create_max, (void *)PLANAR_R }, + { "RPlaneMin", BUILTIN_FUNC_PREFIX, "ci[threshold]f[offset]i", MinMaxPlane::Create_min, (void *)PLANAR_R }, + { "RPlaneMedian", BUILTIN_FUNC_PREFIX, "ci[offset]i", MinMaxPlane::Create_median, (void *)PLANAR_R }, + { "GPlaneMax", BUILTIN_FUNC_PREFIX, "ci[threshold]f[offset]i", MinMaxPlane::Create_max, (void *)PLANAR_G }, + { "GPlaneMin", BUILTIN_FUNC_PREFIX, "ci[threshold]f[offset]i", MinMaxPlane::Create_min, (void *)PLANAR_G }, + { "GPlaneMedian", BUILTIN_FUNC_PREFIX, "ci[offset]i", MinMaxPlane::Create_median, (void *)PLANAR_G }, + { "BPlaneMax", BUILTIN_FUNC_PREFIX, "ci[threshold]f[offset]i", MinMaxPlane::Create_max, (void *)PLANAR_B }, + { "BPlaneMin", BUILTIN_FUNC_PREFIX, "ci[threshold]f[offset]i", MinMaxPlane::Create_min, (void *)PLANAR_B }, + { "BPlaneMedian", BUILTIN_FUNC_PREFIX, "ci[offset]i", MinMaxPlane::Create_median, (void *)PLANAR_B }, + { "YPlaneMinMaxDifference", BUILTIN_FUNC_PREFIX, "ci[threshold]f[offset]i", MinMaxPlane::Create_minmax, (void *)PLANAR_Y }, + { "UPlaneMinMaxDifference", BUILTIN_FUNC_PREFIX, "ci[threshold]f[offset]i", MinMaxPlane::Create_minmax, (void *)PLANAR_U }, // AVS+! was before: missing offset parameter + { "VPlaneMinMaxDifference", BUILTIN_FUNC_PREFIX, "ci[threshold]f[offset]i", MinMaxPlane::Create_minmax, (void *)PLANAR_V }, // AVS+! was before: missing offset parameter + { "RPlaneMinMaxDifference", BUILTIN_FUNC_PREFIX, "ci[threshold]f[offset]i", MinMaxPlane::Create_minmax, (void *)PLANAR_R }, + { "GPlaneMinMaxDifference", BUILTIN_FUNC_PREFIX, "ci[threshold]f[offset]i", MinMaxPlane::Create_minmax, (void *)PLANAR_G }, + { "BPlaneMinMaxDifference", BUILTIN_FUNC_PREFIX, "ci[threshold]f[offset]i", MinMaxPlane::Create_minmax, (void *)PLANAR_B }, + +//{ "SatMax","ci[threshold]f[offset]i", MinMaxPlane::Create_maxsat }, ++accum[SatLookup[U,V]] +//{ "SatMin","ci[threshold]f[offset]i", MinMaxPlane::Create_minsat }, +//{ "SatMedian","ci[offset]i", MinMaxPlane::Create_mediansat }, +//{ "SatMinMaxDifference","ci[threshold]f[offset]i", MinMaxPlane::Create_minmaxsat }, + +//{ "HueMax","ci[threshold]f[offset]i", MinMaxPlane::Create_maxhue }, ++accum[HueLookup[U,V]] +//{ "HueMin","ci[threshold]f[offset]i", MinMaxPlane::Create_minhue }, +//{ "HueMedian","ci[offset]i", MinMaxPlane::Create_medianhue }, +//{ "HueMinMaxDifference","ci[threshold]f[offset]i", MinMaxPlane::Create_minmaxhue }, { 0 } }; @@ -124,7 +124,7 @@ extern const AVSFunction Conditional_funtions_filters[] = { AVSValue AveragePlane::Create(AVSValue args, void* user_data, IScriptEnvironment* env) { int plane = (int)reinterpret_cast(user_data); - return AvgPlane(args[0], user_data, plane, args[1].AsInt(0), env); + return AvgPlane(args[0], args[1].AsInt(-1), user_data, plane, args[2].AsInt(0), env); } // Average plane @@ -197,7 +197,7 @@ static double get_sum_of_pixels_isse(const BYTE* srcp, size_t height, size_t wid -AVSValue AveragePlane::AvgPlane(AVSValue clip, void* user_data, int plane, int offset, IScriptEnvironment* env) +AVSValue AveragePlane::AvgPlane(AVSValue clip, int n, void* user_data, int plane, int offset, IScriptEnvironment* env) { if (!clip.IsClip()) env->ThrowError("Average Plane: No clip supplied!"); @@ -208,11 +208,8 @@ AVSValue AveragePlane::AvgPlane(AVSValue clip, void* user_data, int plane, int o if (!vi.IsPlanar()) env->ThrowError("Average Plane: Only planar YUV or planar RGB images supported!"); - AVSValue cn = env->GetVarDef("current_frame"); - if (!cn.IsInt()) + if (n < 0) env->ThrowError("Average Plane: This filter can only be used within run-time filters"); - - int n = cn.AsInt(); n = min(max(n+offset,0), vi.num_frames-1); PVideoFrame src = child->GetFrame(n,env); @@ -261,17 +258,17 @@ AVSValue AveragePlane::AvgPlane(AVSValue clip, void* user_data, int plane, int o AVSValue ComparePlane::Create(AVSValue args, void* user_data, IScriptEnvironment* env) { int plane = (int)reinterpret_cast(user_data); - return CmpPlane(args[0],args[1], user_data, plane, env); + return CmpPlane(args[0], args[1].AsInt(-1), args[2], user_data, plane, env); } AVSValue ComparePlane::Create_prev(AVSValue args, void* user_data, IScriptEnvironment* env) { int plane = (int)reinterpret_cast(user_data); - return CmpPlaneSame(args[0], user_data, -1, plane, env); + return CmpPlaneSame(args[0], args[1].AsInt(-1), user_data, -1, plane, env); } AVSValue ComparePlane::Create_next(AVSValue args, void* user_data, IScriptEnvironment* env) { int plane = (int)reinterpret_cast(user_data); - return CmpPlaneSame(args[0], user_data, args[1].AsInt(1), plane, env); + return CmpPlaneSame(args[0], args[1].AsInt(-1), user_data, args[2].AsInt(1), plane, env); } @@ -465,7 +462,7 @@ static size_t get_sad_rgb_isse(const BYTE* src_ptr, const BYTE* other_ptr, size_ -AVSValue ComparePlane::CmpPlane(AVSValue clip, AVSValue clip2, void* user_data, int plane, IScriptEnvironment* env) +AVSValue ComparePlane::CmpPlane(AVSValue clip, int n, AVSValue clip2, void* user_data, int plane, IScriptEnvironment* env) { if (!clip.IsClip()) env->ThrowError("Plane Difference: No clip supplied!"); @@ -491,11 +488,8 @@ AVSValue ComparePlane::CmpPlane(AVSValue clip, AVSValue clip2, void* user_data, plane = 0; } - AVSValue cn = env->GetVarDef("current_frame"); - if (!cn.IsInt()) + if (n < 0) env->ThrowError("Plane Difference: This filter can only be used within run-time filters"); - - int n = cn.AsInt(); n = clamp(n,0,vi.num_frames-1); PVideoFrame src = child->GetFrame(n,env); @@ -585,7 +579,7 @@ AVSValue ComparePlane::CmpPlane(AVSValue clip, AVSValue clip2, void* user_data, } -AVSValue ComparePlane::CmpPlaneSame(AVSValue clip, void* user_data, int offset, int plane, IScriptEnvironment* env) +AVSValue ComparePlane::CmpPlaneSame(AVSValue clip, int n, void* user_data, int offset, int plane, IScriptEnvironment* env) { if (!clip.IsClip()) env->ThrowError("Plane Difference: No clip supplied!"); @@ -601,11 +595,8 @@ AVSValue ComparePlane::CmpPlaneSame(AVSValue clip, void* user_data, int offset, env->ThrowError("Plane Difference: Only planar YUV or planar RGB images images supported!"); } - AVSValue cn = env->GetVarDef("current_frame"); - if (!cn.IsInt()) + if (n < 0) env->ThrowError("Plane Difference: This filter can only be used within run-time filters"); - - int n = cn.AsInt(); n = clamp(n,0,vi.num_frames-1); int n2 = clamp(n+offset,0,vi.num_frames-1); @@ -687,26 +678,26 @@ AVSValue ComparePlane::CmpPlaneSame(AVSValue clip, void* user_data, int offset, AVSValue MinMaxPlane::Create_max(AVSValue args, void* user_data, IScriptEnvironment* env) { int plane = (int)reinterpret_cast(user_data); - return MinMax(args[0], user_data, args[1].AsDblDef(0.0), args[2].AsInt(0), plane, MAX, env); + return MinMax(args[0], args[1].AsInt(-1), user_data, args[2].AsDblDef(0.0), args[3].AsInt(0), plane, MAX, env); } AVSValue MinMaxPlane::Create_min(AVSValue args, void* user_data, IScriptEnvironment* env) { int plane = (int)reinterpret_cast(user_data); - return MinMax(args[0], user_data, args[1].AsDblDef(0.0), args[2].AsInt(0), plane, MIN, env); + return MinMax(args[0], args[1].AsInt(-1), user_data, args[2].AsDblDef(0.0), args[3].AsInt(0), plane, MIN, env); } AVSValue MinMaxPlane::Create_median(AVSValue args, void* user_data, IScriptEnvironment* env) { int plane = (int)reinterpret_cast(user_data); - return MinMax(args[0], user_data, 50.0, args[1].AsInt(0), plane, MIN, env); + return MinMax(args[0], args[1].AsInt(-1), user_data, 50.0, args[2].AsInt(0), plane, MIN, env); } AVSValue MinMaxPlane::Create_minmax(AVSValue args, void* user_data, IScriptEnvironment* env) { int plane = (int)reinterpret_cast(user_data); - return MinMax(args[0], user_data, args[1].AsDblDef(0.0), args[2].AsInt(0), plane, MINMAX_DIFFERENCE, env); + return MinMax(args[0], args[1].AsInt(-1), user_data, args[2].AsDblDef(0.0), args[3].AsInt(0), plane, MINMAX_DIFFERENCE, env); } -AVSValue MinMaxPlane::MinMax(AVSValue clip, void* user_data, double threshold, int offset, int plane, int mode, IScriptEnvironment* env) { +AVSValue MinMaxPlane::MinMax(AVSValue clip, int n, void* user_data, double threshold, int offset, int plane, int mode, IScriptEnvironment* env) { if (!clip.IsClip()) env->ThrowError("MinMax: No clip supplied!"); @@ -723,11 +714,8 @@ AVSValue MinMaxPlane::MinMax(AVSValue clip, void* user_data, double threshold, i uint32_t *accum_buf = new uint32_t[buffersize]; // Get current frame number - AVSValue cn = env->GetVarDef("current_frame"); - if (!cn.IsInt()) + if (n < 0) env->ThrowError("MinMax: This filter can only be used within run-time filters"); - - int n = cn.AsInt(); n = min(max(n+offset,0),vi.num_frames-1); #ifdef DEBUG_GSCRIPTCLIP_MT @@ -836,7 +824,7 @@ AVSValue MinMaxPlane::MinMax(AVSValue clip, void* user_data, double threshold, i } delete[] accum_buf; - _RPT2(0, "End of MinMax cn=%d n=%d\r", cn.AsInt(), n); + _RPT2(0, "End of MinMax n=%d\r", n); if (pixelsize == 4) return AVSValue((double)retval / (real_buffersize-1)); // convert back to float, /65535 diff --git a/avs_core/filters/conditional/conditional_functions.h b/avs_core/filters/conditional/conditional_functions.h index cb5ffc78a..0ff36e269 100644 --- a/avs_core/filters/conditional/conditional_functions.h +++ b/avs_core/filters/conditional/conditional_functions.h @@ -40,14 +40,14 @@ class AveragePlane { public: static AVSValue Create(AVSValue args, void* user_data, IScriptEnvironment* env); - static AVSValue AvgPlane(AVSValue clip, void* user_data, int plane, int offset, IScriptEnvironment* env); + static AVSValue AvgPlane(AVSValue clip, int n, void* user_data, int plane, int offset, IScriptEnvironment* env); }; class ComparePlane { public: - static AVSValue CmpPlane(AVSValue clip, AVSValue clip2, void* user_data, int plane, IScriptEnvironment* env); - static AVSValue CmpPlaneSame(AVSValue clip, void* user_data, int offset, int plane, IScriptEnvironment* env); + static AVSValue CmpPlane(AVSValue clip, int n, AVSValue clip2, void* user_data, int plane, IScriptEnvironment* env); + static AVSValue CmpPlaneSame(AVSValue clip, int n, void* user_data, int offset, int plane, IScriptEnvironment* env); static AVSValue Create(AVSValue args, void* user_data, IScriptEnvironment* env); static AVSValue Create_prev(AVSValue args, void* user_data, IScriptEnvironment* env); @@ -58,7 +58,7 @@ class ComparePlane { class MinMaxPlane { public: - static AVSValue MinMax(AVSValue clip, void* user_data, double threshold, int offset, int plane, int mode, IScriptEnvironment* env); + static AVSValue MinMax(AVSValue clip, int n, void* user_data, double threshold, int offset, int plane, int mode, IScriptEnvironment* env); static AVSValue Create_max(AVSValue args, void* user_data, IScriptEnvironment* env); static AVSValue Create_min(AVSValue args, void* user_data, IScriptEnvironment* env); From 7b1f3c71641109584e2d0d226cd4c5b6d727bf53 Mon Sep 17 00:00:00 2001 From: Etienne Charland Date: Tue, 25 Apr 2017 14:11:31 -0500 Subject: [PATCH 2/3] Change per-frame functions syntax to start with "frame_number,last" --- avs_core/core/parser/expression.cpp | 110 +++++++----- avs_core/core/parser/expression.h | 7 +- .../conditional/conditional_functions.cpp | 168 +++++++++--------- .../conditional/conditional_functions.h | 8 +- 4 files changed, 157 insertions(+), 136 deletions(-) diff --git a/avs_core/core/parser/expression.cpp b/avs_core/core/parser/expression.cpp index b339f9286..c6c93a7d8 100644 --- a/avs_core/core/parser/expression.cpp +++ b/avs_core/core/parser/expression.cpp @@ -38,7 +38,6 @@ #include "../internal.h" #include #include -#include class BreakStmtException @@ -445,38 +444,42 @@ AVSValue ExpNot::Evaluate(IScriptEnvironment* env) } -AVSValue ExpVariableReference::Evaluate(IScriptEnvironment* env) +AVSValue ExpVariableReference::Evaluate(IScriptEnvironment* env) { AVSValue result; IScriptEnvironment2 *env2 = static_cast(env); // first look for a genuine variable // Don't add a cache to this one, it's a Var - if (env2->GetVar(name, &result)) { + if (env2->GetVar(name, &result)) return result; - } - else { - // Swap order to match ::Call below -- Gavino Jan 2010 - // look for an argless function - if (!env2->Invoke(&result, name, AVSValue(0,0))) - { - // look for a single-arg function taking implicit "last" - AVSValue last; - if (!env2->GetVar("last", &last) || !env2->Invoke(&result, name, last)) - { - // look for function taking last and frame_number for per-frame expressions - AVSValue sargs[2] = { last, frame_number }; - const char *nargs[2] = { 0, 0 }; - if (frame_number < 0 || !env2->Invoke(&result, name, AVSValue(sargs, 2), nargs)) { - env->ThrowError("I don't know what '%s' means.", name); - return 0; - } - } + // Try various function syntaxes. + + // Per-frame syntax + if (frame_number >= 0) + { + // Try function starting with "n,clip". Only per-frame functions start with "ic". + AVSValue sargs[2] = { frame_number }; + const char *nargs[2] = { 0, 0 }; + if (env2->GetVar("last", &sargs[1])) { + if (env2->Invoke(&result, name, AVSValue(sargs, 2), nargs)) + return result; } } - return result; + // Regular syntax + // look for an argless function + if (env2->Invoke(&result, name, AVSValue(0, 0))) + return result; + + // look for a single-arg function taking implicit "last" + AVSValue last; + if (env2->GetVar("last", &last) && env2->Invoke(&result, name, last)) + return result; + + env->ThrowError("I don't know what '%s' means.", name); + return 0; } @@ -523,34 +526,43 @@ AVSValue ExpFunctionCall::Evaluate(IScriptEnvironment* env) std::vector args(arg_expr_count+2, AVSValue()); for (int a=0; aEvaluate(env); + int HasLast = 0; // Only read if needed. 0=not loaded, 1=loaded, -1=failed - // first try without implicit "last" - try - { // Invoke can always throw by calling a constructor of a filter that throws - if (env2->Invoke(&result, name, AVSValue(args.data()+2, arg_expr_count), arg_expr_names+2)) - return result; - } catch(const IScriptEnvironment::NotFound&){} - - // if that fails, try with implicit "last" (except when OOP notation was used) - if (!oop_notation && env2->GetVar("last", &args[1])) + // Per-frame syntax + if (frame_number >= 0) { - try - { - if (env2->Invoke(&result, name, AVSValue(args.data()+1, arg_expr_count+1), arg_expr_names+1)) + // Try "n,args" if first arg is a clip. Only per-frame functions start with "ic". + if (arg_expr_count > 0 && args[2].IsClip()) { + args[1] = AVSValue(frame_number); + if (EvaluateSyntax(&result, name, &args, 1, env2)) return result; - } catch(const IScriptEnvironment::NotFound&){} + } - // for per-frame expressions, try with implicit "last" and "frame_number" - if (frame_number >= 0) - { - args[0] = args[1]; // "last" - args[1] = AVSValue(frame_number); - try - { - if (env2->Invoke(&result, name, AVSValue(args.data(), arg_expr_count+2), arg_expr_names)) + // Try "n,last,args" (except when OOP notation was used) + if (!oop_notation) { + if (HasLast == 0) // Only read if needed + HasLast = env2->GetVar("last", &args[1]) ? 1 : -1; + if (HasLast == 1) { + args[0] = AVSValue(frame_number); + if (EvaluateSyntax(&result, name, &args, 2, env2)) return result; } - catch (const IScriptEnvironment::NotFound&) {} + } + } + + // Regular syntax + // Try "args" + if (EvaluateSyntax(&result, name, &args, 0, env2)) + return result; + + // Try "last,args" (except when OOP notation was used) + if (!oop_notation) { + if (HasLast == 0) // Only read if needed + HasLast = env2->GetVar("last", &args[1]) ? 1 : -1; + if (HasLast == 1) { + args[0] = AVSValue(frame_number); + if (EvaluateSyntax(&result, name, &args, 1, env2)) + return result; } } @@ -561,3 +573,13 @@ AVSValue ExpFunctionCall::Evaluate(IScriptEnvironment* env) assert(0); // we should never get here return 0; } + +bool ExpFunctionCall::EvaluateSyntax(AVSValue* result, const char* name, std::vector* args, int extra, IScriptEnvironment2* env2) { + try + { + if (env2->Invoke(result, name, AVSValue(args->data() + 2 - extra, arg_expr_count + extra), arg_expr_names + 2 - extra)) + return true; + } + catch (const IScriptEnvironment::NotFound&) {} + return false; +} \ No newline at end of file diff --git a/avs_core/core/parser/expression.h b/avs_core/core/parser/expression.h index 857de53da..3b432f5ca 100644 --- a/avs_core/core/parser/expression.h +++ b/avs_core/core/parser/expression.h @@ -36,10 +36,7 @@ #define __Expression_H__ #include - -#ifdef NEW_AVSVALUE #include -#endif /******************************************************************** ********************************************************************/ @@ -416,8 +413,10 @@ class ExpFunctionCall : public Expression ~ExpFunctionCall(void); virtual AVSValue Evaluate(IScriptEnvironment* env); - + bool EvaluateSyntax(AVSValue* result, const char* name, std::vector* args, int extra, IScriptEnvironment2* env2); + private: + const char* const name; PExpression* arg_exprs; const char** arg_expr_names; diff --git a/avs_core/filters/conditional/conditional_functions.cpp b/avs_core/filters/conditional/conditional_functions.cpp index c43c316bc..0144b5772 100644 --- a/avs_core/filters/conditional/conditional_functions.cpp +++ b/avs_core/filters/conditional/conditional_functions.cpp @@ -45,78 +45,78 @@ #include "../focus.h" // sad extern const AVSFunction Conditional_funtions_filters[] = { - { "AverageLuma", BUILTIN_FUNC_PREFIX, "ci[offset]i", AveragePlane::Create, (void *)PLANAR_Y }, - { "AverageChromaU", BUILTIN_FUNC_PREFIX, "ci[offset]i", AveragePlane::Create, (void *)PLANAR_U }, - { "AverageChromaV", BUILTIN_FUNC_PREFIX, "ci[offset]i", AveragePlane::Create, (void *)PLANAR_V }, - { "AverageR", BUILTIN_FUNC_PREFIX, "ci[offset]i", AveragePlane::Create, (void *)PLANAR_R }, - { "AverageG", BUILTIN_FUNC_PREFIX, "ci[offset]i", AveragePlane::Create, (void *)PLANAR_G }, - { "AverageB", BUILTIN_FUNC_PREFIX, "ci[offset]i", AveragePlane::Create, (void *)PLANAR_B }, - //{ "AverageSat","ci[offset]i", AverageSat::Create }, Sum(SatLookup[U,V])/N, SatLookup[U,V]=1.4087*sqrt((U-128)**2+(V-128)**2) -//{ "AverageHue","ci[offset]i", AverageHue::Create }, Sum(HueLookup[U,V])/N, HueLookup[U,V]=40.5845*Atan2(U-128,V-128) - - { "RGBDifference", BUILTIN_FUNC_PREFIX, "cic", ComparePlane::Create, (void *)-1 }, - { "LumaDifference", BUILTIN_FUNC_PREFIX, "cic", ComparePlane::Create, (void *)PLANAR_Y }, - { "ChromaUDifference", BUILTIN_FUNC_PREFIX, "cic", ComparePlane::Create, (void *)PLANAR_U }, - { "ChromaVDifference", BUILTIN_FUNC_PREFIX, "cic", ComparePlane::Create, (void *)PLANAR_V }, - { "RDifference", BUILTIN_FUNC_PREFIX, "cic", ComparePlane::Create, (void *)PLANAR_R }, - { "GDifference", BUILTIN_FUNC_PREFIX, "cic", ComparePlane::Create, (void *)PLANAR_G }, - { "BDifference", BUILTIN_FUNC_PREFIX, "cic", ComparePlane::Create, (void *)PLANAR_B }, - //{ "SatDifference","cic", CompareSat::Create }, Sum(Abs(SatLookup[U1,V1]-SatLookup[U2,V2]))/N -//{ "HueDifference","cic", CompareHue::Create }, Sum(Abs(HueLookup[U1,V1]-HueLookup[U2,V2]))/N - - { "YDifferenceFromPrevious", BUILTIN_FUNC_PREFIX, "ci", ComparePlane::Create_prev, (void *)PLANAR_Y }, - { "UDifferenceFromPrevious", BUILTIN_FUNC_PREFIX, "ci", ComparePlane::Create_prev, (void *)PLANAR_U }, - { "VDifferenceFromPrevious", BUILTIN_FUNC_PREFIX, "ci", ComparePlane::Create_prev, (void *)PLANAR_V }, - { "RGBDifferenceFromPrevious", BUILTIN_FUNC_PREFIX, "ci", ComparePlane::Create_prev, (void *)-1 }, - { "RDifferenceFromPrevious", BUILTIN_FUNC_PREFIX, "ci", ComparePlane::Create_prev, (void *)PLANAR_R }, - { "GDifferenceFromPrevious", BUILTIN_FUNC_PREFIX, "ci", ComparePlane::Create_prev, (void *)PLANAR_G }, - { "BDifferenceFromPrevious", BUILTIN_FUNC_PREFIX, "ci", ComparePlane::Create_prev, (void *)PLANAR_B }, - //{ "SatDifferenceFromPrevious","ci", CompareSat::Create_prev }, -//{ "HueDifferenceFromPrevious","ci", CompareHue::Create_prev }, - - { "YDifferenceToNext", BUILTIN_FUNC_PREFIX, "ci[offset]i", ComparePlane::Create_next, (void *)PLANAR_Y }, - { "UDifferenceToNext", BUILTIN_FUNC_PREFIX, "ci[offset]i", ComparePlane::Create_next, (void *)PLANAR_U }, - { "VDifferenceToNext", BUILTIN_FUNC_PREFIX, "ci[offset]i", ComparePlane::Create_next, (void *)PLANAR_V }, - { "RGBDifferenceToNext", BUILTIN_FUNC_PREFIX, "ci[offset]i", ComparePlane::Create_next, (void *)-1 }, - { "RDifferenceToNext", BUILTIN_FUNC_PREFIX, "ci[offset]i", ComparePlane::Create_next, (void *)PLANAR_R }, - { "GDifferenceToNext", BUILTIN_FUNC_PREFIX, "ci[offset]i", ComparePlane::Create_next, (void *)PLANAR_G }, - { "BDifferenceToNext", BUILTIN_FUNC_PREFIX, "ci[offset]i", ComparePlane::Create_next, (void *)PLANAR_B }, - //{ "SatDifferenceFromNext","ci[offset]i", CompareSat::Create_next }, -//{ "HueDifferenceFromNext","ci[offset]i", CompareHue::Create_next }, - { "YPlaneMax", BUILTIN_FUNC_PREFIX, "ci[threshold]f[offset]i", MinMaxPlane::Create_max, (void *)PLANAR_Y }, - { "YPlaneMin", BUILTIN_FUNC_PREFIX, "ci[threshold]f[offset]i", MinMaxPlane::Create_min, (void *)PLANAR_Y }, - { "YPlaneMedian", BUILTIN_FUNC_PREFIX, "ci[offset]i", MinMaxPlane::Create_median, (void *)PLANAR_Y }, - { "UPlaneMax", BUILTIN_FUNC_PREFIX, "ci[threshold]f[offset]i", MinMaxPlane::Create_max, (void *)PLANAR_U }, - { "UPlaneMin", BUILTIN_FUNC_PREFIX, "ci[threshold]f[offset]i", MinMaxPlane::Create_min, (void *)PLANAR_U }, - { "UPlaneMedian", BUILTIN_FUNC_PREFIX, "ci[offset]i", MinMaxPlane::Create_median, (void *)PLANAR_U }, - { "VPlaneMax", BUILTIN_FUNC_PREFIX, "ci[threshold]f[offset]i", MinMaxPlane::Create_max, (void *)PLANAR_V }, // AVS+! was before: missing offset parameter - { "VPlaneMin", BUILTIN_FUNC_PREFIX, "ci[threshold]f[offset]i", MinMaxPlane::Create_min, (void *)PLANAR_V }, // AVS+! was before: missing offset parameter - { "VPlaneMedian", BUILTIN_FUNC_PREFIX, "ci[offset]i", MinMaxPlane::Create_median, (void *)PLANAR_V }, - { "RPlaneMax", BUILTIN_FUNC_PREFIX, "ci[threshold]f[offset]i", MinMaxPlane::Create_max, (void *)PLANAR_R }, - { "RPlaneMin", BUILTIN_FUNC_PREFIX, "ci[threshold]f[offset]i", MinMaxPlane::Create_min, (void *)PLANAR_R }, - { "RPlaneMedian", BUILTIN_FUNC_PREFIX, "ci[offset]i", MinMaxPlane::Create_median, (void *)PLANAR_R }, - { "GPlaneMax", BUILTIN_FUNC_PREFIX, "ci[threshold]f[offset]i", MinMaxPlane::Create_max, (void *)PLANAR_G }, - { "GPlaneMin", BUILTIN_FUNC_PREFIX, "ci[threshold]f[offset]i", MinMaxPlane::Create_min, (void *)PLANAR_G }, - { "GPlaneMedian", BUILTIN_FUNC_PREFIX, "ci[offset]i", MinMaxPlane::Create_median, (void *)PLANAR_G }, - { "BPlaneMax", BUILTIN_FUNC_PREFIX, "ci[threshold]f[offset]i", MinMaxPlane::Create_max, (void *)PLANAR_B }, - { "BPlaneMin", BUILTIN_FUNC_PREFIX, "ci[threshold]f[offset]i", MinMaxPlane::Create_min, (void *)PLANAR_B }, - { "BPlaneMedian", BUILTIN_FUNC_PREFIX, "ci[offset]i", MinMaxPlane::Create_median, (void *)PLANAR_B }, - { "YPlaneMinMaxDifference", BUILTIN_FUNC_PREFIX, "ci[threshold]f[offset]i", MinMaxPlane::Create_minmax, (void *)PLANAR_Y }, - { "UPlaneMinMaxDifference", BUILTIN_FUNC_PREFIX, "ci[threshold]f[offset]i", MinMaxPlane::Create_minmax, (void *)PLANAR_U }, // AVS+! was before: missing offset parameter - { "VPlaneMinMaxDifference", BUILTIN_FUNC_PREFIX, "ci[threshold]f[offset]i", MinMaxPlane::Create_minmax, (void *)PLANAR_V }, // AVS+! was before: missing offset parameter - { "RPlaneMinMaxDifference", BUILTIN_FUNC_PREFIX, "ci[threshold]f[offset]i", MinMaxPlane::Create_minmax, (void *)PLANAR_R }, - { "GPlaneMinMaxDifference", BUILTIN_FUNC_PREFIX, "ci[threshold]f[offset]i", MinMaxPlane::Create_minmax, (void *)PLANAR_G }, - { "BPlaneMinMaxDifference", BUILTIN_FUNC_PREFIX, "ci[threshold]f[offset]i", MinMaxPlane::Create_minmax, (void *)PLANAR_B }, - -//{ "SatMax","ci[threshold]f[offset]i", MinMaxPlane::Create_maxsat }, ++accum[SatLookup[U,V]] -//{ "SatMin","ci[threshold]f[offset]i", MinMaxPlane::Create_minsat }, -//{ "SatMedian","ci[offset]i", MinMaxPlane::Create_mediansat }, -//{ "SatMinMaxDifference","ci[threshold]f[offset]i", MinMaxPlane::Create_minmaxsat }, - -//{ "HueMax","ci[threshold]f[offset]i", MinMaxPlane::Create_maxhue }, ++accum[HueLookup[U,V]] -//{ "HueMin","ci[threshold]f[offset]i", MinMaxPlane::Create_minhue }, -//{ "HueMedian","ci[offset]i", MinMaxPlane::Create_medianhue }, -//{ "HueMinMaxDifference","ci[threshold]f[offset]i", MinMaxPlane::Create_minmaxhue }, + { "AverageLuma", BUILTIN_FUNC_PREFIX, "ic[offset]i", AveragePlane::Create, (void *)PLANAR_Y }, + { "AverageChromaU", BUILTIN_FUNC_PREFIX, "ic[offset]i", AveragePlane::Create, (void *)PLANAR_U }, + { "AverageChromaV", BUILTIN_FUNC_PREFIX, "ic[offset]i", AveragePlane::Create, (void *)PLANAR_V }, + { "AverageR", BUILTIN_FUNC_PREFIX, "ic[offset]i", AveragePlane::Create, (void *)PLANAR_R }, + { "AverageG", BUILTIN_FUNC_PREFIX, "ic[offset]i", AveragePlane::Create, (void *)PLANAR_G }, + { "AverageB", BUILTIN_FUNC_PREFIX, "ic[offset]i", AveragePlane::Create, (void *)PLANAR_B }, + //{ "AverageSat","ic[offset]i", AverageSat::Create }, Sum(SatLookup[U,V])/N, SatLookup[U,V]=1.4087*sqrt((U-128)**2+(V-128)**2) +//{ "AverageHue","ic[offset]i", AverageHue::Create }, Sum(HueLookup[U,V])/N, HueLookup[U,V]=40.5845*Atan2(U-128,V-128) + + { "RGBDifference", BUILTIN_FUNC_PREFIX, "icc", ComparePlane::Create, (void *)-1 }, + { "LumaDifference", BUILTIN_FUNC_PREFIX, "icc", ComparePlane::Create, (void *)PLANAR_Y }, + { "ChromaUDifference", BUILTIN_FUNC_PREFIX, "icc", ComparePlane::Create, (void *)PLANAR_U }, + { "ChromaVDifference", BUILTIN_FUNC_PREFIX, "icc", ComparePlane::Create, (void *)PLANAR_V }, + { "RDifference", BUILTIN_FUNC_PREFIX, "icc", ComparePlane::Create, (void *)PLANAR_R }, + { "GDifference", BUILTIN_FUNC_PREFIX, "icc", ComparePlane::Create, (void *)PLANAR_G }, + { "BDifference", BUILTIN_FUNC_PREFIX, "icc", ComparePlane::Create, (void *)PLANAR_B }, + //{ "SatDifference","icc", CompareSat::Create }, Sum(Abs(SatLookup[U1,V1]-SatLookup[U2,V2]))/N +//{ "HueDifference","icc", CompareHue::Create }, Sum(Abs(HueLookup[U1,V1]-HueLookup[U2,V2]))/N + + { "YDifferenceFromPrevious", BUILTIN_FUNC_PREFIX, "ic", ComparePlane::Create_prev, (void *)PLANAR_Y }, + { "UDifferenceFromPrevious", BUILTIN_FUNC_PREFIX, "ic", ComparePlane::Create_prev, (void *)PLANAR_U }, + { "VDifferenceFromPrevious", BUILTIN_FUNC_PREFIX, "ic", ComparePlane::Create_prev, (void *)PLANAR_V }, + { "RGBDifferenceFromPrevious", BUILTIN_FUNC_PREFIX, "ic", ComparePlane::Create_prev, (void *)-1 }, + { "RDifferenceFromPrevious", BUILTIN_FUNC_PREFIX, "ic", ComparePlane::Create_prev, (void *)PLANAR_R }, + { "GDifferenceFromPrevious", BUILTIN_FUNC_PREFIX, "ic", ComparePlane::Create_prev, (void *)PLANAR_G }, + { "BDifferenceFromPrevious", BUILTIN_FUNC_PREFIX, "ic", ComparePlane::Create_prev, (void *)PLANAR_B }, + //{ "SatDifferenceFromPrevious","ic", CompareSat::Create_prev }, +//{ "HueDifferenceFromPrevious","ic", CompareHue::Create_prev }, + + { "YDifferenceToNext", BUILTIN_FUNC_PREFIX, "ic[offset]i", ComparePlane::Create_next, (void *)PLANAR_Y }, + { "UDifferenceToNext", BUILTIN_FUNC_PREFIX, "ic[offset]i", ComparePlane::Create_next, (void *)PLANAR_U }, + { "VDifferenceToNext", BUILTIN_FUNC_PREFIX, "ic[offset]i", ComparePlane::Create_next, (void *)PLANAR_V }, + { "RGBDifferenceToNext", BUILTIN_FUNC_PREFIX, "ic[offset]i", ComparePlane::Create_next, (void *)-1 }, + { "RDifferenceToNext", BUILTIN_FUNC_PREFIX, "ic[offset]i", ComparePlane::Create_next, (void *)PLANAR_R }, + { "GDifferenceToNext", BUILTIN_FUNC_PREFIX, "ic[offset]i", ComparePlane::Create_next, (void *)PLANAR_G }, + { "BDifferenceToNext", BUILTIN_FUNC_PREFIX, "ic[offset]i", ComparePlane::Create_next, (void *)PLANAR_B }, + //{ "SatDifferenceFromNext","ic[offset]i", CompareSat::Create_next }, +//{ "HueDifferenceFromNext","ic[offset]i", CompareHue::Create_next }, + { "YPlaneMax", BUILTIN_FUNC_PREFIX, "ic[threshold]f[offset]i", MinMaxPlane::Create_max, (void *)PLANAR_Y }, + { "YPlaneMin", BUILTIN_FUNC_PREFIX, "ic[threshold]f[offset]i", MinMaxPlane::Create_min, (void *)PLANAR_Y }, + { "YPlaneMedian", BUILTIN_FUNC_PREFIX, "ic[offset]i", MinMaxPlane::Create_median, (void *)PLANAR_Y }, + { "UPlaneMax", BUILTIN_FUNC_PREFIX, "ic[threshold]f[offset]i", MinMaxPlane::Create_max, (void *)PLANAR_U }, + { "UPlaneMin", BUILTIN_FUNC_PREFIX, "ic[threshold]f[offset]i", MinMaxPlane::Create_min, (void *)PLANAR_U }, + { "UPlaneMedian", BUILTIN_FUNC_PREFIX, "ic[offset]i", MinMaxPlane::Create_median, (void *)PLANAR_U }, + { "VPlaneMax", BUILTIN_FUNC_PREFIX, "ic[threshold]f[offset]i", MinMaxPlane::Create_max, (void *)PLANAR_V }, // AVS+! was before: missing offset parameter + { "VPlaneMin", BUILTIN_FUNC_PREFIX, "ic[threshold]f[offset]i", MinMaxPlane::Create_min, (void *)PLANAR_V }, // AVS+! was before: missing offset parameter + { "VPlaneMedian", BUILTIN_FUNC_PREFIX, "ic[offset]i", MinMaxPlane::Create_median, (void *)PLANAR_V }, + { "RPlaneMax", BUILTIN_FUNC_PREFIX, "ic[threshold]f[offset]i", MinMaxPlane::Create_max, (void *)PLANAR_R }, + { "RPlaneMin", BUILTIN_FUNC_PREFIX, "ic[threshold]f[offset]i", MinMaxPlane::Create_min, (void *)PLANAR_R }, + { "RPlaneMedian", BUILTIN_FUNC_PREFIX, "ic[offset]i", MinMaxPlane::Create_median, (void *)PLANAR_R }, + { "GPlaneMax", BUILTIN_FUNC_PREFIX, "ic[threshold]f[offset]i", MinMaxPlane::Create_max, (void *)PLANAR_G }, + { "GPlaneMin", BUILTIN_FUNC_PREFIX, "ic[threshold]f[offset]i", MinMaxPlane::Create_min, (void *)PLANAR_G }, + { "GPlaneMedian", BUILTIN_FUNC_PREFIX, "ic[offset]i", MinMaxPlane::Create_median, (void *)PLANAR_G }, + { "BPlaneMax", BUILTIN_FUNC_PREFIX, "ic[threshold]f[offset]i", MinMaxPlane::Create_max, (void *)PLANAR_B }, + { "BPlaneMin", BUILTIN_FUNC_PREFIX, "ic[threshold]f[offset]i", MinMaxPlane::Create_min, (void *)PLANAR_B }, + { "BPlaneMedian", BUILTIN_FUNC_PREFIX, "ic[offset]i", MinMaxPlane::Create_median, (void *)PLANAR_B }, + { "YPlaneMinMaxDifference", BUILTIN_FUNC_PREFIX, "ic[threshold]f[offset]i", MinMaxPlane::Create_minmax, (void *)PLANAR_Y }, + { "UPlaneMinMaxDifference", BUILTIN_FUNC_PREFIX, "ic[threshold]f[offset]i", MinMaxPlane::Create_minmax, (void *)PLANAR_U }, // AVS+! was before: missing offset parameter + { "VPlaneMinMaxDifference", BUILTIN_FUNC_PREFIX, "ic[threshold]f[offset]i", MinMaxPlane::Create_minmax, (void *)PLANAR_V }, // AVS+! was before: missing offset parameter + { "RPlaneMinMaxDifference", BUILTIN_FUNC_PREFIX, "ic[threshold]f[offset]i", MinMaxPlane::Create_minmax, (void *)PLANAR_R }, + { "GPlaneMinMaxDifference", BUILTIN_FUNC_PREFIX, "ic[threshold]f[offset]i", MinMaxPlane::Create_minmax, (void *)PLANAR_G }, + { "BPlaneMinMaxDifference", BUILTIN_FUNC_PREFIX, "ic[threshold]f[offset]i", MinMaxPlane::Create_minmax, (void *)PLANAR_B }, + +//{ "SatMax","ic[threshold]f[offset]i", MinMaxPlane::Create_maxsat }, ++accum[SatLookup[U,V]] +//{ "SatMin","ic[threshold]f[offset]i", MinMaxPlane::Create_minsat }, +//{ "SatMedian","ic[offset]i", MinMaxPlane::Create_mediansat }, +//{ "SatMinMaxDifference","ic[threshold]f[offset]i", MinMaxPlane::Create_minmaxsat }, + +//{ "HueMax","ic[threshold]f[offset]i", MinMaxPlane::Create_maxhue }, ++accum[HueLookup[U,V]] +//{ "HueMin","ic[threshold]f[offset]i", MinMaxPlane::Create_minhue }, +//{ "HueMedian","ic[offset]i", MinMaxPlane::Create_medianhue }, +//{ "HueMinMaxDifference","ic[threshold]f[offset]i", MinMaxPlane::Create_minmaxhue }, { 0 } }; @@ -124,7 +124,7 @@ extern const AVSFunction Conditional_funtions_filters[] = { AVSValue AveragePlane::Create(AVSValue args, void* user_data, IScriptEnvironment* env) { int plane = (int)reinterpret_cast(user_data); - return AvgPlane(args[0], args[1].AsInt(-1), user_data, plane, args[2].AsInt(0), env); + return AvgPlane(args[0].AsInt(-1), args[1], user_data, plane, args[2].AsInt(0), env); } // Average plane @@ -197,7 +197,7 @@ static double get_sum_of_pixels_isse(const BYTE* srcp, size_t height, size_t wid -AVSValue AveragePlane::AvgPlane(AVSValue clip, int n, void* user_data, int plane, int offset, IScriptEnvironment* env) +AVSValue AveragePlane::AvgPlane(int n, AVSValue clip, void* user_data, int plane, int offset, IScriptEnvironment* env) { if (!clip.IsClip()) env->ThrowError("Average Plane: No clip supplied!"); @@ -258,17 +258,17 @@ AVSValue AveragePlane::AvgPlane(AVSValue clip, int n, void* user_data, int plane AVSValue ComparePlane::Create(AVSValue args, void* user_data, IScriptEnvironment* env) { int plane = (int)reinterpret_cast(user_data); - return CmpPlane(args[0], args[1].AsInt(-1), args[2], user_data, plane, env); + return CmpPlane(args[0].AsInt(-1), args[1], args[2], user_data, plane, env); } AVSValue ComparePlane::Create_prev(AVSValue args, void* user_data, IScriptEnvironment* env) { int plane = (int)reinterpret_cast(user_data); - return CmpPlaneSame(args[0], args[1].AsInt(-1), user_data, -1, plane, env); + return CmpPlaneSame(args[0].AsInt(-1), args[1], user_data, -1, plane, env); } AVSValue ComparePlane::Create_next(AVSValue args, void* user_data, IScriptEnvironment* env) { int plane = (int)reinterpret_cast(user_data); - return CmpPlaneSame(args[0], args[1].AsInt(-1), user_data, args[2].AsInt(1), plane, env); + return CmpPlaneSame(args[0].AsInt(-1), args[1], user_data, args[2].AsInt(1), plane, env); } @@ -462,7 +462,7 @@ static size_t get_sad_rgb_isse(const BYTE* src_ptr, const BYTE* other_ptr, size_ -AVSValue ComparePlane::CmpPlane(AVSValue clip, int n, AVSValue clip2, void* user_data, int plane, IScriptEnvironment* env) +AVSValue ComparePlane::CmpPlane(int n, AVSValue clip, AVSValue clip2, void* user_data, int plane, IScriptEnvironment* env) { if (!clip.IsClip()) env->ThrowError("Plane Difference: No clip supplied!"); @@ -579,7 +579,7 @@ AVSValue ComparePlane::CmpPlane(AVSValue clip, int n, AVSValue clip2, void* user } -AVSValue ComparePlane::CmpPlaneSame(AVSValue clip, int n, void* user_data, int offset, int plane, IScriptEnvironment* env) +AVSValue ComparePlane::CmpPlaneSame(int n, AVSValue clip, void* user_data, int offset, int plane, IScriptEnvironment* env) { if (!clip.IsClip()) env->ThrowError("Plane Difference: No clip supplied!"); @@ -678,26 +678,26 @@ AVSValue ComparePlane::CmpPlaneSame(AVSValue clip, int n, void* user_data, int o AVSValue MinMaxPlane::Create_max(AVSValue args, void* user_data, IScriptEnvironment* env) { int plane = (int)reinterpret_cast(user_data); - return MinMax(args[0], args[1].AsInt(-1), user_data, args[2].AsDblDef(0.0), args[3].AsInt(0), plane, MAX, env); + return MinMax(args[0].AsInt(-1), args[1], user_data, args[2].AsDblDef(0.0), args[3].AsInt(0), plane, MAX, env); } AVSValue MinMaxPlane::Create_min(AVSValue args, void* user_data, IScriptEnvironment* env) { int plane = (int)reinterpret_cast(user_data); - return MinMax(args[0], args[1].AsInt(-1), user_data, args[2].AsDblDef(0.0), args[3].AsInt(0), plane, MIN, env); + return MinMax(args[0].AsInt(-1), args[1], user_data, args[2].AsDblDef(0.0), args[3].AsInt(0), plane, MIN, env); } AVSValue MinMaxPlane::Create_median(AVSValue args, void* user_data, IScriptEnvironment* env) { int plane = (int)reinterpret_cast(user_data); - return MinMax(args[0], args[1].AsInt(-1), user_data, 50.0, args[2].AsInt(0), plane, MIN, env); + return MinMax(args[0].AsInt(-1), args[1], user_data, 50.0, args[2].AsInt(0), plane, MIN, env); } AVSValue MinMaxPlane::Create_minmax(AVSValue args, void* user_data, IScriptEnvironment* env) { int plane = (int)reinterpret_cast(user_data); - return MinMax(args[0], args[1].AsInt(-1), user_data, args[2].AsDblDef(0.0), args[3].AsInt(0), plane, MINMAX_DIFFERENCE, env); + return MinMax(args[0].AsInt(-1), args[1], user_data, args[2].AsDblDef(0.0), args[3].AsInt(0), plane, MINMAX_DIFFERENCE, env); } -AVSValue MinMaxPlane::MinMax(AVSValue clip, int n, void* user_data, double threshold, int offset, int plane, int mode, IScriptEnvironment* env) { +AVSValue MinMaxPlane::MinMax(int n, AVSValue clip, void* user_data, double threshold, int offset, int plane, int mode, IScriptEnvironment* env) { if (!clip.IsClip()) env->ThrowError("MinMax: No clip supplied!"); diff --git a/avs_core/filters/conditional/conditional_functions.h b/avs_core/filters/conditional/conditional_functions.h index 0ff36e269..6bb549a30 100644 --- a/avs_core/filters/conditional/conditional_functions.h +++ b/avs_core/filters/conditional/conditional_functions.h @@ -40,14 +40,14 @@ class AveragePlane { public: static AVSValue Create(AVSValue args, void* user_data, IScriptEnvironment* env); - static AVSValue AvgPlane(AVSValue clip, int n, void* user_data, int plane, int offset, IScriptEnvironment* env); + static AVSValue AvgPlane(int n, AVSValue clip, void* user_data, int plane, int offset, IScriptEnvironment* env); }; class ComparePlane { public: - static AVSValue CmpPlane(AVSValue clip, int n, AVSValue clip2, void* user_data, int plane, IScriptEnvironment* env); - static AVSValue CmpPlaneSame(AVSValue clip, int n, void* user_data, int offset, int plane, IScriptEnvironment* env); + static AVSValue CmpPlane(int n, AVSValue clip, AVSValue clip2, void* user_data, int plane, IScriptEnvironment* env); + static AVSValue CmpPlaneSame(int n, AVSValue clip, void* user_data, int offset, int plane, IScriptEnvironment* env); static AVSValue Create(AVSValue args, void* user_data, IScriptEnvironment* env); static AVSValue Create_prev(AVSValue args, void* user_data, IScriptEnvironment* env); @@ -58,7 +58,7 @@ class ComparePlane { class MinMaxPlane { public: - static AVSValue MinMax(AVSValue clip, int n, void* user_data, double threshold, int offset, int plane, int mode, IScriptEnvironment* env); + static AVSValue MinMax(int n, AVSValue clip, void* user_data, double threshold, int offset, int plane, int mode, IScriptEnvironment* env); static AVSValue Create_max(AVSValue args, void* user_data, IScriptEnvironment* env); static AVSValue Create_min(AVSValue args, void* user_data, IScriptEnvironment* env); From 56682b902d60bbc5088472073ddacc6e90316367 Mon Sep 17 00:00:00 2001 From: Etienne Charland Date: Tue, 25 Apr 2017 22:04:36 -0500 Subject: [PATCH 3/3] Added current_frame function --- avs_core/core/parser/expression.cpp | 31 +++++++++---------- .../conditional/conditional_functions.cpp | 1 + .../conditional/conditional_functions.h | 7 +++++ 3 files changed, 23 insertions(+), 16 deletions(-) diff --git a/avs_core/core/parser/expression.cpp b/avs_core/core/parser/expression.cpp index c6c93a7d8..0d6e0211f 100644 --- a/avs_core/core/parser/expression.cpp +++ b/avs_core/core/parser/expression.cpp @@ -456,27 +456,26 @@ AVSValue ExpVariableReference::Evaluate(IScriptEnvironment* env) // Try various function syntaxes. - // Per-frame syntax - if (frame_number >= 0) - { - // Try function starting with "n,clip". Only per-frame functions start with "ic". - AVSValue sargs[2] = { frame_number }; - const char *nargs[2] = { 0, 0 }; - if (env2->GetVar("last", &sargs[1])) { - if (env2->Invoke(&result, name, AVSValue(sargs, 2), nargs)) - return result; - } - } - - // Regular syntax // look for an argless function if (env2->Invoke(&result, name, AVSValue(0, 0))) return result; - // look for a single-arg function taking implicit "last" AVSValue last; - if (env2->GetVar("last", &last) && env2->Invoke(&result, name, last)) - return result; + if (env2->GetVar("last", &last)) + { + // look for a single-arg function taking implicit "last" + if (env2->Invoke(&result, name, last)) + return result; + + // Per-frame syntax + if (frame_number >= 0) + { + // Try function starting with "n,clip". Only per-frame functions start with "ic". + AVSValue sargs[2] = { frame_number, last }; + if (env2->Invoke(&result, name, AVSValue(sargs, 2))) + return result; + } + } env->ThrowError("I don't know what '%s' means.", name); return 0; diff --git a/avs_core/filters/conditional/conditional_functions.cpp b/avs_core/filters/conditional/conditional_functions.cpp index 0144b5772..f4ec451cb 100644 --- a/avs_core/filters/conditional/conditional_functions.cpp +++ b/avs_core/filters/conditional/conditional_functions.cpp @@ -118,6 +118,7 @@ extern const AVSFunction Conditional_funtions_filters[] = { //{ "HueMedian","ic[offset]i", MinMaxPlane::Create_medianhue }, //{ "HueMinMaxDifference","ic[threshold]f[offset]i", MinMaxPlane::Create_minmaxhue }, + { "current_frame", BUILTIN_FUNC_PREFIX, "ic", CurrentFrame::Create }, { 0 } }; diff --git a/avs_core/filters/conditional/conditional_functions.h b/avs_core/filters/conditional/conditional_functions.h index 6bb549a30..6a4e39f8c 100644 --- a/avs_core/filters/conditional/conditional_functions.h +++ b/avs_core/filters/conditional/conditional_functions.h @@ -69,3 +69,10 @@ class MinMaxPlane { enum { MIN = 1, MAX = 2, MEDIAN = 3, MINMAX_DIFFERENCE = 4 }; }; + +class CurrentFrame { +public: + static AVSValue Create(AVSValue args, void* user_data, IScriptEnvironment* env) { + return AVSValue(args[0].AsInt(-1)); + } +}; \ No newline at end of file