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:
parent
8ad28f857b
commit
c5cd20682d
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue