| 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 | 1188 | static int fill_map(const AVPixFmtDescriptor *desc, uint8_t *map) | |
| 36 | { | ||
| 37 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1188 times.
|
1188 | 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 34 times.
✓ Branch 1 taken 1154 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1188 times.
|
1188 | av_assert0(desc->nb_components == 3 + !!(desc->flags & AV_PIX_FMT_FLAG_ALPHA)); |
| 41 |
2/2✓ Branch 0 taken 949 times.
✓ Branch 1 taken 239 times.
|
1188 | if (desc->flags & AV_PIX_FMT_FLAG_PLANAR) { |
| 42 |
2/2✓ Branch 2 taken 307 times.
✓ Branch 3 taken 642 times.
|
949 | if (desc->nb_components != av_pix_fmt_count_planes(av_pix_fmt_desc_get_id(desc))) |
| 43 | 307 | return AVERROR(EINVAL); | |
| 44 | 642 | map[RED] = desc->comp[0].plane; | |
| 45 | 642 | map[GREEN] = desc->comp[1].plane; | |
| 46 | 642 | map[BLUE] = desc->comp[2].plane; | |
| 47 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 626 times.
|
642 | map[ALPHA] = (desc->flags & AV_PIX_FMT_FLAG_ALPHA) ? desc->comp[3].plane : 3; |
| 48 | } else { | ||
| 49 | 239 | int had0 = 0; | |
| 50 | 239 | unsigned depthb = 0; | |
| 51 |
2/2✓ Branch 0 taken 730 times.
✓ Branch 1 taken 236 times.
|
966 | for (unsigned i = 0; i < desc->nb_components; i++) { |
| 52 | /* all components must have same depth in bytes */ | ||
| 53 | 730 | unsigned db = (desc->comp[i].depth + 7) / 8; | |
| 54 | 730 | unsigned pos = desc->comp[i].offset / db; | |
| 55 |
3/4✓ Branch 0 taken 491 times.
✓ Branch 1 taken 239 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 491 times.
|
730 | if (depthb && (depthb != db)) |
| 56 | ✗ | return AVERROR(ENOSYS); | |
| 57 | |||
| 58 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 727 times.
|
730 | if (desc->comp[i].offset % db) |
| 59 | 3 | return AVERROR(ENOSYS); | |
| 60 | |||
| 61 | 727 | had0 |= pos == 0; | |
| 62 | 727 | map[i] = pos; | |
| 63 | 727 | depthb = db; | |
| 64 | } | ||
| 65 | |||
| 66 |
2/2✓ Branch 0 taken 218 times.
✓ Branch 1 taken 18 times.
|
236 | if (desc->nb_components == 3) |
| 67 |
1/2✓ Branch 0 taken 218 times.
✗ Branch 1 not taken.
|
218 | map[ALPHA] = had0 ? 3 : 0; |
| 68 | } | ||
| 69 | |||
| 70 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 878 times.
|
878 | av_assert0(map[RED] != map[GREEN]); |
| 71 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 878 times.
|
878 | av_assert0(map[GREEN] != map[BLUE]); |
| 72 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 878 times.
|
878 | av_assert0(map[BLUE] != map[RED]); |
| 73 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 878 times.
|
878 | av_assert0(map[RED] != map[ALPHA]); |
| 74 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 878 times.
|
878 | av_assert0(map[GREEN] != map[ALPHA]); |
| 75 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 878 times.
|
878 | av_assert0(map[BLUE] != map[ALPHA]); |
| 76 | |||
| 77 | 878 | return 0; | |
| 78 | } | ||
| 79 | |||
| 80 | 612 | int ff_fill_rgba_map(uint8_t *rgba_map, enum AVPixelFormat pix_fmt) | |
| 81 | { | ||
| 82 | 612 | const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); | |
| 83 |
2/2✓ Branch 0 taken 48 times.
✓ Branch 1 taken 564 times.
|
612 | if (!(desc->flags & AV_PIX_FMT_FLAG_RGB)) |
| 84 | 48 | return AVERROR(EINVAL); | |
| 85 | 564 | return fill_map(desc, rgba_map); | |
| 86 | } | ||
| 87 | |||
| 88 | 624 | int ff_fill_ayuv_map(uint8_t *ayuv_map, enum AVPixelFormat pix_fmt) | |
| 89 | { | ||
| 90 | 624 | const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); | |
| 91 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 624 times.
|
624 | if (desc->flags & AV_PIX_FMT_FLAG_RGB) |
| 92 | ✗ | return AVERROR(EINVAL); | |
| 93 | 624 | return fill_map(desc, ayuv_map); | |
| 94 | } | ||
| 95 | |||
| 96 | 55203 | int ff_draw_init2(FFDrawContext *draw, enum AVPixelFormat format, enum AVColorSpace csp, | |
| 97 | enum AVColorRange range, enum AVAlphaMode alpha, unsigned flags) | ||
| 98 | { | ||
| 99 | 55203 | const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(format); | |
| 100 | 55203 | const AVLumaCoefficients *luma = NULL; | |
| 101 | const AVComponentDescriptor *c; | ||
| 102 | 55203 | unsigned nb_planes = 0; | |
| 103 | 55203 | int pixelstep[MAX_PLANES] = { 0 }; | |
| 104 | 55203 | int depthb = 0; | |
| 105 | |||
| 106 |
2/4✓ Branch 0 taken 55203 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 55203 times.
|
55203 | if (!desc || !desc->name) |
| 107 | ✗ | return AVERROR(EINVAL); | |
| 108 |
2/2✓ Branch 0 taken 20090 times.
✓ Branch 1 taken 35113 times.
|
55203 | if (desc->flags & AV_PIX_FMT_FLAG_BE) |
| 109 | 20090 | return AVERROR(ENOSYS); | |
| 110 |
2/2✓ Branch 0 taken 8815 times.
✓ Branch 1 taken 26298 times.
|
35113 | if (desc->flags & ~(AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_ALPHA)) |
| 111 | 8815 | return AVERROR(ENOSYS); | |
| 112 |
2/2✓ Branch 0 taken 26244 times.
✓ Branch 1 taken 54 times.
|
26298 | if (csp == AVCOL_SPC_UNSPECIFIED) |
| 113 |
2/2✓ Branch 0 taken 8611 times.
✓ Branch 1 taken 17633 times.
|
26244 | csp = (desc->flags & AV_PIX_FMT_FLAG_RGB) ? AVCOL_SPC_RGB : AVCOL_SPC_SMPTE170M; |
| 114 |
3/4✓ Branch 0 taken 17633 times.
✓ Branch 1 taken 8665 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 17633 times.
|
26298 | if (!(desc->flags & AV_PIX_FMT_FLAG_RGB) && !(luma = av_csp_luma_coeffs_from_avcsp(csp))) |
| 115 | ✗ | return AVERROR(EINVAL); | |
| 116 |
2/2✓ Branch 0 taken 26106 times.
✓ Branch 1 taken 192 times.
|
26298 | if (range == AVCOL_RANGE_UNSPECIFIED) |
| 117 |
4/4✓ Branch 0 taken 25696 times.
✓ Branch 1 taken 205 times.
✓ Branch 2 taken 25491 times.
✓ Branch 3 taken 205 times.
|
52007 | range = (format == AV_PIX_FMT_YUVJ420P || format == AV_PIX_FMT_YUVJ422P || |
| 118 |
4/4✓ Branch 0 taken 25286 times.
✓ Branch 1 taken 205 times.
✓ Branch 2 taken 25081 times.
✓ Branch 3 taken 205 times.
|
25491 | format == AV_PIX_FMT_YUVJ444P || format == AV_PIX_FMT_YUVJ411P || |
| 119 |
2/2✓ Branch 0 taken 8611 times.
✓ Branch 1 taken 16470 times.
|
25081 | format == AV_PIX_FMT_YUVJ440P || csp == AVCOL_SPC_RGB) |
| 120 |
2/2✓ Branch 0 taken 25901 times.
✓ Branch 1 taken 205 times.
|
52007 | ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG; |
| 121 |
3/4✓ Branch 0 taken 16586 times.
✓ Branch 1 taken 9712 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 16586 times.
|
26298 | if (range != AVCOL_RANGE_JPEG && range != AVCOL_RANGE_MPEG) |
| 122 | ✗ | return AVERROR(EINVAL); | |
| 123 |
2/2✓ Branch 0 taken 70733 times.
✓ Branch 1 taken 20148 times.
|
90881 | for (unsigned i = 0; i < desc->nb_components; i++) { |
| 124 | int db; | ||
| 125 | 70733 | c = &desc->comp[i]; | |
| 126 | /* for now, only 8-16 bits formats */ | ||
| 127 |
4/4✓ Branch 0 taken 68683 times.
✓ Branch 1 taken 2050 times.
✓ Branch 2 taken 820 times.
✓ Branch 3 taken 67863 times.
|
70733 | if (c->depth < 8 || c->depth > 16) |
| 128 | 2870 | return AVERROR(ENOSYS); | |
| 129 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 67863 times.
|
67863 | if (c->plane >= MAX_PLANES) |
| 130 | ✗ | return AVERROR(ENOSYS); | |
| 131 | /* data must either be in the high or low bits, never middle */ | ||
| 132 |
4/4✓ Branch 0 taken 8025 times.
✓ Branch 1 taken 59838 times.
✓ Branch 2 taken 820 times.
✓ Branch 3 taken 7205 times.
|
67863 | if (c->shift && ((c->shift + c->depth) & 0x7)) |
| 133 | 820 | return AVERROR(ENOSYS); | |
| 134 | /* mixed >8 and <=8 depth */ | ||
| 135 | 67043 | db = (c->depth + 7) / 8; | |
| 136 |
3/4✓ Branch 0 taken 44230 times.
✓ Branch 1 taken 22813 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 44230 times.
|
67043 | if (depthb && (depthb != db)) |
| 137 | ✗ | return AVERROR(ENOSYS); | |
| 138 | 67043 | depthb = db; | |
| 139 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 67043 times.
|
67043 | if (db * (c->offset + 1) > 16) |
| 140 | ✗ | return AVERROR(ENOSYS); | |
| 141 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 67043 times.
|
67043 | if (c->offset % db) |
| 142 | ✗ | return AVERROR(ENOSYS); | |
| 143 | /* strange interleaving */ | ||
| 144 |
2/2✓ Branch 0 taken 13444 times.
✓ Branch 1 taken 53599 times.
|
67043 | if (pixelstep[c->plane] != 0 && |
| 145 |
2/2✓ Branch 0 taken 1435 times.
✓ Branch 1 taken 12009 times.
|
13444 | pixelstep[c->plane] != c->step) |
| 146 | 1435 | return AVERROR(ENOSYS); | |
| 147 | 65608 | pixelstep[c->plane] = c->step; | |
| 148 |
2/2✓ Branch 0 taken 1025 times.
✓ Branch 1 taken 64583 times.
|
65608 | if (pixelstep[c->plane] >= 8) |
| 149 | 1025 | return AVERROR(ENOSYS); | |
| 150 | 64583 | nb_planes = FFMAX(nb_planes, c->plane + 1); | |
| 151 | } | ||
| 152 | 20148 | memset(draw, 0, sizeof(*draw)); | |
| 153 | 20148 | draw->desc = desc; | |
| 154 | 20148 | draw->format = format; | |
| 155 | 20148 | draw->nb_planes = nb_planes; | |
| 156 | 20148 | draw->range = range; | |
| 157 | 20148 | draw->csp = csp; | |
| 158 | 20148 | draw->alpha = alpha; | |
| 159 | 20148 | draw->flags = flags; | |
| 160 |
2/2✓ Branch 0 taken 14968 times.
✓ Branch 1 taken 5180 times.
|
20148 | if (luma) |
| 161 | 14968 | ff_fill_rgb2yuv_table(luma, draw->rgb2yuv); | |
| 162 | 20148 | memcpy(draw->pixelstep, pixelstep, sizeof(draw->pixelstep)); | |
| 163 | 20148 | draw->hsub[1] = draw->hsub[2] = draw->hsub_max = desc->log2_chroma_w; | |
| 164 | 20148 | draw->vsub[1] = draw->vsub[2] = draw->vsub_max = desc->log2_chroma_h; | |
| 165 | 20148 | return 0; | |
| 166 | } | ||
| 167 | |||
| 168 | 262 | int ff_draw_init_from_link(FFDrawContext *draw, const AVFilterLink *link, | |
| 169 | unsigned flags) | ||
| 170 | { | ||
| 171 | 262 | return ff_draw_init2(draw, link->format, link->colorspace, link->color_range, link->alpha_mode, flags); | |
| 172 | } | ||
| 173 | |||
| 174 | 54941 | int ff_draw_init(FFDrawContext *draw, enum AVPixelFormat format, unsigned flags) | |
| 175 | { | ||
| 176 | 54941 | return ff_draw_init2(draw, format, AVCOL_SPC_UNSPECIFIED, AVCOL_RANGE_UNSPECIFIED, AVALPHA_MODE_UNSPECIFIED, flags); | |
| 177 | } | ||
| 178 | |||
| 179 | 232482 | void ff_draw_color(FFDrawContext *draw, FFDrawColor *color, const uint8_t rgba[4]) | |
| 180 | { | ||
| 181 | double yuvad[4]; | ||
| 182 | double rgbad[4]; | ||
| 183 | 232482 | const AVPixFmtDescriptor *desc = draw->desc; | |
| 184 | |||
| 185 |
1/2✓ Branch 0 taken 232482 times.
✗ Branch 1 not taken.
|
232482 | if (rgba != color->rgba) |
| 186 | 232482 | memcpy(color->rgba, rgba, sizeof(color->rgba)); | |
| 187 | |||
| 188 | 232482 | memset(color->comp, 0, sizeof(color->comp)); | |
| 189 | |||
| 190 |
2/2✓ Branch 0 taken 929928 times.
✓ Branch 1 taken 232482 times.
|
1162410 | for (int i = 0; i < 4; i++) |
| 191 | 929928 | rgbad[i] = color->rgba[i] / 255.; | |
| 192 | |||
| 193 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 232482 times.
|
232482 | if (draw->alpha == AVALPHA_MODE_PREMULTIPLIED) { |
| 194 | ✗ | for (int i = 0; i < 3; i++) | |
| 195 | ✗ | rgbad[i] *= rgbad[3]; | |
| 196 | } | ||
| 197 | |||
| 198 |
2/2✓ Branch 0 taken 54632 times.
✓ Branch 1 taken 177850 times.
|
232482 | if (draw->desc->flags & AV_PIX_FMT_FLAG_RGB) |
| 199 | 54632 | memcpy(yuvad, rgbad, sizeof(double) * 3); | |
| 200 | else | ||
| 201 | 177850 | ff_matrix_mul_3x3_vec(yuvad, rgbad, draw->rgb2yuv); | |
| 202 | |||
| 203 | 232482 | yuvad[3] = rgbad[3]; | |
| 204 | |||
| 205 |
2/2✓ Branch 0 taken 697446 times.
✓ Branch 1 taken 232482 times.
|
929928 | for (int i = 0; i < 3; i++) { |
| 206 |
4/4✓ Branch 0 taken 533550 times.
✓ Branch 1 taken 163896 times.
✓ Branch 2 taken 355700 times.
✓ Branch 3 taken 177850 times.
|
697446 | int chroma = (!(draw->desc->flags & AV_PIX_FMT_FLAG_RGB) && i > 0); |
| 207 |
2/2✓ Branch 0 taken 533469 times.
✓ Branch 1 taken 163977 times.
|
697446 | if (draw->range == AVCOL_RANGE_MPEG) { |
| 208 |
2/2✓ Branch 0 taken 355646 times.
✓ Branch 1 taken 177823 times.
|
533469 | yuvad[i] *= (chroma ? 224. : 219.) / 255.; |
| 209 |
2/2✓ Branch 0 taken 355646 times.
✓ Branch 1 taken 177823 times.
|
533469 | yuvad[i] += (chroma ? 128. : 16.) / 255.; |
| 210 |
2/2✓ Branch 0 taken 54 times.
✓ Branch 1 taken 163923 times.
|
163977 | } else if (chroma) { |
| 211 | 54 | yuvad[i] += 0.5; | |
| 212 | } | ||
| 213 | } | ||
| 214 | |||
| 215 | // Ensure we place the alpha appropriately for gray formats | ||
| 216 |
2/2✓ Branch 0 taken 19 times.
✓ Branch 1 taken 232463 times.
|
232482 | if (desc->nb_components <= 2) |
| 217 | 19 | yuvad[1] = yuvad[3]; | |
| 218 | |||
| 219 |
2/2✓ Branch 0 taken 723468 times.
✓ Branch 1 taken 232482 times.
|
955950 | for (unsigned i = 0; i < desc->nb_components; i++) { |
| 220 | 723468 | unsigned val = yuvad[i] * ((1 << (draw->desc->comp[i].depth + draw->desc->comp[i].shift)) - 1) + 0.5; | |
| 221 |
2/2✓ Branch 0 taken 59858 times.
✓ Branch 1 taken 663610 times.
|
723468 | if (desc->comp[i].depth > 8) |
| 222 | 59858 | color->comp[desc->comp[i].plane].u16[desc->comp[i].offset / 2] = val; | |
| 223 | else | ||
| 224 | 663610 | color->comp[desc->comp[i].plane].u8[desc->comp[i].offset] = val; | |
| 225 | } | ||
| 226 | 232482 | } | |
| 227 | |||
| 228 | 694577 | static uint8_t *pointer_at(FFDrawContext *draw, uint8_t *data[], int linesize[], | |
| 229 | int plane, int x, int y) | ||
| 230 | { | ||
| 231 | 694577 | return data[plane] + | |
| 232 | 1389154 | (y >> draw->vsub[plane]) * linesize[plane] + | |
| 233 | 694577 | (x >> draw->hsub[plane]) * draw->pixelstep[plane]; | |
| 234 | } | ||
| 235 | |||
| 236 | 90 | void ff_copy_rectangle2(FFDrawContext *draw, | |
| 237 | uint8_t *dst[], int dst_linesize[], | ||
| 238 | uint8_t *src[], int src_linesize[], | ||
| 239 | int dst_x, int dst_y, int src_x, int src_y, | ||
| 240 | int w, int h) | ||
| 241 | { | ||
| 242 | int wp, hp; | ||
| 243 | uint8_t *p, *q; | ||
| 244 | |||
| 245 |
2/2✓ Branch 0 taken 270 times.
✓ Branch 1 taken 90 times.
|
360 | for (int plane = 0; plane < draw->nb_planes; plane++) { |
| 246 | 270 | p = pointer_at(draw, src, src_linesize, plane, src_x, src_y); | |
| 247 | 270 | q = pointer_at(draw, dst, dst_linesize, plane, dst_x, dst_y); | |
| 248 | 270 | wp = AV_CEIL_RSHIFT(w, draw->hsub[plane]) * draw->pixelstep[plane]; | |
| 249 | 270 | hp = AV_CEIL_RSHIFT(h, draw->vsub[plane]); | |
| 250 |
2/2✓ Branch 0 taken 51840 times.
✓ Branch 1 taken 270 times.
|
52110 | for (int y = 0; y < hp; y++) { |
| 251 | 51840 | memcpy(q, p, wp); | |
| 252 | 51840 | p += src_linesize[plane]; | |
| 253 | 51840 | q += dst_linesize[plane]; | |
| 254 | } | ||
| 255 | } | ||
| 256 | 90 | } | |
| 257 | |||
| 258 | 235136 | void ff_fill_rectangle(FFDrawContext *draw, FFDrawColor *color, | |
| 259 | uint8_t *dst[], int dst_linesize[], | ||
| 260 | int dst_x, int dst_y, int w, int h) | ||
| 261 | { | ||
| 262 | int wp, hp; | ||
| 263 | uint8_t *p0, *p; | ||
| 264 | 235136 | FFDrawColor color_tmp = *color; | |
| 265 | |||
| 266 |
2/2✓ Branch 0 taken 596794 times.
✓ Branch 1 taken 235136 times.
|
831930 | for (int plane = 0; plane < draw->nb_planes; plane++) { |
| 267 | 596794 | p0 = pointer_at(draw, dst, dst_linesize, plane, dst_x, dst_y); | |
| 268 | 596794 | wp = AV_CEIL_RSHIFT(w, draw->hsub[plane]); | |
| 269 | 596794 | hp = AV_CEIL_RSHIFT(h, draw->vsub[plane]); | |
| 270 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 596794 times.
|
596794 | if (!hp) |
| 271 | ✗ | return; | |
| 272 | 596794 | p = p0; | |
| 273 | |||
| 274 | if (HAVE_BIGENDIAN && draw->desc->comp[0].depth > 8) { | ||
| 275 | for (int x = 0; 2*x < draw->pixelstep[plane]; x++) | ||
| 276 | color_tmp.comp[plane].u16[x] = av_bswap16(color_tmp.comp[plane].u16[x]); | ||
| 277 | } | ||
| 278 | |||
| 279 | /* copy first line from color */ | ||
| 280 |
2/2✓ Branch 0 taken 2659191 times.
✓ Branch 1 taken 596794 times.
|
3255985 | for (int x = 0; x < wp; x++) { |
| 281 | 2659191 | memcpy(p, color_tmp.comp[plane].u8, draw->pixelstep[plane]); | |
| 282 | 2659191 | p += draw->pixelstep[plane]; | |
| 283 | } | ||
| 284 | 596794 | wp *= draw->pixelstep[plane]; | |
| 285 | /* copy next lines from first line */ | ||
| 286 | 596794 | p = p0 + dst_linesize[plane]; | |
| 287 |
2/2✓ Branch 0 taken 10204880 times.
✓ Branch 1 taken 596794 times.
|
10801674 | for (int y = 1; y < hp; y++) { |
| 288 | 10204880 | memcpy(p, p0, wp); | |
| 289 | 10204880 | p += dst_linesize[plane]; | |
| 290 | } | ||
| 291 | } | ||
| 292 | } | ||
| 293 | |||
| 294 | /** | ||
| 295 | * Clip interval [x; x+w[ within [0; wmax[. | ||
| 296 | * The resulting w may be negative if the final interval is empty. | ||
| 297 | * dx, if not null, return the difference between in and out value of x. | ||
| 298 | */ | ||
| 299 | 71882 | static void clip_interval(int wmax, int *x, int *w, int *dx) | |
| 300 | { | ||
| 301 |
2/2✓ Branch 0 taken 69612 times.
✓ Branch 1 taken 2270 times.
|
71882 | if (dx) |
| 302 | 69612 | *dx = 0; | |
| 303 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 71882 times.
|
71882 | if (*x < 0) { |
| 304 | ✗ | if (dx) | |
| 305 | ✗ | *dx = -*x; | |
| 306 | ✗ | *w += *x; | |
| 307 | ✗ | *x = 0; | |
| 308 | } | ||
| 309 |
2/2✓ Branch 0 taken 107 times.
✓ Branch 1 taken 71775 times.
|
71882 | if (*x + *w > wmax) |
| 310 | 107 | *w = wmax - *x; | |
| 311 | 71882 | } | |
| 312 | |||
| 313 | /** | ||
| 314 | * Decompose w pixels starting at x | ||
| 315 | * into start + (w starting at x) + end | ||
| 316 | * with x and w aligned on multiples of 1<<sub. | ||
| 317 | */ | ||
| 318 | 194486 | static void subsampling_bounds(int sub, int *x, int *w, int *start, int *end) | |
| 319 | { | ||
| 320 | 194486 | int mask = (1 << sub) - 1; | |
| 321 | |||
| 322 | 194486 | *start = (-*x) & mask; | |
| 323 | 194486 | *x += *start; | |
| 324 | 194486 | *start = FFMIN(*start, *w); | |
| 325 | 194486 | *w -= *start; | |
| 326 | 194486 | *end = *w & mask; | |
| 327 | 194486 | *w >>= sub; | |
| 328 | 194486 | } | |
| 329 | |||
| 330 | /* If alpha is in the [ 0 ; 0x1010101 ] range, | ||
| 331 | then alpha * value is in the [ 0 ; 0xFFFFFFFF ] range, | ||
| 332 | and >> 24 gives a correct rounding. */ | ||
| 333 | 82392 | static void blend_line(uint8_t *dst, unsigned src, unsigned alpha, | |
| 334 | int dx, int w, unsigned hsub, int left, int right) | ||
| 335 | { | ||
| 336 | 82392 | unsigned asrc = alpha * src; | |
| 337 | 82392 | unsigned tau = 0x1010101 - alpha; | |
| 338 | |||
| 339 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 82392 times.
|
82392 | if (left) { |
| 340 | ✗ | unsigned suba = (left * alpha) >> hsub; | |
| 341 | ✗ | *dst = (*dst * (0x1010101 - suba) + src * suba) >> 24; | |
| 342 | ✗ | dst += dx; | |
| 343 | } | ||
| 344 |
2/2✓ Branch 0 taken 6768340 times.
✓ Branch 1 taken 82392 times.
|
6850732 | for (int x = 0; x < w; x++) { |
| 345 | 6768340 | *dst = (*dst * tau + asrc) >> 24; | |
| 346 | 6768340 | dst += dx; | |
| 347 | } | ||
| 348 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 82392 times.
|
82392 | if (right) { |
| 349 | ✗ | unsigned suba = (right * alpha) >> hsub; | |
| 350 | ✗ | *dst = (*dst * (0x1010101 - suba) + src * suba) >> 24; | |
| 351 | } | ||
| 352 | 82392 | } | |
| 353 | |||
| 354 | 11880 | static void blend_line16(uint8_t *dst, unsigned src, unsigned alpha, | |
| 355 | int dx, int w, unsigned hsub, int left, int right) | ||
| 356 | { | ||
| 357 | 11880 | unsigned asrc = alpha * src; | |
| 358 | 11880 | unsigned tau = 0x10001 - alpha; | |
| 359 | |||
| 360 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11880 times.
|
11880 | if (left) { |
| 361 | ✗ | unsigned suba = (left * alpha) >> hsub; | |
| 362 | ✗ | uint16_t value = AV_RL16(dst); | |
| 363 | ✗ | AV_WL16(dst, (value * (0x10001 - suba) + src * suba) >> 16); | |
| 364 | ✗ | dst += dx; | |
| 365 | } | ||
| 366 |
2/2✓ Branch 0 taken 792000 times.
✓ Branch 1 taken 11880 times.
|
803880 | for (int x = 0; x < w; x++) { |
| 367 | 792000 | uint16_t value = AV_RL16(dst); | |
| 368 | 792000 | AV_WL16(dst, (value * tau + asrc) >> 16); | |
| 369 | 792000 | dst += dx; | |
| 370 | } | ||
| 371 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11880 times.
|
11880 | if (right) { |
| 372 | ✗ | unsigned suba = (right * alpha) >> hsub; | |
| 373 | ✗ | uint16_t value = AV_RL16(dst); | |
| 374 | ✗ | AV_WL16(dst, (value * (0x10001 - suba) + src * suba) >> 16); | |
| 375 | } | ||
| 376 | 11880 | } | |
| 377 | |||
| 378 | /* the colour as blended: its transparency is already in the coverage, so it covers the alpha plane fully */ | ||
| 379 | 35941 | static FFDrawColor blended_color(FFDrawContext *draw, const FFDrawColor *color) | |
| 380 | { | ||
| 381 | 35941 | const AVPixFmtDescriptor *desc = draw->desc; | |
| 382 | 35941 | const AVComponentDescriptor *alpha = &desc->comp[desc->nb_components - 1]; | |
| 383 | 35941 | FFDrawColor over = *color; | |
| 384 | |||
| 385 |
4/4✓ Branch 0 taken 2507 times.
✓ Branch 1 taken 33434 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 2505 times.
|
35941 | if (desc->flags & AV_PIX_FMT_FLAG_ALPHA && draw->flags & FF_DRAW_PROCESS_ALPHA) { |
| 386 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | if (alpha->depth <= 8) |
| 387 | 2 | over.comp[alpha->plane].u8[alpha->offset] = 0xFF; | |
| 388 | else | ||
| 389 | ✗ | over.comp[alpha->plane].u16[alpha->offset / 2] = (1 << alpha->depth) - 1; | |
| 390 | } | ||
| 391 | 35941 | return over; | |
| 392 | } | ||
| 393 | |||
| 394 | 1135 | void ff_blend_rectangle(FFDrawContext *draw, FFDrawColor *color, | |
| 395 | uint8_t *dst[], int dst_linesize[], | ||
| 396 | int dst_w, int dst_h, | ||
| 397 | int x0, int y0, int w, int h) | ||
| 398 | { | ||
| 399 | 1135 | FFDrawColor over = blended_color(draw, color); | |
| 400 | unsigned alpha, nb_planes, nb_comp; | ||
| 401 | int w_sub, h_sub, x_sub, y_sub, left, right, top, bottom; | ||
| 402 | uint8_t *p0, *p; | ||
| 403 | |||
| 404 | 2270 | nb_comp = draw->desc->nb_components - | |
| 405 |
4/4✓ Branch 0 taken 72 times.
✓ Branch 1 taken 1063 times.
✓ Branch 2 taken 71 times.
✓ Branch 3 taken 1 times.
|
1135 | !!(draw->desc->flags & AV_PIX_FMT_FLAG_ALPHA && !(draw->flags & FF_DRAW_PROCESS_ALPHA)); |
| 406 | |||
| 407 | /* TODO optimize if alpha = 0xFF */ | ||
| 408 | 1135 | clip_interval(dst_w, &x0, &w, NULL); | |
| 409 | 1135 | clip_interval(dst_h, &y0, &h, NULL); | |
| 410 |
3/6✓ Branch 0 taken 1135 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1135 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1135 times.
|
1135 | if (w <= 0 || h <= 0 || !color->rgba[3]) |
| 411 | ✗ | return; | |
| 412 |
2/2✓ Branch 0 taken 1025 times.
✓ Branch 1 taken 110 times.
|
1135 | if (draw->desc->comp[0].depth <= 8) { |
| 413 | /* 0x10203 * alpha + 2 is in the [ 2 ; 0x1010101 - 2 ] range */ | ||
| 414 | 1025 | alpha = 0x10203 * color->rgba[3] + 0x2; | |
| 415 | } else { | ||
| 416 | /* 0x101 * alpha is in the [ 2 ; 0x1001] range */ | ||
| 417 | 110 | alpha = 0x101 * color->rgba[3] + 0x2; | |
| 418 | } | ||
| 419 |
4/4✓ Branch 0 taken 72 times.
✓ Branch 1 taken 1063 times.
✓ Branch 2 taken 71 times.
✓ Branch 3 taken 1 times.
|
1135 | nb_planes = draw->nb_planes - !!(draw->desc->flags & AV_PIX_FMT_FLAG_ALPHA && !(draw->flags & FF_DRAW_PROCESS_ALPHA)); |
| 420 | 1135 | nb_planes += !nb_planes; | |
| 421 |
2/2✓ Branch 0 taken 3091 times.
✓ Branch 1 taken 1135 times.
|
4226 | for (unsigned plane = 0; plane < nb_planes; plane++) { |
| 422 | 3091 | p0 = pointer_at(draw, dst, dst_linesize, plane, x0, y0); | |
| 423 | 3091 | w_sub = w; | |
| 424 | 3091 | h_sub = h; | |
| 425 | 3091 | x_sub = x0; | |
| 426 | 3091 | y_sub = y0; | |
| 427 | 3091 | subsampling_bounds(draw->hsub[plane], &x_sub, &w_sub, &left, &right); | |
| 428 | 3091 | subsampling_bounds(draw->vsub[plane], &y_sub, &h_sub, &top, &bottom); | |
| 429 |
2/2✓ Branch 0 taken 9274 times.
✓ Branch 1 taken 3091 times.
|
12365 | for (unsigned comp = 0; comp < nb_comp; comp++) { |
| 430 | 9274 | const int depth = draw->desc->comp[comp].depth; | |
| 431 | 9274 | const int offset = draw->desc->comp[comp].offset; | |
| 432 | 9274 | const int index = offset / ((depth + 7) / 8); | |
| 433 | |||
| 434 |
2/2✓ Branch 0 taken 5868 times.
✓ Branch 1 taken 3406 times.
|
9274 | if (draw->desc->comp[comp].plane != plane) |
| 435 | 5868 | continue; | |
| 436 | 3406 | p = p0 + offset; | |
| 437 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3406 times.
|
3406 | if (top) { |
| 438 | ✗ | if (depth <= 8) { | |
| 439 | ✗ | blend_line(p, over.comp[plane].u8[index], alpha >> 1, | |
| 440 | draw->pixelstep[plane], w_sub, | ||
| 441 | ✗ | draw->hsub[plane], left, right); | |
| 442 | } else { | ||
| 443 | ✗ | blend_line16(p, over.comp[plane].u16[index], alpha >> 1, | |
| 444 | draw->pixelstep[plane], w_sub, | ||
| 445 | ✗ | draw->hsub[plane], left, right); | |
| 446 | } | ||
| 447 | ✗ | p += dst_linesize[plane]; | |
| 448 | } | ||
| 449 |
2/2✓ Branch 0 taken 3076 times.
✓ Branch 1 taken 330 times.
|
3406 | if (depth <= 8) { |
| 450 |
2/2✓ Branch 0 taken 82392 times.
✓ Branch 1 taken 3076 times.
|
85468 | for (int y = 0; y < h_sub; y++) { |
| 451 | 82392 | blend_line(p, over.comp[plane].u8[index], alpha, | |
| 452 | draw->pixelstep[plane], w_sub, | ||
| 453 | 82392 | draw->hsub[plane], left, right); | |
| 454 | 82392 | p += dst_linesize[plane]; | |
| 455 | } | ||
| 456 | } else { | ||
| 457 |
2/2✓ Branch 0 taken 11880 times.
✓ Branch 1 taken 330 times.
|
12210 | for (int y = 0; y < h_sub; y++) { |
| 458 | 11880 | blend_line16(p, over.comp[plane].u16[index], alpha, | |
| 459 | draw->pixelstep[plane], w_sub, | ||
| 460 | 11880 | draw->hsub[plane], left, right); | |
| 461 | 11880 | p += dst_linesize[plane]; | |
| 462 | } | ||
| 463 | } | ||
| 464 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3406 times.
|
3406 | if (bottom) { |
| 465 | ✗ | if (depth <= 8) { | |
| 466 | ✗ | blend_line(p, over.comp[plane].u8[index], alpha >> 1, | |
| 467 | draw->pixelstep[plane], w_sub, | ||
| 468 | ✗ | draw->hsub[plane], left, right); | |
| 469 | } else { | ||
| 470 | ✗ | blend_line16(p, over.comp[plane].u16[index], alpha >> 1, | |
| 471 | draw->pixelstep[plane], w_sub, | ||
| 472 | ✗ | draw->hsub[plane], left, right); | |
| 473 | } | ||
| 474 | } | ||
| 475 | } | ||
| 476 | } | ||
| 477 | } | ||
| 478 | |||
| 479 | 1070080 | static void blend_pixel16(uint8_t *dst, unsigned src, unsigned alpha, | |
| 480 | const uint8_t *mask, int mask_linesize, int l2depth, | ||
| 481 | unsigned w, unsigned h, unsigned shift, unsigned xm0) | ||
| 482 | { | ||
| 483 | 1070080 | unsigned t = 0; | |
| 484 | 1070080 | unsigned xmshf = 3 - l2depth; | |
| 485 | 1070080 | unsigned xmmod = 7 >> l2depth; | |
| 486 | 1070080 | unsigned mbits = (1 << (1 << l2depth)) - 1; | |
| 487 | 1070080 | unsigned mmult = 255 / mbits; | |
| 488 | 1070080 | uint16_t value = AV_RL16(dst); | |
| 489 | |||
| 490 |
2/2✓ Branch 0 taken 1070080 times.
✓ Branch 1 taken 1070080 times.
|
2140160 | for (unsigned y = 0; y < h; y++) { |
| 491 | 1070080 | unsigned xm = xm0; | |
| 492 |
2/2✓ Branch 0 taken 1605120 times.
✓ Branch 1 taken 1070080 times.
|
2675200 | for (unsigned x = 0; x < w; x++) { |
| 493 | 1605120 | t += ((mask[xm >> xmshf] >> ((~xm & xmmod) << l2depth)) & mbits) | |
| 494 | 1605120 | * mmult; | |
| 495 | 1605120 | xm++; | |
| 496 | } | ||
| 497 | 1070080 | mask += mask_linesize; | |
| 498 | } | ||
| 499 | 1070080 | alpha = (t >> shift) * alpha; | |
| 500 | 1070080 | AV_WL16(dst, ((0x10001 - alpha) * value + alpha * src) >> 16); | |
| 501 | 1070080 | } | |
| 502 | |||
| 503 | 9101428 | static void blend_pixel(uint8_t *dst, unsigned src, unsigned alpha, | |
| 504 | const uint8_t *mask, int mask_linesize, int l2depth, | ||
| 505 | unsigned w, unsigned h, unsigned shift, unsigned xm0) | ||
| 506 | { | ||
| 507 | 9101428 | unsigned t = 0; | |
| 508 | 9101428 | unsigned xmshf = 3 - l2depth; | |
| 509 | 9101428 | unsigned xmmod = 7 >> l2depth; | |
| 510 | 9101428 | unsigned mbits = (1 << (1 << l2depth)) - 1; | |
| 511 | 9101428 | unsigned mmult = 255 / mbits; | |
| 512 | |||
| 513 |
2/2✓ Branch 0 taken 10923844 times.
✓ Branch 1 taken 9101428 times.
|
20025272 | for (unsigned y = 0; y < h; y++) { |
| 514 | 10923844 | unsigned xm = xm0; | |
| 515 |
2/2✓ Branch 0 taken 14653156 times.
✓ Branch 1 taken 10923844 times.
|
25577000 | for (unsigned x = 0; x < w; x++) { |
| 516 | 14653156 | t += ((mask[xm >> xmshf] >> ((~xm & xmmod) << l2depth)) & mbits) | |
| 517 | 14653156 | * mmult; | |
| 518 | 14653156 | xm++; | |
| 519 | } | ||
| 520 | 10923844 | mask += mask_linesize; | |
| 521 | } | ||
| 522 | 9101428 | alpha = (t >> shift) * alpha; | |
| 523 | 9101428 | *dst = ((0x1010101 - alpha) * *dst + alpha * src) >> 24; | |
| 524 | 9101428 | } | |
| 525 | |||
| 526 | 163680 | static void blend_line_hv16(uint8_t *dst, int dst_delta, | |
| 527 | unsigned src, unsigned alpha, | ||
| 528 | const uint8_t *mask, int mask_linesize, int l2depth, int w, | ||
| 529 | unsigned hsub, unsigned vsub, | ||
| 530 | int xm, int left, int right, int hband) | ||
| 531 | { | ||
| 532 | |||
| 533 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 163680 times.
|
163680 | if (left) { |
| 534 | ✗ | blend_pixel16(dst, src, alpha, mask, mask_linesize, l2depth, | |
| 535 | left, hband, hsub + vsub, xm); | ||
| 536 | ✗ | dst += dst_delta; | |
| 537 | ✗ | xm += left; | |
| 538 | } | ||
| 539 |
2/2✓ Branch 0 taken 1070080 times.
✓ Branch 1 taken 163680 times.
|
1233760 | for (int x = 0; x < w; x++) { |
| 540 | 1070080 | blend_pixel16(dst, src, alpha, mask, mask_linesize, l2depth, | |
| 541 | 1070080 | 1 << hsub, hband, hsub + vsub, xm); | |
| 542 | 1070080 | dst += dst_delta; | |
| 543 | 1070080 | xm += 1 << hsub; | |
| 544 | } | ||
| 545 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 163680 times.
|
163680 | if (right) |
| 546 | ✗ | blend_pixel16(dst, src, alpha, mask, mask_linesize, l2depth, | |
| 547 | right, hband, hsub + vsub, xm); | ||
| 548 | 163680 | } | |
| 549 | |||
| 550 | 1127076 | static void blend_line_hv(uint8_t *dst, int dst_delta, | |
| 551 | unsigned src, unsigned alpha, | ||
| 552 | const uint8_t *mask, int mask_linesize, int l2depth, int w, | ||
| 553 | unsigned hsub, unsigned vsub, | ||
| 554 | int xm, int left, int right, int hband) | ||
| 555 | { | ||
| 556 | |||
| 557 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1127076 times.
|
1127076 | if (left) { |
| 558 | ✗ | blend_pixel(dst, src, alpha, mask, mask_linesize, l2depth, | |
| 559 | left, hband, hsub + vsub, xm); | ||
| 560 | ✗ | dst += dst_delta; | |
| 561 | ✗ | xm += left; | |
| 562 | } | ||
| 563 |
2/2✓ Branch 0 taken 9101428 times.
✓ Branch 1 taken 1127076 times.
|
10228504 | for (int x = 0; x < w; x++) { |
| 564 | 9101428 | blend_pixel(dst, src, alpha, mask, mask_linesize, l2depth, | |
| 565 | 9101428 | 1 << hsub, hband, hsub + vsub, xm); | |
| 566 | 9101428 | dst += dst_delta; | |
| 567 | 9101428 | xm += 1 << hsub; | |
| 568 | } | ||
| 569 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1127076 times.
|
1127076 | if (right) |
| 570 | ✗ | blend_pixel(dst, src, alpha, mask, mask_linesize, l2depth, | |
| 571 | right, hband, hsub + vsub, xm); | ||
| 572 | 1127076 | } | |
| 573 | |||
| 574 | 34806 | void ff_blend_mask(FFDrawContext *draw, FFDrawColor *color, | |
| 575 | uint8_t *dst[], int dst_linesize[], int dst_w, int dst_h, | ||
| 576 | const uint8_t *mask, int mask_linesize, int mask_w, int mask_h, | ||
| 577 | int l2depth, unsigned endianness, int x0, int y0) | ||
| 578 | { | ||
| 579 | 34806 | FFDrawColor over = blended_color(draw, color); | |
| 580 | unsigned alpha, nb_planes, nb_comp; | ||
| 581 | int xm0, ym0, w_sub, h_sub, x_sub, y_sub, left, right, top, bottom; | ||
| 582 | uint8_t *p; | ||
| 583 | const uint8_t *m; | ||
| 584 | |||
| 585 | 69612 | nb_comp = draw->desc->nb_components - | |
| 586 |
4/4✓ Branch 0 taken 2435 times.
✓ Branch 1 taken 32371 times.
✓ Branch 2 taken 2434 times.
✓ Branch 3 taken 1 times.
|
34806 | !!(draw->desc->flags & AV_PIX_FMT_FLAG_ALPHA && !(draw->flags & FF_DRAW_PROCESS_ALPHA)); |
| 587 | |||
| 588 | 34806 | clip_interval(dst_w, &x0, &mask_w, &xm0); | |
| 589 | 34806 | clip_interval(dst_h, &y0, &mask_h, &ym0); | |
| 590 | 34806 | mask += ym0 * mask_linesize; | |
| 591 |
5/6✓ Branch 0 taken 34758 times.
✓ Branch 1 taken 48 times.
✓ Branch 2 taken 34754 times.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 34754 times.
|
34806 | if (mask_w <= 0 || mask_h <= 0 || !color->rgba[3]) |
| 592 | 52 | return; | |
| 593 |
2/2✓ Branch 0 taken 31344 times.
✓ Branch 1 taken 3410 times.
|
34754 | if (draw->desc->comp[0].depth <= 8) { |
| 594 | /* alpha is in the [ 0 ; 0x10203 ] range, | ||
| 595 | alpha * mask is in the [ 0 ; 0x1010101 - 4 ] range */ | ||
| 596 | 31344 | alpha = (0x10307 * color->rgba[3] + 0x3) >> 8; | |
| 597 | } else { | ||
| 598 | 3410 | alpha = (0x101 * color->rgba[3] + 0x2) >> 8; | |
| 599 | } | ||
| 600 |
4/4✓ Branch 0 taken 2435 times.
✓ Branch 1 taken 32319 times.
✓ Branch 2 taken 2434 times.
✓ Branch 3 taken 1 times.
|
34754 | nb_planes = draw->nb_planes - !!(draw->desc->flags & AV_PIX_FMT_FLAG_ALPHA && !(draw->flags & FF_DRAW_PROCESS_ALPHA)); |
| 601 | 34754 | nb_planes += !nb_planes; | |
| 602 |
2/2✓ Branch 0 taken 94152 times.
✓ Branch 1 taken 34754 times.
|
128906 | for (unsigned plane = 0; plane < nb_planes; plane++) { |
| 603 | 94152 | uint8_t *p0 = pointer_at(draw, dst, dst_linesize, plane, x0, y0); | |
| 604 | 94152 | w_sub = mask_w; | |
| 605 | 94152 | h_sub = mask_h; | |
| 606 | 94152 | x_sub = x0; | |
| 607 | 94152 | y_sub = y0; | |
| 608 | 94152 | subsampling_bounds(draw->hsub[plane], &x_sub, &w_sub, &left, &right); | |
| 609 | 94152 | subsampling_bounds(draw->vsub[plane], &y_sub, &h_sub, &top, &bottom); | |
| 610 |
2/2✓ Branch 0 taken 282457 times.
✓ Branch 1 taken 94152 times.
|
376609 | for (unsigned comp = 0; comp < nb_comp; comp++) { |
| 611 | 282457 | const int depth = draw->desc->comp[comp].depth; | |
| 612 | 282457 | const int offset = draw->desc->comp[comp].offset; | |
| 613 | 282457 | const int index = offset / ((depth + 7) / 8); | |
| 614 | |||
| 615 |
2/2✓ Branch 0 taken 178194 times.
✓ Branch 1 taken 104263 times.
|
282457 | if (draw->desc->comp[comp].plane != plane) |
| 616 | 178194 | continue; | |
| 617 | 104263 | p = p0 + offset; | |
| 618 | 104263 | m = mask; | |
| 619 |
2/2✓ Branch 0 taken 352 times.
✓ Branch 1 taken 103911 times.
|
104263 | if (top) { |
| 620 |
1/2✓ Branch 0 taken 352 times.
✗ Branch 1 not taken.
|
352 | if (depth <= 8) { |
| 621 | 352 | blend_line_hv(p, draw->pixelstep[plane], | |
| 622 | 352 | over.comp[plane].u8[index], alpha, | |
| 623 | m, mask_linesize, l2depth, w_sub, | ||
| 624 | 352 | draw->hsub[plane], draw->vsub[plane], | |
| 625 | xm0, left, right, top); | ||
| 626 | } else { | ||
| 627 | ✗ | blend_line_hv16(p, draw->pixelstep[plane], | |
| 628 | ✗ | over.comp[plane].u16[index], alpha, | |
| 629 | m, mask_linesize, l2depth, w_sub, | ||
| 630 | ✗ | draw->hsub[plane], draw->vsub[plane], | |
| 631 | xm0, left, right, top); | ||
| 632 | } | ||
| 633 | 352 | p += dst_linesize[plane]; | |
| 634 | 352 | m += top * mask_linesize; | |
| 635 | } | ||
| 636 |
2/2✓ Branch 0 taken 94033 times.
✓ Branch 1 taken 10230 times.
|
104263 | if (depth <= 8) { |
| 637 |
2/2✓ Branch 0 taken 1126372 times.
✓ Branch 1 taken 94033 times.
|
1220405 | for (int y = 0; y < h_sub; y++) { |
| 638 | 1126372 | blend_line_hv(p, draw->pixelstep[plane], | |
| 639 | 1126372 | over.comp[plane].u8[index], alpha, | |
| 640 | m, mask_linesize, l2depth, w_sub, | ||
| 641 | 1126372 | draw->hsub[plane], draw->vsub[plane], | |
| 642 | 1126372 | xm0, left, right, 1 << draw->vsub[plane]); | |
| 643 | 1126372 | p += dst_linesize[plane]; | |
| 644 | 1126372 | m += mask_linesize << draw->vsub[plane]; | |
| 645 | } | ||
| 646 | } else { | ||
| 647 |
2/2✓ Branch 0 taken 163680 times.
✓ Branch 1 taken 10230 times.
|
173910 | for (int y = 0; y < h_sub; y++) { |
| 648 | 163680 | blend_line_hv16(p, draw->pixelstep[plane], | |
| 649 | 163680 | over.comp[plane].u16[index], alpha, | |
| 650 | m, mask_linesize, l2depth, w_sub, | ||
| 651 | 163680 | draw->hsub[plane], draw->vsub[plane], | |
| 652 | 163680 | xm0, left, right, 1 << draw->vsub[plane]); | |
| 653 | 163680 | p += dst_linesize[plane]; | |
| 654 | 163680 | m += mask_linesize << draw->vsub[plane]; | |
| 655 | } | ||
| 656 | } | ||
| 657 |
2/2✓ Branch 0 taken 352 times.
✓ Branch 1 taken 103911 times.
|
104263 | if (bottom) { |
| 658 |
1/2✓ Branch 0 taken 352 times.
✗ Branch 1 not taken.
|
352 | if (depth <= 8) { |
| 659 | 352 | blend_line_hv(p, draw->pixelstep[plane], | |
| 660 | 352 | over.comp[plane].u8[index], alpha, | |
| 661 | m, mask_linesize, l2depth, w_sub, | ||
| 662 | 352 | draw->hsub[plane], draw->vsub[plane], | |
| 663 | xm0, left, right, bottom); | ||
| 664 | } else { | ||
| 665 | ✗ | blend_line_hv16(p, draw->pixelstep[plane], | |
| 666 | ✗ | over.comp[plane].u16[index], alpha, | |
| 667 | m, mask_linesize, l2depth, w_sub, | ||
| 668 | ✗ | draw->hsub[plane], draw->vsub[plane], | |
| 669 | xm0, left, right, bottom); | ||
| 670 | } | ||
| 671 | } | ||
| 672 | } | ||
| 673 | } | ||
| 674 | } | ||
| 675 | |||
| 676 | 257113 | int ff_draw_round_to_sub(FFDrawContext *draw, int sub_dir, int round_dir, | |
| 677 | int value) | ||
| 678 | { | ||
| 679 |
2/2✓ Branch 0 taken 229521 times.
✓ Branch 1 taken 27592 times.
|
257113 | unsigned shift = sub_dir ? draw->vsub_max : draw->hsub_max; |
| 680 | |||
| 681 |
2/2✓ Branch 0 taken 105742 times.
✓ Branch 1 taken 151371 times.
|
257113 | if (!shift) |
| 682 | 105742 | return value; | |
| 683 |
2/2✓ Branch 0 taken 125793 times.
✓ Branch 1 taken 25578 times.
|
151371 | if (round_dir >= 0) |
| 684 |
2/2✓ Branch 0 taken 4271 times.
✓ Branch 1 taken 121522 times.
|
125793 | value += round_dir ? (1 << shift) - 1 : 1 << (shift - 1); |
| 685 | 151371 | return (value >> shift) << shift; | |
| 686 | } | ||
| 687 | |||
| 688 | 204 | AVFilterFormats *ff_draw_supported_pixel_formats(unsigned flags) | |
| 689 | { | ||
| 690 | FFDrawContext draw; | ||
| 691 | 204 | AVFilterFormats *fmts = NULL; | |
| 692 | int ret; | ||
| 693 | |||
| 694 |
2/2✓ Branch 1 taken 54672 times.
✓ Branch 2 taken 204 times.
|
54876 | for (enum AVPixelFormat i = 0; av_pix_fmt_desc_get(i); i++) |
| 695 |
3/4✓ Branch 1 taken 19788 times.
✓ Branch 2 taken 34884 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 19788 times.
|
74460 | if (ff_draw_init(&draw, i, flags) >= 0 && |
| 696 | 19788 | (ret = ff_add_format(&fmts, i)) < 0) | |
| 697 | ✗ | return NULL; | |
| 698 | 204 | return fmts; | |
| 699 | } | ||
| 700 |