From 83aa01c6af938a067010fee87ac8b9cceae5c2ff Mon Sep 17 00:00:00 2001 From: Urs Fleisch Date: Mon, 8 Feb 2021 10:41:25 +0100 Subject: [PATCH] Ogg: Set granule position to -1 if no packets finish on page (#864) --- taglib/ogg/oggpage.cpp | 6 ++++++ tests/test_ogg.cpp | 28 ++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/taglib/ogg/oggpage.cpp b/taglib/ogg/oggpage.cpp index 414d3d53..8cd15a5c 100644 --- a/taglib/ogg/oggpage.cpp +++ b/taglib/ogg/oggpage.cpp @@ -305,4 +305,10 @@ Ogg::Page::Page(const ByteVectorList &packets, } d->packets = packets; d->header.setPacketSizes(packetSizes); + + // https://xiph.org/ogg/doc/framing.html, absolute granule position: + // A special value of '-1' (in two's complement) indicates that no packets + // finish on this page. + if(!lastPacketCompleted && packets.size() <= 1) + d->header.setAbsoluteGranularPosition(-1); } diff --git a/tests/test_ogg.cpp b/tests/test_ogg.cpp index 6564a247..0008429e 100644 --- a/tests/test_ogg.cpp +++ b/tests/test_ogg.cpp @@ -48,6 +48,7 @@ class TestOGG : public CppUnit::TestFixture CPPUNIT_TEST(testDictInterface2); CPPUNIT_TEST(testAudioProperties); CPPUNIT_TEST(testPageChecksum); + CPPUNIT_TEST(testPageGranulePosition); CPPUNIT_TEST_SUITE_END(); public: @@ -222,6 +223,33 @@ public: } + void testPageGranulePosition() + { + ScopedFileCopy copy("empty", ".ogg"); + { + Vorbis::File f(copy.fileName().c_str()); + // Force the Vorbis comment packet to span more than one page and + // check if the granule position is -1 indicating that no packets + // finish on this page. + f.tag()->setComment(String(ByteVector(70000, 'A'))); + f.save(); + + f.seek(0x3a); + CPPUNIT_ASSERT_EQUAL(ByteVector("OggS\0\0", 6), f.readBlock(6)); + CPPUNIT_ASSERT_EQUAL(static_cast(-1), f.readBlock(8).toLongLong()); + } + { + Vorbis::File f(copy.fileName().c_str()); + // Use a small Vorbis comment package which ends on the seconds page and + // check if the granule position is zero. + f.tag()->setComment("A small comment"); + f.save(); + + f.seek(0x3a); + CPPUNIT_ASSERT_EQUAL(ByteVector("OggS\0\0", 6), f.readBlock(6)); + CPPUNIT_ASSERT_EQUAL(static_cast(0), f.readBlock(8).toLongLong()); + } + } }; CPPUNIT_TEST_SUITE_REGISTRATION(TestOGG);