GCC Code Coverage Report


Directory: avs_core/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 45.0% 245 / 0 / 545
Functions: 90.0% 9 / 0 / 10
Branches: 19.5% 383 / 0 / 1967

filters/overlay/overlay.cpp
Line Branch Exec Source
1 // Avisynth v2.5. Copyright 2002 Ben Rudiak-Gould et al.
2 // http://avisynth.nl
3
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 2 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA, or visit
17 // http://www.gnu.org/copyleft/gpl.html .
18 //
19 // Linking Avisynth statically or dynamically with other modules is making a
20 // combined work based on Avisynth. Thus, the terms and conditions of the GNU
21 // General Public License cover the whole combination.
22 //
23 // As a special exception, the copyright holders of Avisynth give you
24 // permission to link Avisynth with independent modules that communicate with
25 // Avisynth solely through the interfaces defined in avisynth.h, regardless of the license
26 // terms of these independent modules, and to copy and distribute the
27 // resulting combined work under terms of your choice, provided that
28 // every copy of the combined work is accompanied by a complete copy of
29 // the source code of Avisynth (the version of Avisynth used to produce the
30 // combined work), being distributed under the terms of the GNU General
31 // Public License plus this exception. An independent module is a module
32 // which is not derived from or based on Avisynth, such as 3rd-party filters,
33 // import and export plugins, or graphical user interfaces.
34
35 // Overlay (c) 2003, 2004 by Klaus Post
36 #include <avisynth.h>
37 #ifdef AVS_WINDOWS
38 #include <avs/win.h>
39 #else
40 #include <avs/posix.h>
41 #endif
42
43 #include <stdlib.h>
44 #include "overlay.h"
45 #include <string>
46 #include "../core/internal.h"
47
48 /********************************************************************
49 ***** Declare index of new filters for Avisynth's filter engine *****
50 ********************************************************************/
51
52 49 static int getPlacement(const AVSValue& _placement, IScriptEnvironment* env) {
53 49 const char* placement = _placement.AsString(0);
54
1/2
✓ Branch 3 → 4 taken 49 times.
✗ Branch 3 → 11 not taken.
49 if (placement) {
55
1/2
✓ Branch 4 → 5 taken 49 times.
✗ Branch 4 → 6 not taken.
49 if (!lstrcmpi(placement, "mpeg2"))
56 49 return PLACEMENT_MPEG2;
57 if (!lstrcmpi(placement, "mpeg1"))
58 return PLACEMENT_MPEG1;
59 if (!lstrcmpi(placement, "top_left"))
60 return PLACEMENT_TOPLEFT;
61 env->ThrowError("Overlay: Unknown chroma placement");
62 }
63 return PLACEMENT_MPEG2;
64 }
65
66 extern const AVSFunction Overlay_filters[] = {
67 { "Overlay", BUILTIN_FUNC_PREFIX, "cc[x]i[y]i[mask]c[opacity]f[mode]s[greymask]b[output]s[ignore_conditional]b[PC_Range]b[use444]b[condvarsuffix]s[placement]s", Overlay::Create },
68 // 0, src clip
69 // 1, overlay clip
70 // 2, x
71 // 3, y
72 // 4, mask clip
73 // 5, overlay opacity.(0.0->1.0)
74 // 6, mode string, "blend", "add"
75 // 7, greymask bool - true = only use luma information for mask
76 // 8, output type, string
77 // 9, ignore conditional variabels
78 // 10, full YUV range.
79 // 11, ignore 4:4:4 conversion
80 // 12, conditional variable suffix AVS+
81 // 13, chroma placement "mpeg2" (default) or "mpeg1"
82 { 0 }
83 };
84
85 enum {
86 ARG_SRC = 0,
87 ARG_OVERLAY = 1,
88 ARG_X = 2,
89 ARG_Y = 3,
90 ARG_MASK = 4,
91 ARG_OPACITY = 5,
92 ARG_MODE = 6,
93 ARG_GREYMASK = 7,
94 ARG_OUTPUT = 8,
95 ARG_IGNORE_CONDITIONAL = 9,
96 ARG_FULL_RANGE = 10,
97 ARG_USE444 = 11, // 170103 possible conversionless option experimental
98 ARG_CONDVARSUFFIX = 12, // 190408
99 ARG_PLACEMENT = 13
100 };
101
102 30 static int getPixelTypeWithoutAlpha(VideoInfo& vi)
103 {
104
2/2
✓ Branch 3 → 4 taken 2 times.
✓ Branch 3 → 5 taken 28 times.
30 return (vi.IsYUVA() ? (vi.pixel_type & ~VideoInfo::CS_YUVA) | VideoInfo::CS_YUV :
105
1/2
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 28 times.
30 (vi.IsPlanarRGBA() ? (vi.pixel_type & ~VideoInfo::CS_RGBA_TYPE) | VideoInfo::CS_RGB_TYPE : vi.pixel_type));
106 }
107
108 49 Overlay::Overlay(PClip _child, AVSValue args, IScriptEnvironment *env) :
109
5/10
✓ Branch 2 → 3 taken 49 times.
✗ Branch 2 → 694 not taken.
✓ Branch 3 → 4 taken 49 times.
✗ Branch 3 → 692 not taken.
✓ Branch 5 → 6 taken 49 times.
✗ Branch 5 → 1108 not taken.
✓ Branch 6 → 7 taken 49 times.
✗ Branch 6 → 1106 not taken.
✓ Branch 7 → 8 taken 49 times.
✗ Branch 7 → 1104 not taken.
49 GenericVideoFilter(_child), child444(nullptr) {
110
111 // child here is always planar: no packed RGB or YUY2 allowed
112
113
2/4
✓ Branch 8 → 9 taken 49 times.
✗ Branch 8 → 1102 not taken.
✓ Branch 9 → 10 taken 49 times.
✗ Branch 9 → 1102 not taken.
49 full_range = args[ARG_FULL_RANGE].AsBool(false); // Maintain CCIR601 range when converting to/from RGB.
114
2/4
✓ Branch 10 → 11 taken 49 times.
✗ Branch 10 → 1102 not taken.
✓ Branch 11 → 12 taken 49 times.
✗ Branch 11 → 1102 not taken.
49 bool use444_defined = args[ARG_USE444].Defined();
115
2/4
✓ Branch 12 → 13 taken 49 times.
✗ Branch 12 → 1102 not taken.
✓ Branch 13 → 14 taken 49 times.
✗ Branch 13 → 1102 not taken.
49 use444 = args[ARG_USE444].AsBool(true); // avs+ option to use 444-conversionless mode
116
2/4
✓ Branch 14 → 15 taken 49 times.
✗ Branch 14 → 1102 not taken.
✓ Branch 15 → 16 taken 49 times.
✗ Branch 15 → 1102 not taken.
49 name = args[ARG_MODE].AsString("Blend");
117
2/4
✓ Branch 16 → 17 taken 49 times.
✗ Branch 16 → 1102 not taken.
✓ Branch 17 → 18 taken 49 times.
✗ Branch 17 → 1102 not taken.
49 condVarSuffix = args[ARG_CONDVARSUFFIX].AsString("");
118
2/4
✓ Branch 18 → 19 taken 49 times.
✗ Branch 18 → 1102 not taken.
✓ Branch 19 → 20 taken 49 times.
✗ Branch 19 → 1102 not taken.
49 placement = getPlacement(args[ARG_PLACEMENT], env);
119
120 // Make copy of the VideoInfo
121 49 inputVi = vi;
122 // by default outputVi is the same as inputVi
123 49 outputVi = vi;
124 49 viInternalWorkingFormat = vi;
125
126
2/4
✓ Branch 20 → 21 taken 49 times.
✗ Branch 20 → 1102 not taken.
✓ Branch 21 → 22 taken 49 times.
✗ Branch 21 → 1102 not taken.
49 opacity_f = (float)args[ARG_OPACITY].AsDblDef(1.0); // for float support
127 49 opacity = (int)(256.0*opacity_f + 0.5); // range is converted to 256 for all all bit_depth
128
2/4
✓ Branch 22 → 23 taken 49 times.
✗ Branch 22 → 1102 not taken.
✓ Branch 23 → 24 taken 49 times.
✗ Branch 23 → 1102 not taken.
49 offset_x = args[ARG_X].AsInt(0);
129
2/4
✓ Branch 24 → 25 taken 49 times.
✗ Branch 24 → 1102 not taken.
✓ Branch 25 → 26 taken 49 times.
✗ Branch 25 → 1102 not taken.
49 offset_y = args[ARG_Y].AsInt(0);
130
131
3/6
✓ Branch 26 → 27 taken 49 times.
✗ Branch 26 → 1102 not taken.
✓ Branch 27 → 28 taken 49 times.
✗ Branch 27 → 1102 not taken.
✗ Branch 28 → 29 not taken.
✓ Branch 28 → 30 taken 49 times.
49 if (!args[ARG_OVERLAY].IsClip())
132 env->ThrowError("Overlay: Overlay parameter is not a clip");
133
134
3/6
✓ Branch 30 → 31 taken 49 times.
✗ Branch 30 → 697 not taken.
✓ Branch 31 → 32 taken 49 times.
✗ Branch 31 → 697 not taken.
✓ Branch 32 → 33 taken 49 times.
✗ Branch 32 → 695 not taken.
49 overlay = args[ARG_OVERLAY].AsClip();
135
136
1/2
✓ Branch 35 → 36 taken 49 times.
✗ Branch 35 → 1102 not taken.
49 overlayVi = overlay->GetVideoInfo();
137 // overlay clip to always planar
138
6/10
✓ Branch 36 → 37 taken 49 times.
✗ Branch 36 → 1102 not taken.
✓ Branch 37 → 38 taken 8 times.
✓ Branch 37 → 41 taken 41 times.
✓ Branch 38 → 39 taken 8 times.
✗ Branch 38 → 1102 not taken.
✗ Branch 39 → 40 not taken.
✓ Branch 39 → 41 taken 8 times.
✗ Branch 42 → 43 not taken.
✓ Branch 42 → 76 taken 49 times.
49 if (overlayVi.IsRGB() && !overlayVi.IsPlanar()) {
139 // no packed RGB allowed from now on, autoconvert from packed
140 AVSValue new_args[1] = { overlay };
141 if (overlayVi.IsRGB24() || overlayVi.IsRGB48())
142 overlay = env->Invoke("ConvertToPlanarRGB", AVSValue(new_args, 1)).AsClip();
143 else
144 overlay = env->Invoke("ConvertToPlanarRGBA", AVSValue(new_args, 1)).AsClip();
145 overlayVi = overlay->GetVideoInfo();
146 }
147
2/4
✓ Branch 76 → 77 taken 49 times.
✗ Branch 76 → 1102 not taken.
✗ Branch 77 → 78 not taken.
✓ Branch 77 → 96 taken 49 times.
49 else if (overlayVi.IsYUY2()) {
148 // convert YUY2 to 422, keep internals simple
149 AVSValue new_args[2] = { overlay, false };
150 overlay = env->Invoke("ConvertToYUV422", AVSValue(new_args, 2)).AsClip();
151 overlayVi = overlay->GetVideoInfo();
152 }
153
154
1/2
✓ Branch 96 → 97 taken 49 times.
✗ Branch 96 → 1102 not taken.
49 SetOfModeByName(name, env); // setting of_mode, checks valid mode strings as well
155
156 49 viInternalOverlayWorkingFormat = overlayVi;
157
158
2/4
✓ Branch 97 → 98 taken 49 times.
✗ Branch 97 → 1102 not taken.
✓ Branch 98 → 99 taken 49 times.
✗ Branch 98 → 1102 not taken.
49 greymask = args[ARG_GREYMASK].AsBool(true); // Grey mask, default true
159
2/4
✓ Branch 99 → 100 taken 49 times.
✗ Branch 99 → 1102 not taken.
✓ Branch 100 → 101 taken 49 times.
✗ Branch 100 → 1102 not taken.
49 ignore_conditional = args[ARG_IGNORE_CONDITIONAL].AsBool(false); // Don't ignore conditionals by default
160
161
1/2
✓ Branch 101 → 102 taken 49 times.
✗ Branch 101 → 1102 not taken.
49 mask = nullptr;
162
4/6
✓ Branch 102 → 103 taken 49 times.
✗ Branch 102 → 1102 not taken.
✓ Branch 103 → 104 taken 49 times.
✗ Branch 103 → 1102 not taken.
✓ Branch 104 → 105 taken 15 times.
✓ Branch 104 → 119 taken 34 times.
49 if (args[ARG_MASK].Defined()) { // Mask defined
163
3/6
✓ Branch 105 → 106 taken 15 times.
✗ Branch 105 → 753 not taken.
✓ Branch 106 → 107 taken 15 times.
✗ Branch 106 → 753 not taken.
✓ Branch 107 → 108 taken 15 times.
✗ Branch 107 → 751 not taken.
15 mask = args[ARG_MASK].AsClip();
164
1/2
✓ Branch 110 → 111 taken 15 times.
✗ Branch 110 → 1102 not taken.
15 maskVi = mask->GetVideoInfo();
165
1/2
✗ Branch 111 → 112 not taken.
✓ Branch 111 → 113 taken 15 times.
15 if (maskVi.width!=overlayVi.width) {
166 env->ThrowError("Overlay: Mask and overlay must have the same image size! (Width is not the same)");
167 }
168
1/2
✗ Branch 113 → 114 not taken.
✓ Branch 113 → 115 taken 15 times.
15 if (maskVi.height!=overlayVi.height) {
169 env->ThrowError("Overlay: Mask and overlay must have the same image size! (Height is not the same)");
170 }
171
3/6
✓ Branch 115 → 116 taken 15 times.
✗ Branch 115 → 1102 not taken.
✓ Branch 116 → 117 taken 15 times.
✗ Branch 116 → 1102 not taken.
✗ Branch 117 → 118 not taken.
✓ Branch 117 → 119 taken 15 times.
15 if (maskVi.BitsPerComponent() != overlayVi.BitsPerComponent()) {
172 env->ThrowError("Overlay: Mask and overlay must have the same bit depths!");
173 }
174 }
175
176
1/2
✓ Branch 119 → 120 taken 49 times.
✗ Branch 119 → 1102 not taken.
49 pixelsize = vi.ComponentSize();
177
1/2
✓ Branch 120 → 121 taken 49 times.
✗ Branch 120 → 1102 not taken.
49 bits_per_pixel = vi.BitsPerComponent();
178
179
2/4
✓ Branch 121 → 122 taken 49 times.
✗ Branch 121 → 1102 not taken.
✗ Branch 122 → 123 not taken.
✓ Branch 122 → 124 taken 49 times.
49 if (bits_per_pixel != overlayVi.BitsPerComponent()) {
180 env->ThrowError("Overlay: input and overlay clip must have the same bit depths!");
181 }
182
183 // already filled vi = child->GetVideoInfo();
184 // parse and check output format override vi
185
2/4
✓ Branch 124 → 125 taken 49 times.
✗ Branch 124 → 1102 not taken.
✓ Branch 125 → 126 taken 49 times.
✗ Branch 125 → 1102 not taken.
49 output_pixel_format_override = args[ARG_OUTPUT].AsString(nullptr);
186
1/2
✗ Branch 126 → 127 not taken.
✓ Branch 126 → 134 taken 49 times.
49 if(output_pixel_format_override) {
187 int output_pixel_type = GetPixelTypeFromName(output_pixel_format_override);
188 if(output_pixel_type == VideoInfo::CS_UNKNOWN)
189 env->ThrowError("Overlay: invalid pixel_type!");
190
191 outputVi.pixel_type = output_pixel_type; // override output pixel format
192 if(outputVi.BitsPerComponent() != inputVi.BitsPerComponent())
193 env->ThrowError("Overlay: output bitdepth should be the same as input's!");
194 }
195
196
2/2
✓ Branch 134 → 135 taken 8 times.
✓ Branch 134 → 141 taken 41 times.
49 if (bits_per_pixel == 32) {
197
3/6
✓ Branch 135 → 136 taken 8 times.
✗ Branch 135 → 141 not taken.
✓ Branch 136 → 137 taken 8 times.
✗ Branch 136 → 141 not taken.
✓ Branch 137 → 138 taken 8 times.
✗ Branch 137 → 141 not taken.
8 if (_stricmp(name, "Blend") != 0 && _stricmp(name, "Luma") != 0 && _stricmp(name, "Chroma") != 0
198
3/4
✓ Branch 138 → 139 taken 4 times.
✓ Branch 138 → 141 taken 4 times.
✗ Branch 139 → 140 not taken.
✓ Branch 139 → 141 taken 4 times.
8 && _stricmp(name, "Add") != 0 && _stricmp(name, "Subtract") != 0) {
199 env->ThrowError("Overlay: only Blend, Luma, Chroma, Add and Subtract modes are supported for 32-bit float video");
200 }
201 }
202
203
3/4
✓ Branch 141 → 142 taken 49 times.
✗ Branch 141 → 1102 not taken.
✓ Branch 142 → 143 taken 29 times.
✓ Branch 142 → 144 taken 20 times.
49 if (vi.Is444())
204 29 use444 = true; // 444 is conversionless by default
205
206 // let use444=false to go live for subfilters that are ready to use it
207 // except: RGB must be converted to 444 for Luma and Chroma operation
208
6/10
✓ Branch 144 → 145 taken 49 times.
✗ Branch 144 → 1102 not taken.
✓ Branch 145 → 146 taken 8 times.
✓ Branch 145 → 149 taken 41 times.
✓ Branch 146 → 147 taken 8 times.
✗ Branch 146 → 148 not taken.
✗ Branch 147 → 148 not taken.
✓ Branch 147 → 149 taken 8 times.
✗ Branch 150 → 151 not taken.
✓ Branch 150 → 155 taken 49 times.
49 if (vi.IsRGB() && (_stricmp(name, "Luma") == 0 || _stricmp(name, "Chroma") == 0)) {
209 if (use444_defined && !use444) {
210 env->ThrowError("Overlay: for RGB you cannot specify use444=false for overlay mode: %s", name);
211 }
212 use444 = true;
213 }
214 98 else if (!use444_defined &&
215
2/20
✗ Branch 155 → 156 not taken.
✓ Branch 155 → 168 taken 49 times.
✗ Branch 156 → 157 not taken.
✗ Branch 156 → 1102 not taken.
✗ Branch 157 → 158 not taken.
✗ Branch 157 → 164 not taken.
✗ Branch 158 → 159 not taken.
✗ Branch 158 → 1102 not taken.
✗ Branch 159 → 160 not taken.
✗ Branch 159 → 164 not taken.
✗ Branch 160 → 161 not taken.
✗ Branch 160 → 1102 not taken.
✗ Branch 161 → 162 not taken.
✗ Branch 161 → 164 not taken.
✗ Branch 162 → 163 not taken.
✗ Branch 162 → 1102 not taken.
✗ Branch 163 → 164 not taken.
✗ Branch 163 → 168 not taken.
✗ Branch 169 → 170 not taken.
✓ Branch 169 → 171 taken 49 times.
49 (vi.IsY() || vi.Is420() || vi.Is422() || vi.IsRGB()) &&
216 (_stricmp(name, "Blend") == 0 || _stricmp(name, "Luma") == 0 || _stricmp(name, "Chroma") == 0))
217 {
218 use444 = false; // default false for modes capable handling of use444==false, and valid formats
219 }
220 98 else if (!use444_defined &&
221
2/8
✗ Branch 171 → 172 not taken.
✓ Branch 171 → 177 taken 49 times.
✗ Branch 172 → 173 not taken.
✗ Branch 172 → 1102 not taken.
✗ Branch 173 → 174 not taken.
✗ Branch 173 → 177 not taken.
✗ Branch 178 → 179 not taken.
✓ Branch 178 → 180 taken 49 times.
49 (vi.IsRGB()) &&
222 (_stricmp(name, "Add") == 0 || _stricmp(name, "Subtract") == 0))
223 {
224 use444 = false; // native RGB support for Add/Subtract
225 }
226
227
2/2
✓ Branch 180 → 181 taken 14 times.
✓ Branch 180 → 204 taken 35 times.
49 if (!use444) {
228 // check if we can work in conversionless mode
229 // 1.) colorspace is greyscale, 4:2:0 or 4:2:2 or any RGB
230 // 2.) mode is "blend-like" (at the moment)
231
11/18
✓ Branch 181 → 182 taken 14 times.
✗ Branch 181 → 1102 not taken.
✓ Branch 182 → 183 taken 14 times.
✗ Branch 182 → 190 not taken.
✓ Branch 183 → 184 taken 14 times.
✗ Branch 183 → 1102 not taken.
✓ Branch 184 → 185 taken 10 times.
✓ Branch 184 → 190 taken 4 times.
✓ Branch 185 → 186 taken 10 times.
✗ Branch 185 → 1102 not taken.
✓ Branch 186 → 187 taken 8 times.
✓ Branch 186 → 190 taken 2 times.
✓ Branch 187 → 188 taken 8 times.
✗ Branch 187 → 1102 not taken.
✗ Branch 188 → 189 not taken.
✓ Branch 188 → 190 taken 8 times.
✗ Branch 191 → 192 not taken.
✓ Branch 191 → 193 taken 14 times.
14 if (!vi.IsY() && !vi.Is420() && !vi.Is422() && !vi.IsRGB())
232 env->ThrowError("Overlay: use444=false is allowed only for greyscale, 4:2:0, 4:2:2 or any RGB video formats");
233 //if (output_pixel_format_override && outputVi->pixel_type != vi.pixel_type)
234 // env->ThrowError("Overlay: use444=false is allowed only when no output pixel format is specified");
235
2/4
✓ Branch 194 → 195 taken 8 times.
✗ Branch 194 → 201 not taken.
✓ Branch 195 → 196 taken 8 times.
✗ Branch 195 → 201 not taken.
8 if (_stricmp(name, "Blend") != 0 && _stricmp(name, "Luma") != 0 && _stricmp(name, "Chroma") != 0 &&
236
6/12
✓ Branch 193 → 194 taken 8 times.
✓ Branch 193 → 201 taken 6 times.
✓ Branch 196 → 197 taken 4 times.
✓ Branch 196 → 201 taken 4 times.
✗ Branch 197 → 198 not taken.
✓ Branch 197 → 201 taken 4 times.
✗ Branch 198 → 199 not taken.
✗ Branch 198 → 1102 not taken.
✗ Branch 199 → 200 not taken.
✗ Branch 199 → 201 not taken.
✗ Branch 202 → 203 not taken.
✓ Branch 202 → 204 taken 14 times.
22 (_stricmp(name, "Add") != 0 && _stricmp(name, "Subtract") != 0) && !vi.IsRGB())
237 env->ThrowError("Overlay: cannot specify use444=false for this overlay mode: %s", name);
238 }
239
240
5/8
✓ Branch 204 → 205 taken 49 times.
✗ Branch 204 → 1102 not taken.
✓ Branch 205 → 206 taken 45 times.
✓ Branch 205 → 208 taken 4 times.
✓ Branch 206 → 207 taken 45 times.
✗ Branch 206 → 1102 not taken.
✗ Branch 207 → 208 not taken.
✓ Branch 207 → 209 taken 45 times.
49 bool hasAlpha = vi.IsYUVA() || vi.IsPlanarRGBA();
241
242 // set internal working format
243
2/2
✓ Branch 210 → 211 taken 35 times.
✓ Branch 210 → 237 taken 14 times.
49 if (use444) {
244 // we convert everything to 4:4:4
245 // fill yuv 444 template
246
2/7
✓ Branch 211 → 212 taken 31 times.
✗ Branch 211 → 216 not taken.
✗ Branch 211 → 220 not taken.
✗ Branch 211 → 224 not taken.
✗ Branch 211 → 228 not taken.
✓ Branch 211 → 232 taken 4 times.
✗ Branch 211 → 236 not taken.
35 switch (bits_per_pixel) {
247
2/2
✓ Branch 212 → 213 taken 2 times.
✓ Branch 212 → 214 taken 29 times.
31 case 8: viInternalWorkingFormat.pixel_type = hasAlpha ? VideoInfo::CS_YUVA444 : VideoInfo::CS_YV24; break;
248 case 10: viInternalWorkingFormat.pixel_type = hasAlpha ? VideoInfo::CS_YUVA444P10 : VideoInfo::CS_YUV444P10; break;
249 case 12: viInternalWorkingFormat.pixel_type = hasAlpha ? VideoInfo::CS_YUVA444P12 : VideoInfo::CS_YUV444P12; break;
250 case 14: viInternalWorkingFormat.pixel_type = hasAlpha ? VideoInfo::CS_YUVA444P14 : VideoInfo::CS_YUV444P14; break;
251 case 16: viInternalWorkingFormat.pixel_type = hasAlpha ? VideoInfo::CS_YUVA444P16 : VideoInfo::CS_YUV444P16; break;
252
1/2
✗ Branch 232 → 233 not taken.
✓ Branch 232 → 234 taken 4 times.
4 case 32: viInternalWorkingFormat.pixel_type = hasAlpha ? VideoInfo::CS_YUVA444PS : VideoInfo::CS_YUV444PS; break;
253 }
254 }
255 else {
256 // keep input format for internal format. Always 4:2:0, 4:2:2 (or 4:4:4 / Planar RGB)
257 // filters have to prepare to work for these formats
258 14 viInternalWorkingFormat = vi;
259 }
260
261 49 viInternalOverlayWorkingFormat.pixel_type = viInternalWorkingFormat.pixel_type;
262
263 // Set GetFrame's real output format
264
7/8
✓ Branch 238 → 239 taken 49 times.
✗ Branch 238 → 1102 not taken.
✓ Branch 239 → 240 taken 8 times.
✓ Branch 239 → 242 taken 41 times.
✓ Branch 240 → 241 taken 4 times.
✓ Branch 240 → 242 taken 4 times.
✓ Branch 243 → 244 taken 4 times.
✓ Branch 243 → 270 taken 45 times.
49 if (outputVi.Is420() && use444)
265 {
266 // on-the-fly fast conversion at the end of GetFrame
267
1/7
✓ Branch 244 → 245 taken 4 times.
✗ Branch 244 → 249 not taken.
✗ Branch 244 → 253 not taken.
✗ Branch 244 → 257 not taken.
✗ Branch 244 → 261 not taken.
✗ Branch 244 → 265 not taken.
✗ Branch 244 → 269 not taken.
4 switch (bits_per_pixel) {
268
2/2
✓ Branch 245 → 246 taken 2 times.
✓ Branch 245 → 247 taken 2 times.
4 case 8: vi.pixel_type = hasAlpha ? VideoInfo::CS_YUVA420 : VideoInfo::CS_YV12; break;
269 case 10: vi.pixel_type = hasAlpha ? VideoInfo::CS_YUVA420P10 : VideoInfo::CS_YUV420P10; break;
270 case 12: vi.pixel_type = hasAlpha ? VideoInfo::CS_YUVA420P12 : VideoInfo::CS_YUV420P12; break;
271 case 14: vi.pixel_type = hasAlpha ? VideoInfo::CS_YUVA420P14 : VideoInfo::CS_YUV420P14; break;
272 case 16: vi.pixel_type = hasAlpha ? VideoInfo::CS_YUVA420P16 : VideoInfo::CS_YUV420P16; break;
273 case 32: vi.pixel_type = hasAlpha ? VideoInfo::CS_YUVA420PS : VideoInfo::CS_YUV420PS; break;
274 }
275 }
276
7/8
✓ Branch 270 → 271 taken 45 times.
✗ Branch 270 → 1102 not taken.
✓ Branch 271 → 272 taken 4 times.
✓ Branch 271 → 274 taken 41 times.
✓ Branch 272 → 273 taken 2 times.
✓ Branch 272 → 274 taken 2 times.
✓ Branch 275 → 276 taken 2 times.
✓ Branch 275 → 302 taken 43 times.
45 else if (outputVi.Is422() && use444)
277 {
278 // on-the-fly fast conversion at the end of GetFrame
279
1/7
✓ Branch 276 → 277 taken 2 times.
✗ Branch 276 → 281 not taken.
✗ Branch 276 → 285 not taken.
✗ Branch 276 → 289 not taken.
✗ Branch 276 → 293 not taken.
✗ Branch 276 → 297 not taken.
✗ Branch 276 → 301 not taken.
2 switch (bits_per_pixel) {
280
1/2
✗ Branch 277 → 278 not taken.
✓ Branch 277 → 279 taken 2 times.
2 case 8: vi.pixel_type = hasAlpha ? VideoInfo::CS_YUVA422 : VideoInfo::CS_YV16; break;
281 case 10: vi.pixel_type = hasAlpha ? VideoInfo::CS_YUVA422P10 : VideoInfo::CS_YUV422P10; break;
282 case 12: vi.pixel_type = hasAlpha ? VideoInfo::CS_YUVA422P12 : VideoInfo::CS_YUV422P12; break;
283 case 14: vi.pixel_type = hasAlpha ? VideoInfo::CS_YUVA422P14 : VideoInfo::CS_YUV422P14; break;
284 case 16: vi.pixel_type = hasAlpha ? VideoInfo::CS_YUVA422P16 : VideoInfo::CS_YUV422P16; break;
285 case 32: vi.pixel_type = hasAlpha ? VideoInfo::CS_YUVA422PS : VideoInfo::CS_YUV422PS; break;
286 }
287 }
288
2/4
✓ Branch 302 → 303 taken 43 times.
✗ Branch 302 → 1102 not taken.
✗ Branch 303 → 304 not taken.
✓ Branch 303 → 305 taken 43 times.
43 else if (outputVi.IsYUY2())
289 {
290 // on-the-fly fast conversion at the end of GetFrame
291 vi.pixel_type = VideoInfo::CS_YUY2;
292 } else {
293 43 vi.pixel_type = viInternalWorkingFormat.pixel_type;
294 // Y,420,422,444,PlanarRGB (and packed RGB converted to any intermediate)
295 }
296
297 // internal working formats:
298 // - subsampled planar: 420, 422
299 // - full info: 444, planarRGB(A)
300 // - full info 1 plane: greyscale
301
1/2
✓ Branch 306 → 307 taken 49 times.
✗ Branch 306 → 1102 not taken.
49 isInternalRGB = viInternalWorkingFormat.IsRGB(); // must be planar rgb
302
1/2
✓ Branch 307 → 308 taken 49 times.
✗ Branch 307 → 1102 not taken.
49 isInternalGrey = viInternalWorkingFormat.IsY();
303
1/2
✓ Branch 308 → 309 taken 49 times.
✗ Branch 308 → 1102 not taken.
49 isInternal444 = viInternalWorkingFormat.Is444();
304
1/2
✓ Branch 309 → 310 taken 49 times.
✗ Branch 309 → 1102 not taken.
49 isInternal422 = viInternalWorkingFormat.Is422();
305
1/2
✓ Branch 310 → 311 taken 49 times.
✗ Branch 310 → 1102 not taken.
49 isInternal420 = viInternalWorkingFormat.Is420();
306
307 #if 0
308 // FIXME but left here: When this one is here and not in GetFrame, it's much slower.
309 // base clip conversion to internal 444 working format
310 if (inputVi.pixel_type != viInternalWorkingFormat.pixel_type &&
311 isInternal444)
312 {
313 // these two has special quick conversion in GetFrame
314 if (!inputVi.Is420() && !inputVi.Is422()) {
315 // convert input to 444
316 if (inputVi.IsRGB()) {
317 AVSValue new_args[3] = { child, false, full_range ? "PC.601" : "rec601" }; // clip, interlaced, matrix
318 child444 = env->Invoke("ConvertToYUV444", AVSValue(new_args, 3)).AsClip();
319 }
320 else {
321 // Y, 411?
322 AVSValue new_args[2] = { child, false };
323 child444 = env->Invoke("ConvertToYUV444", AVSValue(new_args, 2)).AsClip();
324 }
325 }
326 }
327 #endif
328 // more format match of overlay
329
3/4
✓ Branch 311 → 312 taken 49 times.
✗ Branch 311 → 1102 not taken.
✓ Branch 312 → 313 taken 8 times.
✓ Branch 312 → 358 taken 41 times.
49 if (overlayVi.IsRGB()) {
330
1/2
✗ Branch 313 → 314 not taken.
✓ Branch 313 → 335 taken 8 times.
8 if (isInternalGrey) {
331 AVSValue new_args[2] = { overlay, full_range ? "PC.601" : "rec601" };
332 overlay = env->Invoke("ConvertToY", AVSValue(new_args, 2)).AsClip();
333 overlayVi = overlay->GetVideoInfo();
334 }
335
1/2
✗ Branch 335 → 336 not taken.
✓ Branch 335 → 358 taken 8 times.
8 else if (!isInternalRGB) {
336 AVSValue new_args[3] = { overlay, false, full_range ? "PC.601" : "rec601" };
337 overlay = env->Invoke("ConvertToYUV444", AVSValue(new_args, 3)).AsClip();
338 overlayVi = overlay->GetVideoInfo();
339 }
340 }
341
2/2
✓ Branch 358 → 359 taken 35 times.
✓ Branch 358 → 386 taken 14 times.
49 if (isInternal444) {
342 // 420 and 422 has quick internal conversion in GetFrame, leave them, along with 444.
343
9/14
✓ Branch 359 → 360 taken 35 times.
✗ Branch 359 → 1102 not taken.
✓ Branch 360 → 361 taken 6 times.
✓ Branch 360 → 366 taken 29 times.
✓ Branch 361 → 362 taken 6 times.
✗ Branch 361 → 1102 not taken.
✓ Branch 362 → 363 taken 2 times.
✓ Branch 362 → 366 taken 4 times.
✓ Branch 363 → 364 taken 2 times.
✗ Branch 363 → 1102 not taken.
✗ Branch 364 → 365 not taken.
✓ Branch 364 → 366 taken 2 times.
✗ Branch 367 → 368 not taken.
✓ Branch 367 → 469 taken 35 times.
35 if (!overlayVi.Is444() && !overlayVi.Is420() && !overlayVi.Is422()) {
344 // 411, Y
345 // params: clip, interlaced
346 AVSValue new_args[2] = { overlay, false };
347 overlay = env->Invoke("ConvertToYUV444", AVSValue(new_args, 2)).AsClip();
348 overlayVi = overlay->GetVideoInfo();
349 }
350 }
351
2/2
✓ Branch 386 → 387 taken 8 times.
✓ Branch 386 → 427 taken 6 times.
14 else if (isInternalRGB) {
352
3/10
✓ Branch 387 → 388 taken 8 times.
✗ Branch 387 → 1102 not taken.
✗ Branch 388 → 389 not taken.
✓ Branch 388 → 392 taken 8 times.
✗ Branch 389 → 390 not taken.
✗ Branch 389 → 1102 not taken.
✗ Branch 390 → 391 not taken.
✗ Branch 390 → 392 not taken.
✗ Branch 393 → 394 not taken.
✓ Branch 393 → 469 taken 8 times.
8 if (!overlayVi.IsPlanarRGB() && !overlayVi.IsPlanarRGBA()) {
353 AVSValue new_args[3] = { overlay, full_range ? "PC.601" : "rec601", false};
354 if (overlayVi.IsYUVA())
355 overlay = env->Invoke("ConvertToPlanarRGBA", AVSValue(new_args, 3)).AsClip();
356 else
357 overlay = env->Invoke("ConvertToPlanarRGB", AVSValue(new_args, 3)).AsClip();
358 overlayVi = overlay->GetVideoInfo();
359 }
360 }
361
2/2
✓ Branch 427 → 428 taken 4 times.
✓ Branch 427 → 448 taken 2 times.
6 else if (isInternal420) {
362
2/4
✓ Branch 428 → 429 taken 4 times.
✗ Branch 428 → 1102 not taken.
✗ Branch 429 → 430 not taken.
✓ Branch 429 → 469 taken 4 times.
4 if (!overlayVi.Is420()) {
363 // convert to 444. Quick conversion further in GetFrame
364 AVSValue new_args[2] = { overlay, false };
365 overlay = env->Invoke("ConvertToYUV444", AVSValue(new_args, 2)).AsClip();
366 overlayVi = overlay->GetVideoInfo();
367 }
368 }
369
1/2
✓ Branch 448 → 449 taken 2 times.
✗ Branch 448 → 469 not taken.
2 else if (isInternal422) {
370
2/4
✓ Branch 449 → 450 taken 2 times.
✗ Branch 449 → 1102 not taken.
✗ Branch 450 → 451 not taken.
✓ Branch 450 → 469 taken 2 times.
2 if (!overlayVi.Is422()) {
371 // convert to 444. Quick conversion further in GetFrame
372 AVSValue new_args[2] = { overlay, false };
373 overlay = env->Invoke("ConvertToYUV444", AVSValue(new_args, 2)).AsClip();
374 overlayVi = overlay->GetVideoInfo();
375 }
376 }
377
378
2/2
✓ Branch 470 → 471 taken 15 times.
✓ Branch 470 → 691 taken 34 times.
49 if (mask) {
379
4/8
✓ Branch 471 → 472 taken 15 times.
✗ Branch 471 → 1102 not taken.
✓ Branch 472 → 473 taken 15 times.
✗ Branch 472 → 474 not taken.
✗ Branch 473 → 474 not taken.
✓ Branch 473 → 475 taken 15 times.
✗ Branch 476 → 477 not taken.
✓ Branch 476 → 478 taken 15 times.
15 if (maskVi.IsY() || isInternalGrey)
380 greymask = true;
381
382 // mask to always planar
383
3/10
✓ Branch 478 → 479 taken 15 times.
✗ Branch 478 → 1102 not taken.
✗ Branch 479 → 480 not taken.
✓ Branch 479 → 483 taken 15 times.
✗ Branch 480 → 481 not taken.
✗ Branch 480 → 1102 not taken.
✗ Branch 481 → 482 not taken.
✗ Branch 481 → 483 not taken.
✗ Branch 484 → 485 not taken.
✓ Branch 484 → 518 taken 15 times.
15 if (maskVi.IsRGB() && !maskVi.IsPlanar()) {
384 // no packed RGB mask allowed from now on, autoconvert from packed
385 AVSValue new_args[1] = { mask };
386 if (maskVi.IsRGB24() || maskVi.IsRGB48())
387 mask = env->Invoke("ConvertToPlanarRGB", AVSValue(new_args, 1)).AsClip();
388 else
389 mask = env->Invoke("ConvertToPlanarRGBA", AVSValue(new_args, 1)).AsClip();
390 maskVi = mask->GetVideoInfo();
391 }
392
2/4
✓ Branch 518 → 519 taken 15 times.
✗ Branch 518 → 1102 not taken.
✗ Branch 519 → 520 not taken.
✓ Branch 519 → 538 taken 15 times.
15 else if (maskVi.IsYUY2()) {
393 // convert YUY2 mask to 422, keep internals simple
394 AVSValue new_args[2] = { mask, false };
395 mask = env->Invoke("ConvertToYUV422", AVSValue(new_args, 2)).AsClip();
396 maskVi = mask->GetVideoInfo();
397 }
398
399
2/4
✓ Branch 538 → 539 taken 15 times.
✗ Branch 538 → 1102 not taken.
✗ Branch 539 → 540 not taken.
✓ Branch 539 → 581 taken 15 times.
15 if (maskVi.IsRGB()) {
400 if (greymask) {
401 // Compatibility: ExtractB. See notes above.
402 // This is good, because in the old times rgb32clip.ShowAlpha() was
403 // used for feeding mask to overlay, that spreads alpha to all channels, so classic avisynth chose
404 // B channel for source. (=R=G)
405 // So we are not using greyscale conversion here at mask for compatibility reasons
406 // Still: recommended usage for mask: rgbclip.ExtractA()
407 /*
408 AVSValue new_args[2] = { mask, (full_range) ? "PC.601" : "rec601" };
409 mask2 = env->Invoke("ConvertToY", AVSValue(new_args, 2)).AsClip();
410 */
411 AVSValue new_args[1] = { mask };
412 mask = env->Invoke("ExtractB", AVSValue(new_args, 1)).AsClip();
413 maskVi = mask->GetVideoInfo();
414 }
415 else {
416 if (!isInternalRGB) {
417 AVSValue new_args[3] = { mask, false, full_range ? "PC.601" : "rec601" };
418 mask = env->Invoke("ConvertToYUV444", AVSValue(new_args, 3)).AsClip();
419 maskVi = mask->GetVideoInfo();
420 }
421 }
422 } // RGB mask cases end
423
424
4/6
✓ Branch 581 → 582 taken 15 times.
✗ Branch 581 → 1102 not taken.
✓ Branch 582 → 583 taken 15 times.
✗ Branch 582 → 1102 not taken.
✓ Branch 583 → 584 taken 3 times.
✓ Branch 583 → 691 taken 12 times.
15 if (getPixelTypeWithoutAlpha(maskVi) != getPixelTypeWithoutAlpha(viInternalWorkingFormat))
425 {
426
2/4
✓ Branch 584 → 585 taken 3 times.
✗ Branch 584 → 1102 not taken.
✓ Branch 585 → 586 taken 3 times.
✗ Branch 585 → 688 not taken.
3 if (!maskVi.IsRGB()) {
427
1/2
✗ Branch 586 → 587 not taken.
✓ Branch 586 → 608 taken 3 times.
3 if (isInternalRGB) {
428 if (!greymask) {
429 // mask clip was not RGB, but our internal format is.
430 // convert from any (Y, YUV) mask format to planar RGB
431 AVSValue new_args[3] = { mask, full_range ? "PC.601" : "rec601", false };
432 mask = env->Invoke("ConvertToPlanarRGB", AVSValue(new_args, 3)).AsClip();
433 }
434 }
435 else {
436
1/2
✓ Branch 608 → 609 taken 3 times.
✗ Branch 608 → 624 not taken.
3 if (greymask) {
437
1/6
✓ Branch 609 → 610 taken 3 times.
✗ Branch 609 → 1014 not taken.
✗ Branch 1014 → 1015 not taken.
✗ Branch 1014 → 1018 not taken.
✗ Branch 1016 → 1017 not taken.
✗ Branch 1016 → 1018 not taken.
6 AVSValue new_args[1] = { mask }; // mask is not rgb here, no matrix param
438
4/8
✓ Branch 610 → 611 taken 3 times.
✗ Branch 610 → 1025 not taken.
✓ Branch 611 → 612 taken 3 times.
✗ Branch 611 → 1023 not taken.
✓ Branch 612 → 613 taken 3 times.
✗ Branch 612 → 1021 not taken.
✓ Branch 613 → 614 taken 3 times.
✗ Branch 613 → 1019 not taken.
3 mask = env->Invoke("ConvertToY", AVSValue(new_args, 1)).AsClip();
439
2/4
✓ Branch 618 → 619 taken 3 times.
✓ Branch 618 → 622 taken 3 times.
✗ Branch 1029 → 1030 not taken.
✗ Branch 1029 → 1033 not taken.
6 }
440 else {
441 if (isInternal420) {
442 if (!maskVi.Is420()) {
443 AVSValue new_args[2] = { mask, false };
444 mask = env->Invoke("ConvertToYUV444", AVSValue(new_args, 2)).AsClip();
445 // quick internal 444->420 conversion later in GetFrame
446 }
447 }
448 else if (isInternal422) {
449 if (!maskVi.Is422()) {
450 AVSValue new_args[2] = { mask, false };
451 mask = env->Invoke("ConvertToYUV444", AVSValue(new_args, 2)).AsClip();
452 // quick internal 444->422 conversion later in GetFrame
453 }
454 }
455 else if (isInternal444 && (maskVi.Is420() || maskVi.Is422() || maskVi.Is444())) {
456 // do nothing, quick ->444 conversion inside GetFrame
457 }
458 else {
459 // all other !greymask cases to 444
460 AVSValue new_args[2] = { mask, false };
461 mask = env->Invoke("ConvertToYUV444", AVSValue(new_args, 2)).AsClip();
462 }
463 }
464 }
465 }
466
1/2
✓ Branch 689 → 690 taken 3 times.
✗ Branch 689 → 1102 not taken.
3 maskVi = mask->GetVideoInfo();
467 }
468 }
469 49 }
470
471
472 49 Overlay::~Overlay() {
473 49 }
474
475 47 PVideoFrame __stdcall Overlay::GetFrame(int n, IScriptEnvironment *env) {
476 // fixme: do all necessary conversions in filter creation, not in GetFrame!
477 // 20251122: tried but for some reason it's slower!
478 int op_offset;
479 float op_offset_f;
480 int con_x_offset;
481 int con_y_offset;
482
1/2
✓ Branch 2 → 3 taken 47 times.
✗ Branch 2 → 597 not taken.
47 FetchConditionals(env, &op_offset, &op_offset_f, &con_x_offset, &con_y_offset, ignore_conditional, condVarSuffix);
483
484
1/2
✓ Branch 3 → 4 taken 47 times.
✗ Branch 3 → 597 not taken.
47 AVSValue child2;
485
1/2
✓ Branch 4 → 5 taken 47 times.
✗ Branch 4 → 595 not taken.
47 PVideoFrame frame;
486
487
2/2
✓ Branch 5 → 6 taken 41 times.
✓ Branch 5 → 11 taken 6 times.
47 if (inputVi.pixel_type == viInternalWorkingFormat.pixel_type)
488 {
489 // get frame as is.
490 // includes 420, 422, 444, planarRGB(A)
491
2/4
✓ Branch 7 → 8 taken 41 times.
✗ Branch 7 → 419 not taken.
✓ Branch 8 → 9 taken 41 times.
✗ Branch 8 → 417 not taken.
41 frame = child->GetFrame(n, env);
492 }
493
1/2
✓ Branch 11 → 12 taken 6 times.
✗ Branch 11 → 86 not taken.
6 else if (isInternal444) {
494
3/4
✓ Branch 12 → 13 taken 6 times.
✗ Branch 12 → 593 not taken.
✓ Branch 13 → 14 taken 4 times.
✓ Branch 13 → 22 taken 2 times.
6 if (inputVi.Is420()) {
495 // use blazing fast YV12 -> YV24 converter, not exact chroma placement though
496
1/2
✓ Branch 15 → 16 taken 4 times.
✗ Branch 15 → 425 not taken.
4 PVideoFrame Inframe = child->GetFrame(n, env);
497
2/4
✓ Branch 16 → 17 taken 4 times.
✗ Branch 16 → 422 not taken.
✓ Branch 17 → 18 taken 4 times.
✗ Branch 17 → 420 not taken.
4 frame = env->NewVideoFrameP(viInternalWorkingFormat, &Inframe);
498 // no fancy options for chroma resampler, etc.. simply fast
499
1/2
✓ Branch 19 → 20 taken 4 times.
✗ Branch 19 → 423 not taken.
4 Convert444FromYV12(Inframe, frame, pixelsize, bits_per_pixel, env);
500 4 }
501
2/4
✓ Branch 22 → 23 taken 2 times.
✗ Branch 22 → 593 not taken.
✓ Branch 23 → 24 taken 2 times.
✗ Branch 23 → 32 not taken.
2 else if (inputVi.Is422()) {
502 // use blazing fast YV16 -> YV24 converter, not exact chroma placement though
503
1/2
✓ Branch 25 → 26 taken 2 times.
✗ Branch 25 → 431 not taken.
2 PVideoFrame Inframe = child->GetFrame(n, env);
504
2/4
✓ Branch 26 → 27 taken 2 times.
✗ Branch 26 → 428 not taken.
✓ Branch 27 → 28 taken 2 times.
✗ Branch 27 → 426 not taken.
2 frame = env->NewVideoFrameP(viInternalWorkingFormat, &Inframe);
505
1/2
✓ Branch 29 → 30 taken 2 times.
✗ Branch 29 → 429 not taken.
2 Convert444FromYV16(Inframe, frame, pixelsize, bits_per_pixel, env);
506 2 }
507 #if 1
508 // FIXME but left here: When this one is NOT here in GetFrame, but in ctor, it's much slower.
509 else if (inputVi.IsRGB()) {
510 AVSValue new_args[3] = { child, false, full_range ? "PC.601" : "rec601" };
511 child2 = env->Invoke("ConvertToYUV444", AVSValue(new_args, 3)).AsClip();
512 frame = child2.AsClip()->GetFrame(n, env);
513 }
514 else {
515 AVSValue new_args[2] = { child, false };
516 child2 = env->Invoke("ConvertToYUV444", AVSValue(new_args, 2)).AsClip();
517 frame = child2.AsClip()->GetFrame(n, env);
518 }
519 #else
520 else {
521 frame = child444->GetFrame(n, env);
522 // from non 420/422 such as RGB, the conversion happened already in constructor
523 // (FIXME note: slower)
524 }
525 #endif
526 }
527 else if (isInternalRGB) {
528 if(inputVi.IsYUV()) {
529 // Just for the sake of completeness.
530 // when input is YUV, internal working format is never RGB
531 env->ThrowError("Overlay: internal error; isInternalRGB but input is YUV");
532 }
533 }
534
535 // Fetch current frame and convert it to internal format
536
1/2
✓ Branch 90 → 91 taken 47 times.
✗ Branch 90 → 593 not taken.
47 env->MakeWritable(&frame);
537
538
10/20
✓ Branch 91 → 92 taken 47 times.
✗ Branch 91 → 593 not taken.
✓ Branch 93 → 94 taken 47 times.
✗ Branch 93 → 494 not taken.
✓ Branch 94 → 95 taken 47 times.
✗ Branch 94 → 494 not taken.
✓ Branch 95 → 96 taken 43 times.
✓ Branch 95 → 100 taken 4 times.
✓ Branch 97 → 98 taken 43 times.
✗ Branch 97 → 494 not taken.
✓ Branch 98 → 99 taken 43 times.
✗ Branch 98 → 494 not taken.
✗ Branch 99 → 100 not taken.
✓ Branch 99 → 101 taken 43 times.
✓ Branch 102 → 103 taken 47 times.
✗ Branch 102 → 494 not taken.
✗ Branch 103 → 104 not taken.
✓ Branch 103 → 105 taken 47 times.
✗ Branch 494 → 495 not taken.
✗ Branch 494 → 496 not taken.
47 ImageOverlayInternal* img = new ImageOverlayInternal(frame, vi.width, vi.height, viInternalWorkingFormat, child->GetVideoInfo().IsYUVA() || child->GetVideoInfo().IsPlanarRGBA(), false, env);
539
540
1/2
✓ Branch 105 → 106 taken 47 times.
✗ Branch 105 → 593 not taken.
47 PVideoFrame Oframe;
541
1/2
✓ Branch 106 → 107 taken 47 times.
✗ Branch 106 → 591 not taken.
47 AVSValue overlay2;
542
543
1/2
✓ Branch 107 → 108 taken 47 times.
✗ Branch 107 → 589 not taken.
47 PVideoFrame Mframe;
544 47 ImageOverlayInternal* maskImg = NULL;
545
546 // overlay clip should be converted to internal format if different, except for internal Y,
547 // for which original planar YUV is OK
548
2/2
✓ Branch 108 → 109 taken 41 times.
✓ Branch 108 → 114 taken 6 times.
47 if(overlayVi.pixel_type == viInternalWorkingFormat.pixel_type)
549 {
550 // don't convert is input and overlay is the same formats
551 // so we can work in YUV420 or YUV422 and Planar RGB directly besides YUV444 (use444==false)
552
2/4
✓ Branch 110 → 111 taken 41 times.
✗ Branch 110 → 499 not taken.
✓ Branch 111 → 112 taken 41 times.
✗ Branch 111 → 497 not taken.
41 Oframe = overlay->GetFrame(n, env);
553 }
554
1/2
✓ Branch 114 → 115 taken 6 times.
✗ Branch 114 → 149 not taken.
6 else if (isInternal444) {
555
1/2
✗ Branch 115 → 116 not taken.
✓ Branch 115 → 121 taken 6 times.
6 if (of_mode == OF_Multiply)
556 {
557 // 'multiply' is always using only Y from overlay clip, no need to match chroma
558 Oframe = overlay->GetFrame(n, env);
559 }
560
3/4
✓ Branch 121 → 122 taken 6 times.
✗ Branch 121 → 587 not taken.
✓ Branch 122 → 123 taken 4 times.
✓ Branch 122 → 131 taken 2 times.
6 else if (overlayVi.Is420()) {
561 // use blazing fast YV12 -> YV24 converter. Note: not exact chroma placement
562
1/2
✓ Branch 124 → 125 taken 4 times.
✗ Branch 124 → 508 not taken.
4 PVideoFrame frame = overlay->GetFrame(n, env);
563
2/4
✓ Branch 125 → 126 taken 4 times.
✗ Branch 125 → 505 not taken.
✓ Branch 126 → 127 taken 4 times.
✗ Branch 126 → 503 not taken.
4 Oframe = env->NewVideoFrameP(viInternalOverlayWorkingFormat, &frame);
564 // no fancy options for chroma resampler, etc.. simply fast
565
1/2
✓ Branch 128 → 129 taken 4 times.
✗ Branch 128 → 506 not taken.
4 Convert444FromYV12(frame, Oframe, pixelsize, bits_per_pixel, env);
566 4 }
567
2/4
✓ Branch 131 → 132 taken 2 times.
✗ Branch 131 → 587 not taken.
✓ Branch 132 → 133 taken 2 times.
✗ Branch 132 → 141 not taken.
2 else if (overlayVi.Is422()) {
568 // use blazing fast YV16 -> YV24 converter
569
1/2
✓ Branch 134 → 135 taken 2 times.
✗ Branch 134 → 514 not taken.
2 PVideoFrame frame = overlay->GetFrame(n, env);
570
2/4
✓ Branch 135 → 136 taken 2 times.
✗ Branch 135 → 511 not taken.
✓ Branch 136 → 137 taken 2 times.
✗ Branch 136 → 509 not taken.
2 Oframe = env->NewVideoFrameP(viInternalOverlayWorkingFormat, &frame);
571
1/2
✓ Branch 138 → 139 taken 2 times.
✗ Branch 138 → 512 not taken.
2 Convert444FromYV16(frame, Oframe, pixelsize, bits_per_pixel, env);
572 2 }
573 else {
574 if (!overlayVi.Is444())
575 env->ThrowError("Overlay: internal error, wrong internal overlayVi format for internal 444, must be 420,422 or 444");
576 Oframe = overlay->GetFrame(n, env);
577 }
578 }
579 else if(isInternalGrey) {
580 if (!overlayVi.IsY() && !overlayVi.IsYUV() && !overlayVi.IsYUVA())
581 env->ThrowError("Overlay: internal error, overlayVi must be Y or YUV(A) for internalGrey");
582 // they are good as-is, we'll use only Y
583 Oframe = overlay->GetFrame(n, env);
584 }
585 else if (isInternalRGB) {
586 if (!overlayVi.IsPlanarRGB() && !overlayVi.IsPlanarRGBA())
587 env->ThrowError("Overlay: internal error, overlayVi must be planar RGB(A) for internalRGB");
588 Oframe = overlay->GetFrame(n, env);
589 }
590 else if (isInternal420) {
591 if (overlayVi.Is420()) {
592 Oframe = overlay->GetFrame(n, env);
593 }
594 else if (overlayVi.Is444()) {
595 PVideoFrame frame = overlay->GetFrame(n, env);
596 Oframe = env->NewVideoFrameP(viInternalOverlayWorkingFormat, &frame);
597 // no fancy options for chroma resampler, etc.. simply fast
598 Convert444ToYV12(frame, Oframe, pixelsize, bits_per_pixel, env);
599 }
600 else {
601 env->ThrowError("Overlay: internal error, overlayVi must be 420 or 444 for internal420");
602 }
603 }
604 else if (isInternal422) {
605 if (overlayVi.Is422()) {
606 Oframe = overlay->GetFrame(n, env);
607 }
608 else if(overlayVi.Is444()) {
609 PVideoFrame frame = overlay->GetFrame(n, env);
610 Oframe = env->NewVideoFrameP(viInternalOverlayWorkingFormat, &frame);
611 // no fancy options for chroma resampler, etc.. simply fast
612 Convert444ToYV16(frame, Oframe, pixelsize, bits_per_pixel, env);
613 }
614 else {
615 env->ThrowError("Overlay: internal error, overlayVi must be 422 or 444 for internal420");
616 }
617 }
618 // Fetch current overlay and convert it to internal format
619 47 VideoInfo actual_viInternalOverlayWorkingFormat = viInternalOverlayWorkingFormat;
620
1/2
✗ Branch 217 → 218 not taken.
✓ Branch 217 → 226 taken 47 times.
47 if (of_mode == OF_Multiply) {
621 // this mode does not need chroma for Overlay
622 switch (bits_per_pixel) {
623 case 8: actual_viInternalOverlayWorkingFormat.pixel_type = VideoInfo::CS_Y8; break;
624 case 10: actual_viInternalOverlayWorkingFormat.pixel_type = VideoInfo::CS_Y10; break;
625 case 12: actual_viInternalOverlayWorkingFormat.pixel_type = VideoInfo::CS_Y12; break;
626 case 14: actual_viInternalOverlayWorkingFormat.pixel_type = VideoInfo::CS_Y14; break;
627 case 16: actual_viInternalOverlayWorkingFormat.pixel_type = VideoInfo::CS_Y16; break;
628 case 32: actual_viInternalOverlayWorkingFormat.pixel_type = VideoInfo::CS_Y32; break;
629 }
630 }
631
632
10/20
✓ Branch 226 → 227 taken 47 times.
✗ Branch 226 → 587 not taken.
✓ Branch 228 → 229 taken 47 times.
✗ Branch 228 → 542 not taken.
✓ Branch 229 → 230 taken 47 times.
✗ Branch 229 → 542 not taken.
✓ Branch 230 → 231 taken 43 times.
✓ Branch 230 → 235 taken 4 times.
✓ Branch 232 → 233 taken 43 times.
✗ Branch 232 → 542 not taken.
✓ Branch 233 → 234 taken 43 times.
✗ Branch 233 → 542 not taken.
✗ Branch 234 → 235 not taken.
✓ Branch 234 → 236 taken 43 times.
✓ Branch 237 → 238 taken 47 times.
✗ Branch 237 → 542 not taken.
✗ Branch 238 → 239 not taken.
✓ Branch 238 → 240 taken 47 times.
✗ Branch 542 → 543 not taken.
✗ Branch 542 → 544 not taken.
47 ImageOverlayInternal* overlayImg = new ImageOverlayInternal(Oframe, overlayVi.width, overlayVi.height, actual_viInternalOverlayWorkingFormat, overlay->GetVideoInfo().IsYUVA() || overlay->GetVideoInfo().IsPlanarRGBA(), false, env);
633
634 // Clip overlay to original image
635
1/2
✓ Branch 240 → 241 taken 47 times.
✗ Branch 240 → 587 not taken.
47 ClipFrames(img, overlayImg, offset_x + con_x_offset, offset_y + con_y_offset);
636
637
1/2
✓ Branch 242 → 243 taken 47 times.
✗ Branch 242 → 371 not taken.
47 if (overlayImg->IsSizeZero()) { // Nothing to overlay
638 }
639 else {
640 // fetch current mask (if given)
641
2/2
✓ Branch 244 → 245 taken 15 times.
✓ Branch 244 → 350 taken 32 times.
47 if (mask) {
642
643
1/2
✓ Branch 245 → 246 taken 15 times.
✗ Branch 245 → 580 not taken.
15 AVSValue mask2;
644
3/8
✓ Branch 246 → 247 taken 15 times.
✗ Branch 246 → 578 not taken.
✗ Branch 247 → 248 not taken.
✓ Branch 247 → 250 taken 15 times.
✗ Branch 248 → 249 not taken.
✗ Branch 248 → 250 not taken.
✗ Branch 251 → 252 not taken.
✓ Branch 251 → 253 taken 15 times.
15 if(maskVi.IsRGB() && greymask)
645 env->ThrowError("Overlay: Internal error, this mask cannot be RGB here, it should be Y or 444 by now.");
646
3/8
✓ Branch 253 → 254 taken 15 times.
✗ Branch 253 → 578 not taken.
✗ Branch 254 → 255 not taken.
✓ Branch 254 → 257 taken 15 times.
✗ Branch 255 → 256 not taken.
✗ Branch 255 → 257 not taken.
✗ Branch 258 → 259 not taken.
✓ Branch 258 → 260 taken 15 times.
15 if (maskVi.IsRGB() && isInternal444)
647 env->ThrowError("Overlay: Internal error, this mask cannot be RGB here, it should be 444 by now.");
648
2/10
✗ Branch 260 → 261 not taken.
✓ Branch 260 → 265 taken 15 times.
✗ Branch 261 → 262 not taken.
✗ Branch 261 → 265 not taken.
✗ Branch 262 → 263 not taken.
✗ Branch 262 → 578 not taken.
✗ Branch 263 → 264 not taken.
✗ Branch 263 → 265 not taken.
✗ Branch 266 → 267 not taken.
✓ Branch 266 → 268 taken 15 times.
15 if (!greymask && isInternalRGB && !maskVi.IsRGB())
649 env->ThrowError("Overlay: Internal error, this mask must be RGB here if greymask==false and isInternalRGB.");
650
651 30 if (greymask
652 || getPixelTypeWithoutAlpha(maskVi) == getPixelTypeWithoutAlpha(viInternalWorkingFormat)
653
2/8
✗ Branch 268 → 269 not taken.
✓ Branch 268 → 274 taken 15 times.
✗ Branch 272 → 273 not taken.
✗ Branch 272 → 275 not taken.
✗ Branch 273 → 274 not taken.
✗ Branch 273 → 275 not taken.
✓ Branch 276 → 277 taken 15 times.
✗ Branch 276 → 282 not taken.
15 || (!greymask && isInternalRGB)
654 )
655 {
656 // 4:4:4,
657 // 4:2:0, 4:2:2 -> greymask uses Y
658 // internalworking format: 4:4:4, 4:2:2, 4:2:0
659
2/4
✓ Branch 278 → 279 taken 15 times.
✗ Branch 278 → 547 not taken.
✓ Branch 279 → 280 taken 15 times.
✗ Branch 279 → 545 not taken.
15 Mframe = mask->GetFrame(n, env);
660 }
661 else if (isInternal444 || greymask) {
662 if (maskVi.Is420()) {
663 // use blazing fast YV12 -> YV24 converter
664 PVideoFrame frame = mask->GetFrame(n, env);
665 Mframe = env->NewVideoFrameP(viInternalOverlayWorkingFormat, &frame);
666 // no fancy options for chroma resampler, etc.. simply fast
667 Convert444FromYV12(frame, Mframe, pixelsize, bits_per_pixel, env);
668 // convert frameSrc420 -> frame
669 }
670 else if (maskVi.Is422()) {
671 // use blazing fast YV16 -> YV24 converter
672 PVideoFrame frame = mask->GetFrame(n, env);
673 Mframe = env->NewVideoFrameP(viInternalOverlayWorkingFormat, &frame);
674 Convert444FromYV16(frame, Mframe, pixelsize, bits_per_pixel, env);
675 }
676 else
677 env->ThrowError("Overlay: internal error, maskVi is not 420 or 422 here");
678 }
679 else {
680 // greymask == false
681 if (isInternal420) {
682 // mask is 444 here
683 PVideoFrame frame = mask->GetFrame(n, env);
684 Mframe = env->NewVideoFrameP(viInternalOverlayWorkingFormat, &frame);
685 // no fancy options for chroma resampler, etc.. simply fast
686 Convert444ToYV12(frame, Mframe, pixelsize, bits_per_pixel, env);
687 }
688 else if (isInternal422) {
689 // mask is 444 here
690 PVideoFrame frame = mask->GetFrame(n, env);
691 Mframe = env->NewVideoFrameP(viInternalOverlayWorkingFormat, &frame);
692 // no fancy options for chroma resampler, etc.. simply fast
693 Convert444ToYV16(frame, Mframe, pixelsize, bits_per_pixel, env);
694 }
695 else {
696 if (!maskVi.Is444())
697 env->ThrowError("Overlay: internal error, maskVi must be 444 here in greymask==false");
698 Mframe = mask->GetFrame(n, env);;
699 }
700 }
701 // MFrame here is either internalWorkingFormat or Y or 4:4:4
702
9/20
✓ Branch 332 → 333 taken 15 times.
✗ Branch 332 → 578 not taken.
✓ Branch 334 → 335 taken 15 times.
✗ Branch 334 → 575 not taken.
✓ Branch 335 → 336 taken 15 times.
✗ Branch 335 → 575 not taken.
✓ Branch 336 → 337 taken 15 times.
✗ Branch 336 → 341 not taken.
✓ Branch 338 → 339 taken 15 times.
✗ Branch 338 → 575 not taken.
✓ Branch 339 → 340 taken 15 times.
✗ Branch 339 → 575 not taken.
✗ Branch 340 → 341 not taken.
✓ Branch 340 → 342 taken 15 times.
✓ Branch 343 → 344 taken 15 times.
✗ Branch 343 → 575 not taken.
✗ Branch 344 → 345 not taken.
✓ Branch 344 → 346 taken 15 times.
✗ Branch 575 → 576 not taken.
✗ Branch 575 → 577 not taken.
15 maskImg = new ImageOverlayInternal(Mframe, maskVi.width, maskVi.height, viInternalOverlayWorkingFormat, mask->GetVideoInfo().IsYUVA() || mask->GetVideoInfo().IsPlanarRGBA(), greymask, env);
703
704 15 img->ReturnOriginal(true);
705
1/2
✓ Branch 347 → 348 taken 15 times.
✗ Branch 347 → 578 not taken.
15 ClipFrames(img, maskImg, offset_x + con_x_offset, offset_y + con_y_offset);
706
707
708 15 }
709
710
1/2
✓ Branch 350 → 351 taken 47 times.
✗ Branch 350 → 587 not taken.
47 OverlayFunction* func = SelectFunction();
711
712 // Process the image
713 47 func->setMode(of_mode);
714 47 func->setBitsPerPixel(bits_per_pixel);
715
1/2
✓ Branch 353 → 354 taken 47 times.
✗ Branch 353 → 587 not taken.
47 func->setOpacity(opacity + op_offset, opacity_f + op_offset_f);
716
2/4
✓ Branch 354 → 355 taken 47 times.
✗ Branch 354 → 587 not taken.
✓ Branch 355 → 356 taken 47 times.
✗ Branch 355 → 587 not taken.
47 func->setColorSpaceInfo(viInternalWorkingFormat.IsRGB(), viInternalWorkingFormat.IsY());
717 47 func->setSubsamplingInfo(viInternalWorkingFormat, placement);
718 47 func->setGreyMask(greymask);
719 47 func->setEnv(env);
720
721
2/2
✓ Branch 361 → 362 taken 32 times.
✓ Branch 361 → 363 taken 15 times.
47 if (!mask) {
722
1/2
✓ Branch 362 → 364 taken 32 times.
✗ Branch 362 → 587 not taken.
32 func->DoBlendImage(img, overlayImg);
723 } else {
724
1/2
✓ Branch 363 → 364 taken 15 times.
✗ Branch 363 → 587 not taken.
15 func->DoBlendImageMask(img, overlayImg, maskImg);
725 }
726
727
1/2
✓ Branch 364 → 365 taken 47 times.
✗ Branch 364 → 366 not taken.
47 delete func;
728
729 // Reset overlay & image offsets
730 47 img->ReturnOriginal(true);
731 47 overlayImg->ReturnOriginal(true);
732
2/2
✓ Branch 369 → 370 taken 15 times.
✓ Branch 369 → 371 taken 32 times.
47 if (mask)
733 15 maskImg->ReturnOriginal(true);
734 }
735
736 // Cleanup
737
2/2
✓ Branch 372 → 373 taken 15 times.
✓ Branch 372 → 376 taken 32 times.
47 if (mask) {
738
1/2
✓ Branch 373 → 374 taken 15 times.
✗ Branch 373 → 376 not taken.
15 delete maskImg;
739 }
740
1/2
✓ Branch 376 → 377 taken 47 times.
✗ Branch 376 → 379 not taken.
47 delete overlayImg;
741
1/2
✓ Branch 379 → 380 taken 47 times.
✗ Branch 379 → 383 not taken.
47 if (img) {
742
1/2
✓ Branch 380 → 381 taken 47 times.
✗ Branch 380 → 383 not taken.
47 delete img;
743 }
744
745 // here img->frame is 444
746 // apply fast conversion
747
8/10
✓ Branch 383 → 384 taken 47 times.
✗ Branch 383 → 587 not taken.
✓ Branch 384 → 385 taken 8 times.
✓ Branch 384 → 388 taken 39 times.
✓ Branch 385 → 386 taken 8 times.
✗ Branch 385 → 587 not taken.
✓ Branch 386 → 387 taken 4 times.
✓ Branch 386 → 388 taken 4 times.
✓ Branch 389 → 390 taken 4 times.
✓ Branch 389 → 395 taken 43 times.
47 if(outputVi.Is420() && viInternalWorkingFormat.Is444())
748 {
749
1/4
✓ Branch 390 → 391 taken 4 times.
✗ Branch 390 → 587 not taken.
✗ Branch 581 → 582 not taken.
✗ Branch 581 → 583 not taken.
4 PVideoFrame outputFrame = env->NewVideoFrameP(outputVi, &frame);
750
1/2
✓ Branch 391 → 392 taken 4 times.
✗ Branch 391 → 581 not taken.
4 Convert444ToYV12(frame, outputFrame, pixelsize, bits_per_pixel, env);
751
1/2
✗ Branch 392 → 393 not taken.
✓ Branch 392 → 394 taken 4 times.
4 return outputFrame;
752
8/10
✓ Branch 395 → 396 taken 43 times.
✗ Branch 395 → 587 not taken.
✓ Branch 396 → 397 taken 4 times.
✓ Branch 396 → 400 taken 39 times.
✓ Branch 397 → 398 taken 4 times.
✗ Branch 397 → 587 not taken.
✓ Branch 398 → 399 taken 2 times.
✓ Branch 398 → 400 taken 2 times.
✓ Branch 401 → 402 taken 2 times.
✓ Branch 401 → 408 taken 41 times.
43 } else if(outputVi.Is422() && viInternalWorkingFormat.Is444()) {
753
1/2
✓ Branch 402 → 403 taken 2 times.
✗ Branch 402 → 586 not taken.
2 PVideoFrame outputFrame = env->NewVideoFrameP(outputVi, &frame);
754
1/2
✓ Branch 403 → 404 taken 2 times.
✗ Branch 403 → 584 not taken.
2 Convert444ToYV16(frame, outputFrame, pixelsize, bits_per_pixel, env);
755
1/2
✓ Branch 404 → 405 taken 2 times.
✗ Branch 404 → 584 not taken.
2 return outputFrame;
756 2 }
757 // all other cases return 4:4:4
758 // except when use444 is false
759
1/2
✓ Branch 408 → 409 taken 41 times.
✗ Branch 408 → 587 not taken.
41 return frame;
760 47 }
761
762
763 /*************************
764 * Helper functions *
765 *************************/
766
767 49 void Overlay::SetOfModeByName(const char* name, IScriptEnvironment* env) {
768
769
2/2
✓ Branch 2 → 3 taken 15 times.
✓ Branch 2 → 4 taken 34 times.
49 if (!lstrcmpi(name, "Blend")) {
770 15 of_mode = OF_Blend;
771 }
772
2/2
✓ Branch 4 → 5 taken 10 times.
✓ Branch 4 → 6 taken 24 times.
34 else if (!lstrcmpi(name, "Add")) {
773 10 of_mode = OF_Add;
774 }
775
2/2
✓ Branch 6 → 7 taken 8 times.
✓ Branch 6 → 8 taken 16 times.
24 else if (!lstrcmpi(name, "Subtract")) {
776 8 of_mode = OF_Subtract;
777 }
778
1/2
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 10 taken 16 times.
16 else if (!lstrcmpi(name, "Multiply")) {
779 of_mode = OF_Multiply;
780 }
781
1/2
✗ Branch 10 → 11 not taken.
✓ Branch 10 → 12 taken 16 times.
16 else if (!lstrcmpi(name, "Chroma")) {
782 of_mode = OF_Chroma;
783 }
784
1/2
✗ Branch 12 → 13 not taken.
✓ Branch 12 → 14 taken 16 times.
16 else if (!lstrcmpi(name, "Luma")) {
785 of_mode = OF_Luma;
786 }
787
2/2
✓ Branch 14 → 15 taken 4 times.
✓ Branch 14 → 16 taken 12 times.
16 else if (!lstrcmpi(name, "Lighten")) {
788 4 of_mode = OF_Lighten;
789 }
790
2/2
✓ Branch 16 → 17 taken 4 times.
✓ Branch 16 → 18 taken 8 times.
12 else if (!lstrcmpi(name, "Darken")) {
791 4 of_mode = OF_Darken;
792 }
793
2/2
✓ Branch 18 → 19 taken 2 times.
✓ Branch 18 → 20 taken 6 times.
8 else if (!lstrcmpi(name, "SoftLight")) {
794 2 of_mode = OF_SoftLight;
795 }
796
2/2
✓ Branch 20 → 21 taken 2 times.
✓ Branch 20 → 22 taken 4 times.
6 else if (!lstrcmpi(name, "HardLight")) {
797 2 of_mode = OF_HardLight;
798 }
799
2/2
✓ Branch 22 → 23 taken 2 times.
✓ Branch 22 → 24 taken 2 times.
4 else if (!lstrcmpi(name, "Difference")) {
800 2 of_mode = OF_Difference;
801 }
802
1/2
✓ Branch 24 → 25 taken 2 times.
✗ Branch 24 → 26 not taken.
2 else if (!lstrcmpi(name, "Exclusion")) {
803 2 of_mode = OF_Exclusion;
804 }
805 else env->ThrowError("Overlay: Invalid 'Mode' specified.");
806 49 }
807
808 47 OverlayFunction* Overlay::SelectFunction()
809 {
810
9/13
✓ Branch 2 → 3 taken 13 times.
✓ Branch 2 → 9 taken 10 times.
✓ Branch 2 → 15 taken 8 times.
✗ Branch 2 → 21 not taken.
✗ Branch 2 → 27 not taken.
✗ Branch 2 → 33 not taken.
✓ Branch 2 → 39 taken 4 times.
✓ Branch 2 → 45 taken 4 times.
✓ Branch 2 → 51 taken 2 times.
✓ Branch 2 → 57 taken 2 times.
✓ Branch 2 → 63 taken 2 times.
✓ Branch 2 → 69 taken 2 times.
✗ Branch 2 → 75 not taken.
47 switch (of_mode) {
811
1/2
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 13 times.
13 case OF_Blend: return new OL_BlendImage();
812
1/2
✗ Branch 12 → 13 not taken.
✓ Branch 12 → 14 taken 10 times.
10 case OF_Add: return new OL_AddImage();
813
1/2
✗ Branch 18 → 19 not taken.
✓ Branch 18 → 20 taken 8 times.
8 case OF_Subtract: return new OL_AddImage(); // common with Add
814 case OF_Multiply: return new OL_MultiplyImage();
815 case OF_Chroma: return new OL_BlendImage(); // Common with BlendImage. plane range differs of_mode checked inside
816 case OF_Luma: return new OL_BlendImage(); // Common with BlendImage. plane range differs of_mode checked inside
817
1/2
✗ Branch 42 → 43 not taken.
✓ Branch 42 → 44 taken 4 times.
4 case OF_Lighten: return new OL_DarkenImage(); // common with Darken
818
1/2
✗ Branch 48 → 49 not taken.
✓ Branch 48 → 50 taken 4 times.
4 case OF_Darken: return new OL_DarkenImage();
819
1/2
✗ Branch 54 → 55 not taken.
✓ Branch 54 → 56 taken 2 times.
2 case OF_SoftLight: return new OL_SoftLightImage();
820
1/2
✗ Branch 60 → 61 not taken.
✓ Branch 60 → 62 taken 2 times.
2 case OF_HardLight: return new OL_SoftLightImage(); // Common with SoftLight
821
1/2
✗ Branch 66 → 67 not taken.
✓ Branch 66 → 68 taken 2 times.
2 case OF_Difference: return new OL_DifferenceImage();
822
1/2
✗ Branch 72 → 73 not taken.
✓ Branch 72 → 74 taken 2 times.
2 case OF_Exclusion: return new OL_ExclusionImage();
823 default: return nullptr; // cannot be
824 }
825 }
826
827 62 void Overlay::ClipFrames(ImageOverlayInternal* input, ImageOverlayInternal* overlay, int x, int y) {
828
829 62 input->ResetFake();
830 62 overlay->ResetFake();
831
832 62 input->ReturnOriginal(false); // We now use cropped space
833 62 overlay->ReturnOriginal(false);
834
835 // Crop negative offset off overlay
836
1/2
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 11 taken 62 times.
62 if (x<0) {
837 overlay->SubFrame(-x,0,overlay->w()+x, overlay->h());
838 x=0;
839 }
840
1/2
✗ Branch 11 → 12 not taken.
✓ Branch 11 → 16 taken 62 times.
62 if (y<0) {
841 overlay->SubFrame(0,-y, overlay->w(), overlay->h()+y);
842 y=0;
843 }
844 // Clip input-frame to topleft overlay:
845 62 input->SubFrame(x,y,input->w()-x, input->h()-y);
846
847 // input and overlay are now topleft aligned
848
849 // Clip overlay that is beyond the right side of the input
850
851
1/2
✗ Branch 21 → 22 not taken.
✓ Branch 21 → 25 taken 62 times.
62 if (overlay->w() > input->w()) {
852 overlay->SubFrame(0,0,input->w(), overlay->h());
853 }
854
855
1/2
✗ Branch 27 → 28 not taken.
✓ Branch 27 → 31 taken 62 times.
62 if (overlay->h() > input->h()) {
856 overlay->SubFrame(0,0,overlay->w(), input->h());
857 }
858
859 // Clip right/ bottom of input
860
861
1/2
✗ Branch 33 → 34 not taken.
✓ Branch 33 → 37 taken 62 times.
62 if(input->w() > overlay->w()) {
862 input->SubFrame(0,0, overlay->w(), input->h());
863 }
864
865
1/2
✗ Branch 39 → 40 not taken.
✓ Branch 39 → 43 taken 62 times.
62 if(input->h() > overlay->h()) {
866 input->SubFrame(0,0, input->w(), overlay->h());
867 }
868
869 62 }
870
871 47 void Overlay::FetchConditionals(IScriptEnvironment* env, int* op_offset, float* op_offset_f, int* con_x_offset, int* con_y_offset, bool ignore_conditional, const char *condVarSuffix) {
872 47 *op_offset = 0;
873 47 *op_offset_f = 0.0f;
874 47 *con_x_offset = 0;
875 47 *con_y_offset = 0;
876
877
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 33 taken 47 times.
47 if (!ignore_conditional) {
878 {
879 std::string s = std::string("OL_opacity_offset") + condVarSuffix;
880 *op_offset = (int)(env->GetVarDouble(s.c_str(), 0.0) * 256);
881 *op_offset_f = (float)(env->GetVarDouble(s.c_str(), 0.0));
882 }
883 {
884 std::string s = std::string("OL_x_offset") + condVarSuffix;
885 *con_x_offset = (int)(env->GetVarDouble(s.c_str(), 0.0));
886 }
887 {
888 std::string s = std::string("OL_y_offset") + condVarSuffix;
889 *con_y_offset = (int)(env->GetVarDouble(s.c_str(), 0.0));
890 }
891 }
892 47 }
893
894
895 AVSValue __cdecl Overlay::Create(AVSValue args, void*, IScriptEnvironment* env) {
896 // provide planar-only main clip
897 PClip input = args[0].AsClip();
898 VideoInfo vi_orig = input->GetVideoInfo();
899 bool converted = false;
900
901 // input clip to always planar
902 if (vi_orig.IsRGB() && !vi_orig.IsPlanar()) {
903 // no packed RGB allowed from now on, autoconvert from packed
904 AVSValue new_args[1] = { input };
905 if(vi_orig.IsRGB24() || vi_orig.IsRGB48())
906 input = env->Invoke("ConvertToPlanarRGB", AVSValue(new_args, 1)).AsClip();
907 else // RGB32, RGB64
908 input = env->Invoke("ConvertToPlanarRGBA", AVSValue(new_args, 1)).AsClip();
909 converted = true;
910 }
911 else if (vi_orig.IsYUY2()) {
912 // convert YUY2 to 422, keep internals simple
913 AVSValue new_args[2] = { input, false };
914 input = env->Invoke("ConvertToYUV422", AVSValue(new_args, 2)).AsClip();
915 converted = true;
916 }
917
918 // input now is always planar, overlay and mask clip converted later
919 Overlay* Result = new Overlay(input, args, env);
920
921 // where there was no output override but old formats were converted
922 // then we turn them back
923 if (Result->output_pixel_format_override == nullptr && converted) {
924 if (vi_orig.IsRGB() && !vi_orig.IsPlanar()) {
925 AVSValue new_args[1] = { Result };
926 if (vi_orig.IsRGB24())
927 return env->Invoke("ConvertToRGB24", AVSValue(new_args, 1)).AsClip();
928 else if (vi_orig.IsRGB32())
929 return env->Invoke("ConvertToRGB32", AVSValue(new_args, 1)).AsClip();
930 else if (vi_orig.IsRGB48())
931 return env->Invoke("ConvertToRGB48", AVSValue(new_args, 1)).AsClip();
932 else // if (vi_orig.IsRGB64())
933 return env->Invoke("ConvertToRGB64", AVSValue(new_args, 1)).AsClip();
934 }
935 if (vi_orig.IsYUY2()) {
936 // convert back to YUY2
937 AVSValue new_args[2] = { Result, false };
938 return env->Invoke("ConvertToYUY2", AVSValue(new_args, 2)).AsClip();
939 }
940 }
941
942 if (Result->GetVideoInfo().pixel_type == Result->outputVi.pixel_type)
943 return Result;
944 // c[interlaced]b[matrix]s[ChromaInPlacement]s[chromaresample]s
945 // chromaresample = 'bicubic' default
946 // chromaresample = 'point' is faster
947 if(Result->outputVi.Is444()) {
948 // if workingFormat is not 444 but output was specified
949 AVSValue new_args[3] = { Result, false, Result->full_range ? "PC.601" : "rec601" };
950 return env->Invoke("ConvertToYUV444", AVSValue(new_args, 3)).AsClip();
951 }
952 if(Result->outputVi.Is422()) {
953 AVSValue new_args[3] = { Result, false, Result->full_range ? "PC.601" : "rec601" };
954 return env->Invoke("ConvertToYUV422", AVSValue(new_args, 3)).AsClip();
955 }
956 if(Result->outputVi.Is420()) {
957 AVSValue new_args[3] = { Result, false, Result->full_range ? "PC.601" : "rec601" };
958 return env->Invoke("ConvertToYUV420", AVSValue(new_args, 3)).AsClip();
959 }
960 if (Result->outputVi.IsYV411()) {
961 AVSValue new_args[3] = { Result, false, Result->full_range ? "PC.601" : "rec601" };
962 return env->Invoke("ConvertToYUV411", AVSValue(new_args, 3)).AsClip();
963 }
964 if(Result->outputVi.IsYUY2()) {
965 AVSValue new_args[3] = { Result, false, Result->full_range ? "PC.601" : "rec601" };
966 return env->Invoke("ConvertToYUY2", AVSValue(new_args, 3)).AsClip();
967 }
968 if(Result->outputVi.IsY()) {
969 AVSValue new_args[2] = { Result, Result->full_range ? "PC.601" : "rec601" };
970 return env->Invoke("ConvertToY", AVSValue(new_args, 2)).AsClip();
971 }
972 if(Result->outputVi.IsRGB()) {
973 // c[matrix]s[interlaced]b[ChromaInPlacement]s[chromaresample]s
974 AVSValue new_args[3] = { Result, Result->full_range ? "PC.601" : "rec601", false};
975 if(Result->outputVi.IsPlanarRGB()) {
976 return env->Invoke("ConvertToPlanarRGB", AVSValue(new_args, 3)).AsClip();
977 }
978 if(Result->outputVi.IsPlanarRGBA()) {
979 return env->Invoke("ConvertToPlanarRGBA", AVSValue(new_args, 3)).AsClip();
980 }
981 if(Result->outputVi.IsRGB24()) {
982 return env->Invoke("ConvertToRGB24", AVSValue(new_args, 3)).AsClip();
983 }
984 if(Result->outputVi.IsRGB32()) {
985 return env->Invoke("ConvertToRGB32", AVSValue(new_args, 3)).AsClip();
986 }
987 if(Result->outputVi.IsRGB48()) {
988 return env->Invoke("ConvertToRGB48", AVSValue(new_args, 3)).AsClip();
989 }
990 if(Result->outputVi.IsRGB64()) {
991 return env->Invoke("ConvertToRGB64", AVSValue(new_args, 3)).AsClip();
992 }
993 }
994 env->ThrowError("Overlay: Invalid output format.");
995 return Result;
996 }
997