avcodec/aom_film_grain: allocate film grain metadata dynamically

This removes the ABI breaking use of sizeof(AVFilmGrainParams), and achieves the
same size reduction to decoder structs as 08b1bffa49.

Signed-off-by: James Almer <jamrial@gmail.com>
This commit is contained in:
James Almer 2024-10-24 23:09:23 -03:00
parent 24141a7140
commit fd4a2c9b02
4 changed files with 55 additions and 13 deletions

View file

@ -26,7 +26,9 @@
*/
#include "libavutil/avassert.h"
#include "libavutil/buffer.h"
#include "libavutil/imgutils.h"
#include "libavutil/mem.h"
#include "aom_film_grain.h"
#include "get_bits.h"
@ -124,7 +126,7 @@ int ff_aom_parse_film_grain_sets(AVFilmGrainAFGS1Params *s,
{
GetBitContext gbc, *gb = &gbc;
AVFilmGrainAOMParams *aom;
AVFilmGrainParams *fgp, *ref = NULL;
AVFilmGrainParams *fgp = NULL, *ref = NULL;
int ret, num_sets, n, i, uv, num_y_coeffs, update_grain, luma_only;
ret = init_get_bits8(gb, payload, payload_size);
@ -135,28 +137,38 @@ int ff_aom_parse_film_grain_sets(AVFilmGrainAFGS1Params *s,
if (!s->enable)
return 0;
for (int i = 0; i < FF_ARRAY_ELEMS(s->sets); i++)
av_buffer_unref(&s->sets[i]);
skip_bits(gb, 4); // reserved
num_sets = get_bits(gb, 3) + 1;
for (n = 0; n < num_sets; n++) {
int payload_4byte, payload_size, set_idx, apply_units_log2, vsc_flag;
int predict_scaling, predict_y_scaling, predict_uv_scaling[2];
int payload_bits, start_position;
size_t fgp_size;
start_position = get_bits_count(gb);
payload_4byte = get_bits1(gb);
payload_size = get_bits(gb, payload_4byte ? 2 : 8);
set_idx = get_bits(gb, 3);
fgp = &s->sets[set_idx];
fgp = av_film_grain_params_alloc(&fgp_size);
if (!fgp)
goto error;
aom = &fgp->codec.aom;
fgp->type = get_bits1(gb) ? AV_FILM_GRAIN_PARAMS_AV1 : AV_FILM_GRAIN_PARAMS_NONE;
if (!fgp->type)
if (!fgp->type) {
av_freep(&fgp);
continue;
}
fgp->seed = get_bits(gb, 16);
update_grain = get_bits1(gb);
if (!update_grain)
if (!update_grain) {
av_freep(&fgp);
continue;
}
apply_units_log2 = get_bits(gb, 4);
fgp->width = get_bits(gb, 12) << apply_units_log2;
@ -330,32 +342,49 @@ int ff_aom_parse_film_grain_sets(AVFilmGrainAFGS1Params *s,
if (payload_bits > payload_size * 8)
goto error;
skip_bits(gb, payload_size * 8 - payload_bits);
av_buffer_unref(&s->sets[set_idx]);
s->sets[set_idx] = av_buffer_create((uint8_t *)fgp, fgp_size, NULL, NULL, 0);
if (!s->sets[set_idx])
goto error;
}
return 0;
error:
memset(s, 0, sizeof(*s));
av_free(fgp);
ff_aom_uninit_film_grain_params(s);
return AVERROR_INVALIDDATA;
}
int ff_aom_attach_film_grain_sets(const AVFilmGrainAFGS1Params *s, AVFrame *frame)
{
AVFilmGrainParams *fgp;
if (!s->enable)
return 0;
for (int i = 0; i < FF_ARRAY_ELEMS(s->sets); i++) {
if (s->sets[i].type != AV_FILM_GRAIN_PARAMS_AV1)
AVBufferRef *buf;
if (!s->sets[i])
continue;
fgp = av_film_grain_params_create_side_data(frame);
if (!fgp)
buf = av_buffer_ref(s->sets[i]);
if (!buf || !av_frame_new_side_data_from_buf(frame,
AV_FRAME_DATA_FILM_GRAIN_PARAMS, buf)) {
av_buffer_unref(&buf);
return AVERROR(ENOMEM);
memcpy(fgp, &s->sets[i], sizeof(*fgp));
}
}
return 0;
}
void ff_aom_uninit_film_grain_params(AVFilmGrainAFGS1Params *s)
{
for (int i = 0; i < FF_ARRAY_ELEMS(s->sets); i++)
av_buffer_unref(&s->sets[i]);
s->enable = 0;
}
// Taken from the AV1 spec. Range is [-2048, 2047], mean is 0 and stddev is 512
static const int16_t gaussian_sequence[2048] = {
56, 568, -180, 172, 124, -84, 172, -64, -900, 24, 820,

View file

@ -28,11 +28,12 @@
#ifndef AVCODEC_AOM_FILM_GRAIN_H
#define AVCODEC_AOM_FILM_GRAIN_H
#include "libavutil/buffer.h"
#include "libavutil/film_grain_params.h"
typedef struct AVFilmGrainAFGS1Params {
int enable;
AVFilmGrainParams sets[8];
AVBufferRef *sets[8];
} AVFilmGrainAFGS1Params;
// Synthesizes film grain on top of `in` and stores the result to `out`. `out`
@ -48,4 +49,7 @@ int ff_aom_parse_film_grain_sets(AVFilmGrainAFGS1Params *s,
// Attach all valid film grain param sets to `frame`.
int ff_aom_attach_film_grain_sets(const AVFilmGrainAFGS1Params *s, AVFrame *frame);
// Free all allocations in `s` and zero the entire struct.
void ff_aom_uninit_film_grain_params(AVFilmGrainAFGS1Params *s);
#endif /* AVCODEC_AOM_FILM_GRAIN_H */

View file

@ -26,6 +26,7 @@
#include "config_components.h"
#include "libavutil/ambient_viewing_environment.h"
#include "libavutil/buffer.h"
#include "libavutil/display.h"
#include "libavutil/hdr_dynamic_metadata.h"
#include "libavutil/film_grain_params.h"
@ -542,6 +543,14 @@ int ff_h2645_sei_ctx_replace(H2645SEI *dst, const H2645SEI *src)
}
}
for (unsigned i = 0; i < FF_ARRAY_ELEMS(dst->aom_film_grain.sets); i++) {
ret = av_buffer_replace(&dst->aom_film_grain.sets[i],
src->aom_film_grain.sets[i]);
if (ret < 0)
return ret;
}
dst->aom_film_grain.enable = src->aom_film_grain.enable;
return 0;
}
@ -913,5 +922,6 @@ void ff_h2645_sei_reset(H2645SEI *s)
s->ambient_viewing_environment.present = 0;
s->mastering_display.present = 0;
s->content_light.present = 0;
s->aom_film_grain.enable = 0;
ff_aom_uninit_film_grain_params(&s->aom_film_grain);
}

View file

@ -4004,7 +4004,6 @@ static int hevc_update_thread_context(AVCodecContext *dst,
s->sei.common.alternative_transfer = s0->sei.common.alternative_transfer;
s->sei.common.mastering_display = s0->sei.common.mastering_display;
s->sei.common.content_light = s0->sei.common.content_light;
s->sei.common.aom_film_grain = s0->sei.common.aom_film_grain;
s->sei.tdrdi = s0->sei.tdrdi;
return 0;