[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: */