History

lavfi/drawutils: overhaul to improve pixel format support

- No longer mixes u8 and u16 component accesses (this was UB) - De-duplicated 8->16 conversion - De-duplicated component -> plane+offset conversion - De-duplicated planar + packed RGB - No longer calls ff_fill_rgba_map - Removed redundant comp_mask data member - RGB0 and related formats no longer write an alpha value to the 0 byte - Non-planar YA formats now work correctly - High-bit-depth semi-planar YUV now works correctly

rcombs committed 4 years ago

Commit 66343e41 parent f67bd3a3 files · +58 −73Browse files

Showing the changes to libavfilter (2 of 3 files). Show all

Unified · Split

2 files
  1. libavfilter/drawutils.c +48 −62
  2. libavfilter/drawutils.h +0 −1
libavfilter/drawutils.c+48−62
@@ -137,66 +137,49 @@ int ff_draw_init(FFDrawContext *draw, enum AVPixelFormat format, unsigned flags) · 136 unmodified lines
137 memcpy(draw->pixelstep, pixelstep, sizeof(draw->pixelstep));137 memcpy(draw->pixelstep, pixelstep, sizeof(draw->pixelstep));
138 draw->hsub[1] = draw->hsub[2] = draw->hsub_max = desc->log2_chroma_w;138 draw->hsub[1] = draw->hsub[2] = draw->hsub_max = desc->log2_chroma_w;
139 draw->vsub[1] = draw->vsub[2] = draw->vsub_max = desc->log2_chroma_h;139 draw->vsub[1] = draw->vsub[2] = draw->vsub_max = desc->log2_chroma_h;
140 for (i = 0; i < (desc->nb_components - !!(desc->flags & AV_PIX_FMT_FLAG_ALPHA && !(flags & FF_DRAW_PROCESS_ALPHA))); i++)
141 draw->comp_mask[desc->comp[i].plane] |=
142 1 << desc->comp[i].offset;
143 return 0;140 return 0;
144}141}
145 142
146void ff_draw_color(FFDrawContext *draw, FFDrawColor *color, const uint8_t rgba[4])143void ff_draw_color(FFDrawContext *draw, FFDrawColor *color, const uint8_t rgba[4])
147{144{
148 unsigned i;145 unsigned i;
149 uint8_t rgba_map[4];146 uint8_t tmp8[4];
147 const AVPixFmtDescriptor *desc = draw->desc;
150 148
151 if (rgba != color->rgba)149 if (rgba != color->rgba)
152 memcpy(color->rgba, rgba, sizeof(color->rgba));150 memcpy(color->rgba, rgba, sizeof(color->rgba));
153 if ((draw->desc->flags & AV_PIX_FMT_FLAG_RGB) &&151
154 ff_fill_rgba_map(rgba_map, draw->format) >= 0) {152 memset(color->comp, 0, sizeof(color->comp));
155 if (draw->nb_planes == 1) {153
156 for (i = 0; i < 4; i++) {154 if (draw->desc->flags & AV_PIX_FMT_FLAG_RGB) {
157 color->comp[0].u8[rgba_map[i]] = rgba[i];155 memcpy(tmp8, rgba, sizeof(tmp8));
158 if (draw->desc->comp[rgba_map[i]].depth > 8) {
159 color->comp[0].u16[rgba_map[i]] = color->comp[0].u8[rgba_map[i]] << 8;
160 }
161 }
162 } else {
163 for (i = 0; i < 4; i++) {
164 color->comp[rgba_map[i]].u8[0] = rgba[i];
165 if (draw->desc->comp[rgba_map[i]].depth > 8)
166 color->comp[rgba_map[i]].u16[0] = color->comp[rgba_map[i]].u8[0] << (draw->desc->comp[rgba_map[i]].depth - 8);
167 }
168 }
169 } else if (draw->nb_planes >= 2) {156 } else if (draw->nb_planes >= 2) {
170 /* assume YUV */157 /* assume YUV */
171 const AVPixFmtDescriptor *desc = draw->desc;158 tmp8[0] = draw->full_range ? RGB_TO_Y_JPEG(rgba[0], rgba[1], rgba[2]) : RGB_TO_Y_CCIR(rgba[0], rgba[1], rgba[2]);
172 color->comp[desc->comp[0].plane].u8[desc->comp[0].offset] = draw->full_range ? RGB_TO_Y_JPEG(rgba[0], rgba[1], rgba[2]) : RGB_TO_Y_CCIR(rgba[0], rgba[1], rgba[2]);159 tmp8[1] = draw->full_range ? RGB_TO_U_JPEG(rgba[0], rgba[1], rgba[2]) : RGB_TO_U_CCIR(rgba[0], rgba[1], rgba[2], 0);
173 color->comp[desc->comp[1].plane].u8[desc->comp[1].offset] = draw->full_range ? RGB_TO_U_JPEG(rgba[0], rgba[1], rgba[2]) : RGB_TO_U_CCIR(rgba[0], rgba[1], rgba[2], 0);160 tmp8[2] = draw->full_range ? RGB_TO_V_JPEG(rgba[0], rgba[1], rgba[2]) : RGB_TO_V_CCIR(rgba[0], rgba[1], rgba[2], 0);
174 color->comp[desc->comp[2].plane].u8[desc->comp[2].offset] = draw->full_range ? RGB_TO_V_JPEG(rgba[0], rgba[1], rgba[2]) : RGB_TO_V_CCIR(rgba[0], rgba[1], rgba[2], 0);161 tmp8[3] = rgba[3];
175 color->comp[3].u8[0] = rgba[3];
176#define EXPAND(compn) \
177 if (desc->comp[compn].depth > 8) \
178 color->comp[desc->comp[compn].plane].u16[desc->comp[compn].offset] = \
179 color->comp[desc->comp[compn].plane].u8[desc->comp[compn].offset] << \
180 (draw->desc->comp[compn].depth + draw->desc->comp[compn].shift - 8)
181 EXPAND(3);
182 EXPAND(2);
183 EXPAND(1);
184 EXPAND(0);
185 } else if (draw->format == AV_PIX_FMT_GRAY8 || draw->format == AV_PIX_FMT_GRAY8A ||162 } else if (draw->format == AV_PIX_FMT_GRAY8 || draw->format == AV_PIX_FMT_GRAY8A ||
186 draw->format == AV_PIX_FMT_GRAY16LE || draw->format == AV_PIX_FMT_YA16LE ||163 draw->format == AV_PIX_FMT_GRAY16LE || draw->format == AV_PIX_FMT_YA16LE ||
187 draw->format == AV_PIX_FMT_GRAY9LE ||164 draw->format == AV_PIX_FMT_GRAY9LE ||
188 draw->format == AV_PIX_FMT_GRAY10LE ||165 draw->format == AV_PIX_FMT_GRAY10LE ||
189 draw->format == AV_PIX_FMT_GRAY12LE ||166 draw->format == AV_PIX_FMT_GRAY12LE ||
190 draw->format == AV_PIX_FMT_GRAY14LE) {167 draw->format == AV_PIX_FMT_GRAY14LE) {
191 const AVPixFmtDescriptor *desc = draw->desc;168 tmp8[0] = RGB_TO_Y_CCIR(rgba[0], rgba[1], rgba[2]);
192 color->comp[0].u8[0] = RGB_TO_Y_CCIR(rgba[0], rgba[1], rgba[2]);169 tmp8[1] = rgba[3];
193 EXPAND(0);
194 color->comp[1].u8[0] = rgba[3];
195 EXPAND(1);
196 } else {170 } else {
197 av_log(NULL, AV_LOG_WARNING,171 av_log(NULL, AV_LOG_WARNING,
198 "Color conversion not implemented for %s\n", draw->desc->name);172 "Color conversion not implemented for %s\n", draw->desc->name);
199 memset(color, 128, sizeof(*color));173 memset(color, 128, sizeof(*color));
174 return;
175 }
176
177 for (i = 0; i < desc->nb_components; i++) {
178 if (desc->comp[i].depth > 8)
179 color->comp[desc->comp[i].plane].u16[desc->comp[i].offset / 2] = tmp8[i] <<
180 (draw->desc->comp[i].depth + draw->desc->comp[i].shift - 8);
181 else
182 color->comp[desc->comp[i].plane].u8[desc->comp[i].offset] = tmp8[i];
200 }183 }
201}184}
202 185
@@ -302,11 +285,6 @@ static void subsampling_bounds(int sub, int *x, int *w, int *start, int *end) · 99 unmodified lines
302 *w >>= sub;285 *w >>= sub;
303}286}
304 287
305static int component_used(FFDrawContext *draw, int plane, int comp)
306{
307 return (draw->comp_mask[plane] >> comp) & 1;
308}
309
310/* If alpha is in the [ 0 ; 0x1010101 ] range,288/* If alpha is in the [ 0 ; 0x1010101 ] range,
311 then alpha * value is in the [ 0 ; 0xFFFFFFFF ] range,289 then alpha * value is in the [ 0 ; 0xFFFFFFFF ] range,
312 and >> 24 gives a correct rounding. */290 and >> 24 gives a correct rounding. */
@@ -366,6 +344,9 @@ void ff_blend_rectangle(FFDrawContext *draw, FFDrawColor *color, · 53 unmodified lines
366 int w_sub, h_sub, x_sub, y_sub, left, right, top, bottom, y;344 int w_sub, h_sub, x_sub, y_sub, left, right, top, bottom, y;
367 uint8_t *p0, *p;345 uint8_t *p0, *p;
368 346
347 nb_comp = draw->desc->nb_components -
348 !!(draw->desc->flags & AV_PIX_FMT_FLAG_ALPHA && !(draw->flags & FF_DRAW_PROCESS_ALPHA));
349
369 /* TODO optimize if alpha = 0xFF */350 /* TODO optimize if alpha = 0xFF */
370 clip_interval(dst_w, &x0, &w, NULL);351 clip_interval(dst_w, &x0, &w, NULL);
371 clip_interval(dst_h, &y0, &h, NULL);352 clip_interval(dst_h, &y0, &h, NULL);
@@ -381,7 +362,6 @@ void ff_blend_rectangle(FFDrawContext *draw, FFDrawColor *color, · 9 unmodified lines
381 nb_planes = draw->nb_planes - !!(draw->desc->flags & AV_PIX_FMT_FLAG_ALPHA && !(draw->flags & FF_DRAW_PROCESS_ALPHA));362 nb_planes = draw->nb_planes - !!(draw->desc->flags & AV_PIX_FMT_FLAG_ALPHA && !(draw->flags & FF_DRAW_PROCESS_ALPHA));
382 nb_planes += !nb_planes;363 nb_planes += !nb_planes;
383 for (plane = 0; plane < nb_planes; plane++) {364 for (plane = 0; plane < nb_planes; plane++) {
384 nb_comp = draw->pixelstep[plane];
385 p0 = pointer_at(draw, dst, dst_linesize, plane, x0, y0);365 p0 = pointer_at(draw, dst, dst_linesize, plane, x0, y0);
386 w_sub = w;366 w_sub = w;
387 h_sub = h;367 h_sub = h;
@@ -391,17 +371,19 @@ void ff_blend_rectangle(FFDrawContext *draw, FFDrawColor *color, · 3 unmodified lines
391 subsampling_bounds(draw->vsub[plane], &y_sub, &h_sub, &top, &bottom);371 subsampling_bounds(draw->vsub[plane], &y_sub, &h_sub, &top, &bottom);
392 for (comp = 0; comp < nb_comp; comp++) {372 for (comp = 0; comp < nb_comp; comp++) {
393 const int depth = draw->desc->comp[comp].depth;373 const int depth = draw->desc->comp[comp].depth;
374 const int offset = draw->desc->comp[comp].offset;
375 const int index = offset / ((depth + 7) / 8);
394 376
395 if (!component_used(draw, plane, comp))377 if (draw->desc->comp[comp].plane != plane)
396 continue;378 continue;
397 p = p0 + comp;379 p = p0 + offset;
398 if (top) {380 if (top) {
399 if (depth <= 8) {381 if (depth <= 8) {
400 blend_line(p, color->comp[plane].u8[comp], alpha >> 1,382 blend_line(p, color->comp[plane].u8[index], alpha >> 1,
401 draw->pixelstep[plane], w_sub,383 draw->pixelstep[plane], w_sub,
402 draw->hsub[plane], left, right);384 draw->hsub[plane], left, right);
403 } else {385 } else {
404 blend_line16(p, color->comp[plane].u16[comp], alpha >> 1,386 blend_line16(p, color->comp[plane].u16[index], alpha >> 1,
405 draw->pixelstep[plane], w_sub,387 draw->pixelstep[plane], w_sub,
406 draw->hsub[plane], left, right);388 draw->hsub[plane], left, right);
407 }389 }
@@ -409,14 +391,14 @@ void ff_blend_rectangle(FFDrawContext *draw, FFDrawColor *color, · 1 unmodified line
409 }391 }
410 if (depth <= 8) {392 if (depth <= 8) {
411 for (y = 0; y < h_sub; y++) {393 for (y = 0; y < h_sub; y++) {
412 blend_line(p, color->comp[plane].u8[comp], alpha,394 blend_line(p, color->comp[plane].u8[index], alpha,
413 draw->pixelstep[plane], w_sub,395 draw->pixelstep[plane], w_sub,
414 draw->hsub[plane], left, right);396 draw->hsub[plane], left, right);
415 p += dst_linesize[plane];397 p += dst_linesize[plane];
416 }398 }
417 } else {399 } else {
418 for (y = 0; y < h_sub; y++) {400 for (y = 0; y < h_sub; y++) {
419 blend_line16(p, color->comp[plane].u16[comp], alpha,401 blend_line16(p, color->comp[plane].u16[index], alpha,
420 draw->pixelstep[plane], w_sub,402 draw->pixelstep[plane], w_sub,
421 draw->hsub[plane], left, right);403 draw->hsub[plane], left, right);
422 p += dst_linesize[plane];404 p += dst_linesize[plane];
@@ -424,11 +406,11 @@ void ff_blend_rectangle(FFDrawContext *draw, FFDrawColor *color, · 1 unmodified line
424 }406 }
425 if (bottom) {407 if (bottom) {
426 if (depth <= 8) {408 if (depth <= 8) {
427 blend_line(p, color->comp[plane].u8[comp], alpha >> 1,409 blend_line(p, color->comp[plane].u8[index], alpha >> 1,
428 draw->pixelstep[plane], w_sub,410 draw->pixelstep[plane], w_sub,
429 draw->hsub[plane], left, right);411 draw->hsub[plane], left, right);
430 } else {412 } else {
431 blend_line16(p, color->comp[plane].u16[comp], alpha >> 1,413 blend_line16(p, color->comp[plane].u16[index], alpha >> 1,
432 draw->pixelstep[plane], w_sub,414 draw->pixelstep[plane], w_sub,
433 draw->hsub[plane], left, right);415 draw->hsub[plane], left, right);
434 }416 }
@@ -544,6 +526,9 @@ void ff_blend_mask(FFDrawContext *draw, FFDrawColor *color, · 109 unmodified lines
544 uint8_t *p0, *p;526 uint8_t *p0, *p;
545 const uint8_t *m;527 const uint8_t *m;
546 528
529 nb_comp = draw->desc->nb_components -
530 !!(draw->desc->flags & AV_PIX_FMT_FLAG_ALPHA && !(draw->flags & FF_DRAW_PROCESS_ALPHA));
531
547 clip_interval(dst_w, &x0, &mask_w, &xm0);532 clip_interval(dst_w, &x0, &mask_w, &xm0);
548 clip_interval(dst_h, &y0, &mask_h, &ym0);533 clip_interval(dst_h, &y0, &mask_h, &ym0);
549 mask += ym0 * mask_linesize;534 mask += ym0 * mask_linesize;
@@ -559,7 +544,6 @@ void ff_blend_mask(FFDrawContext *draw, FFDrawColor *color, · 9 unmodified lines
559 nb_planes = draw->nb_planes - !!(draw->desc->flags & AV_PIX_FMT_FLAG_ALPHA && !(draw->flags & FF_DRAW_PROCESS_ALPHA));544 nb_planes = draw->nb_planes - !!(draw->desc->flags & AV_PIX_FMT_FLAG_ALPHA && !(draw->flags & FF_DRAW_PROCESS_ALPHA));
560 nb_planes += !nb_planes;545 nb_planes += !nb_planes;
561 for (plane = 0; plane < nb_planes; plane++) {546 for (plane = 0; plane < nb_planes; plane++) {
562 nb_comp = draw->pixelstep[plane];
563 p0 = pointer_at(draw, dst, dst_linesize, plane, x0, y0);547 p0 = pointer_at(draw, dst, dst_linesize, plane, x0, y0);
564 w_sub = mask_w;548 w_sub = mask_w;
565 h_sub = mask_h;549 h_sub = mask_h;
@@ -569,21 +553,23 @@ void ff_blend_mask(FFDrawContext *draw, FFDrawColor *color, · 3 unmodified lines
569 subsampling_bounds(draw->vsub[plane], &y_sub, &h_sub, &top, &bottom);553 subsampling_bounds(draw->vsub[plane], &y_sub, &h_sub, &top, &bottom);
570 for (comp = 0; comp < nb_comp; comp++) {554 for (comp = 0; comp < nb_comp; comp++) {
571 const int depth = draw->desc->comp[comp].depth;555 const int depth = draw->desc->comp[comp].depth;
556 const int offset = draw->desc->comp[comp].offset;
557 const int index = offset / ((depth + 7) / 8);
572 558
573 if (!component_used(draw, plane, comp))559 if (draw->desc->comp[comp].plane != plane)
574 continue;560 continue;
575 p = p0 + comp;561 p = p0 + offset;
576 m = mask;562 m = mask;
577 if (top) {563 if (top) {
578 if (depth <= 8) {564 if (depth <= 8) {
579 blend_line_hv(p, draw->pixelstep[plane],565 blend_line_hv(p, draw->pixelstep[plane],
580 color->comp[plane].u8[comp], alpha,566 color->comp[plane].u8[index], alpha,
581 m, mask_linesize, l2depth, w_sub,567 m, mask_linesize, l2depth, w_sub,
582 draw->hsub[plane], draw->vsub[plane],568 draw->hsub[plane], draw->vsub[plane],
583 xm0, left, right, top);569 xm0, left, right, top);
584 } else {570 } else {
585 blend_line_hv16(p, draw->pixelstep[plane],571 blend_line_hv16(p, draw->pixelstep[plane],
586 color->comp[plane].u16[comp], alpha,572 color->comp[plane].u16[index], alpha,
587 m, mask_linesize, l2depth, w_sub,573 m, mask_linesize, l2depth, w_sub,
588 draw->hsub[plane], draw->vsub[plane],574 draw->hsub[plane], draw->vsub[plane],
589 xm0, left, right, top);575 xm0, left, right, top);
@@ -594,7 +580,7 @@ void ff_blend_mask(FFDrawContext *draw, FFDrawColor *color, · 4 unmodified lines
594 if (depth <= 8) {580 if (depth <= 8) {
595 for (y = 0; y < h_sub; y++) {581 for (y = 0; y < h_sub; y++) {
596 blend_line_hv(p, draw->pixelstep[plane],582 blend_line_hv(p, draw->pixelstep[plane],
597 color->comp[plane].u8[comp], alpha,583 color->comp[plane].u8[index], alpha,
598 m, mask_linesize, l2depth, w_sub,584 m, mask_linesize, l2depth, w_sub,
599 draw->hsub[plane], draw->vsub[plane],585 draw->hsub[plane], draw->vsub[plane],
600 xm0, left, right, 1 << draw->vsub[plane]);586 xm0, left, right, 1 << draw->vsub[plane]);
@@ -604,7 +590,7 @@ void ff_blend_mask(FFDrawContext *draw, FFDrawColor *color, · 3 unmodified lines
604 } else {590 } else {
605 for (y = 0; y < h_sub; y++) {591 for (y = 0; y < h_sub; y++) {
606 blend_line_hv16(p, draw->pixelstep[plane],592 blend_line_hv16(p, draw->pixelstep[plane],
607 color->comp[plane].u16[comp], alpha,593 color->comp[plane].u16[index], alpha,
608 m, mask_linesize, l2depth, w_sub,594 m, mask_linesize, l2depth, w_sub,
609 draw->hsub[plane], draw->vsub[plane],595 draw->hsub[plane], draw->vsub[plane],
610 xm0, left, right, 1 << draw->vsub[plane]);596 xm0, left, right, 1 << draw->vsub[plane]);
@@ -615,13 +601,13 @@ void ff_blend_mask(FFDrawContext *draw, FFDrawColor *color, · 4 unmodified lines
615 if (bottom) {601 if (bottom) {
616 if (depth <= 8) {602 if (depth <= 8) {
617 blend_line_hv(p, draw->pixelstep[plane],603 blend_line_hv(p, draw->pixelstep[plane],
618 color->comp[plane].u8[comp], alpha,604 color->comp[plane].u8[index], alpha,
619 m, mask_linesize, l2depth, w_sub,605 m, mask_linesize, l2depth, w_sub,
620 draw->hsub[plane], draw->vsub[plane],606 draw->hsub[plane], draw->vsub[plane],
621 xm0, left, right, bottom);607 xm0, left, right, bottom);
622 } else {608 } else {
623 blend_line_hv16(p, draw->pixelstep[plane],609 blend_line_hv16(p, draw->pixelstep[plane],
624 color->comp[plane].u16[comp], alpha,610 color->comp[plane].u16[index], alpha,
625 m, mask_linesize, l2depth, w_sub,611 m, mask_linesize, l2depth, w_sub,
626 draw->hsub[plane], draw->vsub[plane],612 draw->hsub[plane], draw->vsub[plane],
627 xm0, left, right, bottom);613 xm0, left, right, bottom);
libavfilter/drawutils.h+0−1
@@ -37,7 +37,6 @@ typedef struct FFDrawContext { · 36 unmodified lines
37 enum AVPixelFormat format;37 enum AVPixelFormat format;
38 unsigned nb_planes;38 unsigned nb_planes;
39 int pixelstep[MAX_PLANES]; /*< offset between pixels */39 int pixelstep[MAX_PLANES]; /*< offset between pixels */
40 uint8_t comp_mask[MAX_PLANES]; /*< bitmask of used non-alpha components */
41 uint8_t hsub[MAX_PLANES]; /*< horizontal subsampling */40 uint8_t hsub[MAX_PLANES]; /*< horizontal subsampling */
42 uint8_t vsub[MAX_PLANES]; /*< vertical subsampling */41 uint8_t vsub[MAX_PLANES]; /*< vertical subsampling */
43 uint8_t hsub_max;42 uint8_t hsub_max;

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t