4 #include "../vorbis/vorbisidentificationheader.h" 5 #include "../vorbis/vorbispackagetypes.h" 7 #include "../opus/opusidentificationheader.h" 9 #include "../flac/flactooggmappingheader.h" 11 #include "../exceptions.h" 12 #include "../mediafileinfo.h" 13 #include "../mediaformat.h" 15 #include <c++utilities/chrono/timespan.h> 21 using namespace std::placeholders;
22 using namespace ChronoUtilities;
34 OggStream::OggStream(
OggContainer &container, vector<OggPage>::size_type startPage)
35 :
AbstractTrack(container.stream(), container.m_iterator.pages()[startPage].startOffset())
36 , m_startPage(startPage)
37 , m_container(container)
38 , m_currentSequenceNumber(0)
51 static const string context(
"parsing OGG page header");
55 const OggPage &firstPage = iterator.
pages()[m_startPage];
64 for (
bool hasIdentificationHeader =
false, hasCommentHeader =
false; iterator && (!hasIdentificationHeader || !hasCommentHeader); ++iterator) {
66 if (currentSize >= 8) {
69 const uint64 sig =
reader().readUInt64BE();
71 if ((sig & 0x00ffffffffffff00u) == 0x00766F7262697300u) {
88 if (!hasIdentificationHeader) {
103 calculateDurationViaSampleCount();
104 hasIdentificationHeader =
true;
107 "Vorbis identification header appears more than once. Oversupplied occurrence will be ignored.", context);
112 if (!hasCommentHeader) {
114 hasCommentHeader =
true;
117 DiagLevel::Critical,
"Vorbis comment header appears more than once. Oversupplied occurrence will be ignored.", context);
125 }
else if (sig == 0x4F70757348656164u) {
138 if (!hasIdentificationHeader) {
145 calculateDurationViaSampleCount(ind.
preSkip());
146 hasIdentificationHeader =
true;
149 DiagLevel::Critical,
"Opus identification header appears more than once. Oversupplied occurrence will be ignored.", context);
152 }
else if (sig == 0x4F70757354616773u) {
167 if (!hasCommentHeader) {
169 hasCommentHeader =
true;
172 DiagLevel::Critical,
"Opus tags/comment header appears more than once. Oversupplied occurrence will be ignored.", context);
175 }
else if ((sig & 0xFFFFFFFFFF000000u) == 0x7F464C4143000000u) {
189 if (!hasIdentificationHeader) {
198 calculateDurationViaSampleCount();
199 hasIdentificationHeader =
true;
202 DiagLevel::Critical,
"FLAC-to-Ogg mapping header appears more than once. Oversupplied occurrence will be ignored.", context);
205 if (!hasCommentHeader) {
209 iterator.
read(buff, 4);
213 m_container.announceComment(
215 hasCommentHeader =
true;
218 DiagLevel::Critical,
"OGG page after FLAC-to-Ogg mapping header doesn't contain Vorbis comment.", context);
222 DiagLevel::Critical,
"No more OGG pages after FLAC-to-Ogg mapping header (Vorbis comment expected).", context);
226 }
else if ((sig & 0x00ffffffffffff00u) == 0x007468656F726100u) {
241 }
else if ((sig & 0xFFFFFFFFFFFF0000u) == 0x5370656578200000u) {
255 }
else if (sig == 0x595556344D504547u) {
289 void OggStream::calculateDurationViaSampleCount(uint16 preSkip)
295 const auto &iterator = m_container.m_iterator;
297 const auto &pages = iterator.
pages();
298 const auto firstPage = find_if(pages.cbegin(), pages.cend(), pred);
299 const auto lastPage = find_if(pages.crbegin(), pages.crend(), pred);
300 if (firstPage != pages.cend() && lastPage != pages.crend()) {
301 m_sampleCount = lastPage->absoluteGranulePosition() - firstPage->absoluteGranulePosition();
void read(char *buffer, std::size_t count)
Reads count bytes from the OGG stream and writes it to the specified buffer.
const char * m_chromaFormat
void internalParseHeader(Diagnostics &diag) override
This method is internally called to parse header information.
The OggIterator class helps iterating through all segments of an OGG bitstream.
bool matchesStreamSerialNumber(uint32 streamSerialNumber) const
Returns whether the stream serial number of the current instance matches the specified one.
~OggStream() override
Destroys the track.
IoUtilities::BinaryReader & reader()
Returns a binary reader for the associated stream.
uint64 currentSegmentOffset() const
Returns the start offset of the current segment in the input stream if the iterator is valid; otherwi...
std::vector< uint32 >::size_type currentSegmentIndex() const
Returns the index of the current segment (in the current page) if the iterator is valid; otherwise an...
std::vector< OggPage >::size_type currentPageIndex() const
Returns the index of the current page if the iterator is valid; otherwise an undefined index is retur...
Implementation of TagParser::AbstractContainer for OGG files.
const std::vector< OggPage > & pages() const
Returns a vector of containing the OGG pages that have been fetched yet.
uint32 streamSerialNumber() const
Returns the stream serial number.
void setPageIndex(std::vector< OggPage >::size_type index)
Sets the current page index.
ChronoUtilities::TimeSpan m_duration
std::istream & inputStream()
Returns the associated input stream.
void setFilter(uint32 streamSerialId)
Allows to filter pages by the specified streamSerialId.
The AbstractTrack class parses and stores technical information about video, audio and other kinds of...
The OggPage class is used to parse OGG pages.
uint32 currentSegmentSize() const
Returns the size of the current segment.
uint32 m_samplingFrequency
Contains all classes and functions of the TagInfo library.
byte streamStructureVersion() const
Returns the stream structure version.
The Diagnostics class is a container for DiagMessage.