Add drawutils.h and drawutils.c, and use them in the pad filter.
The new functions are going to be shared by other filters.
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
| 18 | 19 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,117 @@ |
| 0 |
+/* |
|
| 1 |
+ * This file is part of FFmpeg. |
|
| 2 |
+ * |
|
| 3 |
+ * FFmpeg is free software; you can redistribute it and/or |
|
| 4 |
+ * modify it under the terms of the GNU Lesser General Public |
|
| 5 |
+ * License as published by the Free Software Foundation; either |
|
| 6 |
+ * version 2.1 of the License, or (at your option) any later version. |
|
| 7 |
+ * |
|
| 8 |
+ * FFmpeg is distributed in the hope that it will be useful, |
|
| 9 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 10 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
| 11 |
+ * Lesser General Public License for more details. |
|
| 12 |
+ * |
|
| 13 |
+ * You should have received a copy of the GNU Lesser General Public |
|
| 14 |
+ * License along with FFmpeg; if not, write to the Free Software |
|
| 15 |
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
| 16 |
+ */ |
|
| 17 |
+ |
|
| 18 |
+#include "libavutil/avutil.h" |
|
| 19 |
+#include "libavutil/colorspace.h" |
|
| 20 |
+#include "libavutil/pixdesc.h" |
|
| 21 |
+#include "drawutils.h" |
|
| 22 |
+ |
|
| 23 |
+enum { RED = 0, GREEN, BLUE, ALPHA };
|
|
| 24 |
+ |
|
| 25 |
+int ff_fill_line_with_color(uint8_t *line[4], int pixel_step[4], int w, uint8_t dst_color[4], |
|
| 26 |
+ enum PixelFormat pix_fmt, uint8_t rgba_color[4], |
|
| 27 |
+ int *is_packed_rgba, uint8_t rgba_map_ptr[4]) |
|
| 28 |
+{
|
|
| 29 |
+ uint8_t rgba_map[4] = {0};
|
|
| 30 |
+ int i; |
|
| 31 |
+ const AVPixFmtDescriptor *pix_desc = &av_pix_fmt_descriptors[pix_fmt]; |
|
| 32 |
+ int hsub = pix_desc->log2_chroma_w; |
|
| 33 |
+ |
|
| 34 |
+ *is_packed_rgba = 1; |
|
| 35 |
+ switch (pix_fmt) {
|
|
| 36 |
+ case PIX_FMT_ARGB: rgba_map[ALPHA] = 0; rgba_map[RED ] = 1; rgba_map[GREEN] = 2; rgba_map[BLUE ] = 3; break; |
|
| 37 |
+ case PIX_FMT_ABGR: rgba_map[ALPHA] = 0; rgba_map[BLUE ] = 1; rgba_map[GREEN] = 2; rgba_map[RED ] = 3; break; |
|
| 38 |
+ case PIX_FMT_RGBA: |
|
| 39 |
+ case PIX_FMT_RGB24: rgba_map[RED ] = 0; rgba_map[GREEN] = 1; rgba_map[BLUE ] = 2; rgba_map[ALPHA] = 3; break; |
|
| 40 |
+ case PIX_FMT_BGRA: |
|
| 41 |
+ case PIX_FMT_BGR24: rgba_map[BLUE ] = 0; rgba_map[GREEN] = 1; rgba_map[RED ] = 2; rgba_map[ALPHA] = 3; break; |
|
| 42 |
+ default: |
|
| 43 |
+ *is_packed_rgba = 0; |
|
| 44 |
+ } |
|
| 45 |
+ |
|
| 46 |
+ if (*is_packed_rgba) {
|
|
| 47 |
+ pixel_step[0] = (av_get_bits_per_pixel(pix_desc))>>3; |
|
| 48 |
+ for (i = 0; i < 4; i++) |
|
| 49 |
+ dst_color[rgba_map[i]] = rgba_color[i]; |
|
| 50 |
+ |
|
| 51 |
+ line[0] = av_malloc(w * pixel_step[0]); |
|
| 52 |
+ for (i = 0; i < w; i++) |
|
| 53 |
+ memcpy(line[0] + i * pixel_step[0], dst_color, pixel_step[0]); |
|
| 54 |
+ if (rgba_map_ptr) |
|
| 55 |
+ memcpy(rgba_map_ptr, rgba_map, sizeof(rgba_map[0]) * 4); |
|
| 56 |
+ } else {
|
|
| 57 |
+ int plane; |
|
| 58 |
+ |
|
| 59 |
+ dst_color[0] = RGB_TO_Y_CCIR(rgba_color[0], rgba_color[1], rgba_color[2]); |
|
| 60 |
+ dst_color[1] = RGB_TO_U_CCIR(rgba_color[0], rgba_color[1], rgba_color[2], 0); |
|
| 61 |
+ dst_color[2] = RGB_TO_V_CCIR(rgba_color[0], rgba_color[1], rgba_color[2], 0); |
|
| 62 |
+ dst_color[3] = rgba_color[3]; |
|
| 63 |
+ |
|
| 64 |
+ for (plane = 0; plane < 4; plane++) {
|
|
| 65 |
+ int line_size; |
|
| 66 |
+ int hsub1 = (plane == 1 || plane == 2) ? hsub : 0; |
|
| 67 |
+ |
|
| 68 |
+ pixel_step[plane] = 1; |
|
| 69 |
+ line_size = (w >> hsub1) * pixel_step[plane]; |
|
| 70 |
+ line[plane] = av_malloc(line_size); |
|
| 71 |
+ memset(line[plane], dst_color[plane], line_size); |
|
| 72 |
+ } |
|
| 73 |
+ } |
|
| 74 |
+ |
|
| 75 |
+ return 0; |
|
| 76 |
+} |
|
| 77 |
+ |
|
| 78 |
+void ff_draw_rectangle(uint8_t *dst[4], int dst_linesize[4], |
|
| 79 |
+ uint8_t *src[4], int pixelstep[4], |
|
| 80 |
+ int hsub, int vsub, int x, int y, int w, int h) |
|
| 81 |
+{
|
|
| 82 |
+ int i, plane; |
|
| 83 |
+ uint8_t *p; |
|
| 84 |
+ |
|
| 85 |
+ for (plane = 0; plane < 4 && dst[plane]; plane++) {
|
|
| 86 |
+ int hsub1 = plane == 1 || plane == 2 ? hsub : 0; |
|
| 87 |
+ int vsub1 = plane == 1 || plane == 2 ? vsub : 0; |
|
| 88 |
+ |
|
| 89 |
+ p = dst[plane] + (y >> vsub1) * dst_linesize[plane]; |
|
| 90 |
+ for (i = 0; i < (h >> vsub1); i++) {
|
|
| 91 |
+ memcpy(p + (x >> hsub1) * pixelstep[plane], |
|
| 92 |
+ src[plane], (w >> hsub1) * pixelstep[plane]); |
|
| 93 |
+ p += dst_linesize[plane]; |
|
| 94 |
+ } |
|
| 95 |
+ } |
|
| 96 |
+} |
|
| 97 |
+ |
|
| 98 |
+void ff_copy_rectangle(uint8_t *dst[4], int dst_linesize[4], |
|
| 99 |
+ uint8_t *src[4], int src_linesize[4], int pixelstep[4], |
|
| 100 |
+ int hsub, int vsub, int x, int y, int y2, int w, int h) |
|
| 101 |
+{
|
|
| 102 |
+ int i, plane; |
|
| 103 |
+ uint8_t *p; |
|
| 104 |
+ |
|
| 105 |
+ for (plane = 0; plane < 4 && dst[plane]; plane++) {
|
|
| 106 |
+ int hsub1 = plane == 1 || plane == 2 ? hsub : 0; |
|
| 107 |
+ int vsub1 = plane == 1 || plane == 2 ? vsub : 0; |
|
| 108 |
+ |
|
| 109 |
+ p = dst[plane] + (y >> vsub1) * dst_linesize[plane]; |
|
| 110 |
+ for (i = 0; i < (h >> vsub1); i++) {
|
|
| 111 |
+ memcpy(p + (x >> hsub1) * pixelstep[plane], |
|
| 112 |
+ src[plane] + src_linesize[plane]*(i+(y2>>vsub1)), (w >> hsub1) * pixelstep[plane]); |
|
| 113 |
+ p += dst_linesize[plane]; |
|
| 114 |
+ } |
|
| 115 |
+ } |
|
| 116 |
+} |
| 0 | 117 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,43 @@ |
| 0 |
+/* |
|
| 1 |
+ * This file is part of FFmpeg. |
|
| 2 |
+ * |
|
| 3 |
+ * FFmpeg is free software; you can redistribute it and/or |
|
| 4 |
+ * modify it under the terms of the GNU Lesser General Public |
|
| 5 |
+ * License as published by the Free Software Foundation; either |
|
| 6 |
+ * version 2.1 of the License, or (at your option) any later version. |
|
| 7 |
+ * |
|
| 8 |
+ * FFmpeg is distributed in the hope that it will be useful, |
|
| 9 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 10 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
| 11 |
+ * Lesser General Public License for more details. |
|
| 12 |
+ * |
|
| 13 |
+ * You should have received a copy of the GNU Lesser General Public |
|
| 14 |
+ * License along with FFmpeg; if not, write to the Free Software |
|
| 15 |
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
| 16 |
+ */ |
|
| 17 |
+ |
|
| 18 |
+#ifndef AVFILTER_DRAWUTILS_H |
|
| 19 |
+#define AVFILTER_DRAWUTILS_H |
|
| 20 |
+ |
|
| 21 |
+/** |
|
| 22 |
+ * @file |
|
| 23 |
+ * misc drawing utilities |
|
| 24 |
+ */ |
|
| 25 |
+ |
|
| 26 |
+#include <stdint.h> |
|
| 27 |
+#include "libavutil/pixfmt.h" |
|
| 28 |
+ |
|
| 29 |
+int ff_fill_line_with_color(uint8_t *line[4], int pixel_step[4], int w, |
|
| 30 |
+ uint8_t dst_color[4], |
|
| 31 |
+ enum PixelFormat pix_fmt, uint8_t rgba_color[4], |
|
| 32 |
+ int *is_packed_rgba, uint8_t rgba_map[4]); |
|
| 33 |
+ |
|
| 34 |
+void ff_draw_rectangle(uint8_t *dst[4], int dst_linesize[4], |
|
| 35 |
+ uint8_t *src[4], int pixelstep[4], |
|
| 36 |
+ int hsub, int vsub, int x, int y, int w, int h); |
|
| 37 |
+ |
|
| 38 |
+void ff_copy_rectangle(uint8_t *dst[4], int dst_linesize[4], |
|
| 39 |
+ uint8_t *src[4], int src_linesize[4], int pixelstep[4], |
|
| 40 |
+ int hsub, int vsub, int x, int y, int y2, int w, int h); |
|
| 41 |
+ |
|
| 42 |
+#endif /* AVFILTER_DRAWUTILS_H */ |
| ... | ... |
@@ -30,94 +30,7 @@ |
| 30 | 30 |
#include "libavutil/avassert.h" |
| 31 | 31 |
#include "libavutil/imgutils.h" |
| 32 | 32 |
#include "libavutil/parseutils.h" |
| 33 |
- |
|
| 34 |
-enum { RED = 0, GREEN, BLUE, ALPHA };
|
|
| 35 |
- |
|
| 36 |
-static int fill_line_with_color(uint8_t *line[4], int line_step[4], int w, uint8_t color[4], |
|
| 37 |
- enum PixelFormat pix_fmt, uint8_t rgba_color[4], int *is_packed_rgba) |
|
| 38 |
-{
|
|
| 39 |
- uint8_t rgba_map[4] = {0};
|
|
| 40 |
- int i; |
|
| 41 |
- const AVPixFmtDescriptor *pix_desc = &av_pix_fmt_descriptors[pix_fmt]; |
|
| 42 |
- int hsub = pix_desc->log2_chroma_w; |
|
| 43 |
- |
|
| 44 |
- *is_packed_rgba = 1; |
|
| 45 |
- switch (pix_fmt) {
|
|
| 46 |
- case PIX_FMT_ARGB: rgba_map[ALPHA] = 0; rgba_map[RED ] = 1; rgba_map[GREEN] = 2; rgba_map[BLUE ] = 3; break; |
|
| 47 |
- case PIX_FMT_ABGR: rgba_map[ALPHA] = 0; rgba_map[BLUE ] = 1; rgba_map[GREEN] = 2; rgba_map[RED ] = 3; break; |
|
| 48 |
- case PIX_FMT_RGBA: |
|
| 49 |
- case PIX_FMT_RGB24: rgba_map[RED ] = 0; rgba_map[GREEN] = 1; rgba_map[BLUE ] = 2; rgba_map[ALPHA] = 3; break; |
|
| 50 |
- case PIX_FMT_BGRA: |
|
| 51 |
- case PIX_FMT_BGR24: rgba_map[BLUE ] = 0; rgba_map[GREEN] = 1; rgba_map[RED ] = 2; rgba_map[ALPHA] = 3; break; |
|
| 52 |
- default: |
|
| 53 |
- *is_packed_rgba = 0; |
|
| 54 |
- } |
|
| 55 |
- |
|
| 56 |
- if (*is_packed_rgba) {
|
|
| 57 |
- line_step[0] = (av_get_bits_per_pixel(pix_desc))>>3; |
|
| 58 |
- for (i = 0; i < 4; i++) |
|
| 59 |
- color[rgba_map[i]] = rgba_color[i]; |
|
| 60 |
- |
|
| 61 |
- line[0] = av_malloc(w * line_step[0]); |
|
| 62 |
- for (i = 0; i < w; i++) |
|
| 63 |
- memcpy(line[0] + i * line_step[0], color, line_step[0]); |
|
| 64 |
- } else {
|
|
| 65 |
- int plane; |
|
| 66 |
- |
|
| 67 |
- color[RED ] = RGB_TO_Y_CCIR(rgba_color[0], rgba_color[1], rgba_color[2]); |
|
| 68 |
- color[GREEN] = RGB_TO_U_CCIR(rgba_color[0], rgba_color[1], rgba_color[2], 0); |
|
| 69 |
- color[BLUE ] = RGB_TO_V_CCIR(rgba_color[0], rgba_color[1], rgba_color[2], 0); |
|
| 70 |
- color[ALPHA] = rgba_color[3]; |
|
| 71 |
- |
|
| 72 |
- for (plane = 0; plane < 4; plane++) {
|
|
| 73 |
- int line_size; |
|
| 74 |
- int hsub1 = (plane == 1 || plane == 2) ? hsub : 0; |
|
| 75 |
- |
|
| 76 |
- line_step[plane] = 1; |
|
| 77 |
- line_size = (w >> hsub1) * line_step[plane]; |
|
| 78 |
- line[plane] = av_malloc(line_size); |
|
| 79 |
- memset(line[plane], color[plane], line_size); |
|
| 80 |
- } |
|
| 81 |
- } |
|
| 82 |
- |
|
| 83 |
- return 0; |
|
| 84 |
-} |
|
| 85 |
- |
|
| 86 |
-static void draw_rectangle(AVFilterBufferRef *outpic, uint8_t *line[4], int line_step[4], |
|
| 87 |
- int hsub, int vsub, int x, int y, int w, int h) |
|
| 88 |
-{
|
|
| 89 |
- int i, plane; |
|
| 90 |
- uint8_t *p; |
|
| 91 |
- |
|
| 92 |
- for (plane = 0; plane < 4 && outpic->data[plane]; plane++) {
|
|
| 93 |
- int hsub1 = plane == 1 || plane == 2 ? hsub : 0; |
|
| 94 |
- int vsub1 = plane == 1 || plane == 2 ? vsub : 0; |
|
| 95 |
- |
|
| 96 |
- p = outpic->data[plane] + (y >> vsub1) * outpic->linesize[plane]; |
|
| 97 |
- for (i = 0; i < (h >> vsub1); i++) {
|
|
| 98 |
- memcpy(p + (x >> hsub1) * line_step[plane], line[plane], (w >> hsub1) * line_step[plane]); |
|
| 99 |
- p += outpic->linesize[plane]; |
|
| 100 |
- } |
|
| 101 |
- } |
|
| 102 |
-} |
|
| 103 |
- |
|
| 104 |
-static void copy_rectangle(AVFilterBufferRef *outpic,uint8_t *line[4], int line_step[4], int linesize[4], |
|
| 105 |
- int hsub, int vsub, int x, int y, int y2, int w, int h) |
|
| 106 |
-{
|
|
| 107 |
- int i, plane; |
|
| 108 |
- uint8_t *p; |
|
| 109 |
- |
|
| 110 |
- for (plane = 0; plane < 4 && outpic->data[plane]; plane++) {
|
|
| 111 |
- int hsub1 = plane == 1 || plane == 2 ? hsub : 0; |
|
| 112 |
- int vsub1 = plane == 1 || plane == 2 ? vsub : 0; |
|
| 113 |
- |
|
| 114 |
- p = outpic->data[plane] + (y >> vsub1) * outpic->linesize[plane]; |
|
| 115 |
- for (i = 0; i < (h >> vsub1); i++) {
|
|
| 116 |
- memcpy(p + (x >> hsub1) * line_step[plane], line[plane] + linesize[plane]*(i+(y2>>vsub1)), (w >> hsub1) * line_step[plane]); |
|
| 117 |
- p += outpic->linesize[plane]; |
|
| 118 |
- } |
|
| 119 |
- } |
|
| 120 |
-} |
|
| 33 |
+#include "drawutils.h" |
|
| 121 | 34 |
|
| 122 | 35 |
static int query_formats(AVFilterContext *ctx) |
| 123 | 36 |
{
|
| ... | ... |
@@ -210,8 +123,8 @@ static int config_input(AVFilterLink *inlink) |
| 210 | 210 |
pad->in_h = inlink->h & ~((1 << pad->vsub) - 1); |
| 211 | 211 |
|
| 212 | 212 |
memcpy(rgba_color, pad->color, sizeof(rgba_color)); |
| 213 |
- fill_line_with_color(pad->line, pad->line_step, pad->w, pad->color, |
|
| 214 |
- inlink->format, rgba_color, &is_packed_rgba); |
|
| 213 |
+ ff_fill_line_with_color(pad->line, pad->line_step, pad->w, pad->color, |
|
| 214 |
+ inlink->format, rgba_color, &is_packed_rgba, NULL); |
|
| 215 | 215 |
|
| 216 | 216 |
av_log(ctx, AV_LOG_INFO, "w:%d h:%d -> w:%d h:%d x:%d y:%d color:0x%02X%02X%02X%02X[%s]\n", |
| 217 | 217 |
inlink->w, inlink->h, pad->w, pad->h, pad->x, pad->y, |
| ... | ... |
@@ -351,9 +264,10 @@ static void draw_send_bar_slice(AVFilterLink *link, int y, int h, int slice_dir, |
| 351 | 351 |
} |
| 352 | 352 |
|
| 353 | 353 |
if (bar_h) {
|
| 354 |
- draw_rectangle(link->dst->outputs[0]->out_buf, |
|
| 355 |
- pad->line, pad->line_step, pad->hsub, pad->vsub, |
|
| 356 |
- 0, bar_y, pad->w, bar_h); |
|
| 354 |
+ ff_draw_rectangle(link->dst->outputs[0]->out_buf->data, |
|
| 355 |
+ link->dst->outputs[0]->out_buf->linesize, |
|
| 356 |
+ pad->line, pad->line_step, pad->hsub, pad->vsub, |
|
| 357 |
+ 0, bar_y, pad->w, bar_h); |
|
| 357 | 358 |
avfilter_draw_slice(link->dst->outputs[0], bar_y, bar_h, slice_dir); |
| 358 | 359 |
} |
| 359 | 360 |
} |
| ... | ... |
@@ -374,18 +288,20 @@ static void draw_slice(AVFilterLink *link, int y, int h, int slice_dir) |
| 374 | 374 |
draw_send_bar_slice(link, y, h, slice_dir, 1); |
| 375 | 375 |
|
| 376 | 376 |
/* left border */ |
| 377 |
- draw_rectangle(outpic, pad->line, pad->line_step, pad->hsub, pad->vsub, |
|
| 378 |
- 0, y, pad->x, h); |
|
| 377 |
+ ff_draw_rectangle(outpic->data, outpic->linesize, pad->line, pad->line_step, |
|
| 378 |
+ pad->hsub, pad->vsub, 0, y, pad->x, h); |
|
| 379 | 379 |
|
| 380 | 380 |
if(pad->needs_copy){
|
| 381 |
- copy_rectangle(outpic, |
|
| 382 |
- inpic->data, pad->line_step, inpic->linesize, pad->hsub, pad->vsub, |
|
| 383 |
- pad->x, y, y-pad->y, inpic->video->w, h); |
|
| 381 |
+ ff_copy_rectangle(outpic->data, outpic->linesize, |
|
| 382 |
+ inpic->data, inpic->linesize, pad->line_step, |
|
| 383 |
+ pad->hsub, pad->vsub, |
|
| 384 |
+ pad->x, y, y-pad->y, inpic->video->w, h); |
|
| 384 | 385 |
} |
| 385 | 386 |
|
| 386 | 387 |
/* right border */ |
| 387 |
- draw_rectangle(outpic, pad->line, pad->line_step, pad->hsub, pad->vsub, |
|
| 388 |
- pad->x + pad->in_w, y, pad->w - pad->x - pad->in_w, h); |
|
| 388 |
+ ff_draw_rectangle(outpic->data, outpic->linesize, |
|
| 389 |
+ pad->line, pad->line_step, pad->hsub, pad->vsub, |
|
| 390 |
+ pad->x + pad->in_w, y, pad->w - pad->x - pad->in_w, h); |
|
| 389 | 391 |
avfilter_draw_slice(link->dst->outputs[0], y, h, slice_dir); |
| 390 | 392 |
|
| 391 | 393 |
draw_send_bar_slice(link, y, h, slice_dir, -1); |
| ... | ... |
@@ -488,8 +404,8 @@ static int color_config_props(AVFilterLink *inlink) |
| 488 | 488 |
return AVERROR(EINVAL); |
| 489 | 489 |
|
| 490 | 490 |
memcpy(rgba_color, color->color, sizeof(rgba_color)); |
| 491 |
- fill_line_with_color(color->line, color->line_step, color->w, color->color, |
|
| 492 |
- inlink->format, rgba_color, &is_packed_rgba); |
|
| 491 |
+ ff_fill_line_with_color(color->line, color->line_step, color->w, color->color, |
|
| 492 |
+ inlink->format, rgba_color, &is_packed_rgba, NULL); |
|
| 493 | 493 |
|
| 494 | 494 |
av_log(ctx, AV_LOG_INFO, "w:%d h:%d r:%d/%d color:0x%02x%02x%02x%02x[%s]\n", |
| 495 | 495 |
color->w, color->h, color->time_base.den, color->time_base.num, |
| ... | ... |
@@ -510,9 +426,9 @@ static int color_request_frame(AVFilterLink *link) |
| 510 | 510 |
picref->pos = 0; |
| 511 | 511 |
|
| 512 | 512 |
avfilter_start_frame(link, avfilter_ref_buffer(picref, ~0)); |
| 513 |
- draw_rectangle(picref, |
|
| 514 |
- color->line, color->line_step, color->hsub, color->vsub, |
|
| 515 |
- 0, 0, color->w, color->h); |
|
| 513 |
+ ff_draw_rectangle(picref->data, picref->linesize, |
|
| 514 |
+ color->line, color->line_step, color->hsub, color->vsub, |
|
| 515 |
+ 0, 0, color->w, color->h); |
|
| 516 | 516 |
avfilter_draw_slice(link, 0, color->h, 1); |
| 517 | 517 |
avfilter_end_frame(link); |
| 518 | 518 |
avfilter_unref_buffer(picref); |