42#define SDR_DIFFUSE_WHITE 203.0
70#define GAINMAP_LUT_SIZE 1025
121#define OFFSET(x) offsetof(GainMapContext, x)
122#define FLAGS AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM
127 {
"luma",
"single gain channel, from luminance", 0,
AV_OPT_TYPE_CONST, { .i64 =
GAINMAP_LUMA }, 0, 0,
FLAGS, .unit =
"mode" },
128 {
"maxrgb",
"single gain channel, from max(R,G,B)", 0,
AV_OPT_TYPE_CONST, { .i64 =
GAINMAP_MAXRGB }, 0, 0,
FLAGS, .unit =
"mode" },
147 const int scale = 1 << 22;
166 s->quant_scale[ch] =
s->quant_offset[ch] = 0.0f;
170 s->quant_scale[ch] = 1.0f / (maxf - minf);
171 s->quant_offset[ch] = -minf *
s->quant_scale[ch];
174 s->params.channels[ch].gain_map_min =
min;
175 s->params.channels[ch].gain_map_max =
max;
183 s->quant_gamma[ch] =
av_q2d(gamma);
184 s->params.channels[ch].gamma = gamma;
186 ch,
s->quant_gamma[ch]);
193 if (
av_cmp_q(
s->gain_min,
s->gain_max) >= 0) {
200 if (!
s->gain_min.den)
202 if (!
s->gain_max.den)
208 "parameters from the input frame.\n");
213 .nb_channels =
s->nb_channels,
218 for (
int c = 0;
c <
s->nb_channels;
c++) {
219 struct AVGainMapChannel *ch = &
s->params.channels[
c];
220 ch->base_offset =
s->base_offset;
221 ch->alternate_offset =
s->alt_offset;
261 switch (
frame->color_trc) {
271 if (trc == tf->
trc && Lw == tf->
Lw)
311 return s ?
s :
"unknown";
320 if (!base_eotf || !alt_eotf) {
330 if (!base_desc || !alt_desc) {
346 for (
int i = 0;
i <
s->nb_channels;
i++) {
352 "Base and alternate renditions have the same peak "
353 "luminance (%g nits), gain map will be empty\n", base_lw);
367 double rgb2xyz[3][3];
369 for (
int i = 0;
i < 3;
i++)
372 s->convert =
base->color_primaries !=
alt->color_primaries;
375 double xyz2rgb[3][3], rgb2rgb[3][3];
380 for (
int i = 0;
i < 3;
i++)
381 for (
int j = 0; j < 3; j++)
382 s->rgb2rgb[
i][j] = (
float) rgb2rgb[
i][j];
384 memset(
s->rgb2rgb, 0,
sizeof(
s->rgb2rgb));
385 for (
int i = 0;
i < 3;
i++)
386 s->rgb2rgb[
i][
i] = 1.0f;
395 return gamma == 1.0f ? norm : powf(norm, gamma);
400 const float *restrict
const src[3],
int x,
int alt)
407 double rgbd[3] = {
src[0][x],
src[1][x],
src[2][x] };
408 tf->
eotf(tf->
Lw, 0.0, rgbd);
409 for (
int i = 0;
i < 3;
i++)
412 for (
int i = 0;
i < 3;
i++) {
414 const int ix = (int) fx;
415 const float lo = tf->
lut[ix];
416 const float hi = tf->
lut[ix + 1];
417 rgb[
i] = lo + (fx - ix) * (hi - lo);
424 for (
int i = 0;
i < 3;
i++) {
426 g *
s->rgb2rgb[
i][1] +
427 b *
s->rgb2rgb[
i][2], 0.0f);
430 for (
int i = 0;
i < 3;
i++)
445 const float *restrict
scale =
s->quant_scale;
446 const float *restrict
offset =
s->quant_offset;
447 const float *restrict gamma =
s->quant_gamma;
450 const float base_off =
av_q2d(
s->base_offset);
451 const float alt_off =
av_q2d(
s->alt_offset);
452 const float sign =
s->sign;
457 const int mode =
s->mode;
458 const int nb_ch =
s->nb_channels;
460 float min[3] = { FLT_MAX, FLT_MAX, FLT_MAX };
461 float max[3] = { -FLT_MAX, -FLT_MAX, -FLT_MAX };
462 double sum[3] = { 0.0, 0.0, 0.0 };
464 for (
int y = y_start; y < y_end; y++) {
465 const float *restrict b_row[3], *restrict a_row[3];
466 for (
int i = 0;
i < 3;
i++) {
468 b_row[
i] = (
const float *) (
base->data[p] + y *
base->linesize[p]);
469 a_row[
i] = (
const float *) (
alt->data[p] + y *
alt->linesize[p]);
472 float *restrict out_row[3];
473 for (
int i = 0;
i < nb_ch;
i++) {
475 out_row[
i] = (
float *) (
out->data[p] + y *
out->linesize[p]);
478 for (
int x = 0; x <
width; x++) {
479 float b[3],
a[3], gain[3];
483 #define GAIN(a, b) (sign * log2f(((a) + alt_off) / ((b) + base_off)))
488 gain[0] =
GAIN(max_a, max_b);
492 const float y_a =
s->rgb2y[0] *
a[0] +
s->rgb2y[1] *
a[1] +
s->rgb2y[2] *
a[2];
493 const float y_b =
s->rgb2y[0] *
b[0] +
s->rgb2y[1] *
b[1] +
s->rgb2y[2] *
b[2];
494 gain[0] =
GAIN(y_a, y_b);
498 gain[0] =
GAIN(
a[0],
b[0]);
499 gain[1] =
GAIN(
a[1],
b[1]);
500 gain[2] =
GAIN(
a[2],
b[2]);
506 for (
int i = 0;
i < nb_ch;
i++)
509 for (
int i = 0;
i < nb_ch;
i++) {
510 out_row[
i][x] = gain[
i];
520 for (
int i = 0; !
quant &&
i < 3;
i++) {
521 s->slice_min[jobnr][
i] =
min[
i];
522 s->slice_max[jobnr][
i] =
max[
i];
523 s->slice_sum[jobnr][
i] = sum[
i];
545 const float *restrict
scale =
s->quant_scale;
546 const float *restrict
offset =
s->quant_offset;
547 const float *restrict gamma =
s->quant_gamma;
552 const int nb_ch =
s->nb_channels;
554 for (
int y = y_start; y < y_end; y++) {
555 float *restrict out_row[3];
556 for (
int i = 0;
i < nb_ch;
i++) {
558 out_row[
i] = (
float *) (
out->data[p] + y *
out->linesize[p]);
561 for (
int x = 0; x <
width; x++) {
562 for (
int i = 0;
i < nb_ch;
i++)
573 float frame_min[3] = { FLT_MAX, FLT_MAX, FLT_MAX };
574 float frame_max[3] = { -FLT_MAX, -FLT_MAX, -FLT_MAX };
575 double frame_sum[3] = { 0.0, 0.0, 0.0 };
577 for (
int j = 0; j < nb_jobs; j++) {
578 for (
int i = 0;
i <
s->nb_channels;
i++) {
579 frame_min[
i] =
fminf(frame_min[
i],
s->slice_min[j][
i]);
580 frame_max[
i] =
fmaxf(frame_max[
i],
s->slice_max[j][
i]);
581 frame_sum[
i] +=
s->slice_sum[j][
i];
585 for (
int i = 0;
i <
s->nb_channels;
i++) {
598 const double mean = frame_sum[
i] / nb_pixels;
599 const double mean_quant =
s->quant_scale[
i] *
mean +
s->quant_offset[
i];
614 double gamma = log(0.5) / log(
av_clipd(mean_quant, 0.01, 0.99));
655 for (
int i = 0;
i <
s->nb_channels;
i++)
656 memset(
out->data[
i], 0,
out->height *
out->linesize[
i]);
660 const int nb_jobs =
FFMIN(outlink->
h,
s->nb_threads);
702 "Input dimensions must match (%dx%d != %dx%d)\n",
707 outlink->
w =
base->w;
708 outlink->
h =
base->h;
713 s->slice_min =
av_calloc(
s->nb_threads,
sizeof(*
s->slice_min));
714 s->slice_max =
av_calloc(
s->nb_threads,
sizeof(*
s->slice_max));
715 s->slice_sum =
av_calloc(
s->nb_threads,
sizeof(*
s->slice_sum));
716 if (!
s->slice_min || !
s->slice_max || !
s->slice_sum)
764 .p.priv_class = &gainmap_class,
766 .preinit = gainmap_framesync_preinit,
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
SwsAArch64OpImplParams params
static int query_formats(const AVFilterContext *ctx, AVFilterFormatsConfig **cfg_in, AVFilterFormatsConfig **cfg_out)
const FFFilter ff_vf_gainmap
static AVFormatContext * ctx
#define av_unreachable(msg)
Asserts that are used as compiler optimization hints depending upon ASSERT_LEVEL and NBDEBUG.
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
int ff_filter_execute(AVFilterContext *ctx, avfilter_action_func *func, void *arg, int *ret, int nb_jobs)
int ff_filter_get_nb_threads(AVFilterContext *ctx)
Get number of threads for current filter instance.
Main libavfilter public API header.
static void BS_FUNC skip(BSCTX *bc, unsigned int n)
Skip n bits in the buffer.
#define i(width, name, range_min, range_max)
#define fs(width, name, subs,...)
Colorspace value utility functions for libavutil.
static __device__ float ceil(float a)
static __device__ float floor(float a)
float fminf(float, float)
double fmax(double, double)
float fmaxf(float, float)
int(* init)(AVBSFContext *ctx)
static const uint8_t gbr_order[4]
static const char * unknown_if_null(const char *str)
static av_always_inline int process_frame(AVTextFormatContext *tfc, InputFile *ifile, AVFrame *frame, const AVPacket *pkt, int *packet_new)
int ff_framesync_configure(FFFrameSync *fs)
Configure a frame sync structure.
int ff_framesync_dualinput_get(FFFrameSync *fs, AVFrame **f0, AVFrame **f1)
int ff_framesync_activate(FFFrameSync *fs)
Examine the frames in the filter's input and try to produce output.
int ff_framesync_init_dualinput(FFFrameSync *fs, AVFilterContext *parent)
Initialize a frame sync structure for dualinput.
void ff_framesync_uninit(FFFrameSync *fs)
Free all memory currently allocated.
#define FRAMESYNC_DEFINE_CLASS(name, context, field)
@ AV_OPT_TYPE_CONST
Special option type for declaring named constants.
@ AV_OPT_TYPE_RATIONAL
Underlying C type is AVRational.
@ AV_OPT_TYPE_INT
Underlying C type is int.
#define AVFILTER_FLAG_SLICE_THREADS
The filter supports multithreading by splitting frames into multiple parts and processing them concur...
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
AVFrameSideData * av_frame_get_side_data(const AVFrame *frame, enum AVFrameSideDataType type)
void av_frame_side_data_remove_by_props(AVFrameSideData ***sd, int *nb_sd, int props)
Remove and free all side data instances that match any of the given side data properties.
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
@ AV_SIDE_DATA_PROP_COLOR_DEPENDENT
Side data depends on the video color space.
@ AV_FRAME_DATA_MASTERING_DISPLAY_METADATA
Mastering display metadata associated with a video frame.
#define AV_LOG_TRACE
Extremely verbose debugging, useful for libav* development.
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
#define AV_LOG_WARNING
Something somehow does not look correct.
#define AV_LOG_VERBOSE
Detailed information.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
const AVColorPrimariesDesc * av_csp_primaries_desc_from_id(enum AVColorPrimaries prm)
Retrieves a complete gamut description from an enum constant describing the color primaries.
void(* av_csp_eotf_function)(double Lw, double Lb, double c[3])
Function pointer representing an ITU EOTF transfer for a given reference display configuration.
av_csp_eotf_function av_csp_itu_eotf(enum AVColorTransferCharacteristic trc)
Returns the ITU EOTF corresponding to a given TRC.
int av_reduce(int *dst_num, int *dst_den, int64_t num, int64_t den, int64_t max)
Reduce a fraction.
static double av_q2d(AVRational a)
Convert an AVRational to a double.
static int av_cmp_q(AVRational a, AVRational b)
Compare two rationals.
AVRounding
Rounding methods.
@ AV_ROUND_DOWN
Round toward -infinity.
@ AV_ROUND_UP
Round toward +infinity.
@ AV_ROUND_NEAR_INF
Round to nearest and halfway cases away from zero.
static void scale(int *out, const int *in, const int w, const int h, const int shift)
static av_cold void uninit(AVBitStreamFilterContext *ctx)
static int activate(AVBitStreamFilterContext *ctx)
static int config_output(AVBitStreamFilterLink *outlink)
void ff_matrix_mul_3x3(double dst[3][3], const double src1[3][3], const double src2[3][3])
void ff_fill_rgb2xyz_table(const AVPrimaryCoefficients *coeffs, const AVWhitepointCoefficients *wp, double rgb2xyz[3][3])
void ff_matrix_invert_3x3(const double in[3][3], double out[3][3])
#define FILTER_INPUTS(array)
#define FILTER_OUTPUTS(array)
static int ff_slice_pos(int total, int jobnr, int nb_jobs)
Compute the boundary index for a slice when work of size total is split into nb_jobs slices.
#define FILTER_QUERY_FUNC2(func)
int av_gain_map_params_validate(const AVGainMapParams *p)
Returns >= 0 if the given AVGainMapParams struct contains valid data; or a negative AVERROR otherwise...
AVGainMapParams * av_gain_map_params_create_side_data(AVFrameSideData ***fsd, int *nb_sd)
Allocate and add an AVGainMapParams structure to an existing AVFrameSideData array as AV_FRAME_DATA_G...
common internal API header
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
void av_log_once(void *avcl, int initial_level, int subsequent_level, int *state, const char *fmt,...)
#define FFSWAP(type, a, b)
#define FFDIFFSIGN(x, y)
Comparator.
void * av_calloc(size_t nmemb, size_t size)
Memory handling functions.
const char * av_color_transfer_name(enum AVColorTransferCharacteristic transfer)
const char * av_color_primaries_name(enum AVColorPrimaries primaries)
#define AV_PIX_FMT_GBRPF32
@ AVCOL_RANGE_JPEG
Full range content.
#define AV_PIX_FMT_GRAYF32
AVPixelFormat
Pixel format.
AVColorTransferCharacteristic
Color Transfer Characteristic.
@ AVCOL_TRC_SMPTE170M
also ITU-R BT601-6 525 or 625 / ITU-R BT1358 525 or 625 / ITU-R BT1700 NTSC
@ AVCOL_TRC_SMPTE2084
SMPTE ST 2084 for 10-, 12-, 14- and 16-bit systems.
@ AVCOL_TRC_GAMMA22
also ITU-R BT470M / ITU-R BT1700 625 PAL & SECAM
@ AVCOL_TRC_BT1361_ECG
ITU-R BT1361 Extended Colour Gamut.
@ AVCOL_TRC_IEC61966_2_4
IEC 61966-2-4.
@ AVCOL_TRC_LINEAR
"Linear transfer characteristics"
@ AVCOL_TRC_GAMMA28
also ITU-R BT470BG
@ AVCOL_TRC_ARIB_STD_B67
ARIB STD-B67, known as "Hybrid log-gamma".
@ AVCOL_TRC_SMPTE428
SMPTE ST 428-1.
@ AVCOL_TRC_BT2020_12
ITU-R BT2020 for 12-bit system.
@ AVCOL_TRC_IEC61966_2_1
IEC 61966-2-1 (sRGB or sYCC)
@ AVCOL_TRC_BT2020_10
ITU-R BT2020 for 10-bit system.
@ AVCOL_TRC_BT709
also ITU-R BT1361
Describe the class of an AVClass context structure.
Struct that contains both white point location and primaries location, providing the complete descrip...
AVWhitepointCoefficients wp
AVPrimaryCoefficients prim
A link between two filters.
int w
agreed upon image width
int h
agreed upon image height
AVFilterContext * src
source filter
enum AVColorSpace colorspace
For non-YUV links, these are respectively set to fallback values (as appropriate for that colorspace)...
enum AVColorRange color_range
agreed upon YUV color range
A filter pad used for either input or output.
Structure to hold side data for an AVFrame.
This structure describes decoded (raw) audio or video data.
Parameters describing how to combine a gain map rendition with its base rendition to recover the alte...
Rational number (pair of numerator and denominator).
enum GainMapMeasure measure
av_csp_eotf_function eotf
float lut[GAINMAP_LUT_SIZE+1]
enum AVColorTransferCharacteristic trc
Used for passing data between threads.
static const float xyz2rgb[3][3]
static void setup_range(AVFilterContext *ctx, int ch, AVRational min, AVRational max)
static int slice_gain(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
static double frame_luminance(const AVFrame *frame)
static int slice_quant(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
static const AVFilterPad gainmap_outputs[]
static int slice_gain_quant(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
static const AVOption gainmap_options[]
static const char * unknown_if_null(const char *s)
static int setup_colorspace(AVFilterContext *ctx, const AVFrame *base, const AVFrame *alt)
@ GAINMAP_CSP_ALT
apply it in the alternate rendition's space
@ GAINMAP_CSP_BASE
apply the map in the base rendition's space
static av_always_inline float quantize(float gain, float scale, float offset, float gamma)
static av_always_inline int slice_internal(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs, int quant)
#define SDR_DIFFUSE_WHITE
static void update_eotf(GainMapEOTF *tf, enum AVColorTransferCharacteristic trc, av_csp_eotf_function eotf, double Lw)
@ GAINMAP_RGB
one channel per component
@ GAINMAP_LUMA
single channel, from the luminance
@ GAINMAP_MAXRGB
single channel, from max(R,G,B)
static int query_formats(const AVFilterContext *ctx, AVFilterFormatsConfig **cfg_in, AVFilterFormatsConfig **cfg_out)
static int activate(AVFilterContext *ctx)
static av_cold void uninit(AVFilterContext *ctx)
static void setup_gamma(AVFilterContext *ctx, int ch, AVRational gamma)
static void choose_quant_params(AVFilterContext *ctx, const AVFrame *out, int nb_jobs)
static int config_output(AVFilterLink *outlink)
static AVRational quantq(double x, enum AVRounding rnd)
static av_always_inline void get_pixel(const GainMapContext *s, float dst[3], const float *restrict const src[3], int x, int alt)
static int process_frame(FFFrameSync *fs)
static const AVFilterPad gainmap_inputs[]
static float mean(const float *input, int size)
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
static const uint8_t quant[64]