filters/planeswap.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 | |||
| 36 | // Avisynth filter: Swap planes | ||
| 37 | // by Klaus Post | ||
| 38 | // adapted by Richard Berg (avisynth-dev@richardberg.net) | ||
| 39 | // iSSE code by Ian Brabham | ||
| 40 | |||
| 41 | #include <avs/config.h> | ||
| 42 | #ifdef AVS_WINDOWS | ||
| 43 | #include <avs/win.h> | ||
| 44 | #else | ||
| 45 | #include <avs/posix.h> | ||
| 46 | #endif | ||
| 47 | #include "planeswap.h" | ||
| 48 | #ifdef INTEL_INTRINSICS | ||
| 49 | #include "intel/planeswap_sse.h" | ||
| 50 | #include "intel/planeswap_avx2.h" | ||
| 51 | #endif | ||
| 52 | #include "../core/internal.h" | ||
| 53 | #include <algorithm> | ||
| 54 | #include <avs/alignment.h> | ||
| 55 | #include "../convert/convert_planar.h" | ||
| 56 | #include "../convert/convert_rgb.h" | ||
| 57 | #include "../convert/convert.h" | ||
| 58 | #include "../convert/convert_helper.h" | ||
| 59 | #include "stdint.h" | ||
| 60 | |||
| 61 | |||
| 62 | /******************************************************************** | ||
| 63 | ***** Declare index of new filters for Avisynth's filter engine ***** | ||
| 64 | ********************************************************************/ | ||
| 65 | |||
| 66 | extern const AVSFunction Swap_filters[] = { | ||
| 67 | { "SwapUV", BUILTIN_FUNC_PREFIX, "c", SwapUV::CreateSwapUV }, | ||
| 68 | { "UToY", BUILTIN_FUNC_PREFIX, "c", SwapUVToY::CreateUToY }, | ||
| 69 | { "VToY", BUILTIN_FUNC_PREFIX, "c", SwapUVToY::CreateVToY }, | ||
| 70 | { "UToY8", BUILTIN_FUNC_PREFIX, "c", SwapUVToY::CreateUToY8 }, | ||
| 71 | { "VToY8", BUILTIN_FUNC_PREFIX, "c", SwapUVToY::CreateVToY8 }, | ||
| 72 | { "ExtractY", BUILTIN_FUNC_PREFIX, "c", SwapUVToY::CreateYToY8 }, // differs, YUY2 checks inside | ||
| 73 | { "ExtractU", BUILTIN_FUNC_PREFIX, "c", SwapUVToY::CreateUToY8 }, // differs, YUY2 checks inside | ||
| 74 | { "ExtractV", BUILTIN_FUNC_PREFIX, "c", SwapUVToY::CreateVToY8 }, // differs, YUY2 checks inside | ||
| 75 | { "ExtractA", BUILTIN_FUNC_PREFIX, "c", SwapUVToY::CreateAnyToY8, (void *)SwapUVToY::AToY8 }, | ||
| 76 | { "ExtractR", BUILTIN_FUNC_PREFIX, "c", SwapUVToY::CreateAnyToY8, (void *)SwapUVToY::RToY8 }, | ||
| 77 | { "ExtractG", BUILTIN_FUNC_PREFIX, "c", SwapUVToY::CreateAnyToY8, (void *)SwapUVToY::GToY8 }, | ||
| 78 | { "ExtractB", BUILTIN_FUNC_PREFIX, "c", SwapUVToY::CreateAnyToY8, (void *)SwapUVToY::BToY8 }, | ||
| 79 | { "YToUV", BUILTIN_FUNC_PREFIX, "cc", SwapYToUV::CreateYToUV }, | ||
| 80 | { "YToUV", BUILTIN_FUNC_PREFIX, "ccc", SwapYToUV::CreateYToYUV }, | ||
| 81 | { "YToUV", BUILTIN_FUNC_PREFIX, "cccc", SwapYToUV::CreateYToYUVA }, // avs+ alpha planes | ||
| 82 | { "PlaneToY", BUILTIN_FUNC_PREFIX, "c[plane]s", SwapUVToY::CreatePlaneToY8 }, | ||
| 83 | { "CombinePlanes", BUILTIN_FUNC_PREFIX, "c[planes]s[source_planes]s[pixel_type]s[sample_clip]c", CombinePlanes::CreateCombinePlanes, (void *)1}, | ||
| 84 | { "CombinePlanes", BUILTIN_FUNC_PREFIX, "cc[planes]s[source_planes]s[pixel_type]s[sample_clip]c", CombinePlanes::CreateCombinePlanes, (void *)2}, | ||
| 85 | { "CombinePlanes", BUILTIN_FUNC_PREFIX, "ccc[planes]s[source_planes]s[pixel_type]s[sample_clip]c", CombinePlanes::CreateCombinePlanes, (void *)3}, | ||
| 86 | { "CombinePlanes", BUILTIN_FUNC_PREFIX, "cccc[planes]s[source_planes]s[pixel_type]s[sample_clip]c", CombinePlanes::CreateCombinePlanes, (void *)4}, | ||
| 87 | { 0 } | ||
| 88 | }; | ||
| 89 | |||
| 90 | |||
| 91 | /************************************** | ||
| 92 | * Swap - swaps UV on planar maps | ||
| 93 | **************************************/ | ||
| 94 | |||
| 95 | ✗ | static void yuy2_swap_c(const BYTE* srcp, BYTE* dstp, int src_pitch, int dst_pitch, int width, int height) | |
| 96 | { | ||
| 97 | ✗ | for (int y = 0; y < height; ++y) { | |
| 98 | ✗ | for (int x = 0; x < width; x += 4) { | |
| 99 | ✗ | dstp[x + 0] = srcp[x + 0]; | |
| 100 | ✗ | dstp[x + 3] = srcp[x + 1]; | |
| 101 | ✗ | dstp[x + 2] = srcp[x + 2]; | |
| 102 | ✗ | dstp[x + 1] = srcp[x + 3]; | |
| 103 | } | ||
| 104 | ✗ | srcp += src_pitch; | |
| 105 | ✗ | dstp += dst_pitch; | |
| 106 | } | ||
| 107 | ✗ | } | |
| 108 | |||
| 109 | ✗ | AVSValue __cdecl SwapUV::CreateSwapUV(AVSValue args, void* , IScriptEnvironment* env) | |
| 110 | { | ||
| 111 | ✗ | PClip p = args[0].AsClip(); | |
| 112 | ✗ | if (p->GetVideoInfo().NumComponents() == 1) | |
| 113 | ✗ | return p; | |
| 114 | ✗ | return new SwapUV(p, env); | |
| 115 | ✗ | } | |
| 116 | |||
| 117 | |||
| 118 |
2/4✓ Branch 2 → 3 taken 6 times.
✗ Branch 2 → 16 not taken.
✓ Branch 3 → 4 taken 6 times.
✗ Branch 3 → 14 not taken.
|
6 | SwapUV::SwapUV(PClip _child, IScriptEnvironment* env) : GenericVideoFilter(_child) |
| 119 | { | ||
| 120 |
6/10✓ Branch 5 → 6 taken 6 times.
✗ Branch 5 → 17 not taken.
✓ Branch 6 → 7 taken 3 times.
✓ Branch 6 → 10 taken 3 times.
✓ Branch 7 → 8 taken 3 times.
✗ Branch 7 → 17 not taken.
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 10 taken 3 times.
✗ Branch 11 → 12 not taken.
✓ Branch 11 → 13 taken 6 times.
|
6 | if (!vi.IsYUV() && !vi.IsYUVA()) |
| 121 | ✗ | env->ThrowError("SwapUV: YUV or YUVA data only!"); | |
| 122 | 6 | } | |
| 123 | |||
| 124 | 6 | PVideoFrame __stdcall SwapUV::GetFrame(int n, IScriptEnvironment* env) | |
| 125 | { | ||
| 126 |
1/2✓ Branch 3 → 4 taken 6 times.
✗ Branch 3 → 72 not taken.
|
6 | PVideoFrame src = child->GetFrame(n, env); |
| 127 | |||
| 128 |
2/4✓ Branch 4 → 5 taken 6 times.
✗ Branch 4 → 70 not taken.
✓ Branch 5 → 6 taken 6 times.
✗ Branch 5 → 38 not taken.
|
6 | if (vi.IsPlanar()) { |
| 129 | // Abuse subframe to flip the UV plane pointers -- extremely fast but a bit naughty! | ||
| 130 | // !! if offsets would be size_t, be cautious when you subtract two unsigned size_t variables | ||
| 131 |
2/4✓ Branch 7 → 8 taken 6 times.
✗ Branch 7 → 70 not taken.
✓ Branch 9 → 10 taken 6 times.
✗ Branch 9 → 70 not taken.
|
6 | const int uvoffset = src->GetOffset(PLANAR_V) - src->GetOffset(PLANAR_U); // very naughty - don't do this at home!! |
| 132 |
3/4✓ Branch 10 → 11 taken 6 times.
✗ Branch 10 → 70 not taken.
✓ Branch 11 → 12 taken 3 times.
✓ Branch 11 → 25 taken 3 times.
|
6 | if (vi.NumComponents() == 4) { |
| 133 | 3 | return env->SubframePlanarA(src, 0, src->GetPitch(PLANAR_Y), src->GetRowSize(PLANAR_Y), src->GetHeight(PLANAR_Y), | |
| 134 |
6/12✓ Branch 13 → 14 taken 3 times.
✗ Branch 13 → 70 not taken.
✓ Branch 15 → 16 taken 3 times.
✗ Branch 15 → 70 not taken.
✓ Branch 17 → 18 taken 3 times.
✗ Branch 17 → 70 not taken.
✓ Branch 19 → 20 taken 3 times.
✗ Branch 19 → 70 not taken.
✓ Branch 20 → 21 taken 3 times.
✗ Branch 20 → 64 not taken.
✓ Branch 21 → 22 taken 3 times.
✗ Branch 21 → 62 not taken.
|
3 | uvoffset, -uvoffset, src->GetPitch(PLANAR_V), 0); |
| 135 | } | ||
| 136 | else { | ||
| 137 | 3 | return env->SubframePlanar(src, 0, src->GetPitch(PLANAR_Y), src->GetRowSize(PLANAR_Y), src->GetHeight(PLANAR_Y), | |
| 138 |
6/12✓ Branch 26 → 27 taken 3 times.
✗ Branch 26 → 70 not taken.
✓ Branch 28 → 29 taken 3 times.
✗ Branch 28 → 70 not taken.
✓ Branch 30 → 31 taken 3 times.
✗ Branch 30 → 70 not taken.
✓ Branch 32 → 33 taken 3 times.
✗ Branch 32 → 70 not taken.
✓ Branch 33 → 34 taken 3 times.
✗ Branch 33 → 67 not taken.
✓ Branch 34 → 35 taken 3 times.
✗ Branch 34 → 65 not taken.
|
3 | uvoffset, -uvoffset, src->GetPitch(PLANAR_V)); |
| 139 | } | ||
| 140 | } | ||
| 141 | |||
| 142 | // YUY2 | ||
| 143 | ✗ | PVideoFrame dst = env->NewVideoFrameP(vi, &src); | |
| 144 | ✗ | const BYTE* srcp = src->GetReadPtr(); | |
| 145 | ✗ | BYTE* dstp = dst->GetWritePtr(); | |
| 146 | ✗ | int src_pitch = src->GetPitch(); | |
| 147 | ✗ | int dst_pitch = dst->GetPitch(); | |
| 148 | ✗ | int rowsize = src->GetRowSize(); | |
| 149 | #ifdef INTEL_INTRINSICS | ||
| 150 | ✗ | if ((env->GetCPUFlags() & CPUF_SSSE3)) | |
| 151 | ✗ | yuy2_swap_ssse3(srcp, dstp, src_pitch, dst_pitch, rowsize, vi.height); | |
| 152 | ✗ | else if ((env->GetCPUFlags() & CPUF_SSE2)) | |
| 153 | ✗ | yuy2_swap_sse2(srcp, dstp, src_pitch, dst_pitch, rowsize, vi.height); | |
| 154 | #ifdef X86_32 | ||
| 155 | else if (env->GetCPUFlags() & CPUF_INTEGER_SSE) // need pshufw | ||
| 156 | yuy2_swap_isse(srcp, dstp, src_pitch, dst_pitch, rowsize, vi.height); | ||
| 157 | #endif | ||
| 158 | else | ||
| 159 | #endif | ||
| 160 | { | ||
| 161 | ✗ | yuy2_swap_c(srcp, dstp, src_pitch, dst_pitch, rowsize, vi.height); | |
| 162 | } | ||
| 163 | ✗ | return dst; | |
| 164 | 6 | } | |
| 165 | |||
| 166 | |||
| 167 | ✗ | AVSValue __cdecl SwapUVToY::CreateUToY(AVSValue args, void* , IScriptEnvironment* env) | |
| 168 | { | ||
| 169 | ✗ | return new SwapUVToY(args[0].AsClip(), UToY, env); | |
| 170 | } | ||
| 171 | |||
| 172 | ✗ | AVSValue __cdecl SwapUVToY::CreateUToY8(AVSValue args, void* , IScriptEnvironment* env) | |
| 173 | { | ||
| 174 | ✗ | PClip clip = args[0].AsClip(); | |
| 175 | ✗ | return new SwapUVToY(clip, (clip->GetVideoInfo().IsYUY2()) ? YUY2UToY8 : UToY8, env); | |
| 176 | ✗ | } | |
| 177 | |||
| 178 | ✗ | AVSValue __cdecl SwapUVToY::CreateYToY8(AVSValue args, void* , IScriptEnvironment* env) | |
| 179 | { | ||
| 180 | ✗ | PClip clip = args[0].AsClip(); | |
| 181 | ✗ | if(clip->GetVideoInfo().IsYUY2()) | |
| 182 | ✗ | return new ConvertYUY2ToYV16_or_Y(clip, true /*to_y*/, env); | |
| 183 | else | ||
| 184 | ✗ | return new SwapUVToY(clip, YToY8, env); | |
| 185 | ✗ | } | |
| 186 | |||
| 187 | ✗ | AVSValue __cdecl SwapUVToY::CreateVToY(AVSValue args, void* , IScriptEnvironment* env) | |
| 188 | { | ||
| 189 | ✗ | return new SwapUVToY(args[0].AsClip(), VToY, env); | |
| 190 | } | ||
| 191 | |||
| 192 | ✗ | AVSValue __cdecl SwapUVToY::CreateVToY8(AVSValue args, void* , IScriptEnvironment* env) | |
| 193 | { | ||
| 194 | ✗ | PClip clip = args[0].AsClip(); | |
| 195 | ✗ | return new SwapUVToY(clip, (clip->GetVideoInfo().IsYUY2()) ? YUY2VToY8 : VToY8, env); | |
| 196 | ✗ | } | |
| 197 | |||
| 198 | ✗ | AVSValue __cdecl SwapUVToY::CreateAnyToY8(AVSValue args, void* user_data, IScriptEnvironment* env) | |
| 199 | { | ||
| 200 | ✗ | int mode = (int)(intptr_t)(user_data); | |
| 201 | ✗ | PClip clip = args[0].AsClip(); | |
| 202 | |||
| 203 | // Packed RGB (RGB24/32/48/64): pass directly to SwapUVToY; GetFrame handles | ||
| 204 | // channel extraction with correct bottom-up row order. No planar conversion needed. | ||
| 205 | |||
| 206 | ✗ | if(clip->GetVideoInfo().IsYUY2() && mode == YToY8) | |
| 207 | ✗ | return new ConvertYUY2ToYV16_or_Y(clip, true /*to_y*/, env); | |
| 208 | |||
| 209 | ✗ | if (clip->GetVideoInfo().IsY() && mode == YToY8) | |
| 210 | ✗ | return clip; | |
| 211 | |||
| 212 | ✗ | return new SwapUVToY(clip, mode, env); | |
| 213 | ✗ | } | |
| 214 | |||
| 215 | ✗ | AVSValue __cdecl SwapUVToY::CreatePlaneToY8(AVSValue args, void* , IScriptEnvironment* env) { | |
| 216 | ✗ | PClip clip = args[0].AsClip(); | |
| 217 | |||
| 218 | ✗ | const VideoInfo& vi_input = clip->GetVideoInfo(); | |
| 219 | |||
| 220 | ✗ | const char* plane = args[1].AsString(""); | |
| 221 | ✗ | int mode = 0; | |
| 222 | // enum {UToY=1, VToY, UToY8, VToY8, YUY2UToY8, YUY2VToY8, AToY8, RToY8, GToY8, BToY8, YToY8}; | ||
| 223 | ✗ | if (!lstrcmpi(plane, "Y")) mode = YToY8; | |
| 224 | ✗ | else if (!lstrcmpi(plane, "U")) mode = vi_input.IsYUY2() ? YUY2UToY8 : UToY8; | |
| 225 | ✗ | else if (!lstrcmpi(plane, "V")) mode = vi_input.IsYUY2() ? YUY2VToY8 : VToY8; | |
| 226 | ✗ | else if (!lstrcmpi(plane, "A")) mode = AToY8; | |
| 227 | ✗ | else if (!lstrcmpi(plane, "R")) mode = RToY8; | |
| 228 | ✗ | else if (!lstrcmpi(plane, "G")) mode = GToY8; | |
| 229 | ✗ | else if (!lstrcmpi(plane, "B")) mode = BToY8; | |
| 230 | ✗ | else env->ThrowError("PlaneToY: Invalid plane!"); | |
| 231 | |||
| 232 | ✗ | return CreateAnyToY8(args, (void* )(intptr_t)mode, env); | |
| 233 | ✗ | } | |
| 234 | |||
| 235 | |||
| 236 | 19 | SwapUVToY::SwapUVToY(PClip _child, int _mode, IScriptEnvironment* env) | |
| 237 |
2/4✓ Branch 2 → 3 taken 19 times.
✗ Branch 2 → 78 not taken.
✓ Branch 3 → 4 taken 19 times.
✗ Branch 3 → 76 not taken.
|
19 | : GenericVideoFilter(_child), mode(_mode) |
| 238 | { | ||
| 239 |
9/14✓ Branch 5 → 6 taken 19 times.
✗ Branch 5 → 12 not taken.
✓ Branch 6 → 7 taken 14 times.
✓ Branch 6 → 12 taken 5 times.
✓ Branch 7 → 8 taken 9 times.
✓ Branch 7 → 12 taken 5 times.
✓ Branch 8 → 9 taken 9 times.
✗ Branch 8 → 12 not taken.
✓ Branch 9 → 10 taken 9 times.
✗ Branch 9 → 12 not taken.
✓ Branch 10 → 11 taken 9 times.
✗ Branch 10 → 12 not taken.
✗ Branch 11 → 12 not taken.
✓ Branch 11 → 13 taken 9 times.
|
19 | bool YUVmode = mode == YToY8 || mode == UToY8 || mode == VToY8 || mode == UToY || mode == VToY || mode == YUY2UToY8 || mode == YUY2VToY8; |
| 240 |
6/6✓ Branch 14 → 15 taken 16 times.
✓ Branch 14 → 17 taken 3 times.
✓ Branch 15 → 16 taken 13 times.
✓ Branch 15 → 17 taken 3 times.
✓ Branch 16 → 17 taken 3 times.
✓ Branch 16 → 18 taken 10 times.
|
19 | bool RGBmode = mode == RToY8 || mode == GToY8 || mode == BToY8; |
| 241 | 19 | bool Alphamode = mode == AToY8; | |
| 242 | |||
| 243 | // RGB32/64 are packed RGBA; RGB24/48 have no alpha channel. | ||
| 244 |
10/20✓ Branch 19 → 20 taken 19 times.
✗ Branch 19 → 79 not taken.
✓ Branch 20 → 21 taken 19 times.
✗ Branch 20 → 29 not taken.
✓ Branch 21 → 22 taken 19 times.
✗ Branch 21 → 79 not taken.
✓ Branch 22 → 23 taken 19 times.
✗ Branch 22 → 29 not taken.
✓ Branch 23 → 24 taken 19 times.
✗ Branch 23 → 79 not taken.
✓ Branch 24 → 25 taken 19 times.
✗ Branch 24 → 29 not taken.
✓ Branch 25 → 26 taken 19 times.
✗ Branch 25 → 79 not taken.
✓ Branch 26 → 27 taken 19 times.
✗ Branch 26 → 29 not taken.
✗ Branch 27 → 28 not taken.
✓ Branch 27 → 29 taken 19 times.
✗ Branch 30 → 31 not taken.
✓ Branch 30 → 32 taken 19 times.
|
19 | if(!vi.IsYUVA() && !vi.IsPlanarRGBA() && !(vi.IsRGB32() || vi.IsRGB64()) && Alphamode) |
| 245 | ✗ | env->ThrowError("PlaneToY: Clip has no Alpha channel!"); | |
| 246 | |||
| 247 |
7/12✓ Branch 32 → 33 taken 19 times.
✗ Branch 32 → 79 not taken.
✓ Branch 33 → 34 taken 9 times.
✓ Branch 33 → 38 taken 10 times.
✓ Branch 34 → 35 taken 9 times.
✗ Branch 34 → 79 not taken.
✓ Branch 35 → 36 taken 9 times.
✗ Branch 35 → 38 not taken.
✗ Branch 36 → 37 not taken.
✓ Branch 36 → 38 taken 9 times.
✗ Branch 39 → 40 not taken.
✓ Branch 39 → 41 taken 19 times.
|
19 | if (!vi.IsYUV() && !vi.IsYUVA() && YUVmode ) |
| 248 | ✗ | env->ThrowError("PlaneToY: clip is not YUV!"); | |
| 249 | |||
| 250 | // IsRGB() covers both packed (RGB24/32/48/64) and planar RGB/RGBA. | ||
| 251 |
5/8✓ Branch 41 → 42 taken 19 times.
✗ Branch 41 → 79 not taken.
✓ Branch 42 → 43 taken 10 times.
✓ Branch 42 → 45 taken 9 times.
✗ Branch 43 → 44 not taken.
✓ Branch 43 → 45 taken 10 times.
✗ Branch 46 → 47 not taken.
✓ Branch 46 → 48 taken 19 times.
|
19 | if (!vi.IsRGB() && RGBmode) |
| 252 | ✗ | env->ThrowError("PlaneToY: clip is not RGB!"); | |
| 253 | |||
| 254 |
3/8✓ Branch 48 → 49 taken 19 times.
✗ Branch 48 → 79 not taken.
✗ Branch 49 → 50 not taken.
✓ Branch 49 → 52 taken 19 times.
✗ Branch 50 → 51 not taken.
✗ Branch 50 → 52 not taken.
✗ Branch 53 → 54 not taken.
✓ Branch 53 → 55 taken 19 times.
|
19 | if (vi.NumComponents() == 1 && mode != YToY8) |
| 255 | ✗ | env->ThrowError("PlaneToY: channel cannot be extracted from a greyscale clip!"); | |
| 256 | |||
| 257 |
3/4✓ Branch 55 → 56 taken 10 times.
✓ Branch 55 → 60 taken 9 times.
✓ Branch 56 → 57 taken 10 times.
✗ Branch 56 → 60 not taken.
|
19 | if(YUVmode && (mode!=YToY8)){ |
| 258 |
1/2✓ Branch 57 → 58 taken 10 times.
✗ Branch 57 → 79 not taken.
|
10 | vi.height >>= vi.GetPlaneHeightSubsampling(PLANAR_U); |
| 259 |
1/2✓ Branch 58 → 59 taken 10 times.
✗ Branch 58 → 79 not taken.
|
10 | vi.width >>= vi.GetPlaneWidthSubsampling(PLANAR_U); |
| 260 | } | ||
| 261 | |||
| 262 |
8/14✓ Branch 60 → 61 taken 19 times.
✗ Branch 60 → 67 not taken.
✓ Branch 61 → 62 taken 14 times.
✓ Branch 61 → 67 taken 5 times.
✓ Branch 62 → 63 taken 9 times.
✓ Branch 62 → 67 taken 5 times.
✓ Branch 63 → 64 taken 9 times.
✗ Branch 63 → 67 not taken.
✓ Branch 64 → 65 taken 9 times.
✗ Branch 64 → 67 not taken.
✗ Branch 65 → 66 not taken.
✓ Branch 65 → 67 taken 9 times.
✗ Branch 66 → 67 not taken.
✗ Branch 66 → 75 not taken.
|
19 | if (mode == YToY8 || mode == UToY8 || mode == VToY8 || mode == YUY2UToY8 || mode == YUY2VToY8 || RGBmode || Alphamode) |
| 263 | { | ||
| 264 |
3/9✓ Branch 67 → 68 taken 19 times.
✗ Branch 67 → 79 not taken.
✓ Branch 68 → 69 taken 11 times.
✗ Branch 68 → 70 not taken.
✗ Branch 68 → 71 not taken.
✗ Branch 68 → 72 not taken.
✓ Branch 68 → 73 taken 8 times.
✗ Branch 68 → 74 not taken.
✗ Branch 68 → 75 not taken.
|
19 | switch (vi.BitsPerComponent()) // although name is Y8, it means that greyscale stays in the same bitdepth |
| 265 | { | ||
| 266 | 11 | case 8: vi.pixel_type = VideoInfo::CS_Y8; break; | |
| 267 | ✗ | case 10: vi.pixel_type = VideoInfo::CS_Y10; break; | |
| 268 | ✗ | case 12: vi.pixel_type = VideoInfo::CS_Y12; break; | |
| 269 | ✗ | case 14: vi.pixel_type = VideoInfo::CS_Y14; break; | |
| 270 | 8 | case 16: vi.pixel_type = VideoInfo::CS_Y16; break; | |
| 271 | ✗ | case 32: vi.pixel_type = VideoInfo::CS_Y32; break; | |
| 272 | } | ||
| 273 | } | ||
| 274 | 19 | } | |
| 275 | |||
| 276 | 17 | PVideoFrame __stdcall SwapUVToY::GetFrame(int n, IScriptEnvironment* env) | |
| 277 | { | ||
| 278 |
1/2✓ Branch 3 → 4 taken 17 times.
✗ Branch 3 → 289 not taken.
|
17 | PVideoFrame src = child->GetFrame(n, env); |
| 279 |
1/2✓ Branch 5 → 6 taken 17 times.
✗ Branch 5 → 287 not taken.
|
17 | const VideoInfo& src_vi = child->GetVideoInfo(); |
| 280 | |||
| 281 | // ----------------------------------------------------------------------- | ||
| 282 | // Packed RGB (RGB24/32/48/64) channel extraction. | ||
| 283 | // Packed RGB is stored bottom-up; the Subframe offset trick used for | ||
| 284 | // planar formats does not apply here. We iterate rows in reverse order | ||
| 285 | // from the source while writing top-down into the Y-only destination. | ||
| 286 | // ----------------------------------------------------------------------- | ||
| 287 |
10/14✓ Branch 6 → 7 taken 17 times.
✗ Branch 6 → 287 not taken.
✓ Branch 7 → 8 taken 9 times.
✓ Branch 7 → 13 taken 8 times.
✓ Branch 8 → 9 taken 9 times.
✗ Branch 8 → 287 not taken.
✓ Branch 9 → 10 taken 6 times.
✓ Branch 9 → 13 taken 3 times.
✓ Branch 10 → 11 taken 6 times.
✗ Branch 10 → 287 not taken.
✓ Branch 11 → 12 taken 6 times.
✗ Branch 11 → 13 not taken.
✓ Branch 14 → 15 taken 6 times.
✓ Branch 14 → 147 taken 11 times.
|
17 | if (src_vi.IsRGB() && !src_vi.IsPlanarRGB() && !src_vi.IsPlanarRGBA()) { |
| 288 |
1/4✓ Branch 15 → 16 taken 6 times.
✗ Branch 15 → 287 not taken.
✗ Branch 276 → 277 not taken.
✗ Branch 276 → 278 not taken.
|
6 | PVideoFrame dst = env->NewVideoFrameP(vi, &src); |
| 289 | 6 | const int height = vi.height; | |
| 290 | 6 | const int width = vi.width; | |
| 291 |
1/2✓ Branch 16 → 17 taken 6 times.
✗ Branch 16 → 276 not taken.
|
6 | const int pixelsize = src_vi.ComponentSize(); // 1 (8-bit) or 2 (16-bit) |
| 292 |
1/2✓ Branch 17 → 18 taken 6 times.
✗ Branch 17 → 276 not taken.
|
6 | const int src_components = src_vi.NumComponents(); // 3 (RGB24/48) or 4 (RGB32/64) |
| 293 | |||
| 294 | // Byte offset of the requested channel within one packed pixel. | ||
| 295 | // Memory order: B=0, G=1, R=2, A=3 (each occupies pixelsize bytes). | ||
| 296 | int channel_index; | ||
| 297 |
3/4✓ Branch 18 → 19 taken 2 times.
✓ Branch 18 → 20 taken 2 times.
✓ Branch 18 → 21 taken 2 times.
✗ Branch 18 → 22 not taken.
|
6 | switch (mode) { |
| 298 | 2 | case BToY8: channel_index = 0; break; | |
| 299 | 2 | case GToY8: channel_index = 1; break; | |
| 300 | 2 | case RToY8: channel_index = 2; break; | |
| 301 | ✗ | default /*AToY8*/: channel_index = 3; break; | |
| 302 | } | ||
| 303 | 6 | const int byte_offset = channel_index * pixelsize; | |
| 304 | 6 | const int pixel_stride = src_components * pixelsize; // bytes between adjacent pixels | |
| 305 | |||
| 306 |
1/2✓ Branch 24 → 25 taken 6 times.
✗ Branch 24 → 276 not taken.
|
6 | const BYTE* srcp_bottom = src->GetReadPtr() |
| 307 |
1/2✓ Branch 26 → 27 taken 6 times.
✗ Branch 26 → 276 not taken.
|
6 | + static_cast<ptrdiff_t>(src->GetPitch()) * (height - 1); |
| 308 |
1/2✓ Branch 28 → 29 taken 6 times.
✗ Branch 28 → 276 not taken.
|
6 | const int src_pitch = src->GetPitch(); |
| 309 |
1/2✓ Branch 30 → 31 taken 6 times.
✗ Branch 30 → 276 not taken.
|
6 | BYTE* dstp_base = dst->GetWritePtr(); |
| 310 |
1/2✓ Branch 32 → 33 taken 6 times.
✗ Branch 32 → 276 not taken.
|
6 | const int dst_pitch = dst->GetPitch(); |
| 311 | |||
| 312 | #ifdef INTEL_INTRINSICS | ||
| 313 |
1/2✓ Branch 33 → 34 taken 6 times.
✗ Branch 33 → 276 not taken.
|
6 | const bool avx2 = (env->GetCPUFlags() & CPUF_AVX2) != 0; |
| 314 |
1/2✓ Branch 34 → 35 taken 6 times.
✗ Branch 34 → 276 not taken.
|
6 | const bool sse2 = (env->GetCPUFlags() & CPUF_SSE2) != 0; |
| 315 |
6/12✓ Branch 35 → 36 taken 6 times.
✗ Branch 35 → 41 not taken.
✓ Branch 36 → 37 taken 6 times.
✗ Branch 36 → 276 not taken.
✓ Branch 37 → 38 taken 6 times.
✗ Branch 37 → 40 not taken.
✓ Branch 38 → 39 taken 6 times.
✗ Branch 38 → 276 not taken.
✗ Branch 39 → 40 not taken.
✓ Branch 39 → 41 taken 6 times.
✗ Branch 42 → 43 not taken.
✓ Branch 42 → 65 taken 6 times.
|
6 | if (avx2 && (src_vi.IsRGB32() || src_vi.IsRGB64())) { |
| 316 | ✗ | if (src_vi.IsRGB32()) { | |
| 317 | ✗ | switch (channel_index) { | |
| 318 | ✗ | case 0: extract_packed_rgb32_channel_avx2<0>(srcp_bottom, dstp_base, src_pitch, dst_pitch, width, height); break; | |
| 319 | ✗ | case 1: extract_packed_rgb32_channel_avx2<1>(srcp_bottom, dstp_base, src_pitch, dst_pitch, width, height); break; | |
| 320 | ✗ | case 2: extract_packed_rgb32_channel_avx2<2>(srcp_bottom, dstp_base, src_pitch, dst_pitch, width, height); break; | |
| 321 | ✗ | case 3: extract_packed_rgb32_channel_avx2<3>(srcp_bottom, dstp_base, src_pitch, dst_pitch, width, height); break; | |
| 322 | } | ||
| 323 | } else { // RGB64 | ||
| 324 | ✗ | switch (channel_index) { | |
| 325 | ✗ | case 0: extract_packed_rgb64_channel_avx2<0>(srcp_bottom, dstp_base, src_pitch, dst_pitch, width, height); break; | |
| 326 | ✗ | case 1: extract_packed_rgb64_channel_avx2<1>(srcp_bottom, dstp_base, src_pitch, dst_pitch, width, height); break; | |
| 327 | ✗ | case 2: extract_packed_rgb64_channel_avx2<2>(srcp_bottom, dstp_base, src_pitch, dst_pitch, width, height); break; | |
| 328 | ✗ | case 3: extract_packed_rgb64_channel_avx2<3>(srcp_bottom, dstp_base, src_pitch, dst_pitch, width, height); break; | |
| 329 | } | ||
| 330 | } | ||
| 331 |
7/12✓ Branch 65 → 66 taken 6 times.
✗ Branch 65 → 71 not taken.
✓ Branch 66 → 67 taken 6 times.
✗ Branch 66 → 276 not taken.
✓ Branch 67 → 68 taken 3 times.
✓ Branch 67 → 71 taken 3 times.
✓ Branch 68 → 69 taken 3 times.
✗ Branch 68 → 71 not taken.
✗ Branch 69 → 70 not taken.
✓ Branch 69 → 71 taken 3 times.
✗ Branch 72 → 73 not taken.
✓ Branch 72 → 81 taken 6 times.
|
6 | } else if (avx2 && src_vi.IsRGB24() && channel_index <= 2 && width >= 32) { |
| 332 | // RGB24 AVX2: 32 pixels/iter; needs width >= 32 for the overlap-remainder to be valid. | ||
| 333 | ✗ | switch (channel_index) { | |
| 334 | ✗ | case 0: extract_packed_rgb_noalpha_channel_avx2<uint8_t, 0>(srcp_bottom, dstp_base, src_pitch, dst_pitch, width, height); break; | |
| 335 | ✗ | case 1: extract_packed_rgb_noalpha_channel_avx2<uint8_t, 1>(srcp_bottom, dstp_base, src_pitch, dst_pitch, width, height); break; | |
| 336 | ✗ | case 2: extract_packed_rgb_noalpha_channel_avx2<uint8_t, 2>(srcp_bottom, dstp_base, src_pitch, dst_pitch, width, height); break; | |
| 337 | } | ||
| 338 |
7/12✓ Branch 81 → 82 taken 6 times.
✗ Branch 81 → 87 not taken.
✓ Branch 82 → 83 taken 6 times.
✗ Branch 82 → 276 not taken.
✓ Branch 83 → 84 taken 3 times.
✓ Branch 83 → 87 taken 3 times.
✓ Branch 84 → 85 taken 3 times.
✗ Branch 84 → 87 not taken.
✗ Branch 85 → 86 not taken.
✓ Branch 85 → 87 taken 3 times.
✗ Branch 88 → 89 not taken.
✓ Branch 88 → 97 taken 6 times.
|
6 | } else if (avx2 && src_vi.IsRGB48() && channel_index <= 2 && width >= 16) { |
| 339 | // RGB48 AVX2: 16 pixels/iter; needs width >= 16 for the overlap-remainder to be valid. | ||
| 340 | ✗ | switch (channel_index) { | |
| 341 | ✗ | case 0: extract_packed_rgb_noalpha_channel_avx2<uint16_t, 0>(srcp_bottom, dstp_base, src_pitch, dst_pitch, width, height); break; | |
| 342 | ✗ | case 1: extract_packed_rgb_noalpha_channel_avx2<uint16_t, 1>(srcp_bottom, dstp_base, src_pitch, dst_pitch, width, height); break; | |
| 343 | ✗ | case 2: extract_packed_rgb_noalpha_channel_avx2<uint16_t, 2>(srcp_bottom, dstp_base, src_pitch, dst_pitch, width, height); break; | |
| 344 | } | ||
| 345 |
6/12✓ Branch 97 → 98 taken 6 times.
✗ Branch 97 → 103 not taken.
✓ Branch 98 → 99 taken 6 times.
✗ Branch 98 → 276 not taken.
✓ Branch 99 → 100 taken 6 times.
✗ Branch 99 → 102 not taken.
✓ Branch 100 → 101 taken 6 times.
✗ Branch 100 → 276 not taken.
✗ Branch 101 → 102 not taken.
✓ Branch 101 → 103 taken 6 times.
✗ Branch 104 → 105 not taken.
✓ Branch 104 → 127 taken 6 times.
|
6 | } else if (sse2 && (src_vi.IsRGB32() || src_vi.IsRGB64())) { |
| 346 | ✗ | if (src_vi.IsRGB32()) { | |
| 347 | ✗ | switch (channel_index) { | |
| 348 | ✗ | case 0: extract_packed_rgb32_channel_sse2<0>(srcp_bottom, dstp_base, src_pitch, dst_pitch, width, height); break; | |
| 349 | ✗ | case 1: extract_packed_rgb32_channel_sse2<1>(srcp_bottom, dstp_base, src_pitch, dst_pitch, width, height); break; | |
| 350 | ✗ | case 2: extract_packed_rgb32_channel_sse2<2>(srcp_bottom, dstp_base, src_pitch, dst_pitch, width, height); break; | |
| 351 | ✗ | case 3: extract_packed_rgb32_channel_sse2<3>(srcp_bottom, dstp_base, src_pitch, dst_pitch, width, height); break; | |
| 352 | } | ||
| 353 | } else { // RGB64 | ||
| 354 | ✗ | switch (channel_index) { | |
| 355 | ✗ | case 0: extract_packed_rgb64_channel_sse2<0>(srcp_bottom, dstp_base, src_pitch, dst_pitch, width, height); break; | |
| 356 | ✗ | case 1: extract_packed_rgb64_channel_sse2<1>(srcp_bottom, dstp_base, src_pitch, dst_pitch, width, height); break; | |
| 357 | ✗ | case 2: extract_packed_rgb64_channel_sse2<2>(srcp_bottom, dstp_base, src_pitch, dst_pitch, width, height); break; | |
| 358 | ✗ | case 3: extract_packed_rgb64_channel_sse2<3>(srcp_bottom, dstp_base, src_pitch, dst_pitch, width, height); break; | |
| 359 | } | ||
| 360 | } | ||
| 361 | } else | ||
| 362 | #endif | ||
| 363 | { // C fallback (RGB24/48 without AVX2, RGB32/64 without SSE2, or small widths) | ||
| 364 | 6 | const BYTE* srcp = srcp_bottom + byte_offset; | |
| 365 | 6 | BYTE* dstp = dstp_base; | |
| 366 |
2/2✓ Branch 127 → 128 taken 3 times.
✓ Branch 127 → 134 taken 3 times.
|
6 | if (pixelsize == 1) { |
| 367 |
2/2✓ Branch 133 → 129 taken 9 times.
✓ Branch 133 → 140 taken 3 times.
|
12 | for (int y = 0; y < height; ++y) { |
| 368 |
2/2✓ Branch 131 → 130 taken 45 times.
✓ Branch 131 → 132 taken 9 times.
|
54 | for (int x = 0; x < width; ++x) |
| 369 | 45 | dstp[x] = srcp[x * pixel_stride]; | |
| 370 | 9 | srcp -= src_pitch; | |
| 371 | 9 | dstp += dst_pitch; | |
| 372 | } | ||
| 373 | } else { // pixelsize == 2 (RGB48 / RGB64) | ||
| 374 |
2/2✓ Branch 139 → 135 taken 9 times.
✓ Branch 139 → 140 taken 3 times.
|
12 | for (int y = 0; y < height; ++y) { |
| 375 | 9 | uint16_t* dstp16 = reinterpret_cast<uint16_t*>(dstp); | |
| 376 |
2/2✓ Branch 137 → 136 taken 27 times.
✓ Branch 137 → 138 taken 9 times.
|
36 | for (int x = 0; x < width; ++x) |
| 377 | 27 | dstp16[x] = *reinterpret_cast<const uint16_t*>(srcp + x * pixel_stride); | |
| 378 | 9 | srcp -= src_pitch; | |
| 379 | 9 | dstp += dst_pitch; | |
| 380 | } | ||
| 381 | } | ||
| 382 | } | ||
| 383 | |||
| 384 |
1/2✓ Branch 140 → 141 taken 6 times.
✗ Branch 140 → 276 not taken.
|
6 | auto props = env->getFramePropsRW(dst); |
| 385 |
1/2✓ Branch 141 → 142 taken 6 times.
✗ Branch 141 → 276 not taken.
|
6 | env->propDeleteKey(props, "_ChromaLocation"); |
| 386 |
1/2✗ Branch 142 → 143 not taken.
✓ Branch 142 → 144 taken 6 times.
|
6 | if (mode == AToY8) |
| 387 | ✗ | env->propSetInt(props, "_ColorRange", ColorRange_Compat_e::AVS_COLORRANGE_FULL, AVSPropAppendMode::PROPAPPENDMODE_REPLACE); | |
| 388 |
1/2✗ Branch 144 → 145 not taken.
✓ Branch 144 → 146 taken 6 times.
|
6 | return dst; |
| 389 | ✗ | } | |
| 390 | |||
| 391 | 11 | bool NonYUY2orPackedRGBtoY8 = true; | |
| 392 | int target_plane, source_plane; | ||
| 393 |
5/8✗ Branch 147 → 148 not taken.
✓ Branch 147 → 149 taken 4 times.
✓ Branch 147 → 150 taken 4 times.
✓ Branch 147 → 151 taken 1 time.
✓ Branch 147 → 152 taken 1 time.
✓ Branch 147 → 153 taken 1 time.
✗ Branch 147 → 154 not taken.
✗ Branch 147 → 159 not taken.
|
11 | switch (mode) { |
| 394 | ✗ | case YToY8: source_plane = PLANAR_Y; target_plane = PLANAR_Y; break; | |
| 395 | 4 | case UToY8: source_plane = PLANAR_U; target_plane = PLANAR_Y; break; | |
| 396 | 4 | case VToY8: source_plane = PLANAR_V; target_plane = PLANAR_Y; break; | |
| 397 | 1 | case RToY8: source_plane = PLANAR_R; target_plane = PLANAR_G; break; // Planar RGB: GBR! | |
| 398 | 1 | case GToY8: source_plane = PLANAR_G; target_plane = PLANAR_G; break; | |
| 399 | 1 | case BToY8: source_plane = PLANAR_B; target_plane = PLANAR_G; break; | |
| 400 | ✗ | case AToY8: source_plane = PLANAR_A; target_plane = vi.IsYUVA() ? PLANAR_Y : PLANAR_G; break; // Planar RGB: GBR! | |
| 401 | ✗ | default: NonYUY2orPackedRGBtoY8 = false; | |
| 402 | } | ||
| 403 |
1/2✓ Branch 160 → 161 taken 11 times.
✗ Branch 160 → 182 not taken.
|
11 | if (NonYUY2orPackedRGBtoY8) { |
| 404 | // !! if offsets would be size_t, be cautious when you subtract two unsigned size_t variables | ||
| 405 |
2/4✓ Branch 162 → 163 taken 11 times.
✗ Branch 162 → 284 not taken.
✓ Branch 164 → 165 taken 11 times.
✗ Branch 164 → 284 not taken.
|
11 | const int offset = src->GetOffset(source_plane) - src->GetOffset(target_plane); // very naughty - don't do this at home!! |
| 406 | // Abuse Subframe to snatch the U/V/R/G/B/A plane | ||
| 407 |
5/10✓ Branch 166 → 167 taken 11 times.
✗ Branch 166 → 284 not taken.
✓ Branch 168 → 169 taken 11 times.
✗ Branch 168 → 284 not taken.
✓ Branch 170 → 171 taken 11 times.
✗ Branch 170 → 284 not taken.
✓ Branch 171 → 172 taken 11 times.
✗ Branch 171 → 281 not taken.
✓ Branch 172 → 173 taken 11 times.
✗ Branch 172 → 279 not taken.
|
11 | PVideoFrame sub = env->Subframe(src, offset, src->GetPitch(source_plane), src->GetRowSize(source_plane), src->GetHeight(source_plane)); |
| 408 | // We have a single plane. It's safe to mod props after a subframe. | ||
| 409 | // Remove props that are irrelevant to a single plane. | ||
| 410 | // _ChromaLocation, (_Primaries, _Transfer) | ||
| 411 |
1/2✓ Branch 174 → 175 taken 11 times.
✗ Branch 174 → 282 not taken.
|
11 | auto props = env->getFramePropsRW(sub); |
| 412 |
1/2✓ Branch 175 → 176 taken 11 times.
✗ Branch 175 → 282 not taken.
|
11 | env->propDeleteKey(props, "_ChromaLocation"); |
| 413 | // keep _Matrix (?) fixme: really? | ||
| 414 |
1/2✗ Branch 176 → 177 not taken.
✓ Branch 176 → 178 taken 11 times.
|
11 | if (mode == AToY8) // alpha is always full range, otherwise keep source |
| 415 | ✗ | env->propSetInt(props, "_ColorRange", ColorRange_Compat_e::AVS_COLORRANGE_FULL, AVSPropAppendMode::PROPAPPENDMODE_REPLACE); | |
| 416 | // else we keep _ColorRange value (if any) | ||
| 417 |
1/2✓ Branch 178 → 179 taken 11 times.
✗ Branch 178 → 282 not taken.
|
11 | return sub; |
| 418 | 11 | } | |
| 419 | |||
| 420 | ✗ | PVideoFrame dst = env->NewVideoFrameP(vi, &src); | |
| 421 | ✗ | if (mode == YUY2UToY8 || mode == YUY2VToY8 || vi.IsYUY2()) { | |
| 422 | ✗ | const BYTE* srcp = src->GetReadPtr(); | |
| 423 | ✗ | BYTE* dstp = dst->GetWritePtr(); | |
| 424 | ✗ | int src_pitch = src->GetPitch(); | |
| 425 | ✗ | int dst_pitch = dst->GetPitch(); | |
| 426 | ✗ | int pos = (mode == YUY2UToY8 || mode == UToY) ? 1 : 3; // YUYV U=offset#1 V=offset#3 | |
| 427 | |||
| 428 | ✗ | if (vi.IsYUY2()) { // YUY2 to YUY2 | |
| 429 | ✗ | int rowsize = dst->GetRowSize(); | |
| 430 | #ifdef INTEL_INTRINSICS | ||
| 431 | ✗ | if (env->GetCPUFlags() & CPUF_SSE2) { | |
| 432 | ✗ | yuy2_uvtoy_sse2(srcp, dstp, src_pitch, dst_pitch, rowsize, vi.height, pos); | |
| 433 | ✗ | return dst; | |
| 434 | } | ||
| 435 | #endif | ||
| 436 | |||
| 437 | ✗ | srcp += pos; | |
| 438 | ✗ | for (int y = 0; y < vi.height; ++y) { | |
| 439 | ✗ | for (int x = 0; x < rowsize; x += 2) { | |
| 440 | ✗ | dstp[x + 0] = srcp[2 * x]; | |
| 441 | ✗ | dstp[x + 1] = 0x80; | |
| 442 | } | ||
| 443 | ✗ | srcp += src_pitch; | |
| 444 | ✗ | dstp += dst_pitch; | |
| 445 | } | ||
| 446 | ✗ | return dst; | |
| 447 | } | ||
| 448 | |||
| 449 | // YUY2 to Y8 | ||
| 450 | |||
| 451 | ✗ | auto props = env->getFramePropsRW(dst); | |
| 452 | ✗ | env->propDeleteKey(props, "_ChromaLocation"); | |
| 453 | |||
| 454 | #ifdef INTEL_INTRINSICS | ||
| 455 | ✗ | if (env->GetCPUFlags() & CPUF_SSE2) { | |
| 456 | ✗ | yuy2_uvtoy8_sse2(srcp, dstp, src_pitch, dst_pitch, vi.width, vi.height, pos); | |
| 457 | ✗ | return dst; | |
| 458 | } | ||
| 459 | #endif | ||
| 460 | ✗ | srcp += pos; | |
| 461 | ✗ | for (int y = 0; y < vi.height; ++y) { | |
| 462 | ✗ | for (int x = 0; x < vi.width; ++x) { | |
| 463 | ✗ | dstp[x] = srcp[x * 4]; | |
| 464 | } | ||
| 465 | ✗ | srcp += src_pitch; | |
| 466 | ✗ | dstp += dst_pitch; | |
| 467 | } | ||
| 468 | ✗ | return dst; | |
| 469 | } | ||
| 470 | |||
| 471 | // Planar to Planar. Only two modes possible UToY and VToY | ||
| 472 | // Copy U or V to Y and set the other chroma planes to grey | ||
| 473 | ✗ | const int plane = mode == UToY ? PLANAR_U : PLANAR_V; | |
| 474 | ✗ | env->BitBlt(dst->GetWritePtr(PLANAR_Y), dst->GetPitch(PLANAR_Y), src->GetReadPtr(plane), | |
| 475 | src->GetPitch(plane), src->GetRowSize(plane), src->GetHeight(plane)); | ||
| 476 | |||
| 477 | // Clear chroma | ||
| 478 | ✗ | int pitch = dst->GetPitch(PLANAR_U); | |
| 479 | ✗ | int height = dst->GetHeight(PLANAR_U); | |
| 480 | ✗ | int rowsize = dst->GetRowSize(PLANAR_U); | |
| 481 | ✗ | BYTE* dstp_u = dst->GetWritePtr(PLANAR_U); | |
| 482 | ✗ | BYTE* dstp_v = dst->GetWritePtr(PLANAR_V); | |
| 483 | |||
| 484 | ✗ | if (vi.ComponentSize() == 1) { // 8bit | |
| 485 | ✗ | fill_chroma<BYTE>(dstp_u, dstp_v, height, rowsize, pitch, 0x80); | |
| 486 | } | ||
| 487 | ✗ | else if (vi.ComponentSize() == 2) { // 16bit | |
| 488 | ✗ | uint16_t grey_val = 1 << (vi.BitsPerComponent() - 1); // 0x8000 for 16 bit | |
| 489 | ✗ | fill_chroma<uint16_t>(dstp_u, dstp_v, height, rowsize, pitch, grey_val); | |
| 490 | } | ||
| 491 | else { // 32bit(float) | ||
| 492 | ✗ | float grey_val = uv8tof(128); | |
| 493 | ✗ | fill_chroma<float>(dstp_u, dstp_v, height, rowsize, pitch, grey_val); | |
| 494 | } | ||
| 495 | |||
| 496 | ✗ | return dst; | |
| 497 | 17 | } | |
| 498 | |||
| 499 | |||
| 500 | ✗ | AVSValue __cdecl SwapYToUV::CreateYToUV(AVSValue args, void* , IScriptEnvironment* env) | |
| 501 | { | ||
| 502 | ✗ | return new SwapYToUV(args[0].AsClip(), args[1].AsClip(), NULL , NULL, env); | |
| 503 | } | ||
| 504 | |||
| 505 | ✗ | AVSValue __cdecl SwapYToUV::CreateYToYUV(AVSValue args, void* , IScriptEnvironment* env) | |
| 506 | { | ||
| 507 | ✗ | return new SwapYToUV(args[0].AsClip(), args[1].AsClip(), args[2].AsClip(), NULL, env); | |
| 508 | } | ||
| 509 | |||
| 510 | ✗ | AVSValue __cdecl SwapYToUV::CreateYToYUVA(AVSValue args, void* , IScriptEnvironment* env) | |
| 511 | { | ||
| 512 | ✗ | return new SwapYToUV(args[0].AsClip(), args[1].AsClip(), args[2].AsClip(), args[3].AsClip(), env); | |
| 513 | } | ||
| 514 | |||
| 515 | 3 | SwapYToUV::SwapYToUV(PClip _child, PClip _clip, PClip _clipY, PClip _clipA, IScriptEnvironment* env) | |
| 516 |
5/10✓ Branch 2 → 3 taken 3 times.
✗ Branch 2 → 132 not taken.
✓ Branch 3 → 4 taken 3 times.
✗ Branch 3 → 130 not taken.
✓ Branch 5 → 6 taken 3 times.
✗ Branch 5 → 139 not taken.
✓ Branch 6 → 7 taken 3 times.
✗ Branch 6 → 137 not taken.
✓ Branch 7 → 8 taken 3 times.
✗ Branch 7 → 135 not taken.
|
3 | : GenericVideoFilter(_child), clip(_clip), clipY(_clipY), clipA(_clipA) |
| 517 | { | ||
| 518 |
5/12✓ Branch 8 → 9 taken 3 times.
✗ Branch 8 → 133 not taken.
✓ Branch 9 → 10 taken 3 times.
✗ Branch 9 → 15 not taken.
✓ Branch 10 → 11 taken 3 times.
✗ Branch 10 → 133 not taken.
✗ Branch 11 → 12 not taken.
✓ Branch 11 → 15 taken 3 times.
✗ Branch 13 → 14 not taken.
✗ Branch 13 → 15 not taken.
✗ Branch 16 → 17 not taken.
✓ Branch 16 → 18 taken 3 times.
|
3 | if(!(vi.IsYUVA() || vi.IsY()) && clipA) |
| 519 | ✗ | env->ThrowError("YToUV: Only Y or YUVA data accepted when alpha clip is provided"); // Y, YUV and YUY2 | |
| 520 |
3/10✓ Branch 18 → 19 taken 3 times.
✗ Branch 18 → 133 not taken.
✗ Branch 19 → 20 not taken.
✓ Branch 19 → 23 taken 3 times.
✗ Branch 20 → 21 not taken.
✗ Branch 20 → 133 not taken.
✗ Branch 21 → 22 not taken.
✗ Branch 21 → 23 not taken.
✗ Branch 24 → 25 not taken.
✓ Branch 24 → 26 taken 3 times.
|
3 | if (!vi.IsYUV() && !vi.IsYUVA()) |
| 521 | { | ||
| 522 | ✗ | env->ThrowError("YToUV: Only YUV or YUVA data accepted"); // Y, YUV and YUY2 | |
| 523 | } | ||
| 524 | |||
| 525 |
1/2✓ Branch 27 → 28 taken 3 times.
✗ Branch 27 → 133 not taken.
|
3 | const VideoInfo& vi2 = clip->GetVideoInfo(); |
| 526 |
1/2✗ Branch 28 → 29 not taken.
✓ Branch 28 → 30 taken 3 times.
|
3 | if (vi.height != vi2.height) |
| 527 | ✗ | env->ThrowError("YToUV: Clips do not have the same height (U & V mismatch) !"); | |
| 528 |
1/2✗ Branch 30 → 31 not taken.
✓ Branch 30 → 32 taken 3 times.
|
3 | if (vi.width != vi2.width) |
| 529 | ✗ | env->ThrowError("YToUV: Clips do not have the same width (U & V mismatch) !"); | |
| 530 |
3/6✓ Branch 32 → 33 taken 3 times.
✗ Branch 32 → 133 not taken.
✓ Branch 33 → 34 taken 3 times.
✗ Branch 33 → 133 not taken.
✗ Branch 34 → 35 not taken.
✓ Branch 34 → 36 taken 3 times.
|
3 | if (vi.IsYUY2() != vi2.IsYUY2()) |
| 531 | ✗ | env->ThrowError("YToUV: YUY2 Clips must have same colorspace (U & V mismatch) !"); | |
| 532 | |||
| 533 | // no third parameter: no Y clip | ||
| 534 |
2/2✓ Branch 37 → 38 taken 1 time.
✓ Branch 37 → 56 taken 2 times.
|
3 | if (!clipY) { |
| 535 |
2/4✓ Branch 38 → 39 taken 1 time.
✗ Branch 38 → 133 not taken.
✗ Branch 39 → 40 not taken.
✓ Branch 39 → 41 taken 1 time.
|
1 | if (vi.IsYUY2()) |
| 536 | ✗ | vi.width *= 2; | |
| 537 |
2/4✓ Branch 41 → 42 taken 1 time.
✗ Branch 41 → 133 not taken.
✓ Branch 42 → 43 taken 1 time.
✗ Branch 42 → 52 not taken.
|
1 | else if (vi.IsY()) { |
| 538 |
2/9✓ Branch 43 → 44 taken 1 time.
✗ Branch 43 → 133 not taken.
✓ Branch 44 → 45 taken 1 time.
✗ Branch 44 → 46 not taken.
✗ Branch 44 → 47 not taken.
✗ Branch 44 → 48 not taken.
✗ Branch 44 → 49 not taken.
✗ Branch 44 → 50 not taken.
✗ Branch 44 → 51 not taken.
|
1 | switch(vi.BitsPerComponent()) { |
| 539 | 1 | case 8: vi.pixel_type = VideoInfo::CS_YV24; break; | |
| 540 | ✗ | case 10: vi.pixel_type = VideoInfo::CS_YUV444P10; break; | |
| 541 | ✗ | case 12: vi.pixel_type = VideoInfo::CS_YUV444P12; break; | |
| 542 | ✗ | case 14: vi.pixel_type = VideoInfo::CS_YUV444P14; break; | |
| 543 | ✗ | case 16: vi.pixel_type = VideoInfo::CS_YUV444P16; break; | |
| 544 | ✗ | case 32: vi.pixel_type = VideoInfo::CS_YUV444PS; break; | |
| 545 | } | ||
| 546 | } | ||
| 547 | else { | ||
| 548 | ✗ | vi.height <<= vi.GetPlaneHeightSubsampling(PLANAR_U); | |
| 549 | ✗ | vi.width <<= vi.GetPlaneWidthSubsampling(PLANAR_U); | |
| 550 | } | ||
| 551 | 1 | return; | |
| 552 | } | ||
| 553 | |||
| 554 | // Y clip parameter exists, Y channel will be copied from that | ||
| 555 |
1/2✓ Branch 57 → 58 taken 2 times.
✗ Branch 57 → 133 not taken.
|
2 | const VideoInfo& vi3 = clipY->GetVideoInfo(); |
| 556 |
3/6✓ Branch 58 → 59 taken 2 times.
✗ Branch 58 → 133 not taken.
✓ Branch 59 → 60 taken 2 times.
✗ Branch 59 → 133 not taken.
✗ Branch 60 → 61 not taken.
✓ Branch 60 → 62 taken 2 times.
|
2 | if (vi.IsYUY2() != vi3.IsYUY2()) |
| 557 | ✗ | env->ThrowError("YToUV: YUY2 Clips must have same colorspace (UV & Y mismatch) !"); | |
| 558 | |||
| 559 |
2/4✓ Branch 62 → 63 taken 2 times.
✗ Branch 62 → 133 not taken.
✗ Branch 63 → 64 not taken.
✓ Branch 63 → 69 taken 2 times.
|
2 | if (vi.IsYUY2()) { |
| 560 | ✗ | if (vi3.height != vi.height) | |
| 561 | ✗ | env->ThrowError("YToUV: Y clip does not have the same height of the UV clips! (YUY2 mode)"); | |
| 562 | ✗ | vi.width *= 2; | |
| 563 | ✗ | if (vi3.width != vi.width) | |
| 564 | ✗ | env->ThrowError("YToUV: Y clip does not have the double width of the UV clips!"); | |
| 565 | ✗ | return; | |
| 566 | } | ||
| 567 | |||
| 568 |
2/2✓ Branch 70 → 71 taken 1 time.
✓ Branch 70 → 83 taken 1 time.
|
2 | if (clipA) { |
| 569 |
2/4✓ Branch 71 → 72 taken 1 time.
✗ Branch 71 → 133 not taken.
✗ Branch 72 → 73 not taken.
✓ Branch 72 → 74 taken 1 time.
|
1 | if(vi.IsYUY2()) |
| 570 | ✗ | env->ThrowError("YToUV: YUY2 not supported with alpha clip"); | |
| 571 |
1/2✓ Branch 75 → 76 taken 1 time.
✗ Branch 75 → 133 not taken.
|
1 | const VideoInfo& vi4 = clipA->GetVideoInfo(); |
| 572 |
2/4✓ Branch 76 → 77 taken 1 time.
✗ Branch 76 → 78 not taken.
✗ Branch 77 → 78 not taken.
✓ Branch 77 → 79 taken 1 time.
|
1 | if (vi4.width != vi3.width || vi4.height != vi3.height) // Y width == A width |
| 573 | ✗ | env->ThrowError("YToUV: different Y and A clip dimensions"); | |
| 574 |
3/6✓ Branch 79 → 80 taken 1 time.
✗ Branch 79 → 133 not taken.
✓ Branch 80 → 81 taken 1 time.
✗ Branch 80 → 133 not taken.
✗ Branch 81 → 82 not taken.
✓ Branch 81 → 83 taken 1 time.
|
1 | if(vi4.BitsPerComponent() != vi3.BitsPerComponent()) |
| 575 | ✗ | env->ThrowError("YToUV: different Y and A clip bit depth"); | |
| 576 | } | ||
| 577 | |||
| 578 | // Autogenerate destination colorformat | ||
| 579 |
2/9✓ Branch 83 → 84 taken 2 times.
✗ Branch 83 → 133 not taken.
✓ Branch 84 → 85 taken 2 times.
✗ Branch 84 → 90 not taken.
✗ Branch 84 → 95 not taken.
✗ Branch 84 → 100 not taken.
✗ Branch 84 → 105 not taken.
✗ Branch 84 → 110 not taken.
✗ Branch 84 → 115 not taken.
|
2 | switch (vi.BitsPerComponent()) |
| 580 | { // CS_Sub_Width_2 and CS_Sub_Height_2 are 0, vi bitfield can or'd if change needed | ||
| 581 |
2/2✓ Branch 86 → 87 taken 1 time.
✓ Branch 86 → 88 taken 1 time.
|
2 | case 8: vi.pixel_type = clipA ? VideoInfo::CS_YUVA420 : vi.pixel_type = VideoInfo::CS_YV12; break; |
| 582 | ✗ | case 10: vi.pixel_type = clipA ? VideoInfo::CS_YUVA420P10 : vi.pixel_type = VideoInfo::CS_YUV420P10; break; | |
| 583 | ✗ | case 12: vi.pixel_type = clipA ? VideoInfo::CS_YUVA420P12 : vi.pixel_type = VideoInfo::CS_YUV420P12; break; | |
| 584 | ✗ | case 14: vi.pixel_type = clipA ? VideoInfo::CS_YUVA420P14 : VideoInfo::CS_YUV420P14; break; | |
| 585 | ✗ | case 16: vi.pixel_type = clipA ? VideoInfo::CS_YUVA420P16 : VideoInfo::CS_YUV420P16; break; | |
| 586 | ✗ | case 32: vi.pixel_type = clipA ? VideoInfo::CS_YUVA420PS : VideoInfo::CS_YUV420PS; break; | |
| 587 | } | ||
| 588 | |||
| 589 |
1/2✓ Branch 115 → 116 taken 2 times.
✗ Branch 115 → 117 not taken.
|
2 | if (vi3.width == vi.width) // Y width == U width -> subsampling 1:1 |
| 590 | 2 | vi.pixel_type |= VideoInfo::CS_Sub_Width_1; | |
| 591 | ✗ | else if (vi3.width == vi.width * 2) // Y width == U width*2 -> horiz. subsampling 2 | |
| 592 | ✗ | vi.width *= 2; // YV12 subsampling CS_Sub_Width_2 is o.k. | |
| 593 | ✗ | else if (vi3.width == vi.width * 4) { // Y width == U width*4 -> horiz. subsampling 4 | |
| 594 | ✗ | vi.pixel_type |= VideoInfo::CS_Sub_Width_4; | |
| 595 | ✗ | vi.width *= 4; // final clip width is 3x of the U channel width | |
| 596 | } | ||
| 597 | else | ||
| 598 | ✗ | env->ThrowError("YToUV: Video width ratio does not match any internal colorspace."); | |
| 599 | |||
| 600 |
1/2✓ Branch 122 → 123 taken 2 times.
✗ Branch 122 → 124 not taken.
|
2 | if (vi3.height == vi.height) |
| 601 | 2 | vi.pixel_type |= VideoInfo::CS_Sub_Height_1; | |
| 602 | ✗ | else if (vi3.height == vi.height * 2) | |
| 603 | ✗ | vi.height *= 2; | |
| 604 | ✗ | else if (vi3.height == vi.height * 4) { | |
| 605 | ✗ | vi.pixel_type |= VideoInfo::CS_Sub_Height_4; | |
| 606 | ✗ | vi.height *= 4; | |
| 607 | } | ||
| 608 | else | ||
| 609 | ✗ | env->ThrowError("YToUV: Video height ratio does not match any internal colorspace."); | |
| 610 | ✗ | } | |
| 611 | |||
| 612 | template <bool has_clipY> | ||
| 613 | ✗ | static void yuy2_ytouv_c(const BYTE* src_y, const BYTE* src_u, const BYTE* src_v, BYTE* dstp, int pitch_y, int pitch_u, int pitch_v, int dst_pitch, int dst_rowsize, int height) | |
| 614 | { | ||
| 615 | ✗ | for (int y = 0; y < height; ++y) { | |
| 616 | ✗ | for (int x = 0; x < dst_rowsize; x += 4) { | |
| 617 | ✗ | dstp[x + 0] = has_clipY ? src_y[x] : 0x7e; | |
| 618 | ✗ | dstp[x + 1] = src_u[x / 2]; | |
| 619 | ✗ | dstp[x + 2] = has_clipY ? src_y[x + 2] : 0x7e; | |
| 620 | ✗ | dstp[x + 3] = src_v[x / 2]; | |
| 621 | } | ||
| 622 | ✗ | src_y += pitch_y; | |
| 623 | ✗ | src_u += pitch_u; | |
| 624 | ✗ | src_v += pitch_v; | |
| 625 | ✗ | dstp += dst_pitch; | |
| 626 | } | ||
| 627 | ✗ | } | |
| 628 | |||
| 629 | ✗ | PVideoFrame __stdcall SwapYToUV::GetFrame(int n, IScriptEnvironment* env) { | |
| 630 | ✗ | PVideoFrame src = child->GetFrame(n, env); | |
| 631 | ✗ | PVideoFrame dst = env->NewVideoFrameP(vi, &src); | |
| 632 | |||
| 633 | ✗ | if (vi.IsYUY2()) { | |
| 634 | ✗ | const BYTE* srcp_u = src->GetReadPtr(); | |
| 635 | ✗ | const int pitch_u = src->GetPitch(); | |
| 636 | |||
| 637 | ✗ | PVideoFrame srcv = clip->GetFrame(n, env); | |
| 638 | ✗ | const BYTE* srcp_v = srcv->GetReadPtr(); | |
| 639 | ✗ | const int pitch_v = srcv->GetPitch(); | |
| 640 | |||
| 641 | ✗ | BYTE* dstp = dst->GetWritePtr(); | |
| 642 | ✗ | const int rowsize = dst->GetRowSize(); | |
| 643 | ✗ | const int dst_pitch = dst->GetPitch(); | |
| 644 | |||
| 645 | ✗ | if (clipY) { | |
| 646 | ✗ | PVideoFrame srcy = clipY->GetFrame(n, env); | |
| 647 | ✗ | const BYTE* srcp_y = srcy->GetReadPtr(); | |
| 648 | ✗ | const int pitch_y = srcy->GetPitch(); | |
| 649 | #ifdef INTEL_INTRINSICS | ||
| 650 | ✗ | if (env->GetCPUFlags() & CPUF_SSE2) | |
| 651 | ✗ | yuy2_ytouv_sse2<true>(srcp_y, srcp_u, srcp_v, dstp, pitch_y, pitch_u, pitch_v, dst_pitch, rowsize, vi.height); | |
| 652 | else | ||
| 653 | #endif | ||
| 654 | ✗ | yuy2_ytouv_c<true>(srcp_y, srcp_u, srcp_v, dstp, pitch_y, pitch_u, pitch_v, dst_pitch, rowsize, vi.height); | |
| 655 | ✗ | } | |
| 656 | else | ||
| 657 | ✗ | yuy2_ytouv_c<false>(nullptr, srcp_u, srcp_v, dstp, 0, pitch_u, pitch_v, dst_pitch, rowsize, vi.height); | |
| 658 | |||
| 659 | ✗ | return dst; | |
| 660 | ✗ | } | |
| 661 | |||
| 662 | // Planar: | ||
| 663 | ✗ | env->BitBlt(dst->GetWritePtr(PLANAR_U), dst->GetPitch(PLANAR_U), | |
| 664 | src->GetReadPtr(PLANAR_Y), src->GetPitch(PLANAR_Y), src->GetRowSize(PLANAR_Y), src->GetHeight(PLANAR_Y)); | ||
| 665 | |||
| 666 | ✗ | src = clip->GetFrame(n, env); | |
| 667 | ✗ | env->BitBlt(dst->GetWritePtr(PLANAR_V), dst->GetPitch(PLANAR_V), | |
| 668 | src->GetReadPtr(PLANAR_Y), src->GetPitch(PLANAR_Y), src->GetRowSize(PLANAR_Y), src->GetHeight(PLANAR_Y)); | ||
| 669 | |||
| 670 | ✗ | if (clipA) { | |
| 671 | ✗ | int source_plane = (clipA->GetVideoInfo().IsPlanarRGBA() || | |
| 672 | ✗ | clipA->GetVideoInfo().IsYUVA()) ? PLANAR_A : PLANAR_Y; | |
| 673 | ✗ | src = clipA->GetFrame(n, env); | |
| 674 | ✗ | env->BitBlt(dst->GetWritePtr(PLANAR_A), dst->GetPitch(PLANAR_A), | |
| 675 | src->GetReadPtr(source_plane), src->GetPitch(source_plane), src->GetRowSize(source_plane), src->GetHeight(source_plane)); | ||
| 676 | } | ||
| 677 | |||
| 678 | ✗ | if (clipY) { | |
| 679 | ✗ | src = clipY->GetFrame(n, env); | |
| 680 | ✗ | env->BitBlt(dst->GetWritePtr(PLANAR_Y), dst->GetPitch(PLANAR_Y), | |
| 681 | src->GetReadPtr(PLANAR_Y), src->GetPitch(PLANAR_Y), src->GetRowSize(PLANAR_Y), src->GetHeight(PLANAR_Y)); | ||
| 682 | ✗ | return dst; | |
| 683 | } | ||
| 684 | |||
| 685 | // if no Y script was given, fill Y plane with neutral value | ||
| 686 | // Luma = 126 (0x7e) | ||
| 687 | ✗ | BYTE* dstp = dst->GetWritePtr(PLANAR_Y); | |
| 688 | ✗ | int rowsize = dst->GetRowSize(PLANAR_Y); | |
| 689 | ✗ | int pitch = dst->GetPitch(PLANAR_Y); | |
| 690 | |||
| 691 | ✗ | if (vi.ComponentSize() == 1) // 8bit | |
| 692 | ✗ | fill_plane<BYTE>(dstp, vi.height, rowsize, pitch, 0x7e); | |
| 693 | ✗ | else if (vi.ComponentSize() == 2) { // 16bit | |
| 694 | ✗ | uint16_t luma_val = 0x7e << (vi.BitsPerComponent() - 8); | |
| 695 | ✗ | fill_plane<uint16_t>(dstp, vi.height, rowsize, pitch, luma_val); | |
| 696 | } | ||
| 697 | else { // 32bit(float) | ||
| 698 | ✗ | fill_plane<float>(dstp, vi.height, rowsize, pitch, 126.0f / 256); | |
| 699 | } | ||
| 700 | |||
| 701 | ✗ | return dst; | |
| 702 | ✗ | } | |
| 703 | |||
| 704 | // AVS+: Combine planes free-style for all planar formats | ||
| 705 | ✗ | AVSValue __cdecl CombinePlanes::CreateCombinePlanes(AVSValue args, void* user_data, IScriptEnvironment* env) | |
| 706 | { | ||
| 707 | ✗ | int mode = (int)(intptr_t)(user_data); | |
| 708 | ✗ | int target_planes_param = 0 + mode; | |
| 709 | ✗ | int source_planes_param = 1 + mode; | |
| 710 | ✗ | int pixel_type_param = 2 + mode; | |
| 711 | ✗ | int sample_clip_param = 3 + mode; | |
| 712 | |||
| 713 | ✗ | bool hasSampleClip = args[sample_clip_param].Defined(); | |
| 714 | |||
| 715 | ✗ | return new CombinePlanes(args[0].AsClip(), | |
| 716 | ✗ | mode >= 2 ? args[1].AsClip() : nullptr, | |
| 717 | ✗ | mode >= 3 ? args[2].AsClip() : nullptr, | |
| 718 | ✗ | mode >= 4 ? args[3].AsClip() : nullptr, | |
| 719 | ✗ | hasSampleClip ? args[sample_clip_param].AsClip() : nullptr, | |
| 720 | ✗ | args[target_planes_param].AsString(""), | |
| 721 | ✗ | args[source_planes_param].AsString(""), | |
| 722 | ✗ | args[pixel_type_param].AsString(""), | |
| 723 | ✗ | env); | |
| 724 | } | ||
| 725 | |||
| 726 | 6 | CombinePlanes::CombinePlanes(PClip _child, PClip _clip2, PClip _clip3, PClip _clip4, PClip _sample, | |
| 727 | 6 | const char *_target_planes_str, const char *_source_planes_str, const char *_pixel_type, IScriptEnvironment* env) | |
| 728 |
6/14✓ Branch 2 → 3 taken 6 times.
✗ Branch 2 → 242 not taken.
✓ Branch 3 → 4 taken 6 times.
✗ Branch 3 → 240 not taken.
✓ Branch 6 → 7 taken 24 times.
✗ Branch 6 → 243 not taken.
✓ Branch 8 → 6 taken 24 times.
✓ Branch 8 → 9 taken 6 times.
✗ Branch 243 → 244 not taken.
✗ Branch 243 → 247 not taken.
✗ Branch 245 → 246 not taken.
✗ Branch 245 → 247 not taken.
✓ Branch 265 → 266 taken 4 times.
✗ Branch 265 → 270 not taken.
|
50 | : GenericVideoFilter(_child) |
| 729 | { | ||
| 730 |
1/2✓ Branch 9 → 10 taken 6 times.
✗ Branch 9 → 264 not taken.
|
6 | clips[0] = _child; |
| 731 |
1/2✓ Branch 10 → 11 taken 6 times.
✗ Branch 10 → 264 not taken.
|
6 | clips[1] = _clip2; |
| 732 |
1/2✓ Branch 11 → 12 taken 6 times.
✗ Branch 11 → 264 not taken.
|
6 | clips[2] = _clip3; |
| 733 |
1/2✓ Branch 12 → 13 taken 6 times.
✗ Branch 12 → 264 not taken.
|
6 | clips[3] = _clip4; |
| 734 | // planes(_planes), pixel_type(pixel_type) | ||
| 735 | // getting target video format | ||
| 736 | VideoInfo vi_default; | ||
| 737 | 6 | memset(&vi_default, 0, sizeof(VideoInfo)); | |
| 738 | |||
| 739 | 6 | bool videoFormatOverridden = false; | |
| 740 | |||
| 741 |
1/2✗ Branch 14 → 15 not taken.
✓ Branch 14 → 18 taken 6 times.
|
6 | if (_sample) { |
| 742 | ✗ | vi_default = _sample->GetVideoInfo(); | |
| 743 | ✗ | videoFormatOverridden = true; | |
| 744 | } | ||
| 745 | else { // no sample video: format from first clip | ||
| 746 |
1/2✓ Branch 19 → 20 taken 6 times.
✗ Branch 19 → 264 not taken.
|
6 | vi_default = child->GetVideoInfo(); |
| 747 | } | ||
| 748 | // 1.) sample clip 2.) first clip 3.) pixel_type override | ||
| 749 | // 4.) when input clips are greyscale, automatically use YUV(A)/RGB(A) depending on "planes" string | ||
| 750 |
2/2✓ Branch 21 → 22 taken 1 time.
✓ Branch 21 → 26 taken 5 times.
|
6 | if (*_pixel_type) { |
| 751 |
1/2✓ Branch 22 → 23 taken 1 time.
✗ Branch 22 → 264 not taken.
|
1 | int i_pixel_type = GetPixelTypeFromName(_pixel_type); |
| 752 |
1/2✗ Branch 23 → 24 not taken.
✓ Branch 23 → 25 taken 1 time.
|
1 | if (i_pixel_type == VideoInfo::CS_UNKNOWN) |
| 753 | ✗ | env->ThrowError("CombinePlanes: unknown pixel_type %s", _pixel_type); | |
| 754 | 1 | vi_default.pixel_type = i_pixel_type; | |
| 755 | 1 | videoFormatOverridden = true; | |
| 756 | } | ||
| 757 | |||
| 758 |
2/4✓ Branch 26 → 27 taken 6 times.
✗ Branch 26 → 264 not taken.
✗ Branch 27 → 28 not taken.
✓ Branch 27 → 29 taken 6 times.
|
6 | if (!vi_default.IsPlanar()) |
| 759 | ✗ | env->ThrowError("CombinePlanes: output clip video format is not planar!"); | |
| 760 | |||
| 761 | // autoconvert packed RGB or YUY2 inputs, in order to able to extract planes | ||
| 762 |
2/2✓ Branch 64 → 30 taken 24 times.
✓ Branch 64 → 65 taken 6 times.
|
30 | for (int i = 0; i < 4; i++) { |
| 763 |
2/2✓ Branch 31 → 32 taken 13 times.
✓ Branch 31 → 33 taken 11 times.
|
24 | if (!clips[i]) continue; |
| 764 |
1/2✓ Branch 34 → 35 taken 11 times.
✗ Branch 34 → 264 not taken.
|
11 | const VideoInfo &vi_test = clips[i]->GetVideoInfo(); |
| 765 |
3/10✓ Branch 35 → 36 taken 11 times.
✗ Branch 35 → 264 not taken.
✗ Branch 36 → 37 not taken.
✓ Branch 36 → 40 taken 11 times.
✗ Branch 37 → 38 not taken.
✗ Branch 37 → 264 not taken.
✗ Branch 38 → 39 not taken.
✗ Branch 38 → 40 not taken.
✗ Branch 41 → 42 not taken.
✓ Branch 41 → 51 taken 11 times.
|
11 | if (vi_test.IsRGB() && !vi_test.IsPlanar()) { |
| 766 | ✗ | bool hasAlpha = vi_test.NumComponents() == 4; | |
| 767 | ✗ | clips[i] = new PackedRGBtoPlanarRGB(clips[i], hasAlpha, hasAlpha); | |
| 768 | } | ||
| 769 |
2/4✓ Branch 51 → 52 taken 11 times.
✗ Branch 51 → 264 not taken.
✗ Branch 52 → 53 not taken.
✓ Branch 52 → 63 taken 11 times.
|
11 | else if (vi_test.IsYUY2()) { |
| 770 | ✗ | AVSValue emptyValue; | |
| 771 | ✗ | clips[i] = new ConvertYUY2ToYV16_or_Y(clips[i], false /*to_y*/, env); | |
| 772 | ✗ | } | |
| 773 | } | ||
| 774 | |||
| 775 | 6 | int source_plane_count = (int)strlen(_source_planes_str); // no check here, can be 0 | |
| 776 | 6 | int target_plane_count = (int)strlen(_target_planes_str); | |
| 777 |
1/2✗ Branch 65 → 66 not taken.
✓ Branch 65 → 67 taken 6 times.
|
6 | if (target_plane_count == 0) |
| 778 | ✗ | env->ThrowError("CombinePlanes: no target planes given!"); | |
| 779 |
5/6✓ Branch 68 → 69 taken 6 times.
✗ Branch 68 → 76 not taken.
✓ Branch 70 → 71 taken 4 times.
✓ Branch 70 → 75 taken 2 times.
✓ Branch 72 → 73 taken 1 time.
✓ Branch 72 → 74 taken 3 times.
|
6 | int clip_count = clips[3] ? 4 : clips[2] ? 3 : clips[1] ? 2 : 1; |
| 780 |
2/2✓ Branch 77 → 78 taken 1 time.
✓ Branch 77 → 79 taken 5 times.
|
6 | if (target_plane_count < clip_count) |
| 781 |
1/2✗ Branch 78 → 79 not taken.
✓ Branch 78 → 264 taken 1 time.
|
1 | env->ThrowError("CombinePlanes: more clips specified than target planes"); |
| 782 | |||
| 783 | // If no video format was forced and no input planes were given | ||
| 784 | // and all the source clips are Y, then | ||
| 785 | // we give it a try of easy greyscale->RGB(A) or YUV(A) conversion | ||
| 786 | // depending on the _target_planes_str | ||
| 787 | 5 | bool allIsGrey = true; | |
| 788 |
2/2✓ Branch 86 → 80 taken 8 times.
✓ Branch 86 → 87 taken 4 times.
|
12 | for (int i = 0; i < clip_count; i++) { |
| 789 |
4/6✓ Branch 81 → 82 taken 8 times.
✗ Branch 81 → 264 not taken.
✓ Branch 82 → 83 taken 8 times.
✗ Branch 82 → 264 not taken.
✓ Branch 83 → 84 taken 1 time.
✓ Branch 83 → 85 taken 7 times.
|
8 | if (!clips[i]->GetVideoInfo().IsY()) { |
| 790 | 1 | allIsGrey = false; | |
| 791 | 1 | break; | |
| 792 | } | ||
| 793 | } | ||
| 794 | |||
| 795 |
4/4✓ Branch 87 → 88 taken 4 times.
✓ Branch 87 → 113 taken 1 time.
✓ Branch 88 → 89 taken 3 times.
✓ Branch 88 → 113 taken 1 time.
|
5 | if (!videoFormatOverridden && source_plane_count == 0) { |
| 796 |
1/2✓ Branch 89 → 90 taken 3 times.
✗ Branch 89 → 113 not taken.
|
3 | if (allIsGrey) { |
| 797 | // special case. Figure out RGB(A) or YUV(A) or Y | ||
| 798 | 3 | bool allIsYUV = true; | |
| 799 | 3 | bool allIsRGB = true; | |
| 800 |
2/2✓ Branch 100 → 91 taken 8 times.
✓ Branch 100 → 101 taken 3 times.
|
11 | for (int i = 0; i < target_plane_count; i++) { |
| 801 | 8 | char ch = toupper(_target_planes_str[i]); | |
| 802 |
3/6✓ Branch 91 → 92 taken 8 times.
✗ Branch 91 → 94 not taken.
✓ Branch 92 → 93 taken 8 times.
✗ Branch 92 → 94 not taken.
✗ Branch 93 → 94 not taken.
✓ Branch 93 → 95 taken 8 times.
|
8 | if (ch == 'R' || ch == 'G' || ch == 'B') allIsYUV = false; |
| 803 |
6/6✓ Branch 95 → 96 taken 5 times.
✓ Branch 95 → 98 taken 3 times.
✓ Branch 96 → 97 taken 3 times.
✓ Branch 96 → 98 taken 2 times.
✓ Branch 97 → 98 taken 2 times.
✓ Branch 97 → 99 taken 1 time.
|
8 | if (ch == 'Y' || ch == 'U' || ch == 'V') allIsRGB = false; |
| 804 | } | ||
| 805 |
1/4✗ Branch 101 → 102 not taken.
✓ Branch 101 → 103 taken 3 times.
✗ Branch 102 → 103 not taken.
✗ Branch 102 → 113 not taken.
|
3 | if (allIsYUV || allIsRGB) { |
| 806 | int new_pixel_type; | ||
| 807 |
1/2✗ Branch 103 → 104 not taken.
✓ Branch 103 → 107 taken 3 times.
|
3 | if (allIsRGB) |
| 808 | ✗ | new_pixel_type = target_plane_count == 4 ? VideoInfo::CS_GENERIC_RGBAP : VideoInfo::CS_GENERIC_RGBP; | |
| 809 | else // if (allIsYUV) | ||
| 810 |
1/2✗ Branch 107 → 108 not taken.
✓ Branch 107 → 109 taken 3 times.
|
3 | new_pixel_type = target_plane_count == 4 ? VideoInfo::CS_GENERIC_YUVA444 : VideoInfo::CS_GENERIC_YUV444; |
| 811 |
1/2✓ Branch 111 → 112 taken 3 times.
✗ Branch 111 → 264 not taken.
|
3 | int bits_mask = clips[0]->GetVideoInfo().pixel_type & VideoInfo::CS_Sample_Bits_Mask; |
| 812 | 3 | new_pixel_type |= bits_mask; // copy bit-depth from the first clip | |
| 813 | 3 | vi_default.pixel_type = new_pixel_type; | |
| 814 | } | ||
| 815 | } | ||
| 816 | } | ||
| 817 | |||
| 818 | 5 | vi = vi_default; | |
| 819 | |||
| 820 |
2/4✓ Branch 113 → 114 taken 5 times.
✗ Branch 113 → 264 not taken.
✗ Branch 114 → 115 not taken.
✓ Branch 114 → 116 taken 5 times.
|
5 | if(!vi_default.IsPlanar()) |
| 821 | ✗ | env->ThrowError("CombinePlanes: target format must be planar!"); | |
| 822 | |||
| 823 |
3/4✓ Branch 116 → 117 taken 5 times.
✗ Branch 116 → 264 not taken.
✓ Branch 117 → 118 taken 1 time.
✓ Branch 117 → 120 taken 4 times.
|
5 | if(target_plane_count > vi_default.NumComponents()) |
| 824 |
2/4✓ Branch 118 → 119 taken 1 time.
✗ Branch 118 → 264 not taken.
✗ Branch 119 → 120 not taken.
✓ Branch 119 → 264 taken 1 time.
|
1 | env->ThrowError("CombinePlanes: too many target planes (%d)! Target video plane count is %d!", target_plane_count, vi_default.NumComponents()); |
| 825 | |||
| 826 |
3/4✓ Branch 120 → 121 taken 1 time.
✓ Branch 120 → 123 taken 3 times.
✗ Branch 121 → 122 not taken.
✓ Branch 121 → 123 taken 1 time.
|
4 | if(source_plane_count != 0 && source_plane_count != target_plane_count) |
| 827 | ✗ | env->ThrowError("CombinePlanes: source plane count must match with target plane count if provided!"); | |
| 828 | |||
| 829 | // useful for later check | ||
| 830 |
2/8✓ Branch 123 → 124 taken 4 times.
✗ Branch 123 → 264 not taken.
✗ Branch 124 → 125 not taken.
✓ Branch 124 → 127 taken 4 times.
✗ Branch 125 → 126 not taken.
✗ Branch 125 → 264 not taken.
✗ Branch 126 → 127 not taken.
✗ Branch 126 → 128 not taken.
|
4 | bool targetIsYUV = vi_default.IsYUV() || vi_default.IsYUVA(); |
| 831 |
4/8✓ Branch 129 → 130 taken 4 times.
✗ Branch 129 → 264 not taken.
✓ Branch 130 → 131 taken 4 times.
✗ Branch 130 → 133 not taken.
✓ Branch 131 → 132 taken 4 times.
✗ Branch 131 → 264 not taken.
✗ Branch 132 → 133 not taken.
✓ Branch 132 → 134 taken 4 times.
|
4 | bool targetHasAlpha = vi_default.IsYUVA() || vi_default.IsPlanarRGBA(); |
| 832 |
1/2✓ Branch 135 → 136 taken 4 times.
✗ Branch 135 → 264 not taken.
|
4 | bool targetIsY = vi_default.IsY(); |
| 833 | |||
| 834 | // class variables | ||
| 835 |
1/2✓ Branch 136 → 137 taken 4 times.
✗ Branch 136 → 264 not taken.
|
4 | bits_per_pixel = vi_default.BitsPerComponent(); |
| 836 |
1/2✓ Branch 137 → 138 taken 4 times.
✗ Branch 137 → 264 not taken.
|
4 | pixelsize = vi_default.ComponentSize(); |
| 837 | 4 | planecount = target_plane_count; | |
| 838 | |||
| 839 | // if source plane is given, use it otherwise assume these | ||
| 840 | 4 | const char * rgb_source_planes_str_def = "RGBA"; | |
| 841 |
2/2✓ Branch 138 → 139 taken 3 times.
✓ Branch 138 → 140 taken 1 time.
|
4 | const char * yuv_source_planes_str_def = allIsGrey ? "YYYY" : "YUVA"; |
| 842 | |||
| 843 | 4 | int last_clip_index = 0; | |
| 844 |
2/2✓ Branch 238 → 142 taken 10 times.
✓ Branch 238 → 239 taken 2 times.
|
12 | for (int i = 0; i < target_plane_count; i++) { |
| 845 | 10 | char ch = toupper(_target_planes_str[i]); | |
| 846 |
3/6✓ Branch 142 → 143 taken 10 times.
✗ Branch 142 → 145 not taken.
✓ Branch 143 → 144 taken 10 times.
✗ Branch 143 → 145 not taken.
✗ Branch 144 → 145 not taken.
✓ Branch 144 → 146 taken 10 times.
|
10 | bool isRGB = ch == 'R' || ch == 'G' || ch == 'B'; |
| 847 |
6/6✓ Branch 147 → 148 taken 6 times.
✓ Branch 147 → 150 taken 4 times.
✓ Branch 148 → 149 taken 3 times.
✓ Branch 148 → 150 taken 3 times.
✓ Branch 149 → 150 taken 2 times.
✓ Branch 149 → 151 taken 1 time.
|
10 | bool isYUV = ch == 'Y' || ch == 'U' || ch == 'V'; |
| 848 | 10 | bool isAlpha = ch == 'A'; | |
| 849 |
4/6✓ Branch 152 → 153 taken 10 times.
✗ Branch 152 → 156 not taken.
✓ Branch 153 → 154 taken 1 time.
✓ Branch 153 → 156 taken 9 times.
✓ Branch 154 → 155 taken 1 time.
✗ Branch 154 → 156 not taken.
|
10 | if(!isRGB && !isYUV && !isAlpha) |
| 850 |
1/2✗ Branch 155 → 156 not taken.
✓ Branch 155 → 263 taken 1 time.
|
1 | env->ThrowError("CombinePlanes: invalid plane definifion :%s", planes); |
| 851 |
6/16✓ Branch 156 → 157 taken 9 times.
✗ Branch 156 → 158 not taken.
✓ Branch 157 → 158 taken 9 times.
✗ Branch 157 → 164 not taken.
✗ Branch 158 → 159 not taken.
✓ Branch 158 → 160 taken 9 times.
✗ Branch 159 → 160 not taken.
✗ Branch 159 → 164 not taken.
✓ Branch 160 → 161 taken 9 times.
✗ Branch 160 → 162 not taken.
✓ Branch 161 → 162 taken 9 times.
✗ Branch 161 → 164 not taken.
✗ Branch 162 → 163 not taken.
✓ Branch 162 → 165 taken 9 times.
✗ Branch 163 → 164 not taken.
✗ Branch 163 → 165 not taken.
|
9 | if((targetIsYUV && isRGB) || (!targetIsYUV && isYUV) || (!targetHasAlpha && isAlpha) || (targetIsY && ch!='Y')) |
| 852 | ✗ | env->ThrowError("CombinePlanes: target has no such plane %c", ch); | |
| 853 | |||
| 854 | int current_target_plane; | ||
| 855 |
3/8✗ Branch 165 → 166 not taken.
✗ Branch 165 → 167 not taken.
✗ Branch 165 → 168 not taken.
✗ Branch 165 → 169 not taken.
✓ Branch 165 → 170 taken 4 times.
✓ Branch 165 → 171 taken 3 times.
✓ Branch 165 → 172 taken 2 times.
✗ Branch 165 → 173 not taken.
|
9 | switch (ch) { |
| 856 | ✗ | case 'R': current_target_plane = PLANAR_R; break; | |
| 857 | ✗ | case 'G': current_target_plane = PLANAR_G; break; | |
| 858 | ✗ | case 'B': current_target_plane = PLANAR_B; break; | |
| 859 | ✗ | case 'A': current_target_plane = PLANAR_A; break; | |
| 860 | 4 | case 'Y': current_target_plane = PLANAR_Y; break; | |
| 861 | 3 | case 'U': current_target_plane = PLANAR_U; break; | |
| 862 | 2 | case 'V': current_target_plane = PLANAR_V; break; | |
| 863 | } | ||
| 864 | 9 | target_planes[i] = current_target_plane; | |
| 865 |
1/2✓ Branch 173 → 174 taken 9 times.
✗ Branch 173 → 263 not taken.
|
9 | int target_plane_width = vi_default.width >> vi_default.GetPlaneWidthSubsampling(current_target_plane); |
| 866 |
1/2✓ Branch 174 → 175 taken 9 times.
✗ Branch 174 → 263 not taken.
|
9 | int target_plane_height = vi_default.height >> vi_default.GetPlaneHeightSubsampling(current_target_plane); |
| 867 | |||
| 868 |
2/2✓ Branch 176 → 177 taken 7 times.
✓ Branch 176 → 178 taken 2 times.
|
9 | if (clips[i]) // source clip count can be less than target planes count |
| 869 | 7 | last_clip_index = i; // last defined clip is used for the others | |
| 870 | |||
| 871 | // check source clips and optinally their plane order | ||
| 872 |
1/2✓ Branch 179 → 180 taken 9 times.
✗ Branch 179 → 263 not taken.
|
9 | VideoInfo src_vi = clips[last_clip_index]->GetVideoInfo(); |
| 873 | |||
| 874 |
2/4✓ Branch 180 → 181 taken 9 times.
✗ Branch 180 → 263 not taken.
✗ Branch 181 → 182 not taken.
✓ Branch 181 → 183 taken 9 times.
|
9 | if(src_vi.BitsPerComponent() != bits_per_pixel) |
| 875 | ✗ | env->ThrowError("CombinePlanes: source bit depth is different from %d", bits_per_pixel); | |
| 876 | |||
| 877 |
2/8✓ Branch 183 → 184 taken 9 times.
✗ Branch 183 → 263 not taken.
✗ Branch 184 → 185 not taken.
✓ Branch 184 → 187 taken 9 times.
✗ Branch 185 → 186 not taken.
✗ Branch 185 → 263 not taken.
✗ Branch 186 → 187 not taken.
✗ Branch 186 → 188 not taken.
|
9 | bool sourceIsYUV = src_vi.IsYUV() || src_vi.IsYUVA(); |
| 878 |
4/8✓ Branch 189 → 190 taken 9 times.
✗ Branch 189 → 263 not taken.
✓ Branch 190 → 191 taken 9 times.
✗ Branch 190 → 193 not taken.
✓ Branch 191 → 192 taken 9 times.
✗ Branch 191 → 263 not taken.
✗ Branch 192 → 193 not taken.
✓ Branch 192 → 194 taken 9 times.
|
9 | bool sourceHasAlpha = src_vi.IsYUVA() || src_vi.IsPlanarRGBA(); |
| 879 |
1/2✓ Branch 195 → 196 taken 9 times.
✗ Branch 195 → 263 not taken.
|
9 | bool sourceIsY = src_vi.IsY(); |
| 880 | // check source | ||
| 881 | // source_plane_count is either 0 or == target_plane_count | ||
| 882 | { | ||
| 883 | char ch; | ||
| 884 |
2/2✓ Branch 196 → 197 taken 3 times.
✓ Branch 196 → 198 taken 6 times.
|
9 | if (source_plane_count > 0) // optinal! defaults are filled |
| 885 | 3 | ch = toupper(_source_planes_str[i]); | |
| 886 |
1/2✓ Branch 198 → 199 taken 6 times.
✗ Branch 198 → 200 not taken.
|
6 | else if (sourceIsYUV) |
| 887 | 6 | ch = toupper(yuv_source_planes_str_def[i]); | |
| 888 | else // rgb | ||
| 889 | ✗ | ch = toupper(rgb_source_planes_str_def[i]); | |
| 890 |
3/6✓ Branch 201 → 202 taken 9 times.
✗ Branch 201 → 204 not taken.
✓ Branch 202 → 203 taken 9 times.
✗ Branch 202 → 204 not taken.
✗ Branch 203 → 204 not taken.
✓ Branch 203 → 205 taken 9 times.
|
9 | bool isRGB = ch == 'R' || ch == 'G' || ch == 'B'; |
| 891 |
5/6✓ Branch 206 → 207 taken 2 times.
✓ Branch 206 → 209 taken 7 times.
✓ Branch 207 → 208 taken 1 time.
✓ Branch 207 → 209 taken 1 time.
✓ Branch 208 → 209 taken 1 time.
✗ Branch 208 → 210 not taken.
|
9 | bool isYUV = ch == 'Y' || ch == 'U' || ch == 'V'; |
| 892 | 9 | bool isAlpha = ch == 'A'; | |
| 893 |
2/6✓ Branch 211 → 212 taken 9 times.
✗ Branch 211 → 215 not taken.
✗ Branch 212 → 213 not taken.
✓ Branch 212 → 215 taken 9 times.
✗ Branch 213 → 214 not taken.
✗ Branch 213 → 215 not taken.
|
9 | if(!isRGB && !isYUV && !isAlpha) |
| 894 | ✗ | env->ThrowError("CombinePlanes: invalid source plane definifion :%s", planes); | |
| 895 |
8/16✓ Branch 215 → 216 taken 9 times.
✗ Branch 215 → 217 not taken.
✓ Branch 216 → 217 taken 9 times.
✗ Branch 216 → 223 not taken.
✗ Branch 217 → 218 not taken.
✓ Branch 217 → 219 taken 9 times.
✗ Branch 218 → 219 not taken.
✗ Branch 218 → 223 not taken.
✓ Branch 219 → 220 taken 9 times.
✗ Branch 219 → 221 not taken.
✓ Branch 220 → 221 taken 9 times.
✗ Branch 220 → 223 not taken.
✓ Branch 221 → 222 taken 6 times.
✓ Branch 221 → 224 taken 3 times.
✗ Branch 222 → 223 not taken.
✓ Branch 222 → 224 taken 6 times.
|
9 | if((sourceIsYUV && isRGB) || (!sourceIsYUV && isYUV) || (!sourceHasAlpha && isAlpha) || (sourceIsY && ch!='Y')) |
| 896 | ✗ | env->ThrowError("CombinePlanes: source has no such plane %c", ch); | |
| 897 | // todo lambda | ||
| 898 | int current_source_plane; | ||
| 899 |
3/8✗ Branch 224 → 225 not taken.
✗ Branch 224 → 226 not taken.
✗ Branch 224 → 227 not taken.
✗ Branch 224 → 228 not taken.
✓ Branch 224 → 229 taken 7 times.
✓ Branch 224 → 230 taken 1 time.
✓ Branch 224 → 231 taken 1 time.
✗ Branch 224 → 232 not taken.
|
9 | switch (ch) { |
| 900 | ✗ | case 'R': current_source_plane = PLANAR_R; break; | |
| 901 | ✗ | case 'G': current_source_plane = PLANAR_G; break; | |
| 902 | ✗ | case 'B': current_source_plane = PLANAR_B; break; | |
| 903 | ✗ | case 'A': current_source_plane = PLANAR_A; break; | |
| 904 | 7 | case 'Y': current_source_plane = PLANAR_Y; break; | |
| 905 | 1 | case 'U': current_source_plane = PLANAR_U; break; | |
| 906 | 1 | case 'V': current_source_plane = PLANAR_V; break; | |
| 907 | } | ||
| 908 | 9 | source_planes[i] = current_source_plane; | |
| 909 | // check dimensions | ||
| 910 |
1/2✓ Branch 232 → 233 taken 9 times.
✗ Branch 232 → 263 not taken.
|
9 | int source_plane_width = src_vi.width >> src_vi.GetPlaneWidthSubsampling(current_source_plane); |
| 911 |
1/2✓ Branch 233 → 234 taken 9 times.
✗ Branch 233 → 263 not taken.
|
9 | int source_plane_height = src_vi.height >> src_vi.GetPlaneHeightSubsampling(current_source_plane); |
| 912 |
3/4✓ Branch 234 → 235 taken 8 times.
✓ Branch 234 → 236 taken 1 time.
✗ Branch 235 → 236 not taken.
✓ Branch 235 → 237 taken 8 times.
|
9 | if(source_plane_width != target_plane_width || source_plane_height != target_plane_height) |
| 913 |
1/2✗ Branch 236 → 237 not taken.
✓ Branch 236 → 263 taken 1 time.
|
1 | env->ThrowError("CombinePlanes: source and target plane dimensions are different"); |
| 914 | } | ||
| 915 | } | ||
| 916 |
2/2✓ Branch 267 → 268 taken 16 times.
✓ Branch 267 → 270 taken 4 times.
|
26 | } |
| 917 | |||
| 918 | |||
| 919 | 3 | PVideoFrame __stdcall CombinePlanes::GetFrame(int n, IScriptEnvironment* env) { | |
| 920 | |||
| 921 |
1/2✓ Branch 3 → 4 taken 3 times.
✗ Branch 3 → 254 not taken.
|
3 | VideoInfo vi_src = clips[0]->GetVideoInfo(); |
| 922 | |||
| 923 | // check if fast Subframe magic can replace BitBlt | ||
| 924 |
7/10✓ Branch 5 → 6 taken 2 times.
✓ Branch 5 → 10 taken 1 time.
✓ Branch 6 → 7 taken 2 times.
✗ Branch 6 → 254 not taken.
✓ Branch 7 → 8 taken 2 times.
✗ Branch 7 → 254 not taken.
✓ Branch 8 → 9 taken 2 times.
✗ Branch 8 → 10 not taken.
✓ Branch 11 → 12 taken 2 times.
✓ Branch 11 → 78 taken 1 time.
|
3 | if (!clips[1] && vi.NumComponents() <= vi_src.NumComponents()) // YUV<->RGB, YUVA<->RGBA YUV->Y |
| 925 | { | ||
| 926 | // we have only one clip, plane shuffle is valid if target has less plane that defined in source | ||
| 927 |
1/2✓ Branch 13 → 14 taken 2 times.
✗ Branch 13 → 238 not taken.
|
2 | PVideoFrame src = clips[0]->GetFrame(n, env); |
| 928 | |||
| 929 | 2 | int planes_y[4] = { PLANAR_Y, PLANAR_U, PLANAR_V, PLANAR_A }; | |
| 930 | 2 | int planes_r[4] = { PLANAR_G, PLANAR_B, PLANAR_R, PLANAR_A }; | |
| 931 |
2/8✓ Branch 14 → 15 taken 2 times.
✗ Branch 14 → 236 not taken.
✗ Branch 15 → 16 not taken.
✓ Branch 15 → 18 taken 2 times.
✗ Branch 16 → 17 not taken.
✗ Branch 16 → 236 not taken.
✗ Branch 17 → 18 not taken.
✗ Branch 17 → 19 not taken.
|
2 | int *planes = (vi_src.IsYUV() || vi_src.IsYUVA()) ? planes_y : planes_r; |
| 932 | |||
| 933 | int Offsets[4]; | ||
| 934 | int Pitches[4], NewPitches[4]; | ||
| 935 | int RowSizes[4], NewRowSizes[4]; | ||
| 936 | |||
| 937 | int RelOffsets[4]; | ||
| 938 | |||
| 939 |
3/4✓ Branch 28 → 29 taken 8 times.
✗ Branch 28 → 236 not taken.
✓ Branch 29 → 21 taken 6 times.
✓ Branch 29 → 30 taken 2 times.
|
8 | for (int i = 0; i < vi_src.NumComponents(); i++) { |
| 940 |
1/2✓ Branch 22 → 23 taken 6 times.
✗ Branch 22 → 236 not taken.
|
6 | Offsets[i] = src->GetOffset(planes[i]); |
| 941 |
1/2✓ Branch 24 → 25 taken 6 times.
✗ Branch 24 → 236 not taken.
|
6 | Pitches[i] = NewPitches[i] = src->GetPitch(planes[i]); |
| 942 |
1/2✓ Branch 26 → 27 taken 6 times.
✗ Branch 26 → 236 not taken.
|
6 | RowSizes[i] = NewRowSizes[i] = src->GetRowSize(planes[i]); |
| 943 | 6 | RelOffsets[i] = 0; | |
| 944 | } | ||
| 945 | |||
| 946 |
2/2✓ Branch 42 → 31 taken 6 times.
✓ Branch 42 → 43 taken 2 times.
|
8 | for (int i = 0; i < planecount; i++) { |
| 947 | 6 | int target_plane = target_planes[i]; | |
| 948 | 6 | int source_plane = source_planes[i]; | |
| 949 | int target_index, source_index; | ||
| 950 |
3/5✓ Branch 31 → 32 taken 2 times.
✓ Branch 31 → 33 taken 2 times.
✓ Branch 31 → 34 taken 2 times.
✗ Branch 31 → 35 not taken.
✗ Branch 31 → 36 not taken.
|
6 | switch (target_plane) { |
| 951 | 2 | case PLANAR_Y: case PLANAR_G: target_index = 0; break; | |
| 952 | 2 | case PLANAR_U: case PLANAR_B: target_index = 1; break; | |
| 953 | 2 | case PLANAR_V: case PLANAR_R: target_index = 2; break; | |
| 954 | ✗ | case PLANAR_A: target_index = 3; break; | |
| 955 | } | ||
| 956 |
3/5✓ Branch 36 → 37 taken 2 times.
✓ Branch 36 → 38 taken 2 times.
✓ Branch 36 → 39 taken 2 times.
✗ Branch 36 → 40 not taken.
✗ Branch 36 → 41 not taken.
|
6 | switch (source_plane) { |
| 957 | 2 | case PLANAR_Y: case PLANAR_G: source_index = 0; break; | |
| 958 | 2 | case PLANAR_U: case PLANAR_B: source_index = 1; break; | |
| 959 | 2 | case PLANAR_V: case PLANAR_R: source_index = 2; break; | |
| 960 | ✗ | case PLANAR_A: source_index = 3; break; | |
| 961 | } | ||
| 962 | // !! if offsets would be size_t, be cautious when you subtract two unsigned size_t variables | ||
| 963 | 6 | RelOffsets[target_index] = Offsets[source_index] - Offsets[target_index]; | |
| 964 | 6 | NewPitches[target_index] = Pitches[source_index]; | |
| 965 | 6 | NewRowSizes[target_index] = RowSizes[source_index]; | |
| 966 | // Y U V A | ||
| 967 | // 10 1010 2010 3010 offsets | ||
| 968 | // src: AUVY target: YVUA | ||
| 969 | // 3010-10 2010-1010 1010-2010 10-3010 | ||
| 970 | // 3000 =+1000 =-1000 =-3000 reloffsets | ||
| 971 | // 3010 2010 1010 10 new offsets inside | ||
| 972 | } | ||
| 973 | |||
| 974 |
1/4✓ Branch 43 → 44 taken 2 times.
✗ Branch 43 → 236 not taken.
✗ Branch 233 → 234 not taken.
✗ Branch 233 → 235 not taken.
|
2 | PVideoFrame dst; |
| 975 |
2/4✓ Branch 44 → 45 taken 2 times.
✗ Branch 44 → 233 not taken.
✗ Branch 45 → 46 not taken.
✓ Branch 45 → 54 taken 2 times.
|
2 | if (vi.NumComponents() == 4) { |
| 976 | ✗ | dst = env->SubframePlanarA(src, RelOffsets[0], NewPitches[0], NewRowSizes[0], src->GetHeight(), | |
| 977 | RelOffsets[1], RelOffsets[2], NewPitches[1], RelOffsets[3]); | ||
| 978 | } | ||
| 979 |
2/4✓ Branch 54 → 55 taken 2 times.
✗ Branch 54 → 233 not taken.
✓ Branch 55 → 56 taken 2 times.
✗ Branch 55 → 64 not taken.
|
2 | else if (vi.NumComponents() == 3) { |
| 980 |
4/8✓ Branch 57 → 58 taken 2 times.
✗ Branch 57 → 226 not taken.
✓ Branch 58 → 59 taken 2 times.
✗ Branch 58 → 225 not taken.
✓ Branch 59 → 60 taken 2 times.
✗ Branch 59 → 223 not taken.
✓ Branch 60 → 61 taken 2 times.
✗ Branch 60 → 221 not taken.
|
2 | dst = env->SubframePlanar(src, RelOffsets[0], NewPitches[0], NewRowSizes[0], src->GetHeight(), |
| 981 | RelOffsets[1], RelOffsets[2], NewPitches[1]); | ||
| 982 | } | ||
| 983 | else { | ||
| 984 | ✗ | dst = env->Subframe(src, RelOffsets[0], NewPitches[0], NewRowSizes[0], src->GetHeight()); | |
| 985 | } | ||
| 986 | |||
| 987 | // RGB(A)<->YUV(A) color space conversion can't be caught by Subframe...() | ||
| 988 |
1/2✓ Branch 73 → 74 taken 2 times.
✗ Branch 73 → 233 not taken.
|
2 | dst->AmendPixelType(vi.pixel_type); |
| 989 | |||
| 990 |
1/2✗ Branch 74 → 75 not taken.
✓ Branch 74 → 76 taken 2 times.
|
2 | return dst; |
| 991 | 2 | } | |
| 992 | |||
| 993 | // check if first clip could be used as the target clip | ||
| 994 |
1/2✓ Branch 79 → 80 taken 1 time.
✗ Branch 79 → 254 not taken.
|
2 | PVideoFrame src = clips[0]->GetFrame(n, env); |
| 995 |
2/6✓ Branch 81 → 82 taken 1 time.
✗ Branch 81 → 84 not taken.
✓ Branch 83 → 85 taken 1 time.
✗ Branch 83 → 252 not taken.
✗ Branch 84 → 85 not taken.
✗ Branch 84 → 252 not taken.
|
2 | PVideoFrame src1 = clips[1] ? clips[1]->GetFrame(n, env) : nullptr; |
| 996 | |||
| 997 | // case 1: when Y is kept from the original clip and other planes may be merged | ||
| 998 |
3/8✓ Branch 85 → 86 taken 1 time.
✗ Branch 85 → 250 not taken.
✗ Branch 86 → 87 not taken.
✓ Branch 86 → 89 taken 1 time.
✗ Branch 87 → 88 not taken.
✗ Branch 87 → 89 not taken.
✗ Branch 90 → 91 not taken.
✓ Branch 90 → 132 taken 1 time.
|
1 | if (vi_src.IsSameColorspace(vi) && target_planes[0] == source_planes[0]) { |
| 999 | // source (clip#0) has the same format as the target, and the first plane is the same | ||
| 1000 | // luma (Y) comes w/o BitBlt. Only U and V (and optionally A) is copied. | ||
| 1001 | ✗ | if (src->IsWritable()) // we are the only one | |
| 1002 | { | ||
| 1003 | ✗ | src->AmendPixelType(vi.pixel_type); | |
| 1004 | |||
| 1005 | ✗ | PVideoFrame src_other = nullptr; | |
| 1006 | ✗ | bool writeptr_obtained = false; | |
| 1007 | |||
| 1008 | ✗ | for (int i = 1; i < planecount; i++) { | |
| 1009 | ✗ | int target_plane = target_planes[i]; | |
| 1010 | ✗ | int source_plane = source_planes[i]; | |
| 1011 | |||
| 1012 | ✗ | if (clips[i]) { // source clips can be less than defined planes | |
| 1013 | ✗ | if (!writeptr_obtained) { | |
| 1014 | ✗ | src->GetWritePtr(PLANAR_Y); //Must be requested BUT only if we actually do something | |
| 1015 | ✗ | writeptr_obtained = true; | |
| 1016 | } | ||
| 1017 | |||
| 1018 | ✗ | if (i == 1) | |
| 1019 | ✗ | src_other = src1; // already requested | |
| 1020 | else | ||
| 1021 | ✗ | src_other = clips[i]->GetFrame(n, env); // last defined clip is used for the others | |
| 1022 | } | ||
| 1023 | |||
| 1024 | ✗ | if (src_other) { | |
| 1025 | ✗ | env->BitBlt(src->GetWritePtr(target_plane), src->GetPitch(target_plane), | |
| 1026 | src_other->GetReadPtr(source_plane), src_other->GetPitch(source_plane), src_other->GetRowSize(source_plane), src_other->GetHeight(source_plane)); | ||
| 1027 | } else { | ||
| 1028 | // we are still at the first (master) clip, no need for plane copy | ||
| 1029 | } | ||
| 1030 | } | ||
| 1031 | |||
| 1032 | ✗ | return src; | |
| 1033 | ✗ | } | |
| 1034 | } | ||
| 1035 |
3/6✓ Branch 133 → 134 taken 1 time.
✗ Branch 133 → 137 not taken.
✗ Branch 135 → 136 not taken.
✓ Branch 135 → 137 taken 1 time.
✗ Branch 138 → 139 not taken.
✓ Branch 138 → 178 taken 1 time.
|
1 | else if (clips[1] && !clips[2]){ |
| 1036 | // Try to optimize a MergeLuma case, where luma comes from Y (can even be a format of single plane), | ||
| 1037 | // Clip a's UV is kept. | ||
| 1038 | // MergeLuma's speed gain: if 'a' is IsWritable() then there is no need for BitBlt chroma planes. | ||
| 1039 | // We can only make a BitBlt from Y. | ||
| 1040 | // We'd like to recognize the following scenario | ||
| 1041 | // Output YUV: | ||
| 1042 | // - Y from clip #0 (format:Y) | ||
| 1043 | // - UV from clip #1 (format YUV420, same as output) | ||
| 1044 | // planes: "YUV" | ||
| 1045 | // | ||
| 1046 | // clip #0 format does not match with the output, maybe it is a single plane | ||
| 1047 | // let's try with the second (clip #1) if it can be used | ||
| 1048 | ✗ | if (clips[1]->GetVideoInfo().IsSameColorspace(vi) && | |
| 1049 | // the rest plane IDs are matching between source and target | ||
| 1050 | ✗ | vi.NumComponents() >= 3 && target_planes[1] == source_planes[1] && target_planes[2] == source_planes[2] && | |
| 1051 | ✗ | (vi.NumComponents() < 4 || (vi.NumComponents() == 4 && target_planes[3] == source_planes[3]))) | |
| 1052 | { | ||
| 1053 | ✗ | if (src1->IsWritable()) // we are the only one | |
| 1054 | { | ||
| 1055 | ✗ | src1->AmendPixelType(vi.pixel_type); | |
| 1056 | |||
| 1057 | ✗ | src1->GetWritePtr(PLANAR_Y); //Must be requested BUT only if we actually do something | |
| 1058 | |||
| 1059 | ✗ | int target_plane = target_planes[0]; | |
| 1060 | ✗ | int source_plane = source_planes[0]; | |
| 1061 | |||
| 1062 | // Copy from first clip | ||
| 1063 | ✗ | env->BitBlt(src1->GetWritePtr(target_plane), src1->GetPitch(target_plane), | |
| 1064 | src->GetReadPtr(source_plane), src->GetPitch(source_plane), src->GetRowSize(source_plane), src->GetHeight(source_plane)); | ||
| 1065 | |||
| 1066 | ✗ | env->copyFrameProps(src, src1); | |
| 1067 | |||
| 1068 | ✗ | return src1; | |
| 1069 | } | ||
| 1070 | } | ||
| 1071 | } | ||
| 1072 | |||
| 1073 |
1/2✓ Branch 178 → 179 taken 1 time.
✗ Branch 178 → 250 not taken.
|
2 | PVideoFrame dst = env->NewVideoFrame(vi); |
| 1074 | 1 | bool propCopied = false; | |
| 1075 | |||
| 1076 |
2/2✓ Branch 207 → 180 taken 3 times.
✓ Branch 207 → 208 taken 1 time.
|
4 | for (int i = 0; i < planecount; i++) { |
| 1077 |
1/2✓ Branch 181 → 182 taken 3 times.
✗ Branch 181 → 193 not taken.
|
3 | if (clips[i]) { // source clips can be less than defined planes |
| 1078 |
2/2✓ Branch 182 → 183 taken 2 times.
✓ Branch 182 → 190 taken 1 time.
|
3 | if (i > 0) { // clip #0 was already requested |
| 1079 |
2/2✓ Branch 183 → 184 taken 1 time.
✓ Branch 183 → 185 taken 1 time.
|
2 | if (i == 1) // clip #1 was already requested |
| 1080 |
1/2✓ Branch 184 → 190 taken 1 time.
✗ Branch 184 → 248 not taken.
|
1 | src = src1; |
| 1081 | else | ||
| 1082 |
2/4✓ Branch 186 → 187 taken 1 time.
✗ Branch 186 → 247 not taken.
✓ Branch 187 → 188 taken 1 time.
✗ Branch 187 → 245 not taken.
|
1 | src = clips[i]->GetFrame(n, env); // last defined clip is used for the others |
| 1083 | } | ||
| 1084 | |||
| 1085 |
2/2✓ Branch 190 → 191 taken 1 time.
✓ Branch 190 → 193 taken 2 times.
|
3 | if (!propCopied) { |
| 1086 |
1/2✓ Branch 191 → 192 taken 1 time.
✗ Branch 191 → 248 not taken.
|
1 | env->copyFrameProps(src, dst); |
| 1087 | 1 | propCopied = true; | |
| 1088 | } | ||
| 1089 | } | ||
| 1090 | |||
| 1091 | 3 | int target_plane = target_planes[i]; | |
| 1092 | 3 | int source_plane = source_planes[i]; | |
| 1093 | |||
| 1094 |
7/14✓ Branch 194 → 195 taken 3 times.
✗ Branch 194 → 248 not taken.
✓ Branch 196 → 197 taken 3 times.
✗ Branch 196 → 248 not taken.
✓ Branch 198 → 199 taken 3 times.
✗ Branch 198 → 248 not taken.
✓ Branch 200 → 201 taken 3 times.
✗ Branch 200 → 248 not taken.
✓ Branch 202 → 203 taken 3 times.
✗ Branch 202 → 248 not taken.
✓ Branch 204 → 205 taken 3 times.
✗ Branch 204 → 248 not taken.
✓ Branch 205 → 206 taken 3 times.
✗ Branch 205 → 248 not taken.
|
3 | env->BitBlt(dst->GetWritePtr(target_plane), dst->GetPitch(target_plane), |
| 1095 | src->GetReadPtr(source_plane), src->GetPitch(source_plane), src->GetRowSize(source_plane), src->GetHeight(source_plane)); | ||
| 1096 | } | ||
| 1097 | |||
| 1098 |
1/2✓ Branch 208 → 209 taken 1 time.
✗ Branch 208 → 248 not taken.
|
1 | return dst; |
| 1099 | } | ||
| 1100 |