From ba2441b378eaa0121fbf60bcc540a741c4424939 Mon Sep 17 00:00:00 2001 From: Ryan Francesconi Date: Wed, 15 Apr 2026 09:29:52 -0700 Subject: [PATCH] corrected nanosecond unit change -> milliseconds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit taglib/mp4/mp4chapterlist.h • start​Time doc comment: 100​-nanosecond units → milliseconds taglib/mp4/mp4chapterlist.cpp • render​Chpl​Data: from​Long​Long(ch​.start​Time) → from​Long​Long(ch​.start​Time * 10000​LL) • parse​Chpl​Data: ch​.start​Time = start​Time → ch​.start​Time = start​Time100ns / 10000​LL taglib/mp4/mp4qtchapterlist.cpp • read: current​Time * 10000000​.0 / timescale → current​Time * 1000​.0 / timescale • build​Stts lambda: time100ns * timescale / 10000000​.0 → time​Ms * timescale / 1000​.0 tests/test_mp4.cpp • All start​Time assignments and assertions divided by 10,000 (e.g. 300000000​LL → 30000​LL) --- taglib/mp4/mp4chapterlist.cpp | 8 ++--- taglib/mp4/mp4chapterlist.h | 2 +- taglib/mp4/mp4qtchapterlist.cpp | 10 +++---- tests/test_mp4.cpp | 52 ++++++++++++++++----------------- 4 files changed, 36 insertions(+), 36 deletions(-) diff --git a/taglib/mp4/mp4chapterlist.cpp b/taglib/mp4/mp4chapterlist.cpp index dca06cda..606de55b 100644 --- a/taglib/mp4/mp4chapterlist.cpp +++ b/taglib/mp4/mp4chapterlist.cpp @@ -149,8 +149,8 @@ namespace if(i++ >= count) break; - // Start time: 8 bytes big-endian - data.append(ByteVector::fromLongLong(ch.startTime)); + // Start time: 8 bytes big-endian, on-disk format is 100-nanosecond units + data.append(ByteVector::fromLongLong(ch.startTime * 10000LL)); // Title: 1-byte length + UTF-8 bytes (max 255 bytes) ByteVector titleBytes = ch.title.data(String::UTF8); @@ -188,7 +188,7 @@ namespace unsigned int count = static_cast(data[pos++]); for(unsigned int i = 0; i < count && pos + 9 <= data.size(); ++i) { - long long startTime = data.toLongLong(pos); + long long startTime100ns = data.toLongLong(pos); pos += 8; unsigned int titleLen = static_cast(data[pos++]); @@ -200,7 +200,7 @@ namespace } MP4::Chapter ch; - ch.startTime = startTime; + ch.startTime = startTime100ns / 10000LL; ch.title = title; chapters.append(ch); } diff --git a/taglib/mp4/mp4chapterlist.h b/taglib/mp4/mp4chapterlist.h index 3f739fb2..1bb9ed83 100644 --- a/taglib/mp4/mp4chapterlist.h +++ b/taglib/mp4/mp4chapterlist.h @@ -37,7 +37,7 @@ namespace TagLib { * A single Nero-style chapter marker. */ struct TAGLIB_EXPORT Chapter { - long long startTime; //!< Start time in 100-nanosecond units + long long startTime; //!< Start time in milliseconds String title; }; diff --git a/taglib/mp4/mp4qtchapterlist.cpp b/taglib/mp4/mp4qtchapterlist.cpp index a726c748..3afc572a 100644 --- a/taglib/mp4/mp4qtchapterlist.cpp +++ b/taglib/mp4/mp4qtchapterlist.cpp @@ -446,9 +446,9 @@ namespace return ByteVector(); // Convert 100-ns units to timescale units - auto toTimescale = [timescale](long long time100ns) -> unsigned int { + auto toTimescale = [timescale](long long timeMs) -> unsigned int { return static_cast( - static_cast(time100ns) * static_cast(timescale) / 10000000.0 + 0.5); + static_cast(timeMs) * static_cast(timescale) / 1000.0 + 0.5); }; unsigned int totalDuration = static_cast( @@ -992,12 +992,12 @@ MP4::MP4QTChapterList::read(MP4::File *file) String title = readTextSample(file, offsets[sampleIndex], sampleSize); - long long startTime100ns = static_cast( - static_cast(currentTime) * 10000000.0 / + long long startTimeMs = static_cast( + static_cast(currentTime) * 1000.0 / static_cast(trackInfo.timescale) + 0.5); Chapter ch; - ch.startTime = startTime100ns; + ch.startTime = startTimeMs; ch.title = title; chapters.append(ch); diff --git a/tests/test_mp4.cpp b/tests/test_mp4.cpp index b2be6734..1e6b8899 100644 --- a/tests/test_mp4.cpp +++ b/tests/test_mp4.cpp @@ -908,12 +908,12 @@ public: chapters.append(ch1); MP4::Chapter ch2; - ch2.startTime = 300000000LL; // 30 seconds in 100ns units + ch2.startTime = 30000LL; // 30 seconds in ms ch2.title = "Main Content"; chapters.append(ch2); MP4::Chapter ch3; - ch3.startTime = 600000000LL; // 60 seconds + ch3.startTime = 60000LL; // 60 seconds in ms ch3.title = "Conclusion"; chapters.append(ch3); @@ -926,9 +926,9 @@ public: CPPUNIT_ASSERT_EQUAL(3U, chapters.size()); CPPUNIT_ASSERT_EQUAL(0LL, chapters[0].startTime); CPPUNIT_ASSERT_EQUAL(String("Introduction"), chapters[0].title); - CPPUNIT_ASSERT_EQUAL(300000000LL, chapters[1].startTime); + CPPUNIT_ASSERT_EQUAL(30000LL, chapters[1].startTime); CPPUNIT_ASSERT_EQUAL(String("Main Content"), chapters[1].title); - CPPUNIT_ASSERT_EQUAL(600000000LL, chapters[2].startTime); + CPPUNIT_ASSERT_EQUAL(60000LL, chapters[2].startTime); CPPUNIT_ASSERT_EQUAL(String("Conclusion"), chapters[2].title); } @@ -1009,7 +1009,7 @@ public: chapters.append(ch1); MP4::Chapter ch2; - ch2.startTime = 100000000LL; // 10 seconds + ch2.startTime = 10000LL; // 10 seconds in ms ch2.title = "Verse"; chapters.append(ch2); @@ -1065,12 +1065,12 @@ public: chapters.append(ch1); MP4::Chapter ch2; - ch2.startTime = 150000000LL; // 15 seconds + ch2.startTime = 15000LL; // 15 seconds in ms ch2.title = "Verse"; chapters.append(ch2); MP4::Chapter ch3; - ch3.startTime = 300000000LL; // 30 seconds + ch3.startTime = 30000LL; // 30 seconds in ms ch3.title = "Outro"; chapters.append(ch3); @@ -1083,9 +1083,9 @@ public: CPPUNIT_ASSERT_EQUAL(3U, chapters.size()); CPPUNIT_ASSERT_EQUAL(0LL, chapters[0].startTime); CPPUNIT_ASSERT_EQUAL(String("Intro"), chapters[0].title); - CPPUNIT_ASSERT_EQUAL(150000000LL, chapters[1].startTime); + CPPUNIT_ASSERT_EQUAL(15000LL, chapters[1].startTime); CPPUNIT_ASSERT_EQUAL(String("Verse"), chapters[1].title); - CPPUNIT_ASSERT_EQUAL(300000000LL, chapters[2].startTime); + CPPUNIT_ASSERT_EQUAL(30000LL, chapters[2].startTime); CPPUNIT_ASSERT_EQUAL(String("Outro"), chapters[2].title); } } @@ -1104,7 +1104,7 @@ public: chapters.append(ch1); MP4::Chapter ch2; - ch2.startTime = 100000000LL; // 10 seconds + ch2.startTime = 10000LL; // 10 seconds in ms ch2.title = "Chapter 2"; chapters.append(ch2); @@ -1153,7 +1153,7 @@ public: chapters.append(ch1); MP4::Chapter ch2; - ch2.startTime = 100000000LL; // 10 seconds + ch2.startTime = 10000LL; // 10 seconds in ms ch2.title = "Verse"; chapters.append(ch2); @@ -1203,7 +1203,7 @@ public: chapters.append(ch1); MP4::Chapter ch2; - ch2.startTime = 50000000LL; // 5 seconds + ch2.startTime = 5000LL; // 5 seconds in ms ch2.title = "Old2"; chapters.append(ch2); @@ -1225,12 +1225,12 @@ public: chapters.append(ch1); MP4::Chapter ch2; - ch2.startTime = 100000000LL; // 10 seconds + ch2.startTime = 10000LL; // 10 seconds in ms ch2.title = "New2"; chapters.append(ch2); MP4::Chapter ch3; - ch3.startTime = 200000000LL; // 20 seconds + ch3.startTime = 20000LL; // 20 seconds in ms ch3.title = "New3"; chapters.append(ch3); @@ -1261,7 +1261,7 @@ public: chapters.append(ch1); MP4::Chapter ch2; - ch2.startTime = 15000000LL; // 1.5 seconds in 100ns units + ch2.startTime = 1500LL; // 1.5 seconds in ms ch2.title = "Precise"; chapters.append(ch2); @@ -1273,7 +1273,7 @@ public: MP4::ChapterList chapters = MP4::MP4QTChapterList::read(filename.c_str()); CPPUNIT_ASSERT_EQUAL(2U, chapters.size()); CPPUNIT_ASSERT_EQUAL(0LL, chapters[0].startTime); - CPPUNIT_ASSERT_EQUAL(15000000LL, chapters[1].startTime); + CPPUNIT_ASSERT_EQUAL(1500LL, chapters[1].startTime); } } @@ -1286,17 +1286,17 @@ public: { MP4::ChapterList chapters; MP4::Chapter ch1; - ch1.startTime = 100000000LL; // 10 seconds + ch1.startTime = 10000LL; // 10 seconds in ms ch1.title = "One"; chapters.append(ch1); MP4::Chapter ch2; - ch2.startTime = 200000000LL; // 20 seconds + ch2.startTime = 20000LL; // 20 seconds in ms ch2.title = "Two"; chapters.append(ch2); MP4::Chapter ch3; - ch3.startTime = 300000000LL; // 30 seconds + ch3.startTime = 30000LL; // 30 seconds in ms ch3.title = "Three"; chapters.append(ch3); @@ -1307,9 +1307,9 @@ public: { MP4::ChapterList chapters = MP4::MP4QTChapterList::read(filename.c_str()); CPPUNIT_ASSERT_EQUAL(3U, chapters.size()); - CPPUNIT_ASSERT_EQUAL(100000000LL, chapters[0].startTime); - CPPUNIT_ASSERT_EQUAL(200000000LL, chapters[1].startTime); - CPPUNIT_ASSERT_EQUAL(300000000LL, chapters[2].startTime); + CPPUNIT_ASSERT_EQUAL(10000LL, chapters[0].startTime); + CPPUNIT_ASSERT_EQUAL(20000LL, chapters[1].startTime); + CPPUNIT_ASSERT_EQUAL(30000LL, chapters[2].startTime); CPPUNIT_ASSERT_EQUAL(String("One"), chapters[0].title); CPPUNIT_ASSERT_EQUAL(String("Two"), chapters[1].title); CPPUNIT_ASSERT_EQUAL(String("Three"), chapters[2].title); @@ -1332,7 +1332,7 @@ public: chapters.append(ch1); MP4::Chapter ch2; - ch2.startTime = 200000000LL; // 20 seconds + ch2.startTime = 20000LL; // 20 seconds in ms ch2.title = "Beta"; chapters.append(ch2); @@ -1348,7 +1348,7 @@ public: CPPUNIT_ASSERT_EQUAL(2U, chapters.size()); CPPUNIT_ASSERT_EQUAL(0LL, chapters[0].startTime); CPPUNIT_ASSERT_EQUAL(String("Alpha"), chapters[0].title); - CPPUNIT_ASSERT_EQUAL(200000000LL, chapters[1].startTime); + CPPUNIT_ASSERT_EQUAL(20000LL, chapters[1].startTime); CPPUNIT_ASSERT_EQUAL(String("Beta"), chapters[1].title); } @@ -1384,7 +1384,7 @@ public: chapters.append(ch1); MP4::Chapter ch2; - ch2.startTime = 200000000LL; // 20 seconds + ch2.startTime = 20000LL; // 20 seconds in ms ch2.title = "Beta"; chapters.append(ch2); @@ -1400,7 +1400,7 @@ public: CPPUNIT_ASSERT_EQUAL(2U, chapters.size()); CPPUNIT_ASSERT_EQUAL(0LL, chapters[0].startTime); CPPUNIT_ASSERT_EQUAL(String("Alpha"), chapters[0].title); - CPPUNIT_ASSERT_EQUAL(200000000LL, chapters[1].startTime); + CPPUNIT_ASSERT_EQUAL(20000LL, chapters[1].startTime); CPPUNIT_ASSERT_EQUAL(String("Beta"), chapters[1].title); }