[PATCH] Recognize the documented unknown sample-count sentinel

"Maya R. Odinezenko via Lame-dev" <[email protected]> Fri, 17 Jul 2026 15:17:15 -0400
Newsgroups gmane.comp.audio.mp3.lame
Message-ID <CAFCgL3mb+GCvN=_B5HexgBwMyjme40AN_DqW6sJtww-VOzpOaQ@mail.gmail.com>
Hello,

On a 64-bit (LP64) build, two places that should detect an unknown
num_samples never do. Both test the count against (0ul-1ul), but the
documented default and the "unknown" sentinel used elsewhere in the
code is 2^32-1 (lame.h documents "default = 2^32-1"; MAX_U_32_NUM in
util.h and the frontend). (0ul-1ul) equals that only where long is
32-bit, so on LP64 the unknown case is missed:

  - lame_get_totalframes() returns an estimate instead of 0
    (libmp3lame/set_get.c), so encoding an unknown-length stream --
    e.g. from a pipe -- shows a bogus ~3.7M-frame total with a
    phantom ETA; and
  - the decoder progress display makes the same wrong comparison
    (frontend/timestatus.c).

The patch recognizes MAX_U_32_NUM in both places and keeps the
existing (0ul-1ul) comparison, so behavior where long is 32-bit is
unchanged, and counts legitimately larger than the sentinel (possible
on LP64, e.g. the raw-input file-size fallback for very large files)
keep their real estimates.

Tested on Apple Silicon (LP64): the sentinel and the default now
report unknown; 53113, 0x100000000 and ULONG_MAX behave as before;
encoded output is byte-identical.

The patch is against current trunk (r6597).

Maya

-- >8 --
From: Maya <[email protected]>
Date: Fri, 17 Jul 2026 14:30:00 -0400
Subject: [PATCH] Recognize the documented unknown sample-count sentinel

The frontend and libmp3lame test num_samples against (0ul-1ul) to
detect "length unknown", but the documented default and the unknown
sentinel used elsewhere in the code is 2^32-1 (lame.h: "default =
2^32-1"; MAX_U_32_NUM in util.h and the frontend). The two values
coincide only where long is 32 bits, so on LP64 the unknown case is
never recognized: lame_get_totalframes() returns an estimate instead
of 0, and stdin encodes show a bogus ~3.7M-frame total with a phantom
ETA.

Recognize MAX_U_32_NUM in both places. The (0ul-1ul) comparison is
kept to preserve existing LP64 behavior. Values merely larger than the
sentinel -- legitimate on LP64, e.g. the raw-input file-size fallback
for very large files -- keep their real estimates.

Tested on Apple Silicon (LP64): the sentinel and the default now
report unknown; 53113, 0x100000000 and ULONG_MAX behave as before;
encoded output is byte-identical. Where long is 32 bits the new test
collapses to the old one by value equality.
---
 frontend/timestatus.c | 10 +++++++++-
 libmp3lame/set_get.c  |  7 ++++++-
 2 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/frontend/timestatus.c b/frontend/timestatus.c
index d5b33fc..e6f1a71 100644
--- a/frontend/timestatus.c
+++ b/frontend/timestatus.c
@@ -47,6 +47,12 @@
 #include "brhist.h"
 #include "console.h"

+/* num_samples uses 2^32-1 as its "unknown" sentinel (lame.h documents it as
+   the default); libmp3lame's util.h defines the same name, so guard it */
+#ifndef MAX_U_32_NUM
+#define MAX_U_32_NUM 0xFFFFFFFF
+#endif
+
 #ifdef WITH_DMALLOC
 #include <dmalloc.h>
 #endif
@@ -373,7 +379,9 @@ decoder_progress_init(unsigned long n, int framesize)
     dp->frame_ctr = 0;
     dp->framesize = framesize;
     dp->samples = 0;
-    if (n != (0ul-1ul)) {
+    /* also recognize the documented unknown sentinel; the (0ul-1ul) test
+       alone matches it only where long is 32-bit */
+    if (n != MAX_U_32_NUM && n != (0ul-1ul)) {
         if (framesize == 576 || framesize == 1152) {
             dp->frames_total = calcNumBlocks(n, framesize);
             dp->samples = 576 + calcEndPadding(n, framesize);
diff --git a/libmp3lame/set_get.c b/libmp3lame/set_get.c
index 1ee60f6..76b99c1 100644
--- a/libmp3lame/set_get.c
+++ b/libmp3lame/set_get.c
@@ -2136,7 +2136,12 @@ lame_get_totalframes(const lame_global_flags * gfp)
             unsigned long end_padding = 0;
             int frames = 0;

-            if (pcm_samples_to_encode == (0ul-1ul))
+            /* compare against the documented unknown sentinel (lame.h:
+               default = 2^32-1); the (0ul-1ul) test alone matches it only
+               where long is 32-bit, and is kept to preserve existing LP64
+               behavior */
+            if (pcm_samples_to_encode == MAX_U_32_NUM
+                || pcm_samples_to_encode == (0ul-1ul))
                 return 0; /* unknown */

             /* estimate based on user set num_samples: */