Line | Branch | Exec | Source |
---|---|---|---|
1 | /* | ||
2 | * Copyright 2011 Stefano Sabatini <stefano.sabatini-lala poste it> | ||
3 | * Copyright 2012 Nicolas George <nicolas.george normalesup org> | ||
4 | * | ||
5 | * This file is part of FFmpeg. | ||
6 | * | ||
7 | * FFmpeg is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU Lesser General Public | ||
9 | * License as published by the Free Software Foundation; either | ||
10 | * version 2.1 of the License, or (at your option) any later version. | ||
11 | * | ||
12 | * FFmpeg is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * Lesser General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU Lesser General Public | ||
18 | * License along with FFmpeg; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
20 | */ | ||
21 | |||
22 | #include <string.h> | ||
23 | |||
24 | #include "libavutil/avassert.h" | ||
25 | #include "libavutil/avutil.h" | ||
26 | #include "libavutil/csp.h" | ||
27 | #include "libavutil/intreadwrite.h" | ||
28 | #include "libavutil/pixdesc.h" | ||
29 | #include "colorspace.h" | ||
30 | #include "drawutils.h" | ||
31 | #include "formats.h" | ||
32 | |||
33 | enum { RED = 0, GREEN, BLUE, ALPHA }; | ||
34 | |||
35 | 845 | static int fill_map(const AVPixFmtDescriptor *desc, uint8_t *map) | |
36 | { | ||
37 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 845 times.
|
845 | if (desc->flags & (AV_PIX_FMT_FLAG_BITSTREAM | AV_PIX_FMT_FLAG_HWACCEL | |
38 | AV_PIX_FMT_FLAG_BAYER | AV_PIX_FMT_FLAG_XYZ | AV_PIX_FMT_FLAG_PAL)) | ||
39 | ✗ | return AVERROR(EINVAL); | |
40 |
3/4✓ Branch 0 taken 30 times.
✓ Branch 1 taken 815 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 845 times.
|
845 | av_assert0(desc->nb_components == 3 + !!(desc->flags & AV_PIX_FMT_FLAG_ALPHA)); |
41 |
2/2✓ Branch 0 taken 614 times.
✓ Branch 1 taken 231 times.
|
845 | if (desc->flags & AV_PIX_FMT_FLAG_PLANAR) { |
42 | 614 | map[RED] = desc->comp[0].plane; | |
43 | 614 | map[GREEN] = desc->comp[1].plane; | |
44 | 614 | map[BLUE] = desc->comp[2].plane; | |
45 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 602 times.
|
614 | map[ALPHA] = (desc->flags & AV_PIX_FMT_FLAG_ALPHA) ? desc->comp[3].plane : 3; |
46 | } else { | ||
47 | 231 | int had0 = 0; | |
48 | 231 | unsigned depthb = 0; | |
49 | unsigned i; | ||
50 |
2/2✓ Branch 0 taken 706 times.
✓ Branch 1 taken 228 times.
|
934 | for (i = 0; i < desc->nb_components; i++) { |
51 | /* all components must have same depth in bytes */ | ||
52 | 706 | unsigned db = (desc->comp[i].depth + 7) / 8; | |
53 | 706 | unsigned pos = desc->comp[i].offset / db; | |
54 |
3/4✓ Branch 0 taken 475 times.
✓ Branch 1 taken 231 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 475 times.
|
706 | if (depthb && (depthb != db)) |
55 | ✗ | return AVERROR(ENOSYS); | |
56 | |||
57 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 703 times.
|
706 | if (desc->comp[i].offset % db) |
58 | 3 | return AVERROR(ENOSYS); | |
59 | |||
60 | 703 | had0 |= pos == 0; | |
61 | 703 | map[i] = pos; | |
62 | 703 | depthb = db; | |
63 | } | ||
64 | |||
65 |
2/2✓ Branch 0 taken 210 times.
✓ Branch 1 taken 18 times.
|
228 | if (desc->nb_components == 3) |
66 |
1/2✓ Branch 0 taken 210 times.
✗ Branch 1 not taken.
|
210 | map[ALPHA] = had0 ? 3 : 0; |
67 | } | ||
68 | |||
69 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 842 times.
|
842 | av_assert0(map[RED] != map[GREEN]); |
70 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 842 times.
|
842 | av_assert0(map[GREEN] != map[BLUE]); |
71 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 842 times.
|
842 | av_assert0(map[BLUE] != map[RED]); |
72 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 842 times.
|
842 | av_assert0(map[RED] != map[ALPHA]); |
73 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 842 times.
|
842 | av_assert0(map[GREEN] != map[ALPHA]); |
74 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 842 times.
|
842 | av_assert0(map[BLUE] != map[ALPHA]); |
75 | |||
76 | 842 | return 0; | |
77 | } | ||
78 | |||
79 | 589 | int ff_fill_rgba_map(uint8_t *rgba_map, enum AVPixelFormat pix_fmt) | |
80 | { | ||
81 | 589 | const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); | |
82 |
2/2✓ Branch 0 taken 47 times.
✓ Branch 1 taken 542 times.
|
589 | if (!(desc->flags & AV_PIX_FMT_FLAG_RGB)) |
83 | 47 | return AVERROR(EINVAL); | |
84 | 542 | return fill_map(desc, rgba_map); | |
85 | } | ||
86 | |||
87 | 303 | int ff_fill_ayuv_map(uint8_t *ayuv_map, enum AVPixelFormat pix_fmt) | |
88 | { | ||
89 | 303 | const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); | |
90 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 303 times.
|
303 | if (desc->flags & AV_PIX_FMT_FLAG_RGB) |
91 | ✗ | return AVERROR(EINVAL); | |
92 | 303 | return fill_map(desc, ayuv_map); | |
93 | } | ||
94 | |||
95 | 40318 | int ff_draw_init2(FFDrawContext *draw, enum AVPixelFormat format, enum AVColorSpace csp, | |
96 | enum AVColorRange range, unsigned flags) | ||
97 | { | ||
98 | 40318 | const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(format); | |
99 | 40318 | const AVLumaCoefficients *luma = NULL; | |
100 | const AVComponentDescriptor *c; | ||
101 | 40318 | unsigned i, nb_planes = 0; | |
102 | 40318 | int pixelstep[MAX_PLANES] = { 0 }; | |
103 | 40318 | int depthb = 0; | |
104 | |||
105 |
2/4✓ Branch 0 taken 40318 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 40318 times.
|
40318 | if (!desc || !desc->name) |
106 | ✗ | return AVERROR(EINVAL); | |
107 |
2/2✓ Branch 0 taken 14355 times.
✓ Branch 1 taken 25963 times.
|
40318 | if (desc->flags & AV_PIX_FMT_FLAG_BE) |
108 | 14355 | return AVERROR(ENOSYS); | |
109 |
2/2✓ Branch 0 taken 5775 times.
✓ Branch 1 taken 20188 times.
|
25963 | if (desc->flags & ~(AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_ALPHA)) |
110 | 5775 | return AVERROR(ENOSYS); | |
111 |
2/2✓ Branch 0 taken 20141 times.
✓ Branch 1 taken 47 times.
|
20188 | if (csp == AVCOL_SPC_UNSPECIFIED) |
112 |
2/2✓ Branch 0 taken 6435 times.
✓ Branch 1 taken 13706 times.
|
20141 | csp = (desc->flags & AV_PIX_FMT_FLAG_RGB) ? AVCOL_SPC_RGB : AVCOL_SPC_SMPTE170M; |
113 |
3/4✓ Branch 0 taken 13706 times.
✓ Branch 1 taken 6482 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 13706 times.
|
20188 | if (!(desc->flags & AV_PIX_FMT_FLAG_RGB) && !(luma = av_csp_luma_coeffs_from_avcsp(csp))) |
114 | ✗ | return AVERROR(EINVAL); | |
115 |
2/2✓ Branch 0 taken 20013 times.
✓ Branch 1 taken 175 times.
|
20188 | if (range == AVCOL_RANGE_UNSPECIFIED) |
116 |
4/4✓ Branch 0 taken 19683 times.
✓ Branch 1 taken 165 times.
✓ Branch 2 taken 19518 times.
✓ Branch 3 taken 165 times.
|
39861 | range = (format == AV_PIX_FMT_YUVJ420P || format == AV_PIX_FMT_YUVJ422P || |
117 |
4/4✓ Branch 0 taken 19353 times.
✓ Branch 1 taken 165 times.
✓ Branch 2 taken 19188 times.
✓ Branch 3 taken 165 times.
|
19518 | format == AV_PIX_FMT_YUVJ444P || format == AV_PIX_FMT_YUVJ411P || |
118 |
2/2✓ Branch 0 taken 6435 times.
✓ Branch 1 taken 12753 times.
|
19188 | format == AV_PIX_FMT_YUVJ440P || csp == AVCOL_SPC_RGB) |
119 |
2/2✓ Branch 0 taken 19848 times.
✓ Branch 1 taken 165 times.
|
39861 | ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG; |
120 |
3/4✓ Branch 0 taken 12860 times.
✓ Branch 1 taken 7328 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12860 times.
|
20188 | if (range != AVCOL_RANGE_JPEG && range != AVCOL_RANGE_MPEG) |
121 | ✗ | return AVERROR(EINVAL); | |
122 |
2/2✓ Branch 0 taken 54664 times.
✓ Branch 1 taken 15568 times.
|
70232 | for (i = 0; i < desc->nb_components; i++) { |
123 | int db; | ||
124 | 54664 | c = &desc->comp[i]; | |
125 | /* for now, only 8-16 bits formats */ | ||
126 |
4/4✓ Branch 0 taken 53014 times.
✓ Branch 1 taken 1650 times.
✓ Branch 2 taken 330 times.
✓ Branch 3 taken 52684 times.
|
54664 | if (c->depth < 8 || c->depth > 16) |
127 | 1980 | return AVERROR(ENOSYS); | |
128 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 52684 times.
|
52684 | if (c->plane >= MAX_PLANES) |
129 | ✗ | return AVERROR(ENOSYS); | |
130 | /* data must either be in the high or low bits, never middle */ | ||
131 |
4/4✓ Branch 0 taken 4473 times.
✓ Branch 1 taken 48211 times.
✓ Branch 2 taken 660 times.
✓ Branch 3 taken 3813 times.
|
52684 | if (c->shift && ((c->shift + c->depth) & 0x7)) |
132 | 660 | return AVERROR(ENOSYS); | |
133 | /* mixed >8 and <=8 depth */ | ||
134 | 52024 | db = (c->depth + 7) / 8; | |
135 |
3/4✓ Branch 0 taken 34311 times.
✓ Branch 1 taken 17713 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 34311 times.
|
52024 | if (depthb && (depthb != db)) |
136 | ✗ | return AVERROR(ENOSYS); | |
137 | 52024 | depthb = db; | |
138 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 52024 times.
|
52024 | if (db * (c->offset + 1) > 16) |
139 | ✗ | return AVERROR(ENOSYS); | |
140 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 52024 times.
|
52024 | if (c->offset % db) |
141 | ✗ | return AVERROR(ENOSYS); | |
142 | /* strange interleaving */ | ||
143 |
2/2✓ Branch 0 taken 10830 times.
✓ Branch 1 taken 41194 times.
|
52024 | if (pixelstep[c->plane] != 0 && |
144 |
2/2✓ Branch 0 taken 1155 times.
✓ Branch 1 taken 9675 times.
|
10830 | pixelstep[c->plane] != c->step) |
145 | 1155 | return AVERROR(ENOSYS); | |
146 | 50869 | pixelstep[c->plane] = c->step; | |
147 |
2/2✓ Branch 0 taken 825 times.
✓ Branch 1 taken 50044 times.
|
50869 | if (pixelstep[c->plane] >= 8) |
148 | 825 | return AVERROR(ENOSYS); | |
149 | 50044 | nb_planes = FFMAX(nb_planes, c->plane + 1); | |
150 | } | ||
151 | 15568 | memset(draw, 0, sizeof(*draw)); | |
152 | 15568 | draw->desc = desc; | |
153 | 15568 | draw->format = format; | |
154 | 15568 | draw->nb_planes = nb_planes; | |
155 | 15568 | draw->range = range; | |
156 | 15568 | draw->csp = csp; | |
157 | 15568 | draw->flags = flags; | |
158 |
2/2✓ Branch 0 taken 11726 times.
✓ Branch 1 taken 3842 times.
|
15568 | if (luma) |
159 | 11726 | ff_fill_rgb2yuv_table(luma, draw->rgb2yuv); | |
160 | 15568 | memcpy(draw->pixelstep, pixelstep, sizeof(draw->pixelstep)); | |
161 | 15568 | draw->hsub[1] = draw->hsub[2] = draw->hsub_max = desc->log2_chroma_w; | |
162 | 15568 | draw->vsub[1] = draw->vsub[2] = draw->vsub_max = desc->log2_chroma_h; | |
163 | 15568 | return 0; | |
164 | } | ||
165 | |||
166 | 40095 | int ff_draw_init(FFDrawContext *draw, enum AVPixelFormat format, unsigned flags) | |
167 | { | ||
168 | 40095 | return ff_draw_init2(draw, format, AVCOL_SPC_UNSPECIFIED, AVCOL_RANGE_UNSPECIFIED, flags); | |
169 | } | ||
170 | |||
171 | 209610 | void ff_draw_color(FFDrawContext *draw, FFDrawColor *color, const uint8_t rgba[4]) | |
172 | { | ||
173 | unsigned i; | ||
174 | double yuvad[4]; | ||
175 | double rgbad[4]; | ||
176 | 209610 | const AVPixFmtDescriptor *desc = draw->desc; | |
177 | |||
178 |
1/2✓ Branch 0 taken 209610 times.
✗ Branch 1 not taken.
|
209610 | if (rgba != color->rgba) |
179 | 209610 | memcpy(color->rgba, rgba, sizeof(color->rgba)); | |
180 | |||
181 | 209610 | memset(color->comp, 0, sizeof(color->comp)); | |
182 | |||
183 |
2/2✓ Branch 0 taken 838440 times.
✓ Branch 1 taken 209610 times.
|
1048050 | for (int i = 0; i < 4; i++) |
184 | 838440 | rgbad[i] = color->rgba[i] / 255.; | |
185 | |||
186 |
2/2✓ Branch 0 taken 54599 times.
✓ Branch 1 taken 155011 times.
|
209610 | if (draw->desc->flags & AV_PIX_FMT_FLAG_RGB) |
187 | 54599 | memcpy(yuvad, rgbad, sizeof(double) * 3); | |
188 | else | ||
189 | 155011 | ff_matrix_mul_3x3_vec(yuvad, rgbad, draw->rgb2yuv); | |
190 | |||
191 | 209610 | yuvad[3] = rgbad[3]; | |
192 | |||
193 |
2/2✓ Branch 0 taken 628830 times.
✓ Branch 1 taken 209610 times.
|
838440 | for (int i = 0; i < 3; i++) { |
194 |
4/4✓ Branch 0 taken 465033 times.
✓ Branch 1 taken 163797 times.
✓ Branch 2 taken 310022 times.
✓ Branch 3 taken 155011 times.
|
628830 | int chroma = (!(draw->desc->flags & AV_PIX_FMT_FLAG_RGB) && i > 0); |
195 |
2/2✓ Branch 0 taken 464970 times.
✓ Branch 1 taken 163860 times.
|
628830 | if (draw->range == AVCOL_RANGE_MPEG) { |
196 |
2/2✓ Branch 0 taken 309980 times.
✓ Branch 1 taken 154990 times.
|
464970 | yuvad[i] *= (chroma ? 224. : 219.) / 255.; |
197 |
2/2✓ Branch 0 taken 309980 times.
✓ Branch 1 taken 154990 times.
|
464970 | yuvad[i] += (chroma ? 128. : 16.) / 255.; |
198 |
2/2✓ Branch 0 taken 42 times.
✓ Branch 1 taken 163818 times.
|
163860 | } else if (chroma) { |
199 | 42 | yuvad[i] += 0.5; | |
200 | } | ||
201 | } | ||
202 | |||
203 | // Ensure we place the alpha appropriately for gray formats | ||
204 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 209600 times.
|
209610 | if (desc->nb_components <= 2) |
205 | 10 | yuvad[1] = yuvad[3]; | |
206 | |||
207 |
2/2✓ Branch 0 taken 654841 times.
✓ Branch 1 taken 209610 times.
|
864451 | for (i = 0; i < desc->nb_components; i++) { |
208 | 654841 | unsigned val = yuvad[i] * ((1 << (draw->desc->comp[i].depth + draw->desc->comp[i].shift)) - 1) + 0.5; | |
209 |
2/2✓ Branch 0 taken 59662 times.
✓ Branch 1 taken 595179 times.
|
654841 | if (desc->comp[i].depth > 8) |
210 | 59662 | color->comp[desc->comp[i].plane].u16[desc->comp[i].offset / 2] = val; | |
211 | else | ||
212 | 595179 | color->comp[desc->comp[i].plane].u8[desc->comp[i].offset] = val; | |
213 | } | ||
214 | 209610 | } | |
215 | |||
216 | 607542 | static uint8_t *pointer_at(FFDrawContext *draw, uint8_t *data[], int linesize[], | |
217 | int plane, int x, int y) | ||
218 | { | ||
219 | 607542 | return data[plane] + | |
220 | 1215084 | (y >> draw->vsub[plane]) * linesize[plane] + | |
221 | 607542 | (x >> draw->hsub[plane]) * draw->pixelstep[plane]; | |
222 | } | ||
223 | |||
224 | 37 | void ff_copy_rectangle2(FFDrawContext *draw, | |
225 | uint8_t *dst[], int dst_linesize[], | ||
226 | uint8_t *src[], int src_linesize[], | ||
227 | int dst_x, int dst_y, int src_x, int src_y, | ||
228 | int w, int h) | ||
229 | { | ||
230 | int plane, y, wp, hp; | ||
231 | uint8_t *p, *q; | ||
232 | |||
233 |
2/2✓ Branch 0 taken 111 times.
✓ Branch 1 taken 37 times.
|
148 | for (plane = 0; plane < draw->nb_planes; plane++) { |
234 | 111 | p = pointer_at(draw, src, src_linesize, plane, src_x, src_y); | |
235 | 111 | q = pointer_at(draw, dst, dst_linesize, plane, dst_x, dst_y); | |
236 | 111 | wp = AV_CEIL_RSHIFT(w, draw->hsub[plane]) * draw->pixelstep[plane]; | |
237 | 111 | hp = AV_CEIL_RSHIFT(h, draw->vsub[plane]); | |
238 |
2/2✓ Branch 0 taken 21312 times.
✓ Branch 1 taken 111 times.
|
21423 | for (y = 0; y < hp; y++) { |
239 | 21312 | memcpy(q, p, wp); | |
240 | 21312 | p += src_linesize[plane]; | |
241 | 21312 | q += dst_linesize[plane]; | |
242 | } | ||
243 | } | ||
244 | 37 | } | |
245 | |||
246 | 211267 | void ff_fill_rectangle(FFDrawContext *draw, FFDrawColor *color, | |
247 | uint8_t *dst[], int dst_linesize[], | ||
248 | int dst_x, int dst_y, int w, int h) | ||
249 | { | ||
250 | int plane, x, y, wp, hp; | ||
251 | uint8_t *p0, *p; | ||
252 | 211267 | FFDrawColor color_tmp = *color; | |
253 | |||
254 |
2/2✓ Branch 0 taken 525400 times.
✓ Branch 1 taken 211267 times.
|
736667 | for (plane = 0; plane < draw->nb_planes; plane++) { |
255 | 525400 | p0 = pointer_at(draw, dst, dst_linesize, plane, dst_x, dst_y); | |
256 | 525400 | wp = AV_CEIL_RSHIFT(w, draw->hsub[plane]); | |
257 | 525400 | hp = AV_CEIL_RSHIFT(h, draw->vsub[plane]); | |
258 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 525400 times.
|
525400 | if (!hp) |
259 | ✗ | return; | |
260 | 525400 | p = p0; | |
261 | |||
262 | if (HAVE_BIGENDIAN && draw->desc->comp[0].depth > 8) { | ||
263 | for (x = 0; 2*x < draw->pixelstep[plane]; x++) | ||
264 | color_tmp.comp[plane].u16[x] = av_bswap16(color_tmp.comp[plane].u16[x]); | ||
265 | } | ||
266 | |||
267 | /* copy first line from color */ | ||
268 |
2/2✓ Branch 0 taken 2013673 times.
✓ Branch 1 taken 525400 times.
|
2539073 | for (x = 0; x < wp; x++) { |
269 | 2013673 | memcpy(p, color_tmp.comp[plane].u8, draw->pixelstep[plane]); | |
270 | 2013673 | p += draw->pixelstep[plane]; | |
271 | } | ||
272 | 525400 | wp *= draw->pixelstep[plane]; | |
273 | /* copy next lines from first line */ | ||
274 | 525400 | p = p0 + dst_linesize[plane]; | |
275 |
2/2✓ Branch 0 taken 9008101 times.
✓ Branch 1 taken 525400 times.
|
9533501 | for (y = 1; y < hp; y++) { |
276 | 9008101 | memcpy(p, p0, wp); | |
277 | 9008101 | p += dst_linesize[plane]; | |
278 | } | ||
279 | } | ||
280 | } | ||
281 | |||
282 | /** | ||
283 | * Clip interval [x; x+w[ within [0; wmax[. | ||
284 | * The resulting w may be negative if the final interval is empty. | ||
285 | * dx, if not null, return the difference between in and out value of x. | ||
286 | */ | ||
287 | 61560 | static void clip_interval(int wmax, int *x, int *w, int *dx) | |
288 | { | ||
289 |
2/2✓ Branch 0 taken 59648 times.
✓ Branch 1 taken 1912 times.
|
61560 | if (dx) |
290 | 59648 | *dx = 0; | |
291 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 61560 times.
|
61560 | if (*x < 0) { |
292 | ✗ | if (dx) | |
293 | ✗ | *dx = -*x; | |
294 | ✗ | *w += *x; | |
295 | ✗ | *x = 0; | |
296 | } | ||
297 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 61560 times.
|
61560 | if (*x + *w > wmax) |
298 | ✗ | *w = wmax - *x; | |
299 | 61560 | } | |
300 | |||
301 | /** | ||
302 | * Decompose w pixels starting at x | ||
303 | * into start + (w starting at x) + end | ||
304 | * with x and w aligned on multiples of 1<<sub. | ||
305 | */ | ||
306 | 163840 | static void subsampling_bounds(int sub, int *x, int *w, int *start, int *end) | |
307 | { | ||
308 | 163840 | int mask = (1 << sub) - 1; | |
309 | |||
310 | 163840 | *start = (-*x) & mask; | |
311 | 163840 | *x += *start; | |
312 | 163840 | *start = FFMIN(*start, *w); | |
313 | 163840 | *w -= *start; | |
314 | 163840 | *end = *w & mask; | |
315 | 163840 | *w >>= sub; | |
316 | 163840 | } | |
317 | |||
318 | /* If alpha is in the [ 0 ; 0x1010101 ] range, | ||
319 | then alpha * value is in the [ 0 ; 0xFFFFFFFF ] range, | ||
320 | and >> 24 gives a correct rounding. */ | ||
321 | 69660 | static void blend_line(uint8_t *dst, unsigned src, unsigned alpha, | |
322 | int dx, int w, unsigned hsub, int left, int right) | ||
323 | { | ||
324 | 69660 | unsigned asrc = alpha * src; | |
325 | 69660 | unsigned tau = 0x1010101 - alpha; | |
326 | int x; | ||
327 | |||
328 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 69660 times.
|
69660 | if (left) { |
329 | ✗ | unsigned suba = (left * alpha) >> hsub; | |
330 | ✗ | *dst = (*dst * (0x1010101 - suba) + src * suba) >> 24; | |
331 | ✗ | dst += dx; | |
332 | } | ||
333 |
2/2✓ Branch 0 taken 5819400 times.
✓ Branch 1 taken 69660 times.
|
5889060 | for (x = 0; x < w; x++) { |
334 | 5819400 | *dst = (*dst * tau + asrc) >> 24; | |
335 | 5819400 | dst += dx; | |
336 | } | ||
337 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 69660 times.
|
69660 | if (right) { |
338 | ✗ | unsigned suba = (right * alpha) >> hsub; | |
339 | ✗ | *dst = (*dst * (0x1010101 - suba) + src * suba) >> 24; | |
340 | } | ||
341 | 69660 | } | |
342 | |||
343 | 11880 | static void blend_line16(uint8_t *dst, unsigned src, unsigned alpha, | |
344 | int dx, int w, unsigned hsub, int left, int right) | ||
345 | { | ||
346 | 11880 | unsigned asrc = alpha * src; | |
347 | 11880 | unsigned tau = 0x10001 - alpha; | |
348 | int x; | ||
349 | |||
350 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11880 times.
|
11880 | if (left) { |
351 | ✗ | unsigned suba = (left * alpha) >> hsub; | |
352 | ✗ | uint16_t value = AV_RL16(dst); | |
353 | ✗ | AV_WL16(dst, (value * (0x10001 - suba) + src * suba) >> 16); | |
354 | ✗ | dst += dx; | |
355 | } | ||
356 |
2/2✓ Branch 0 taken 792000 times.
✓ Branch 1 taken 11880 times.
|
803880 | for (x = 0; x < w; x++) { |
357 | 792000 | uint16_t value = AV_RL16(dst); | |
358 | 792000 | AV_WL16(dst, (value * tau + asrc) >> 16); | |
359 | 792000 | dst += dx; | |
360 | } | ||
361 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11880 times.
|
11880 | if (right) { |
362 | ✗ | unsigned suba = (right * alpha) >> hsub; | |
363 | ✗ | uint16_t value = AV_RL16(dst); | |
364 | ✗ | AV_WL16(dst, (value * (0x10001 - suba) + src * suba) >> 16); | |
365 | } | ||
366 | 11880 | } | |
367 | |||
368 | 956 | void ff_blend_rectangle(FFDrawContext *draw, FFDrawColor *color, | |
369 | uint8_t *dst[], int dst_linesize[], | ||
370 | int dst_w, int dst_h, | ||
371 | int x0, int y0, int w, int h) | ||
372 | { | ||
373 | unsigned alpha, nb_planes, nb_comp, plane, comp; | ||
374 | int w_sub, h_sub, x_sub, y_sub, left, right, top, bottom, y; | ||
375 | uint8_t *p0, *p; | ||
376 | |||
377 | 1912 | nb_comp = draw->desc->nb_components - | |
378 |
3/4✓ Branch 0 taken 71 times.
✓ Branch 1 taken 885 times.
✓ Branch 2 taken 71 times.
✗ Branch 3 not taken.
|
956 | !!(draw->desc->flags & AV_PIX_FMT_FLAG_ALPHA && !(draw->flags & FF_DRAW_PROCESS_ALPHA)); |
379 | |||
380 | /* TODO optimize if alpha = 0xFF */ | ||
381 | 956 | clip_interval(dst_w, &x0, &w, NULL); | |
382 | 956 | clip_interval(dst_h, &y0, &h, NULL); | |
383 |
3/6✓ Branch 0 taken 956 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 956 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 956 times.
|
956 | if (w <= 0 || h <= 0 || !color->rgba[3]) |
384 | ✗ | return; | |
385 |
2/2✓ Branch 0 taken 846 times.
✓ Branch 1 taken 110 times.
|
956 | if (draw->desc->comp[0].depth <= 8) { |
386 | /* 0x10203 * alpha + 2 is in the [ 2 ; 0x1010101 - 2 ] range */ | ||
387 | 846 | alpha = 0x10203 * color->rgba[3] + 0x2; | |
388 | } else { | ||
389 | /* 0x101 * alpha is in the [ 2 ; 0x1001] range */ | ||
390 | 110 | alpha = 0x101 * color->rgba[3] + 0x2; | |
391 | } | ||
392 |
3/4✓ Branch 0 taken 71 times.
✓ Branch 1 taken 885 times.
✓ Branch 2 taken 71 times.
✗ Branch 3 not taken.
|
956 | nb_planes = draw->nb_planes - !!(draw->desc->flags & AV_PIX_FMT_FLAG_ALPHA && !(draw->flags & FF_DRAW_PROCESS_ALPHA)); |
393 | 956 | nb_planes += !nb_planes; | |
394 |
2/2✓ Branch 0 taken 2556 times.
✓ Branch 1 taken 956 times.
|
3512 | for (plane = 0; plane < nb_planes; plane++) { |
395 | 2556 | p0 = pointer_at(draw, dst, dst_linesize, plane, x0, y0); | |
396 | 2556 | w_sub = w; | |
397 | 2556 | h_sub = h; | |
398 | 2556 | x_sub = x0; | |
399 | 2556 | y_sub = y0; | |
400 | 2556 | subsampling_bounds(draw->hsub[plane], &x_sub, &w_sub, &left, &right); | |
401 | 2556 | subsampling_bounds(draw->vsub[plane], &y_sub, &h_sub, &top, &bottom); | |
402 |
2/2✓ Branch 0 taken 7668 times.
✓ Branch 1 taken 2556 times.
|
10224 | for (comp = 0; comp < nb_comp; comp++) { |
403 | 7668 | const int depth = draw->desc->comp[comp].depth; | |
404 | 7668 | const int offset = draw->desc->comp[comp].offset; | |
405 | 7668 | const int index = offset / ((depth + 7) / 8); | |
406 | |||
407 |
2/2✓ Branch 0 taken 4800 times.
✓ Branch 1 taken 2868 times.
|
7668 | if (draw->desc->comp[comp].plane != plane) |
408 | 4800 | continue; | |
409 | 2868 | p = p0 + offset; | |
410 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2868 times.
|
2868 | if (top) { |
411 | ✗ | if (depth <= 8) { | |
412 | ✗ | blend_line(p, color->comp[plane].u8[index], alpha >> 1, | |
413 | draw->pixelstep[plane], w_sub, | ||
414 | ✗ | draw->hsub[plane], left, right); | |
415 | } else { | ||
416 | ✗ | blend_line16(p, color->comp[plane].u16[index], alpha >> 1, | |
417 | draw->pixelstep[plane], w_sub, | ||
418 | ✗ | draw->hsub[plane], left, right); | |
419 | } | ||
420 | ✗ | p += dst_linesize[plane]; | |
421 | } | ||
422 |
2/2✓ Branch 0 taken 2538 times.
✓ Branch 1 taken 330 times.
|
2868 | if (depth <= 8) { |
423 |
2/2✓ Branch 0 taken 69660 times.
✓ Branch 1 taken 2538 times.
|
72198 | for (y = 0; y < h_sub; y++) { |
424 | 69660 | blend_line(p, color->comp[plane].u8[index], alpha, | |
425 | draw->pixelstep[plane], w_sub, | ||
426 | 69660 | draw->hsub[plane], left, right); | |
427 | 69660 | p += dst_linesize[plane]; | |
428 | } | ||
429 | } else { | ||
430 |
2/2✓ Branch 0 taken 11880 times.
✓ Branch 1 taken 330 times.
|
12210 | for (y = 0; y < h_sub; y++) { |
431 | 11880 | blend_line16(p, color->comp[plane].u16[index], alpha, | |
432 | draw->pixelstep[plane], w_sub, | ||
433 | 11880 | draw->hsub[plane], left, right); | |
434 | 11880 | p += dst_linesize[plane]; | |
435 | } | ||
436 | } | ||
437 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2868 times.
|
2868 | if (bottom) { |
438 | ✗ | if (depth <= 8) { | |
439 | ✗ | blend_line(p, color->comp[plane].u8[index], alpha >> 1, | |
440 | draw->pixelstep[plane], w_sub, | ||
441 | ✗ | draw->hsub[plane], left, right); | |
442 | } else { | ||
443 | ✗ | blend_line16(p, color->comp[plane].u16[index], alpha >> 1, | |
444 | draw->pixelstep[plane], w_sub, | ||
445 | ✗ | draw->hsub[plane], left, right); | |
446 | } | ||
447 | } | ||
448 | } | ||
449 | } | ||
450 | } | ||
451 | |||
452 | 1070080 | static void blend_pixel16(uint8_t *dst, unsigned src, unsigned alpha, | |
453 | const uint8_t *mask, int mask_linesize, int l2depth, | ||
454 | unsigned w, unsigned h, unsigned shift, unsigned xm0) | ||
455 | { | ||
456 | 1070080 | unsigned xm, x, y, t = 0; | |
457 | 1070080 | unsigned xmshf = 3 - l2depth; | |
458 | 1070080 | unsigned xmmod = 7 >> l2depth; | |
459 | 1070080 | unsigned mbits = (1 << (1 << l2depth)) - 1; | |
460 | 1070080 | unsigned mmult = 255 / mbits; | |
461 | 1070080 | uint16_t value = AV_RL16(dst); | |
462 | |||
463 |
2/2✓ Branch 0 taken 1070080 times.
✓ Branch 1 taken 1070080 times.
|
2140160 | for (y = 0; y < h; y++) { |
464 | 1070080 | xm = xm0; | |
465 |
2/2✓ Branch 0 taken 1605120 times.
✓ Branch 1 taken 1070080 times.
|
2675200 | for (x = 0; x < w; x++) { |
466 | 1605120 | t += ((mask[xm >> xmshf] >> ((~xm & xmmod) << l2depth)) & mbits) | |
467 | 1605120 | * mmult; | |
468 | 1605120 | xm++; | |
469 | } | ||
470 | 1070080 | mask += mask_linesize; | |
471 | } | ||
472 | 1070080 | alpha = (t >> shift) * alpha; | |
473 | 1070080 | AV_WL16(dst, ((0x10001 - alpha) * value + alpha * src) >> 16); | |
474 | 1070080 | } | |
475 | |||
476 | 8018080 | static void blend_pixel(uint8_t *dst, unsigned src, unsigned alpha, | |
477 | const uint8_t *mask, int mask_linesize, int l2depth, | ||
478 | unsigned w, unsigned h, unsigned shift, unsigned xm0) | ||
479 | { | ||
480 | 8018080 | unsigned xm, x, y, t = 0; | |
481 | 8018080 | unsigned xmshf = 3 - l2depth; | |
482 | 8018080 | unsigned xmmod = 7 >> l2depth; | |
483 | 8018080 | unsigned mbits = (1 << (1 << l2depth)) - 1; | |
484 | 8018080 | unsigned mmult = 255 / mbits; | |
485 | |||
486 |
2/2✓ Branch 0 taken 9481216 times.
✓ Branch 1 taken 8018080 times.
|
17499296 | for (y = 0; y < h; y++) { |
487 | 9481216 | xm = xm0; | |
488 |
2/2✓ Branch 0 taken 12489216 times.
✓ Branch 1 taken 9481216 times.
|
21970432 | for (x = 0; x < w; x++) { |
489 | 12489216 | t += ((mask[xm >> xmshf] >> ((~xm & xmmod) << l2depth)) & mbits) | |
490 | 12489216 | * mmult; | |
491 | 12489216 | xm++; | |
492 | } | ||
493 | 9481216 | mask += mask_linesize; | |
494 | } | ||
495 | 8018080 | alpha = (t >> shift) * alpha; | |
496 | 8018080 | *dst = ((0x1010101 - alpha) * *dst + alpha * src) >> 24; | |
497 | 8018080 | } | |
498 | |||
499 | 163680 | static void blend_line_hv16(uint8_t *dst, int dst_delta, | |
500 | unsigned src, unsigned alpha, | ||
501 | const uint8_t *mask, int mask_linesize, int l2depth, int w, | ||
502 | unsigned hsub, unsigned vsub, | ||
503 | int xm, int left, int right, int hband) | ||
504 | { | ||
505 | int x; | ||
506 | |||
507 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 163680 times.
|
163680 | if (left) { |
508 | ✗ | blend_pixel16(dst, src, alpha, mask, mask_linesize, l2depth, | |
509 | left, hband, hsub + vsub, xm); | ||
510 | ✗ | dst += dst_delta; | |
511 | ✗ | xm += left; | |
512 | } | ||
513 |
2/2✓ Branch 0 taken 1070080 times.
✓ Branch 1 taken 163680 times.
|
1233760 | for (x = 0; x < w; x++) { |
514 | 1070080 | blend_pixel16(dst, src, alpha, mask, mask_linesize, l2depth, | |
515 | 1070080 | 1 << hsub, hband, hsub + vsub, xm); | |
516 | 1070080 | dst += dst_delta; | |
517 | 1070080 | xm += 1 << hsub; | |
518 | } | ||
519 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 163680 times.
|
163680 | if (right) |
520 | ✗ | blend_pixel16(dst, src, alpha, mask, mask_linesize, l2depth, | |
521 | right, hband, hsub + vsub, xm); | ||
522 | 163680 | } | |
523 | |||
524 | 969204 | static void blend_line_hv(uint8_t *dst, int dst_delta, | |
525 | unsigned src, unsigned alpha, | ||
526 | const uint8_t *mask, int mask_linesize, int l2depth, int w, | ||
527 | unsigned hsub, unsigned vsub, | ||
528 | int xm, int left, int right, int hband) | ||
529 | { | ||
530 | int x; | ||
531 | |||
532 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 969204 times.
|
969204 | if (left) { |
533 | ✗ | blend_pixel(dst, src, alpha, mask, mask_linesize, l2depth, | |
534 | left, hband, hsub + vsub, xm); | ||
535 | ✗ | dst += dst_delta; | |
536 | ✗ | xm += left; | |
537 | } | ||
538 |
2/2✓ Branch 0 taken 8018080 times.
✓ Branch 1 taken 969204 times.
|
8987284 | for (x = 0; x < w; x++) { |
539 | 8018080 | blend_pixel(dst, src, alpha, mask, mask_linesize, l2depth, | |
540 | 8018080 | 1 << hsub, hband, hsub + vsub, xm); | |
541 | 8018080 | dst += dst_delta; | |
542 | 8018080 | xm += 1 << hsub; | |
543 | } | ||
544 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 969204 times.
|
969204 | if (right) |
545 | ✗ | blend_pixel(dst, src, alpha, mask, mask_linesize, l2depth, | |
546 | right, hband, hsub + vsub, xm); | ||
547 | 969204 | } | |
548 | |||
549 | 29824 | void ff_blend_mask(FFDrawContext *draw, FFDrawColor *color, | |
550 | uint8_t *dst[], int dst_linesize[], int dst_w, int dst_h, | ||
551 | const uint8_t *mask, int mask_linesize, int mask_w, int mask_h, | ||
552 | int l2depth, unsigned endianness, int x0, int y0) | ||
553 | { | ||
554 | unsigned alpha, nb_planes, nb_comp, plane, comp; | ||
555 | int xm0, ym0, w_sub, h_sub, x_sub, y_sub, left, right, top, bottom, y; | ||
556 | uint8_t *p0, *p; | ||
557 | const uint8_t *m; | ||
558 | |||
559 | 59648 | nb_comp = draw->desc->nb_components - | |
560 |
3/4✓ Branch 0 taken 2434 times.
✓ Branch 1 taken 27390 times.
✓ Branch 2 taken 2434 times.
✗ Branch 3 not taken.
|
29824 | !!(draw->desc->flags & AV_PIX_FMT_FLAG_ALPHA && !(draw->flags & FF_DRAW_PROCESS_ALPHA)); |
561 | |||
562 | 29824 | clip_interval(dst_w, &x0, &mask_w, &xm0); | |
563 | 29824 | clip_interval(dst_h, &y0, &mask_h, &ym0); | |
564 | 29824 | mask += ym0 * mask_linesize; | |
565 |
3/6✓ Branch 0 taken 29824 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 29824 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 29824 times.
|
29824 | if (mask_w <= 0 || mask_h <= 0 || !color->rgba[3]) |
566 | ✗ | return; | |
567 |
2/2✓ Branch 0 taken 26414 times.
✓ Branch 1 taken 3410 times.
|
29824 | if (draw->desc->comp[0].depth <= 8) { |
568 | /* alpha is in the [ 0 ; 0x10203 ] range, | ||
569 | alpha * mask is in the [ 0 ; 0x1010101 - 4 ] range */ | ||
570 | 26414 | alpha = (0x10307 * color->rgba[3] + 0x3) >> 8; | |
571 | } else { | ||
572 | 3410 | alpha = (0x101 * color->rgba[3] + 0x2) >> 8; | |
573 | } | ||
574 |
3/4✓ Branch 0 taken 2434 times.
✓ Branch 1 taken 27390 times.
✓ Branch 2 taken 2434 times.
✗ Branch 3 not taken.
|
29824 | nb_planes = draw->nb_planes - !!(draw->desc->flags & AV_PIX_FMT_FLAG_ALPHA && !(draw->flags & FF_DRAW_PROCESS_ALPHA)); |
575 | 29824 | nb_planes += !nb_planes; | |
576 |
2/2✓ Branch 0 taken 79364 times.
✓ Branch 1 taken 29824 times.
|
109188 | for (plane = 0; plane < nb_planes; plane++) { |
577 | 79364 | p0 = pointer_at(draw, dst, dst_linesize, plane, x0, y0); | |
578 | 79364 | w_sub = mask_w; | |
579 | 79364 | h_sub = mask_h; | |
580 | 79364 | x_sub = x0; | |
581 | 79364 | y_sub = y0; | |
582 | 79364 | subsampling_bounds(draw->hsub[plane], &x_sub, &w_sub, &left, &right); | |
583 | 79364 | subsampling_bounds(draw->vsub[plane], &y_sub, &h_sub, &top, &bottom); | |
584 |
2/2✓ Branch 0 taken 238092 times.
✓ Branch 1 taken 79364 times.
|
317456 | for (comp = 0; comp < nb_comp; comp++) { |
585 | 238092 | const int depth = draw->desc->comp[comp].depth; | |
586 | 238092 | const int offset = draw->desc->comp[comp].offset; | |
587 | 238092 | const int index = offset / ((depth + 7) / 8); | |
588 | |||
589 |
2/2✓ Branch 0 taken 148620 times.
✓ Branch 1 taken 89472 times.
|
238092 | if (draw->desc->comp[comp].plane != plane) |
590 | 148620 | continue; | |
591 | 89472 | p = p0 + offset; | |
592 | 89472 | m = mask; | |
593 |
2/2✓ Branch 0 taken 180 times.
✓ Branch 1 taken 89292 times.
|
89472 | if (top) { |
594 |
1/2✓ Branch 0 taken 180 times.
✗ Branch 1 not taken.
|
180 | if (depth <= 8) { |
595 | 180 | blend_line_hv(p, draw->pixelstep[plane], | |
596 | 180 | color->comp[plane].u8[index], alpha, | |
597 | m, mask_linesize, l2depth, w_sub, | ||
598 | 180 | draw->hsub[plane], draw->vsub[plane], | |
599 | xm0, left, right, top); | ||
600 | } else { | ||
601 | ✗ | blend_line_hv16(p, draw->pixelstep[plane], | |
602 | ✗ | color->comp[plane].u16[index], alpha, | |
603 | m, mask_linesize, l2depth, w_sub, | ||
604 | ✗ | draw->hsub[plane], draw->vsub[plane], | |
605 | xm0, left, right, top); | ||
606 | } | ||
607 | 180 | p += dst_linesize[plane]; | |
608 | 180 | m += top * mask_linesize; | |
609 | } | ||
610 |
2/2✓ Branch 0 taken 79242 times.
✓ Branch 1 taken 10230 times.
|
89472 | if (depth <= 8) { |
611 |
2/2✓ Branch 0 taken 968844 times.
✓ Branch 1 taken 79242 times.
|
1048086 | for (y = 0; y < h_sub; y++) { |
612 | 968844 | blend_line_hv(p, draw->pixelstep[plane], | |
613 | 968844 | color->comp[plane].u8[index], alpha, | |
614 | m, mask_linesize, l2depth, w_sub, | ||
615 | 968844 | draw->hsub[plane], draw->vsub[plane], | |
616 | 968844 | xm0, left, right, 1 << draw->vsub[plane]); | |
617 | 968844 | p += dst_linesize[plane]; | |
618 | 968844 | m += mask_linesize << draw->vsub[plane]; | |
619 | } | ||
620 | } else { | ||
621 |
2/2✓ Branch 0 taken 163680 times.
✓ Branch 1 taken 10230 times.
|
173910 | for (y = 0; y < h_sub; y++) { |
622 | 163680 | blend_line_hv16(p, draw->pixelstep[plane], | |
623 | 163680 | color->comp[plane].u16[index], alpha, | |
624 | m, mask_linesize, l2depth, w_sub, | ||
625 | 163680 | draw->hsub[plane], draw->vsub[plane], | |
626 | 163680 | xm0, left, right, 1 << draw->vsub[plane]); | |
627 | 163680 | p += dst_linesize[plane]; | |
628 | 163680 | m += mask_linesize << draw->vsub[plane]; | |
629 | } | ||
630 | } | ||
631 |
2/2✓ Branch 0 taken 180 times.
✓ Branch 1 taken 89292 times.
|
89472 | if (bottom) { |
632 |
1/2✓ Branch 0 taken 180 times.
✗ Branch 1 not taken.
|
180 | if (depth <= 8) { |
633 | 180 | blend_line_hv(p, draw->pixelstep[plane], | |
634 | 180 | color->comp[plane].u8[index], alpha, | |
635 | m, mask_linesize, l2depth, w_sub, | ||
636 | 180 | draw->hsub[plane], draw->vsub[plane], | |
637 | xm0, left, right, bottom); | ||
638 | } else { | ||
639 | ✗ | blend_line_hv16(p, draw->pixelstep[plane], | |
640 | ✗ | color->comp[plane].u16[index], alpha, | |
641 | m, mask_linesize, l2depth, w_sub, | ||
642 | ✗ | draw->hsub[plane], draw->vsub[plane], | |
643 | xm0, left, right, bottom); | ||
644 | } | ||
645 | } | ||
646 | } | ||
647 | } | ||
648 | } | ||
649 | |||
650 | 230094 | int ff_draw_round_to_sub(FFDrawContext *draw, int sub_dir, int round_dir, | |
651 | int value) | ||
652 | { | ||
653 |
2/2✓ Branch 0 taken 206761 times.
✓ Branch 1 taken 23333 times.
|
230094 | unsigned shift = sub_dir ? draw->vsub_max : draw->hsub_max; |
654 | |||
655 |
2/2✓ Branch 0 taken 105715 times.
✓ Branch 1 taken 124379 times.
|
230094 | if (!shift) |
656 | 105715 | return value; | |
657 |
2/2✓ Branch 0 taken 104106 times.
✓ Branch 1 taken 20273 times.
|
124379 | if (round_dir >= 0) |
658 |
2/2✓ Branch 0 taken 3396 times.
✓ Branch 1 taken 100710 times.
|
104106 | value += round_dir ? (1 << shift) - 1 : 1 << (shift - 1); |
659 | 124379 | return (value >> shift) << shift; | |
660 | } | ||
661 | |||
662 | 165 | AVFilterFormats *ff_draw_supported_pixel_formats(unsigned flags) | |
663 | { | ||
664 | enum AVPixelFormat i; | ||
665 | FFDrawContext draw; | ||
666 | 165 | AVFilterFormats *fmts = NULL; | |
667 | int ret; | ||
668 | |||
669 |
2/2✓ Branch 1 taken 40095 times.
✓ Branch 2 taken 165 times.
|
40260 | for (i = 0; av_pix_fmt_desc_get(i); i++) |
670 |
3/4✓ Branch 1 taken 15345 times.
✓ Branch 2 taken 24750 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 15345 times.
|
55440 | if (ff_draw_init(&draw, i, flags) >= 0 && |
671 | 15345 | (ret = ff_add_format(&fmts, i)) < 0) | |
672 | ✗ | return NULL; | |
673 | 165 | return fmts; | |
674 | } | ||
675 |