diff --git a/mpegaudio/mpegaudioframe.cpp b/mpegaudio/mpegaudioframe.cpp index c7ec3c1..78b6b17 100644 --- a/mpegaudio/mpegaudioframe.cpp +++ b/mpegaudio/mpegaudioframe.cpp @@ -2,6 +2,8 @@ #include "../exceptions.h" +#include +#include #include using namespace std; @@ -46,15 +48,23 @@ const std::uint16_t MpegAudioFrame::s_bitrateTable[0x2][0x3][0xF] = { { { 0, 32, */ void MpegAudioFrame::parseHeader(BinaryReader &reader, Diagnostics &diag) { + // read MPEG audio frame header m_header = reader.readUInt32BE(); if (!isValid()) { - diag.emplace_back(DiagLevel::Critical, "Header is invalid.", "parsing MPEG audio frame header"); + diag.emplace_back(DiagLevel::Critical, + "Frame 0x" % numberToString(m_header, 16) % " at 0x" % numberToString(reader.stream()->tellg() - 4l, 16) + " is invalid.", + "parsing MPEG audio frame header"); throw InvalidDataException(); } + + // read XING header (see https://www.codeproject.com/Articles/8295/MPEG-Audio-Frame-Header#XINGHeader) + if (size() < s_xingHeaderOffset - 4 + 8) { + return; + } reader.stream()->seekg(s_xingHeaderOffset - 4, ios_base::cur); m_xingHeader = reader.readUInt64BE(); - m_xingHeaderFlags = static_cast(m_xingHeader & 0xffffffffuL); if (isXingHeaderAvailable()) { + m_xingHeaderFlags = static_cast(m_xingHeader & 0xffffffffuL); if (isXingFramefieldPresent()) { m_xingFramefield = reader.readUInt32BE(); } diff --git a/mpegaudio/mpegaudioframestream.cpp b/mpegaudio/mpegaudioframestream.cpp index f9bf990..b1fd585 100644 --- a/mpegaudio/mpegaudioframestream.cpp +++ b/mpegaudio/mpegaudioframestream.cpp @@ -41,16 +41,24 @@ void MpegAudioFrameStream::internalParseHeader(Diagnostics &diag) m_size = static_cast(m_istream->tellg()) + 125u - m_startOffset; } m_istream->seekg(static_cast(m_startOffset), ios_base::beg); - // parse frame header - m_frames.emplace_back(); - MpegAudioFrame &frame = m_frames.back(); - frame.parseHeader(m_reader, diag); + // parse frames until the first non-empty frame is reached + auto isFrameEmpty = false; + while (!isFrameEmpty && m_frames.size() < 200) { + MpegAudioFrame &frame = m_frames.emplace_back(); + frame.parseHeader(m_reader, diag); + isFrameEmpty = frame.size(); + if (frame.isProtectedByCrc()) { + m_istream->seekg(2, ios_base::cur); + } + } + const MpegAudioFrame &frame = m_frames.back(); addInfo(frame, *this); if (frame.isXingBytesfieldPresent()) { std::uint32_t xingSize = frame.xingBytesfield(); if (m_size && xingSize != m_size) { diag.emplace_back(DiagLevel::Warning, - "Real length of MPEG audio frames is not equal with value provided by Xing header. The Xing header value will be used.", context); + "Real length of MPEG audio frames is not in accordance with value provided by Xing header. The Xing header value will be used.", + context); m_size = xingSize; } }