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]"); PExpression exp = parser.Parse(); result = exp->Evaluate(env); if (!result.IsInt()) env->ThrowError("Conditional Select: Expression must return an integer!"); } catch (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); env->MakeWritable(&dst); env->ApplyMessage(&dst, vi, error.msg, vi.width/W_DIVISOR, 0xa0a0a0, 0, 0); return dst; } env->SetVar("last", prev_last); // Restore implicit last env->SetVar("current_frame", prev_current_frame); // Restore current_frame const int i = result.AsInt(); PVideoFrame dst; if (i < 0 || i >= num_args) { const int num_frames = child->GetVideoInfo().num_frames; dst = child->GetFrame(min(num_frames-1, n), env); } else { const int num_frames = child_array[i]->GetVideoInfo().num_frames; dst = child_array[i]->GetFrame(min(num_frames-1, n), env); } if (show) { char text[32]; _snprintf(text, sizeof(text)-1, "Expression Result:%i\n", result.AsInt()); text[sizeof(text)-1] = '\0'; env->MakeWritable(&dst); env->ApplyMessage(&dst, vi, text, vi.width/4, 0xa0a0a0, 0, 0); } return dst; }
PVideoFrame __stdcall ScriptClip::GetFrame(int n, IScriptEnvironment* env) { AVSValue prev_last = env->GetVar("last"); // Store previous last AVSValue prev_current_frame = GetVar(env, "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); ApplyMessage(&dst, vi, script.AsString(), vi.width/6, 0xa0a0a0,0,0 , env ); env->SetVar("last",prev_last); // Restore implicit last env->SetVar("current_frame",prev_current_frame); // Restore current_frame return dst; } AVSValue result; PVideoFrame eval_return; // Frame to be returned if script should be evaluated AFTER frame has been fetched. Otherwise not used. if (eval_after) eval_return = child->GetFrame(n,env); try { ScriptParser parser(env, script.AsString(), "[ScriptClip]"); PExpression exp = parser.Parse(); result = exp->Evaluate(env); } catch (AvisynthError error) { const char* error_msg = error.msg; PVideoFrame dst = child->GetFrame(n,env); env->MakeWritable(&dst); ApplyMessage(&dst, vi, error_msg, vi.width/W_DIVISOR, 0xa0a0a0,0,0 , env ); 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); const char* error = NULL; VideoInfo vi2; if (!result.IsClip()) { error = "ScriptClip: Function did not return a video clip!"; } else { vi2 = result.AsClip()->GetVideoInfo(); if (!vi.IsSameColorspace(vi2)) { error = "ScriptClip: Function did not return a video clip of the same colorspace as the source clip!"; } else if (vi2.width != vi.width) { error = "ScriptClip: Function did not return a video clip with the same width as the source clip!"; } else if (vi2.height != vi.height) { error = "ScriptClip: Function did not return a video clip with the same height as the source clip!"; } } if (error != NULL) { PVideoFrame dst = child->GetFrame(n,env); env->MakeWritable(&dst); ApplyMessage(&dst, vi, error, vi.width/W_DIVISOR, 0xa0a0a0,0,0 , env ); return dst; } n = min(n,vi2.num_frames-1); // We ignore it if the new clip is not as long as the current one. This can allow the resulting clip to be one frame. return result.AsClip()->GetFrame(n,env); }
PVideoFrame __stdcall ConditionalFilter::GetFrame(int n, IScriptEnvironment* env) { VideoInfo vi1 = source1->GetVideoInfo(); VideoInfo vi2 = source2->GetVideoInfo(); AVSValue prev_last = env->GetVar("last"); // Store previous last AVSValue prev_current_frame = GetVar(env, "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]"); PExpression exp = parser.Parse(); e1_result = exp->Evaluate(env); ScriptParser parser2(env, eval2.AsString(), "[Conditional Filter, Expression 2]"); exp = parser2.Parse(); e2_result = exp->Evaluate(env); } catch (AvisynthError error) { const char* error_msg = error.msg; PVideoFrame dst = source1->GetFrame(n,env); env->MakeWritable(&dst); ApplyMessage(&dst, vi1, error_msg, vi.width/W_DIVISOR, 0xa0a0a0,0,0 , env ); 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 int test_int=false; int e1 = 0; int e2 = 0; float f1 = 0.0f; float f2 = 0.0f; try { if (e1_result.IsInt() || e1_result.IsBool()) { test_int = true; e1 = e1_result.IsInt() ? e1_result.AsInt() : e1_result.AsBool(); if (!(e2_result.IsInt() || e2_result.IsBool())) env->ThrowError("Conditional filter: Second expression did not return an integer or bool, as first expression."); e2 = e2_result.IsInt() ? e2_result.AsInt() : e2_result.AsBool(); } else if (e1_result.IsFloat()) { f1 = e1_result.AsFloat(); if (!e2_result.IsFloat()) env->ThrowError("Conditional filter: Second expression did not return a float or an integer, as first expression."); f2 = e2_result.AsFloat(); } else { env->ThrowError("ConditionalFilter: First condition did not return an int, bool or float!"); } } catch (AvisynthError error) { const char* error_msg = error.msg; PVideoFrame dst = source1->GetFrame(n,env); env->MakeWritable(&dst); ApplyMessage(&dst, vi1, error_msg, vi.width/W_DIVISOR, 0xa0a0a0,0,0 , env ); return dst; } bool state = false; if (test_int) { if (evaluator&EQUALS) if (e1 == e2) state = true; if (evaluator&GREATERTHAN) if (e1 > e2) state = true; if (evaluator&LESSTHAN) if (e1 < e2) state = true; } else { // Float compare if (evaluator&EQUALS) if (fabs(f1-f2)<0.000001f) state = true; // Exact equal will sometimes be rounded to wrong values. if (evaluator&GREATERTHAN) if (f1 > f2) state = true; if (evaluator&LESSTHAN) if (f1 < f2) state = true; } if (show) { char text[400]; if (test_int) { sprintf(text, "Left side Conditional Result:%i\n" "Right side Conditional Result:%i\n" "Evaluate result: %s\n", e1, e2, (state) ? t_TRUE : t_FALSE ); } else { sprintf(text, "Left side Conditional Result:%7.4f\n" "Right side Conditional Result:%7.4f\n" "Evaluate result: %s\n", f1, f2, (state) ? t_TRUE : t_FALSE ); } PVideoFrame dst = (state) ? source1->GetFrame(min(vi1.num_frames-1,n),env) : source2->GetFrame(min(vi2.num_frames-1,n),env); env->MakeWritable(&dst); ApplyMessage(&dst, vi, text, vi.width/4, 0xa0a0a0,0,0 , env ); return dst; } if (state) return source1->GetFrame(min(vi1.num_frames-1,n),env); return source2->GetFrame(min(vi1.num_frames-1,n),env); }