Message ID | 1562582926-27231-1-git-send-email-lance.lmwang@gmail.com |
---|---|
State | New |
Headers | show |
On Mon, Jul 08, 2019 at 18:48:46 +0800, lance.lmwang@gmail.com wrote: > +@item keep_dar > +stack with 1/nb_inputs of each inputs screen to keep the same DAR, Default is 0. ^ Probably "input's". Is screen the correct term here at all? (In three places in the patch.) > + { "keep_dar", "stack with 1/nb_inputs of each inputs screen to keep the same DAR", OFFSET(keep_dar), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, .flags = FLAGS }, AV_OPT_TYPE_BOOL Not sure about the actual implementation, can't judge. Cheers, Moritz
On 08-07-2019 04:18 PM, lance.lmwang@gmail.com wrote: > From: Limin Wang <lance.lmwang@gmail.com> > > It's useful to compare two 4K videos quality side by side on 4K TV. > > Signed-off-by: Limin Wang <lance.lmwang@gmail.com> > --- > doc/filters.texi | 6 ++++++ > libavfilter/vf_stack.c | 31 ++++++++++++++++++++++++++----- > 2 files changed, 32 insertions(+), 5 deletions(-) > > diff --git a/doc/filters.texi b/doc/filters.texi > index ee6a93ffbf..675b02fc34 100644 > --- a/doc/filters.texi > +++ b/doc/filters.texi > @@ -11280,6 +11280,9 @@ The filter accept the following option: > @item inputs > Set number of input streams. Default is 2. > > +@item keep_dar > +stack with 1/nb_inputs of each inputs screen to keep the same DAR, Default is 0. > + > @item shortest > If set to 1, force the output to terminate when the shortest input > terminates. Default value is 0. > @@ -18333,6 +18336,9 @@ The filter accept the following option: > @item inputs > Set number of input streams. Default is 2. > > +@item keep_dar > +stack with 1/nb_inputs of each inputs screen to keep the same DAR, Default is 0. > + > @item shortest > If set to 1, force the output to terminate when the shortest input > terminates. Default value is 0. > diff --git a/libavfilter/vf_stack.c b/libavfilter/vf_stack.c > index 4d254e0013..9196b5b0b7 100644 > --- a/libavfilter/vf_stack.c > +++ b/libavfilter/vf_stack.c > @@ -44,6 +44,7 @@ typedef struct StackContext { > int is_vertical; > int is_horizontal; > int nb_planes; > + int keep_dar; > > StackItem *items; > AVFrame **frames; > @@ -123,7 +124,7 @@ static int process_frame(FFFrameSync *fs) > StackContext *s = fs->opaque; > AVFrame **in = s->frames; > AVFrame *out; > - int i, p, ret, offset[4] = { 0 }; > + int i, p, ret, offset[4] = { 0 }, in_offset[4] = { 0 }; > > for (i = 0; i < s->nb_inputs; i++) { > if ((ret = ff_framesync_get_frame(&s->fs, i, &in[i], 0)) < 0) > @@ -153,16 +154,25 @@ static int process_frame(FFFrameSync *fs) > > for (p = 0; p < s->nb_planes; p++) { > if (s->is_vertical) { > + if (s->keep_dar) { > + height[p] /= s->nb_inputs; > + in_offset[p] = i * height[p] * in[i]->linesize[p]; > + } > + > av_image_copy_plane(out->data[p] + offset[p] * out->linesize[p], > out->linesize[p], > - in[i]->data[p], > + in[i]->data[p] + in_offset[p], > in[i]->linesize[p], > linesize[p], height[p]); > offset[p] += height[p]; > } else if (s->is_horizontal) { > + if (s->keep_dar) { > + linesize[p] /= s->nb_inputs; > + in_offset[p] = i * in[i]->linesize[p] / s->nb_inputs; > + } > av_image_copy_plane(out->data[p] + offset[p], > out->linesize[p], > - in[i]->data[p], > + in[i]->data[p] + in_offset[p], > in[i]->linesize[p], > linesize[p], height[p]); > offset[p] += linesize[p]; > @@ -197,20 +207,30 @@ static int config_output(AVFilterLink *outlink) > return AVERROR_BUG; > > if (s->is_vertical) { > + if (s->keep_dar) > + height /= s->nb_inputs; > for (i = 1; i < s->nb_inputs; i++) { > if (ctx->inputs[i]->w != width) { > av_log(ctx, AV_LOG_ERROR, "Input %d width %d does not match input %d width %d.\n", i, ctx->inputs[i]->w, 0, width); > return AVERROR(EINVAL); > } > - height += ctx->inputs[i]->h; > + if (!s->keep_dar) > + height += ctx->inputs[i]->h; > + else > + height += ctx->inputs[i]->h / s->nb_inputs; > } > } else if (s->is_horizontal) { > + if (s->keep_dar) > + width /= s->nb_inputs; > for (i = 1; i < s->nb_inputs; i++) { > if (ctx->inputs[i]->h != height) { > av_log(ctx, AV_LOG_ERROR, "Input %d height %d does not match input %d height %d.\n", i, ctx->inputs[i]->h, 0, height); > return AVERROR(EINVAL); > } > - width += ctx->inputs[i]->w; > + if (!s->keep_dar) > + width += ctx->inputs[i]->w; > + else > + width += ctx->inputs[i]->w / s->nb_inputs; > } > } else { > char *arg, *p = s->layout, *saveptr = NULL; > @@ -339,6 +359,7 @@ static int activate(AVFilterContext *ctx) > #define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM > static const AVOption stack_options[] = { > { "inputs", "set number of inputs", OFFSET(nb_inputs), AV_OPT_TYPE_INT, {.i64=2}, 2, INT_MAX, .flags = FLAGS }, > + { "keep_dar", "stack with 1/nb_inputs of each inputs screen to keep the same DAR", OFFSET(keep_dar), AV_OPT_TYPE_INT, {.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 }, > { NULL }, > }; Keep DAR of which input i.e. what if the inputs have different DARs? The user can already emulate this by cropping inputs beforehand. Gyan
Not acceptable patch. Please do not merge. On 7/8/19, lance.lmwang@gmail.com <lance.lmwang@gmail.com> wrote: > From: Limin Wang <lance.lmwang@gmail.com> > > It's useful to compare two 4K videos quality side by side on 4K TV. > > Signed-off-by: Limin Wang <lance.lmwang@gmail.com> > --- > doc/filters.texi | 6 ++++++ > libavfilter/vf_stack.c | 31 ++++++++++++++++++++++++++----- > 2 files changed, 32 insertions(+), 5 deletions(-) > > diff --git a/doc/filters.texi b/doc/filters.texi > index ee6a93ffbf..675b02fc34 100644 > --- a/doc/filters.texi > +++ b/doc/filters.texi > @@ -11280,6 +11280,9 @@ The filter accept the following option: > @item inputs > Set number of input streams. Default is 2. > > +@item keep_dar > +stack with 1/nb_inputs of each inputs screen to keep the same DAR, Default > is 0. > + > @item shortest > If set to 1, force the output to terminate when the shortest input > terminates. Default value is 0. > @@ -18333,6 +18336,9 @@ The filter accept the following option: > @item inputs > Set number of input streams. Default is 2. > > +@item keep_dar > +stack with 1/nb_inputs of each inputs screen to keep the same DAR, Default > is 0. > + > @item shortest > If set to 1, force the output to terminate when the shortest input > terminates. Default value is 0. > diff --git a/libavfilter/vf_stack.c b/libavfilter/vf_stack.c > index 4d254e0013..9196b5b0b7 100644 > --- a/libavfilter/vf_stack.c > +++ b/libavfilter/vf_stack.c > @@ -44,6 +44,7 @@ typedef struct StackContext { > int is_vertical; > int is_horizontal; > int nb_planes; > + int keep_dar; > > StackItem *items; > AVFrame **frames; > @@ -123,7 +124,7 @@ static int process_frame(FFFrameSync *fs) > StackContext *s = fs->opaque; > AVFrame **in = s->frames; > AVFrame *out; > - int i, p, ret, offset[4] = { 0 }; > + int i, p, ret, offset[4] = { 0 }, in_offset[4] = { 0 }; > > for (i = 0; i < s->nb_inputs; i++) { > if ((ret = ff_framesync_get_frame(&s->fs, i, &in[i], 0)) < 0) > @@ -153,16 +154,25 @@ static int process_frame(FFFrameSync *fs) > > for (p = 0; p < s->nb_planes; p++) { > if (s->is_vertical) { > + if (s->keep_dar) { > + height[p] /= s->nb_inputs; > + in_offset[p] = i * height[p] * in[i]->linesize[p]; > + } > + > av_image_copy_plane(out->data[p] + offset[p] * > out->linesize[p], > out->linesize[p], > - in[i]->data[p], > + in[i]->data[p] + in_offset[p], > in[i]->linesize[p], > linesize[p], height[p]); > offset[p] += height[p]; > } else if (s->is_horizontal) { > + if (s->keep_dar) { > + linesize[p] /= s->nb_inputs; > + in_offset[p] = i * in[i]->linesize[p] / s->nb_inputs; > + } > av_image_copy_plane(out->data[p] + offset[p], > out->linesize[p], > - in[i]->data[p], > + in[i]->data[p] + in_offset[p], > in[i]->linesize[p], > linesize[p], height[p]); > offset[p] += linesize[p]; > @@ -197,20 +207,30 @@ static int config_output(AVFilterLink *outlink) > return AVERROR_BUG; > > if (s->is_vertical) { > + if (s->keep_dar) > + height /= s->nb_inputs; > for (i = 1; i < s->nb_inputs; i++) { > if (ctx->inputs[i]->w != width) { > av_log(ctx, AV_LOG_ERROR, "Input %d width %d does not match > input %d width %d.\n", i, ctx->inputs[i]->w, 0, width); > return AVERROR(EINVAL); > } > - height += ctx->inputs[i]->h; > + if (!s->keep_dar) > + height += ctx->inputs[i]->h; > + else > + height += ctx->inputs[i]->h / s->nb_inputs; > } > } else if (s->is_horizontal) { > + if (s->keep_dar) > + width /= s->nb_inputs; > for (i = 1; i < s->nb_inputs; i++) { > if (ctx->inputs[i]->h != height) { > av_log(ctx, AV_LOG_ERROR, "Input %d height %d does not > match input %d height %d.\n", i, ctx->inputs[i]->h, 0, height); > return AVERROR(EINVAL); > } > - width += ctx->inputs[i]->w; > + if (!s->keep_dar) > + width += ctx->inputs[i]->w; > + else > + width += ctx->inputs[i]->w / s->nb_inputs; > } > } else { > char *arg, *p = s->layout, *saveptr = NULL; > @@ -339,6 +359,7 @@ static int activate(AVFilterContext *ctx) > #define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM > static const AVOption stack_options[] = { > { "inputs", "set number of inputs", OFFSET(nb_inputs), AV_OPT_TYPE_INT, > {.i64=2}, 2, INT_MAX, .flags = FLAGS }, > + { "keep_dar", "stack with 1/nb_inputs of each inputs screen to keep the > same DAR", OFFSET(keep_dar), AV_OPT_TYPE_INT, {.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 }, > { NULL }, > }; > -- > 2.21.0 > > _______________________________________________ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel > > To unsubscribe, visit link above, or email > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
On Mon, Jul 08, 2019 at 05:44:06PM +0530, Gyan wrote: > > > On 08-07-2019 04:18 PM, lance.lmwang@gmail.com wrote: > >From: Limin Wang <lance.lmwang@gmail.com> > > > >It's useful to compare two 4K videos quality side by side on 4K TV. > > > >Signed-off-by: Limin Wang <lance.lmwang@gmail.com> > >--- > > doc/filters.texi | 6 ++++++ > > libavfilter/vf_stack.c | 31 ++++++++++++++++++++++++++----- > > 2 files changed, 32 insertions(+), 5 deletions(-) > > > >diff --git a/doc/filters.texi b/doc/filters.texi > >index ee6a93ffbf..675b02fc34 100644 > >--- a/doc/filters.texi > >+++ b/doc/filters.texi > >@@ -11280,6 +11280,9 @@ The filter accept the following option: > > @item inputs > > Set number of input streams. Default is 2. > >+@item keep_dar > >+stack with 1/nb_inputs of each inputs screen to keep the same DAR, Default is 0. > >+ > > @item shortest > > If set to 1, force the output to terminate when the shortest input > > terminates. Default value is 0. > >@@ -18333,6 +18336,9 @@ The filter accept the following option: > > @item inputs > > Set number of input streams. Default is 2. > >+@item keep_dar > >+stack with 1/nb_inputs of each inputs screen to keep the same DAR, Default is 0. > >+ > > @item shortest > > If set to 1, force the output to terminate when the shortest input > > terminates. Default value is 0. > >diff --git a/libavfilter/vf_stack.c b/libavfilter/vf_stack.c > >index 4d254e0013..9196b5b0b7 100644 > >--- a/libavfilter/vf_stack.c > >+++ b/libavfilter/vf_stack.c > >@@ -44,6 +44,7 @@ typedef struct StackContext { > > int is_vertical; > > int is_horizontal; > > int nb_planes; > >+ int keep_dar; > > StackItem *items; > > AVFrame **frames; > >@@ -123,7 +124,7 @@ static int process_frame(FFFrameSync *fs) > > StackContext *s = fs->opaque; > > AVFrame **in = s->frames; > > AVFrame *out; > >- int i, p, ret, offset[4] = { 0 }; > >+ int i, p, ret, offset[4] = { 0 }, in_offset[4] = { 0 }; > > for (i = 0; i < s->nb_inputs; i++) { > > if ((ret = ff_framesync_get_frame(&s->fs, i, &in[i], 0)) < 0) > >@@ -153,16 +154,25 @@ static int process_frame(FFFrameSync *fs) > > for (p = 0; p < s->nb_planes; p++) { > > if (s->is_vertical) { > >+ if (s->keep_dar) { > >+ height[p] /= s->nb_inputs; > >+ in_offset[p] = i * height[p] * in[i]->linesize[p]; > >+ } > >+ > > av_image_copy_plane(out->data[p] + offset[p] * out->linesize[p], > > out->linesize[p], > >- in[i]->data[p], > >+ in[i]->data[p] + in_offset[p], > > in[i]->linesize[p], > > linesize[p], height[p]); > > offset[p] += height[p]; > > } else if (s->is_horizontal) { > >+ if (s->keep_dar) { > >+ linesize[p] /= s->nb_inputs; > >+ in_offset[p] = i * in[i]->linesize[p] / s->nb_inputs; > >+ } > > av_image_copy_plane(out->data[p] + offset[p], > > out->linesize[p], > >- in[i]->data[p], > >+ in[i]->data[p] + in_offset[p], > > in[i]->linesize[p], > > linesize[p], height[p]); > > offset[p] += linesize[p]; > >@@ -197,20 +207,30 @@ static int config_output(AVFilterLink *outlink) > > return AVERROR_BUG; > > if (s->is_vertical) { > >+ if (s->keep_dar) > >+ height /= s->nb_inputs; > > for (i = 1; i < s->nb_inputs; i++) { > > if (ctx->inputs[i]->w != width) { > > av_log(ctx, AV_LOG_ERROR, "Input %d width %d does not match input %d width %d.\n", i, ctx->inputs[i]->w, 0, width); > > return AVERROR(EINVAL); > > } > >- height += ctx->inputs[i]->h; > >+ if (!s->keep_dar) > >+ height += ctx->inputs[i]->h; > >+ else > >+ height += ctx->inputs[i]->h / s->nb_inputs; > > } > > } else if (s->is_horizontal) { > >+ if (s->keep_dar) > >+ width /= s->nb_inputs; > > for (i = 1; i < s->nb_inputs; i++) { > > if (ctx->inputs[i]->h != height) { > > av_log(ctx, AV_LOG_ERROR, "Input %d height %d does not match input %d height %d.\n", i, ctx->inputs[i]->h, 0, height); > > return AVERROR(EINVAL); > > } > >- width += ctx->inputs[i]->w; > >+ if (!s->keep_dar) > >+ width += ctx->inputs[i]->w; > >+ else > >+ width += ctx->inputs[i]->w / s->nb_inputs; > > } > > } else { > > char *arg, *p = s->layout, *saveptr = NULL; > >@@ -339,6 +359,7 @@ static int activate(AVFilterContext *ctx) > > #define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM > > static const AVOption stack_options[] = { > > { "inputs", "set number of inputs", OFFSET(nb_inputs), AV_OPT_TYPE_INT, {.i64=2}, 2, INT_MAX, .flags = FLAGS }, > >+ { "keep_dar", "stack with 1/nb_inputs of each inputs screen to keep the same DAR", OFFSET(keep_dar), AV_OPT_TYPE_INT, {.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 }, > > { NULL }, > > }; > > Keep DAR of which input i.e. what if the inputs have different DARs? I'm using it for comparing two same video quality, it's not general for all condition anyway. > > The user can already emulate this by cropping inputs befoehand. Yes, we can use the crop filter to get the same function, however the command line isn't very direct to use and difficult to recall. > > Gyan > _______________________________________________ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel > > To unsubscribe, visit link above, or email > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
On Mon, Jul 08, 2019 at 01:52:16PM +0200, Moritz Barsnick wrote: > On Mon, Jul 08, 2019 at 18:48:46 +0800, lance.lmwang@gmail.com wrote: > > +@item keep_dar > > +stack with 1/nb_inputs of each inputs screen to keep the same DAR, Default is 0. > ^ > Probably "input's". Is screen the correct term here at all? (In three > places in the patch.) > > > + { "keep_dar", "stack with 1/nb_inputs of each inputs screen to keep the same DAR", OFFSET(keep_dar), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, .flags = FLAGS }, > > AV_OPT_TYPE_BOOL > Yes, I'll update for my local, thank for the review. > Not sure about the actual implementation, can't judge. > > Cheers, > Moritz > _______________________________________________ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel > > To unsubscribe, visit link above, or email > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
>> >> Keep DAR of which input i.e. what if the inputs have different DARs? > > I'm using it for comparing two same video quality, it's not general > for all condition anyway. > >> >> The user can already emulate this by cropping inputs befoehand. > Yes, we can use the crop filter to get the same function, however the > command line isn't very direct to use and difficult to recall. Write scripts then.
diff --git a/doc/filters.texi b/doc/filters.texi index ee6a93ffbf..675b02fc34 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -11280,6 +11280,9 @@ The filter accept the following option: @item inputs Set number of input streams. Default is 2. +@item keep_dar +stack with 1/nb_inputs of each inputs screen to keep the same DAR, Default is 0. + @item shortest If set to 1, force the output to terminate when the shortest input terminates. Default value is 0. @@ -18333,6 +18336,9 @@ The filter accept the following option: @item inputs Set number of input streams. Default is 2. +@item keep_dar +stack with 1/nb_inputs of each inputs screen to keep the same DAR, Default is 0. + @item shortest If set to 1, force the output to terminate when the shortest input terminates. Default value is 0. diff --git a/libavfilter/vf_stack.c b/libavfilter/vf_stack.c index 4d254e0013..9196b5b0b7 100644 --- a/libavfilter/vf_stack.c +++ b/libavfilter/vf_stack.c @@ -44,6 +44,7 @@ typedef struct StackContext { int is_vertical; int is_horizontal; int nb_planes; + int keep_dar; StackItem *items; AVFrame **frames; @@ -123,7 +124,7 @@ static int process_frame(FFFrameSync *fs) StackContext *s = fs->opaque; AVFrame **in = s->frames; AVFrame *out; - int i, p, ret, offset[4] = { 0 }; + int i, p, ret, offset[4] = { 0 }, in_offset[4] = { 0 }; for (i = 0; i < s->nb_inputs; i++) { if ((ret = ff_framesync_get_frame(&s->fs, i, &in[i], 0)) < 0) @@ -153,16 +154,25 @@ static int process_frame(FFFrameSync *fs) for (p = 0; p < s->nb_planes; p++) { if (s->is_vertical) { + if (s->keep_dar) { + height[p] /= s->nb_inputs; + in_offset[p] = i * height[p] * in[i]->linesize[p]; + } + av_image_copy_plane(out->data[p] + offset[p] * out->linesize[p], out->linesize[p], - in[i]->data[p], + in[i]->data[p] + in_offset[p], in[i]->linesize[p], linesize[p], height[p]); offset[p] += height[p]; } else if (s->is_horizontal) { + if (s->keep_dar) { + linesize[p] /= s->nb_inputs; + in_offset[p] = i * in[i]->linesize[p] / s->nb_inputs; + } av_image_copy_plane(out->data[p] + offset[p], out->linesize[p], - in[i]->data[p], + in[i]->data[p] + in_offset[p], in[i]->linesize[p], linesize[p], height[p]); offset[p] += linesize[p]; @@ -197,20 +207,30 @@ static int config_output(AVFilterLink *outlink) return AVERROR_BUG; if (s->is_vertical) { + if (s->keep_dar) + height /= s->nb_inputs; for (i = 1; i < s->nb_inputs; i++) { if (ctx->inputs[i]->w != width) { av_log(ctx, AV_LOG_ERROR, "Input %d width %d does not match input %d width %d.\n", i, ctx->inputs[i]->w, 0, width); return AVERROR(EINVAL); } - height += ctx->inputs[i]->h; + if (!s->keep_dar) + height += ctx->inputs[i]->h; + else + height += ctx->inputs[i]->h / s->nb_inputs; } } else if (s->is_horizontal) { + if (s->keep_dar) + width /= s->nb_inputs; for (i = 1; i < s->nb_inputs; i++) { if (ctx->inputs[i]->h != height) { av_log(ctx, AV_LOG_ERROR, "Input %d height %d does not match input %d height %d.\n", i, ctx->inputs[i]->h, 0, height); return AVERROR(EINVAL); } - width += ctx->inputs[i]->w; + if (!s->keep_dar) + width += ctx->inputs[i]->w; + else + width += ctx->inputs[i]->w / s->nb_inputs; } } else { char *arg, *p = s->layout, *saveptr = NULL; @@ -339,6 +359,7 @@ static int activate(AVFilterContext *ctx) #define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM static const AVOption stack_options[] = { { "inputs", "set number of inputs", OFFSET(nb_inputs), AV_OPT_TYPE_INT, {.i64=2}, 2, INT_MAX, .flags = FLAGS }, + { "keep_dar", "stack with 1/nb_inputs of each inputs screen to keep the same DAR", OFFSET(keep_dar), AV_OPT_TYPE_INT, {.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 }, { NULL }, };