Determine "effective size" via file info instead of track implementations

This allows removing duplicated code from the track implementations to take
APE tags into account.
This commit is contained in:
Martchus 2023-05-06 20:24:13 +02:00
parent 8ad28f857b
commit c5cd20682d
5 changed files with 38 additions and 16 deletions

View File

@ -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.
*/

View File

@ -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<std::uint64_t>(m_istream->tellg()) - 3u - m_startOffset;
} else {
m_size = static_cast<std::uint64_t>(m_istream->tellg()) + 125u - m_startOffset;
}
m_istream->seekg(static_cast<streamoff>(m_startOffset), ios_base::beg);
// parse frame header
m_istream->seekg(static_cast<std::streamoff>(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());

View File

@ -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<std::uint64_t>(effectiveSize - m_containerOffset);
// check for tags in tracks (FLAC only) or via container object
try {
if (m_containerFormat == ContainerFormat::Flac) {

View File

@ -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<std::streamoff> m_actualId3v2TagOffsets;
std::unique_ptr<AbstractContainer> 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.
*/

View File

@ -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<std::uint64_t>(m_istream->tellg()) - 3u - m_startOffset;
} else {
m_size = static_cast<std::uint64_t>(m_istream->tellg()) + 125u - m_startOffset;
}
m_istream->seekg(static_cast<streamoff>(m_startOffset), ios_base::beg);
// parse frames until the first valid, non-empty frame is reached
m_istream->seekg(static_cast<std::streamoff>(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 {