mirror of
https://github.com/taglib/taglib.git
synced 2026-08-14 06:17:00 -04:00
Support Vorbis comments from a multiplexed Ogg stream (#1370)
Ogg::File::readPages() read pages from all logical bitstreams and indexed their packets into one global list. In a multiplexed file the Theora and Vorbis packets got interleaved, so packet 0 was a Theora header rather than the expected Vorbis type-3 comment header. Before reading packets, the Vorbis reader now selects the Vorbis logical bitstream (the one whose first packet is the Vorbis identification header), so it reads the correct stream regardless of position. Packet parsing is scoped to the selected bitstream, so packets from other codecs in the same file are ignored. tests/data/multiplex.ogg is generated using ffmpeg -hide_banner -y \ -f lavfi -i "color=c=navy:s=500x500:r=1:d=2" \ -f lavfi -i "sine=frequency=440:sample_rate=48000:duration=2" \ -map 0:v -map 1:a \ -c:v libtheora -q:v 3 \ -c:a libvorbis -ac 2 -q:a 2 \ -flags +bitexact -fflags +bitexact \ -metadata:s:a:0 TITLE="Paper Lights" \ -metadata:s:a:0 encoder= -metadata:s:v:0 encoder= \ -f ogg tests/data/multiplex.ogg
This commit is contained in:
Binary file not shown.
@@ -32,6 +32,7 @@
|
||||
#include "oggfile.h"
|
||||
#include "vorbisfile.h"
|
||||
#include "oggpageheader.h"
|
||||
#include "plainfile.h"
|
||||
#include <cppunit/extensions/HelperMacros.h>
|
||||
#include "utils.h"
|
||||
|
||||
@@ -47,6 +48,7 @@ class TestOGG : public CppUnit::TestFixture
|
||||
CPPUNIT_TEST(testDictInterface1);
|
||||
CPPUNIT_TEST(testDictInterface2);
|
||||
CPPUNIT_TEST(testAudioProperties);
|
||||
CPPUNIT_TEST(testMultiplexed);
|
||||
CPPUNIT_TEST(testPageChecksum);
|
||||
CPPUNIT_TEST(testPageGranulePosition);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
@@ -200,6 +202,45 @@ public:
|
||||
CPPUNIT_ASSERT_EQUAL(0, f.audioProperties()->bitrateMinimum());
|
||||
}
|
||||
|
||||
void testMultiplexed()
|
||||
{
|
||||
// A multiplexed Ogg stream where the Vorbis logical bitstream is not the
|
||||
// first one (it is preceded by a Theora video stream). The Vorbis comment
|
||||
// and audio properties must still be read from the Vorbis stream.
|
||||
ScopedFileCopy copy("multiplex", ".ogg");
|
||||
string filename = copy.fileName();
|
||||
{
|
||||
Vorbis::File f(filename.c_str());
|
||||
CPPUNIT_ASSERT(f.isValid());
|
||||
CPPUNIT_ASSERT(f.tag());
|
||||
CPPUNIT_ASSERT_EQUAL(String("Paper Lights"), f.tag()->title());
|
||||
CPPUNIT_ASSERT(f.audioProperties());
|
||||
CPPUNIT_ASSERT_EQUAL(2, f.audioProperties()->channels());
|
||||
CPPUNIT_ASSERT_EQUAL(48000, f.audioProperties()->sampleRate());
|
||||
|
||||
f.tag()->setTitle("Changed Title");
|
||||
CPPUNIT_ASSERT(f.save());
|
||||
}
|
||||
{
|
||||
Vorbis::File f(filename.c_str());
|
||||
CPPUNIT_ASSERT(f.isValid());
|
||||
CPPUNIT_ASSERT_EQUAL(String("Changed Title"), f.tag()->title());
|
||||
|
||||
f.tag()->setTitle("Paper Lights");
|
||||
CPPUNIT_ASSERT(f.save());
|
||||
}
|
||||
{
|
||||
Vorbis::File f(filename.c_str());
|
||||
CPPUNIT_ASSERT(f.isValid());
|
||||
CPPUNIT_ASSERT_EQUAL(String("Paper Lights"), f.tag()->title());
|
||||
}
|
||||
|
||||
// Check if the modified file is byte for byte equal to the original file
|
||||
const ByteVector origData = PlainFile(TEST_FILE_PATH_C("multiplex.ogg")).readAll();
|
||||
const ByteVector fileData = PlainFile(filename.c_str()).readAll();
|
||||
CPPUNIT_ASSERT(origData == fileData);
|
||||
}
|
||||
|
||||
void testPageChecksum()
|
||||
{
|
||||
ScopedFileCopy copy("empty", ".ogg");
|
||||
|
||||
Reference in New Issue
Block a user