avfilter/vf_fieldhint: add support for duplicating fields

Fixes #7066
This commit is contained in:
Paul B Mahol 2019-10-19 13:08:37 +02:00
parent ce5274c138
commit 7056ddc0e0
2 changed files with 33 additions and 3 deletions

View File

@ -10121,6 +10121,8 @@ field and second number tells from which frame to pick up bottom field.
If optionally followed by @code{+} output frame will be marked as interlaced, If optionally followed by @code{+} output frame will be marked as interlaced,
else if followed by @code{-} output frame will be marked as progressive, else else if followed by @code{-} output frame will be marked as progressive, else
it will be marked same as input frame. it will be marked same as input frame.
If optionally followed by @code{t} output frame will use only top field, or in
case of @code{b} it will use only bottom field.
If line starts with @code{#} or @code{;} that line is skipped. If line starts with @code{#} or @code{;} that line is skipped.
@item mode @item mode

View File

@ -117,7 +117,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
AVFrame *out, *top, *bottom; AVFrame *out, *top, *bottom;
char buf[1024] = { 0 }; char buf[1024] = { 0 };
int64_t tf, bf; int64_t tf, bf;
char hint = '='; int tfactor = 0, bfactor = 1;
char hint = '=', field = '=';
int p; int p;
av_frame_free(&s->frame[0]); av_frame_free(&s->frame[0]);
@ -137,6 +138,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
s->line++; s->line++;
if (buf[0] == '#' || buf[0] == ';') { if (buf[0] == '#' || buf[0] == ';') {
continue; continue;
} else if (sscanf(buf, "%"PRId64",%"PRId64" %c %c", &tf, &bf, &hint, &field) == 4) {
;
} else if (sscanf(buf, "%"PRId64",%"PRId64" %c", &tf, &bf, &hint) == 3) { } else if (sscanf(buf, "%"PRId64",%"PRId64" %c", &tf, &bf, &hint) == 3) {
; ;
} else if (sscanf(buf, "%"PRId64",%"PRId64"", &tf, &bf) == 2) { } else if (sscanf(buf, "%"PRId64",%"PRId64"", &tf, &bf) == 2) {
@ -185,6 +188,23 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
av_assert0(0); av_assert0(0);
} }
switch (field) {
case 'b':
tfactor = 1;
top = bottom;
break;
case 't':
bfactor = 0;
bottom = top;
break;
case '=':
break;
default:
av_log(ctx, AV_LOG_ERROR, "Invalid field: %c.\n", field);
av_frame_free(&out);
return AVERROR(EINVAL);
}
switch (hint) { switch (hint) {
case '+': case '+':
out->interlaced_frame = 1; out->interlaced_frame = 1;
@ -194,6 +214,14 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
break; break;
case '=': case '=':
break; break;
case 'b':
tfactor = 1;
top = bottom;
break;
case 't':
bfactor = 0;
bottom = top;
break;
default: default:
av_log(ctx, AV_LOG_ERROR, "Invalid hint: %c.\n", hint); av_log(ctx, AV_LOG_ERROR, "Invalid hint: %c.\n", hint);
av_frame_free(&out); av_frame_free(&out);
@ -203,13 +231,13 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
for (p = 0; p < s->nb_planes; p++) { for (p = 0; p < s->nb_planes; p++) {
av_image_copy_plane(out->data[p], av_image_copy_plane(out->data[p],
out->linesize[p] * 2, out->linesize[p] * 2,
top->data[p], top->data[p] + tfactor * top->linesize[p],
top->linesize[p] * 2, top->linesize[p] * 2,
s->planewidth[p], s->planewidth[p],
(s->planeheight[p] + 1) / 2); (s->planeheight[p] + 1) / 2);
av_image_copy_plane(out->data[p] + out->linesize[p], av_image_copy_plane(out->data[p] + out->linesize[p],
out->linesize[p] * 2, out->linesize[p] * 2,
bottom->data[p] + bottom->linesize[p], bottom->data[p] + bfactor * bottom->linesize[p],
bottom->linesize[p] * 2, bottom->linesize[p] * 2,
s->planewidth[p], s->planewidth[p],
(s->planeheight[p] + 1) / 2); (s->planeheight[p] + 1) / 2);