diff --git a/libavcodec/aom_film_grain.c b/libavcodec/aom_film_grain.c
index e302567ba5..de4437fd16 100644
--- a/libavcodec/aom_film_grain.c
+++ b/libavcodec/aom_film_grain.c
@@ -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,47 @@ 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_film_grain_uninit_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))
             return AVERROR(ENOMEM);
-        memcpy(fgp, &s->sets[i], sizeof(*fgp));
     }
 
     return 0;
 }
 
+void ff_aom_film_grain_uninit_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,
diff --git a/libavcodec/aom_film_grain.h b/libavcodec/aom_film_grain.h
index 1f8c78f657..94cd9d9f67 100644
--- a/libavcodec/aom_film_grain.h
+++ b/libavcodec/aom_film_grain.h
@@ -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_film_grain_uninit_params(AVFilmGrainAFGS1Params *s);
+
 #endif /* AVCODEC_AOM_FILM_GRAIN_H */
diff --git a/libavcodec/h2645_sei.c b/libavcodec/h2645_sei.c
index a481dbca2c..33390d389d 100644
--- a/libavcodec/h2645_sei.c
+++ b/libavcodec/h2645_sei.c
@@ -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"
@@ -547,6 +548,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;
 }
 
@@ -918,7 +927,8 @@ 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_film_grain_uninit_params(&s->aom_film_grain);
 
     av_freep(&s->film_grain_characteristics);
 }
diff --git a/libavcodec/hevc/hevcdec.c b/libavcodec/hevc/hevcdec.c
index 900895598f..f2bdf6134e 100644
--- a/libavcodec/hevc/hevcdec.c
+++ b/libavcodec/hevc/hevcdec.c
@@ -4010,7 +4010,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;
