parse audio specific config for AAC tracks in MKV container (exposed API

in Mp4Track to do that)
renamed sampleRate to samplingFrequency
This commit is contained in:
Martchus 2015-08-13 03:23:28 +02:00
parent 8dc85941eb
commit 3d6c7f33d9
10 changed files with 145 additions and 124 deletions

View File

@ -43,8 +43,8 @@ AbstractTrack::AbstractTrack(istream &inputStream, ostream &outputStream, uint64
m_id(0),
m_bitrate(0.0),
m_maxBitrate(0.0),
m_sampleRate(0),
m_extensionSampleRate(0),
m_samplingFrequency(0),
m_extensionSamplingFrequency(0),
m_bitsPerSample(0),
m_bytesPerSecond(0),
m_channelCount(0),

View File

@ -123,8 +123,8 @@ protected:
ChronoUtilities::DateTime m_creationTime;
ChronoUtilities::DateTime m_modificationTime;
std::string m_language;
uint32 m_sampleRate;
uint32 m_extensionSampleRate;
uint32 m_samplingFrequency;
uint32 m_extensionSamplingFrequency;
uint16 m_bitsPerSample;
uint32 m_bytesPerSecond;
uint16 m_channelCount;
@ -371,7 +371,7 @@ inline const std::string &AbstractTrack::language() const
*/
inline uint32 AbstractTrack::samplingFrequency() const
{
return m_sampleRate;
return m_samplingFrequency;
}
/*!
@ -380,7 +380,7 @@ inline uint32 AbstractTrack::samplingFrequency() const
*/
inline uint32 AbstractTrack::extensionSamplingFrequency() const
{
return m_extensionSampleRate;
return m_extensionSamplingFrequency;
}
/*!

View File

@ -33,7 +33,7 @@ void AdtsStream::internalParseHeader()
m_format = Mpeg4AudioObjectIds::idToMediaFormat(m_firstFrame.mpeg4AudioObjectId());
m_channelCount = Mpeg4ChannelConfigs::channelCount(m_channelConfig = m_firstFrame.mpeg4ChannelConfig());
byte sampleRateIndex = m_firstFrame.mpeg4SamplingFrequencyIndex();
m_sampleRate = sampleRateIndex < sizeof(mpeg4SamplingFrequencyTable) ? mpeg4SamplingFrequencyTable[sampleRateIndex] : 0;
m_samplingFrequency = sampleRateIndex < sizeof(mpeg4SamplingFrequencyTable) ? mpeg4SamplingFrequencyTable[sampleRateIndex] : 0;
}
} // namespace Media

View File

@ -86,8 +86,8 @@ const char *matroskaIdName(uint32 matroskaId)
case TrackAudio: return "audio track";
case TrackVideo: return "video track";
case ContentEncodings: return "content encodings";
case CodecID: return "content id";
case CodecPrivate: return "code private";
case CodecID: return "codec id";
case CodecPrivate: return "codec private";
case CodecName: return "codec name";
case TrackName: return "track name";
case TrackLanguage: return "track language";

View File

@ -6,6 +6,7 @@
#include "../avi/bitmapinfoheader.h"
#include "../wav/waveaudiostream.h"
#include "../mp4/mp4ids.h"
#include "../mp4/mp4track.h"
#include "../mediaformat.h"
#include "../exceptions.h"
@ -285,7 +286,14 @@ void MatroskaTrack::internalParseHeader()
m_channelCount = subElement->readUInteger();
break;
case MatroskaIds::SamplingFrequency:
m_sampleRate = subElement->readFloat();
if(!m_samplingFrequency) {
m_samplingFrequency = subElement->readFloat();
}
break;
case MatroskaIds::OutputSamplingFrequency:
if(!m_extensionSamplingFrequency) {
m_extensionSamplingFrequency = subElement->readFloat();
}
break;
default:
;
@ -307,9 +315,6 @@ void MatroskaTrack::internalParseHeader()
break;
case MatroskaIds::CodecID:
m_format = codecIdToMediaFormat(m_formatId = trackInfoElement->readString());
if(m_formatName.empty()) {
m_formatName = m_format ? string(m_format.name()) : m_formatId;
}
break;
case MatroskaIds::CodecName:
m_formatName = trackInfoElement->readString();
@ -377,6 +382,27 @@ void MatroskaTrack::internalParseHeader()
}
}
break;
case GeneralMediaFormat::Aac:
if((codecPrivateElement = m_trackElement->childById(MatroskaIds::CodecPrivate))) {
auto audioSpecificConfig = Mp4Track::parseAudioSpecificConfig(*this, *m_istream, codecPrivateElement->dataOffset(), codecPrivateElement->dataSize());
m_format += Mpeg4AudioObjectIds::idToMediaFormat(audioSpecificConfig->audioObjectType, audioSpecificConfig->sbrPresent, audioSpecificConfig->psPresent);
if(audioSpecificConfig->sampleFrequencyIndex == 0xF) {
//m_samplingFrequency = audioSpecificConfig->sampleFrequency;
} else if(audioSpecificConfig->sampleFrequencyIndex < sizeof(mpeg4SamplingFrequencyTable)) {
//m_samplingFrequency = mpeg4SamplingFrequencyTable[audioSpecificConfig->sampleFrequencyIndex];
} else {
addNotification(NotificationType::Warning, "Audio specific config has invalid sample frequency index.", context);
}
if(audioSpecificConfig->extensionSampleFrequencyIndex == 0xF) {
//m_extensionSamplingFrequency = audioSpecificConfig->extensionSampleFrequency;
} else if(audioSpecificConfig->extensionSampleFrequencyIndex < sizeof(mpeg4SamplingFrequencyTable)) {
//m_extensionSamplingFrequency = mpeg4SamplingFrequencyTable[audioSpecificConfig->extensionSampleFrequencyIndex];
} else {
addNotification(NotificationType::Warning, "Audio specific config has invalid extension sample frequency index.", context);
}
m_channelConfig = audioSpecificConfig->channelConfiguration;
}
break;
default:
;
}

View File

@ -438,54 +438,51 @@ vector<uint64> Mp4Track::readChunkSizes()
* - Returns an empty configuration for non-AVC tracks.
* - Notifications might be added.
*/
AvcConfiguration Mp4Track::parseAvcConfiguration(Mp4Atom *avcConfigAtom)
AvcConfiguration Mp4Track::parseAvcConfiguration(StatusProvider &statusProvider, BinaryReader &reader, uint64 startOffset, uint64 size)
{
AvcConfiguration config;
if(avcConfigAtom) {
try {
auto configSize = avcConfigAtom->dataSize();
if(avcConfigAtom && configSize >= 5) {
// skip first byte (is always 1)
m_istream->seekg(avcConfigAtom->dataOffset() + 1);
// read profile, IDC level, NALU size length
config.profileIdc = m_reader.readByte();
config.profileCompat = m_reader.readByte();
config.levelIdc = m_reader.readByte();
config.naluSizeLength = m_reader.readByte() & 0x03;
// read SPS infos
if((configSize -= 5) >= 3) {
byte entryCount = m_reader.readByte() & 0x0f;
uint16 entrySize;
while(entryCount && configSize) {
if((entrySize = m_reader.readUInt16BE()) <= configSize) {
try {
if(size >= 5) {
// skip first byte (is always 1)
reader.stream()->seekg(startOffset + 1);
// read profile, IDC level, NALU size length
config.profileIdc = reader.readByte();
config.profileCompat = reader.readByte();
config.levelIdc = reader.readByte();
config.naluSizeLength = reader.readByte() & 0x03;
// read SPS infos
if((size -= 5) >= 3) {
byte entryCount = reader.readByte() & 0x0f;
uint16 entrySize;
while(entryCount && size) {
if((entrySize = reader.readUInt16BE()) <= size) {
// TODO: read entry
size -= entrySize;
} else {
throw TruncatedDataException();
}
--entryCount;
}
// read PPS infos
if((size -= 5) >= 3) {
entryCount = reader.readByte();
while(entryCount && size) {
if((entrySize = reader.readUInt16BE()) <= size) {
// TODO: read entry
configSize -= entrySize;
size -= entrySize;
} else {
throw TruncatedDataException();
}
--entryCount;
}
// read PPS infos
if((configSize -= 5) >= 3) {
entryCount = m_reader.readByte();
while(entryCount && configSize) {
if((entrySize = m_reader.readUInt16BE()) <= configSize) {
// TODO: read entry
configSize -= entrySize;
} else {
throw TruncatedDataException();
}
--entryCount;
}
// TODO: read trailer
return config;
}
// TODO: read trailer
return config;
}
}
throw TruncatedDataException();
} catch (TruncatedDataException &) {
addNotification(NotificationType::Critical, "AVC configuration is truncated.", "parsing AVC configuration");
}
throw TruncatedDataException();
} catch (TruncatedDataException &) {
statusProvider.addNotification(NotificationType::Critical, "AVC configuration is truncated.", "parsing AVC configuration");
}
return config;
}
@ -496,51 +493,51 @@ AvcConfiguration Mp4Track::parseAvcConfiguration(Mp4Atom *avcConfigAtom)
* - Notifications might be added.
* \sa mpeg4ElementaryStreamInfo()
*/
std::unique_ptr<Mpeg4ElementaryStreamInfo> Mp4Track::parseMpeg4ElementaryStreamInfo(Mp4Atom *esDescAtom)
std::unique_ptr<Mpeg4ElementaryStreamInfo> Mp4Track::parseMpeg4ElementaryStreamInfo(StatusProvider &statusProvider, IoUtilities::BinaryReader &reader, Mp4Atom *esDescAtom)
{
static const string context("parsing MPEG-4 elementary stream descriptor");
using namespace Mpeg4ElementaryStreamObjectIds;
unique_ptr<Mpeg4ElementaryStreamInfo> esInfo;
if(esDescAtom->dataSize() >= 12) {
m_istream->seekg(esDescAtom->dataOffset());
reader.stream()->seekg(esDescAtom->dataOffset());
// read version/flags
if(m_reader.readUInt32BE() != 0) {
addNotification(NotificationType::Warning, "Unknown version/flags.", context);
if(reader.readUInt32BE() != 0) {
statusProvider.addNotification(NotificationType::Warning, "Unknown version/flags.", context);
}
// read extended descriptor
Mpeg4Descriptor esDesc(esDescAtom->container(), m_istream->tellg(), esDescAtom->dataSize() - 4);
Mpeg4Descriptor esDesc(esDescAtom->container(), reader.stream()->tellg(), esDescAtom->dataSize() - 4);
try {
esDesc.parse();
// check ID
if(esDesc.id() != Mpeg4DescriptorIds::ElementaryStreamDescr) {
addNotification(NotificationType::Critical, "Invalid descriptor found.", context);
statusProvider.addNotification(NotificationType::Critical, "Invalid descriptor found.", context);
throw Failure();
}
// read stream info
m_istream->seekg(esDesc.dataOffset());
reader.stream()->seekg(esDesc.dataOffset());
esInfo = make_unique<Mpeg4ElementaryStreamInfo>();
esInfo->id = m_reader.readUInt16BE();
esInfo->esDescFlags = m_reader.readByte();
esInfo->id = reader.readUInt16BE();
esInfo->esDescFlags = reader.readByte();
if(esInfo->dependencyFlag()) {
esInfo->dependsOnId = m_reader.readUInt16BE();
esInfo->dependsOnId = reader.readUInt16BE();
}
if(esInfo->urlFlag()) {
esInfo->url = m_reader.readString(m_reader.readByte());
esInfo->url = reader.readString(reader.readByte());
}
if(esInfo->ocrFlag()) {
esInfo->ocrId = m_reader.readUInt16BE();
esInfo->ocrId = reader.readUInt16BE();
}
for(Mpeg4Descriptor *esDescChild = esDesc.denoteFirstChild(static_cast<uint64>(m_istream->tellg()) - esDesc.startOffset()); esDescChild; esDescChild = esDescChild->nextSibling()) {
for(Mpeg4Descriptor *esDescChild = esDesc.denoteFirstChild(static_cast<uint64>(reader.stream()->tellg()) - esDesc.startOffset()); esDescChild; esDescChild = esDescChild->nextSibling()) {
esDescChild->parse();
switch(esDescChild->id()) {
case Mpeg4DescriptorIds::DecoderConfigDescr:
// read decoder config descriptor
m_istream->seekg(esDescChild->dataOffset());
esInfo->objectTypeId = m_reader.readByte();
esInfo->decCfgDescFlags = m_reader.readByte();
esInfo->bufferSize = m_reader.readUInt24BE();
esInfo->maxBitrate = m_reader.readUInt32BE();
esInfo->averageBitrate = m_reader.readUInt32BE();
reader.stream()->seekg(esDescChild->dataOffset());
esInfo->objectTypeId = reader.readByte();
esInfo->decCfgDescFlags = reader.readByte();
esInfo->bufferSize = reader.readUInt24BE();
esInfo->maxBitrate = reader.readUInt32BE();
esInfo->averageBitrate = reader.readUInt32BE();
for(Mpeg4Descriptor *decCfgDescChild = esDescChild->denoteFirstChild(esDescChild->headerSize() + 13); decCfgDescChild; decCfgDescChild = decCfgDescChild->nextSibling()) {
decCfgDescChild->parse();
switch(decCfgDescChild->id()) {
@ -549,10 +546,10 @@ std::unique_ptr<Mpeg4ElementaryStreamInfo> Mp4Track::parseMpeg4ElementaryStreamI
switch(esInfo->objectTypeId) {
case Aac: case Mpeg2AacMainProfile: case Mpeg2AacLowComplexityProfile:
case Mpeg2AacScaleableSamplingRateProfile: case Mpeg2Audio: case Mpeg1Audio:
esInfo->audioSpecificConfig = parseAudioSpecificConfig(decCfgDescChild);
esInfo->audioSpecificConfig = parseAudioSpecificConfig(statusProvider, *reader.stream(), decCfgDescChild->dataOffset(), decCfgDescChild->dataSize());
break;
case Mpeg4Visual:
esInfo->videoSpecificConfig = parseVideoSpecificConfig(decCfgDescChild);
esInfo->videoSpecificConfig = parseVideoSpecificConfig(statusProvider, reader, decCfgDescChild->dataOffset(), decCfgDescChild->dataSize());
break;
default:
; // TODO: cover more object types
@ -567,10 +564,10 @@ std::unique_ptr<Mpeg4ElementaryStreamInfo> Mp4Track::parseMpeg4ElementaryStreamI
}
}
} catch (Failure &) {
addNotification(NotificationType::Critical, "The MPEG-4 descriptor element structure is invalid.", context);
statusProvider.addNotification(NotificationType::Critical, "The MPEG-4 descriptor element structure is invalid.", context);
}
} else {
addNotification(NotificationType::Warning, "Elementary stream descriptor atom (esds) is truncated.", context);
statusProvider.addNotification(NotificationType::Warning, "Elementary stream descriptor atom (esds) is truncated.", context);
}
return esInfo;
}
@ -581,16 +578,15 @@ std::unique_ptr<Mpeg4ElementaryStreamInfo> Mp4Track::parseMpeg4ElementaryStreamI
* - Notifications might be added.
* \sa mpeg4ElementaryStreamInfo()
*/
unique_ptr<Mpeg4AudioSpecificConfig> Mp4Track::parseAudioSpecificConfig(Mpeg4Descriptor *decSpecInfoDesc)
unique_ptr<Mpeg4AudioSpecificConfig> Mp4Track::parseAudioSpecificConfig(StatusProvider &statusProvider, istream &stream, uint64 startOffset, uint64 size)
{
static const string context("parsing MPEG-4 audio specific config from elementary stream descriptor");
using namespace Mpeg4AudioObjectIds;
// read config into buffer and construct BitReader for bitwise reading
m_istream->seekg(decSpecInfoDesc->dataOffset());
//cout << "audio cfg @" << decSpecInfoDesc->dataOffset() << endl;
auto buff = make_unique<char []>(decSpecInfoDesc->dataSize());
m_istream->read(buff.get(), decSpecInfoDesc->dataSize());
BitReader bitReader(buff.get(), decSpecInfoDesc->dataSize());
stream.seekg(startOffset);
auto buff = make_unique<char []>(size);
stream.read(buff.get(), size);
BitReader bitReader(buff.get(), size);
auto audioCfg = make_unique<Mpeg4AudioSpecificConfig>();
try {
// read audio object type
@ -703,15 +699,15 @@ unique_ptr<Mpeg4AudioSpecificConfig> Mp4Track::parseAudioSpecificConfig(Mpeg4Des
}
}
} catch(ios_base::failure &) {
if(m_istream->fail()) {
if(stream.fail()) {
// IO error caused by input stream
throw;
} else {
// IO error caused by bitReader
addNotification(NotificationType::Critical, "Audio specific configuration is truncated.", context);
statusProvider.addNotification(NotificationType::Critical, "Audio specific configuration is truncated.", context);
}
} catch(NotImplementedException &) {
addNotification(NotificationType::Information, "Not implemented for the format of audio track.", context);
statusProvider.addNotification(NotificationType::Information, "Not implemented for the format of audio track.", context);
}
return audioCfg;
}
@ -722,24 +718,23 @@ unique_ptr<Mpeg4AudioSpecificConfig> Mp4Track::parseAudioSpecificConfig(Mpeg4Des
* - Notifications might be added.
* \sa mpeg4ElementaryStreamInfo()
*/
std::unique_ptr<Mpeg4VideoSpecificConfig> Mp4Track::parseVideoSpecificConfig(Mpeg4Descriptor *decSpecInfoDesc)
std::unique_ptr<Mpeg4VideoSpecificConfig> Mp4Track::parseVideoSpecificConfig(StatusProvider &statusProvider, BinaryReader &reader, uint64 startOffset, uint64 size)
{
static const string context("parsing MPEG-4 video specific config from elementary stream descriptor");
using namespace Mpeg4AudioObjectIds;
auto videoCfg = make_unique<Mpeg4VideoSpecificConfig>();
// seek to start
m_istream->seekg(decSpecInfoDesc->dataOffset());
uint64 bytesRemaining = decSpecInfoDesc->dataSize();
if(bytesRemaining > 3 && (m_reader.readUInt24BE() == 1)) {
bytesRemaining -= 3;
reader.stream()->seekg(startOffset);
if(size > 3 && (reader.readUInt24BE() == 1)) {
size -= 3;
uint32 buff1;
while(bytesRemaining) {
--bytesRemaining;
switch(m_reader.readByte()) { // read start code
while(size) {
--size;
switch(reader.readByte()) { // read start code
case Mpeg4VideoCodes::VisualObjectSequenceStart:
if(bytesRemaining) {
videoCfg->profile = m_reader.readByte();
--bytesRemaining;
if(size) {
videoCfg->profile = reader.readByte();
--size;
}
break;
case Mpeg4VideoCodes::VideoObjectLayerStart:
@ -747,19 +742,19 @@ std::unique_ptr<Mpeg4VideoSpecificConfig> Mp4Track::parseVideoSpecificConfig(Mpe
break;
case Mpeg4VideoCodes::UserDataStart:
buff1 = 0;
while(bytesRemaining >= 3) {
if((buff1 = m_reader.readUInt24BE()) != 1) {
m_istream->seekg(-2, ios_base::cur);
while(size >= 3) {
if((buff1 = reader.readUInt24BE()) != 1) {
reader.stream()->seekg(-2, ios_base::cur);
videoCfg->userData.push_back(buff1 >> 16);
--bytesRemaining;
--size;
} else {
bytesRemaining -= 3;
size -= 3;
break;
}
}
if(buff1 != 1 && bytesRemaining > 0) {
videoCfg->userData += m_reader.readString(bytesRemaining);
bytesRemaining = 0;
if(buff1 != 1 && size > 0) {
videoCfg->userData += reader.readString(size);
size = 0;
}
break;
default:
@ -767,18 +762,18 @@ std::unique_ptr<Mpeg4VideoSpecificConfig> Mp4Track::parseVideoSpecificConfig(Mpe
}
// skip stuff we're not interested in to get the start of the
// next video object
while(bytesRemaining >= 3) {
if(m_reader.readUInt24BE() != 1) {
m_istream->seekg(-2, ios_base::cur);
--bytesRemaining;
while(size >= 3) {
if(reader.readUInt24BE() != 1) {
reader.stream()->seekg(-2, ios_base::cur);
--size;
} else {
bytesRemaining -= 3;
size -= 3;
break;
}
}
}
} else {
addNotification(NotificationType::Critical, "\"Visual Object Sequence Header\" not found.", context);
statusProvider.addNotification(NotificationType::Critical, "\"Visual Object Sequence Header\" not found.", context);
}
return videoCfg;
}
@ -1285,10 +1280,10 @@ void Mp4Track::internalParseHeader()
m_channelCount = reader.readUInt16BE();
m_bitsPerSample = reader.readUInt16BE();
m_istream->seekg(4, ios_base::cur); // skip reserved bytes (again)
if(!m_sampleRate) {
m_sampleRate = reader.readUInt32BE() >> 16;
if(!m_samplingFrequency) {
m_samplingFrequency = reader.readUInt32BE() >> 16;
if(codecConfigContainerAtom->id() != FourccIds::DolbyMpl) {
m_sampleRate >>= 16;
m_samplingFrequency >>= 16;
}
} else {
m_istream->seekg(4, ios_base::cur);
@ -1357,7 +1352,7 @@ void Mp4Track::internalParseHeader()
}
if(esDescAtom) {
try {
if((m_esInfo = parseMpeg4ElementaryStreamInfo(esDescAtom))) {
if((m_esInfo = parseMpeg4ElementaryStreamInfo(*this, m_reader, esDescAtom))) {
m_format += Mpeg4ElementaryStreamObjectIds::streamObjectTypeFormat(m_esInfo->objectTypeId);
m_bitrate = static_cast<double>(m_esInfo->averageBitrate) / 1000;
m_maxBitrate = static_cast<double>(m_esInfo->maxBitrate) / 1000;
@ -1365,16 +1360,16 @@ void Mp4Track::internalParseHeader()
// check the audio specific config for useful information
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;
m_samplingFrequency = m_esInfo->audioSpecificConfig->sampleFrequency;
} else if(m_esInfo->audioSpecificConfig->sampleFrequencyIndex < sizeof(mpeg4SamplingFrequencyTable)) {
m_sampleRate = mpeg4SamplingFrequencyTable[m_esInfo->audioSpecificConfig->sampleFrequencyIndex];
m_samplingFrequency = mpeg4SamplingFrequencyTable[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;
m_extensionSamplingFrequency = m_esInfo->audioSpecificConfig->extensionSampleFrequency;
} else if(m_esInfo->audioSpecificConfig->extensionSampleFrequencyIndex < sizeof(mpeg4SamplingFrequencyTable)) {
m_extensionSampleRate = mpeg4SamplingFrequencyTable[m_esInfo->audioSpecificConfig->extensionSampleFrequencyIndex];
m_extensionSamplingFrequency = mpeg4SamplingFrequencyTable[m_esInfo->audioSpecificConfig->extensionSampleFrequencyIndex];
} else {
addNotification(NotificationType::Warning, "Audio specific config has invalid extension sample frequency index.", context);
}

View File

@ -133,10 +133,10 @@ public:
const Mpeg4ElementaryStreamInfo *mpeg4ElementaryStreamInfo() const;
// methods to parse configuration details from the track header
AvcConfiguration parseAvcConfiguration(Mp4Atom *avcConfigAtom);
std::unique_ptr<Mpeg4ElementaryStreamInfo> parseMpeg4ElementaryStreamInfo(Mp4Atom *esDescAtom);
std::unique_ptr<Mpeg4AudioSpecificConfig> parseAudioSpecificConfig(Mpeg4Descriptor *decSpecInfoDesc);
std::unique_ptr<Mpeg4VideoSpecificConfig> parseVideoSpecificConfig(Mpeg4Descriptor *decSpecInfoDesc);
static AvcConfiguration parseAvcConfiguration(StatusProvider &statusProvider, IoUtilities::BinaryReader &reader, uint64 startOffset, uint64 size);
static std::unique_ptr<Mpeg4ElementaryStreamInfo> parseMpeg4ElementaryStreamInfo(StatusProvider &statusProvider, IoUtilities::BinaryReader &reader, Mp4Atom *esDescAtom);
static std::unique_ptr<Mpeg4AudioSpecificConfig> parseAudioSpecificConfig(StatusProvider &statusProvider, std::istream &stream, uint64 startOffset, uint64 size);
static std::unique_ptr<Mpeg4VideoSpecificConfig> parseVideoSpecificConfig(StatusProvider &statusProvider, IoUtilities::BinaryReader &reader, uint64 startOffset, uint64 size);
// methods to read the "index" (chunk offsets and sizes)
std::vector<uint64> readChunkOffsets();

View File

@ -26,7 +26,7 @@ void MpegAudioFrameStream::addInfo(const MpegAudioFrame &frame, AbstractTrack &t
track.m_format = MediaFormat(GeneralMediaFormat::Mpeg1Audio, frame.layer());
track.m_channelCount = frame.channelMode() == MpegChannelMode::SingleChannel ? 1 : 2;
track.m_channelConfig = static_cast<byte>(frame.channelMode());
track.m_sampleRate = frame.samplingFrequency();
track.m_samplingFrequency = frame.samplingFrequency();
}
void MpegAudioFrameStream::internalParseHeader()

View File

@ -78,7 +78,7 @@ void OggStream::internalParseHeader()
VorbisIdentificationHeader ind;
ind.parseHeader(iterator);
m_channelCount = ind.channels();
m_sampleRate = ind.sampleRate();
m_samplingFrequency = ind.sampleRate();
if(ind.nominalBitrate()) {
m_bitrate = ind.nominalBitrate();
} else if(ind.maxBitrate() == ind.minBitrate()) {
@ -96,7 +96,7 @@ void OggStream::internalParseHeader()
auto lastPage = find_if(pages.crbegin(), pages.crend(), pred);
if(firstPage != pages.cend() && lastPage != pages.crend()) {
m_sampleCount = lastPage->absoluteGranulePosition() - firstPage->absoluteGranulePosition();
m_duration = TimeSpan::fromSeconds(static_cast<double>(m_sampleCount) / m_sampleRate);
m_duration = TimeSpan::fromSeconds(static_cast<double>(m_sampleCount) / m_samplingFrequency);
}
}
hasIdentificationHeader = true;

View File

@ -86,7 +86,7 @@ void WaveAudioStream::addInfo(const WaveFormatHeader &waveHeader, AbstractTrack
{
track.m_format = waveHeader.format();
track.m_channelCount = waveHeader.channelCount;
track.m_sampleRate = waveHeader.sampleRate;
track.m_samplingFrequency = waveHeader.sampleRate;
track.m_bytesPerSecond = waveHeader.bytesPerSecond;
track.m_chunkSize = waveHeader.chunkSize;
track.m_bitsPerSample = waveHeader.bitsPerSample;
@ -114,7 +114,7 @@ void WaveAudioStream::internalParseHeader()
if(m_reader.readUInt32BE() == 0x64617461u) {
m_size = m_reader.readUInt32LE();
m_sampleCount = m_size / m_chunkSize;
m_duration = ChronoUtilities::TimeSpan::fromSeconds(static_cast<double>(m_sampleCount) / static_cast<double>(m_sampleRate));
m_duration = ChronoUtilities::TimeSpan::fromSeconds(static_cast<double>(m_sampleCount) / static_cast<double>(m_samplingFrequency));
} else {
throw NoDataFoundException();
}