[FFmpeg-devel] [PATCH 2/2] avfilter/vf_tinterlace: support full-range YUV
Thomas Mundt
tmundt75 at gmail.com
Fri Dec 16 18:15:40 EET 2022
Am Fr., 9. Dez. 2022 um 01:28 Uhr schrieb Niklas Haas <ffmpeg at haasn.xyz>:
> From: Niklas Haas <git at haasn.dev>
>
> This filter, when used in the "pad" mode, currently makes the
> distinction between limited and full range solely by testing for YUVJ
> pixel formats at link setup time. This is deprecated and should be
> improved to perform the detection based on the per-frame metadata.
>
> In order to make this distinction based on color range metadata, which
> is only known at the time of filtering frames, for simplicity, we simply
> allocate two copies of the "black" frame - one for limited range and the
> other for full range metadata. This could be done more dynamically (e.g.
> as-needed or simply by blitting the appropriate pixel value directly),
> but this change is relatively simple and preserves the structure of the
> existing code.
>
> This commit actually fixes a bug in FATE - the new output is correct for
> the first time. The previous md5 ref was of a frame that incorrectly
> combined full-range pixel data with limited-range black fields. The
> corresponding result has been updated.
>
> Signed-off-by: Niklas Haas <git at haasn.dev>
> ---
> libavfilter/tinterlace.h | 2 +-
> libavfilter/vf_tinterlace.c | 26 ++++++++++++++------
> tests/ref/fate/filter-pixfmts-tinterlace_pad | 2 +-
> 3 files changed, 20 insertions(+), 10 deletions(-)
>
> diff --git a/libavfilter/tinterlace.h b/libavfilter/tinterlace.h
> index 4059ebf81a..37b6c10c08 100644
> --- a/libavfilter/tinterlace.h
> +++ b/libavfilter/tinterlace.h
> @@ -70,7 +70,7 @@ typedef struct TInterlaceContext {
> int vsub; ///< chroma vertical subsampling
> AVFrame *cur;
> AVFrame *next;
> - uint8_t *black_data[4]; ///< buffer used to fill padded lines
> + uint8_t *black_data[2][4]; ///< buffer used to fill padded lines
> (limited/full)
> int black_linesize[4];
> FFDrawContext draw;
> FFDrawColor color;
> diff --git a/libavfilter/vf_tinterlace.c b/libavfilter/vf_tinterlace.c
> index 7c54861de4..032629279a 100644
> --- a/libavfilter/vf_tinterlace.c
> +++ b/libavfilter/vf_tinterlace.c
> @@ -201,7 +201,8 @@ static av_cold void uninit(AVFilterContext *ctx)
>
> av_frame_free(&tinterlace->cur );
> av_frame_free(&tinterlace->next);
> - av_freep(&tinterlace->black_data[0]);
> + av_freep(&tinterlace->black_data[0][0]);
> + av_freep(&tinterlace->black_data[1][0]);
> }
>
> static int config_out_props(AVFilterLink *outlink)
> @@ -225,14 +226,22 @@ static int config_out_props(AVFilterLink *outlink)
> int ret;
> ff_draw_init(&tinterlace->draw, outlink->format, 0);
> ff_draw_color(&tinterlace->draw, &tinterlace->color, black);
> - if (ff_fmt_is_in(outlink->format, full_scale_yuvj_pix_fmts))
> - tinterlace->color.comp[0].u8[0] = 0;
> - ret = av_image_alloc(tinterlace->black_data,
> tinterlace->black_linesize,
> + /* limited range */
> + if (!ff_fmt_is_in(outlink->format, full_scale_yuvj_pix_fmts)) {
> + ret = av_image_alloc(tinterlace->black_data[0],
> tinterlace->black_linesize,
> + outlink->w, outlink->h, outlink->format,
> 16);
> + if (ret < 0)
> + return ret;
> + ff_fill_rectangle(&tinterlace->draw, &tinterlace->color,
> tinterlace->black_data[0],
> + tinterlace->black_linesize, 0, 0,
> outlink->w, outlink->h);
> + }
> + /* full range */
> + tinterlace->color.comp[0].u8[0] = 0;
> + ret = av_image_alloc(tinterlace->black_data[1],
> tinterlace->black_linesize,
> outlink->w, outlink->h, outlink->format, 16);
> if (ret < 0)
> return ret;
> -
> - ff_fill_rectangle(&tinterlace->draw, &tinterlace->color,
> tinterlace->black_data,
> + ff_fill_rectangle(&tinterlace->draw, &tinterlace->color,
> tinterlace->black_data[1],
> tinterlace->black_linesize, 0, 0, outlink->w,
> outlink->h);
> }
> if (tinterlace->flags & (TINTERLACE_FLAG_VLPF | TINTERLACE_FLAG_CVLPF)
> @@ -360,7 +369,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame
> *picref)
> AVFilterLink *outlink = ctx->outputs[0];
> TInterlaceContext *tinterlace = ctx->priv;
> AVFrame *cur, *next, *out;
> - int field, tff, ret;
> + int field, tff, full, ret;
>
> av_frame_free(&tinterlace->cur);
> tinterlace->cur = tinterlace->next;
> @@ -418,6 +427,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame
> *picref)
> out->sample_aspect_ratio = av_mul_q(cur->sample_aspect_ratio,
> av_make_q(2, 1));
>
> field = (1 + outlink->frame_count_in) & 1 ? FIELD_UPPER :
> FIELD_LOWER;
> + full = out->color_range == AVCOL_RANGE_JPEG ||
> ff_fmt_is_in(out->format, full_scale_yuvj_pix_fmts);
> /* copy upper and lower fields */
> copy_picture_field(tinterlace, out->data, out->linesize,
> (const uint8_t **)cur->data, cur->linesize,
> @@ -425,7 +435,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame
> *picref)
> FIELD_UPPER_AND_LOWER, 1, field,
> tinterlace->flags);
> /* pad with black the other field */
> copy_picture_field(tinterlace, out->data, out->linesize,
> - (const uint8_t **)tinterlace->black_data,
> tinterlace->black_linesize,
> + (const uint8_t
> **)tinterlace->black_data[full], tinterlace->black_linesize,
> inlink->format, inlink->w, inlink->h,
> FIELD_UPPER_AND_LOWER, 1, !field,
> tinterlace->flags);
> break;
> diff --git a/tests/ref/fate/filter-pixfmts-tinterlace_pad
> b/tests/ref/fate/filter-pixfmts-tinterlace_pad
> index 81a6961215..29321e542b 100644
> --- a/tests/ref/fate/filter-pixfmts-tinterlace_pad
> +++ b/tests/ref/fate/filter-pixfmts-tinterlace_pad
> @@ -1,4 +1,4 @@
> -gray 7ef396fecd8d1c9fe32173e4415ba671
> +gray 227a6fe36a31fbef80210823454131ea
> yuv410p 35bc11d0d32efc9e9a969be7d720f4e6
> yuv411p 17ef3cd22a74f7368b5e02f68779f294
> yuv420p 93d5b6a4c44d67e4d4447e8dd0bf3d33
> --
> 2.38.1
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request at ffmpeg.org with subject "unsubscribe".
>
Looks OK for me.
Regards,
Thomas
More information about the ffmpeg-devel
mailing list