Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
 help / color / mirror / Atom feed
* [FFmpeg-devel] [PR] avcodec/notchlc: lz4_decompress() avoid byte loops, try to work in blocks (PR #22287)
@ 2026-02-26  1:38 michaelni via ffmpeg-devel
  0 siblings, 0 replies; only message in thread
From: michaelni via ffmpeg-devel @ 2026-02-26  1:38 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: michaelni

PR #22287 opened by michaelni
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/22287
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/22287.patch

47720380 decicycles -> 34335598 decicycles


>From b14a62a84da87062bf9a1c63e06773b819cbf7b4 Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <michael@niedermayer.cc>
Date: Wed, 25 Feb 2026 16:57:01 +0100
Subject: [PATCH 1/2] avcodec/notchlc: Avoid clearing history in
 lz4_decompress()

instead of clearing history before "byte 0", we error out

clearing 64kb takes time, which this commit avoids
Benchmark with big_buck_bunny\ NotchLC\ Optimal\ Encoding\ 1920.mov shows no meassurable difference though

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
---
 libavcodec/notchlc.c | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/libavcodec/notchlc.c b/libavcodec/notchlc.c
index c28fddcea0..278499f450 100644
--- a/libavcodec/notchlc.c
+++ b/libavcodec/notchlc.c
@@ -79,8 +79,9 @@ static int lz4_decompress(AVCodecContext *avctx,
                           PutByteContext *pb)
 {
     unsigned reference_pos, delta, pos = 0;
-    uint8_t history[HISTORY_SIZE] = { 0 };
+    uint8_t history[HISTORY_SIZE];
     int match_length;
+    int wraped = 0;
 
     while (bytestream2_get_bytes_left(gb) > 0) {
         uint8_t token = bytestream2_get_byte(gb);
@@ -106,6 +107,7 @@ static int lz4_decompress(AVCodecContext *avctx,
                 if (pos == HISTORY_SIZE) {
                     bytestream2_put_buffer(pb, history, HISTORY_SIZE);
                     pos = 0;
+                    wraped = 1;
                 }
             }
         }
@@ -125,7 +127,13 @@ static int lz4_decompress(AVCodecContext *avctx,
                 match_length += current;
             } while (current == 255);
         }
-        reference_pos = (pos >= delta) ? (pos - delta) : (HISTORY_SIZE + pos - delta);
+        reference_pos = pos - delta;
+        if (pos < delta) {
+            if (!wraped)
+                return AVERROR_INVALIDDATA;
+            reference_pos += HISTORY_SIZE;
+        }
+
         if (pos + match_length < HISTORY_SIZE && reference_pos + match_length < HISTORY_SIZE) {
             if (pos >= reference_pos + match_length || reference_pos >= pos + match_length) {
                 memcpy(history + pos, history + reference_pos, match_length);
@@ -140,6 +148,7 @@ static int lz4_decompress(AVCodecContext *avctx,
                 if (pos == HISTORY_SIZE) {
                     bytestream2_put_buffer(pb, history, HISTORY_SIZE);
                     pos = 0;
+                    wraped = 1;
                 }
                 reference_pos %= HISTORY_SIZE;
             }
-- 
2.52.0


>From b889dbc8dc1451b75e4db67c3c3bd7d4eef7e067 Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <michael@niedermayer.cc>
Date: Wed, 25 Feb 2026 17:47:11 +0100
Subject: [PATCH 2/2] avcodec/notchlc: lz4_decompress() avoid byte loops, try
 to work in blocks

47720380 decicycles -> 34335598 decicycles
---
 libavcodec/notchlc.c | 44 ++++++++++++++++++++++----------------------
 1 file changed, 22 insertions(+), 22 deletions(-)

diff --git a/libavcodec/notchlc.c b/libavcodec/notchlc.c
index 278499f450..079e821d6c 100644
--- a/libavcodec/notchlc.c
+++ b/libavcodec/notchlc.c
@@ -98,18 +98,16 @@ static int lz4_decompress(AVCodecContext *avctx,
         if (bytestream2_get_bytes_left(gb) < num_literals)
             return AVERROR_INVALIDDATA;
 
-        if (pos + num_literals < HISTORY_SIZE) {
-            bytestream2_get_buffer(gb, history + pos, num_literals);
-            pos += num_literals;
-        } else {
-            while (num_literals-- > 0) {
-                history[pos++] = bytestream2_get_byte(gb);
-                if (pos == HISTORY_SIZE) {
-                    bytestream2_put_buffer(pb, history, HISTORY_SIZE);
-                    pos = 0;
-                    wraped = 1;
-                }
+        while (num_literals) {
+            int max_literals = FFMIN(num_literals, HISTORY_SIZE - pos);
+            bytestream2_get_buffer(gb, history + pos, max_literals);
+            pos += max_literals;
+            if (pos == HISTORY_SIZE) {
+                bytestream2_put_buffer(pb, history, HISTORY_SIZE);
+                pos = 0;
+                wraped = 1;
             }
+            num_literals -= max_literals;
         }
 
         if (bytestream2_get_bytes_left(gb) <= 0)
@@ -134,24 +132,26 @@ static int lz4_decompress(AVCodecContext *avctx,
             reference_pos += HISTORY_SIZE;
         }
 
-        if (pos + match_length < HISTORY_SIZE && reference_pos + match_length < HISTORY_SIZE) {
-            if (pos >= reference_pos + match_length || reference_pos >= pos + match_length) {
-                memcpy(history + pos, history + reference_pos, match_length);
-                pos += match_length;
+        while (match_length) {
+            int max_match;
+            if (reference_pos > pos) {
+                max_match = FFMIN(match_length, HISTORY_SIZE - reference_pos);
+                memmove(history + pos, history + reference_pos, max_match);
+                pos += max_match;
+                reference_pos += max_match;
+                if (reference_pos == HISTORY_SIZE) reference_pos = 0;
             } else {
-                while (match_length-- > 0)
-                    history[pos++] = history[reference_pos++];
-            }
-        } else {
-            while (match_length-- > 0) {
-                history[pos++] = history[reference_pos++];
+                max_match = FFMIN(match_length, HISTORY_SIZE - pos);
+                av_memcpy_backptr(history + pos, pos - reference_pos, max_match);
+                pos += max_match;
+                reference_pos += max_match;
                 if (pos == HISTORY_SIZE) {
                     bytestream2_put_buffer(pb, history, HISTORY_SIZE);
                     pos = 0;
                     wraped = 1;
                 }
-                reference_pos %= HISTORY_SIZE;
             }
+            match_length -= max_match;
         }
     }
 
-- 
2.52.0

_______________________________________________
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:[~2026-02-26  1:39 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-02-26  1:38 [FFmpeg-devel] [PR] avcodec/notchlc: lz4_decompress() avoid byte loops, try to work in blocks (PR #22287) michaelni 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