| 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 | 68892 | int ff_draw_init2(FFDrawContext *draw, enum AVPixelFormat format, enum AVColorSpace csp, | |
| 97 | enum AVColorRange range, enum AVAlphaMode alpha, unsigned flags) | ||
| 98 | { | ||
| 99 | 68892 | const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(format); | |
| 100 | 68892 | const AVLumaCoefficients *luma = NULL; | |
| 101 | const AVComponentDescriptor *c; | ||
| 102 | 68892 | unsigned nb_planes = 0; | |
| 103 | 68892 | int pixelstep[MAX_PLANES] = { 0 }; | |
| 104 | 68892 | int depthb = 0; | |
| 105 | |||
| 106 |
2/4✓ Branch 0 taken 68892 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 68892 times.
|
68892 | if (!desc || !desc->name) |
| 107 | ✗ | return AVERROR(EINVAL); | |
| 108 |
2/2✓ Branch 0 taken 25146 times.
✓ Branch 1 taken 43746 times.
|
68892 | if (desc->flags & AV_PIX_FMT_FLAG_BE) |
| 109 | 25146 | return AVERROR(ENOSYS); | |
| 110 |
2/2✓ Branch 0 taken 11176 times.
✓ Branch 1 taken 32570 times.
|
43746 | if (desc->flags & ~(AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_ALPHA)) |
| 111 | 11176 | return AVERROR(ENOSYS); | |
| 112 |
2/2✓ Branch 0 taken 32516 times.
✓ Branch 1 taken 54 times.
|
32570 | if (csp == AVCOL_SPC_UNSPECIFIED) |
| 113 |
2/2✓ Branch 0 taken 10669 times.
✓ Branch 1 taken 21847 times.
|
32516 | csp = (desc->flags & AV_PIX_FMT_FLAG_RGB) ? AVCOL_SPC_RGB : AVCOL_SPC_SMPTE170M; |
| 114 |
3/4✓ Branch 0 taken 21847 times.
✓ Branch 1 taken 10723 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 21847 times.
|
32570 | 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 32377 times.
✓ Branch 1 taken 193 times.
|
32570 | if (range == AVCOL_RANGE_UNSPECIFIED) |
| 117 |
4/4✓ Branch 0 taken 31869 times.
✓ Branch 1 taken 254 times.
✓ Branch 2 taken 31615 times.
✓ Branch 3 taken 254 times.
|
64500 | range = (format == AV_PIX_FMT_YUVJ420P || format == AV_PIX_FMT_YUVJ422P || |
| 118 |
4/4✓ Branch 0 taken 31361 times.
✓ Branch 1 taken 254 times.
✓ Branch 2 taken 31107 times.
✓ Branch 3 taken 254 times.
|
31615 | format == AV_PIX_FMT_YUVJ444P || format == AV_PIX_FMT_YUVJ411P || |
| 119 |
2/2✓ Branch 0 taken 10669 times.
✓ Branch 1 taken 20438 times.
|
31107 | format == AV_PIX_FMT_YUVJ440P || csp == AVCOL_SPC_RGB) |
| 120 |
2/2✓ Branch 0 taken 32123 times.
✓ Branch 1 taken 254 times.
|
64500 | ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG; |
| 121 |
3/4✓ Branch 0 taken 20555 times.
✓ Branch 1 taken 12015 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 20555 times.
|
32570 | if (range != AVCOL_RANGE_JPEG && range != AVCOL_RANGE_MPEG) |
| 122 | ✗ | return AVERROR(EINVAL); | |
| 123 |
2/2✓ Branch 0 taken 87591 times.
✓ Branch 1 taken 24950 times.
|
112541 | for (unsigned i = 0; i < desc->nb_components; i++) { |
| 124 | int db; | ||
| 125 | 87591 | c = &desc->comp[i]; | |
| 126 | /* for now, only 8-16 bits formats */ | ||
| 127 |
4/4✓ Branch 0 taken 85051 times.
✓ Branch 1 taken 2540 times.
✓ Branch 2 taken 1016 times.
✓ Branch 3 taken 84035 times.
|
87591 | if (c->depth < 8 || c->depth > 16) |
| 128 | 3556 | return AVERROR(ENOSYS); | |
| 129 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 84035 times.
|
84035 | 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 9936 times.
✓ Branch 1 taken 74099 times.
✓ Branch 2 taken 1016 times.
✓ Branch 3 taken 8920 times.
|
84035 | if (c->shift && ((c->shift + c->depth) & 0x7)) |
| 133 | 1016 | return AVERROR(ENOSYS); | |
| 134 | /* mixed >8 and <=8 depth */ | ||
| 135 | 83019 | db = (c->depth + 7) / 8; | |
| 136 |
3/4✓ Branch 0 taken 54767 times.
✓ Branch 1 taken 28252 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 54767 times.
|
83019 | if (depthb && (depthb != db)) |
| 137 | ✗ | return AVERROR(ENOSYS); | |
| 138 | 83019 | depthb = db; | |
| 139 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 83019 times.
|
83019 | if (db * (c->offset + 1) > 16) |
| 140 | ✗ | return AVERROR(ENOSYS); | |
| 141 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 83019 times.
|
83019 | if (c->offset % db) |
| 142 | ✗ | return AVERROR(ENOSYS); | |
| 143 | /* strange interleaving */ | ||
| 144 |
2/2✓ Branch 0 taken 16629 times.
✓ Branch 1 taken 66390 times.
|
83019 | if (pixelstep[c->plane] != 0 && |
| 145 |
2/2✓ Branch 0 taken 1778 times.
✓ Branch 1 taken 14851 times.
|
16629 | pixelstep[c->plane] != c->step) |
| 146 | 1778 | return AVERROR(ENOSYS); | |
| 147 | 81241 | pixelstep[c->plane] = c->step; | |
| 148 |
2/2✓ Branch 0 taken 1270 times.
✓ Branch 1 taken 79971 times.
|
81241 | if (pixelstep[c->plane] >= 8) |
| 149 | 1270 | return AVERROR(ENOSYS); | |
| 150 | 79971 | nb_planes = FFMAX(nb_planes, c->plane + 1); | |
| 151 | } | ||
| 152 | 24950 | memset(draw, 0, sizeof(*draw)); | |
| 153 | 24950 | draw->desc = desc; | |
| 154 | 24950 | draw->format = format; | |
| 155 | 24950 | draw->nb_planes = nb_planes; | |
| 156 | 24950 | draw->range = range; | |
| 157 | 24950 | draw->csp = csp; | |
| 158 | 24950 | draw->alpha = alpha; | |
| 159 | 24950 | draw->flags = flags; | |
| 160 |
2/2✓ Branch 0 taken 18545 times.
✓ Branch 1 taken 6405 times.
|
24950 | if (luma) |
| 161 | 18545 | ff_fill_rgb2yuv_table(luma, draw->rgb2yuv); | |
| 162 | 24950 | memcpy(draw->pixelstep, pixelstep, sizeof(draw->pixelstep)); | |
| 163 | 24950 | draw->hsub[1] = draw->hsub[2] = draw->hsub_max = desc->log2_chroma_w; | |
| 164 | 24950 | draw->vsub[1] = draw->vsub[2] = draw->vsub_max = desc->log2_chroma_h; | |
| 165 | 24950 | return 0; | |
| 166 | } | ||
| 167 | |||
| 168 | 311 | int ff_draw_init_from_link(FFDrawContext *draw, const AVFilterLink *link, | |
| 169 | unsigned flags) | ||
| 170 | { | ||
| 171 | 311 | return ff_draw_init2(draw, link->format, link->colorspace, link->color_range, link->alpha_mode, flags); | |
| 172 | } | ||
| 173 | |||
| 174 | 68581 | int ff_draw_init(FFDrawContext *draw, enum AVPixelFormat format, unsigned flags) | |
| 175 | { | ||
| 176 | 68581 | return ff_draw_init2(draw, format, AVCOL_SPC_UNSPECIFIED, AVCOL_RANGE_UNSPECIFIED, AVALPHA_MODE_UNSPECIFIED, flags); | |
| 177 | } | ||
| 178 | |||
| 179 | 235163 | void ff_draw_color(FFDrawContext *draw, FFDrawColor *color, const uint8_t rgba[4]) | |
| 180 | { | ||
| 181 | double yuvad[4]; | ||
| 182 | double rgbad[4]; | ||
| 183 | 235163 | const AVPixFmtDescriptor *desc = draw->desc; | |
| 184 | |||
| 185 |
1/2✓ Branch 0 taken 235163 times.
✗ Branch 1 not taken.
|
235163 | if (rgba != color->rgba) |
| 186 | 235163 | memcpy(color->rgba, rgba, sizeof(color->rgba)); | |
| 187 | |||
| 188 | 235163 | memset(color->comp, 0, sizeof(color->comp)); | |
| 189 | |||
| 190 |
2/2✓ Branch 0 taken 940652 times.
✓ Branch 1 taken 235163 times.
|
1175815 | for (int i = 0; i < 4; i++) |
| 191 | 940652 | rgbad[i] = color->rgba[i] / 255.; | |
| 192 | |||
| 193 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 235163 times.
|
235163 | 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 180531 times.
|
235163 | if (draw->desc->flags & AV_PIX_FMT_FLAG_RGB) |
| 199 | 54632 | memcpy(yuvad, rgbad, sizeof(double) * 3); | |
| 200 | else | ||
| 201 | 180531 | ff_matrix_mul_3x3_vec(yuvad, rgbad, draw->rgb2yuv); | |
| 202 | |||
| 203 | 235163 | yuvad[3] = rgbad[3]; | |
| 204 | |||
| 205 |
2/2✓ Branch 0 taken 705489 times.
✓ Branch 1 taken 235163 times.
|
940652 | for (int i = 0; i < 3; i++) { |
| 206 |
4/4✓ Branch 0 taken 541593 times.
✓ Branch 1 taken 163896 times.
✓ Branch 2 taken 361062 times.
✓ Branch 3 taken 180531 times.
|
705489 | int chroma = (!(draw->desc->flags & AV_PIX_FMT_FLAG_RGB) && i > 0); |
| 207 |
2/2✓ Branch 0 taken 541512 times.
✓ Branch 1 taken 163977 times.
|
705489 | if (draw->range == AVCOL_RANGE_MPEG) { |
| 208 |
2/2✓ Branch 0 taken 361008 times.
✓ Branch 1 taken 180504 times.
|
541512 | yuvad[i] *= (chroma ? 224. : 219.) / 255.; |
| 209 |
2/2✓ Branch 0 taken 361008 times.
✓ Branch 1 taken 180504 times.
|
541512 | 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 235144 times.
|
235163 | if (desc->nb_components <= 2) |
| 217 | 19 | yuvad[1] = yuvad[3]; | |
| 218 | |||
| 219 |
2/2✓ Branch 0 taken 731603 times.
✓ Branch 1 taken 235163 times.
|
966766 | for (unsigned i = 0; i < desc->nb_components; i++) { |
| 220 | 731603 | unsigned val = yuvad[i] * ((1 << (draw->desc->comp[i].depth + draw->desc->comp[i].shift)) - 1) + 0.5; | |
| 221 |
2/2✓ Branch 0 taken 59864 times.
✓ Branch 1 taken 671739 times.
|
731603 | if (desc->comp[i].depth > 8) |
| 222 | 59864 | color->comp[desc->comp[i].plane].u16[desc->comp[i].offset / 2] = val; | |
| 223 | else | ||
| 224 | 671739 | color->comp[desc->comp[i].plane].u8[desc->comp[i].offset] = val; | |
| 225 | } | ||
| 226 | 235163 | } | |
| 227 | |||
| 228 | 704908 | static uint8_t *pointer_at(FFDrawContext *draw, uint8_t *data[], int linesize[], | |
| 229 | int plane, int x, int y) | ||
| 230 | { | ||
| 231 | 704908 | return data[plane] + | |
| 232 | 1409816 | (y >> draw->vsub[plane]) * linesize[plane] + | |
| 233 | 704908 | (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 | 237503 | 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 | 237503 | FFDrawColor color_tmp = *color; | |
| 265 | |||
| 266 |
2/2✓ Branch 0 taken 603999 times.
✓ Branch 1 taken 237503 times.
|
841502 | for (int plane = 0; plane < draw->nb_planes; plane++) { |
| 267 | 603999 | p0 = pointer_at(draw, dst, dst_linesize, plane, dst_x, dst_y); | |
| 268 | 603999 | wp = AV_CEIL_RSHIFT(w, draw->hsub[plane]); | |
| 269 | 603999 | hp = AV_CEIL_RSHIFT(h, draw->vsub[plane]); | |
| 270 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 603999 times.
|
603999 | if (!hp) |
| 271 | ✗ | return; | |
| 272 | 603999 | 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 2682259 times.
✓ Branch 1 taken 603999 times.
|
3286258 | for (int x = 0; x < wp; x++) { |
| 281 | 2682259 | memcpy(p, color_tmp.comp[plane].u8, draw->pixelstep[plane]); | |
| 282 | 2682259 | p += draw->pixelstep[plane]; | |
| 283 | } | ||
| 284 | 603999 | wp *= draw->pixelstep[plane]; | |
| 285 | /* copy next lines from first line */ | ||
| 286 | 603999 | p = p0 + dst_linesize[plane]; | |
| 287 |
2/2✓ Branch 0 taken 10308335 times.
✓ Branch 1 taken 603999 times.
|
10912334 | for (int y = 1; y < hp; y++) { |
| 288 | 10308335 | memcpy(p, p0, wp); | |
| 289 | 10308335 | 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 | 74650 | static void clip_interval(int wmax, int *x, int *w, int *dx) | |
| 300 | { | ||
| 301 |
2/2✓ Branch 0 taken 72312 times.
✓ Branch 1 taken 2338 times.
|
74650 | if (dx) |
| 302 | 72312 | *dx = 0; | |
| 303 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 74650 times.
|
74650 | if (*x < 0) { |
| 304 | ✗ | if (dx) | |
| 305 | ✗ | *dx = -*x; | |
| 306 | ✗ | *w += *x; | |
| 307 | ✗ | *x = 0; | |
| 308 | } | ||
| 309 |
2/2✓ Branch 0 taken 663 times.
✓ Branch 1 taken 73987 times.
|
74650 | if (*x + *w > wmax) |
| 310 | 663 | *w = wmax - *x; | |
| 311 | 74650 | } | |
| 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 | 200738 | static void subsampling_bounds(int sub, int *x, int *w, int *start, int *end) | |
| 319 | { | ||
| 320 | 200738 | int mask = (1 << sub) - 1; | |
| 321 | |||
| 322 | 200738 | *start = (-*x) & mask; | |
| 323 | 200738 | *x += *start; | |
| 324 | 200738 | *start = FFMIN(*start, *w); | |
| 325 | 200738 | *w -= *start; | |
| 326 | 200738 | *end = *w & mask; | |
| 327 | 200738 | *w >>= sub; | |
| 328 | 200738 | } | |
| 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 | 84620 | static void blend_line(uint8_t *dst, unsigned src, unsigned alpha, | |
| 334 | int dx, int w, unsigned hsub, int left, int right) | ||
| 335 | { | ||
| 336 | 84620 | unsigned asrc = alpha * src; | |
| 337 | 84620 | unsigned tau = 0x1010101 - alpha; | |
| 338 | |||
| 339 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 84620 times.
|
84620 | 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 6867226 times.
✓ Branch 1 taken 84620 times.
|
6951846 | for (int x = 0; x < w; x++) { |
| 345 | 6867226 | *dst = (*dst * tau + asrc) >> 24; | |
| 346 | 6867226 | dst += dx; | |
| 347 | } | ||
| 348 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 84620 times.
|
84620 | if (right) { |
| 349 | ✗ | unsigned suba = (right * alpha) >> hsub; | |
| 350 | ✗ | *dst = (*dst * (0x1010101 - suba) + src * suba) >> 24; | |
| 351 | } | ||
| 352 | 84620 | } | |
| 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 | 37325 | static FFDrawColor blended_color(FFDrawContext *draw, const FFDrawColor *color) | |
| 380 | { | ||
| 381 | 37325 | const AVPixFmtDescriptor *desc = draw->desc; | |
| 382 | 37325 | const AVComponentDescriptor *alpha = &desc->comp[desc->nb_components - 1]; | |
| 383 | 37325 | FFDrawColor over = *color; | |
| 384 | |||
| 385 |
4/4✓ Branch 0 taken 2559 times.
✓ Branch 1 taken 34766 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 2557 times.
|
37325 | 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 | 37325 | return over; | |
| 392 | } | ||
| 393 | |||
| 394 | 1169 | 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 | 1169 | 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 | 2338 | nb_comp = draw->desc->nb_components - | |
| 405 |
4/4✓ Branch 0 taken 74 times.
✓ Branch 1 taken 1095 times.
✓ Branch 2 taken 73 times.
✓ Branch 3 taken 1 times.
|
1169 | !!(draw->desc->flags & AV_PIX_FMT_FLAG_ALPHA && !(draw->flags & FF_DRAW_PROCESS_ALPHA)); |
| 406 | |||
| 407 | /* TODO optimize if alpha = 0xFF */ | ||
| 408 | 1169 | clip_interval(dst_w, &x0, &w, NULL); | |
| 409 | 1169 | clip_interval(dst_h, &y0, &h, NULL); | |
| 410 |
3/6✓ Branch 0 taken 1169 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1169 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1169 times.
|
1169 | if (w <= 0 || h <= 0 || !color->rgba[3]) |
| 411 | ✗ | return; | |
| 412 |
2/2✓ Branch 0 taken 1059 times.
✓ Branch 1 taken 110 times.
|
1169 | if (draw->desc->comp[0].depth <= 8) { |
| 413 | /* 0x10203 * alpha + 2 is in the [ 2 ; 0x1010101 - 2 ] range */ | ||
| 414 | 1059 | 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 74 times.
✓ Branch 1 taken 1095 times.
✓ Branch 2 taken 73 times.
✓ Branch 3 taken 1 times.
|
1169 | nb_planes = draw->nb_planes - !!(draw->desc->flags & AV_PIX_FMT_FLAG_ALPHA && !(draw->flags & FF_DRAW_PROCESS_ALPHA)); |
| 420 | 1169 | nb_planes += !nb_planes; | |
| 421 |
2/2✓ Branch 0 taken 3193 times.
✓ Branch 1 taken 1169 times.
|
4362 | for (unsigned plane = 0; plane < nb_planes; plane++) { |
| 422 | 3193 | p0 = pointer_at(draw, dst, dst_linesize, plane, x0, y0); | |
| 423 | 3193 | w_sub = w; | |
| 424 | 3193 | h_sub = h; | |
| 425 | 3193 | x_sub = x0; | |
| 426 | 3193 | y_sub = y0; | |
| 427 | 3193 | subsampling_bounds(draw->hsub[plane], &x_sub, &w_sub, &left, &right); | |
| 428 | 3193 | subsampling_bounds(draw->vsub[plane], &y_sub, &h_sub, &top, &bottom); | |
| 429 |
2/2✓ Branch 0 taken 9580 times.
✓ Branch 1 taken 3193 times.
|
12773 | for (unsigned comp = 0; comp < nb_comp; comp++) { |
| 430 | 9580 | const int depth = draw->desc->comp[comp].depth; | |
| 431 | 9580 | const int offset = draw->desc->comp[comp].offset; | |
| 432 | 9580 | const int index = offset / ((depth + 7) / 8); | |
| 433 | |||
| 434 |
2/2✓ Branch 0 taken 6072 times.
✓ Branch 1 taken 3508 times.
|
9580 | if (draw->desc->comp[comp].plane != plane) |
| 435 | 6072 | continue; | |
| 436 | 3508 | p = p0 + offset; | |
| 437 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3508 times.
|
3508 | 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 3178 times.
✓ Branch 1 taken 330 times.
|
3508 | if (depth <= 8) { |
| 450 |
2/2✓ Branch 0 taken 84620 times.
✓ Branch 1 taken 3178 times.
|
87798 | for (int y = 0; y < h_sub; y++) { |
| 451 | 84620 | blend_line(p, over.comp[plane].u8[index], alpha, | |
| 452 | draw->pixelstep[plane], w_sub, | ||
| 453 | 84620 | draw->hsub[plane], left, right); | |
| 454 | 84620 | 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 3508 times.
|
3508 | 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 | 9391276 | 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 | 9391276 | unsigned t = 0; | |
| 508 | 9391276 | unsigned xmshf = 3 - l2depth; | |
| 509 | 9391276 | unsigned xmmod = 7 >> l2depth; | |
| 510 | 9391276 | unsigned mbits = (1 << (1 << l2depth)) - 1; | |
| 511 | 9391276 | unsigned mmult = 255 / mbits; | |
| 512 | |||
| 513 |
2/2✓ Branch 0 taken 11310308 times.
✓ Branch 1 taken 9391276 times.
|
20701584 | for (unsigned y = 0; y < h; y++) { |
| 514 | 11310308 | unsigned xm = xm0; | |
| 515 |
2/2✓ Branch 0 taken 15232852 times.
✓ Branch 1 taken 11310308 times.
|
26543160 | for (unsigned x = 0; x < w; x++) { |
| 516 | 15232852 | t += ((mask[xm >> xmshf] >> ((~xm & xmmod) << l2depth)) & mbits) | |
| 517 | 15232852 | * mmult; | |
| 518 | 15232852 | xm++; | |
| 519 | } | ||
| 520 | 11310308 | mask += mask_linesize; | |
| 521 | } | ||
| 522 | 9391276 | alpha = (t >> shift) * alpha; | |
| 523 | 9391276 | *dst = ((0x1010101 - alpha) * *dst + alpha * src) >> 24; | |
| 524 | 9391276 | } | |
| 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 | 1159252 | 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 1159252 times.
|
1159252 | 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 9391276 times.
✓ Branch 1 taken 1159252 times.
|
10550528 | for (int x = 0; x < w; x++) { |
| 564 | 9391276 | blend_pixel(dst, src, alpha, mask, mask_linesize, l2depth, | |
| 565 | 9391276 | 1 << hsub, hband, hsub + vsub, xm); | |
| 566 | 9391276 | dst += dst_delta; | |
| 567 | 9391276 | xm += 1 << hsub; | |
| 568 | } | ||
| 569 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1159252 times.
|
1159252 | if (right) |
| 570 | ✗ | blend_pixel(dst, src, alpha, mask, mask_linesize, l2depth, | |
| 571 | right, hband, hsub + vsub, xm); | ||
| 572 | 1159252 | } | |
| 573 | |||
| 574 | 36156 | 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 | 36156 | 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 | 72312 | nb_comp = draw->desc->nb_components - | |
| 586 |
4/4✓ Branch 0 taken 2485 times.
✓ Branch 1 taken 33671 times.
✓ Branch 2 taken 2484 times.
✓ Branch 3 taken 1 times.
|
36156 | !!(draw->desc->flags & AV_PIX_FMT_FLAG_ALPHA && !(draw->flags & FF_DRAW_PROCESS_ALPHA)); |
| 587 | |||
| 588 | 36156 | clip_interval(dst_w, &x0, &mask_w, &xm0); | |
| 589 | 36156 | clip_interval(dst_h, &y0, &mask_h, &ym0); | |
| 590 | 36156 | mask += ym0 * mask_linesize; | |
| 591 |
5/6✓ Branch 0 taken 35776 times.
✓ Branch 1 taken 380 times.
✓ Branch 2 taken 35762 times.
✓ Branch 3 taken 14 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 35762 times.
|
36156 | if (mask_w <= 0 || mask_h <= 0 || !color->rgba[3]) |
| 592 | 394 | return; | |
| 593 |
2/2✓ Branch 0 taken 32352 times.
✓ Branch 1 taken 3410 times.
|
35762 | 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 | 32352 | 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 2469 times.
✓ Branch 1 taken 33293 times.
✓ Branch 2 taken 2468 times.
✓ Branch 3 taken 1 times.
|
35762 | nb_planes = draw->nb_planes - !!(draw->desc->flags & AV_PIX_FMT_FLAG_ALPHA && !(draw->flags & FF_DRAW_PROCESS_ALPHA)); |
| 601 | 35762 | nb_planes += !nb_planes; | |
| 602 |
2/2✓ Branch 0 taken 97176 times.
✓ Branch 1 taken 35762 times.
|
132938 | for (unsigned plane = 0; plane < nb_planes; plane++) { |
| 603 | 97176 | uint8_t *p0 = pointer_at(draw, dst, dst_linesize, plane, x0, y0); | |
| 604 | 97176 | w_sub = mask_w; | |
| 605 | 97176 | h_sub = mask_h; | |
| 606 | 97176 | x_sub = x0; | |
| 607 | 97176 | y_sub = y0; | |
| 608 | 97176 | subsampling_bounds(draw->hsub[plane], &x_sub, &w_sub, &left, &right); | |
| 609 | 97176 | subsampling_bounds(draw->vsub[plane], &y_sub, &h_sub, &top, &bottom); | |
| 610 |
2/2✓ Branch 0 taken 291529 times.
✓ Branch 1 taken 97176 times.
|
388705 | for (unsigned comp = 0; comp < nb_comp; comp++) { |
| 611 | 291529 | const int depth = draw->desc->comp[comp].depth; | |
| 612 | 291529 | const int offset = draw->desc->comp[comp].offset; | |
| 613 | 291529 | const int index = offset / ((depth + 7) / 8); | |
| 614 | |||
| 615 |
2/2✓ Branch 0 taken 184242 times.
✓ Branch 1 taken 107287 times.
|
291529 | if (draw->desc->comp[comp].plane != plane) |
| 616 | 184242 | continue; | |
| 617 | 107287 | p = p0 + offset; | |
| 618 | 107287 | m = mask; | |
| 619 |
2/2✓ Branch 0 taken 352 times.
✓ Branch 1 taken 106935 times.
|
107287 | 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 97057 times.
✓ Branch 1 taken 10230 times.
|
107287 | if (depth <= 8) { |
| 637 |
2/2✓ Branch 0 taken 1158548 times.
✓ Branch 1 taken 97057 times.
|
1255605 | for (int y = 0; y < h_sub; y++) { |
| 638 | 1158548 | blend_line_hv(p, draw->pixelstep[plane], | |
| 639 | 1158548 | over.comp[plane].u8[index], alpha, | |
| 640 | m, mask_linesize, l2depth, w_sub, | ||
| 641 | 1158548 | draw->hsub[plane], draw->vsub[plane], | |
| 642 | 1158548 | xm0, left, right, 1 << draw->vsub[plane]); | |
| 643 | 1158548 | p += dst_linesize[plane]; | |
| 644 | 1158548 | 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 106935 times.
|
107287 | 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 | 260090 | int ff_draw_round_to_sub(FFDrawContext *draw, int sub_dir, int round_dir, | |
| 677 | int value) | ||
| 678 | { | ||
| 679 |
2/2✓ Branch 0 taken 231760 times.
✓ Branch 1 taken 28330 times.
|
260090 | unsigned shift = sub_dir ? draw->vsub_max : draw->hsub_max; |
| 680 | |||
| 681 |
2/2✓ Branch 0 taken 105742 times.
✓ Branch 1 taken 154348 times.
|
260090 | if (!shift) |
| 682 | 105742 | return value; | |
| 683 |
2/2✓ Branch 0 taken 127840 times.
✓ Branch 1 taken 26508 times.
|
154348 | if (round_dir >= 0) |
| 684 |
2/2✓ Branch 0 taken 4386 times.
✓ Branch 1 taken 123454 times.
|
127840 | value += round_dir ? (1 << shift) - 1 : 1 << (shift - 1); |
| 685 | 154348 | return (value >> shift) << shift; | |
| 686 | } | ||
| 687 | |||
| 688 | 253 | AVFilterFormats *ff_draw_supported_pixel_formats(unsigned flags) | |
| 689 | { | ||
| 690 | FFDrawContext draw; | ||
| 691 | 253 | AVFilterFormats *fmts = NULL; | |
| 692 | int ret; | ||
| 693 | |||
| 694 |
2/2✓ Branch 1 taken 68310 times.
✓ Branch 2 taken 253 times.
|
68563 | for (enum AVPixelFormat i = 0; av_pix_fmt_desc_get(i); i++) |
| 695 |
3/4✓ Branch 1 taken 24541 times.
✓ Branch 2 taken 43769 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 24541 times.
|
92851 | if (ff_draw_init(&draw, i, flags) >= 0 && |
| 696 | 24541 | (ret = ff_add_format(&fmts, i)) < 0) | |
| 697 | ✗ | return NULL; | |
| 698 | 253 | return fmts; | |
| 699 | } | ||
| 700 |