15#include <c++utilities/chrono/timespan.h>
21using namespace std::placeholders;
35 :
AbstractTrack(container.stream(), container.m_iterator.pages()[startPage].startOffset())
36 , m_startPage(startPage)
37 , m_container(container)
38 , m_currentSequenceNumber(0)
51 CPP_UTILITIES_UNUSED(progress)
53 static const string context(
"parsing Ogg page header");
57 const OggPage &firstPage = iterator.
pages()[m_startPage];
66 for (
bool hasIdentificationHeader =
false, hasCommentHeader =
false; iterator && (!hasIdentificationHeader || !hasCommentHeader); ++iterator) {
68 if (currentSize >= 8) {
71 const std::uint64_t sig =
reader().readUInt64BE();
73 if ((sig & 0x00ffffffffffff00u) == 0x00766F7262697300u) {
90 if (!hasIdentificationHeader) {
105 calculateDurationViaSampleCount();
106 hasIdentificationHeader =
true;
109 "Vorbis identification header appears more than once. Oversupplied occurrence will be ignored.", context);
114 if (!hasCommentHeader) {
116 hasCommentHeader =
true;
119 DiagLevel::Critical,
"Vorbis comment header appears more than once. Oversupplied occurrence will be ignored.", context);
127 }
else if (sig == 0x4F70757348656164u) {
140 if (!hasIdentificationHeader) {
147 calculateDurationViaSampleCount(ind.
preSkip());
148 hasIdentificationHeader =
true;
151 DiagLevel::Critical,
"Opus identification header appears more than once. Oversupplied occurrence will be ignored.", context);
154 }
else if (sig == 0x4F70757354616773u) {
169 if (!hasCommentHeader) {
171 hasCommentHeader =
true;
174 DiagLevel::Critical,
"Opus tags/comment header appears more than once. Oversupplied occurrence will be ignored.", context);
177 }
else if ((sig & 0xFFFFFFFFFF000000u) == 0x7F464C4143000000u) {
191 if (!hasIdentificationHeader) {
200 calculateDurationViaSampleCount();
201 hasIdentificationHeader =
true;
204 DiagLevel::Critical,
"FLAC-to-Ogg mapping header appears more than once. Oversupplied occurrence will be ignored.", context);
207 if (!hasCommentHeader) {
210 constexpr auto headerSize = 4;
211 char buff[headerSize];
212 iterator.
read(buff, headerSize);
214 header.
parseHeader(std::string_view(buff, headerSize));
216 m_container.announceComment(
218 hasCommentHeader =
true;
221 DiagLevel::Critical,
"Ogg page after FLAC-to-Ogg mapping header doesn't contain Vorbis comment.", context);
225 DiagLevel::Critical,
"No more Ogg pages after FLAC-to-Ogg mapping header (Vorbis comment expected).", context);
229 }
else if ((sig & 0x00ffffffffffff00u) == 0x007468656F726100u) {
244 }
else if ((sig & 0xFFFFFFFFFFFF0000u) == 0x5370656578200000u) {
258 }
else if (sig == 0x595556344D504547u) {
291void OggStream::calculateDurationViaSampleCount(std::uint16_t preSkip)
297 const auto &iterator = m_container.m_iterator;
299 const auto &pages = iterator.pages();
300 const auto firstPage = find_if(pages.cbegin(), pages.cend(), pred);
301 const auto lastPage = find_if(pages.crbegin(), pages.crend(), pred);
302 if (firstPage != pages.cend() && lastPage != pages.crend()) {
303 m_sampleCount = lastPage->absoluteGranulePosition() - firstPage->absoluteGranulePosition();
The AbortableProgressFeedback class provides feedback about an ongoing operation via callbacks.
The AbstractTrack class parses and stores technical information about video, audio and other kinds of...
std::string_view m_chromaFormat
std::uint64_t m_sampleCount
std::uint16_t m_bitsPerSample
std::istream & inputStream()
Returns the associated input stream.
std::uint16_t m_channelCount
CppUtilities::BinaryReader & reader()
Returns a binary reader for the associated stream.
CppUtilities::TimeSpan m_duration
std::uint32_t m_samplingFrequency
The Diagnostics class is a container for DiagMessage.
Implementation of TagParser::AbstractContainer for Ogg files.
The OggIterator class helps iterating through all segments of an Ogg bitstream.
void read(char *buffer, std::size_t count)
Reads count bytes from the Ogg stream and writes it to the specified buffer.
std::vector< std::uint32_t >::size_type currentSegmentIndex() const
Returns the index of the current segment (in the current page) if the iterator is valid; otherwise an...
std::uint64_t currentSegmentOffset() const
Returns the start offset of the current segment in the input stream if the iterator is valid; otherwi...
const std::vector< OggPage > & pages() const
Returns a vector of containing the Ogg pages that have been fetched yet.
void setPageIndex(std::vector< OggPage >::size_type index)
Sets the current page index.
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...
std::uint32_t currentSegmentSize() const
Returns the size of the current segment.
void setFilter(std::uint32_t streamSerialId)
Allows to filter pages by the specified streamSerialId.
The OggPage class is used to parse Ogg pages.
std::uint32_t streamSerialNumber() const
Returns the stream serial number.
bool matchesStreamSerialNumber(std::uint32_t streamSerialNumber) const
Returns whether the stream serial number of the current instance matches the specified one.
std::uint8_t streamStructureVersion() const
Returns the stream structure version.
~OggStream() override
Destroys the track.
OggStream(OggContainer &container, std::vector< OggPage >::size_type startPage)
Constructs a new track for the stream at the specified startOffset.
void internalParseHeader(Diagnostics &diag, AbortableProgressFeedback &progress) override
This method is internally called to parse header information.
Contains all classes and functions of the TagInfo library.
@ UncompressedVideoFrames