added detection of ADTS files
This commit is contained in:
parent
15a03a0029
commit
1f4800c9be
|
@ -32,7 +32,8 @@ enum class TrackType
|
|||
MpegAudioFrameStream, /**< The track is a Media::MpegAudioFrameStream. */
|
||||
Mp4Track, /**< The track is a Media::Mp4Track. */
|
||||
WaveAudioStream, /**< The track is a Media::WaveAudioStream. */
|
||||
OggStream /**< The track is a Media::OggStream. */
|
||||
OggStream, /**< The track is a Media::OggStream. */
|
||||
AdtsStream /**< The track is a Media::AdtsStream. */
|
||||
};
|
||||
|
||||
class LIB_EXPORT AbstractTrack : public StatusProvider
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
#include "adtsstream.h"
|
||||
|
||||
#include "../mp4/mp4ids.h"
|
||||
#include "../exceptions.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace Media {
|
||||
|
||||
/*!
|
||||
* \class Media::AdtsStream
|
||||
* \brief Implementation of Media::AbstractTrack for ADTS streams.
|
||||
*/
|
||||
|
||||
void AdtsStream::internalParseHeader()
|
||||
{
|
||||
//static const string context("parsing ADTS frame header");
|
||||
if(!m_istream) {
|
||||
throw NoDataFoundException();
|
||||
}
|
||||
// get size
|
||||
m_istream->seekg(-128, ios_base::end);
|
||||
if(m_reader.readUInt24BE() == 0x544147) {
|
||||
m_size = static_cast<uint64>(m_istream->tellg()) - 3u - m_startOffset;
|
||||
} else {
|
||||
m_size = static_cast<uint64>(m_istream->tellg()) + 125u - m_startOffset;
|
||||
}
|
||||
m_istream->seekg(m_startOffset, ios_base::beg);
|
||||
// parse frame header
|
||||
m_firstFrame.parseHeader(m_reader);
|
||||
m_format = Mpeg4AudioObjectIds::idToMediaFormat(m_firstFrame.mpeg4AudioObjectId());
|
||||
m_channelCount = Mpeg4ChannelConfigs::channelCount(m_firstFrame.mpeg4ChannelConfig());
|
||||
byte sampleRateIndex = m_firstFrame.mpeg4SampleRateIndex();
|
||||
m_sampleRate = sampleRateIndex < sizeof(mpeg4SampleRateTable) ? mpeg4SampleRateTable[sampleRateIndex] : 0;
|
||||
}
|
||||
|
||||
} // namespace Media
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
#ifndef MEDIA_ADTSSTREAM_H
|
||||
#define MEDIA_ADTSSTREAM_H
|
||||
|
||||
#include "adtsframe.h"
|
||||
#include "../abstracttrack.h"
|
||||
|
||||
namespace Media {
|
||||
|
||||
class LIB_EXPORT AdtsStream : public AbstractTrack
|
||||
{
|
||||
public:
|
||||
AdtsStream(std::iostream &stream, uint64 startOffset);
|
||||
~AdtsStream();
|
||||
|
||||
TrackType type() const;
|
||||
|
||||
protected:
|
||||
void internalParseHeader();
|
||||
|
||||
private:
|
||||
AdtsFrame m_firstFrame;
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Constructs a new track for the \a stream at the specified \a startOffset.
|
||||
*/
|
||||
inline AdtsStream::AdtsStream(std::iostream &stream, uint64 startOffset) :
|
||||
AbstractTrack(stream, startOffset)
|
||||
{
|
||||
m_mediaType = MediaType::Audio;
|
||||
}
|
||||
|
||||
inline AdtsStream::~AdtsStream()
|
||||
{}
|
||||
|
||||
inline TrackType AdtsStream::type() const
|
||||
{
|
||||
return TrackType::AdtsStream;
|
||||
}
|
||||
|
||||
} // namespace Media
|
||||
|
||||
#endif // MEDIA_ADTSSTREAM_H
|
|
@ -5,8 +5,8 @@
|
|||
#include "id3/id3v1tag.h"
|
||||
#include "id3/id3v2tag.h"
|
||||
#include "wav/waveaudiostream.h"
|
||||
#include "mpegaudio/mpegaudioframe.h"
|
||||
#include "mpegaudio/mpegaudioframestream.h"
|
||||
#include "adts/adtsstream.h"
|
||||
#include "mp4/mp4container.h"
|
||||
#include "mp4/mp4atom.h"
|
||||
#include "mp4/mp4tag.h"
|
||||
|
@ -131,7 +131,7 @@ startParsingSignature:
|
|||
stream().seekg(m_containerOffset, ios_base::beg);
|
||||
stream().read(buff, sizeof(buff));
|
||||
// skip zero bytes/padding
|
||||
if(buff[0] == 0 && buff[1] == 0 && buff[2] == 0 && buff[3] == 0) {
|
||||
if(!(*reinterpret_cast<uint32 *>(buff))) {
|
||||
// give up after 0x100 bytes
|
||||
if(m_paddingSize >= 0x100u) {
|
||||
m_containerParsed = true;
|
||||
|
@ -143,11 +143,10 @@ startParsingSignature:
|
|||
goto startParsingSignature; // read signature again
|
||||
}
|
||||
if(m_paddingSize) {
|
||||
addNotification(NotificationType::Warning, ConversionUtilities::numberToString(m_paddingSize) + " empty bytes skipped.", context);
|
||||
addNotification(NotificationType::Warning, ConversionUtilities::numberToString(m_paddingSize) + " zero-bytes skipped at the beginning of the file.", context);
|
||||
}
|
||||
// parse signature
|
||||
m_containerFormat = parseSignature(buff, sizeof(buff));
|
||||
switch(m_containerFormat) {
|
||||
switch(m_containerFormat = parseSignature(buff, sizeof(buff))) {
|
||||
case ContainerFormat::Id2v2Tag:
|
||||
m_actualId3v2TagOffsets.push_back(m_containerOffset);
|
||||
if(m_actualId3v2TagOffsets.size() == 2) {
|
||||
|
@ -233,16 +232,18 @@ void MediaFileInfo::parseTracks()
|
|||
} else {
|
||||
switch(m_containerFormat) {
|
||||
case ContainerFormat::RiffWave:
|
||||
m_waveAudioStream = make_unique<WaveAudioStream>(stream(), m_containerOffset);
|
||||
m_waveAudioStream->parseHeader();
|
||||
m_singleTrack = make_unique<WaveAudioStream>(stream(), m_containerOffset);
|
||||
break;
|
||||
case ContainerFormat::MpegAudioFrames:
|
||||
m_mpegAudioFrameStream = make_unique<MpegAudioFrameStream>(stream(), m_containerOffset);
|
||||
m_mpegAudioFrameStream->parseHeader();
|
||||
m_singleTrack = make_unique<MpegAudioFrameStream>(stream(), m_containerOffset);
|
||||
break;
|
||||
case ContainerFormat::Adts:
|
||||
m_singleTrack = make_unique<AdtsStream>(stream(), m_containerOffset);
|
||||
break;
|
||||
default:
|
||||
throw NotImplementedException();
|
||||
}
|
||||
m_singleTrack->parseHeader();
|
||||
}
|
||||
} catch (NotImplementedException &) {
|
||||
addNotification(NotificationType::Information, "Parsing tracks is not implemented for the container format of the file.", context);
|
||||
|
@ -339,28 +340,32 @@ void MediaFileInfo::parseTags()
|
|||
void MediaFileInfo::parseChapters()
|
||||
{
|
||||
static const string context("parsing chapters");
|
||||
if(m_container) {
|
||||
try {
|
||||
try {
|
||||
if(m_container) {
|
||||
m_container->parseChapters();
|
||||
} catch (NotImplementedException &) {
|
||||
addNotification(NotificationType::Information, "Parsing chapters is not implemented for the container format of the file.", context);
|
||||
} catch (Failure &) {
|
||||
addNotification(NotificationType::Critical, "Unable to parse chapters.", context);
|
||||
} else {
|
||||
throw NotImplementedException();
|
||||
}
|
||||
} catch (NotImplementedException &) {
|
||||
addNotification(NotificationType::Information, "Parsing chapters is not implemented for the container format of the file.", context);
|
||||
} catch (Failure &) {
|
||||
addNotification(NotificationType::Critical, "Unable to parse chapters.", context);
|
||||
}
|
||||
}
|
||||
|
||||
void MediaFileInfo::parseAttachments()
|
||||
{
|
||||
static const string context("parsing attachments");
|
||||
if(m_container) {
|
||||
try {
|
||||
try {
|
||||
if(m_container) {
|
||||
m_container->parseAttachments();
|
||||
} catch (NotImplementedException &) {
|
||||
addNotification(NotificationType::Information, "Parsing attachments is not implemented for the container format of the file.", context);
|
||||
} catch (Failure &) {
|
||||
addNotification(NotificationType::Critical, "Unable to parse attachments.", context);
|
||||
} else {
|
||||
throw NotImplementedException();
|
||||
}
|
||||
} catch (NotImplementedException &) {
|
||||
addNotification(NotificationType::Information, "Parsing attachments is not implemented for the container format of the file.", context);
|
||||
} catch (Failure &) {
|
||||
addNotification(NotificationType::Critical, "Unable to parse attachments.", context);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -540,8 +545,8 @@ const char *MediaFileInfo::containerFormatAbbreviation() const
|
|||
mediaType = hasTracksOfType(MediaType::Video) ? MediaType::Video : MediaType::Audio;
|
||||
break;
|
||||
case ContainerFormat::MpegAudioFrames:
|
||||
if(m_mpegAudioFrameStream) {
|
||||
version = m_mpegAudioFrameStream->format().sub;
|
||||
if(m_singleTrack) {
|
||||
version = m_singleTrack->format().sub;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -627,29 +632,6 @@ const char *MediaFileInfo::mimeType() const
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Returns the number of tracks that could be parsed.
|
||||
*
|
||||
* parseTracks() needs to be called before. Otherwise this
|
||||
* method always returns zero.
|
||||
*
|
||||
* \sa parseTracks()
|
||||
*/
|
||||
size_t MediaFileInfo::trackCount() const
|
||||
{
|
||||
size_t c = 0;
|
||||
if(m_waveAudioStream) {
|
||||
++c;
|
||||
}
|
||||
if(m_mpegAudioFrameStream) {
|
||||
++c;
|
||||
}
|
||||
if(m_container) {
|
||||
c += m_container->trackCount();
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Returns the tracks for the current file.
|
||||
*
|
||||
|
@ -665,11 +647,8 @@ size_t MediaFileInfo::trackCount() const
|
|||
vector<AbstractTrack *> MediaFileInfo::tracks() const
|
||||
{
|
||||
vector<AbstractTrack *> res;
|
||||
if(m_waveAudioStream) {
|
||||
res.push_back(m_waveAudioStream.get());
|
||||
}
|
||||
if(m_mpegAudioFrameStream) {
|
||||
res.push_back(m_mpegAudioFrameStream.get());
|
||||
if(m_singleTrack) {
|
||||
res.push_back(m_singleTrack.get());
|
||||
}
|
||||
if(m_container) {
|
||||
for(size_t i = 0, count = m_container->trackCount(); i < count; ++i) {
|
||||
|
@ -692,7 +671,7 @@ bool MediaFileInfo::hasTracksOfType(MediaType type) const
|
|||
if(!areTracksParsed()) {
|
||||
return false;
|
||||
}
|
||||
if(type == MediaType::Audio && (m_waveAudioStream || m_mpegAudioFrameStream)) {
|
||||
if(type == MediaType::Audio && m_singleTrack) {
|
||||
return true;
|
||||
} else if(m_container) {
|
||||
for(size_t i = 0, count = m_container->trackCount(); i < count; ++i) {
|
||||
|
@ -1142,8 +1121,7 @@ void MediaFileInfo::clearParsingResults()
|
|||
m_actualId3v2TagOffsets.clear();
|
||||
m_actualExistingId3v1Tag = false;
|
||||
m_container.reset();
|
||||
m_waveAudioStream.reset();
|
||||
m_mpegAudioFrameStream.reset();
|
||||
m_singleTrack.reset();
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
|
@ -142,8 +142,7 @@ private:
|
|||
std::unique_ptr<AbstractContainer> m_container;
|
||||
// fields related to the tracks
|
||||
bool m_tracksParsed;
|
||||
std::unique_ptr<WaveAudioStream> m_waveAudioStream;
|
||||
std::unique_ptr<MpegAudioFrameStream> m_mpegAudioFrameStream;
|
||||
std::unique_ptr<AbstractTrack> m_singleTrack;
|
||||
// fields related to the tag
|
||||
bool m_tagParsed;
|
||||
std::unique_ptr<Id3v1Tag> m_id3v1Tag;
|
||||
|
@ -203,6 +202,19 @@ inline bool MediaFileInfo::areTracksParsed() const
|
|||
return m_tracksParsed;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Returns the number of tracks that could be parsed.
|
||||
*
|
||||
* parseTracks() needs to be called before. Otherwise this
|
||||
* method always returns zero.
|
||||
*
|
||||
* \sa parseTracks()
|
||||
*/
|
||||
inline size_t MediaFileInfo::trackCount() const
|
||||
{
|
||||
return m_singleTrack ? 1 : 0 + m_container->trackCount();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Returns whether the chapters have been parsed yet.
|
||||
*/
|
||||
|
|
|
@ -223,7 +223,7 @@ const char *streamTypeName(byte streamTypeId)
|
|||
}
|
||||
|
||||
/*!
|
||||
* \brief Encapsulates all supported MPEG-4 audio object format IDs.
|
||||
* \brief Encapsulates all supported MPEG-4 audio object type IDs.
|
||||
* \sa http://wiki.multimedia.cx/index.php?title=MPEG-4_Audio
|
||||
*/
|
||||
namespace Mpeg4AudioObjectIds {
|
||||
|
@ -279,6 +279,61 @@ LIB_EXPORT MediaFormat idToMediaFormat(byte mpeg4AudioObjectId, bool sbrPresent,
|
|||
|
||||
}
|
||||
|
||||
uint32 mpeg4SampleRateTable[] = {
|
||||
96000, 88200, 64000, 48000, 44100, 32000,
|
||||
24000, 22050, 16000, 12000, 11025, 8000, 7350
|
||||
};
|
||||
|
||||
namespace Mpeg4ChannelConfigs {
|
||||
|
||||
const char *channelConfigString(byte config)
|
||||
{
|
||||
switch(config) {
|
||||
case AotSpecificConfig:
|
||||
return "defined in AOT Specific Config";
|
||||
case FrontCenter:
|
||||
return "1 channel: front-center";
|
||||
case FrontLeftFrontRight:
|
||||
return "2 channels: front-left, front-right";
|
||||
case FrontCenterFrontLeftFrontRight:
|
||||
return "3 channels: front-center, front-left, front-right";
|
||||
case FrontCenterFrontLeftFrontRightBackCenter:
|
||||
return "4 channels: front-center, front-left, front-right, back-center";
|
||||
case FrontCenterFrontLeftFrontRightBackLeftBackRight:
|
||||
return "5 channels: front-center, front-left, front-right, back-left, back-right";
|
||||
case FrontCenterFrontLeftFrontRightBackLeftBackRightLFEChannel:
|
||||
return "6 channels: front-center, front-left, front-right, back-left, back-right, LFE-channel";
|
||||
case FrontCenterFrontLeftFrontRightSideLeftSideRightBackLeftBackRightLFEChannel:
|
||||
return "8 channels: front-center, front-left, front-right, side-left, side-right, back-left, back-right, LFE-channel";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
byte channelCount(byte config)
|
||||
{
|
||||
switch(config) {
|
||||
case FrontCenter:
|
||||
return 1;
|
||||
case FrontLeftFrontRight:
|
||||
return 2;
|
||||
case FrontCenterFrontLeftFrontRight:
|
||||
return 3;
|
||||
case FrontCenterFrontLeftFrontRightBackCenter:
|
||||
return 4;
|
||||
case FrontCenterFrontLeftFrontRightBackLeftBackRight:
|
||||
return 5;
|
||||
case FrontCenterFrontLeftFrontRightBackLeftBackRightLFEChannel:
|
||||
return 6;
|
||||
case FrontCenterFrontLeftFrontRightSideLeftSideRightBackLeftBackRightLFEChannel:
|
||||
return 8;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Encapsulates MPEG-4 video (14496-2) codes.
|
||||
*/
|
||||
|
|
20
mp4/mp4ids.h
20
mp4/mp4ids.h
|
@ -585,6 +585,26 @@ LIB_EXPORT MediaFormat idToMediaFormat(byte mpeg4AudioObjectId, bool sbrPresent
|
|||
|
||||
}
|
||||
|
||||
extern uint32 mpeg4SampleRateTable[13];
|
||||
|
||||
namespace Mpeg4ChannelConfigs {
|
||||
enum Mpeg4ChannelConfig : byte
|
||||
{
|
||||
AotSpecificConfig = 0,
|
||||
FrontCenter,
|
||||
FrontLeftFrontRight,
|
||||
FrontCenterFrontLeftFrontRight,
|
||||
FrontCenterFrontLeftFrontRightBackCenter,
|
||||
FrontCenterFrontLeftFrontRightBackLeftBackRight,
|
||||
FrontCenterFrontLeftFrontRightBackLeftBackRightLFEChannel,
|
||||
FrontCenterFrontLeftFrontRightSideLeftSideRightBackLeftBackRightLFEChannel
|
||||
};
|
||||
|
||||
LIB_EXPORT const char *channelConfigString(byte config);
|
||||
LIB_EXPORT byte channelCount(byte config);
|
||||
|
||||
}
|
||||
|
||||
namespace Mpeg4VideoCodes {
|
||||
enum KnownValue : byte {
|
||||
VideoObjectStart = 0x00,
|
||||
|
|
|
@ -26,10 +26,6 @@ namespace Media {
|
|||
|
||||
DateTime startDate = DateTime::fromDate(1904, 1, 1);
|
||||
|
||||
uint32 sampleRateTable[] = {
|
||||
96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000
|
||||
};
|
||||
|
||||
MediaFormat fmtTable[] = {
|
||||
GeneralMediaFormat::Unknown,
|
||||
MediaFormat(GeneralMediaFormat::Aac, SubFormats::AacMpeg4MainProfile),
|
||||
|
@ -1369,15 +1365,15 @@ void Mp4Track::internalParseHeader()
|
|||
m_format += Mpeg4AudioObjectIds::idToMediaFormat(m_esInfo->audioSpecificConfig->audioObjectType, m_esInfo->audioSpecificConfig->sbrPresent, m_esInfo->audioSpecificConfig->psPresent);
|
||||
if(m_esInfo->audioSpecificConfig->sampleFrequencyIndex == 0xF) {
|
||||
m_sampleRate = m_esInfo->audioSpecificConfig->sampleFrequency;
|
||||
} else if(m_esInfo->audioSpecificConfig->sampleFrequencyIndex < sizeof(sampleRateTable)) {
|
||||
m_sampleRate = sampleRateTable[m_esInfo->audioSpecificConfig->sampleFrequencyIndex];
|
||||
} else if(m_esInfo->audioSpecificConfig->sampleFrequencyIndex < sizeof(mpeg4SampleRateTable)) {
|
||||
m_sampleRate = mpeg4SampleRateTable[m_esInfo->audioSpecificConfig->sampleFrequencyIndex];
|
||||
} else {
|
||||
addNotification(NotificationType::Warning, "Audio specific config has invalid sample frequency index.", context);
|
||||
}
|
||||
if(m_esInfo->audioSpecificConfig->extensionSampleFrequencyIndex == 0xF) {
|
||||
m_extensionSampleRate = m_esInfo->audioSpecificConfig->extensionSampleFrequency;
|
||||
} else if(m_esInfo->audioSpecificConfig->extensionSampleFrequencyIndex < sizeof(sampleRateTable)) {
|
||||
m_extensionSampleRate = sampleRateTable[m_esInfo->audioSpecificConfig->extensionSampleFrequencyIndex];
|
||||
} else if(m_esInfo->audioSpecificConfig->extensionSampleFrequencyIndex < sizeof(mpeg4SampleRateTable)) {
|
||||
m_extensionSampleRate = mpeg4SampleRateTable[m_esInfo->audioSpecificConfig->extensionSampleFrequencyIndex];
|
||||
} else {
|
||||
addNotification(NotificationType::Warning, "Audio specific config has invalid extension sample frequency index.", context);
|
||||
}
|
||||
|
@ -1397,7 +1393,7 @@ void Mp4Track::internalParseHeader()
|
|||
MpegAudioFrame frame;
|
||||
m_istream->seekg(m_stcoAtom->dataOffset() + 8);
|
||||
m_istream->seekg(m_chunkOffsetSize == 8 ? reader.readUInt64BE() : reader.readUInt32BE());
|
||||
frame.parseHeader(*m_istream);
|
||||
frame.parseHeader(reader);
|
||||
MpegAudioFrameStream::addInfo(frame, *this);
|
||||
break;
|
||||
} default:
|
||||
|
|
|
@ -28,15 +28,14 @@ const int MpegAudioFrame::m_bitrateTable[0x2][0x3][0xF] =
|
|||
const uint32 MpegAudioFrame::m_sync = 0xFFE00000u;
|
||||
|
||||
/*!
|
||||
* \brief Parses the header read from the specified \a stream at the current position.
|
||||
* \brief Parses the header read using the specified \a reader.
|
||||
* \throws Throws InvalidDataException if the data read from the stream is
|
||||
* no valid frame header.
|
||||
*/
|
||||
void MpegAudioFrame::parseHeader(istream &stream)
|
||||
void MpegAudioFrame::parseHeader(BinaryReader &reader)
|
||||
{
|
||||
BinaryReader reader(&stream);
|
||||
m_header = reader.readUInt32BE();
|
||||
stream.seekg(m_xingHeaderOffset - 4, ios_base::cur);
|
||||
reader.stream()->seekg(m_xingHeaderOffset - 4, ios_base::cur);
|
||||
m_xingHeader = reader.readUInt64BE();
|
||||
m_xingHeaderFlags = static_cast<XingHeaderFlags>(m_xingHeader & 0xffffffffuL);
|
||||
if(isXingHeaderAvailable()) {
|
||||
|
@ -47,7 +46,7 @@ void MpegAudioFrame::parseHeader(istream &stream)
|
|||
m_xingBytesfield = reader.readUInt32BE();
|
||||
}
|
||||
if(isXingTocFieldPresent()) {
|
||||
stream.seekg(64, ios_base::cur);
|
||||
reader.stream()->seekg(64, ios_base::cur);
|
||||
}
|
||||
if(isXingQualityIndicatorFieldPresent()) {
|
||||
m_xingQualityIndicator = reader.readUInt32BE();
|
||||
|
|
|
@ -6,6 +6,10 @@
|
|||
|
||||
#include <iostream>
|
||||
|
||||
namespace IoUtilities {
|
||||
class BinaryReader;
|
||||
}
|
||||
|
||||
namespace Media
|
||||
{
|
||||
|
||||
|
@ -35,7 +39,7 @@ class LIB_EXPORT MpegAudioFrame
|
|||
public:
|
||||
MpegAudioFrame();
|
||||
|
||||
void parseHeader(std::istream &stream);
|
||||
void parseHeader(IoUtilities::BinaryReader &reader);
|
||||
|
||||
bool isValid() const;
|
||||
double mpegVersion() const;
|
||||
|
|
|
@ -14,30 +14,9 @@ namespace Media {
|
|||
|
||||
/*!
|
||||
* \class Media::MpegAudioFrameStream
|
||||
* \brief Implementation of Media::AbstractTrack for a stream of
|
||||
* MPEG audio frames (run-of-the-mill MP3 file).
|
||||
* \brief Implementation of Media::AbstractTrack MPEG audio streams.
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \brief Constructs a new track for the \a stream at the specified \a startOffset.
|
||||
*/
|
||||
MpegAudioFrameStream::MpegAudioFrameStream(iostream &stream, uint64 startOffset) :
|
||||
AbstractTrack(stream, startOffset)
|
||||
{
|
||||
m_mediaType = MediaType::Audio;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Destroys the track.
|
||||
*/
|
||||
MpegAudioFrameStream::~MpegAudioFrameStream()
|
||||
{}
|
||||
|
||||
TrackType MpegAudioFrameStream::type() const
|
||||
{
|
||||
return TrackType::MpegAudioFrameStream;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds the information from the specified \a frame to the specified \a track.
|
||||
*/
|
||||
|
@ -66,7 +45,7 @@ void MpegAudioFrameStream::internalParseHeader()
|
|||
// parse frame header
|
||||
m_frames.emplace_back();
|
||||
MpegAudioFrame &frame = m_frames.back();
|
||||
frame.parseHeader(*m_istream);
|
||||
frame.parseHeader(m_reader);
|
||||
addInfo(frame, *this);
|
||||
if(frame.isXingBytesfieldPresent()) {
|
||||
uint32 xingSize = frame.xingBytesfield();
|
||||
|
|
|
@ -26,6 +26,23 @@ private:
|
|||
std::list<MpegAudioFrame> m_frames;
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Constructs a new track for the \a stream at the specified \a startOffset.
|
||||
*/
|
||||
inline MpegAudioFrameStream::MpegAudioFrameStream(std::iostream &stream, uint64 startOffset) :
|
||||
AbstractTrack(stream, startOffset)
|
||||
{
|
||||
m_mediaType = MediaType::Audio;
|
||||
}
|
||||
|
||||
inline MpegAudioFrameStream::~MpegAudioFrameStream()
|
||||
{}
|
||||
|
||||
inline TrackType MpegAudioFrameStream::type() const
|
||||
{
|
||||
return TrackType::MpegAudioFrameStream;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // MPEGAUDIOFRAMESTREAM_H
|
||||
|
|
|
@ -66,7 +66,7 @@ enum Sig24 : uint32
|
|||
Bzip2 = 0x425A68u,
|
||||
Gzip = 0x1F8B08u,
|
||||
Id3v2 = 0x494433u,
|
||||
Utf8Text = 0xEFBBBFu
|
||||
Utf8Text = 0xEFBBBFu,
|
||||
};
|
||||
|
||||
/*!
|
||||
|
@ -74,6 +74,8 @@ enum Sig24 : uint32
|
|||
*/
|
||||
enum Sig16 : uint16
|
||||
{
|
||||
Adts = 0xFFF0u,
|
||||
AdtsMask = 0xFFF6u,
|
||||
Jpeg = 0xffd8u,
|
||||
Lha = 0x1FA0u,
|
||||
Lzw = 0x1F9Du,
|
||||
|
@ -202,6 +204,9 @@ ContainerFormat parseSignature(const char *buffer, int bufferSize)
|
|||
default:
|
||||
;
|
||||
}
|
||||
if(((sig >> 48) & AdtsMask) == Adts) {
|
||||
return ContainerFormat::Adts;
|
||||
}
|
||||
return ContainerFormat::Unknown;
|
||||
}
|
||||
|
||||
|
@ -282,6 +287,8 @@ const char *containerFormatAbbreviation(ContainerFormat containerFormat, MediaTy
|
|||
const char *containerFormatName(ContainerFormat containerFormat)
|
||||
{
|
||||
switch(containerFormat) {
|
||||
case ContainerFormat::Adts:
|
||||
return "Audio Data Transport Stream";
|
||||
case ContainerFormat::Asf:
|
||||
return "Advanced Systems Format";
|
||||
case ContainerFormat::Elf:
|
||||
|
|
|
@ -14,6 +14,7 @@ namespace Media {
|
|||
enum class ContainerFormat
|
||||
{
|
||||
Unknown, /**< unknown container format */
|
||||
Adts, /** < Audio Data Transport Stream */
|
||||
Asf, /**< Advanced Systems Format */
|
||||
Bzip2, /** bzip2 compressed file */
|
||||
Elf, /**< Executable and Linkable Format */
|
||||
|
|
Loading…
Reference in New Issue