Commit a3e67c2d authored by Paul B Mahol's avatar Paul B Mahol

avfilter/vf_stack: add fill option for xstack

parent 07b3dbbb
...@@ -20062,6 +20062,10 @@ a layout must be set by the user. ...@@ -20062,6 +20062,10 @@ a layout must be set by the user.
@item shortest @item shortest
If set to 1, force the output to terminate when the shortest input If set to 1, force the output to terminate when the shortest input
terminates. Default value is 0. terminates. Default value is 0.
@item fill
If set to valid color, all unused pixels will be filled with that color.
By default fill is set to none, so it is disabled.
@end table @end table
@subsection Examples @subsection Examples
......
...@@ -21,9 +21,11 @@ ...@@ -21,9 +21,11 @@
#include "libavutil/avstring.h" #include "libavutil/avstring.h"
#include "libavutil/imgutils.h" #include "libavutil/imgutils.h"
#include "libavutil/opt.h" #include "libavutil/opt.h"
#include "libavutil/parseutils.h"
#include "libavutil/pixdesc.h" #include "libavutil/pixdesc.h"
#include "avfilter.h" #include "avfilter.h"
#include "drawutils.h"
#include "formats.h" #include "formats.h"
#include "internal.h" #include "internal.h"
#include "framesync.h" #include "framesync.h"
...@@ -44,6 +46,12 @@ typedef struct StackContext { ...@@ -44,6 +46,12 @@ typedef struct StackContext {
int is_vertical; int is_vertical;
int is_horizontal; int is_horizontal;
int nb_planes; int nb_planes;
uint8_t fillcolor[4];
char *fillcolor_str;
int fillcolor_enable;
FFDrawContext draw;
FFDrawColor color;
StackItem *items; StackItem *items;
AVFrame **frames; AVFrame **frames;
...@@ -53,8 +61,13 @@ typedef struct StackContext { ...@@ -53,8 +61,13 @@ typedef struct StackContext {
static int query_formats(AVFilterContext *ctx) static int query_formats(AVFilterContext *ctx)
{ {
AVFilterFormats *pix_fmts = NULL; AVFilterFormats *pix_fmts = NULL;
StackContext *s = ctx->priv;
int fmt, ret; int fmt, ret;
if (s->fillcolor_enable) {
return ff_set_common_formats(ctx, ff_draw_supported_pixel_formats(0));
}
for (fmt = 0; av_pix_fmt_desc_get(fmt); fmt++) { for (fmt = 0; av_pix_fmt_desc_get(fmt); fmt++) {
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt); const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt);
if (!(desc->flags & AV_PIX_FMT_FLAG_PAL || if (!(desc->flags & AV_PIX_FMT_FLAG_PAL ||
...@@ -87,6 +100,12 @@ static av_cold int init(AVFilterContext *ctx) ...@@ -87,6 +100,12 @@ static av_cold int init(AVFilterContext *ctx)
return AVERROR(ENOMEM); return AVERROR(ENOMEM);
if (!strcmp(ctx->filter->name, "xstack")) { if (!strcmp(ctx->filter->name, "xstack")) {
if (strcmp(s->fillcolor_str, "none") &&
av_parse_color(s->fillcolor, s->fillcolor_str, -1, ctx) >= 0) {
s->fillcolor_enable = 1;
} else {
s->fillcolor_enable = 0;
}
if (!s->layout) { if (!s->layout) {
if (s->nb_inputs == 2) { if (s->nb_inputs == 2) {
s->layout = av_strdup("0_0|w0_0"); s->layout = av_strdup("0_0|w0_0");
...@@ -159,6 +178,10 @@ static int process_frame(FFFrameSync *fs) ...@@ -159,6 +178,10 @@ static int process_frame(FFFrameSync *fs)
out->pts = av_rescale_q(s->fs.pts, s->fs.time_base, outlink->time_base); out->pts = av_rescale_q(s->fs.pts, s->fs.time_base, outlink->time_base);
out->sample_aspect_ratio = outlink->sample_aspect_ratio; out->sample_aspect_ratio = outlink->sample_aspect_ratio;
if (s->fillcolor_enable)
ff_fill_rectangle(&s->draw, &s->color, out->data, out->linesize,
0, 0, outlink->w, outlink->h);
ctx->internal->execute(ctx, process_slice, out, NULL, FFMIN(s->nb_inputs, ff_filter_get_nb_threads(ctx))); ctx->internal->execute(ctx, process_slice, out, NULL, FFMIN(s->nb_inputs, ff_filter_get_nb_threads(ctx)));
return ff_filter_frame(outlink, out); return ff_filter_frame(outlink, out);
...@@ -234,6 +257,11 @@ static int config_output(AVFilterLink *outlink) ...@@ -234,6 +257,11 @@ static int config_output(AVFilterLink *outlink)
char *arg3, *p3, *saveptr3 = NULL; char *arg3, *p3, *saveptr3 = NULL;
int inw, inh, size; int inw, inh, size;
if (s->fillcolor_enable) {
ff_draw_init(&s->draw, ctx->inputs[0]->format, 0);
ff_draw_color(&s->draw, &s->color, s->fillcolor);
}
for (i = 0; i < s->nb_inputs; i++) { for (i = 0; i < s->nb_inputs; i++) {
AVFilterLink *inlink = ctx->inputs[i]; AVFilterLink *inlink = ctx->inputs[i];
StackItem *item = &s->items[i]; StackItem *item = &s->items[i];
...@@ -425,6 +453,7 @@ static const AVOption xstack_options[] = { ...@@ -425,6 +453,7 @@ static const AVOption xstack_options[] = {
{ "inputs", "set number of inputs", OFFSET(nb_inputs), AV_OPT_TYPE_INT, {.i64=2}, 2, INT_MAX, .flags = FLAGS }, { "inputs", "set number of inputs", OFFSET(nb_inputs), AV_OPT_TYPE_INT, {.i64=2}, 2, INT_MAX, .flags = FLAGS },
{ "layout", "set custom layout", OFFSET(layout), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, .flags = FLAGS }, { "layout", "set custom layout", OFFSET(layout), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, .flags = FLAGS },
{ "shortest", "force termination when the shortest input terminates", OFFSET(shortest), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, .flags = FLAGS }, { "shortest", "force termination when the shortest input terminates", OFFSET(shortest), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, .flags = FLAGS },
{ "fill", "set the color for unused pixels", OFFSET(fillcolor_str), AV_OPT_TYPE_STRING, {.str = "none"}, .flags = FLAGS },
{ NULL }, { NULL },
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment