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> 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.
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...
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.
uint32 currentSegmentSize() const
Returns the size of the current segment.
uint32 m_samplingFrequency
byte streamStructureVersion() const
Returns the stream structure version.