diff --git a/abstracttrack.h b/abstracttrack.h index 249141a..6b285c4 100644 --- a/abstracttrack.h +++ b/abstracttrack.h @@ -132,6 +132,7 @@ public: MediaType mediaType() const; std::string_view mediaTypeName() const; std::uint64_t size() const; + void setSize(std::uint64_t size); std::uint32_t trackNumber() const; void setTrackNumber(std::uint32_t trackNumber); std::uint64_t id() const; @@ -396,6 +397,19 @@ inline std::uint64_t AbstractTrack::size() const return m_size; } +/*! + * \brief Sets the size in bytes. + * \remarks + * This is used by MediaFileInfo to set the track size for certain types of tracks before invoking the parsing. + * If you use this a class derived from AbstractTrack directly you may want to do the same if not the entire + * input stream is supposed to be considered part of the track and the parser would otherwise assume that (like + * the parser of MpegAudioFrameStream might do). + */ +inline void AbstractTrack::setSize(std::uint64_t size) +{ + m_size = size; +} + /*! * \brief Returns the track number if known; otherwise returns 0. */ diff --git a/adts/adtsstream.cpp b/adts/adtsstream.cpp index 057d157..405fbda 100644 --- a/adts/adtsstream.cpp +++ b/adts/adtsstream.cpp @@ -24,15 +24,8 @@ void AdtsStream::internalParseHeader(Diagnostics &diag, AbortableProgressFeedbac if (!m_istream) { throw NoDataFoundException(); } - // get size - m_istream->seekg(-128, ios_base::end); - if (m_reader.readUInt24BE() == 0x544147) { - m_size = static_cast(m_istream->tellg()) - 3u - m_startOffset; - } else { - m_size = static_cast(m_istream->tellg()) + 125u - m_startOffset; - } - m_istream->seekg(static_cast(m_startOffset), ios_base::beg); // parse frame header + m_istream->seekg(static_cast(m_startOffset), ios_base::beg); m_firstFrame.parseHeader(m_reader); m_format = Mpeg4AudioObjectIds::idToMediaFormat(m_firstFrame.mpeg4AudioObjectId()); m_channelCount = Mpeg4ChannelConfigs::channelCount(m_channelConfig = m_firstFrame.mpeg4ChannelConfig()); diff --git a/mediafileinfo.cpp b/mediafileinfo.cpp index 112c13e..b1a3eca 100644 --- a/mediafileinfo.cpp +++ b/mediafileinfo.cpp @@ -83,6 +83,7 @@ MediaFileInfo::MediaFileInfo(std::string &&path) , m_containerFormat(ContainerFormat::Unknown) , m_containerOffset(0) , m_paddingSize(0) + , m_effectiveSize(0) , m_fileStructureFlags(MediaFileStructureFlags::None) , m_tracksParsingStatus(ParsingStatus::NotParsedYet) , m_tagsParsingStatus(ParsingStatus::NotParsedYet) @@ -354,6 +355,13 @@ void MediaFileInfo::parseTracks(Diagnostics &diag, AbortableProgressFeedback &pr default: throw NotImplementedException(); } + if (m_containerFormat != ContainerFormat::Flac) { + // ensure the effective size has been determined + // note: This is not required for FLAC and should also be avoided as parseTags() will invoke + // parseTracks() when dealing with FLAC files. + parseTags(diag, progress); + m_singleTrack->setSize(m_effectiveSize); + } m_singleTrack->parseHeader(diag, progress); // take padding for some "single-track" formats into account @@ -453,6 +461,9 @@ void MediaFileInfo::parseTags(Diagnostics &diag, AbortableProgressFeedback &prog m_id3v2Tags.emplace_back(id3v2Tag.release()); } + // compute effective size + m_effectiveSize = static_cast(effectiveSize - m_containerOffset); + // check for tags in tracks (FLAC only) or via container object try { if (m_containerFormat == ContainerFormat::Flac) { diff --git a/mediafileinfo.h b/mediafileinfo.h index 80d068b..4e90707 100644 --- a/mediafileinfo.h +++ b/mediafileinfo.h @@ -105,6 +105,7 @@ public: std::string_view mimeType() const; std::uint64_t containerOffset() const; std::uint64_t paddingSize() const; + std::uint64_t effectiveSize() const; AbstractContainer *container() const; ParsingStatus containerParsingStatus() const; // ... the chapters @@ -201,6 +202,7 @@ private: ContainerFormat m_containerFormat; std::streamoff m_containerOffset; std::uint64_t m_paddingSize; + std::uint64_t m_effectiveSize; std::vector m_actualId3v2TagOffsets; std::unique_ptr m_container; MediaFileStructureFlags m_fileStructureFlags; @@ -296,6 +298,15 @@ inline std::uint64_t MediaFileInfo::paddingSize() const return m_paddingSize; } +/*! + * \brief Returns the "effective size" of the file if know; otherwise returns 0. + * \remarks This is the size of the file minus tags at the beginning and the end. + */ +inline std::uint64_t MediaFileInfo::effectiveSize() const +{ + return m_effectiveSize; +} + /*! * \brief Returns an indication whether tag information has been parsed yet. */ diff --git a/mpegaudio/mpegaudioframestream.cpp b/mpegaudio/mpegaudioframestream.cpp index bb64acc..4ae5e4e 100644 --- a/mpegaudio/mpegaudioframestream.cpp +++ b/mpegaudio/mpegaudioframestream.cpp @@ -35,15 +35,8 @@ void MpegAudioFrameStream::internalParseHeader(Diagnostics &diag, AbortableProgr if (!m_istream) { throw NoDataFoundException(); } - // get size - m_istream->seekg(-128, ios_base::end); - if (m_reader.readUInt24BE() == 0x544147) { - m_size = static_cast(m_istream->tellg()) - 3u - m_startOffset; - } else { - m_size = static_cast(m_istream->tellg()) + 125u - m_startOffset; - } - m_istream->seekg(static_cast(m_startOffset), ios_base::beg); // parse frames until the first valid, non-empty frame is reached + m_istream->seekg(static_cast(m_startOffset), ios_base::beg); for (size_t invalidByteskipped = 0; m_frames.size() < 200 && invalidByteskipped <= 0x600u;) { MpegAudioFrame &frame = invalidByteskipped > 0 ? m_frames.back() : m_frames.emplace_back(); try {