* [FFmpeg-devel] [PATCH] avcodec/h274: Make H274FilmGrainDatabase a shared object (PR #20549)
@ 2025-09-18 16:52 mkver via ffmpeg-devel
0 siblings, 0 replies; only message in thread
From: mkver via ffmpeg-devel @ 2025-09-18 16:52 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: mkver
PR #20549 opened by mkver
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20549
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20549.patch
Right now, the private contexts of every decoder supporting
H.274 film grain synthesis (namely H.264, HEVC and VVC)
contain a H274FilmGrainDatabase; said structure is very large
700442B before this commit) and takes up the overwhelming
majority of said contexts: Removing it reduces sizeof(H264Context)
by 92.88%, sizeof(HEVCContext) by 97.78% and sizeof(VVCContext)
by 99.86%. This is especially important for H.264 and HEVC
when using frame-threading.
The content of said film grain database does not depend on
any input parameter; it is shareable between all its users and
could be hardcoded in the binary (but isn't, because it is so huge).
This commit adds a database with static storage duration to h274.c
and uses it instead of the elements in the private contexts above.
It is still lazily initialized as-needed; a mutex is used
for the necessary synchronization. An alternative would be to use
an AV_ONCE to initialize the whole database either in the decoders'
init function (which would be wasteful given that most videos
don't use film grain synthesis) or in ff_h274_apply_film_grain().
>From 8569976d747f422c4ce88a0248525b60259541de Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Thu, 18 Sep 2025 17:57:16 +0200
Subject: [PATCH] avcodec/h274: Make H274FilmGrainDatabase a shared object
Right now, the private contexts of every decoder supporting
H.274 film grain synthesis (namely H.264, HEVC and VVC)
contain a H274FilmGrainDatabase; said structure is very large
700442B before this commit) and takes up the overwhelming
majority of said contexts: Removing it reduces sizeof(H264Context)
by 92.88%, sizeof(HEVCContext) by 97.78% and sizeof(VVCContext)
by 99.86%. This is especially important for H.264 and HEVC
when using frame-threading.
The content of said film grain database does not depend on
any input parameter; it is shareable between all its users and
could be hardcoded in the binary (but isn't, because it is so huge).
This commit adds a database with static storage duration to h274.c
and uses it instead of the elements in the private contexts above.
It is still lazily initialized as-needed; a mutex is used
for the necessary synchronization. An alternative would be to use
an AV_ONCE to initialize the whole database either in the decoders'
init function (which would be wasteful given that most videos
don't use film grain synthesis) or in ff_h274_apply_film_grain().
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
libavcodec/h264_picture.c | 4 ++--
libavcodec/h264dec.h | 3 ---
libavcodec/h274.c | 42 ++++++++++++++++++++++++++++++---------
libavcodec/h274.h | 11 ----------
libavcodec/hevc/hevcdec.c | 4 ++--
libavcodec/hevc/hevcdec.h | 3 ---
libavcodec/vvc/dec.c | 3 +--
libavcodec/vvc/dec.h | 1 -
8 files changed, 38 insertions(+), 33 deletions(-)
diff --git a/libavcodec/h264_picture.c b/libavcodec/h264_picture.c
index f5d2b31cd6..aa3d2629c8 100644
--- a/libavcodec/h264_picture.c
+++ b/libavcodec/h264_picture.c
@@ -30,10 +30,10 @@
#include "error_resilience.h"
#include "avcodec.h"
#include "h264dec.h"
+#include "h274.h"
#include "hwaccel_internal.h"
#include "mpegutils.h"
#include "libavutil/refstruct.h"
-#include "thread.h"
#include "threadframe.h"
void ff_h264_unref_picture(H264Picture *pic)
@@ -213,7 +213,7 @@ int ff_h264_field_end(H264Context *h, H264SliceContext *sl, int in_setup)
err = AVERROR_INVALIDDATA;
if (sd) // a decoding error may have happened before the side data could be allocated
- err = ff_h274_apply_film_grain(cur->f_grain, cur->f, &h->h274db,
+ err = ff_h274_apply_film_grain(cur->f_grain, cur->f,
(AVFilmGrainParams *) sd->data);
if (err < 0) {
av_log(h->avctx, AV_LOG_WARNING, "Failed synthesizing film "
diff --git a/libavcodec/h264dec.h b/libavcodec/h264dec.h
index 1df99015cc..74fd09dfaa 100644
--- a/libavcodec/h264dec.h
+++ b/libavcodec/h264dec.h
@@ -28,7 +28,6 @@
#ifndef AVCODEC_H264DEC_H
#define AVCODEC_H264DEC_H
-#include "libavutil/buffer.h"
#include "libavutil/mem_internal.h"
#include "cabac.h"
@@ -41,7 +40,6 @@
#include "h264dsp.h"
#include "h264pred.h"
#include "h264qpel.h"
-#include "h274.h"
#include "mpegutils.h"
#include "threadframe.h"
#include "videodsp.h"
@@ -344,7 +342,6 @@ typedef struct H264Context {
H264DSPContext h264dsp;
H264ChromaContext h264chroma;
H264QpelContext h264qpel;
- H274FilmGrainDatabase h274db;
H264Picture DPB[H264_MAX_PICTURE_COUNT];
H264Picture *cur_pic_ptr;
diff --git a/libavcodec/h274.c b/libavcodec/h274.c
index 332d0c2c52..81bbea7bfa 100644
--- a/libavcodec/h274.c
+++ b/libavcodec/h274.c
@@ -25,6 +25,8 @@
* @author Niklas Haas <ffmpeg@haasn.xyz>
*/
+#include <stdatomic.h>
+
#include "libavutil/avassert.h"
#include "libavutil/bswap.h"
#include "libavcodec/bswapdsp.h"
@@ -32,9 +34,23 @@
#include "libavutil/imgutils.h"
#include "libavutil/md5.h"
#include "libavutil/mem.h"
+#include "libavutil/thread.h"
#include "h274.h"
+typedef struct H274FilmGrainDatabase {
+ // Database of film grain patterns, lazily computed as-needed
+ int8_t db[13 /* h */][13 /* v */][64][64];
+ atomic_uint residency[6];
+
+ // Temporary buffer for slice generation
+ int16_t slice_tmp[64][64];
+} H274FilmGrainDatabase;
+
+static H274FilmGrainDatabase film_grain_db;
+
+static AVMutex mutex = AV_MUTEX_INITIALIZER;
+
static const int8_t Gaussian_LUT[2048+4];
static const uint32_t Seed_LUT[256];
static const int8_t R64T[64][64];
@@ -106,13 +122,23 @@ static void init_slice_c(int8_t out[64][64], uint8_t h, uint8_t v,
}
}
-static void init_slice(H274FilmGrainDatabase *database, uint8_t h, uint8_t v)
+static void init_slice(uint8_t h, uint8_t v)
{
- if (database->residency[h] & (1 << v))
+ unsigned bitpos = h * 13 + v;
+ unsigned res = atomic_load_explicit(&film_grain_db.residency[bitpos / 32],
+ memory_order_acquire);
+
+ if (res & (1U << (bitpos & 31)))
return;
- database->residency[h] |= (1 << v);
- init_slice_c(database->db[h][v], h, v, database->slice_tmp);
+ ff_mutex_lock(&mutex);
+ res = atomic_load_explicit(&film_grain_db.residency[bitpos / 32], memory_order_relaxed);
+ if (!(res & (1U << (bitpos & 31)))) {
+ init_slice_c(film_grain_db.db[h][v], h, v, film_grain_db.slice_tmp);
+ atomic_store_explicit(&film_grain_db.residency[bitpos / 32],
+ res | (1U << (bitpos & 31)), memory_order_release);
+ }
+ ff_mutex_unlock(&mutex);
}
// Computes the average of an 8x8 block
@@ -160,7 +186,6 @@ static void deblock_8x8_c(int8_t *out, const int out_stride)
// deblocking step (note that this implies writing to the previous block).
static av_always_inline void generate(int8_t *out, int out_stride,
const uint8_t *in, int in_stride,
- H274FilmGrainDatabase *database,
const AVFilmGrainH274Params *h274,
int c, int invert, int deblock,
int y_offset, int x_offset)
@@ -198,14 +223,14 @@ static av_always_inline void generate(int8_t *out, int out_stride,
h = av_clip(h274->comp_model_value[c][s][1], 2, 14) - 2;
v = av_clip(h274->comp_model_value[c][s][2], 2, 14) - 2;
- init_slice(database, h, v);
+ init_slice(h, v);
scale = h274->comp_model_value[c][s][0];
if (invert)
scale = -scale;
synth_grain_8x8_c(out, out_stride, scale, shift,
- &database->db[h][v][y_offset][x_offset]);
+ &film_grain_db.db[h][v][y_offset][x_offset]);
if (deblock)
deblock_8x8_c(out, out_stride);
@@ -220,7 +245,6 @@ static void add_8x8_clip_c(uint8_t *out, const uint8_t *a, const int8_t *b,
}
int ff_h274_apply_film_grain(AVFrame *out_frame, const AVFrame *in_frame,
- H274FilmGrainDatabase *database,
const AVFilmGrainParams *params)
{
AVFilmGrainH274Params h274 = params->codec.h274;
@@ -275,7 +299,7 @@ int ff_h274_apply_film_grain(AVFrame *out_frame, const AVFrame *in_frame,
for (int xx = 0; xx < 16 && x+xx < width; xx += 8) {
generate(grain + (y+yy) * grain_stride + (x+xx), grain_stride,
in + (y+yy) * in_stride + (x+xx), in_stride,
- database, &h274, c, invert, (x+xx) > 0,
+ &h274, c, invert, (x+xx) > 0,
y_offset + yy, x_offset + xx);
}
}
diff --git a/libavcodec/h274.h b/libavcodec/h274.h
index 055dd591d2..7bbc3e8aa7 100644
--- a/libavcodec/h274.h
+++ b/libavcodec/h274.h
@@ -30,16 +30,6 @@
#include "libavutil/film_grain_params.h"
-// Must be initialized to {0} prior to first usage
-typedef struct H274FilmGrainDatabase {
- // Database of film grain patterns, lazily computed as-needed
- int8_t db[13 /* h */][13 /* v */][64][64];
- uint16_t residency[13 /* h */]; // bit field of v
-
- // Temporary buffer for slice generation
- int16_t slice_tmp[64][64];
-} H274FilmGrainDatabase;
-
/**
* Check whether ff_h274_apply_film_grain() supports the given parameter combination.
*
@@ -61,7 +51,6 @@ static inline int ff_h274_film_grain_params_supported(int model_id, enum AVPixel
// ff_h274_film_grain_params_supported() coincide with actual values
// from the frames and params.
int ff_h274_apply_film_grain(AVFrame *out, const AVFrame *in,
- H274FilmGrainDatabase *db,
const AVFilmGrainParams *params);
typedef struct H274HashContext H274HashContext;
diff --git a/libavcodec/hevc/hevcdec.c b/libavcodec/hevc/hevcdec.c
index ba12d84474..b27d1d79e8 100644
--- a/libavcodec/hevc/hevcdec.c
+++ b/libavcodec/hevc/hevcdec.c
@@ -45,6 +45,7 @@
#include "codec_internal.h"
#include "decode.h"
#include "golomb.h"
+#include "h274.h"
#include "hevc.h"
#include "parse.h"
#include "hevcdec.h"
@@ -3496,8 +3497,7 @@ static int hevc_frame_end(HEVCContext *s, HEVCLayerContext *l)
av_assert0(0);
return AVERROR_BUG;
case AV_FILM_GRAIN_PARAMS_H274:
- ret = ff_h274_apply_film_grain(out->frame_grain, out->f,
- &s->h274db, fgp);
+ ret = ff_h274_apply_film_grain(out->frame_grain, out->f, fgp);
break;
case AV_FILM_GRAIN_PARAMS_AV1:
ret = ff_aom_apply_film_grain(out->frame_grain, out->f, fgp);
diff --git a/libavcodec/hevc/hevcdec.h b/libavcodec/hevc/hevcdec.h
index 911d5c3ae3..8394740c4b 100644
--- a/libavcodec/hevc/hevcdec.h
+++ b/libavcodec/hevc/hevcdec.h
@@ -32,9 +32,7 @@
#include "libavcodec/bswapdsp.h"
#include "libavcodec/cabac.h"
#include "libavcodec/dovi_rpu.h"
-#include "libavcodec/get_bits.h"
#include "libavcodec/h2645_parse.h"
-#include "libavcodec/h274.h"
#include "libavcodec/progressframe.h"
#include "libavcodec/videodsp.h"
@@ -537,7 +535,6 @@ typedef struct HEVCContext {
HEVCDSPContext hevcdsp;
VideoDSPContext vdsp;
BswapDSPContext bdsp;
- H274FilmGrainDatabase h274db;
/** used on BE to byteswap the lines for checksumming */
uint8_t *checksum_buf;
diff --git a/libavcodec/vvc/dec.c b/libavcodec/vvc/dec.c
index 6f52306080..b31fceef40 100644
--- a/libavcodec/vvc/dec.c
+++ b/libavcodec/vvc/dec.c
@@ -1091,8 +1091,7 @@ static int frame_end(VVCContext *s, VVCFrameContext *fc)
av_assert0(0);
return AVERROR_BUG;
case AV_FILM_GRAIN_PARAMS_H274:
- ret = ff_h274_apply_film_grain(fc->ref->frame_grain, fc->ref->frame,
- &s->h274db, fgp);
+ ret = ff_h274_apply_film_grain(fc->ref->frame_grain, fc->ref->frame, fgp);
if (ret < 0)
return ret;
break;
diff --git a/libavcodec/vvc/dec.h b/libavcodec/vvc/dec.h
index 5f8065b38b..bfb8a2e20d 100644
--- a/libavcodec/vvc/dec.h
+++ b/libavcodec/vvc/dec.h
@@ -222,7 +222,6 @@ typedef struct VVCContext {
CodedBitstreamFragment current_frame;
VVCParamSets ps;
- H274FilmGrainDatabase h274db;
int temporal_id; ///< temporal_id_plus1 - 1
int poc_tid0;
--
2.49.1
_______________________________________________
ffmpeg-devel mailing list -- ffmpeg-devel@ffmpeg.org
To unsubscribe send an email to ffmpeg-devel-leave@ffmpeg.org
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2025-09-18 16:53 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-09-18 16:52 [FFmpeg-devel] [PATCH] avcodec/h274: Make H274FilmGrainDatabase a shared object (PR #20549) mkver via ffmpeg-devel
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
This inbox may be cloned and mirrored by anyone:
git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git
# If you have public-inbox 1.1+ installed, you may
# initialize and index your mirror using the following commands:
public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
ffmpegdev@gitmailbox.com
public-inbox-index ffmpegdev
Example config snippet for mirrors.
AGPL code for this site: git clone https://public-inbox.org/public-inbox.git