00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00026 #include "avfilter.h"
00027 #include "libavutil/pixdesc.h"
00028 #include "libavutil/colorspace.h"
00029 #include "libavutil/imgutils.h"
00030 #include "libavutil/mathematics.h"
00031 #include "libavutil/parseutils.h"
00032 #include "drawutils.h"
00033
00034 typedef struct {
00035 int w, h;
00036 uint8_t color_rgba[4];
00037 AVRational time_base;
00038 uint64_t pts;
00039 FFDrawContext draw;
00040 FFDrawColor color;
00041 } ColorContext;
00042
00043 static av_cold int color_init(AVFilterContext *ctx, const char *args, void *opaque)
00044 {
00045 ColorContext *color = ctx->priv;
00046 char color_string[128] = "black";
00047 char frame_size [128] = "320x240";
00048 char frame_rate [128] = "25";
00049 AVRational frame_rate_q;
00050 int ret;
00051
00052 if (args)
00053 sscanf(args, "%127[^:]:%127[^:]:%127s", color_string, frame_size, frame_rate);
00054
00055 if (av_parse_video_size(&color->w, &color->h, frame_size) < 0) {
00056 av_log(ctx, AV_LOG_ERROR, "Invalid frame size: %s\n", frame_size);
00057 return AVERROR(EINVAL);
00058 }
00059
00060 if (av_parse_video_rate(&frame_rate_q, frame_rate) < 0 ||
00061 frame_rate_q.den <= 0 || frame_rate_q.num <= 0) {
00062 av_log(ctx, AV_LOG_ERROR, "Invalid frame rate: %s\n", frame_rate);
00063 return AVERROR(EINVAL);
00064 }
00065 color->time_base.num = frame_rate_q.den;
00066 color->time_base.den = frame_rate_q.num;
00067
00068 if ((ret = av_parse_color(color->color_rgba, color_string, -1, ctx)) < 0)
00069 return ret;
00070
00071 return 0;
00072 }
00073
00074 static int query_formats(AVFilterContext *ctx)
00075 {
00076 avfilter_set_common_pixel_formats(ctx, ff_draw_supported_pixel_formats(0));
00077 return 0;
00078 }
00079
00080 static int color_config_props(AVFilterLink *inlink)
00081 {
00082 AVFilterContext *ctx = inlink->src;
00083 ColorContext *color = ctx->priv;
00084
00085 ff_draw_init(&color->draw, inlink->format, 0);
00086 ff_draw_color(&color->draw, &color->color, color->color_rgba);
00087
00088 color->w = ff_draw_round_to_sub(&color->draw, 0, -1, color->w);
00089 color->h = ff_draw_round_to_sub(&color->draw, 1, -1, color->h);
00090 if (av_image_check_size(color->w, color->h, 0, ctx) < 0)
00091 return AVERROR(EINVAL);
00092
00093 av_log(ctx, AV_LOG_INFO, "w:%d h:%d r:%d/%d color:0x%02x%02x%02x%02x\n",
00094 color->w, color->h, color->time_base.den, color->time_base.num,
00095 color->color_rgba[0], color->color_rgba[1], color->color_rgba[2], color->color_rgba[3]);
00096 inlink->w = color->w;
00097 inlink->h = color->h;
00098 inlink->time_base = color->time_base;
00099
00100 return 0;
00101 }
00102
00103 static int color_request_frame(AVFilterLink *link)
00104 {
00105 ColorContext *color = link->src->priv;
00106 AVFilterBufferRef *picref = avfilter_get_video_buffer(link, AV_PERM_WRITE, color->w, color->h);
00107 picref->video->sample_aspect_ratio = (AVRational) {1, 1};
00108 picref->pts = color->pts++;
00109 picref->pos = -1;
00110
00111 avfilter_start_frame(link, avfilter_ref_buffer(picref, ~0));
00112 ff_fill_rectangle(&color->draw, &color->color, picref->data, picref->linesize,
00113 0, 0, color->w, color->h);
00114 avfilter_draw_slice(link, 0, color->h, 1);
00115 avfilter_end_frame(link);
00116 avfilter_unref_buffer(picref);
00117
00118 return 0;
00119 }
00120
00121 AVFilter avfilter_vsrc_color = {
00122 .name = "color",
00123 .description = NULL_IF_CONFIG_SMALL("Provide an uniformly colored input, syntax is: [color[:size[:rate]]]."),
00124
00125 .priv_size = sizeof(ColorContext),
00126 .init = color_init,
00127
00128 .query_formats = query_formats,
00129
00130 .inputs = (const AVFilterPad[]) {{ .name = NULL}},
00131
00132 .outputs = (const AVFilterPad[]) {{ .name = "default",
00133 .type = AVMEDIA_TYPE_VIDEO,
00134 .request_frame = color_request_frame,
00135 .config_props = color_config_props },
00136 { .name = NULL}},
00137 };