filters/transform.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 | #include "transform.h" | ||
| 36 | #include "../convert/convert_matrix.h" | ||
| 37 | #include "../convert/convert_helper.h" | ||
| 38 | #include <avs/minmax.h> | ||
| 39 | #include "../core/bitblt.h" | ||
| 40 | #include <stdint.h> | ||
| 41 | #include "resample_functions.h" | ||
| 42 | #include "../convert/convert_planar.h" | ||
| 43 | #include "combine.h" | ||
| 44 | #include <vector> | ||
| 45 | #include <cmath> | ||
| 46 | |||
| 47 | |||
| 48 | |||
| 49 | /******************************************************************** | ||
| 50 | ***** Declare index of new filters for Avisynth's filter engine ***** | ||
| 51 | ********************************************************************/ | ||
| 52 | |||
| 53 | extern const AVSFunction Transform_filters[] = { | ||
| 54 | { "FlipVertical", BUILTIN_FUNC_PREFIX, "c", FlipVertical::Create }, | ||
| 55 | { "FlipHorizontal", BUILTIN_FUNC_PREFIX, "c", FlipHorizontal::Create }, | ||
| 56 | { "Crop", BUILTIN_FUNC_PREFIX, "ciiii[align]b", Crop::Create }, // left, top, width, height *OR* | ||
| 57 | // left, top, -right, -bottom (VDub style) | ||
| 58 | { "CropBottom", BUILTIN_FUNC_PREFIX, "ci", Create_CropBottom }, // bottom amount | ||
| 59 | { "AddBorders", BUILTIN_FUNC_PREFIX, "ciiii[color]i[color_yuv]i[resample]s[param1]f[param2]f[param3]f[r]i", AddBorders::Create }, // left, top, right, bottom [,color] [,color_yuv] | ||
| 60 | { "Letterbox", BUILTIN_FUNC_PREFIX, "cii[x1]i[x2]i[color]i[color_yuv]i[resample]s[param1]f[param2]f[param3]f[r]i", Create_Letterbox }, // top, bottom, [left], [right] [,color] [,color_yuv] | ||
| 61 | { 0 } | ||
| 62 | }; | ||
| 63 | |||
| 64 | |||
| 65 | |||
| 66 | |||
| 67 | |||
| 68 | /******************************** | ||
| 69 | ******* Flip Vertical ****** | ||
| 70 | ********************************/ | ||
| 71 | |||
| 72 | 5 | PVideoFrame FlipVertical::GetFrame(int n, IScriptEnvironment* env) { | |
| 73 |
1/2✓ Branch 3 → 4 taken 5 times.
✗ Branch 3 → 84 not taken.
|
5 | PVideoFrame src = child->GetFrame(n, env); |
| 74 |
1/2✓ Branch 4 → 5 taken 5 times.
✗ Branch 4 → 82 not taken.
|
5 | PVideoFrame dst = env->NewVideoFrameP(vi, &src); |
| 75 |
1/2✓ Branch 6 → 7 taken 5 times.
✗ Branch 6 → 80 not taken.
|
5 | const BYTE* srcp = src->GetReadPtr(); |
| 76 |
1/2✓ Branch 8 → 9 taken 5 times.
✗ Branch 8 → 80 not taken.
|
5 | BYTE* dstp = dst->GetWritePtr(); |
| 77 |
1/2✓ Branch 10 → 11 taken 5 times.
✗ Branch 10 → 80 not taken.
|
5 | int row_size = src->GetRowSize(); |
| 78 |
1/2✓ Branch 12 → 13 taken 5 times.
✗ Branch 12 → 80 not taken.
|
5 | int src_pitch = src->GetPitch(); |
| 79 |
1/2✓ Branch 14 → 15 taken 5 times.
✗ Branch 14 → 80 not taken.
|
5 | int dst_pitch = dst->GetPitch(); |
| 80 |
1/2✓ Branch 15 → 16 taken 5 times.
✗ Branch 15 → 80 not taken.
|
5 | env->BitBlt(dstp, dst_pitch, srcp + (vi.height-1) * src_pitch, -src_pitch, row_size, vi.height); |
| 81 | |||
| 82 |
4/8✓ Branch 16 → 17 taken 5 times.
✗ Branch 16 → 80 not taken.
✓ Branch 17 → 18 taken 5 times.
✗ Branch 17 → 20 not taken.
✓ Branch 18 → 19 taken 5 times.
✗ Branch 18 → 80 not taken.
✗ Branch 19 → 20 not taken.
✓ Branch 19 → 21 taken 5 times.
|
5 | bool isRGBPfamily = vi.IsPlanarRGB() || vi.IsPlanarRGBA(); |
| 83 |
1/2✗ Branch 22 → 23 not taken.
✓ Branch 22 → 24 taken 5 times.
|
5 | int planeUB = isRGBPfamily ? PLANAR_B : PLANAR_U; |
| 84 |
1/2✗ Branch 25 → 26 not taken.
✓ Branch 25 → 27 taken 5 times.
|
5 | int planeVR = isRGBPfamily ? PLANAR_R : PLANAR_V; |
| 85 | |||
| 86 |
3/4✓ Branch 29 → 30 taken 5 times.
✗ Branch 29 → 80 not taken.
✓ Branch 30 → 31 taken 3 times.
✓ Branch 30 → 77 taken 2 times.
|
5 | if (src->GetPitch(planeUB)) { |
| 87 |
1/2✓ Branch 32 → 33 taken 3 times.
✗ Branch 32 → 80 not taken.
|
3 | srcp = src->GetReadPtr(planeUB); |
| 88 |
1/2✓ Branch 34 → 35 taken 3 times.
✗ Branch 34 → 80 not taken.
|
3 | dstp = dst->GetWritePtr(planeUB); |
| 89 |
1/2✓ Branch 36 → 37 taken 3 times.
✗ Branch 36 → 80 not taken.
|
3 | row_size = src->GetRowSize(planeUB); |
| 90 |
1/2✓ Branch 38 → 39 taken 3 times.
✗ Branch 38 → 80 not taken.
|
3 | src_pitch = src->GetPitch(planeUB); |
| 91 |
1/2✓ Branch 40 → 41 taken 3 times.
✗ Branch 40 → 80 not taken.
|
3 | dst_pitch = dst->GetPitch(planeUB); |
| 92 |
3/6✓ Branch 42 → 43 taken 3 times.
✗ Branch 42 → 80 not taken.
✓ Branch 44 → 45 taken 3 times.
✗ Branch 44 → 80 not taken.
✓ Branch 45 → 46 taken 3 times.
✗ Branch 45 → 80 not taken.
|
3 | env->BitBlt(dstp, dst_pitch, srcp + (src->GetHeight(planeUB)-1) * src_pitch, -src_pitch, row_size, src->GetHeight(planeUB)); |
| 93 | |||
| 94 |
1/2✓ Branch 47 → 48 taken 3 times.
✗ Branch 47 → 80 not taken.
|
3 | srcp = src->GetReadPtr(planeVR); |
| 95 |
1/2✓ Branch 49 → 50 taken 3 times.
✗ Branch 49 → 80 not taken.
|
3 | dstp = dst->GetWritePtr(planeVR); |
| 96 |
3/6✓ Branch 51 → 52 taken 3 times.
✗ Branch 51 → 80 not taken.
✓ Branch 53 → 54 taken 3 times.
✗ Branch 53 → 80 not taken.
✓ Branch 54 → 55 taken 3 times.
✗ Branch 54 → 80 not taken.
|
3 | env->BitBlt(dstp, dst_pitch, srcp + (src->GetHeight(planeVR)-1) * src_pitch, -src_pitch, row_size, src->GetHeight(planeVR)); |
| 97 | |||
| 98 |
7/10✓ Branch 55 → 56 taken 3 times.
✗ Branch 55 → 80 not taken.
✓ Branch 56 → 57 taken 2 times.
✓ Branch 56 → 59 taken 1 time.
✓ Branch 57 → 58 taken 2 times.
✗ Branch 57 → 80 not taken.
✗ Branch 58 → 59 not taken.
✓ Branch 58 → 60 taken 2 times.
✓ Branch 61 → 62 taken 1 time.
✓ Branch 61 → 77 taken 2 times.
|
3 | if (vi.IsYUVA() || vi.IsPlanarRGBA()) |
| 99 | { | ||
| 100 |
1/2✓ Branch 63 → 64 taken 1 time.
✗ Branch 63 → 80 not taken.
|
1 | srcp = src->GetReadPtr(PLANAR_A); |
| 101 |
1/2✓ Branch 65 → 66 taken 1 time.
✗ Branch 65 → 80 not taken.
|
1 | dstp = dst->GetWritePtr(PLANAR_A); |
| 102 |
1/2✓ Branch 67 → 68 taken 1 time.
✗ Branch 67 → 80 not taken.
|
1 | row_size = src->GetRowSize(PLANAR_A); |
| 103 |
1/2✓ Branch 69 → 70 taken 1 time.
✗ Branch 69 → 80 not taken.
|
1 | src_pitch = src->GetPitch(PLANAR_A); |
| 104 |
1/2✓ Branch 71 → 72 taken 1 time.
✗ Branch 71 → 80 not taken.
|
1 | dst_pitch = dst->GetPitch(PLANAR_A); |
| 105 |
3/6✓ Branch 73 → 74 taken 1 time.
✗ Branch 73 → 80 not taken.
✓ Branch 75 → 76 taken 1 time.
✗ Branch 75 → 80 not taken.
✓ Branch 76 → 77 taken 1 time.
✗ Branch 76 → 80 not taken.
|
1 | env->BitBlt(dstp, dst_pitch, srcp + (src->GetHeight(PLANAR_A)-1) * src_pitch, -src_pitch, row_size, src->GetHeight(PLANAR_A)); |
| 106 | } | ||
| 107 | } | ||
| 108 | 5 | return dst; | |
| 109 | 5 | } | |
| 110 | |||
| 111 | ✗ | AVSValue __cdecl FlipVertical::Create(AVSValue args, void*, IScriptEnvironment* env) | |
| 112 | { | ||
| 113 | AVS_UNUSED(env); | ||
| 114 | ✗ | return new FlipVertical(args[0].AsClip()); | |
| 115 | } | ||
| 116 | |||
| 117 | |||
| 118 | |||
| 119 | /******************************** | ||
| 120 | ******* Flip Horizontal ****** | ||
| 121 | ********************************/ | ||
| 122 | |||
| 123 | template<typename pixel_t> | ||
| 124 | 18 | static void flip_horizontal_plane_c(BYTE* dstp, const BYTE* srcp, int dst_pitch, int src_pitch, int width, int height) { | |
| 125 | 18 | width = width / sizeof(pixel_t); // width is called with GetRowSize value | |
| 126 | 18 | dstp += (width - 1) * sizeof(pixel_t); | |
| 127 |
6/10void flip_horizontal_plane_c<float>(unsigned char*, unsigned char const*, int, int, int, int):
✗ Branch 7 → 3 not taken.
✗ Branch 7 → 8 not taken.
void flip_horizontal_plane_c<unsigned char>(unsigned char*, unsigned char const*, int, int, int, int):
✓ Branch 7 → 3 taken 57 times.
✓ Branch 7 → 8 taken 14 times.
void flip_horizontal_plane_c<unsigned int>(unsigned char*, unsigned char const*, int, int, int, int):
✗ Branch 7 → 3 not taken.
✗ Branch 7 → 8 not taken.
void flip_horizontal_plane_c<unsigned long>(unsigned char*, unsigned char const*, int, int, int, int):
✓ Branch 7 → 3 taken 4 times.
✓ Branch 7 → 8 taken 1 time.
void flip_horizontal_plane_c<unsigned short>(unsigned char*, unsigned char const*, int, int, int, int):
✓ Branch 7 → 3 taken 12 times.
✓ Branch 7 → 8 taken 3 times.
|
91 | for (int y = 0; y < height; y++) { // Loop planar luma. |
| 128 |
6/10void flip_horizontal_plane_c<float>(unsigned char*, unsigned char const*, int, int, int, int):
✗ Branch 5 → 4 not taken.
✗ Branch 5 → 6 not taken.
void flip_horizontal_plane_c<unsigned char>(unsigned char*, unsigned char const*, int, int, int, int):
✓ Branch 5 → 4 taken 357 times.
✓ Branch 5 → 6 taken 57 times.
void flip_horizontal_plane_c<unsigned int>(unsigned char*, unsigned char const*, int, int, int, int):
✗ Branch 5 → 4 not taken.
✗ Branch 5 → 6 not taken.
void flip_horizontal_plane_c<unsigned long>(unsigned char*, unsigned char const*, int, int, int, int):
✓ Branch 5 → 4 taken 20 times.
✓ Branch 5 → 6 taken 4 times.
void flip_horizontal_plane_c<unsigned short>(unsigned char*, unsigned char const*, int, int, int, int):
✓ Branch 5 → 4 taken 84 times.
✓ Branch 5 → 6 taken 12 times.
|
534 | for (int x = 0; x < width; x++) { |
| 129 | 461 | (reinterpret_cast<pixel_t *>(dstp))[-x] = (reinterpret_cast<const pixel_t *>(srcp))[x]; | |
| 130 | } | ||
| 131 | 73 | srcp += src_pitch; | |
| 132 | 73 | dstp += dst_pitch; | |
| 133 | } | ||
| 134 | 18 | } | |
| 135 | |||
| 136 | 7 | PVideoFrame FlipHorizontal::GetFrame(int n, IScriptEnvironment* env) { | |
| 137 |
1/2✓ Branch 3 → 4 taken 7 times.
✗ Branch 3 → 118 not taken.
|
7 | PVideoFrame src = child->GetFrame(n, env); |
| 138 |
1/2✓ Branch 4 → 5 taken 7 times.
✗ Branch 4 → 116 not taken.
|
7 | PVideoFrame dst = env->NewVideoFrameP(vi, &src); |
| 139 |
1/2✓ Branch 6 → 7 taken 7 times.
✗ Branch 6 → 114 not taken.
|
7 | const BYTE* srcp = src->GetReadPtr(); |
| 140 |
1/2✓ Branch 8 → 9 taken 7 times.
✗ Branch 8 → 114 not taken.
|
7 | BYTE* dstp = dst->GetWritePtr(); |
| 141 |
1/2✓ Branch 10 → 11 taken 7 times.
✗ Branch 10 → 114 not taken.
|
7 | int width = src->GetRowSize(); |
| 142 |
1/2✓ Branch 12 → 13 taken 7 times.
✗ Branch 12 → 114 not taken.
|
7 | int src_pitch = src->GetPitch(); |
| 143 |
1/2✓ Branch 14 → 15 taken 7 times.
✗ Branch 14 → 114 not taken.
|
7 | int dst_pitch = dst->GetPitch(); |
| 144 |
1/2✓ Branch 16 → 17 taken 7 times.
✗ Branch 16 → 114 not taken.
|
7 | int height = src->GetHeight(); |
| 145 |
2/4✓ Branch 17 → 18 taken 7 times.
✗ Branch 17 → 114 not taken.
✗ Branch 18 → 19 not taken.
✓ Branch 18 → 26 taken 7 times.
|
7 | if (vi.IsYUY2()) { // Avoid flipping UV in YUY2 mode. |
| 146 | ✗ | srcp += width; | |
| 147 | ✗ | srcp -= 4; | |
| 148 | ✗ | for (int y = 0; y<height; y++) { | |
| 149 | ✗ | for (int x = 0; x<width; x += 4) { | |
| 150 | ✗ | dstp[x] = srcp[-x+2]; | |
| 151 | ✗ | dstp[x+1] = srcp[-x+1]; | |
| 152 | ✗ | dstp[x+2] = srcp[-x]; | |
| 153 | ✗ | dstp[x+3] = srcp[-x+3]; | |
| 154 | } | ||
| 155 | ✗ | srcp += src_pitch; | |
| 156 | ✗ | dstp += dst_pitch; | |
| 157 | } | ||
| 158 | ✗ | return dst; | |
| 159 | } | ||
| 160 | |||
| 161 | typedef void(*FlipFuncPtr) (BYTE * dstp, const BYTE * srcp, int dst_pitch, int src_pitch, int width, int height); | ||
| 162 | FlipFuncPtr flip_h_func; | ||
| 163 | |||
| 164 |
3/4✓ Branch 26 → 27 taken 7 times.
✗ Branch 26 → 114 not taken.
✓ Branch 27 → 28 taken 5 times.
✓ Branch 27 → 88 taken 2 times.
|
7 | if (vi.IsPlanar()) { |
| 165 |
3/5✓ Branch 28 → 29 taken 5 times.
✗ Branch 28 → 114 not taken.
✓ Branch 29 → 30 taken 4 times.
✓ Branch 29 → 31 taken 1 time.
✗ Branch 29 → 32 not taken.
|
5 | switch (vi.ComponentSize()) // AVS16 |
| 166 | { | ||
| 167 | 4 | case 1: flip_h_func = flip_horizontal_plane_c<uint8_t>; break; | |
| 168 | 1 | case 2: flip_h_func = flip_horizontal_plane_c<uint16_t>; break; | |
| 169 | ✗ | default: // 4 float | |
| 170 | ✗ | flip_h_func = flip_horizontal_plane_c<float>; break; | |
| 171 | } | ||
| 172 |
1/2✓ Branch 33 → 34 taken 5 times.
✗ Branch 33 → 114 not taken.
|
5 | flip_h_func(dstp, srcp, dst_pitch, src_pitch, width, height); |
| 173 | |||
| 174 |
5/8✓ Branch 34 → 35 taken 5 times.
✗ Branch 34 → 114 not taken.
✓ Branch 35 → 36 taken 4 times.
✓ Branch 35 → 38 taken 1 time.
✓ Branch 36 → 37 taken 4 times.
✗ Branch 36 → 114 not taken.
✗ Branch 37 → 38 not taken.
✓ Branch 37 → 39 taken 4 times.
|
5 | bool isRGBPfamily = vi.IsPlanarRGB() || vi.IsPlanarRGBA(); |
| 175 |
2/2✓ Branch 40 → 41 taken 1 time.
✓ Branch 40 → 42 taken 4 times.
|
5 | int planeUB = isRGBPfamily ? PLANAR_B : PLANAR_U; |
| 176 |
2/2✓ Branch 43 → 44 taken 1 time.
✓ Branch 43 → 45 taken 4 times.
|
5 | int planeVR = isRGBPfamily ? PLANAR_R : PLANAR_V; |
| 177 | |||
| 178 |
2/4✓ Branch 47 → 48 taken 5 times.
✗ Branch 47 → 114 not taken.
✓ Branch 48 → 49 taken 5 times.
✗ Branch 48 → 87 not taken.
|
5 | if (src->GetPitch(planeUB)) { |
| 179 |
1/2✓ Branch 50 → 51 taken 5 times.
✗ Branch 50 → 114 not taken.
|
5 | srcp = src->GetReadPtr(planeUB); |
| 180 |
1/2✓ Branch 52 → 53 taken 5 times.
✗ Branch 52 → 114 not taken.
|
5 | dstp = dst->GetWritePtr(planeUB); |
| 181 |
1/2✓ Branch 54 → 55 taken 5 times.
✗ Branch 54 → 114 not taken.
|
5 | width = src->GetRowSize(planeUB); |
| 182 |
1/2✓ Branch 56 → 57 taken 5 times.
✗ Branch 56 → 114 not taken.
|
5 | src_pitch = src->GetPitch(planeUB); |
| 183 |
1/2✓ Branch 58 → 59 taken 5 times.
✗ Branch 58 → 114 not taken.
|
5 | dst_pitch = dst->GetPitch(planeUB); |
| 184 |
1/2✓ Branch 60 → 61 taken 5 times.
✗ Branch 60 → 114 not taken.
|
5 | height = src->GetHeight(planeUB); |
| 185 |
1/2✓ Branch 61 → 62 taken 5 times.
✗ Branch 61 → 114 not taken.
|
5 | flip_h_func(dstp, srcp, dst_pitch, src_pitch, width, height); |
| 186 | |||
| 187 |
1/2✓ Branch 63 → 64 taken 5 times.
✗ Branch 63 → 114 not taken.
|
5 | srcp = src->GetReadPtr(planeVR); |
| 188 |
1/2✓ Branch 65 → 66 taken 5 times.
✗ Branch 65 → 114 not taken.
|
5 | dstp = dst->GetWritePtr(planeVR); |
| 189 | |||
| 190 |
1/2✓ Branch 66 → 67 taken 5 times.
✗ Branch 66 → 114 not taken.
|
5 | flip_h_func(dstp, srcp, dst_pitch, src_pitch, width, height); |
| 191 | |||
| 192 |
7/10✓ Branch 67 → 68 taken 5 times.
✗ Branch 67 → 114 not taken.
✓ Branch 68 → 69 taken 3 times.
✓ Branch 68 → 71 taken 2 times.
✓ Branch 69 → 70 taken 3 times.
✗ Branch 69 → 114 not taken.
✗ Branch 70 → 71 not taken.
✓ Branch 70 → 72 taken 3 times.
✓ Branch 73 → 74 taken 2 times.
✓ Branch 73 → 87 taken 3 times.
|
5 | if (vi.IsYUVA() || vi.IsPlanarRGBA()) |
| 193 | { | ||
| 194 |
1/2✓ Branch 75 → 76 taken 2 times.
✗ Branch 75 → 114 not taken.
|
2 | srcp = src->GetReadPtr(PLANAR_A); |
| 195 |
1/2✓ Branch 77 → 78 taken 2 times.
✗ Branch 77 → 114 not taken.
|
2 | dstp = dst->GetWritePtr(PLANAR_A); |
| 196 |
1/2✓ Branch 79 → 80 taken 2 times.
✗ Branch 79 → 114 not taken.
|
2 | width = src->GetRowSize(PLANAR_A); |
| 197 |
1/2✓ Branch 81 → 82 taken 2 times.
✗ Branch 81 → 114 not taken.
|
2 | src_pitch = src->GetPitch(PLANAR_A); |
| 198 |
1/2✓ Branch 83 → 84 taken 2 times.
✗ Branch 83 → 114 not taken.
|
2 | dst_pitch = dst->GetPitch(PLANAR_A); |
| 199 |
1/2✓ Branch 85 → 86 taken 2 times.
✗ Branch 85 → 114 not taken.
|
2 | height = src->GetHeight(PLANAR_A); |
| 200 |
1/2✓ Branch 86 → 87 taken 2 times.
✗ Branch 86 → 114 not taken.
|
2 | flip_h_func(dstp, srcp, dst_pitch, src_pitch, width, height); |
| 201 | } | ||
| 202 | } | ||
| 203 | 5 | return dst; | |
| 204 | } | ||
| 205 | |||
| 206 | // width is GetRowSize | ||
| 207 |
2/4✓ Branch 88 → 89 taken 2 times.
✗ Branch 88 → 114 not taken.
✗ Branch 89 → 90 not taken.
✓ Branch 89 → 91 taken 2 times.
|
2 | if (vi.IsRGB32()) { // fast method |
| 208 | ✗ | flip_h_func = flip_horizontal_plane_c<uint32_t>; | |
| 209 | ✗ | flip_h_func(dstp, srcp, dst_pitch, src_pitch, width, height); | |
| 210 | } | ||
| 211 |
3/4✓ Branch 91 → 92 taken 2 times.
✗ Branch 91 → 114 not taken.
✓ Branch 92 → 93 taken 1 time.
✓ Branch 92 → 94 taken 1 time.
|
2 | else if (vi.IsRGB64()) { |
| 212 | 1 | flip_h_func = flip_horizontal_plane_c<uint64_t>; | |
| 213 |
1/2✓ Branch 93 → 110 taken 1 time.
✗ Branch 93 → 114 not taken.
|
1 | flip_h_func(dstp, srcp, dst_pitch, src_pitch, width, height); |
| 214 | } | ||
| 215 |
2/4✓ Branch 94 → 95 taken 1 time.
✗ Branch 94 → 114 not taken.
✓ Branch 95 → 96 taken 1 time.
✗ Branch 95 → 102 not taken.
|
1 | else if (vi.IsRGB24()) { |
| 216 | 1 | dstp += width - 3; | |
| 217 |
2/2✓ Branch 101 → 97 taken 4 times.
✓ Branch 101 → 110 taken 1 time.
|
5 | for (int y = 0; y < height; y++) { |
| 218 |
2/2✓ Branch 99 → 98 taken 20 times.
✓ Branch 99 → 100 taken 4 times.
|
24 | for (int x = 0; x < width; x += 3) { |
| 219 | 20 | dstp[-x + 0] = srcp[x + 0]; | |
| 220 | 20 | dstp[-x + 1] = srcp[x + 1]; | |
| 221 | 20 | dstp[-x + 2] = srcp[x + 2]; | |
| 222 | } | ||
| 223 | 4 | srcp += src_pitch; | |
| 224 | 4 | dstp += dst_pitch; | |
| 225 | } | ||
| 226 | } | ||
| 227 | ✗ | else if (vi.IsRGB48()) { | |
| 228 | ✗ | dstp += width - 3 * sizeof(uint16_t); | |
| 229 | ✗ | for (int y = 0; y < height; y++) { | |
| 230 | ✗ | for (int x = 0; x < width / 2 /*sizeof(uint16_t)*/; x += 3) { | |
| 231 | ✗ | reinterpret_cast<uint16_t*>(dstp)[-x + 0] = reinterpret_cast<const uint16_t*>(srcp)[x + 0]; | |
| 232 | ✗ | reinterpret_cast<uint16_t*>(dstp)[-x + 1] = reinterpret_cast<const uint16_t*>(srcp)[x + 1]; | |
| 233 | ✗ | reinterpret_cast<uint16_t*>(dstp)[-x + 2] = reinterpret_cast<const uint16_t*>(srcp)[x + 2]; | |
| 234 | } | ||
| 235 | ✗ | srcp += src_pitch; | |
| 236 | ✗ | dstp += dst_pitch; | |
| 237 | } | ||
| 238 | } | ||
| 239 | 2 | return dst; | |
| 240 | 7 | } | |
| 241 | |||
| 242 | |||
| 243 | ✗ | AVSValue __cdecl FlipHorizontal::Create(AVSValue args, void*, IScriptEnvironment* env) | |
| 244 | { | ||
| 245 | AVS_UNUSED(env); | ||
| 246 | ✗ | return new FlipHorizontal(args[0].AsClip()); | |
| 247 | } | ||
| 248 | |||
| 249 | |||
| 250 | |||
| 251 | |||
| 252 | |||
| 253 | /****************************** | ||
| 254 | ******* Crop Filter ****** | ||
| 255 | *****************************/ | ||
| 256 | |||
| 257 | 6 | Crop::Crop(int _left, int _top, int _width, int _height, bool _align, PClip _child, IScriptEnvironment* env) | |
| 258 |
2/4✓ Branch 2 → 3 taken 6 times.
✗ Branch 2 → 57 not taken.
✓ Branch 3 → 4 taken 6 times.
✗ Branch 3 → 55 not taken.
|
6 | : GenericVideoFilter(_child), align(FRAME_ALIGN - 1), xsub(0), ysub(0) |
| 259 | { | ||
| 260 | AVS_UNUSED(_align); | ||
| 261 | // _align parameter exists only for the backward compatibility. | ||
| 262 | |||
| 263 | /* Negative values -> VDub-style syntax | ||
| 264 | Namely, Crop(a, b, -c, -d) will crop c pixels from the right and d pixels from the bottom. | ||
| 265 | Flags on 0 values too since AFAICT it's much more useful to this syntax than the standard one. */ | ||
| 266 |
2/4✓ Branch 5 → 6 taken 6 times.
✗ Branch 5 → 7 not taken.
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 6 times.
|
6 | if ( (_left<0) || (_top<0) ) |
| 267 | ✗ | env->ThrowError("Crop: Top and Left must be more than 0"); | |
| 268 | |||
| 269 |
1/2✗ Branch 8 → 9 not taken.
✓ Branch 8 → 10 taken 6 times.
|
6 | if (_width <= 0) |
| 270 | ✗ | _width = vi.width - _left + _width; | |
| 271 |
1/2✗ Branch 10 → 11 not taken.
✓ Branch 10 → 12 taken 6 times.
|
6 | if (_height <= 0) |
| 272 | ✗ | _height = vi.height - _top + _height; | |
| 273 | |||
| 274 |
1/2✗ Branch 12 → 13 not taken.
✓ Branch 12 → 14 taken 6 times.
|
6 | if (_width <=0) |
| 275 | ✗ | env->ThrowError("Crop: Destination width is 0 or less."); | |
| 276 | |||
| 277 |
1/2✗ Branch 14 → 15 not taken.
✓ Branch 14 → 16 taken 6 times.
|
6 | if (_height<=0) |
| 278 | ✗ | env->ThrowError("Crop: Destination height is 0 or less."); | |
| 279 | |||
| 280 |
2/4✓ Branch 16 → 17 taken 6 times.
✗ Branch 16 → 18 not taken.
✗ Branch 17 → 18 not taken.
✓ Branch 17 → 19 taken 6 times.
|
6 | if (_left + _width > vi.width || _top + _height > vi.height) |
| 281 | ✗ | env->ThrowError("Crop: you cannot use crop to enlarge or 'shift' a clip"); | |
| 282 | |||
| 283 |
5/8✓ Branch 19 → 20 taken 6 times.
✗ Branch 19 → 58 not taken.
✓ Branch 20 → 21 taken 5 times.
✓ Branch 20 → 23 taken 1 time.
✓ Branch 21 → 22 taken 5 times.
✗ Branch 21 → 58 not taken.
✗ Branch 22 → 23 not taken.
✓ Branch 22 → 24 taken 5 times.
|
6 | isRGBPfamily = vi.IsPlanarRGB() || vi.IsPlanarRGBA(); |
| 284 |
5/8✓ Branch 25 → 26 taken 6 times.
✗ Branch 25 → 58 not taken.
✓ Branch 26 → 27 taken 6 times.
✗ Branch 26 → 29 not taken.
✓ Branch 27 → 28 taken 6 times.
✗ Branch 27 → 58 not taken.
✓ Branch 28 → 29 taken 1 time.
✓ Branch 28 → 30 taken 5 times.
|
6 | hasAlpha = vi.IsPlanarRGBA() || vi.IsYUVA(); |
| 285 | |||
| 286 |
8/10✓ Branch 31 → 32 taken 6 times.
✗ Branch 31 → 58 not taken.
✓ Branch 32 → 33 taken 3 times.
✓ Branch 32 → 35 taken 3 times.
✓ Branch 33 → 34 taken 3 times.
✗ Branch 33 → 58 not taken.
✓ Branch 34 → 35 taken 1 time.
✓ Branch 34 → 36 taken 2 times.
✓ Branch 37 → 38 taken 4 times.
✓ Branch 37 → 51 taken 2 times.
|
6 | if (vi.IsYUV() || vi.IsYUVA()) { |
| 287 |
2/4✓ Branch 38 → 39 taken 4 times.
✗ Branch 38 → 58 not taken.
✓ Branch 39 → 40 taken 4 times.
✗ Branch 39 → 43 not taken.
|
4 | if (vi.NumComponents() > 1) { |
| 288 |
1/2✓ Branch 40 → 41 taken 4 times.
✗ Branch 40 → 58 not taken.
|
4 | xsub=vi.GetPlaneWidthSubsampling(PLANAR_U); |
| 289 |
1/2✓ Branch 41 → 42 taken 4 times.
✗ Branch 41 → 58 not taken.
|
4 | ysub=vi.GetPlaneHeightSubsampling(PLANAR_U); |
| 290 | } | ||
| 291 | 4 | const int xmask = (1 << xsub) - 1; | |
| 292 | 4 | const int ymask = (1 << ysub) - 1; | |
| 293 | |||
| 294 | // YUY2, etc, ... can only crop to even pixel boundaries horizontally | ||
| 295 |
1/2✗ Branch 43 → 44 not taken.
✓ Branch 43 → 45 taken 4 times.
|
4 | if (_left & xmask) |
| 296 | ✗ | env->ThrowError("Crop: YUV image can only be cropped by Mod %d (left side).", xmask+1); | |
| 297 |
1/2✗ Branch 45 → 46 not taken.
✓ Branch 45 → 47 taken 4 times.
|
4 | if (_width & xmask) |
| 298 | ✗ | env->ThrowError("Crop: YUV image can only be cropped by Mod %d (right side).", xmask+1); | |
| 299 |
1/2✗ Branch 47 → 48 not taken.
✓ Branch 47 → 49 taken 4 times.
|
4 | if (_top & ymask) |
| 300 | ✗ | env->ThrowError("Crop: YUV image can only be cropped by Mod %d (top).", ymask+1); | |
| 301 |
1/2✗ Branch 49 → 50 not taken.
✓ Branch 49 → 53 taken 4 times.
|
4 | if (_height & ymask) |
| 302 | ✗ | env->ThrowError("Crop: YUV image can only be cropped by Mod %d (bottom).", ymask+1); | |
| 303 |
2/2✓ Branch 51 → 52 taken 1 time.
✓ Branch 51 → 53 taken 1 time.
|
2 | } else if (!isRGBPfamily) { |
| 304 | // RGB is upside-down | ||
| 305 | 1 | _top = vi.height - _height - _top; | |
| 306 | } | ||
| 307 | |||
| 308 |
1/2✓ Branch 53 → 54 taken 6 times.
✗ Branch 53 → 58 not taken.
|
6 | left_bytes = vi.BytesFromPixels(_left); |
| 309 | 6 | top = _top; | |
| 310 | 6 | vi.width = _width; | |
| 311 | 6 | vi.height = _height; | |
| 312 | |||
| 313 | 6 | } | |
| 314 | |||
| 315 | |||
| 316 | 6 | PVideoFrame Crop::GetFrame(int n, IScriptEnvironment* env_) | |
| 317 | { | ||
| 318 |
1/2✓ Branch 2 → 3 taken 6 times.
✗ Branch 2 → 162 not taken.
|
6 | InternalEnvironment* IEnv = GetAndRevealCamouflagedEnv(env_); // though here a static cast would do |
| 319 | 6 | IScriptEnvironment* env = static_cast<IScriptEnvironment*>(IEnv); | |
| 320 | |||
| 321 |
1/2✓ Branch 4 → 5 taken 6 times.
✗ Branch 4 → 162 not taken.
|
6 | PVideoFrame frame = child->GetFrame(n, env); |
| 322 | |||
| 323 |
2/2✓ Branch 5 → 6 taken 1 time.
✓ Branch 5 → 7 taken 5 times.
|
6 | int plane0 = isRGBPfamily ? PLANAR_G : PLANAR_Y; |
| 324 |
2/2✓ Branch 8 → 9 taken 1 time.
✓ Branch 8 → 10 taken 5 times.
|
6 | int plane1 = isRGBPfamily ? PLANAR_B : PLANAR_U; |
| 325 |
2/2✓ Branch 11 → 12 taken 1 time.
✓ Branch 11 → 13 taken 5 times.
|
6 | int plane2 = isRGBPfamily ? PLANAR_R : PLANAR_V; |
| 326 | |||
| 327 |
2/4✓ Branch 15 → 16 taken 6 times.
✗ Branch 15 → 160 not taken.
✓ Branch 17 → 18 taken 6 times.
✗ Branch 17 → 160 not taken.
|
6 | const BYTE* srcp0 = frame->GetReadPtr(plane0) + top * frame->GetPitch(plane0) + left_bytes; |
| 328 |
2/4✓ Branch 19 → 20 taken 6 times.
✗ Branch 19 → 160 not taken.
✓ Branch 21 → 22 taken 6 times.
✗ Branch 21 → 160 not taken.
|
6 | const BYTE* srcp1 = frame->GetReadPtr(plane1) + (top>>ysub) * frame->GetPitch(plane1) + (left_bytes>>xsub); |
| 329 |
2/4✓ Branch 23 → 24 taken 6 times.
✗ Branch 23 → 160 not taken.
✓ Branch 25 → 26 taken 6 times.
✗ Branch 25 → 160 not taken.
|
6 | const BYTE* srcp2 = frame->GetReadPtr(plane2) + (top>>ysub) * frame->GetPitch(plane2) + (left_bytes>>xsub); |
| 330 | |||
| 331 | size_t _align; | ||
| 332 | |||
| 333 |
10/14✓ Branch 27 → 28 taken 6 times.
✗ Branch 27 → 160 not taken.
✓ Branch 28 → 29 taken 5 times.
✓ Branch 28 → 34 taken 1 time.
✓ Branch 29 → 30 taken 5 times.
✗ Branch 29 → 160 not taken.
✓ Branch 30 → 31 taken 1 time.
✓ Branch 30 → 33 taken 4 times.
✓ Branch 31 → 32 taken 1 time.
✗ Branch 31 → 160 not taken.
✓ Branch 32 → 33 taken 1 time.
✗ Branch 32 → 34 not taken.
✓ Branch 35 → 36 taken 5 times.
✓ Branch 35 → 37 taken 1 time.
|
6 | if (frame->GetPitch(plane1) && (!vi.IsYV12() || env->PlanarChromaAlignment(IScriptEnvironment::PlanarChromaAlignmentTest))) |
| 334 | 5 | _align = this->align & ((size_t)srcp0|(size_t)srcp1|(size_t)srcp2); | |
| 335 | else | ||
| 336 | 1 | _align = this->align & (size_t)srcp0; | |
| 337 | |||
| 338 | // Ignore alignment for CUDA. Clip should be explicitly aligned by Align() | ||
| 339 |
4/8✓ Branch 38 → 39 taken 6 times.
✗ Branch 38 → 42 not taken.
✓ Branch 39 → 40 taken 6 times.
✗ Branch 39 → 160 not taken.
✓ Branch 40 → 41 taken 6 times.
✗ Branch 40 → 42 not taken.
✓ Branch 43 → 44 taken 6 times.
✗ Branch 43 → 97 not taken.
|
6 | if (0 != _align && (IEnv->GetDeviceType() == DEV_TYPE_CPU)) { |
| 340 |
1/4✓ Branch 44 → 45 taken 6 times.
✗ Branch 44 → 160 not taken.
✗ Branch 148 → 149 not taken.
✗ Branch 148 → 150 not taken.
|
6 | PVideoFrame dst = env->NewVideoFrameP(vi, &frame, (int)align+1); |
| 341 | |||
| 342 |
6/12✓ Branch 46 → 47 taken 6 times.
✗ Branch 46 → 148 not taken.
✓ Branch 48 → 49 taken 6 times.
✗ Branch 48 → 148 not taken.
✓ Branch 50 → 51 taken 6 times.
✗ Branch 50 → 148 not taken.
✓ Branch 52 → 53 taken 6 times.
✗ Branch 52 → 148 not taken.
✓ Branch 54 → 55 taken 6 times.
✗ Branch 54 → 148 not taken.
✓ Branch 55 → 56 taken 6 times.
✗ Branch 55 → 148 not taken.
|
6 | env->BitBlt(dst->GetWritePtr(plane0), dst->GetPitch(plane0), srcp0, |
| 343 | frame->GetPitch(plane0), dst->GetRowSize(plane0), dst->GetHeight(plane0)); | ||
| 344 | |||
| 345 |
6/12✓ Branch 57 → 58 taken 6 times.
✗ Branch 57 → 148 not taken.
✓ Branch 59 → 60 taken 6 times.
✗ Branch 59 → 148 not taken.
✓ Branch 61 → 62 taken 6 times.
✗ Branch 61 → 148 not taken.
✓ Branch 63 → 64 taken 6 times.
✗ Branch 63 → 148 not taken.
✓ Branch 65 → 66 taken 6 times.
✗ Branch 65 → 148 not taken.
✓ Branch 66 → 67 taken 6 times.
✗ Branch 66 → 148 not taken.
|
6 | env->BitBlt(dst->GetWritePtr(plane1), dst->GetPitch(plane1), srcp1, |
| 346 | frame->GetPitch(plane1), dst->GetRowSize(plane1), dst->GetHeight(plane1)); | ||
| 347 | |||
| 348 |
6/12✓ Branch 68 → 69 taken 6 times.
✗ Branch 68 → 148 not taken.
✓ Branch 70 → 71 taken 6 times.
✗ Branch 70 → 148 not taken.
✓ Branch 72 → 73 taken 6 times.
✗ Branch 72 → 148 not taken.
✓ Branch 74 → 75 taken 6 times.
✗ Branch 74 → 148 not taken.
✓ Branch 76 → 77 taken 6 times.
✗ Branch 76 → 148 not taken.
✓ Branch 77 → 78 taken 6 times.
✗ Branch 77 → 148 not taken.
|
6 | env->BitBlt(dst->GetWritePtr(plane2), dst->GetPitch(plane2), srcp2, |
| 349 | frame->GetPitch(plane2), dst->GetRowSize(plane2), dst->GetHeight(plane2)); | ||
| 350 | |||
| 351 |
2/2✓ Branch 78 → 79 taken 1 time.
✓ Branch 78 → 94 taken 5 times.
|
6 | if(hasAlpha) |
| 352 |
8/16✓ Branch 80 → 81 taken 1 time.
✗ Branch 80 → 148 not taken.
✓ Branch 82 → 83 taken 1 time.
✗ Branch 82 → 148 not taken.
✓ Branch 84 → 85 taken 1 time.
✗ Branch 84 → 148 not taken.
✓ Branch 86 → 87 taken 1 time.
✗ Branch 86 → 148 not taken.
✓ Branch 88 → 89 taken 1 time.
✗ Branch 88 → 148 not taken.
✓ Branch 90 → 91 taken 1 time.
✗ Branch 90 → 148 not taken.
✓ Branch 92 → 93 taken 1 time.
✗ Branch 92 → 148 not taken.
✓ Branch 93 → 94 taken 1 time.
✗ Branch 93 → 148 not taken.
|
1 | env->BitBlt(dst->GetWritePtr(PLANAR_A), dst->GetPitch(PLANAR_A), frame->GetReadPtr(PLANAR_A) + top * frame->GetPitch(PLANAR_A) + left_bytes, |
| 353 | frame->GetPitch(PLANAR_A), dst->GetRowSize(PLANAR_A), dst->GetHeight(PLANAR_A)); | ||
| 354 | |||
| 355 |
1/2✗ Branch 94 → 95 not taken.
✓ Branch 94 → 96 taken 6 times.
|
6 | return dst; |
| 356 | ✗ | } | |
| 357 | |||
| 358 | // subframe is preserving frame properties | ||
| 359 | ✗ | if (!frame->GetPitch(plane1)) | |
| 360 | ✗ | return env->Subframe(frame, top * frame->GetPitch() + left_bytes, frame->GetPitch(), vi.RowSize(), vi.height); | |
| 361 | else { | ||
| 362 | ✗ | if (hasAlpha) { | |
| 363 | |||
| 364 | ✗ | return env->SubframePlanarA(frame, top * frame->GetPitch() + left_bytes, frame->GetPitch(), vi.RowSize(), vi.height, | |
| 365 | ✗ | (top >> ysub) * frame->GetPitch(plane1) + (left_bytes >> xsub), | |
| 366 | ✗ | (top >> ysub) * frame->GetPitch(plane2) + (left_bytes >> xsub), | |
| 367 | ✗ | frame->GetPitch(plane1), top * frame->GetPitch(PLANAR_A) + left_bytes); | |
| 368 | } | ||
| 369 | else { | ||
| 370 | ✗ | return env->SubframePlanar(frame, top * frame->GetPitch() + left_bytes, frame->GetPitch(), vi.RowSize(), vi.height, | |
| 371 | ✗ | (top >> ysub) * frame->GetPitch(plane1) + (left_bytes >> xsub), | |
| 372 | ✗ | (top >> ysub) * frame->GetPitch(plane2) + (left_bytes >> xsub), | |
| 373 | ✗ | frame->GetPitch(plane1)); | |
| 374 | } | ||
| 375 | } | ||
| 376 | 6 | } | |
| 377 | |||
| 378 | 1 | int __stdcall Crop::SetCacheHints(int cachehints, int frame_range) { | |
| 379 | AVS_UNUSED(frame_range); | ||
| 380 |
1/3✓ Branch 2 → 3 taken 1 time.
✗ Branch 2 → 4 not taken.
✗ Branch 2 → 6 not taken.
|
1 | switch (cachehints) { |
| 381 | 1 | case CACHE_GET_MTMODE: | |
| 382 | 1 | return MT_NICE_FILTER; | |
| 383 | ✗ | case CACHE_GET_DEV_TYPE: | |
| 384 | ✗ | return GetDeviceTypes(child) & (DEV_TYPE_CPU | DEV_TYPE_CUDA); | |
| 385 | } | ||
| 386 | ✗ | return 0; | |
| 387 | } | ||
| 388 | |||
| 389 | |||
| 390 | ✗ | AVSValue __cdecl Crop::Create(AVSValue args, void*, IScriptEnvironment* env) | |
| 391 | { | ||
| 392 | ✗ | return new Crop( args[1].AsInt(), args[2].AsInt(), args[3].AsInt(), args[4].AsInt(), args[5].AsBool(true), | |
| 393 | ✗ | args[0].AsClip(), env ); | |
| 394 | } | ||
| 395 | |||
| 396 | |||
| 397 | |||
| 398 | |||
| 399 | |||
| 400 | /****************************** | ||
| 401 | ******* Add Borders ****** | ||
| 402 | *****************************/ | ||
| 403 | |||
| 404 | 6 | AddBorders::AddBorders(int _left, int _top, int _right, int _bot, int _clr, bool _force_color_as_yuv, PClip _child, IScriptEnvironment* env) | |
| 405 | : GenericVideoFilter(_child), | ||
| 406 | 6 | left(max(0, _left)), top(max(0, _top)), right(max(0, _right)), bot(max(0, _bot)), | |
| 407 | 6 | clr(_clr), | |
| 408 | 6 | xsub(0), ysub(0), | |
| 409 |
2/4✓ Branch 2 → 3 taken 6 times.
✗ Branch 2 → 40 not taken.
✓ Branch 3 → 4 taken 6 times.
✗ Branch 3 → 38 not taken.
|
6 | force_color_as_yuv(_force_color_as_yuv) |
| 410 | |||
| 411 | { | ||
| 412 |
8/10✓ Branch 9 → 10 taken 6 times.
✗ Branch 9 → 41 not taken.
✓ Branch 10 → 11 taken 4 times.
✓ Branch 10 → 13 taken 2 times.
✓ Branch 11 → 12 taken 4 times.
✗ Branch 11 → 41 not taken.
✓ Branch 12 → 13 taken 1 time.
✓ Branch 12 → 14 taken 3 times.
✓ Branch 15 → 16 taken 3 times.
✓ Branch 15 → 29 taken 3 times.
|
6 | if (vi.IsYUV() || vi.IsYUVA()) { |
| 413 |
2/4✓ Branch 16 → 17 taken 3 times.
✗ Branch 16 → 41 not taken.
✓ Branch 17 → 18 taken 3 times.
✗ Branch 17 → 21 not taken.
|
3 | if (vi.NumComponents() > 1) { |
| 414 |
1/2✓ Branch 18 → 19 taken 3 times.
✗ Branch 18 → 41 not taken.
|
3 | xsub=vi.GetPlaneWidthSubsampling(PLANAR_U); |
| 415 |
1/2✓ Branch 19 → 20 taken 3 times.
✗ Branch 19 → 41 not taken.
|
3 | ysub=vi.GetPlaneHeightSubsampling(PLANAR_U); |
| 416 | } | ||
| 417 | |||
| 418 | 3 | const int xmask = (1 << xsub) - 1; | |
| 419 | 3 | const int ymask = (1 << ysub) - 1; | |
| 420 | |||
| 421 | // YUY2, etc, ... can only add even amounts | ||
| 422 |
1/2✗ Branch 21 → 22 not taken.
✓ Branch 21 → 23 taken 3 times.
|
3 | if (_left & xmask) |
| 423 | ✗ | env->ThrowError("AddBorders: YUV image can only add by Mod %d (left side).", xmask+1); | |
| 424 |
1/2✗ Branch 23 → 24 not taken.
✓ Branch 23 → 25 taken 3 times.
|
3 | if (_right & xmask) |
| 425 | ✗ | env->ThrowError("AddBorders: YUV image can only add by Mod %d (right side).", xmask+1); | |
| 426 | |||
| 427 |
1/2✗ Branch 25 → 26 not taken.
✓ Branch 25 → 27 taken 3 times.
|
3 | if (_top & ymask) |
| 428 | ✗ | env->ThrowError("AddBorders: YUV image can only add by Mod %d (top).", ymask+1); | |
| 429 |
1/2✗ Branch 27 → 28 not taken.
✓ Branch 27 → 37 taken 3 times.
|
3 | if (_bot & ymask) |
| 430 | ✗ | env->ThrowError("AddBorders: YUV image can only add by Mod %d (bottom).", ymask+1); | |
| 431 |
7/10✓ Branch 29 → 30 taken 3 times.
✗ Branch 29 → 41 not taken.
✓ Branch 30 → 31 taken 2 times.
✓ Branch 30 → 34 taken 1 time.
✓ Branch 31 → 32 taken 2 times.
✗ Branch 31 → 41 not taken.
✓ Branch 32 → 33 taken 2 times.
✗ Branch 32 → 34 not taken.
✓ Branch 35 → 36 taken 2 times.
✓ Branch 35 → 37 taken 1 time.
|
3 | } else if (!vi.IsPlanarRGB() && !vi.IsPlanarRGBA()){ |
| 432 | // RGB is upside-down | ||
| 433 | 2 | int t = top; top = bot; bot = t; | |
| 434 | } | ||
| 435 | 6 | vi.width += left+right; | |
| 436 | 6 | vi.height += top+bot; | |
| 437 | 6 | } | |
| 438 | |||
| 439 | template<typename pixel_t> | ||
| 440 | 17 | static inline pixel_t GetHbdColorFromByte(uint8_t color, bool fullscale, int bits_per_pixel, bool chroma) | |
| 441 | { | ||
| 442 | 10 | if constexpr(sizeof(pixel_t) == 1) return color; | |
| 443 |
1/2✓ Branch 2 → 3 taken 7 times.
✗ Branch 2 → 4 not taken.
|
7 | else if constexpr(sizeof(pixel_t) == 2) return (pixel_t)(fullscale ? (color * ((1 << bits_per_pixel)-1)) / 255 : (int)color << (bits_per_pixel - 8)); |
| 444 | else { | ||
| 445 | ✗ | if (chroma) | |
| 446 | ✗ | return (pixel_t)uv8tof(color); // float, scale, 128=0.0f | |
| 447 | else | ||
| 448 | ✗ | return (pixel_t)c8tof(color); // float, scale to [0..1] | |
| 449 | } | ||
| 450 | } | ||
| 451 | |||
| 452 | template<typename pixel_t> | ||
| 453 | 4 | static void addborders_planar(PVideoFrame &dst, PVideoFrame &src, VideoInfo &vi, int top, int bot, int left, int right, int color, bool isYUV, bool force_color_as_yuv, int bits_per_pixel) | |
| 454 | { | ||
| 455 |
3/18void addborders_planar<float>(PVideoFrame&, PVideoFrame&, VideoInfo&, int, int, int, int, int, bool, bool, int):
✗ Branch 2 → 3 not taken.
✗ Branch 2 → 6 not taken.
✗ Branch 3 → 4 not taken.
✗ Branch 3 → 6 not taken.
✗ Branch 4 → 5 not taken.
✗ Branch 4 → 54 not taken.
void addborders_planar<unsigned char>(PVideoFrame&, PVideoFrame&, VideoInfo&, int, int, int, int, int, bool, bool, int):
✓ Branch 2 → 3 taken 3 times.
✗ Branch 2 → 6 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 6 taken 3 times.
✗ Branch 4 → 5 not taken.
✗ Branch 4 → 54 not taken.
void addborders_planar<unsigned short>(PVideoFrame&, PVideoFrame&, VideoInfo&, int, int, int, int, int, bool, bool, int):
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 6 taken 1 time.
✗ Branch 3 → 4 not taken.
✗ Branch 3 → 6 not taken.
✗ Branch 4 → 5 not taken.
✗ Branch 4 → 54 not taken.
|
4 | const unsigned int colr = isYUV && !force_color_as_yuv ? RGB2YUV_Rec601(color) : color; |
| 456 | 4 | const unsigned char YBlack=(unsigned char)((colr >> 16) & 0xff); | |
| 457 | 4 | const unsigned char UBlack=(unsigned char)((colr >> 8) & 0xff); | |
| 458 | 4 | const unsigned char VBlack=(unsigned char)((colr ) & 0xff); | |
| 459 | 4 | const unsigned char ABlack=(unsigned char)((colr >> 24) & 0xff); | |
| 460 | |||
| 461 | 4 | int planesYUV[4] = { PLANAR_Y, PLANAR_U, PLANAR_V, PLANAR_A }; | |
| 462 | 4 | int planesRGB[4] = { PLANAR_G, PLANAR_B, PLANAR_R, PLANAR_A }; | |
| 463 |
2/6void addborders_planar<float>(PVideoFrame&, PVideoFrame&, VideoInfo&, int, int, int, int, int, bool, bool, int):
✗ Branch 7 → 8 not taken.
✗ Branch 7 → 9 not taken.
void addborders_planar<unsigned char>(PVideoFrame&, PVideoFrame&, VideoInfo&, int, int, int, int, int, bool, bool, int):
✓ Branch 7 → 8 taken 3 times.
✗ Branch 7 → 9 not taken.
void addborders_planar<unsigned short>(PVideoFrame&, PVideoFrame&, VideoInfo&, int, int, int, int, int, bool, bool, int):
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 9 taken 1 time.
|
4 | int *planes = isYUV ? planesYUV : planesRGB; |
| 464 | 4 | uint8_t colorsYUV[4] = { YBlack, UBlack, VBlack, ABlack }; | |
| 465 | 4 | uint8_t colorsRGB[4] = { UBlack, VBlack, YBlack, ABlack }; // mapping for planar RGB | |
| 466 |
2/6void addborders_planar<float>(PVideoFrame&, PVideoFrame&, VideoInfo&, int, int, int, int, int, bool, bool, int):
✗ Branch 10 → 11 not taken.
✗ Branch 10 → 12 not taken.
void addborders_planar<unsigned char>(PVideoFrame&, PVideoFrame&, VideoInfo&, int, int, int, int, int, bool, bool, int):
✓ Branch 10 → 11 taken 3 times.
✗ Branch 10 → 12 not taken.
void addborders_planar<unsigned short>(PVideoFrame&, PVideoFrame&, VideoInfo&, int, int, int, int, int, bool, bool, int):
✗ Branch 10 → 11 not taken.
✓ Branch 10 → 12 taken 1 time.
|
4 | uint8_t *colors = isYUV ? colorsYUV : colorsRGB; |
| 467 |
6/12void addborders_planar<float>(PVideoFrame&, PVideoFrame&, VideoInfo&, int, int, int, int, int, bool, bool, int):
✗ Branch 51 → 52 not taken.
✗ Branch 51 → 54 not taken.
✗ Branch 52 → 14 not taken.
✗ Branch 52 → 53 not taken.
void addborders_planar<unsigned char>(PVideoFrame&, PVideoFrame&, VideoInfo&, int, int, int, int, int, bool, bool, int):
✓ Branch 51 → 52 taken 13 times.
✗ Branch 51 → 54 not taken.
✓ Branch 52 → 14 taken 10 times.
✓ Branch 52 → 53 taken 3 times.
void addborders_planar<unsigned short>(PVideoFrame&, PVideoFrame&, VideoInfo&, int, int, int, int, int, bool, bool, int):
✓ Branch 51 → 52 taken 4 times.
✗ Branch 51 → 54 not taken.
✓ Branch 52 → 14 taken 3 times.
✓ Branch 52 → 53 taken 1 time.
|
17 | for (int p = 0; p < vi.NumComponents(); p++) |
| 468 | { | ||
| 469 | 13 | int plane = planes[p]; | |
| 470 |
2/6void addborders_planar<float>(PVideoFrame&, PVideoFrame&, VideoInfo&, int, int, int, int, int, bool, bool, int):
✗ Branch 15 → 16 not taken.
✗ Branch 15 → 54 not taken.
void addborders_planar<unsigned char>(PVideoFrame&, PVideoFrame&, VideoInfo&, int, int, int, int, int, bool, bool, int):
✓ Branch 15 → 16 taken 10 times.
✗ Branch 15 → 54 not taken.
void addborders_planar<unsigned short>(PVideoFrame&, PVideoFrame&, VideoInfo&, int, int, int, int, int, bool, bool, int):
✓ Branch 15 → 16 taken 3 times.
✗ Branch 15 → 54 not taken.
|
13 | int src_pitch = src->GetPitch(plane); |
| 471 |
2/6void addborders_planar<float>(PVideoFrame&, PVideoFrame&, VideoInfo&, int, int, int, int, int, bool, bool, int):
✗ Branch 17 → 18 not taken.
✗ Branch 17 → 54 not taken.
void addborders_planar<unsigned char>(PVideoFrame&, PVideoFrame&, VideoInfo&, int, int, int, int, int, bool, bool, int):
✓ Branch 17 → 18 taken 10 times.
✗ Branch 17 → 54 not taken.
void addborders_planar<unsigned short>(PVideoFrame&, PVideoFrame&, VideoInfo&, int, int, int, int, int, bool, bool, int):
✓ Branch 17 → 18 taken 3 times.
✗ Branch 17 → 54 not taken.
|
13 | int src_rowsize = src->GetRowSize(plane); |
| 472 |
2/6void addborders_planar<float>(PVideoFrame&, PVideoFrame&, VideoInfo&, int, int, int, int, int, bool, bool, int):
✗ Branch 19 → 20 not taken.
✗ Branch 19 → 54 not taken.
void addborders_planar<unsigned char>(PVideoFrame&, PVideoFrame&, VideoInfo&, int, int, int, int, int, bool, bool, int):
✓ Branch 19 → 20 taken 10 times.
✗ Branch 19 → 54 not taken.
void addborders_planar<unsigned short>(PVideoFrame&, PVideoFrame&, VideoInfo&, int, int, int, int, int, bool, bool, int):
✓ Branch 19 → 20 taken 3 times.
✗ Branch 19 → 54 not taken.
|
13 | int src_height = src->GetHeight(plane); |
| 473 | |||
| 474 |
2/6void addborders_planar<float>(PVideoFrame&, PVideoFrame&, VideoInfo&, int, int, int, int, int, bool, bool, int):
✗ Branch 21 → 22 not taken.
✗ Branch 21 → 54 not taken.
void addborders_planar<unsigned char>(PVideoFrame&, PVideoFrame&, VideoInfo&, int, int, int, int, int, bool, bool, int):
✓ Branch 21 → 22 taken 10 times.
✗ Branch 21 → 54 not taken.
void addborders_planar<unsigned short>(PVideoFrame&, PVideoFrame&, VideoInfo&, int, int, int, int, int, bool, bool, int):
✓ Branch 21 → 22 taken 3 times.
✗ Branch 21 → 54 not taken.
|
13 | int dst_pitch = dst->GetPitch(plane); |
| 475 | |||
| 476 |
2/6void addborders_planar<float>(PVideoFrame&, PVideoFrame&, VideoInfo&, int, int, int, int, int, bool, bool, int):
✗ Branch 22 → 23 not taken.
✗ Branch 22 → 54 not taken.
void addborders_planar<unsigned char>(PVideoFrame&, PVideoFrame&, VideoInfo&, int, int, int, int, int, bool, bool, int):
✓ Branch 22 → 23 taken 10 times.
✗ Branch 22 → 54 not taken.
void addborders_planar<unsigned short>(PVideoFrame&, PVideoFrame&, VideoInfo&, int, int, int, int, int, bool, bool, int):
✓ Branch 22 → 23 taken 3 times.
✗ Branch 22 → 54 not taken.
|
13 | int xsub=vi.GetPlaneWidthSubsampling(plane); |
| 477 |
2/6void addborders_planar<float>(PVideoFrame&, PVideoFrame&, VideoInfo&, int, int, int, int, int, bool, bool, int):
✗ Branch 23 → 24 not taken.
✗ Branch 23 → 54 not taken.
void addborders_planar<unsigned char>(PVideoFrame&, PVideoFrame&, VideoInfo&, int, int, int, int, int, bool, bool, int):
✓ Branch 23 → 24 taken 10 times.
✗ Branch 23 → 54 not taken.
void addborders_planar<unsigned short>(PVideoFrame&, PVideoFrame&, VideoInfo&, int, int, int, int, int, bool, bool, int):
✓ Branch 23 → 24 taken 3 times.
✗ Branch 23 → 54 not taken.
|
13 | int ysub=vi.GetPlaneHeightSubsampling(plane); |
| 478 | |||
| 479 |
2/6void addborders_planar<float>(PVideoFrame&, PVideoFrame&, VideoInfo&, int, int, int, int, int, bool, bool, int):
✗ Branch 24 → 25 not taken.
✗ Branch 24 → 54 not taken.
void addborders_planar<unsigned char>(PVideoFrame&, PVideoFrame&, VideoInfo&, int, int, int, int, int, bool, bool, int):
✓ Branch 24 → 25 taken 10 times.
✗ Branch 24 → 54 not taken.
void addborders_planar<unsigned short>(PVideoFrame&, PVideoFrame&, VideoInfo&, int, int, int, int, int, bool, bool, int):
✓ Branch 24 → 25 taken 3 times.
✗ Branch 24 → 54 not taken.
|
13 | const int initial_black = (top >> ysub) * dst_pitch + vi.BytesFromPixels(left >> xsub); |
| 480 | 13 | const int middle_black = dst_pitch - src_rowsize; | |
| 481 |
2/6void addborders_planar<float>(PVideoFrame&, PVideoFrame&, VideoInfo&, int, int, int, int, int, bool, bool, int):
✗ Branch 25 → 26 not taken.
✗ Branch 25 → 54 not taken.
void addborders_planar<unsigned char>(PVideoFrame&, PVideoFrame&, VideoInfo&, int, int, int, int, int, bool, bool, int):
✓ Branch 25 → 26 taken 10 times.
✗ Branch 25 → 54 not taken.
void addborders_planar<unsigned short>(PVideoFrame&, PVideoFrame&, VideoInfo&, int, int, int, int, int, bool, bool, int):
✓ Branch 25 → 26 taken 3 times.
✗ Branch 25 → 54 not taken.
|
13 | const int final_black = (bot >> ysub) * dst_pitch + vi.BytesFromPixels(right >> xsub) + |
| 482 |
2/6void addborders_planar<float>(PVideoFrame&, PVideoFrame&, VideoInfo&, int, int, int, int, int, bool, bool, int):
✗ Branch 27 → 28 not taken.
✗ Branch 27 → 54 not taken.
void addborders_planar<unsigned char>(PVideoFrame&, PVideoFrame&, VideoInfo&, int, int, int, int, int, bool, bool, int):
✓ Branch 27 → 28 taken 10 times.
✗ Branch 27 → 54 not taken.
void addborders_planar<unsigned short>(PVideoFrame&, PVideoFrame&, VideoInfo&, int, int, int, int, int, bool, bool, int):
✓ Branch 27 → 28 taken 3 times.
✗ Branch 27 → 54 not taken.
|
13 | (dst_pitch - dst->GetRowSize(plane)); |
| 483 | |||
| 484 |
6/12void addborders_planar<float>(PVideoFrame&, PVideoFrame&, VideoInfo&, int, int, int, int, int, bool, bool, int):
✗ Branch 28 → 29 not taken.
✗ Branch 28 → 30 not taken.
✗ Branch 29 → 30 not taken.
✗ Branch 29 → 31 not taken.
void addborders_planar<unsigned char>(PVideoFrame&, PVideoFrame&, VideoInfo&, int, int, int, int, int, bool, bool, int):
✓ Branch 28 → 29 taken 7 times.
✓ Branch 28 → 30 taken 3 times.
✓ Branch 29 → 30 taken 3 times.
✓ Branch 29 → 31 taken 4 times.
void addborders_planar<unsigned short>(PVideoFrame&, PVideoFrame&, VideoInfo&, int, int, int, int, int, bool, bool, int):
✓ Branch 28 → 29 taken 3 times.
✗ Branch 28 → 30 not taken.
✗ Branch 29 → 30 not taken.
✓ Branch 29 → 31 taken 3 times.
|
13 | const bool chroma = plane == PLANAR_U || plane == PLANAR_V; |
| 485 | |||
| 486 | 13 | pixel_t current_color = GetHbdColorFromByte<pixel_t>(colors[p], !isYUV, bits_per_pixel, chroma); | |
| 487 | |||
| 488 |
2/6void addborders_planar<float>(PVideoFrame&, PVideoFrame&, VideoInfo&, int, int, int, int, int, bool, bool, int):
✗ Branch 34 → 35 not taken.
✗ Branch 34 → 54 not taken.
void addborders_planar<unsigned char>(PVideoFrame&, PVideoFrame&, VideoInfo&, int, int, int, int, int, bool, bool, int):
✓ Branch 34 → 35 taken 10 times.
✗ Branch 34 → 54 not taken.
void addborders_planar<unsigned short>(PVideoFrame&, PVideoFrame&, VideoInfo&, int, int, int, int, int, bool, bool, int):
✓ Branch 34 → 35 taken 3 times.
✗ Branch 34 → 54 not taken.
|
13 | BYTE *dstp = dst->GetWritePtr(plane); |
| 489 | // copy original | ||
| 490 |
4/12void addborders_planar<float>(PVideoFrame&, PVideoFrame&, VideoInfo&, int, int, int, int, int, bool, bool, int):
✗ Branch 36 → 37 not taken.
✗ Branch 36 → 54 not taken.
✗ Branch 37 → 38 not taken.
✗ Branch 37 → 54 not taken.
void addborders_planar<unsigned char>(PVideoFrame&, PVideoFrame&, VideoInfo&, int, int, int, int, int, bool, bool, int):
✓ Branch 36 → 37 taken 10 times.
✗ Branch 36 → 54 not taken.
✓ Branch 37 → 38 taken 10 times.
✗ Branch 37 → 54 not taken.
void addborders_planar<unsigned short>(PVideoFrame&, PVideoFrame&, VideoInfo&, int, int, int, int, int, bool, bool, int):
✓ Branch 36 → 37 taken 3 times.
✗ Branch 36 → 54 not taken.
✓ Branch 37 → 38 taken 3 times.
✗ Branch 37 → 54 not taken.
|
13 | BitBlt(dstp+initial_black, dst_pitch, src->GetReadPtr(plane), src_pitch, src_rowsize, src_height); |
| 491 | // add top | ||
| 492 |
4/6void addborders_planar<float>(PVideoFrame&, PVideoFrame&, VideoInfo&, int, int, int, int, int, bool, bool, int):
✗ Branch 40 → 39 not taken.
✗ Branch 40 → 41 not taken.
void addborders_planar<unsigned char>(PVideoFrame&, PVideoFrame&, VideoInfo&, int, int, int, int, int, bool, bool, int):
✓ Branch 40 → 39 taken 1040 times.
✓ Branch 40 → 41 taken 10 times.
void addborders_planar<unsigned short>(PVideoFrame&, PVideoFrame&, VideoInfo&, int, int, int, int, int, bool, bool, int):
✓ Branch 40 → 39 taken 99 times.
✓ Branch 40 → 41 taken 3 times.
|
1152 | for (size_t a = 0; a<initial_black / sizeof(pixel_t); a++) { |
| 493 | 1139 | reinterpret_cast<pixel_t *>(dstp)[a] = current_color; | |
| 494 | } | ||
| 495 | // middle right + left (fill overflows from right to left) | ||
| 496 | 13 | dstp += initial_black + src_rowsize; | |
| 497 |
4/6void addborders_planar<float>(PVideoFrame&, PVideoFrame&, VideoInfo&, int, int, int, int, int, bool, bool, int):
✗ Branch 46 → 42 not taken.
✗ Branch 46 → 47 not taken.
void addborders_planar<unsigned char>(PVideoFrame&, PVideoFrame&, VideoInfo&, int, int, int, int, int, bool, bool, int):
✓ Branch 46 → 42 taken 19 times.
✓ Branch 46 → 47 taken 10 times.
void addborders_planar<unsigned short>(PVideoFrame&, PVideoFrame&, VideoInfo&, int, int, int, int, int, bool, bool, int):
✓ Branch 46 → 42 taken 6 times.
✓ Branch 46 → 47 taken 3 times.
|
38 | for (int y = src_height-1; y>0; --y) { |
| 498 |
4/6void addborders_planar<float>(PVideoFrame&, PVideoFrame&, VideoInfo&, int, int, int, int, int, bool, bool, int):
✗ Branch 44 → 43 not taken.
✗ Branch 44 → 45 not taken.
void addborders_planar<unsigned char>(PVideoFrame&, PVideoFrame&, VideoInfo&, int, int, int, int, int, bool, bool, int):
✓ Branch 44 → 43 taken 1112 times.
✓ Branch 44 → 45 taken 19 times.
void addborders_planar<unsigned short>(PVideoFrame&, PVideoFrame&, VideoInfo&, int, int, int, int, int, bool, bool, int):
✓ Branch 44 → 43 taken 162 times.
✓ Branch 44 → 45 taken 6 times.
|
1299 | for (size_t b = 0; b<middle_black / sizeof(pixel_t); b++) { |
| 499 | 1274 | reinterpret_cast<pixel_t *>(dstp)[b] = current_color; | |
| 500 | } | ||
| 501 | 25 | dstp += dst_pitch; | |
| 502 | } | ||
| 503 | // bottom | ||
| 504 |
4/6void addborders_planar<float>(PVideoFrame&, PVideoFrame&, VideoInfo&, int, int, int, int, int, bool, bool, int):
✗ Branch 49 → 48 not taken.
✗ Branch 49 → 50 not taken.
void addborders_planar<unsigned char>(PVideoFrame&, PVideoFrame&, VideoInfo&, int, int, int, int, int, bool, bool, int):
✓ Branch 49 → 48 taken 1599 times.
✓ Branch 49 → 50 taken 10 times.
void addborders_planar<unsigned short>(PVideoFrame&, PVideoFrame&, VideoInfo&, int, int, int, int, int, bool, bool, int):
✓ Branch 49 → 48 taken 174 times.
✓ Branch 49 → 50 taken 3 times.
|
1786 | for (size_t c = 0; c<final_black / sizeof(pixel_t); c++) |
| 505 | 1773 | reinterpret_cast<pixel_t *>(dstp)[c] = current_color; | |
| 506 | } | ||
| 507 | 4 | } | |
| 508 | |||
| 509 | 6 | PVideoFrame AddBorders::GetFrame(int n, IScriptEnvironment* env) | |
| 510 | { | ||
| 511 |
1/2✓ Branch 3 → 4 taken 6 times.
✗ Branch 3 → 155 not taken.
|
6 | PVideoFrame src = child->GetFrame(n, env); |
| 512 |
1/2✓ Branch 4 → 5 taken 6 times.
✗ Branch 4 → 153 not taken.
|
6 | PVideoFrame dst = env->NewVideoFrameP(vi, &src); |
| 513 | |||
| 514 |
3/4✓ Branch 5 → 6 taken 6 times.
✗ Branch 5 → 151 not taken.
✓ Branch 6 → 7 taken 4 times.
✓ Branch 6 → 23 taken 2 times.
|
6 | if (vi.IsPlanar()) { |
| 515 |
1/2✓ Branch 7 → 8 taken 4 times.
✗ Branch 7 → 151 not taken.
|
4 | int bits_per_pixel = vi.BitsPerComponent(); |
| 516 |
6/8✓ Branch 8 → 9 taken 4 times.
✗ Branch 8 → 151 not taken.
✓ Branch 9 → 10 taken 2 times.
✓ Branch 9 → 12 taken 2 times.
✓ Branch 10 → 11 taken 2 times.
✗ Branch 10 → 151 not taken.
✓ Branch 11 → 12 taken 1 time.
✓ Branch 11 → 13 taken 1 time.
|
4 | bool isYUV = vi.IsYUV() || vi.IsYUVA(); |
| 517 |
3/5✓ Branch 14 → 15 taken 4 times.
✗ Branch 14 → 151 not taken.
✓ Branch 15 → 16 taken 3 times.
✓ Branch 15 → 18 taken 1 time.
✗ Branch 15 → 20 not taken.
|
4 | switch(vi.ComponentSize()) { |
| 518 |
1/2✓ Branch 16 → 17 taken 3 times.
✗ Branch 16 → 151 not taken.
|
3 | case 1: addborders_planar<uint8_t>(dst, src, vi, top, bot, left, right, clr, isYUV, force_color_as_yuv /*like MODE_COLOR_YUV in BlankClip */, bits_per_pixel); break; |
| 519 |
1/2✓ Branch 18 → 19 taken 1 time.
✗ Branch 18 → 151 not taken.
|
1 | case 2: addborders_planar<uint16_t>(dst, src, vi, top, bot, left, right, clr, isYUV, force_color_as_yuv, bits_per_pixel); break; |
| 520 | ✗ | default: //case 4: | |
| 521 | ✗ | addborders_planar<float>(dst, src, vi, top, bot, left, right, clr, isYUV, force_color_as_yuv, bits_per_pixel); break; | |
| 522 | } | ||
| 523 | 4 | return dst; | |
| 524 | } | ||
| 525 | |||
| 526 |
1/2✓ Branch 24 → 25 taken 2 times.
✗ Branch 24 → 151 not taken.
|
2 | const BYTE* srcp = src->GetReadPtr(); |
| 527 |
1/2✓ Branch 26 → 27 taken 2 times.
✗ Branch 26 → 151 not taken.
|
2 | BYTE* dstp = dst->GetWritePtr(); |
| 528 |
1/2✓ Branch 28 → 29 taken 2 times.
✗ Branch 28 → 151 not taken.
|
2 | const int src_pitch = src->GetPitch(); |
| 529 |
1/2✓ Branch 30 → 31 taken 2 times.
✗ Branch 30 → 151 not taken.
|
2 | const int dst_pitch = dst->GetPitch(); |
| 530 |
1/2✓ Branch 32 → 33 taken 2 times.
✗ Branch 32 → 151 not taken.
|
2 | const int src_row_size = src->GetRowSize(); |
| 531 |
1/2✓ Branch 34 → 35 taken 2 times.
✗ Branch 34 → 151 not taken.
|
2 | const int dst_row_size = dst->GetRowSize(); |
| 532 |
1/2✓ Branch 36 → 37 taken 2 times.
✗ Branch 36 → 151 not taken.
|
2 | const int src_height = src->GetHeight(); |
| 533 | |||
| 534 |
1/2✓ Branch 37 → 38 taken 2 times.
✗ Branch 37 → 151 not taken.
|
2 | const int initial_black = top * dst_pitch + vi.BytesFromPixels(left); |
| 535 | 2 | const int middle_black = dst_pitch - src_row_size; | |
| 536 |
1/2✓ Branch 38 → 39 taken 2 times.
✗ Branch 38 → 151 not taken.
|
2 | const int final_black = bot * dst_pitch + vi.BytesFromPixels(right) |
| 537 | 2 | + (dst_pitch - dst_row_size); | |
| 538 | |||
| 539 |
2/4✓ Branch 39 → 40 taken 2 times.
✗ Branch 39 → 151 not taken.
✗ Branch 40 → 41 not taken.
✓ Branch 40 → 58 taken 2 times.
|
2 | if (vi.IsYUY2()) { |
| 540 | ✗ | const unsigned int colr = force_color_as_yuv ? clr : RGB2YUV_Rec601(clr); | |
| 541 | ✗ | const uint32_t black = (colr>>16) * 0x010001 + ((colr>>8)&255) * 0x0100 + (colr&255) * 0x01000000; | |
| 542 | |||
| 543 | ✗ | BitBlt(dstp+initial_black, dst_pitch, srcp, src_pitch, src_row_size, src_height); | |
| 544 | ✗ | for (int a = 0; a<initial_black; a += 4) { | |
| 545 | ✗ | *(uint32_t*)(dstp+a) = black; | |
| 546 | } | ||
| 547 | ✗ | dstp += initial_black + src_row_size; | |
| 548 | ✗ | for (int y = src_height-1; y>0; --y) { | |
| 549 | ✗ | for (int b = 0; b<middle_black; b += 4) { | |
| 550 | ✗ | *(uint32_t*)(dstp+b) = black; | |
| 551 | } | ||
| 552 | ✗ | dstp += dst_pitch; | |
| 553 | } | ||
| 554 | ✗ | for (int c = 0; c<final_black; c += 4) { | |
| 555 | ✗ | *(uint32_t*)(dstp+c) = black; | |
| 556 | } | ||
| 557 |
3/4✓ Branch 58 → 59 taken 2 times.
✗ Branch 58 → 151 not taken.
✓ Branch 59 → 60 taken 1 time.
✓ Branch 59 → 84 taken 1 time.
|
2 | } else if (vi.IsRGB24()) { |
| 558 | 1 | const unsigned char clr0 = (unsigned char)(clr & 0xFF); | |
| 559 | 1 | const unsigned short clr1 = (unsigned short)(clr >> 8); | |
| 560 |
1/2✓ Branch 60 → 61 taken 1 time.
✗ Branch 60 → 151 not taken.
|
1 | const int leftbytes = vi.BytesFromPixels(left); |
| 561 | 1 | const int leftrow = src_row_size + leftbytes; | |
| 562 |
1/2✓ Branch 61 → 62 taken 1 time.
✗ Branch 61 → 151 not taken.
|
1 | const int rightbytes = vi.BytesFromPixels(right); |
| 563 | 1 | const int rightrow = dst_pitch - dst_row_size + rightbytes; | |
| 564 | |||
| 565 |
1/2✓ Branch 62 → 63 taken 1 time.
✗ Branch 62 → 151 not taken.
|
1 | BitBlt(dstp+initial_black, dst_pitch, srcp, src_pitch, src_row_size, src_height); |
| 566 | /* Cannot use *_black optimisation as pitch may not be mod 3 */ | ||
| 567 |
2/2✓ Branch 68 → 64 taken 2 times.
✓ Branch 68 → 69 taken 1 time.
|
3 | for (int y = top; y>0; --y) { |
| 568 |
2/2✓ Branch 66 → 65 taken 16 times.
✓ Branch 66 → 67 taken 2 times.
|
18 | for (int i = 0; i<dst_row_size; i += 3) { |
| 569 | 16 | dstp[i] = clr0; | |
| 570 | 16 | *(uint16_t*)(dstp+i+1) = clr1; | |
| 571 | } | ||
| 572 | 2 | dstp += dst_pitch; | |
| 573 | } | ||
| 574 |
2/2✓ Branch 77 → 70 taken 3 times.
✓ Branch 77 → 78 taken 1 time.
|
4 | for (int y = src_height; y>0; --y) { |
| 575 |
2/2✓ Branch 72 → 71 taken 3 times.
✓ Branch 72 → 73 taken 3 times.
|
6 | for (int i = 0; i<leftbytes; i += 3) { |
| 576 | 3 | dstp[i] = clr0; | |
| 577 | 3 | *(uint16_t*)(dstp+i+1) = clr1; | |
| 578 | } | ||
| 579 | 3 | dstp += leftrow; | |
| 580 |
2/2✓ Branch 75 → 74 taken 6 times.
✓ Branch 75 → 76 taken 3 times.
|
9 | for (int i = 0; i<rightbytes; i += 3) { |
| 581 | 6 | dstp[i] = clr0; | |
| 582 | 6 | *(uint16_t*)(dstp+i+1) = clr1; | |
| 583 | } | ||
| 584 | 3 | dstp += rightrow; | |
| 585 | } | ||
| 586 |
2/2✓ Branch 83 → 79 taken 1 time.
✓ Branch 83 → 147 taken 1 time.
|
2 | for (int y = bot; y>0; --y) { |
| 587 |
2/2✓ Branch 81 → 80 taken 8 times.
✓ Branch 81 → 82 taken 1 time.
|
9 | for (int i = 0; i<dst_row_size; i += 3) { |
| 588 | 8 | dstp[i] = clr0; | |
| 589 | 8 | *(uint16_t*)(dstp+i+1) = clr1; | |
| 590 | } | ||
| 591 | 1 | dstp += dst_pitch; | |
| 592 | } | ||
| 593 | } | ||
| 594 |
2/4✓ Branch 84 → 85 taken 1 time.
✗ Branch 84 → 151 not taken.
✗ Branch 85 → 86 not taken.
✓ Branch 85 → 99 taken 1 time.
|
1 | else if (vi.IsRGB32()) { |
| 595 | ✗ | BitBlt(dstp+initial_black, dst_pitch, srcp, src_pitch, src_row_size, src_height); | |
| 596 | ✗ | for (int i = 0; i<initial_black; i += 4) { | |
| 597 | ✗ | *(uint32_t*)(dstp+i) = clr; | |
| 598 | } | ||
| 599 | ✗ | dstp += initial_black + src_row_size; | |
| 600 | ✗ | for (int y = src_height-1; y>0; --y) { | |
| 601 | ✗ | for (int i = 0; i<middle_black; i += 4) { | |
| 602 | ✗ | *(uint32_t*)(dstp+i) = clr; | |
| 603 | } | ||
| 604 | ✗ | dstp += dst_pitch; | |
| 605 | } // for y | ||
| 606 | ✗ | for (int i = 0; i<final_black; i += 4) { | |
| 607 | ✗ | *(uint32_t*)(dstp+i) = clr; | |
| 608 | } | ||
| 609 |
2/4✓ Branch 99 → 100 taken 1 time.
✗ Branch 99 → 151 not taken.
✗ Branch 100 → 101 not taken.
✓ Branch 100 → 128 taken 1 time.
|
1 | } else if (vi.IsRGB48()) { |
| 610 | ✗ | const uint16_t clr0 = GetHbdColorFromByte<uint16_t>(clr & 0xFF, true, 16, false); | |
| 611 | uint32_t clr1 = | ||
| 612 | ✗ | ((uint32_t)GetHbdColorFromByte<uint16_t>((clr >> 16) & 0xFF, true, 16, false) << (8 * 2)) + | |
| 613 | ✗ | ((uint32_t)GetHbdColorFromByte<uint16_t>((clr >> 8) & 0xFF, true, 16, false)); | |
| 614 | ✗ | const int leftbytes = vi.BytesFromPixels(left); | |
| 615 | ✗ | const int leftrow = src_row_size + leftbytes; | |
| 616 | ✗ | const int rightbytes = vi.BytesFromPixels(right); | |
| 617 | ✗ | const int rightrow = dst_pitch - dst_row_size + rightbytes; | |
| 618 | |||
| 619 | ✗ | BitBlt(dstp+initial_black, dst_pitch, srcp, src_pitch, src_row_size, src_height); | |
| 620 | /* Cannot use *_black optimisation as pitch may not be mod 3 */ | ||
| 621 | ✗ | for (int y = top; y>0; --y) { | |
| 622 | ✗ | for (int i = 0; i<dst_row_size; i += 6) { | |
| 623 | ✗ | *(uint16_t*)(dstp+i) = clr0; | |
| 624 | ✗ | *(uint32_t*)(dstp+i+2) = clr1; | |
| 625 | } | ||
| 626 | ✗ | dstp += dst_pitch; | |
| 627 | } | ||
| 628 | ✗ | for (int y = src_height; y>0; --y) { | |
| 629 | ✗ | for (int i = 0; i<leftbytes; i += 6) { | |
| 630 | ✗ | *(uint16_t*)(dstp+i) = clr0; | |
| 631 | ✗ | *(uint32_t*)(dstp+i+2) = clr1; | |
| 632 | } | ||
| 633 | ✗ | dstp += leftrow; | |
| 634 | ✗ | for (int i = 0; i<rightbytes; i += 6) { | |
| 635 | ✗ | *(uint16_t*)(dstp+i) = clr0; | |
| 636 | ✗ | *(uint32_t*)(dstp+i+2) = clr1; | |
| 637 | } | ||
| 638 | ✗ | dstp += rightrow; | |
| 639 | } | ||
| 640 | ✗ | for (int y = bot; y>0; --y) { | |
| 641 | ✗ | for (int i = 0; i<dst_row_size; i += 6) { | |
| 642 | ✗ | *(uint16_t*)(dstp+i) = clr0; | |
| 643 | ✗ | *(uint32_t*)(dstp+i+2) = clr1; | |
| 644 | } | ||
| 645 | ✗ | dstp += dst_pitch; | |
| 646 | } | ||
| 647 |
2/4✓ Branch 128 → 129 taken 1 time.
✗ Branch 128 → 151 not taken.
✓ Branch 129 → 130 taken 1 time.
✗ Branch 129 → 147 not taken.
|
1 | } else if (vi.IsRGB64()) { |
| 648 |
1/2✓ Branch 130 → 131 taken 1 time.
✗ Branch 130 → 151 not taken.
|
1 | BitBlt(dstp+initial_black, dst_pitch, srcp, src_pitch, src_row_size, src_height); |
| 649 | |||
| 650 | uint64_t clr64 = | ||
| 651 | 1 | ((uint64_t)GetHbdColorFromByte<uint16_t>((clr >> 24) & 0xFF, true, 16, false) << (24 * 2)) + | |
| 652 | 1 | ((uint64_t)GetHbdColorFromByte<uint16_t>((clr >> 16) & 0xFF, true, 16, false) << (16 * 2)) + | |
| 653 | 1 | ((uint64_t)GetHbdColorFromByte<uint16_t>((clr >> 8) & 0xFF, true, 16, false) << (8 * 2)) + | |
| 654 | 1 | ((uint64_t)GetHbdColorFromByte<uint16_t>((clr) & 0xFF, true, 16, false)); | |
| 655 | |||
| 656 |
2/2✓ Branch 137 → 136 taken 9 times.
✓ Branch 137 → 138 taken 1 time.
|
10 | for (int i = 0; i<initial_black; i += 8) { |
| 657 | 9 | *(uint64_t*)(dstp+i) = clr64; | |
| 658 | } | ||
| 659 | 1 | dstp += initial_black + src_row_size; | |
| 660 |
2/2✓ Branch 143 → 139 taken 2 times.
✓ Branch 143 → 144 taken 1 time.
|
3 | for (int y = src_height-1; y>0; --y) { |
| 661 |
2/2✓ Branch 141 → 140 taken 10 times.
✓ Branch 141 → 142 taken 2 times.
|
12 | for (int i = 0; i<middle_black; i += 8) { |
| 662 | 10 | *(uint64_t*)(dstp+i) = clr64; | |
| 663 | } | ||
| 664 | 2 | dstp += dst_pitch; | |
| 665 | } // for y | ||
| 666 |
2/2✓ Branch 146 → 145 taken 12 times.
✓ Branch 146 → 147 taken 1 time.
|
13 | for (int i = 0; i<final_black; i += 8) { |
| 667 | 12 | *(uint64_t*)(dstp+i) = clr64; | |
| 668 | } | ||
| 669 | } | ||
| 670 | |||
| 671 | 2 | return dst; | |
| 672 | 6 | } | |
| 673 | |||
| 674 | // Optional transient area filtering when radius > 0 | ||
| 675 | // The primary aim to blur the border neighborhood to prevent excessive ringing on | ||
| 676 | // a following upscaleing process | ||
| 677 | ✗ | static PClip AddBorderPostProcess(PClip child, | |
| 678 | int left, int top, int right, int bottom, | ||
| 679 | const AVSValue& _resample, const AVSValue& _param1, const AVSValue& _param2, const AVSValue& _param3, const AVSValue& _flt_rad, | ||
| 680 | int forced_chroma_placement, | ||
| 681 | IScriptEnvironment* env) { | ||
| 682 | |||
| 683 | // filtering radius, default 0: no transient area filtering | ||
| 684 | ✗ | int r = _flt_rad.AsInt(0); | |
| 685 | |||
| 686 | ✗ | if (r == 0) | |
| 687 | ✗ | return child; | |
| 688 | |||
| 689 | // Default: only the border side gets the blur treatment | ||
| 690 | // Minus "r": only the outer - added border - part is blurred | ||
| 691 | // though this is usually not enough to prevent ringing when upscaling. | ||
| 692 | ✗ | const bool both_side = (r > 0); | |
| 693 | ✗ | if (r < 0) | |
| 694 | ✗ | r = -r; | |
| 695 | |||
| 696 | ✗ | const VideoInfo& vi = child->GetVideoInfo(); | |
| 697 | |||
| 698 | /*if (vi.IsYUY2()) | ||
| 699 | env->ThrowError("AddBorders: YUY2 transient filtering not supported, use YV16."); | ||
| 700 | */ | ||
| 701 | |||
| 702 | ✗ | AVSValue param1 = _param1; | |
| 703 | ✗ | AVSValue param2 = _param2; | |
| 704 | ✗ | AVSValue param3 = _param3; | |
| 705 | |||
| 706 | // evaluate resample parameters only radius > 0 | ||
| 707 | ✗ | const char* resampler_name = _resample.AsString("gauss"); | |
| 708 | ✗ | if (_stricmp(resampler_name, "gauss") == 0) { | |
| 709 | // for gauss, defaults are different from what we use in chroma resamplers. | ||
| 710 | // here we use this filter for blurring (convolution use) | ||
| 711 | // p = 10, b = 2.71828, s = 0 | ||
| 712 | ✗ | param1 = _param1.AsDblDef(10); // p | |
| 713 | ✗ | param2 = _param2.AsDblDef(2.718281828); // b | |
| 714 | ✗ | param3 = _param3.AsDblDef(0); // 0 | |
| 715 | } | ||
| 716 | ✗ | ResamplingFunction* filter = getResampler(resampler_name, param1, param2, param3, false, env); | |
| 717 | ✗ | if (filter == nullptr) | |
| 718 | ✗ | env->ThrowError("AddBorders: unknown resampler name: %s", resampler_name); | |
| 719 | |||
| 720 | ✗ | const bool grey = vi.IsY(); | |
| 721 | ✗ | const bool isRGBPfamily = vi.IsPlanarRGB() || vi.IsPlanarRGBA(); | |
| 722 | |||
| 723 | ✗ | const int shift_w = (vi.IsPlanar() && !grey && !isRGBPfamily) ? vi.GetPlaneWidthSubsampling(PLANAR_U) : 0; | |
| 724 | ✗ | const int shift_h = (vi.IsPlanar() && !grey && !isRGBPfamily) ? vi.GetPlaneHeightSubsampling(PLANAR_U) : 0; | |
| 725 | ✗ | const int shift = max(shift_w, shift_h); // worst case | |
| 726 | |||
| 727 | // adjust radius for worst case chroma | ||
| 728 | ✗ | r = (r + (1 << shift) - 1) & ~((1 << shift) - 1); // chroma friendly | |
| 729 | |||
| 730 | ✗ | const int MIN_FILTERING_EXTENT = 10; // +/- | |
| 731 | // but if one of the margins are smaller, e.g. 5, the the 2*10 is achieved as 5+15 pixel wide (high) parts | ||
| 732 | // We always filter a larger area, but only copy the 2*radius (r) pixels from it. | ||
| 733 | // a radius plus the filter support size overrides | ||
| 734 | ✗ | int filtering_width = max(MIN_FILTERING_EXTENT, r + (int)std::ceil(filter->support())); | |
| 735 | |||
| 736 | // adjust the filtering width for the worst case, considering the chroma subsampling | ||
| 737 | ✗ | filtering_width = (filtering_width + (1 << shift) - 1) & ~((1 << shift) - 1); | |
| 738 | // active area before adding the new borders | ||
| 739 | ✗ | const int orig_width = vi.width - left - right; | |
| 740 | ✗ | const int orig_height = vi.height - top - bottom; | |
| 741 | |||
| 742 | // End of safety adjustments | ||
| 743 | // Radius "r" and "filtering_width" are both +/- values and are chroma and resizer friendly. | ||
| 744 | // left, right, top, bottom are already chroma subsample friendly values | ||
| 745 | |||
| 746 | /* | ||
| 747 | Create up to 8 sections. | ||
| 748 | |||
| 749 | left, top, right, bottom and the four corner bars mark the convolution (blur) area. | ||
| 750 | - left and right needs only force horizontal resizer | ||
| 751 | - top and bottom bars force vertical resizer | ||
| 752 | - corners force both H and V resizer | ||
| 753 | +---+-------------------+ | ||
| 754 | | oo|ooooooooooooooo|oo | | ||
| 755 | +-o-+-----------------o-+ | ||
| 756 | | o | | o | | ||
| 757 | | o | | o | | ||
| 758 | | o | | o | | ||
| 759 | | o | | o | | ||
| 760 | | o | | o | | ||
| 761 | | o | | o | | ||
| 762 | +-o-+---------------+-o-+ | ||
| 763 | | oo|ooooooooooooooo|oo | | ||
| 764 | +---+---------------+---+ | ||
| 765 | */ | ||
| 766 | |||
| 767 | typedef struct { | ||
| 768 | PClip clip; // a smart pointer | ||
| 769 | int extent_outer_horiz, extent_inner_horiz; // may not be symmetric | ||
| 770 | int extent_outer_vert, extent_inner_vert; | ||
| 771 | int crop_x, crop_y; | ||
| 772 | int target_x, target_y; | ||
| 773 | int target_width, target_height; | ||
| 774 | int src_x, src_y; | ||
| 775 | int src_width, src_height; | ||
| 776 | int force; | ||
| 777 | // 0 - return unchanged if no resize needed | ||
| 778 | // 1 - force H - Horizontal resizing phase, For vertical bars | ||
| 779 | // 2 - force V - Vertical resizing phase, For horizontal bars | ||
| 780 | // 3 - force H and V for corner rectangles | ||
| 781 | } BarSection; | ||
| 782 | |||
| 783 | ✗ | std::vector<BarSection> bars; | |
| 784 | |||
| 785 | /* Example on LEFT and RIGHT vertical bar | ||
| 786 | |||
| 787 | extent_outer extent_inner extent_inner extent_outer | ||
| 788 | <------>|<---------> <------>|<---------> | ||
| 789 | |||
| 790 | r*2 r*2 | ||
| 791 | |<>|<>| orig_width |<>|<>| | ||
| 792 | <------------------------------------> | ||
| 793 | +----+--|--+-------+ ^ +----+--|--+-------+ | ||
| 794 | | | | | | | | | | | | | ||
| 795 | | | | | | |orig_height | | | | | | ||
| 796 | | | | | | | | | | | | | ||
| 797 | | | | | | | | | | | | | ||
| 798 | | | | | | | | | | | | | ||
| 799 | +----+--|--+-------+ V +----+--|--+-------+ | ||
| 800 | |||
| 801 | The extent_inner+extent_outer area is cropped and blurred (filtered) with the given algoritm, e.g "gauss". | ||
| 802 | From this blurred Clip only the (2*r) * orig_height rectangle is copied back onto the transient area. | ||
| 803 | */ | ||
| 804 | |||
| 805 | // Define bar sections data for iteration | ||
| 806 | |||
| 807 | struct BarSectionTemplate { | ||
| 808 | int side; // 0=left, 1=right, 2=top, 3=bottom 4=top-left 5=top-right 6=bottom-left 7=bottom-right | ||
| 809 | int direction; // 1=horizontally, 2=vertically filtere, 3=both (corners) | ||
| 810 | }; | ||
| 811 | |||
| 812 | ✗ | const BarSectionTemplate templates[] = { | |
| 813 | {0, 1}, // left bar (horizontally filtered) | ||
| 814 | {1, 1}, // right bar (horizontally filtered) | ||
| 815 | {2, 2}, // top bar (vertically filtered) | ||
| 816 | {3, 2}, // bottom bar (vertically filtered) | ||
| 817 | {4, 3}, // top left rectangle (H-V filtered) | ||
| 818 | {5, 3}, // top right rectangle (H-V filtered) | ||
| 819 | {6, 3}, // bottom left rectangle (H-V filtered) | ||
| 820 | {7, 3} // bottom right rectangle (H-V filtered) | ||
| 821 | }; | ||
| 822 | |||
| 823 | // First cycle: initialize common parameters and calculate dimensions | ||
| 824 | ✗ | for (int i = 0; i < 8; i++) { | |
| 825 | ✗ | BarSection bar = {}; | |
| 826 | |||
| 827 | ✗ | const bool isHorizontallyFiltered = (templates[i].direction == 1) || (templates[i].direction == 3); | |
| 828 | ✗ | const bool isVerticallyFiltered = (templates[i].direction == 2) || (templates[i].direction == 3); | |
| 829 | ✗ | const int side = templates[i].side; | |
| 830 | |||
| 831 | // Calculate border to use based on side | ||
| 832 | int borderSize, borderSize2; | ||
| 833 | ✗ | switch (side) { | |
| 834 | ✗ | case 0: borderSize = left; borderSize2 = 0; break; | |
| 835 | ✗ | case 1: borderSize = right; borderSize2 = 0; break; | |
| 836 | ✗ | case 2: borderSize = 0; borderSize2 = top; break; | |
| 837 | ✗ | case 3: borderSize = 0; borderSize2 = bottom; break; | |
| 838 | ✗ | case 4: borderSize = left; borderSize2 = top; break; | |
| 839 | ✗ | case 5: borderSize = right; borderSize2 = top; break; | |
| 840 | ✗ | case 6: borderSize = left; borderSize2 = bottom; break; | |
| 841 | ✗ | case 7: borderSize = right; borderSize2 = bottom; break; | |
| 842 | } | ||
| 843 | |||
| 844 | ✗ | int safe_flt_rad = r; | |
| 845 | ✗ | if (borderSize > 0) { // same as isHorizontallyFiltered | |
| 846 | ✗ | bar.extent_outer_horiz = std::min(filtering_width, borderSize); | |
| 847 | ✗ | bar.extent_inner_horiz = 2 * filtering_width - bar.extent_outer_horiz; | |
| 848 | } | ||
| 849 | ✗ | if (borderSize2 > 0) { // same as(isVerticallyFiltered | |
| 850 | ✗ | bar.extent_outer_vert = std::min(filtering_width, borderSize2); | |
| 851 | ✗ | bar.extent_inner_vert = 2 * filtering_width - bar.extent_outer_vert; | |
| 852 | } | ||
| 853 | |||
| 854 | ✗ | if (isHorizontallyFiltered) { | |
| 855 | ✗ | safe_flt_rad = std::min(safe_flt_rad, borderSize); | |
| 856 | ✗ | bar.extent_inner_horiz = std::min(bar.extent_inner_horiz, orig_width); | |
| 857 | } | ||
| 858 | ✗ | if (isVerticallyFiltered) { | |
| 859 | ✗ | safe_flt_rad = std::min(safe_flt_rad, borderSize2); | |
| 860 | ✗ | bar.extent_inner_vert = std::min(bar.extent_inner_vert, orig_height); | |
| 861 | } | ||
| 862 | |||
| 863 | ✗ | int safe_flt_rad_inner = both_side ? safe_flt_rad : 0; | |
| 864 | |||
| 865 | ✗ | int safe_flt_rad_inner_horiz = std::min(bar.extent_inner_horiz, safe_flt_rad_inner); | |
| 866 | ✗ | int safe_flt_rad_inner_vert = std::min(bar.extent_inner_vert, safe_flt_rad_inner); | |
| 867 | |||
| 868 | // Set force direction | ||
| 869 | ✗ | bar.force = templates[i].direction; | |
| 870 | |||
| 871 | // Set dimensions based on direction and side | ||
| 872 | ✗ | if (isHorizontallyFiltered && isVerticallyFiltered) { // corners | |
| 873 | ✗ | bar.target_width = bar.extent_outer_horiz + bar.extent_inner_horiz; | |
| 874 | ✗ | bar.target_height = bar.extent_outer_vert + bar.extent_inner_vert; | |
| 875 | ✗ | bar.src_width = safe_flt_rad + safe_flt_rad_inner_horiz; | |
| 876 | ✗ | bar.src_height = safe_flt_rad + safe_flt_rad_inner_vert; | |
| 877 | |||
| 878 | ✗ | if (side == 4 || side == 6) { // Top Left Bottom Left | |
| 879 | ✗ | bar.crop_x = left - bar.extent_outer_horiz; | |
| 880 | ✗ | bar.target_x = left - safe_flt_rad; | |
| 881 | ✗ | bar.src_x = bar.extent_outer_horiz - safe_flt_rad; | |
| 882 | } | ||
| 883 | else { // Top Right Bottom Right | ||
| 884 | ✗ | bar.crop_x = left + orig_width - bar.extent_inner_horiz; | |
| 885 | ✗ | bar.target_x = left + orig_width - safe_flt_rad_inner_horiz; | |
| 886 | ✗ | bar.src_x = bar.extent_inner_horiz - safe_flt_rad_inner_horiz; | |
| 887 | } | ||
| 888 | |||
| 889 | ✗ | if (side == 4 || side == 5) { // Top Left Top Right | |
| 890 | ✗ | bar.crop_y = top - bar.extent_outer_vert; | |
| 891 | ✗ | bar.target_y = top - safe_flt_rad; | |
| 892 | ✗ | bar.src_y = bar.extent_outer_vert - safe_flt_rad; | |
| 893 | } | ||
| 894 | else { // Bottom Left Bottom Right | ||
| 895 | ✗ | bar.crop_y = top + orig_height - bar.extent_inner_vert; | |
| 896 | ✗ | bar.target_y = top + orig_height - safe_flt_rad_inner_vert; | |
| 897 | ✗ | bar.src_y = bar.extent_inner_vert - safe_flt_rad_inner_vert; | |
| 898 | } | ||
| 899 | } | ||
| 900 | ✗ | else if (isHorizontallyFiltered) { | |
| 901 | // Vertical but horizontally filtered bars on the left/right side | ||
| 902 | ✗ | bar.target_width = bar.extent_outer_horiz + bar.extent_inner_horiz; | |
| 903 | ✗ | bar.target_height = orig_height; | |
| 904 | ✗ | bar.src_width = safe_flt_rad + safe_flt_rad_inner_horiz; | |
| 905 | ✗ | bar.src_height = orig_height; | |
| 906 | |||
| 907 | ✗ | if (side == 0) { // Left | |
| 908 | ✗ | bar.crop_x = left - bar.extent_outer_horiz;; | |
| 909 | ✗ | bar.crop_y = top; | |
| 910 | ✗ | bar.target_x = left - safe_flt_rad; | |
| 911 | ✗ | bar.target_y = top; | |
| 912 | ✗ | bar.src_x = bar.extent_outer_horiz - safe_flt_rad; | |
| 913 | |||
| 914 | } | ||
| 915 | else { // Right | ||
| 916 | ✗ | bar.crop_x = left + orig_width - bar.extent_inner_horiz; | |
| 917 | ✗ | bar.crop_y = top; | |
| 918 | ✗ | bar.target_x = left + orig_width - safe_flt_rad_inner_horiz; | |
| 919 | ✗ | bar.target_y = top; | |
| 920 | ✗ | bar.src_x = bar.extent_inner_horiz - safe_flt_rad_inner_horiz; | |
| 921 | } | ||
| 922 | |||
| 923 | ✗ | bar.src_y = 0; | |
| 924 | } | ||
| 925 | else { | ||
| 926 | // Horizontal, but vertically filtered bars (top/bottom) | ||
| 927 | ✗ | bar.target_width = orig_width; | |
| 928 | ✗ | bar.target_height = bar.extent_outer_vert + bar.extent_inner_vert; | |
| 929 | ✗ | bar.src_width = orig_width; | |
| 930 | ✗ | bar.src_height = safe_flt_rad + safe_flt_rad_inner_vert; | |
| 931 | |||
| 932 | ✗ | if (side == 2) { // Top | |
| 933 | ✗ | bar.crop_x = left; | |
| 934 | ✗ | bar.crop_y = top - bar.extent_outer_vert; | |
| 935 | ✗ | bar.target_x = left; | |
| 936 | ✗ | bar.target_y = top - safe_flt_rad; | |
| 937 | ✗ | bar.src_y = bar.extent_outer_vert - safe_flt_rad; | |
| 938 | } | ||
| 939 | else { // Bottom | ||
| 940 | ✗ | bar.crop_x = left; | |
| 941 | ✗ | bar.crop_y = top + orig_height - bar.extent_inner_vert; | |
| 942 | ✗ | bar.target_x = left; | |
| 943 | ✗ | bar.target_y = top + orig_height - safe_flt_rad_inner_vert; | |
| 944 | ✗ | bar.src_y = bar.extent_inner_vert - safe_flt_rad_inner_vert; | |
| 945 | } | ||
| 946 | |||
| 947 | ✗ | bar.src_x = 0; | |
| 948 | } | ||
| 949 | |||
| 950 | // avoid "Resize: Source image too small for this resize method. Width=%d, Support=%d", source_size, int(ceil(filter_support))" | ||
| 951 | // int source_size, double crop_size, int target_size | ||
| 952 | // all are the same here | ||
| 953 | // whether H or V resizing is forced, only check for that dimension | ||
| 954 | ✗ | bool ok = true; | |
| 955 | ✗ | if (isHorizontallyFiltered && bar.target_width <= 0) ok = false; | |
| 956 | ✗ | if (isVerticallyFiltered && bar.target_height <= 0) ok = false; | |
| 957 | // size is indifferent since avs 3.7.4, resizers are robust, accept anything, | ||
| 958 | // no other size constraint check is needed. | ||
| 959 | |||
| 960 | ✗ | if(ok) | |
| 961 | ✗ | bars.push_back(bar); | |
| 962 | ✗ | } | |
| 963 | |||
| 964 | ✗ | std::vector<PClip> child_array = { child }; | |
| 965 | ✗ | std::vector<int> position_array = { }; | |
| 966 | |||
| 967 | ✗ | const bool preserve_center = true; | |
| 968 | ✗ | const char* placement_name = nullptr; | |
| 969 | // along with forced_chroma_placement, does not read frame props again in eight child resizers | ||
| 970 | // _ChromaLocation - if any - was read in AddBorders - once - and passed here | ||
| 971 | |||
| 972 | ✗ | for (auto& bar : bars) { | |
| 973 | // or use [src_left]f[src_top]f[src_width]f[src_height]f | ||
| 974 | // resizer parameters set for convolution (unchanged dimensions) filter | ||
| 975 | /* When we directly pass source position, it's not possible to govern the directional "force", anyway, it would just call crop as well. | ||
| 976 | AVSValue args_left_top_w_h[4] = {bar.crop_x, bar.crop_y, bar.target_width, bar.target_height}; // left, top, width (auto), height (auto) | ||
| 977 | bar.clip = FilteredResize::CreateResize(child, bar.target_width, bar.target_height, args_left_top_w_h, bar.force, filter, env); | ||
| 978 | */ | ||
| 979 | ✗ | AVSValue args_left_top_w_h[4] = { 0, 0, AVSValue(), AVSValue() }; // left, top, width (auto), height (auto) | |
| 980 | |||
| 981 | ✗ | bar.clip = FilteredResize::CreateResize( | |
| 982 | ✗ | new Crop(bar.crop_x, bar.crop_y, bar.target_width, bar.target_height, 0, child, env), | |
| 983 | bar.target_width, bar.target_height, args_left_top_w_h, bar.force, filter, | ||
| 984 | preserve_center, placement_name, forced_chroma_placement, | ||
| 985 | env); | ||
| 986 | |||
| 987 | |||
| 988 | // Add to vector | ||
| 989 | ✗ | child_array.push_back(bar.clip); | |
| 990 | ✗ | position_array.push_back(bar.target_x); | |
| 991 | ✗ | position_array.push_back(bar.target_y); | |
| 992 | // we can copy only a smaller part from the filtered area | ||
| 993 | // After blurring e.g. a 10x10 rectangle, we'd copy only from a radius of +/-1 or +/-2 | ||
| 994 | ✗ | position_array.push_back(bar.src_x); | |
| 995 | ✗ | position_array.push_back(bar.src_y); | |
| 996 | ✗ | position_array.push_back(bar.src_width); | |
| 997 | ✗ | position_array.push_back(bar.src_height); | |
| 998 | ✗ | } | |
| 999 | |||
| 1000 | ✗ | PClip clip = new MultiOverlay(child_array, position_array, env); | |
| 1001 | |||
| 1002 | ✗ | delete filter; | |
| 1003 | |||
| 1004 | ✗ | return clip; | |
| 1005 | ✗ | } | |
| 1006 | |||
| 1007 | |||
| 1008 | ✗ | AVSValue __cdecl AddBorders::Create(AVSValue args, void*, IScriptEnvironment* env) | |
| 1009 | { | ||
| 1010 | // [0][1][2][3][4] [5] [6] [7] [8] [9] [10] [11] | ||
| 1011 | // c i i i i [color]i[color_yuv]i[resample]s[param1]f[param2]f[param3]f[r]i | ||
| 1012 | // int left, int top, int right, int bottom | ||
| 1013 | |||
| 1014 | // similar to BlankClip | ||
| 1015 | ✗ | int color = args[5].AsInt(0); | |
| 1016 | ✗ | bool color_as_yuv = false; | |
| 1017 | |||
| 1018 | ✗ | const VideoInfo& vi = args[0].AsClip()->GetVideoInfo(); | |
| 1019 | |||
| 1020 | ✗ | if (args[6].Defined()) { | |
| 1021 | ✗ | if (color != 0) // Not quite 100% test | |
| 1022 | ✗ | env->ThrowError("AddBorders: color and color_yuv are mutually exclusive"); | |
| 1023 | |||
| 1024 | ✗ | if (!vi.IsYUV() && !vi.IsYUVA()) | |
| 1025 | ✗ | env->ThrowError("AddBorders: color_yuv only valid for YUV color spaces"); | |
| 1026 | ✗ | color = args[6].AsInt(); // override | |
| 1027 | ✗ | color_as_yuv = true; | |
| 1028 | } | ||
| 1029 | |||
| 1030 | ✗ | const int left = max(0, args[1].AsInt()); | |
| 1031 | ✗ | const int top = max(0, args[2].AsInt()); | |
| 1032 | ✗ | const int right = max(0, args[3].AsInt()); | |
| 1033 | ✗ | const int bottom = max(0, args[4].AsInt()); | |
| 1034 | |||
| 1035 | ✗ | int forced_chroma_placement = ChromaLocation_e::AVS_CHROMA_UNUSED; | |
| 1036 | ✗ | if (vi.IsYV411() || vi.Is420() || vi.Is422()) { | |
| 1037 | ✗ | auto frame0 = args[0].AsClip()->GetFrame(0, env); | |
| 1038 | ✗ | const AVSMap* props = env->getFramePropsRO(frame0); | |
| 1039 | ✗ | if (props) { | |
| 1040 | ✗ | if (env->propNumElements(props, "_ChromaLocation") > 0) { | |
| 1041 | ✗ | forced_chroma_placement = (int)env->propGetIntSaturated(props, "_ChromaLocation", 0, nullptr); | |
| 1042 | } | ||
| 1043 | } | ||
| 1044 | ✗ | } | |
| 1045 | |||
| 1046 | // here we have read _ChromaLocation, in order to pass it directly to the many blurring resizers to prevent them | ||
| 1047 | // to read up to 8x GetFrame(0) in their init for getting the same frame properties like we had. | ||
| 1048 | |||
| 1049 | ✗ | PClip clip = new AddBorders( left, top, right, bottom, color, color_as_yuv, args[0].AsClip(), env); | |
| 1050 | |||
| 1051 | // args[7], args[8], args[9], args[10], args[11], // [resample]s[param1]f[param2]f[param3]f[r]i | ||
| 1052 | |||
| 1053 | ✗ | clip = AddBorderPostProcess(clip, left, top, right, bottom, args[7], args[8], args[9], args[10], args[11], forced_chroma_placement, env); | |
| 1054 | |||
| 1055 | ✗ | return clip; | |
| 1056 | ✗ | } | |
| 1057 | |||
| 1058 | |||
| 1059 | /********************************** | ||
| 1060 | ******* Factory Methods ****** | ||
| 1061 | *********************************/ | ||
| 1062 | |||
| 1063 | |||
| 1064 | ✗ | AVSValue __cdecl Create_Letterbox(AVSValue args, void*, IScriptEnvironment* env) | |
| 1065 | { | ||
| 1066 | ✗ | PClip clip = args[0].AsClip(); | |
| 1067 | ✗ | int top = args[1].AsInt(); | |
| 1068 | ✗ | int bottom = args[2].AsInt(); | |
| 1069 | ✗ | int left = args[3].AsInt(0); | |
| 1070 | ✗ | int right = args[4].AsInt(0); | |
| 1071 | ✗ | int color = args[5].AsInt(0); | |
| 1072 | ✗ | const VideoInfo& vi = clip->GetVideoInfo(); | |
| 1073 | |||
| 1074 | // [0][1][2][3] [4] [5] [6] [7] [8] [9] [10] [11] | ||
| 1075 | // c i i [x1]i [x2]i [color]i [color_yuv]i[resample]s[param1]f[param2]f[param3]f[r]i | ||
| 1076 | // top, bottom, [left], [right] [,color] [,color_yuv] | ||
| 1077 | |||
| 1078 | // similar to BlankClip/AddBorders | ||
| 1079 | ✗ | bool color_as_yuv = false; | |
| 1080 | ✗ | if (args[6].Defined()) { | |
| 1081 | ✗ | if (color != 0) // Not quite 100% test | |
| 1082 | ✗ | env->ThrowError("LetterBox: color and color_yuv are mutually exclusive"); | |
| 1083 | |||
| 1084 | ✗ | if (!vi.IsYUV() && !vi.IsYUVA()) | |
| 1085 | ✗ | env->ThrowError("LetterBox: color_yuv only valid for YUV color spaces"); | |
| 1086 | ✗ | color = args[6].AsInt(); // override | |
| 1087 | ✗ | color_as_yuv = true; | |
| 1088 | } | ||
| 1089 | |||
| 1090 | ✗ | if ( (top<0) || (bottom<0) || (left<0) || (right<0) ) | |
| 1091 | ✗ | env->ThrowError("LetterBox: You cannot specify letterboxing less than 0."); | |
| 1092 | ✗ | if (top+bottom>=vi.height) // Must be >= otherwise it is interpreted wrong by crop() | |
| 1093 | ✗ | env->ThrowError("LetterBox: You cannot specify letterboxing that is bigger than the picture (height)."); | |
| 1094 | ✗ | if (right+left>=vi.width) // Must be >= otherwise it is interpreted wrong by crop() | |
| 1095 | ✗ | env->ThrowError("LetterBox: You cannot specify letterboxing that is bigger than the picture (width)."); | |
| 1096 | |||
| 1097 | ✗ | if (vi.IsYUV() || vi.IsYUVA()) { | |
| 1098 | ✗ | int xsub = 0; | |
| 1099 | ✗ | int ysub = 0; | |
| 1100 | |||
| 1101 | ✗ | if (vi.NumComponents() > 1) { | |
| 1102 | ✗ | xsub=vi.GetPlaneWidthSubsampling(PLANAR_U); | |
| 1103 | ✗ | ysub=vi.GetPlaneHeightSubsampling(PLANAR_U); | |
| 1104 | } | ||
| 1105 | ✗ | const int xmask = (1 << xsub) - 1; | |
| 1106 | ✗ | const int ymask = (1 << ysub) - 1; | |
| 1107 | |||
| 1108 | // YUY2, etc, ... can only operate to even pixel boundaries | ||
| 1109 | ✗ | if (left & xmask) | |
| 1110 | ✗ | env->ThrowError("LetterBox: YUV images width must be divideable by %d (left side).", xmask+1); | |
| 1111 | ✗ | if (right & xmask) | |
| 1112 | ✗ | env->ThrowError("LetterBox: YUV images width must be divideable by %d (right side).", xmask+1); | |
| 1113 | |||
| 1114 | ✗ | if (top & ymask) | |
| 1115 | ✗ | env->ThrowError("LetterBox: YUV images height must be divideable by %d (top).", ymask+1); | |
| 1116 | ✗ | if (bottom & ymask) | |
| 1117 | ✗ | env->ThrowError("LetterBox: YUV images height must be divideable by %d (bottom).", ymask+1); | |
| 1118 | } | ||
| 1119 | |||
| 1120 | ✗ | left = max(0, left); | |
| 1121 | ✗ | top = max(0, top); | |
| 1122 | ✗ | right = max(0, right); | |
| 1123 | ✗ | bottom = max(0, bottom); | |
| 1124 | |||
| 1125 | ✗ | int forced_chroma_placement = ChromaLocation_e::AVS_CHROMA_UNUSED; | |
| 1126 | ✗ | if (vi.IsYV411() || vi.Is420() || vi.Is422()) { | |
| 1127 | ✗ | auto frame0 = clip->GetFrame(0, env); | |
| 1128 | ✗ | const AVSMap* props = env->getFramePropsRO(frame0); | |
| 1129 | ✗ | if (props) { | |
| 1130 | ✗ | if (env->propNumElements(props, "_ChromaLocation") > 0) { | |
| 1131 | ✗ | forced_chroma_placement = (int)env->propGetIntSaturated(props, "_ChromaLocation", 0, nullptr); | |
| 1132 | } | ||
| 1133 | } | ||
| 1134 | ✗ | } | |
| 1135 | |||
| 1136 | ✗ | clip = new AddBorders(left, top, right, bottom, color, color_as_yuv, new Crop(left, top, vi.width-left-right, vi.height-top-bottom, 0, clip, env), env); | |
| 1137 | |||
| 1138 | // args[7], args[8], args[9], args[10], args[11], // [resample]s[param1]f[param2]f[param3]f[r]i | ||
| 1139 | |||
| 1140 | ✗ | clip = AddBorderPostProcess(clip, left, top, right, bottom, args[7], args[8], args[9], args[10], args[11], forced_chroma_placement, env); | |
| 1141 | |||
| 1142 | ✗ | return clip; | |
| 1143 | |||
| 1144 | ✗ | } | |
| 1145 | |||
| 1146 | |||
| 1147 | ✗ | AVSValue __cdecl Create_CropBottom(AVSValue args, void*, IScriptEnvironment* env) | |
| 1148 | { | ||
| 1149 | ✗ | PClip clip = args[0].AsClip(); | |
| 1150 | ✗ | const VideoInfo& vi = clip->GetVideoInfo(); | |
| 1151 | ✗ | return new Crop(0, 0, vi.width, vi.height - args[1].AsInt(), 0, clip, env); | |
| 1152 | ✗ | } | |
| 1153 |