[FFmpeg-cvslog] avformat/lrcdec: support arbitrary precision timestamp

Kacper Michajłow git at videolan.org
Tue Aug 5 03:07:45 EEST 2025


ffmpeg | branch: release/7.0 | Kacper Michajłow <kasper93 at gmail.com> | Wed Jul 23 20:04:53 2025 +0200| [acf92ba7ab1e723f0dca4fc2bfc3b605d2ed2d15] | committer: Michael Niedermayer

avformat/lrcdec: support arbitrary precision timestamp

Apparently files with milliseconds exist in the wild. And since it cost
nothing to support arbitrary number of digits, extend format to support
that.

Depending on number of digits, the time base of fractional part is
changing. Most LRCs use 2 digits and centiseconds base, but subs with 3
digits and miliseconds exist too.

Set internal time base to AV_TIME_BASE, which in parcitice allows to
hold microseconds with 6 digits. Totally artificial, but who knows maybe
someone wants that.

Fixes: #11677

Signed-off-by: Kacper Michajłow <kasper93 at gmail.com>
(cherry picked from commit bc3cc0a6af44adc63caf4e5097fcfebd7a7475b4)
Signed-off-by: Michael Niedermayer <michael at niedermayer.cc>

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=acf92ba7ab1e723f0dca4fc2bfc3b605d2ed2d15
---

 libavformat/lrcdec.c | 18 ++++++++++--------
 1 file changed, 10 insertions(+), 8 deletions(-)

diff --git a/libavformat/lrcdec.c b/libavformat/lrcdec.c
index 5435a65b15..842a392468 100644
--- a/libavformat/lrcdec.c
+++ b/libavformat/lrcdec.c
@@ -78,7 +78,9 @@ static int64_t count_ts(const char *p)
 static int64_t read_ts(const char *p, int64_t *start)
 {
     int64_t offset = 0;
-    uint64_t mm, ss, cs;
+    uint64_t mm;
+    double ss;
+    char prefix[3];
 
     while(p[offset] == ' ' || p[offset] == '\t') {
         offset++;
@@ -86,14 +88,14 @@ static int64_t read_ts(const char *p, int64_t *start)
     if(p[offset] != '[') {
         return 0;
     }
-    if(sscanf(p, "[-%"SCNu64":%"SCNu64".%"SCNu64"]", &mm, &ss, &cs) == 3) {
-        /* Just in case negative pts, players may drop it but we won't. */
-        *start = -(int64_t) (mm*60000 + ss*1000 + cs*10);
-    } else if(sscanf(p, "[%"SCNu64":%"SCNu64".%"SCNu64"]", &mm, &ss, &cs) == 3) {
-        *start = mm*60000 + ss*1000 + cs*10;
-    } else {
+    int ret = sscanf(p, "%2[[-]%"SCNu64":%lf]", prefix, &mm, &ss);
+    if (ret != 3 || prefix[0] != '[') {
         return 0;
     }
+    *start = (mm * 60 + ss) * AV_TIME_BASE;
+    if (prefix[1] == '-') {
+        *start = - *start;
+    }
     do {
         offset++;
     } while(p[offset] && p[offset-1] != ']');
@@ -164,7 +166,7 @@ static int lrc_read_header(AVFormatContext *s)
     if(!st) {
         return AVERROR(ENOMEM);
     }
-    avpriv_set_pts_info(st, 64, 1, 1000);
+    avpriv_set_pts_info(st, 64, 1, AV_TIME_BASE);
     lrc->ts_offset = 0;
     st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
     st->codecpar->codec_id   = AV_CODEC_ID_TEXT;



More information about the ffmpeg-cvslog mailing list