Line | Branch | Exec | Source |
---|---|---|---|
1 | /* | ||
2 | * Copyright (c) 2010 Niel van der Westhuizen <nielkie@gmail.com> | ||
3 | * Copyright (c) 2002 A'rpi | ||
4 | * Copyright (c) 1997-2001 ZSNES Team ( zsknight@zsnes.com / _demo_@zsnes.com ) | ||
5 | * | ||
6 | * This file is part of FFmpeg. | ||
7 | * | ||
8 | * FFmpeg is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * FFmpeg is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License along | ||
19 | * with FFmpeg; if not, write to the Free Software Foundation, Inc., | ||
20 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | */ | ||
22 | |||
23 | /** | ||
24 | * @file | ||
25 | * Super 2xSaI video filter | ||
26 | * Ported from MPlayer libmpcodecs/vf_2xsai.c. | ||
27 | */ | ||
28 | |||
29 | #include "libavutil/pixdesc.h" | ||
30 | #include "libavutil/intreadwrite.h" | ||
31 | #include "avfilter.h" | ||
32 | #include "filters.h" | ||
33 | #include "video.h" | ||
34 | |||
35 | typedef struct Super2xSaIContext { | ||
36 | /* masks used for two pixels interpolation */ | ||
37 | uint32_t hi_pixel_mask; | ||
38 | uint32_t lo_pixel_mask; | ||
39 | |||
40 | /* masks used for four pixels interpolation */ | ||
41 | uint32_t q_hi_pixel_mask; | ||
42 | uint32_t q_lo_pixel_mask; | ||
43 | |||
44 | int bpp; ///< bytes per pixel, pixel stride for each (packed) pixel | ||
45 | int is_be; | ||
46 | } Super2xSaIContext; | ||
47 | |||
48 | typedef struct ThreadData { | ||
49 | AVFrame *in, *out; | ||
50 | } ThreadData; | ||
51 | |||
52 | #define GET_RESULT(A, B, C, D) ((A != C || A != D) - (B != C || B != D)) | ||
53 | |||
54 | #define INTERPOLATE(A, B) (((A & hi_pixel_mask) >> 1) + ((B & hi_pixel_mask) >> 1) + (A & B & lo_pixel_mask)) | ||
55 | |||
56 | #define Q_INTERPOLATE(A, B, C, D) ((A & q_hi_pixel_mask) >> 2) + ((B & q_hi_pixel_mask) >> 2) + ((C & q_hi_pixel_mask) >> 2) + ((D & q_hi_pixel_mask) >> 2) \ | ||
57 | + ((((A & q_lo_pixel_mask) + (B & q_lo_pixel_mask) + (C & q_lo_pixel_mask) + (D & q_lo_pixel_mask)) >> 2) & q_lo_pixel_mask) | ||
58 | |||
59 | 14 | static int super2xsai(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) | |
60 | { | ||
61 | 14 | Super2xSaIContext *s = ctx->priv; | |
62 | 14 | ThreadData *td = arg; | |
63 | 14 | AVFrame *in = td->in; | |
64 | 14 | AVFrame *out = td->out; | |
65 | 14 | const uint8_t *src = in->data[0]; | |
66 | 14 | uint8_t *dst = out->data[0]; | |
67 | 14 | const int src_linesize = in->linesize[0]; | |
68 | 14 | const int dst_linesize = out->linesize[0]; | |
69 | 14 | const int width = in->width; | |
70 | 14 | const int height = in->height; | |
71 | unsigned int x, y; | ||
72 | uint32_t color[4][4]; | ||
73 | const uint8_t *src_line[4]; | ||
74 | 14 | const int bpp = s->bpp; | |
75 | 14 | const uint32_t hi_pixel_mask = s->hi_pixel_mask; | |
76 | 14 | const uint32_t lo_pixel_mask = s->lo_pixel_mask; | |
77 | 14 | const uint32_t q_hi_pixel_mask = s->q_hi_pixel_mask; | |
78 | 14 | const uint32_t q_lo_pixel_mask = s->q_lo_pixel_mask; | |
79 | 14 | const int slice_start = (height * jobnr) / nb_jobs; | |
80 | 14 | const int slice_end = (height * (jobnr+1)) / nb_jobs; | |
81 | |||
82 | /* Point to the first 4 lines, first line is duplicated */ | ||
83 | 14 | src_line[0] = src + src_linesize*FFMAX(slice_start - 1, 0); | |
84 | 14 | src_line[1] = src + src_linesize*slice_start; | |
85 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
|
14 | src_line[2] = src + src_linesize*FFMIN(slice_start + 1, height-1); |
86 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
|
14 | src_line[3] = src + src_linesize*FFMIN(slice_start + 2, height-1); |
87 | |||
88 | #define READ_COLOR4(dst, src_line, off) dst = *((const uint32_t *)src_line + off) | ||
89 | #define READ_COLOR3(dst, src_line, off) dst = AV_RL24 (src_line + 3*off) | ||
90 | #define READ_COLOR2(dst, src_line, off) dst = s->is_be ? AV_RB16(src_line + 2 * off) : AV_RL16(src_line + 2 * off) | ||
91 | |||
92 |
2/2✓ Branch 0 taken 4032 times.
✓ Branch 1 taken 14 times.
|
4046 | for (y = slice_start; y < slice_end; y++) { |
93 | uint8_t *dst_line[2]; | ||
94 | |||
95 | 4032 | dst_line[0] = dst + dst_linesize*2*y; | |
96 | 4032 | dst_line[1] = dst + dst_linesize*(2*y+1); | |
97 | |||
98 |
3/3✓ Branch 0 taken 1152 times.
✓ Branch 1 taken 576 times.
✓ Branch 2 taken 2304 times.
|
4032 | switch (bpp) { |
99 | 1152 | case 4: | |
100 | 1152 | READ_COLOR4(color[0][0], src_line[0], 0); color[0][1] = color[0][0]; READ_COLOR4(color[0][2], src_line[0], 1); READ_COLOR4(color[0][3], src_line[0], 2); | |
101 | 1152 | READ_COLOR4(color[1][0], src_line[1], 0); color[1][1] = color[1][0]; READ_COLOR4(color[1][2], src_line[1], 1); READ_COLOR4(color[1][3], src_line[1], 2); | |
102 | 1152 | READ_COLOR4(color[2][0], src_line[2], 0); color[2][1] = color[2][0]; READ_COLOR4(color[2][2], src_line[2], 1); READ_COLOR4(color[2][3], src_line[2], 2); | |
103 | 1152 | READ_COLOR4(color[3][0], src_line[3], 0); color[3][1] = color[3][0]; READ_COLOR4(color[3][2], src_line[3], 1); READ_COLOR4(color[3][3], src_line[3], 2); | |
104 | 1152 | break; | |
105 | 576 | case 3: | |
106 | 576 | READ_COLOR3(color[0][0], src_line[0], 0); color[0][1] = color[0][0]; READ_COLOR3(color[0][2], src_line[0], 1); READ_COLOR3(color[0][3], src_line[0], 2); | |
107 | 576 | READ_COLOR3(color[1][0], src_line[1], 0); color[1][1] = color[1][0]; READ_COLOR3(color[1][2], src_line[1], 1); READ_COLOR3(color[1][3], src_line[1], 2); | |
108 | 576 | READ_COLOR3(color[2][0], src_line[2], 0); color[2][1] = color[2][0]; READ_COLOR3(color[2][2], src_line[2], 1); READ_COLOR3(color[2][3], src_line[2], 2); | |
109 | 576 | READ_COLOR3(color[3][0], src_line[3], 0); color[3][1] = color[3][0]; READ_COLOR3(color[3][2], src_line[3], 1); READ_COLOR3(color[3][3], src_line[3], 2); | |
110 | 576 | break; | |
111 | 2304 | default: | |
112 |
6/6✓ Branch 0 taken 1152 times.
✓ Branch 1 taken 1152 times.
✓ Branch 2 taken 1152 times.
✓ Branch 3 taken 1152 times.
✓ Branch 4 taken 1152 times.
✓ Branch 5 taken 1152 times.
|
2304 | READ_COLOR2(color[0][0], src_line[0], 0); color[0][1] = color[0][0]; READ_COLOR2(color[0][2], src_line[0], 1); READ_COLOR2(color[0][3], src_line[0], 2); |
113 |
6/6✓ Branch 0 taken 1152 times.
✓ Branch 1 taken 1152 times.
✓ Branch 2 taken 1152 times.
✓ Branch 3 taken 1152 times.
✓ Branch 4 taken 1152 times.
✓ Branch 5 taken 1152 times.
|
2304 | READ_COLOR2(color[1][0], src_line[1], 0); color[1][1] = color[1][0]; READ_COLOR2(color[1][2], src_line[1], 1); READ_COLOR2(color[1][3], src_line[1], 2); |
114 |
6/6✓ Branch 0 taken 1152 times.
✓ Branch 1 taken 1152 times.
✓ Branch 2 taken 1152 times.
✓ Branch 3 taken 1152 times.
✓ Branch 4 taken 1152 times.
✓ Branch 5 taken 1152 times.
|
2304 | READ_COLOR2(color[2][0], src_line[2], 0); color[2][1] = color[2][0]; READ_COLOR2(color[2][2], src_line[2], 1); READ_COLOR2(color[2][3], src_line[2], 2); |
115 |
6/6✓ Branch 0 taken 1152 times.
✓ Branch 1 taken 1152 times.
✓ Branch 2 taken 1152 times.
✓ Branch 3 taken 1152 times.
✓ Branch 4 taken 1152 times.
✓ Branch 5 taken 1152 times.
|
2304 | READ_COLOR2(color[3][0], src_line[3], 0); color[3][1] = color[3][0]; READ_COLOR2(color[3][2], src_line[3], 1); READ_COLOR2(color[3][3], src_line[3], 2); |
116 | } | ||
117 | |||
118 |
2/2✓ Branch 0 taken 1419264 times.
✓ Branch 1 taken 4032 times.
|
1423296 | for (x = 0; x < width; x++) { |
119 | uint32_t product1a, product1b, product2a, product2b; | ||
120 | |||
121 | //--------------------------------------- B0 B1 B2 B3 0 1 2 3 | ||
122 | // 4 5* 6 S2 -> 4 5* 6 7 | ||
123 | // 1 2 3 S1 8 9 10 11 | ||
124 | // A0 A1 A2 A3 12 13 14 15 | ||
125 | //-------------------------------------- | ||
126 |
4/4✓ Branch 0 taken 33902 times.
✓ Branch 1 taken 1385362 times.
✓ Branch 2 taken 33756 times.
✓ Branch 3 taken 146 times.
|
1419264 | if (color[2][1] == color[1][2] && color[1][1] != color[2][2]) { |
127 | 33756 | product2b = color[2][1]; | |
128 | 33756 | product1b = product2b; | |
129 |
4/4✓ Branch 0 taken 1900 times.
✓ Branch 1 taken 1383608 times.
✓ Branch 2 taken 1754 times.
✓ Branch 3 taken 146 times.
|
1385508 | } else if (color[1][1] == color[2][2] && color[2][1] != color[1][2]) { |
130 | 1754 | product2b = color[1][1]; | |
131 | 1754 | product1b = product2b; | |
132 |
3/4✓ Branch 0 taken 146 times.
✓ Branch 1 taken 1383608 times.
✓ Branch 2 taken 146 times.
✗ Branch 3 not taken.
|
1383754 | } else if (color[1][1] == color[2][2] && color[2][1] == color[1][2]) { |
133 | 146 | int r = 0; | |
134 | |||
135 |
2/8✗ Branch 0 not taken.
✓ Branch 1 taken 146 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 146 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
146 | r += GET_RESULT(color[1][2], color[1][1], color[1][0], color[3][1]); |
136 |
6/8✓ Branch 0 taken 12 times.
✓ Branch 1 taken 134 times.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
✓ Branch 5 taken 134 times.
✓ Branch 6 taken 12 times.
✗ Branch 7 not taken.
|
146 | r += GET_RESULT(color[1][2], color[1][1], color[2][0], color[0][1]); |
137 |
8/8✓ Branch 0 taken 34 times.
✓ Branch 1 taken 112 times.
✓ Branch 2 taken 20 times.
✓ Branch 3 taken 14 times.
✓ Branch 4 taken 34 times.
✓ Branch 5 taken 112 times.
✓ Branch 6 taken 20 times.
✓ Branch 7 taken 14 times.
|
146 | r += GET_RESULT(color[1][2], color[1][1], color[3][2], color[2][3]); |
138 |
6/8✓ Branch 0 taken 32 times.
✓ Branch 1 taken 114 times.
✓ Branch 2 taken 32 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 28 times.
✓ Branch 5 taken 118 times.
✓ Branch 6 taken 28 times.
✗ Branch 7 not taken.
|
146 | r += GET_RESULT(color[1][2], color[1][1], color[0][2], color[1][3]); |
139 | |||
140 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 146 times.
|
146 | if (r > 0) |
141 | ✗ | product1b = color[1][2]; | |
142 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 146 times.
|
146 | else if (r < 0) |
143 | ✗ | product1b = color[1][1]; | |
144 | else | ||
145 | 146 | product1b = INTERPOLATE(color[1][1], color[1][2]); | |
146 | |||
147 | 146 | product2b = product1b; | |
148 | } else { | ||
149 |
6/8✓ Branch 0 taken 8330 times.
✓ Branch 1 taken 1375278 times.
✓ Branch 2 taken 104 times.
✓ Branch 3 taken 8226 times.
✓ Branch 4 taken 104 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 104 times.
✗ Branch 7 not taken.
|
1383608 | if (color[1][2] == color[2][2] && color[2][2] == color[3][1] && color[2][1] != color[3][2] && color[2][2] != color[3][0]) |
150 | 104 | product2b = Q_INTERPOLATE(color[2][2], color[2][2], color[2][2], color[2][1]); | |
151 |
7/8✓ Branch 0 taken 8652 times.
✓ Branch 1 taken 1374852 times.
✓ Branch 2 taken 28 times.
✓ Branch 3 taken 8624 times.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 24 times.
✓ Branch 7 taken 4 times.
|
1383504 | else if (color[1][1] == color[2][1] && color[2][1] == color[3][2] && color[3][1] != color[2][2] && color[2][1] != color[3][3]) |
152 | 24 | product2b = Q_INTERPOLATE(color[2][1], color[2][1], color[2][1], color[2][2]); | |
153 | else | ||
154 | 1383480 | product2b = INTERPOLATE(color[2][1], color[2][2]); | |
155 | |||
156 |
6/8✓ Branch 0 taken 8330 times.
✓ Branch 1 taken 1375278 times.
✓ Branch 2 taken 28 times.
✓ Branch 3 taken 8302 times.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 28 times.
✗ Branch 7 not taken.
|
1383608 | if (color[1][2] == color[2][2] && color[1][2] == color[0][1] && color[1][1] != color[0][2] && color[1][2] != color[0][0]) |
157 | 28 | product1b = Q_INTERPOLATE(color[1][2], color[1][2], color[1][2], color[1][1]); | |
158 |
7/8✓ Branch 0 taken 8644 times.
✓ Branch 1 taken 1374936 times.
✓ Branch 2 taken 662 times.
✓ Branch 3 taken 7982 times.
✓ Branch 4 taken 662 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 618 times.
✓ Branch 7 taken 44 times.
|
1383580 | else if (color[1][1] == color[2][1] && color[1][1] == color[0][2] && color[0][1] != color[1][2] && color[1][1] != color[0][3]) |
159 | 618 | product1b = Q_INTERPOLATE(color[1][2], color[1][1], color[1][1], color[1][1]); | |
160 | else | ||
161 | 1382962 | product1b = INTERPOLATE(color[1][1], color[1][2]); | |
162 | } | ||
163 | |||
164 |
7/8✓ Branch 0 taken 1900 times.
✓ Branch 1 taken 1417364 times.
✓ Branch 2 taken 1754 times.
✓ Branch 3 taken 146 times.
✓ Branch 4 taken 12 times.
✓ Branch 5 taken 1742 times.
✓ Branch 6 taken 12 times.
✗ Branch 7 not taken.
|
1419264 | if (color[1][1] == color[2][2] && color[2][1] != color[1][2] && color[1][0] == color[1][1] && color[1][1] != color[3][2]) |
165 | 12 | product2a = INTERPOLATE(color[2][1], color[1][1]); | |
166 |
7/8✓ Branch 0 taken 33890 times.
✓ Branch 1 taken 1385362 times.
✓ Branch 2 taken 260 times.
✓ Branch 3 taken 33630 times.
✓ Branch 4 taken 260 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 216 times.
✓ Branch 7 taken 44 times.
|
1419252 | else if (color[1][1] == color[2][0] && color[1][2] == color[1][1] && color[1][0] != color[2][1] && color[1][1] != color[3][0]) |
167 | 216 | product2a = INTERPOLATE(color[2][1], color[1][1]); | |
168 | else | ||
169 | 1419036 | product2a = color[2][1]; | |
170 | |||
171 |
8/8✓ Branch 0 taken 33902 times.
✓ Branch 1 taken 1385362 times.
✓ Branch 2 taken 33756 times.
✓ Branch 3 taken 146 times.
✓ Branch 4 taken 136 times.
✓ Branch 5 taken 33620 times.
✓ Branch 6 taken 128 times.
✓ Branch 7 taken 8 times.
|
1419264 | if (color[2][1] == color[1][2] && color[1][1] != color[2][2] && color[2][0] == color[2][1] && color[2][1] != color[0][2]) |
172 | 128 | product1a = INTERPOLATE(color[2][1], color[1][1]); | |
173 |
7/8✓ Branch 0 taken 1884 times.
✓ Branch 1 taken 1417252 times.
✓ Branch 2 taken 44 times.
✓ Branch 3 taken 1840 times.
✓ Branch 4 taken 44 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 40 times.
✓ Branch 7 taken 4 times.
|
1419136 | else if (color[1][0] == color[2][1] && color[2][2] == color[2][1] && color[2][0] != color[1][1] && color[2][1] != color[0][0]) |
174 | 40 | product1a = INTERPOLATE(color[2][1], color[1][1]); | |
175 | else | ||
176 | 1419096 | product1a = color[1][1]; | |
177 | |||
178 | /* Set the calculated pixels */ | ||
179 |
3/3✓ Branch 0 taken 405504 times.
✓ Branch 1 taken 202752 times.
✓ Branch 2 taken 811008 times.
|
1419264 | switch (bpp) { |
180 | 405504 | case 4: | |
181 | 405504 | AV_WN32A(dst_line[0] + x * 8, product1a); | |
182 | 405504 | AV_WN32A(dst_line[0] + x * 8 + 4, product1b); | |
183 | 405504 | AV_WN32A(dst_line[1] + x * 8, product2a); | |
184 | 405504 | AV_WN32A(dst_line[1] + x * 8 + 4, product2b); | |
185 | 405504 | break; | |
186 | 202752 | case 3: | |
187 | 202752 | AV_WL24(dst_line[0] + x * 6, product1a); | |
188 | 202752 | AV_WL24(dst_line[0] + x * 6 + 3, product1b); | |
189 | 202752 | AV_WL24(dst_line[1] + x * 6, product2a); | |
190 | 202752 | AV_WL24(dst_line[1] + x * 6 + 3, product2b); | |
191 | 202752 | break; | |
192 | 811008 | default: // bpp = 2 | |
193 |
2/2✓ Branch 0 taken 405504 times.
✓ Branch 1 taken 405504 times.
|
811008 | if (s->is_be) { |
194 | 405504 | AV_WB32(dst_line[0] + x * 4, product1a | (product1b << 16)); | |
195 | 405504 | AV_WB32(dst_line[1] + x * 4, product2a | (product2b << 16)); | |
196 | } else { | ||
197 | 405504 | AV_WL32(dst_line[0] + x * 4, product1a | (product1b << 16)); | |
198 | 405504 | AV_WL32(dst_line[1] + x * 4, product2a | (product2b << 16)); | |
199 | } | ||
200 | } | ||
201 | |||
202 | /* Move color matrix forward */ | ||
203 | 1419264 | color[0][0] = color[0][1]; color[0][1] = color[0][2]; color[0][2] = color[0][3]; | |
204 | 1419264 | color[1][0] = color[1][1]; color[1][1] = color[1][2]; color[1][2] = color[1][3]; | |
205 | 1419264 | color[2][0] = color[2][1]; color[2][1] = color[2][2]; color[2][2] = color[2][3]; | |
206 | 1419264 | color[3][0] = color[3][1]; color[3][1] = color[3][2]; color[3][2] = color[3][3]; | |
207 | |||
208 |
2/2✓ Branch 0 taken 1407168 times.
✓ Branch 1 taken 12096 times.
|
1419264 | if (x < width - 3) { |
209 | 1407168 | x += 3; | |
210 |
3/3✓ Branch 0 taken 402048 times.
✓ Branch 1 taken 201024 times.
✓ Branch 2 taken 804096 times.
|
1407168 | switch (bpp) { |
211 | 402048 | case 4: | |
212 | 402048 | READ_COLOR4(color[0][3], src_line[0], x); | |
213 | 402048 | READ_COLOR4(color[1][3], src_line[1], x); | |
214 | 402048 | READ_COLOR4(color[2][3], src_line[2], x); | |
215 | 402048 | READ_COLOR4(color[3][3], src_line[3], x); | |
216 | 402048 | break; | |
217 | 201024 | case 3: | |
218 | 201024 | READ_COLOR3(color[0][3], src_line[0], x); | |
219 | 201024 | READ_COLOR3(color[1][3], src_line[1], x); | |
220 | 201024 | READ_COLOR3(color[2][3], src_line[2], x); | |
221 | 201024 | READ_COLOR3(color[3][3], src_line[3], x); | |
222 | 201024 | break; | |
223 | 804096 | default: /* case 2 */ | |
224 |
2/2✓ Branch 0 taken 402048 times.
✓ Branch 1 taken 402048 times.
|
804096 | READ_COLOR2(color[0][3], src_line[0], x); |
225 |
2/2✓ Branch 0 taken 402048 times.
✓ Branch 1 taken 402048 times.
|
804096 | READ_COLOR2(color[1][3], src_line[1], x); |
226 |
2/2✓ Branch 0 taken 402048 times.
✓ Branch 1 taken 402048 times.
|
804096 | READ_COLOR2(color[2][3], src_line[2], x); |
227 |
2/2✓ Branch 0 taken 402048 times.
✓ Branch 1 taken 402048 times.
|
804096 | READ_COLOR2(color[3][3], src_line[3], x); |
228 | } | ||
229 | 1407168 | x -= 3; | |
230 | } | ||
231 | } | ||
232 | |||
233 | /* We're done with one line, so we shift the source lines up */ | ||
234 | 4032 | src_line[0] = src_line[1]; | |
235 | 4032 | src_line[1] = src_line[2]; | |
236 | 4032 | src_line[2] = src_line[3]; | |
237 | |||
238 | /* Read next line */ | ||
239 | 4032 | src_line[3] = src_line[2]; | |
240 |
2/2✓ Branch 0 taken 3990 times.
✓ Branch 1 taken 42 times.
|
4032 | if (y < height - 3) |
241 | 3990 | src_line[3] += src_linesize; | |
242 | } // y loop | ||
243 | |||
244 | 14 | return 0; | |
245 | } | ||
246 | |||
247 | static const enum AVPixelFormat pix_fmts[] = { | ||
248 | AV_PIX_FMT_RGBA, AV_PIX_FMT_BGRA, AV_PIX_FMT_ARGB, AV_PIX_FMT_ABGR, | ||
249 | AV_PIX_FMT_RGB24, AV_PIX_FMT_BGR24, | ||
250 | AV_PIX_FMT_RGB565BE, AV_PIX_FMT_BGR565BE, AV_PIX_FMT_RGB555BE, AV_PIX_FMT_BGR555BE, | ||
251 | AV_PIX_FMT_RGB565LE, AV_PIX_FMT_BGR565LE, AV_PIX_FMT_RGB555LE, AV_PIX_FMT_BGR555LE, | ||
252 | AV_PIX_FMT_NONE | ||
253 | }; | ||
254 | |||
255 | 14 | static int config_input(AVFilterLink *inlink) | |
256 | { | ||
257 | 14 | Super2xSaIContext *s = inlink->dst->priv; | |
258 | |||
259 | 14 | s->hi_pixel_mask = 0xFEFEFEFE; | |
260 | 14 | s->lo_pixel_mask = 0x01010101; | |
261 | 14 | s->q_hi_pixel_mask = 0xFCFCFCFC; | |
262 | 14 | s->q_lo_pixel_mask = 0x03030303; | |
263 | 14 | s->bpp = 4; | |
264 | |||
265 |
6/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 4 times.
|
14 | switch (inlink->format) { |
266 | 2 | case AV_PIX_FMT_RGB24: | |
267 | case AV_PIX_FMT_BGR24: | ||
268 | 2 | s->bpp = 3; | |
269 | 2 | break; | |
270 | |||
271 | 2 | case AV_PIX_FMT_RGB565BE: | |
272 | case AV_PIX_FMT_BGR565BE: | ||
273 | 2 | s->is_be = 1; | |
274 | 4 | case AV_PIX_FMT_RGB565LE: | |
275 | case AV_PIX_FMT_BGR565LE: | ||
276 | 4 | s->hi_pixel_mask = 0xF7DEF7DE; | |
277 | 4 | s->lo_pixel_mask = 0x08210821; | |
278 | 4 | s->q_hi_pixel_mask = 0xE79CE79C; | |
279 | 4 | s->q_lo_pixel_mask = 0x18631863; | |
280 | 4 | s->bpp = 2; | |
281 | 4 | break; | |
282 | |||
283 | 2 | case AV_PIX_FMT_BGR555BE: | |
284 | case AV_PIX_FMT_RGB555BE: | ||
285 | 2 | s->is_be = 1; | |
286 | 4 | case AV_PIX_FMT_BGR555LE: | |
287 | case AV_PIX_FMT_RGB555LE: | ||
288 | 4 | s->hi_pixel_mask = 0x7BDE7BDE; | |
289 | 4 | s->lo_pixel_mask = 0x04210421; | |
290 | 4 | s->q_hi_pixel_mask = 0x739C739C; | |
291 | 4 | s->q_lo_pixel_mask = 0x0C630C63; | |
292 | 4 | s->bpp = 2; | |
293 | 4 | break; | |
294 | } | ||
295 | |||
296 | 14 | return 0; | |
297 | } | ||
298 | |||
299 | 14 | static int config_output(AVFilterLink *outlink) | |
300 | { | ||
301 | 14 | AVFilterLink *inlink = outlink->src->inputs[0]; | |
302 | |||
303 | 14 | outlink->w = inlink->w*2; | |
304 | 14 | outlink->h = inlink->h*2; | |
305 | |||
306 | 14 | av_log(inlink->dst, AV_LOG_VERBOSE, "fmt:%s size:%dx%d -> size:%dx%d\n", | |
307 | 14 | av_get_pix_fmt_name(inlink->format), | |
308 | inlink->w, inlink->h, outlink->w, outlink->h); | ||
309 | |||
310 | 14 | return 0; | |
311 | } | ||
312 | |||
313 | 14 | static int filter_frame(AVFilterLink *inlink, AVFrame *in) | |
314 | { | ||
315 | 14 | AVFilterContext *ctx = inlink->dst; | |
316 | 14 | AVFilterLink *outlink = ctx->outputs[0]; | |
317 | ThreadData td; | ||
318 | 14 | AVFrame *out = ff_get_video_buffer(outlink, outlink->w, outlink->h); | |
319 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
|
14 | if (!out) { |
320 | ✗ | av_frame_free(&in); | |
321 | ✗ | return AVERROR(ENOMEM); | |
322 | } | ||
323 | 14 | av_frame_copy_props(out, in); | |
324 | 14 | out->width = outlink->w; | |
325 | 14 | out->height = outlink->h; | |
326 | |||
327 | 14 | td.in = in, td.out = out; | |
328 | 14 | ff_filter_execute(ctx, super2xsai, &td, NULL, | |
329 |
1/2✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
|
14 | FFMIN(in->height, ff_filter_get_nb_threads(ctx))); |
330 | |||
331 | 14 | av_frame_free(&in); | |
332 | 14 | return ff_filter_frame(outlink, out); | |
333 | } | ||
334 | |||
335 | static const AVFilterPad super2xsai_inputs[] = { | ||
336 | { | ||
337 | .name = "default", | ||
338 | .type = AVMEDIA_TYPE_VIDEO, | ||
339 | .config_props = config_input, | ||
340 | .filter_frame = filter_frame, | ||
341 | }, | ||
342 | }; | ||
343 | |||
344 | static const AVFilterPad super2xsai_outputs[] = { | ||
345 | { | ||
346 | .name = "default", | ||
347 | .type = AVMEDIA_TYPE_VIDEO, | ||
348 | .config_props = config_output, | ||
349 | }, | ||
350 | }; | ||
351 | |||
352 | const AVFilter ff_vf_super2xsai = { | ||
353 | .name = "super2xsai", | ||
354 | .description = NULL_IF_CONFIG_SMALL("Scale the input by 2x using the Super2xSaI pixel art algorithm."), | ||
355 | .priv_size = sizeof(Super2xSaIContext), | ||
356 | FILTER_INPUTS(super2xsai_inputs), | ||
357 | FILTER_OUTPUTS(super2xsai_outputs), | ||
358 | FILTER_PIXFMTS_ARRAY(pix_fmts), | ||
359 | .flags = AVFILTER_FLAG_SLICE_THREADS, | ||
360 | }; | ||
361 |