Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
 help / color / mirror / Atom feed
From: mkver via ffmpeg-devel <ffmpeg-devel@ffmpeg.org>
To: ffmpeg-devel@ffmpeg.org
Cc: mkver <code@ffmpeg.org>
Subject: [FFmpeg-devel] [PATCH] avcodec/h274: Make H274FilmGrainDatabase a shared object (PR #20549)
Date: Thu, 18 Sep 2025 16:52:59 -0000
Message-ID: <175821438045.25.17531496873284204896@463a07221176> (raw)

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

                 reply	other threads:[~2025-09-18 16:53 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=175821438045.25.17531496873284204896@463a07221176 \
    --to=ffmpeg-devel@ffmpeg.org \
    --cc=code@ffmpeg.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

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