History

avfilter/drawutils: >8 bit support

Paul B Mahol committed 10 years ago

Commit 38ed5281 parent 6b706ce3 files · +239 −43Browse files

Showing the changes to libavfilter/drawutils.c (1 of 3 files). Show all

Unified · Split

libavfilter/drawutils.c+204−40
@@ -24,6 +24,7 @@ · 23 unmodified lines
24#include "libavutil/avassert.h"24#include "libavutil/avassert.h"
25#include "libavutil/avutil.h"25#include "libavutil/avutil.h"
26#include "libavutil/colorspace.h"26#include "libavutil/colorspace.h"
27#include "libavutil/intreadwrite.h"
27#include "libavutil/mem.h"28#include "libavutil/mem.h"
28#include "libavutil/pixdesc.h"29#include "libavutil/pixdesc.h"
29#include "drawutils.h"30#include "drawutils.h"
@@ -175,8 +176,10 @@ int ff_draw_init(FFDrawContext *draw, enum AVPixelFormat format, unsigned flags) · 145 unmodified lines
175 return AVERROR(ENOSYS);176 return AVERROR(ENOSYS);
176 for (i = 0; i < desc->nb_components; i++) {177 for (i = 0; i < desc->nb_components; i++) {
177 c = &desc->comp[i];178 c = &desc->comp[i];
178 /* for now, only 8-bits formats */179 /* for now, only 8-16 bits formats */
179 if (c->depth != 8)180 if (c->depth < 8 || c->depth > 16)
181 return AVERROR(ENOSYS);
182 if (desc->flags & AV_PIX_FMT_FLAG_BE)
180 return AVERROR(ENOSYS);183 return AVERROR(ENOSYS);
181 if (c->plane >= MAX_PLANES)184 if (c->plane >= MAX_PLANES)
182 return AVERROR(ENOSYS);185 return AVERROR(ENOSYS);
@@ -184,6 +187,9 @@ int ff_draw_init(FFDrawContext *draw, enum AVPixelFormat format, unsigned flags) · 1 unmodified line
184 if (pixelstep[c->plane] != 0 &&187 if (pixelstep[c->plane] != 0 &&
185 pixelstep[c->plane] != c->step)188 pixelstep[c->plane] != c->step)
186 return AVERROR(ENOSYS);189 return AVERROR(ENOSYS);
190 if (pixelstep[c->plane] == 6 &&
191 c->depth == 16)
192 return AVERROR(ENOSYS);
187 pixelstep[c->plane] = c->step;193 pixelstep[c->plane] = c->step;
188 if (pixelstep[c->plane] >= 8)194 if (pixelstep[c->plane] >= 8)
189 return AVERROR(ENOSYS);195 return AVERROR(ENOSYS);
@@ -214,11 +220,18 @@ void ff_draw_color(FFDrawContext *draw, FFDrawColor *color, const uint8_t rgba[4 · 24 unmodified lines
214 if ((draw->desc->flags & AV_PIX_FMT_FLAG_RGB) &&220 if ((draw->desc->flags & AV_PIX_FMT_FLAG_RGB) &&
215 ff_fill_rgba_map(rgba_map, draw->format) >= 0) {221 ff_fill_rgba_map(rgba_map, draw->format) >= 0) {
216 if (draw->nb_planes == 1) {222 if (draw->nb_planes == 1) {
217 for (i = 0; i < 4; i++)223 for (i = 0; i < 4; i++) {
218 color->comp[0].u8[rgba_map[i]] = rgba[i];224 color->comp[0].u8[rgba_map[i]] = rgba[i];
225 if (draw->desc->comp[rgba_map[i]].depth > 8) {
226 color->comp[0].u16[rgba_map[i]] = color->comp[0].u8[rgba_map[i]] << 8;
227 }
228 }
219 } else {229 } else {
220 for (i = 0; i < 4; i++)230 for (i = 0; i < 4; i++) {
221 color->comp[rgba_map[i]].u8[0] = rgba[i];231 color->comp[rgba_map[i]].u8[0] = rgba[i];
232 if (draw->desc->comp[rgba_map[i]].depth > 8)
233 color->comp[rgba_map[i]].u16[0] = color->comp[rgba_map[i]].u8[0] << (draw->desc->comp[rgba_map[i]].depth - 8);
234 }
222 }235 }
223 } else if (draw->nb_planes == 3 || draw->nb_planes == 4) {236 } else if (draw->nb_planes == 3 || draw->nb_planes == 4) {
224 /* assume YUV */237 /* assume YUV */
@@ -226,9 +239,22 @@ void ff_draw_color(FFDrawContext *draw, FFDrawColor *color, const uint8_t rgba[4 · 1 unmodified line
226 color->comp[1].u8[0] = RGB_TO_U_CCIR(rgba[0], rgba[1], rgba[2], 0);239 color->comp[1].u8[0] = RGB_TO_U_CCIR(rgba[0], rgba[1], rgba[2], 0);
227 color->comp[2].u8[0] = RGB_TO_V_CCIR(rgba[0], rgba[1], rgba[2], 0);240 color->comp[2].u8[0] = RGB_TO_V_CCIR(rgba[0], rgba[1], rgba[2], 0);
228 color->comp[3].u8[0] = rgba[3];241 color->comp[3].u8[0] = rgba[3];
242 if (draw->desc->comp[0].depth > 8)
243 color->comp[0].u16[0] = color->comp[0].u8[0] << (draw->desc->comp[0].depth - 8);
244 if (draw->desc->comp[1].depth > 8)
245 color->comp[1].u16[0] = color->comp[1].u8[0] << (draw->desc->comp[1].depth - 8);
246 if (draw->desc->comp[2].depth > 8)
247 color->comp[2].u16[0] = color->comp[2].u8[0] << (draw->desc->comp[2].depth - 8);
248 if (draw->desc->comp[3].depth > 8)
249 color->comp[3].u16[0] = color->comp[3].u8[0] << (draw->desc->comp[3].depth - 8);
229 } else if (draw->format == AV_PIX_FMT_GRAY8 || draw->format == AV_PIX_FMT_GRAY8A) {250 } else if (draw->format == AV_PIX_FMT_GRAY8 || draw->format == AV_PIX_FMT_GRAY8A) {
230 color->comp[0].u8[0] = RGB_TO_Y_CCIR(rgba[0], rgba[1], rgba[2]);251 color->comp[0].u8[0] = RGB_TO_Y_CCIR(rgba[0], rgba[1], rgba[2]);
231 color->comp[1].u8[0] = rgba[3];252 color->comp[1].u8[0] = rgba[3];
253 } else if (draw->format == AV_PIX_FMT_GRAY16 || draw->format == AV_PIX_FMT_YA16) {
254 color->comp[0].u8[0] = RGB_TO_Y_CCIR(rgba[0], rgba[1], rgba[2]);
255 color->comp[0].u16[0] = color->comp[0].u8[0] << 8;
256 color->comp[1].u8[0] = rgba[3];
257 color->comp[1].u16[0] = color->comp[1].u8[0] << 8;
232 } else {258 } else {
233 av_log(NULL, AV_LOG_WARNING,259 av_log(NULL, AV_LOG_WARNING,
234 "Color conversion not implemented for %s\n", draw->desc->name);260 "Color conversion not implemented for %s\n", draw->desc->name);
@@ -361,6 +387,31 @@ static void blend_line(uint8_t *dst, unsigned src, unsigned alpha, · 126 unmodified lines
361 }387 }
362}388}
363 389
390static void blend_line16(uint8_t *dst, unsigned src, unsigned alpha,
391 int dx, int w, unsigned hsub, int left, int right)
392{
393 unsigned asrc = alpha * src;
394 unsigned tau = 0x10001 - alpha;
395 int x;
396
397 if (left) {
398 unsigned suba = (left * alpha) >> hsub;
399 uint16_t value = AV_RL16(dst);
400 AV_WL16(dst, (value * (0x10001 - suba) + src * suba) >> 16);
401 dst += dx;
402 }
403 for (x = 0; x < w; x++) {
404 uint16_t value = AV_RL16(dst);
405 AV_WL16(dst, (value * tau + asrc) >> 16);
406 dst += dx;
407 }
408 if (right) {
409 unsigned suba = (right * alpha) >> hsub;
410 uint16_t value = AV_RL16(dst);
411 AV_WL16(dst, (value * (0x10001 - suba) + src * suba) >> 16);
412 }
413}
414
364void ff_blend_rectangle(FFDrawContext *draw, FFDrawColor *color,415void ff_blend_rectangle(FFDrawContext *draw, FFDrawColor *color,
365 uint8_t *dst[], int dst_linesize[],416 uint8_t *dst[], int dst_linesize[],
366 int dst_w, int dst_h,417 int dst_w, int dst_h,
@@ -375,8 +426,13 @@ void ff_blend_rectangle(FFDrawContext *draw, FFDrawColor *color, · 8 unmodified lines
375 clip_interval(dst_h, &y0, &h, NULL);426 clip_interval(dst_h, &y0, &h, NULL);
376 if (w <= 0 || h <= 0 || !color->rgba[3])427 if (w <= 0 || h <= 0 || !color->rgba[3])
377 return;428 return;
378 /* 0x10203 * alpha + 2 is in the [ 2 ; 0x1010101 - 2 ] range */429 if (draw->desc->comp[0].depth <= 8) {
379 alpha = 0x10203 * color->rgba[3] + 0x2;430 /* 0x10203 * alpha + 2 is in the [ 2 ; 0x1010101 - 2 ] range */
431 alpha = 0x10203 * color->rgba[3] + 0x2;
432 } else {
433 /* 0x101 * alpha is in the [ 2 ; 0x1001] range */
434 alpha = 0x101 * color->rgba[3] + 0x2;
435 }
380 nb_planes = (draw->nb_planes - 1) | 1; /* eliminate alpha */436 nb_planes = (draw->nb_planes - 1) | 1; /* eliminate alpha */
381 for (plane = 0; plane < nb_planes; plane++) {437 for (plane = 0; plane < nb_planes; plane++) {
382 nb_comp = draw->pixelstep[plane];438 nb_comp = draw->pixelstep[plane];
@@ -388,29 +444,77 @@ void ff_blend_rectangle(FFDrawContext *draw, FFDrawColor *color, · 5 unmodified lines
388 subsampling_bounds(draw->hsub[plane], &x_sub, &w_sub, &left, &right);444 subsampling_bounds(draw->hsub[plane], &x_sub, &w_sub, &left, &right);
389 subsampling_bounds(draw->vsub[plane], &y_sub, &h_sub, &top, &bottom);445 subsampling_bounds(draw->vsub[plane], &y_sub, &h_sub, &top, &bottom);
390 for (comp = 0; comp < nb_comp; comp++) {446 for (comp = 0; comp < nb_comp; comp++) {
447 const int depth = draw->desc->comp[comp].depth;
448
391 if (!component_used(draw, plane, comp))449 if (!component_used(draw, plane, comp))
392 continue;450 continue;
393 p = p0 + comp;451 p = p0 + comp;
394 if (top) {452 if (top) {
395 blend_line(p, color->comp[plane].u8[comp], alpha >> 1,453 if (depth <= 8) {
396 draw->pixelstep[plane], w_sub,454 blend_line(p, color->comp[plane].u8[comp], alpha >> 1,
397 draw->hsub[plane], left, right);455 draw->pixelstep[plane], w_sub,
456 draw->hsub[plane], left, right);
457 } else {
458 blend_line16(p, color->comp[plane].u16[comp], alpha >> 1,
459 draw->pixelstep[plane], w_sub,
460 draw->hsub[plane], left, right);
461 }
398 p += dst_linesize[plane];462 p += dst_linesize[plane];
399 }463 }
400 for (y = 0; y < h_sub; y++) {464 if (depth <= 8) {
401 blend_line(p, color->comp[plane].u8[comp], alpha,465 for (y = 0; y < h_sub; y++) {
402 draw->pixelstep[plane], w_sub,466 blend_line(p, color->comp[plane].u8[comp], alpha,
403 draw->hsub[plane], left, right);467 draw->pixelstep[plane], w_sub,
404 p += dst_linesize[plane];468 draw->hsub[plane], left, right);
469 p += dst_linesize[plane];
470 }
471 } else {
472 for (y = 0; y < h_sub; y++) {
473 blend_line16(p, color->comp[plane].u16[comp], alpha,
474 draw->pixelstep[plane], w_sub,
475 draw->hsub[plane], left, right);
476 p += dst_linesize[plane];
477 }
478 }
479 if (bottom) {
480 if (depth <= 8) {
481 blend_line(p, color->comp[plane].u8[comp], alpha >> 1,
482 draw->pixelstep[plane], w_sub,
483 draw->hsub[plane], left, right);
484 } else {
485 blend_line16(p, color->comp[plane].u16[comp], alpha >> 1,
486 draw->pixelstep[plane], w_sub,
487 draw->hsub[plane], left, right);
488 }
405 }489 }
406 if (bottom)
407 blend_line(p, color->comp[plane].u8[comp], alpha >> 1,
408 draw->pixelstep[plane], w_sub,
409 draw->hsub[plane], left, right);
410 }490 }
411 }491 }
412}492}
413 493
494static void blend_pixel16(uint8_t *dst, unsigned src, unsigned alpha,
495 const uint8_t *mask, int mask_linesize, int l2depth,
496 unsigned w, unsigned h, unsigned shift, unsigned xm0)
497{
498 unsigned xm, x, y, t = 0;
499 unsigned xmshf = 3 - l2depth;
500 unsigned xmmod = 7 >> l2depth;
501 unsigned mbits = (1 << (1 << l2depth)) - 1;
502 unsigned mmult = 255 / mbits;
503 uint16_t value = AV_RL16(dst);
504
505 for (y = 0; y < h; y++) {
506 xm = xm0;
507 for (x = 0; x < w; x++) {
508 t += ((mask[xm >> xmshf] >> ((~xm & xmmod) << l2depth)) & mbits)
509 * mmult;
510 xm++;
511 }
512 mask += mask_linesize;
513 }
514 alpha = (t >> shift) * alpha;
515 AV_WL16(dst, ((0x10001 - alpha) * value + alpha * src) >> 16);
516}
517
414static void blend_pixel(uint8_t *dst, unsigned src, unsigned alpha,518static void blend_pixel(uint8_t *dst, unsigned src, unsigned alpha,
415 const uint8_t *mask, int mask_linesize, int l2depth,519 const uint8_t *mask, int mask_linesize, int l2depth,
416 unsigned w, unsigned h, unsigned shift, unsigned xm0)520 unsigned w, unsigned h, unsigned shift, unsigned xm0)
@@ -434,6 +538,31 @@ static void blend_pixel(uint8_t *dst, unsigned src, unsigned alpha, · 17 unmodified lines
434 *dst = ((0x1010101 - alpha) * *dst + alpha * src) >> 24;538 *dst = ((0x1010101 - alpha) * *dst + alpha * src) >> 24;
435}539}
436 540
541static void blend_line_hv16(uint8_t *dst, int dst_delta,
542 unsigned src, unsigned alpha,
543 const uint8_t *mask, int mask_linesize, int l2depth, int w,
544 unsigned hsub, unsigned vsub,
545 int xm, int left, int right, int hband)
546{
547 int x;
548
549 if (left) {
550 blend_pixel16(dst, src, alpha, mask, mask_linesize, l2depth,
551 left, hband, hsub + vsub, xm);
552 dst += dst_delta;
553 xm += left;
554 }
555 for (x = 0; x < w; x++) {
556 blend_pixel16(dst, src, alpha, mask, mask_linesize, l2depth,
557 1 << hsub, hband, hsub + vsub, xm);
558 dst += dst_delta;
559 xm += 1 << hsub;
560 }
561 if (right)
562 blend_pixel16(dst, src, alpha, mask, mask_linesize, l2depth,
563 right, hband, hsub + vsub, xm);
564}
565
437static void blend_line_hv(uint8_t *dst, int dst_delta,566static void blend_line_hv(uint8_t *dst, int dst_delta,
438 unsigned src, unsigned alpha,567 unsigned src, unsigned alpha,
439 const uint8_t *mask, int mask_linesize, int l2depth, int w,568 const uint8_t *mask, int mask_linesize, int l2depth, int w,
@@ -474,9 +603,13 @@ void ff_blend_mask(FFDrawContext *draw, FFDrawColor *color, · 34 unmodified lines
474 mask += ym0 * mask_linesize;603 mask += ym0 * mask_linesize;
475 if (mask_w <= 0 || mask_h <= 0 || !color->rgba[3])604 if (mask_w <= 0 || mask_h <= 0 || !color->rgba[3])
476 return;605 return;
477 /* alpha is in the [ 0 ; 0x10203 ] range,606 if (draw->desc->comp[0].depth <= 8) {
478 alpha * mask is in the [ 0 ; 0x1010101 - 4 ] range */607 /* alpha is in the [ 0 ; 0x10203 ] range,
479 alpha = (0x10307 * color->rgba[3] + 0x3) >> 8;608 alpha * mask is in the [ 0 ; 0x1010101 - 4 ] range */
609 alpha = (0x10307 * color->rgba[3] + 0x3) >> 8;
610 } else {
611 alpha = (0x101 * color->rgba[3] + 0x2) >> 8;
612 }
480 nb_planes = (draw->nb_planes - 1) | 1; /* eliminate alpha */613 nb_planes = (draw->nb_planes - 1) | 1; /* eliminate alpha */
481 for (plane = 0; plane < nb_planes; plane++) {614 for (plane = 0; plane < nb_planes; plane++) {
482 nb_comp = draw->pixelstep[plane];615 nb_comp = draw->pixelstep[plane];
@@ -488,34 +621,65 @@ void ff_blend_mask(FFDrawContext *draw, FFDrawColor *color, · 5 unmodified lines
488 subsampling_bounds(draw->hsub[plane], &x_sub, &w_sub, &left, &right);621 subsampling_bounds(draw->hsub[plane], &x_sub, &w_sub, &left, &right);
489 subsampling_bounds(draw->vsub[plane], &y_sub, &h_sub, &top, &bottom);622 subsampling_bounds(draw->vsub[plane], &y_sub, &h_sub, &top, &bottom);
490 for (comp = 0; comp < nb_comp; comp++) {623 for (comp = 0; comp < nb_comp; comp++) {
624 const int depth = draw->desc->comp[comp].depth;
625
491 if (!component_used(draw, plane, comp))626 if (!component_used(draw, plane, comp))
492 continue;627 continue;
493 p = p0 + comp;628 p = p0 + comp;
494 m = mask;629 m = mask;
495 if (top) {630 if (top) {
496 blend_line_hv(p, draw->pixelstep[plane],631 if (depth <= 8) {
497 color->comp[plane].u8[comp], alpha,632 blend_line_hv(p, draw->pixelstep[plane],
498 m, mask_linesize, l2depth, w_sub,633 color->comp[plane].u8[comp], alpha,
499 draw->hsub[plane], draw->vsub[plane],634 m, mask_linesize, l2depth, w_sub,
500 xm0, left, right, top);635 draw->hsub[plane], draw->vsub[plane],
636 xm0, left, right, top);
637 } else {
638 blend_line_hv16(p, draw->pixelstep[plane],
639 color->comp[plane].u16[comp], alpha,
640 m, mask_linesize, l2depth, w_sub,
641 draw->hsub[plane], draw->vsub[plane],
642 xm0, left, right, top);
643 }
501 p += dst_linesize[plane];644 p += dst_linesize[plane];
502 m += top * mask_linesize;645 m += top * mask_linesize;
503 }646 }
504 for (y = 0; y < h_sub; y++) {647 if (depth <= 8) {
505 blend_line_hv(p, draw->pixelstep[plane],648 for (y = 0; y < h_sub; y++) {
506 color->comp[plane].u8[comp], alpha,649 blend_line_hv(p, draw->pixelstep[plane],
507 m, mask_linesize, l2depth, w_sub,650 color->comp[plane].u8[comp], alpha,
508 draw->hsub[plane], draw->vsub[plane],651 m, mask_linesize, l2depth, w_sub,
509 xm0, left, right, 1 << draw->vsub[plane]);652 draw->hsub[plane], draw->vsub[plane],
510 p += dst_linesize[plane];653 xm0, left, right, 1 << draw->vsub[plane]);
511 m += mask_linesize << draw->vsub[plane];654 p += dst_linesize[plane];
655 m += mask_linesize << draw->vsub[plane];
656 }
657 } else {
658 for (y = 0; y < h_sub; y++) {
659 blend_line_hv16(p, draw->pixelstep[plane],
660 color->comp[plane].u16[comp], alpha,
661 m, mask_linesize, l2depth, w_sub,
662 draw->hsub[plane], draw->vsub[plane],
663 xm0, left, right, 1 << draw->vsub[plane]);
664 p += dst_linesize[plane];
665 m += mask_linesize << draw->vsub[plane];
666 }
667 }
668 if (bottom) {
669 if (depth <= 8) {
670 blend_line_hv(p, draw->pixelstep[plane],
671 color->comp[plane].u8[comp], alpha,
672 m, mask_linesize, l2depth, w_sub,
673 draw->hsub[plane], draw->vsub[plane],
674 xm0, left, right, bottom);
675 } else {
676 blend_line_hv16(p, draw->pixelstep[plane],
677 color->comp[plane].u16[comp], alpha,
678 m, mask_linesize, l2depth, w_sub,
679 draw->hsub[plane], draw->vsub[plane],
680 xm0, left, right, bottom);
681 }
512 }682 }
513 if (bottom)
514 blend_line_hv(p, draw->pixelstep[plane],
515 color->comp[plane].u8[comp], alpha,
516 m, mask_linesize, l2depth, w_sub,
517 draw->hsub[plane], draw->vsub[plane],
518 xm0, left, right, bottom);
519 }683 }
520 }684 }
521}685}

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