avutil/film_grain_params: add av_film_grain_params_select()

Common utility function that can be used by all codecs to select the
right (any valid) film grain parameter set. In particular, this is
useful for AFGS1, which has support for multiple parameters.

However, it also performs parameter validation for H274.
This commit is contained in:
Niklas Haas
2024-03-15 12:15:11 +01:00
parent ea147f3b50
commit a9023377b2
4 changed files with 76 additions and 1 deletions

View File

@@ -17,6 +17,7 @@
*/
#include "film_grain_params.h"
#include "pixdesc.h"
AVFilmGrainParams *av_film_grain_params_alloc(size_t *size)
{
@@ -47,3 +48,63 @@ AVFilmGrainParams *av_film_grain_params_create_side_data(AVFrame *frame)
return fgp;
}
const AVFilmGrainParams *av_film_grain_params_select(const AVFrame *frame)
{
const AVFilmGrainParams *fgp, *best = NULL;
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format);
const AVFilmGrainAOMParams *aom;
const AVFilmGrainH274Params *h274;
int bit_depth_luma, bit_depth_chroma;
if (!desc)
return NULL;
/* There are no YUV formats with different bit depth per component,
* so just check both against the first component for simplicity */
bit_depth_luma = bit_depth_chroma = desc->comp[0].depth;
for (int i = 0; i < frame->nb_side_data; i++) {
if (frame->side_data[i]->type != AV_FRAME_DATA_FILM_GRAIN_PARAMS)
continue;
fgp = (const AVFilmGrainParams*)frame->side_data[i]->data;
if (fgp->width && fgp->width > frame->width ||
fgp->height && fgp->height > frame->height)
continue;
#define CHECK(a, b, unspec) \
do { \
if ((a) != (unspec) && (b) != (unspec) && (a) != (b)) \
continue; \
} while (0)
CHECK(fgp->bit_depth_luma, bit_depth_luma, 0);
CHECK(fgp->bit_depth_chroma, bit_depth_chroma, 0);
CHECK(fgp->color_range, frame->color_range, AVCOL_RANGE_UNSPECIFIED);
CHECK(fgp->color_primaries, frame->color_primaries, AVCOL_PRI_UNSPECIFIED);
CHECK(fgp->color_trc, frame->color_trc, AVCOL_TRC_UNSPECIFIED);
CHECK(fgp->color_space, frame->colorspace, AVCOL_SPC_UNSPECIFIED);
switch (fgp->type) {
case AV_FILM_GRAIN_PARAMS_NONE:
continue;
case AV_FILM_GRAIN_PARAMS_AV1:
aom = &fgp->codec.aom;
/* AOM FGS needs an exact match for the chroma resolution */
if (fgp->subsampling_x != desc->log2_chroma_w ||
fgp->subsampling_y != desc->log2_chroma_h)
continue;
break;
case AV_FILM_GRAIN_PARAMS_H274:
/* H.274 FGS can be adapted to any lower chroma resolution */
if (fgp->subsampling_x > desc->log2_chroma_w ||
fgp->subsampling_y > desc->log2_chroma_h)
continue;
break;
}
if (!best || best->width < fgp->width || best->height < fgp->height)
best = fgp;
}
return best;
}