GCC Code Coverage Report


Directory: avs_core/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 58.8% 20 / 0 / 34
Functions: 100.0% 2 / 0 / 2
Branches: 13.9% 10 / 0 / 72

core/FilterConstructor.cpp
Line Branch Exec Source
1 #include "FilterConstructor.h"
2 #include "avisynth.h"
3
4 7 FilterConstructor::FilterConstructor(IScriptEnvironment2 * env,
5 IScriptEnvironment_Avs25* env25,
6 IScriptEnvironment_AvsPreV11C* envPreV11C,
7 7 const Function *func, std::vector<AVSValue>* argStorage, std::vector<AVSValue>* ctorArgs) :
8 7 Env(env),
9 7 Env25(env25),
10 7 EnvPreV11C(envPreV11C),
11 7 Func(func),
12 #if 1
13 14 ArgStorage(std::move(*argStorage)),
14 14 CtorArgs(std::move(*ctorArgs))
15 #else
16 // no need to move, subarrays could not be returned
17 ArgStorage(*argStorage),
18 CtorArgs(*ctorArgs)
19 #endif
20 {
21 7 }
22
23
24 7 AVSValue FilterConstructor::InstantiateFilter() const
25 {
26 // funcArgs is passed to the function as an array.
27 // Calls the plugin's instance creator, which is usually Filter_Create(AVSValue args, void *user_data, IScriptEnvironment *env)
28 // or create_c_filter
29
1/2
✓ Branch 2 → 3 taken 7 times.
✗ Branch 2 → 107 not taken.
7 AVSValue funcArgs;
30
31 // isPluginAvs25 and isPluginPreV11C cannot accept long and double types in
32 // their parameters passed to them.
33 // Such plugins don't recognize 'l' and 'd' 64-bit types due to direct type field checks in AVSValue/AVS_Value.
34 // IsInt/avs_is_int and IsFloat/avs_is_float check the type field directly in the old header, without an interface call.
35 // New avisynth_c.h supports these types, but old plugins don't.
36 // Thus we convert 64-bit types in the parameter list to 32-bit ones.
37
2/4
✓ Branch 3 → 4 taken 7 times.
✗ Branch 3 → 5 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 46 taken 7 times.
7 if (Func->isPluginAvs25 || Func->isPluginPreV11C) {
38 std::vector<AVSValue> funcArgs_temp(CtorArgs.size(), AVSValue());
39 for (auto i = 0; i < (int)CtorArgs.size(); i++) {
40 if (CtorArgs[i].GetType() == AvsValueType::VALUE_TYPE_LONG) // long int64 -> 32 bit int
41 funcArgs_temp[i] = CtorArgs[i].AsInt();
42 else if (CtorArgs[i].GetType() == AvsValueType::VALUE_TYPE_DOUBLE) // double -> float
43 funcArgs_temp[i] = CtorArgs[i].AsFloatf();
44 else
45 funcArgs_temp[i] = CtorArgs[i];
46 }
47 funcArgs = AVSValue(funcArgs_temp.data(), (int)funcArgs_temp.size());
48 }
49 else {
50
2/4
✓ Branch 48 → 49 taken 7 times.
✗ Branch 48 → 98 not taken.
✓ Branch 49 → 50 taken 7 times.
✗ Branch 49 → 96 not taken.
7 funcArgs = AVSValue(CtorArgs.data(), (int)CtorArgs.size());
51 }
52
53
1/2
✓ Branch 57 → 58 taken 7 times.
✗ Branch 57 → 101 not taken.
14 AVSValue retval = Func->apply(funcArgs, Func->user_data,
54 7 Func->isPluginAvs25 ? (IScriptEnvironment *)Env25 :
55
1/2
✗ Branch 54 → 55 not taken.
✓ Branch 54 → 56 taken 7 times.
7 Func->isPluginPreV11C ? (IScriptEnvironment*)EnvPreV11C :
56
2/4
✗ Branch 52 → 53 not taken.
✓ Branch 52 → 54 taken 7 times.
✓ Branch 58 → 59 taken 7 times.
✗ Branch 58 → 99 not taken.
21 Env);
57 // pass back proper ScriptEnvironment, because a 2.5 plugin e.g. GRunT can back-Invoke ScriptClip
58
1/2
✗ Branch 60 → 61 not taken.
✓ Branch 60 → 75 taken 7 times.
7 if (Func->isPluginAvs25)
59 {
60 // After instantiate a v2.5 "baked code" function,
61 // manually release Clips or else clip variables get stuck in memory on exit
62 if (funcArgs.IsArray())
63 {
64 for (int i = 0; i < funcArgs.ArraySize(); i++)
65 {
66 if (funcArgs[i].IsClip()) {
67 IClip* rawClip = (IClip*)(void*)funcArgs[i].AsClip(); // de-smart pointering
68 rawClip->Release();
69 }
70 }
71 }
72 // Problem: AVS 2.5 plugins have "baked code", their interface contains direct manipulation, refcount, free of AVSValue resources.
73 // So they do not know about array deep copy and deep free mechanism.
74 // Thus array sub-elements of the parameter AVSValue won't be freed up on exiting of such functions.
75 // Example: CtorArgs contains clip(s) with reference count N
76 // Upon creating funcArgs the "smart" array creation will copy the subarray as well.
77 // Because of the deep copy the reference count of these PClip values are increased by 1.
78 // Then funcArgs will be passed to the CPP 2.5 function which won't release the Array content, only destroys the
79 // 'holder' array-typed AVSValue, array elements will be untouched.
80 // So if there is a PClip parameters the Clip's reference count remains N+1, causing memory leak.
81 // This is why we have to release them manually, deferencing the Clip by one, instead of the plugin's code.
82 // If this reference count decrease is not done then env->DeleteScriptEnvironment will not free up everything.
83 // ScriptEnvironment destroy is freeing up variables as well.
84 // If a variable contains such a clip (e.g. "last"), it will fail to be released, because such Clip will not reached refcount==0.
85 // e.g. VirtualDub consecutively press "script reload"s. Memory will leak even 50-80Mbytes so after a while
86 // memory gets full.
87 }
88 7 return retval;
89 7 }
90