[FFmpeg-devel] [PATCH 05/19] swscale/utils: add SwsFormat abstraction and helpers
Niklas Haas
ffmpeg at haasn.xyz
Mon Oct 14 12:57:02 EEST 2024
On Fri, 11 Oct 2024 00:26:52 +0200 Niklas Haas <ffmpeg at haasn.xyz> wrote:
> From: Niklas Haas <git at haasn.dev>
>
> Groups together all relevant color metadata from an AVFrame. While we could
> use AVFrame directly, keeping it a separate struct has three advantages:
>
> 1. Functions accepting an SwsFormat will definitely not care about the
> data pointers.
> 2. It clearly separates sanitized and raw metadata, since the function to
> construct an SwsFormat from an AVFrame will also sanitize.
> 3. It's slightly more lightweight to pass around.
>
> Move these into a new header file "utils.h" to avoid crowding
> swscale_internal.h even more, and also to solve a circular dependency issue
> down the line.
>
> Sponsored-by: Sovereign Tech Fund
> Signed-off-by: Niklas Haas <git at haasn.dev>
> ---
> libswscale/utils.c | 65 ++++++++++++++++++++++++++++++++++++++++++
> libswscale/utils.h | 70 ++++++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 135 insertions(+)
> create mode 100644 libswscale/utils.h
>
> diff --git a/libswscale/utils.c b/libswscale/utils.c
> index d80a3f0a80..074be65410 100644
> --- a/libswscale/utils.c
> +++ b/libswscale/utils.c
> @@ -1,4 +1,5 @@
> /*
> + * Copyright (C) 2024 Niklas Haas
> * Copyright (C) 2001-2003 Michael Niedermayer <michaelni at gmx.at>
> *
> * This file is part of FFmpeg.
> @@ -59,6 +60,7 @@
> #include "rgb2rgb.h"
> #include "swscale.h"
> #include "swscale_internal.h"
> +#include "utils.h"
>
> typedef struct FormatEntry {
> uint8_t is_supported_in :1;
> @@ -2647,3 +2649,66 @@ int ff_range_add(RangeList *rl, unsigned int start, unsigned int len)
>
> return 0;
> }
> +
> +/**
> + * This function also sanitizes and strips the input data, removing irrelevant
> + * fields for certain formats.
> + */
> +SwsFormat ff_fmt_from_frame(const AVFrame *frame)
> +{
> + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format);
> + SwsFormat fmt = {
> + .width = frame->width,
> + .height = frame->height,
> + .format = frame->format,
> + .range = frame->color_range,
> + .prim = frame->color_primaries,
> + .trc = frame->color_trc,
> + .csp = frame->colorspace,
> + .loc = frame->chroma_location,
> + .desc = desc,
> + };
> +
> + av_assert1(fmt.width > 0);
> + av_assert1(fmt.height > 0);
> + av_assert1(fmt.format != AV_PIX_FMT_NONE);
> + av_assert0(desc);
> + if (desc->flags & (AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_PAL | AV_PIX_FMT_FLAG_BAYER)) {
> + /* RGB-like family */
> + fmt.csp = AVCOL_SPC_RGB;
> + fmt.range = AVCOL_RANGE_JPEG;
> + } else if (desc->flags & AV_PIX_FMT_FLAG_XYZ) {
> + fmt.csp = AVCOL_SPC_UNSPECIFIED;
> + fmt.prim = AVCOL_PRI_SMPTE428;
> + fmt.trc = AVCOL_TRC_SMPTE428;
> + } else if (desc->nb_components < 3) {
> + /* Grayscale formats */
> + fmt.prim = AVCOL_PRI_UNSPECIFIED;
> + fmt.csp = AVCOL_SPC_UNSPECIFIED;
> + if (desc->flags & AV_PIX_FMT_FLAG_FLOAT)
> + fmt.range = AVCOL_RANGE_UNSPECIFIED;
> + else
> + fmt.range = AVCOL_RANGE_JPEG; // FIXME: this restriction should be lifted
I should point out that this recreates the swscale status quo behavior.
> + }
> +
> + switch (frame->format) {
> + case AV_PIX_FMT_YUVJ420P:
> + case AV_PIX_FMT_YUVJ411P:
> + case AV_PIX_FMT_YUVJ422P:
> + case AV_PIX_FMT_YUVJ444P:
> + case AV_PIX_FMT_YUVJ440P:
> + fmt.range = AVCOL_RANGE_JPEG;
> + break;
> + }
> +
> + if (!desc->log2_chroma_w && !desc->log2_chroma_h)
> + fmt.loc = AVCHROMA_LOC_UNSPECIFIED;
> +
> + if (frame->flags & AV_FRAME_FLAG_INTERLACED) {
> + av_assert1(!(fmt.height & 1));
I'm not sure about this assertion; I think it may need to go. The easiest way
to handle inherlaced odd sized frames would be to just discard the last line,
though with a little extra effort we could easily support them as two
differently sized fields.
Does anybody know how odd sized interlaced frames are handled in elsewhere?
> + fmt.height >>= 1;
> + fmt.interlaced = 1;
> + }
> +
> + return fmt;
> +}
> diff --git a/libswscale/utils.h b/libswscale/utils.h
> new file mode 100644
> index 0000000000..3d0b08ffe1
> --- /dev/null
> +++ b/libswscale/utils.h
> @@ -0,0 +1,70 @@
> +/*
> + * Copyright (C) 2024 Niklas Haas
> + *
> + * This file is part of FFmpeg.
> + *
> + * FFmpeg is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + *
> + * FFmpeg is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with FFmpeg; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
> + */
> +
> +#ifndef SWSCALE_UTILS_H
> +#define SWSCALE_UTILS_H
> +
> +#include "libavutil/pixdesc.h"
> +
> +#include "swscale.h"
> +
> +/* Subset of AVFrame parameters that uniquely determine pixel representation */
> +typedef struct SwsFormat {
> + int width, height;
> + int interlaced;
> + enum AVPixelFormat format;
> + enum AVColorRange range;
> + enum AVColorPrimaries prim;
> + enum AVColorTransferCharacteristic trc;
> + enum AVColorSpace csp;
> + enum AVChromaLocation loc;
> + const AVPixFmtDescriptor *desc; /* convenience */
> +} SwsFormat;
> +
> +/**
> + * This function also sanitizes and strips the input data, removing irrelevant
> + * fields for certain formats.
> + */
> +SwsFormat ff_fmt_from_frame(const AVFrame *frame);
> +
> +static inline int ff_fmt_equal(const SwsFormat *fmt1, const SwsFormat *fmt2)
> +{
> + return fmt1->width == fmt2->width &&
> + fmt1->height == fmt2->height &&
> + fmt1->interlaced == fmt2->interlaced &&
> + fmt1->format == fmt2->format &&
> + fmt1->range == fmt2->range &&
> + fmt1->prim == fmt2->prim &&
> + fmt1->trc == fmt2->trc &&
> + fmt1->csp == fmt2->csp &&
> + fmt1->loc == fmt2->loc;
> +}
> +
> +static inline int ff_fmt_align(enum AVPixelFormat fmt)
> +{
> + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt);
> + if (desc->flags & AV_PIX_FMT_FLAG_BAYER) {
> + return 2;
> + } else {
> + return 1 << desc->log2_chroma_h;
> + }
> +}
> +
> +#endif /* SWSCALE_UTILS_H */
> --
> 2.46.1
>
More information about the ffmpeg-devel
mailing list