1
0
mirror of https://github.com/FFmpeg/FFmpeg.git synced 2024-12-23 12:43:46 +02:00

avfilter/vf_stack: add fill option for xstack

This commit is contained in:
Paul B Mahol 2020-01-22 19:11:38 +01:00
parent 07b3dbbbb2
commit a3e67c2d2f
2 changed files with 33 additions and 0 deletions

View File

@ -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

View File

@ -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 {
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 {
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)
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)
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)
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[] = {
{ "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 },
}; };