mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2026-11-06 05:17:42 +00:00
The tables were computed from the exponents 2.6 and 2.2 written into the code. Build them from the lavu functions of SMPTE ST 428-1 and gamma 2.2 instead, normalized to the top code of each curve with the peaks in the matrix as before, so that the conversion can be set up for any tagged transfer. The values are unchanged. Signed-off-by: Kacper Michajłow <kasper93@gmail.com>
229 lines
7.2 KiB
C
229 lines
7.2 KiB
C
/*
|
|
* 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_FORMAT_H
|
|
#define SWSCALE_FORMAT_H
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include "libavutil/csp.h"
|
|
#include "libavutil/pixdesc.h"
|
|
|
|
#include "swscale.h"
|
|
|
|
static inline int ff_q_isnan(const AVRational a)
|
|
{
|
|
return !a.num && !a.den;
|
|
}
|
|
|
|
/* Like av_cmp_q but considers NaN == NaN */
|
|
static inline int ff_q_equal(const AVRational a, const AVRational b)
|
|
{
|
|
return (ff_q_isnan(a) && ff_q_isnan(b)) || !av_cmp_q(a, b);
|
|
}
|
|
|
|
static inline int ff_cie_xy_equal(const AVCIExy a, const AVCIExy b)
|
|
{
|
|
return ff_q_equal(a.x, b.x) && ff_q_equal(a.y, b.y);
|
|
}
|
|
|
|
static inline int ff_prim_equal(const AVPrimaryCoefficients *a,
|
|
const AVPrimaryCoefficients *b)
|
|
{
|
|
return ff_cie_xy_equal(a->r, b->r) &&
|
|
ff_cie_xy_equal(a->g, b->g) &&
|
|
ff_cie_xy_equal(a->b, b->b);
|
|
}
|
|
|
|
enum {
|
|
FIELD_TOP, /* top/even rows, or progressive */
|
|
FIELD_BOTTOM, /* bottom/odd rows */
|
|
};
|
|
|
|
/* The X'Y'Z' conversion: ST 428-1 codes to and from gamma 2.2 RGB */
|
|
#define XYZ_TRC AVCOL_TRC_SMPTE428
|
|
#define XYZ_RGB_TRC AVCOL_TRC_GAMMA22
|
|
|
|
typedef struct SwsColor {
|
|
enum AVColorPrimaries prim;
|
|
enum AVColorTransferCharacteristic trc;
|
|
AVPrimaryCoefficients gamut; /* mastering display gamut */
|
|
AVRational min_luma; /* minimum luminance in nits */
|
|
AVRational max_luma; /* maximum luminance in nits */
|
|
AVRational frame_peak; /* per-frame/scene peak luminance, or 0 */
|
|
AVRational frame_avg; /* per-frame/scene average luminance, or 0 */
|
|
} SwsColor;
|
|
|
|
static inline void ff_color_update_dynamic(SwsColor *dst, const SwsColor *src)
|
|
{
|
|
dst->frame_peak = src->frame_peak;
|
|
dst->frame_avg = src->frame_avg;
|
|
}
|
|
|
|
/* Subset of AVFrame parameters that uniquely determine pixel representation */
|
|
typedef struct SwsFormat {
|
|
int width, height;
|
|
int interlaced;
|
|
int field;
|
|
enum AVPixelFormat format;
|
|
enum AVPixelFormat hw_format;
|
|
enum AVColorRange range;
|
|
enum AVColorSpace csp;
|
|
enum AVChromaLocation loc;
|
|
const AVPixFmtDescriptor *desc; /* convenience */
|
|
SwsColor color;
|
|
} SwsFormat;
|
|
|
|
static inline void ff_fmt_clear(SwsFormat *fmt)
|
|
{
|
|
*fmt = (SwsFormat) {
|
|
.format = AV_PIX_FMT_NONE,
|
|
.range = AVCOL_RANGE_UNSPECIFIED,
|
|
.csp = AVCOL_SPC_UNSPECIFIED,
|
|
.loc = AVCHROMA_LOC_UNSPECIFIED,
|
|
.color = {
|
|
.prim = AVCOL_PRI_UNSPECIFIED,
|
|
.trc = AVCOL_TRC_UNSPECIFIED,
|
|
},
|
|
};
|
|
}
|
|
|
|
/**
|
|
* 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);
|
|
|
|
/**
|
|
* Subset of ff_fmt_from_frame() that sets default metadata for the format.
|
|
*/
|
|
void ff_fmt_from_pixfmt(enum AVPixelFormat pixfmt, SwsFormat *fmt);
|
|
|
|
static inline int ff_color_equal(const SwsColor *c1, const SwsColor *c2)
|
|
{
|
|
return c1->prim == c2->prim &&
|
|
c1->trc == c2->trc &&
|
|
ff_q_equal(c1->min_luma, c2->min_luma) &&
|
|
ff_q_equal(c1->max_luma, c2->max_luma) &&
|
|
ff_prim_equal(&c1->gamut, &c2->gamut);
|
|
}
|
|
|
|
/* Tests only the static components of a colorspace, ignoring per-frame data */
|
|
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->field == fmt2->field &&
|
|
fmt1->format == fmt2->format &&
|
|
fmt1->range == fmt2->range &&
|
|
fmt1->csp == fmt2->csp &&
|
|
fmt1->loc == fmt2->loc &&
|
|
ff_color_equal(&fmt1->color, &fmt2->color);
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
/* Internal helper to test a format for either the legacy backend or the
|
|
* ops-based backends, depending on `backends` (must be nonzero). */
|
|
int ff_sws_test_pixfmt_backend(const SwsBackend backends,
|
|
enum AVPixelFormat format, int output);
|
|
|
|
/**
|
|
* Statically test if a given format is supported by the given set of
|
|
* backends. This is a heuristic, which may have false positives if a
|
|
* specific backend does not actually implement all operations that would be
|
|
* required to support the format.
|
|
*/
|
|
int ff_test_fmt(SwsBackend backends, const SwsFormat *fmt, int output);
|
|
|
|
/* Returns true if the formats are incomplete, false otherwise */
|
|
bool ff_infer_colors(SwsColor *src, SwsColor *dst);
|
|
|
|
/**
|
|
* Infers an unspecified chroma location of a subsampled format from the
|
|
* other format. Returns true if a location was inferred, false otherwise.
|
|
*/
|
|
bool ff_infer_chroma_loc(SwsFormat *src, SwsFormat *dst);
|
|
|
|
/**
|
|
* Wrapper around av_chroma_location_enum_to_pos() that accounts for
|
|
* the per-field offset introduced by interlacing.
|
|
*/
|
|
void ff_sws_chroma_pos(const SwsFormat *fmt, bool *incomplete,
|
|
int *out_xpos, int *out_ypos);
|
|
|
|
typedef struct SwsOpList SwsOpList;
|
|
typedef struct SwsLut3D SwsLut3D;
|
|
|
|
/**
|
|
* Generate an SwsOpList defining a conversion from `src` to `dst`, with an
|
|
* optional 3DLUT for converting between gamuts.
|
|
*
|
|
* Returns 0 on success, or a negative error code on failure.
|
|
*/
|
|
int ff_sws_op_list_generate(SwsContext *ctx, const SwsFormat *src,
|
|
const SwsFormat *dst, const SwsLut3D *lut3d,
|
|
SwsOpList **out_ops, bool *incomplete);
|
|
|
|
/**
|
|
* Represents a view into a single field of frame data.
|
|
*
|
|
* Ostensibly, this is a (non-compatible) subset of AVFrame, however, the
|
|
* semantics are VERY different.
|
|
*
|
|
* Unlike AVFrame, this struct does NOT own any data references. All buffers
|
|
* referenced by a SwsFrame are managed externally. This merely represents
|
|
* a view into data.
|
|
*
|
|
* This struct is not refcounted, and may be freely copied onto the stack.
|
|
*/
|
|
typedef struct SwsFrame {
|
|
/* Data buffers and line stride */
|
|
uint8_t *data[4];
|
|
int linesize[4];
|
|
|
|
/**
|
|
* Dimensions and format
|
|
*/
|
|
int width, height;
|
|
enum AVPixelFormat format;
|
|
|
|
/**
|
|
* Pointer to the original AVFrame, if there is a 1:1 correspondence.
|
|
**/
|
|
const AVFrame *avframe;
|
|
} SwsFrame;
|
|
|
|
/**
|
|
* Initialize a SwsFrame from an AVFrame.
|
|
*/
|
|
void ff_sws_frame_from_avframe(SwsFrame *dst, const AVFrame *src);
|
|
|
|
#endif /* SWSCALE_FORMAT_H */
|