@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2024 Niklas Haas
* Copyright (C) 2001-2003 Michael Niedermayer <michaelni@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;
@@ -2653,3 +2655,65 @@ 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, int field)
+{
+ 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
+ }
+
+ 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) {
+ fmt.height = (fmt.height + (field == FIELD_TOP)) >> 1;
+ fmt.interlaced = 1;
+ }
+
+ return fmt;
+}
new file mode 100644
@@ -0,0 +1,75 @@
+/*
+ * 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"
+
+enum {
+ FIELD_TOP, /* top/even rows, or progressive */
+ FIELD_BOTTOM, /* bottom/odd rows */
+};
+
+/* 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, int field);
+
+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 */