Tag Parser  10.0.0
C++ library for reading and writing MP4 (iTunes), ID3, Vorbis, Opus, FLAC and Matroska tags
matroskatrack.cpp
Go to the documentation of this file.
1 #include "./matroskatrack.h"
2 #include "./ebmlelement.h"
3 #include "./matroskacontainer.h"
4 #include "./matroskaid.h"
5 #include "./matroskatag.h"
6 
7 #include "../avi/bitmapinfoheader.h"
8 
9 #include "../wav/waveaudiostream.h"
10 
11 #include "../avc/avcconfiguration.h"
12 
13 #include "../mp4/mp4ids.h"
14 #include "../mp4/mp4track.h"
15 
16 #include "../exceptions.h"
17 #include "../mediaformat.h"
18 
19 #include <c++utilities/conversion/stringconversion.h>
20 
21 using namespace std;
22 using namespace CppUtilities;
23 
24 namespace TagParser {
25 
37 MatroskaTrack::MatroskaTrack(EbmlElement &trackElement)
38  : AbstractTrack(trackElement.stream(), trackElement.startOffset())
39  , m_trackElement(&trackElement)
40 {
41 }
42 
47 {
48 }
49 
51 {
53 }
54 
60 {
61  auto parts = splitString<vector<string>>(codecId, "/", EmptyPartsTreat::Keep, 3);
62  parts.resize(3);
63  const auto &part1 = parts[0], &part2 = parts[1], &part3 = parts[2];
64  MediaFormat fmt;
65  if (part1 == "V_MS" && part2 == "VFW" && part3 == "FOURCC") {
67  } else if (part1 == "V_UNCOMPRESSED") {
69  } else if (part1 == "V_MPEG4") {
71  if (part2 == "ISO") {
72  if (part3 == "SP") {
74  } else if (part3 == "ASP") {
76  } else if (part3 == "AVC") {
78  }
79  } else if (part2 == "MS" && part3 == "V3") {
81  }
82  } else if (part1 == "V_MPEG1") {
84  } else if (part1 == "V_MPEG2") {
86  } else if (part1 == "V_REAL") {
88  } else if (part1 == "V_QUICKTIME") {
90  } else if (part1 == "V_THEORA") {
92  } else if (part1 == "V_PRORES") {
94  } else if (part1 == "V_VP8") {
96  } else if (part1 == "V_VP9") {
98  } else if (part1 == "V_AV1") {
100  } else if (part1 == "A_MPEG") {
102  if (part2 == "L1") {
104  } else if (part2 == "L2") {
106  } else if (part2 == "L3") {
108  }
109  } else if (part1 == "V_MPEGH" && part2 == "ISO" && part3 == "HEVC") {
111  } else if (part1 == "A_PCM") {
113  if (part2 == "INT") {
114  if (part3 == "BIG") {
116  } else if (part3 == "LIT") {
118  }
119  } else if (part2 == "FLOAT" && part3 == "IEEE") {
121  }
122  } else if (part1 == "A_MPC") {
124  } else if (part1 == "A_AC3") {
126  } else if (part1 == "A_EAC3") {
128  } else if (part1 == "A_ALAC") {
130  } else if (part1 == "A_DTS") {
132  if (part2 == "EXPRESS") {
134  } else if (part2 == "LOSSLESS") {
136  }
137  } else if (part1 == "A_VORBIS") {
139  } else if (part1 == "A_FLAC") {
141  } else if (part1 == "A_OPUS") {
143  } else if (part1 == "A_REAL") {
145  } else if (part1 == "A_MS" && part2 == "ACM") {
147  } else if (part1 == "A_AAC") {
149  if (part2 == "MPEG2") {
150  if (part3 == "MAIN") {
152  } else if (part3 == "LC") {
154  } else if (part3 == "SBR") {
157  } else if (part3 == "SSR") {
159  }
160  } else if (part2 == "MPEG4") {
161  if (part3 == "MAIN") {
163  } else if (part3 == "LC") {
165  } else if (part3 == "SBR") {
168  } else if (part3 == "SSR") {
170  } else if (part3 == "LTP") {
172  }
173  }
174  } else if (part1 == "A_QUICKTIME") {
176  } else if (part1 == "A_TTA1") {
178  } else if (part1 == "A_WAVPACK4") {
180  } else if (part1 == "S_TEXT") {
182  if (part2 == "UTF8") {
184  } else if (part2 == "SSA") {
186  } else if (part2 == "ASS") {
188  } else if (part2 == "USF") {
190  } else if (part2 == "WEBVTT") {
192  }
193  } else if (part1 == "S_IMAGE") {
195  if (part2 == "BMP") {
197  }
198  } else if (part1 == "S_VOBSUB") {
200  } else if (part1 == "S_KATE") {
202  } else if (part1 == "B_VOBBTN") {
204  } else if (part1 == "S_DVBSUB") {
206  } else if (part1 == "V_MSWMV") {
208  }
209  return fmt;
210 }
211 
213 
214 template <typename PropertyType, typename ConversionFunction>
215 void MatroskaTrack::assignPropertyFromTagValue(const std::unique_ptr<MatroskaTag> &tag, std::string_view fieldId, PropertyType &property,
216  const ConversionFunction &conversionFunction, Diagnostics &diag)
217 {
218  const TagValue &value = tag->value(std::string(fieldId));
219  if (!value.isEmpty()) {
220  try {
221  property = conversionFunction(value);
222  } catch (const ConversionException &) {
223  string message;
224  try {
225  message = argsToString("Ignoring invalid value \"", value.toString(TagTextEncoding::Utf8), "\" of \"", fieldId, '\"', '.');
226  } catch (const ConversionException &) {
227  message = argsToString("Ignoring invalid value of \"", fieldId, '\"', '.');
228  }
229  diag.emplace_back(DiagLevel::Warning, message, argsToString("reading track statatistic from \"", tag->toString(), '\"'));
230  }
231  }
232 }
233 
234 template <typename NumberType, Traits::EnableIf<std::is_integral<NumberType>> * = nullptr> NumberType tagValueToNumber(const TagValue &tagValue)
235 {
236  // optimization for Latin1/UTF-8 strings
237  if (tagValue.type() == TagDataType::Text) {
238  switch (tagValue.dataEncoding()) {
241  return bufferToNumber<NumberType>(tagValue.dataPointer(), tagValue.dataSize());
242  default:;
243  }
244  }
245  // generic conversion
246  return stringToNumber<NumberType>(tagValue.toString(TagTextEncoding::Utf8));
247 }
248 
249 template <typename NumberType, Traits::EnableIf<std::is_floating_point<NumberType>> * = nullptr>
250 NumberType tagValueToBitrate(const TagValue &tagValue)
251 {
252  return stringToNumber<NumberType>(tagValue.toString(TagTextEncoding::Utf8)) / 1000;
253 }
254 
256 
266 void MatroskaTrack::readStatisticsFromTags(const std::vector<std::unique_ptr<MatroskaTag>> &tags, Diagnostics &diag)
267 {
268  using namespace std::placeholders;
269  using namespace MatroskaTagIds::TrackSpecific;
270  for (const auto &tag : tags) {
271  const TagTarget &target = tag->target();
272  if (find(target.tracks().cbegin(), target.tracks().cend(), id()) == target.tracks().cend()) {
273  continue;
274  }
275  assignPropertyFromTagValue(tag, numberOfBytes(), m_size, &tagValueToNumber<std::uint64_t>, diag);
276  assignPropertyFromTagValue(tag, numberOfFrames(), m_sampleCount, &tagValueToNumber<std::uint64_t>, diag);
277  assignPropertyFromTagValue(tag, MatroskaTagIds::TrackSpecific::duration(), m_duration, bind(&TagValue::toTimeSpan, _1), diag);
278  assignPropertyFromTagValue(tag, MatroskaTagIds::TrackSpecific::bitrate(), m_bitrate, &tagValueToBitrate<double>, diag);
279  assignPropertyFromTagValue(tag, writingDate(), m_modificationTime, bind(&TagValue::toDateTime, _1), diag);
280  if (m_creationTime.isNull()) {
282  }
283  }
284 }
285 
287 {
288  CPP_UTILITIES_UNUSED(progress)
289 
290  static const string context("parsing header of Matroska track");
291  try {
292  m_trackElement->parse(diag);
293  } catch (const Failure &) {
294  diag.emplace_back(DiagLevel::Critical, "Unable to parse track element.", context);
295  throw;
296  }
297  // read information about the track from the children of the track entry element
298  auto hasIsoLanguage = false;
299  for (EbmlElement *trackInfoElement = m_trackElement->firstChild(), *subElement = nullptr; trackInfoElement;
300  trackInfoElement = trackInfoElement->nextSibling()) {
301  try {
302  trackInfoElement->parse(diag);
303  } catch (const Failure &) {
304  diag.emplace_back(DiagLevel::Critical, "Unable to parse track information element.", context);
305  break;
306  }
307  std::uint64_t defaultDuration = 0;
308  switch (trackInfoElement->id()) {
310  switch (trackInfoElement->readUInteger()) {
313  break;
316  break;
319  break;
322  break;
325  break;
326  default:
328  }
329  break;
331  for (subElement = trackInfoElement->firstChild(); subElement; subElement = subElement->nextSibling()) {
332  try {
333  subElement->parse(diag);
334  } catch (const Failure &) {
335  diag.emplace_back(DiagLevel::Critical, "Unable to parse video track element.", context);
336  break;
337  }
338  switch (subElement->id()) {
340  m_displaySize.setWidth(static_cast<std::uint32_t>(subElement->readUInteger()));
341  break;
343  m_displaySize.setHeight(static_cast<std::uint32_t>(subElement->readUInteger()));
344  break;
346  m_pixelSize.setWidth(static_cast<std::uint32_t>(subElement->readUInteger()));
347  break;
349  m_pixelSize.setHeight(static_cast<std::uint32_t>(subElement->readUInteger()));
350  break;
352  m_cropping.setTop(static_cast<std::uint32_t>(subElement->readUInteger()));
353  break;
355  m_cropping.setLeft(static_cast<std::uint32_t>(subElement->readUInteger()));
356  break;
358  m_cropping.setBottom(static_cast<std::uint32_t>(subElement->readUInteger()));
359  break;
361  m_cropping.setRight(static_cast<std::uint32_t>(subElement->readUInteger()));
362  break;
364  m_fps = static_cast<std::uint32_t>(subElement->readFloat());
365  break;
367  modFlagEnum(m_flags, TrackFlags::Interlaced, subElement->readUInteger());
368  break;
370  m_colorSpace = static_cast<std::uint32_t>(subElement->readUInteger());
371  break;
372  default:;
373  }
374  }
375  break;
377  for (subElement = trackInfoElement->firstChild(); subElement; subElement = subElement->nextSibling()) {
378  try {
379  subElement->parse(diag);
380  } catch (const Failure &) {
381  diag.emplace_back(DiagLevel::Critical, "Unable to parse audio track element.", context);
382  break;
383  }
384  switch (subElement->id()) {
386  m_bitsPerSample = static_cast<std::uint16_t>(subElement->readUInteger());
387  break;
389  m_channelCount = static_cast<std::uint16_t>(subElement->readUInteger());
390  break;
392  if (!m_samplingFrequency) {
393  m_samplingFrequency = static_cast<std::uint32_t>(subElement->readFloat());
394  }
395  break;
398  m_extensionSamplingFrequency = static_cast<std::uint32_t>(subElement->readFloat());
399  }
400  break;
401  default:;
402  }
403  }
404  break;
406  m_trackNumber = static_cast<std::uint32_t>(trackInfoElement->readUInteger());
407  break;
409  m_id = trackInfoElement->readUInteger();
410  break;
412  m_name = trackInfoElement->readString();
413  break;
415  m_locale.emplace_back(trackInfoElement->readString(), LocaleFormat::ISO_639_2_B);
416  hasIsoLanguage = true;
417  break;
419  m_locale.emplace_back(trackInfoElement->readString(), LocaleFormat::BCP_47);
420  break;
422  m_format = codecIdToMediaFormat(m_formatId = trackInfoElement->readString());
423  break;
425  m_formatName = trackInfoElement->readString();
426  break;
428  break; // TODO
430  modFlagEnum(m_flags, TrackFlags::Enabled, trackInfoElement->readUInteger());
431  break;
433  modFlagEnum(m_flags, TrackFlags::Default, trackInfoElement->readUInteger());
434  break;
436  modFlagEnum(m_flags, TrackFlags::Forced, trackInfoElement->readUInteger());
437  break;
439  modFlagEnum(m_flags, TrackFlags::Lacing, trackInfoElement->readUInteger());
440  break;
442  defaultDuration = trackInfoElement->readUInteger();
443  break;
444  default:;
445  }
446  switch (m_mediaType) {
447  case MediaType::Video:
448  if (!m_fps && defaultDuration) {
449  m_fps = static_cast<std::uint32_t>(1000000000.0 / static_cast<double>(defaultDuration));
450  }
451  break;
452  default:;
453  }
454  }
455 
456  // read further information from the CodecPrivate element for some codecs
457  EbmlElement *codecPrivateElement;
458  switch (m_format.general) {
460  if ((codecPrivateElement = m_trackElement->childById(MatroskaIds::CodecPrivate, diag))) {
461  // parse bitmap info header to determine actual format
462  if (codecPrivateElement->dataSize() >= 0x28) {
463  m_istream->seekg(static_cast<streamoff>(codecPrivateElement->dataOffset()));
464  BitmapInfoHeader bitmapInfoHeader;
465  bitmapInfoHeader.parse(reader());
466  m_formatId.reserve(m_formatId.size() + 7);
467  m_formatId += " \"";
468  m_formatId += interpretIntegerAsString(bitmapInfoHeader.compression);
469  m_formatId += "\"";
471  } else {
472  diag.emplace_back(DiagLevel::Critical, "BITMAPINFOHEADER structure (in \"CodecPrivate\"-element) is truncated.", context);
473  }
474  }
475  break;
477  if ((codecPrivateElement = m_trackElement->childById(MatroskaIds::CodecPrivate, diag))) {
478  // parse WAVE header to determine actual format
479  m_istream->seekg(static_cast<streamoff>(codecPrivateElement->dataOffset()));
480  WaveFormatHeader waveFormatHeader;
481  waveFormatHeader.parse(reader(), codecPrivateElement->dataSize(), diag);
482  WaveAudioStream::addInfo(waveFormatHeader, *this);
483  }
484  break;
486  if ((codecPrivateElement = m_trackElement->childById(MatroskaIds::CodecPrivate, diag))) {
487  auto audioSpecificConfig
488  = Mp4Track::parseAudioSpecificConfig(*m_istream, codecPrivateElement->dataOffset(), codecPrivateElement->dataSize(), diag);
490  audioSpecificConfig->audioObjectType, audioSpecificConfig->sbrPresent, audioSpecificConfig->psPresent);
491  if (audioSpecificConfig->sampleFrequencyIndex == 0xF) {
492  //m_samplingFrequency = audioSpecificConfig->sampleFrequency;
493  } else if (audioSpecificConfig->sampleFrequencyIndex < sizeof(mpeg4SamplingFrequencyTable)) {
494  //m_samplingFrequency = mpeg4SamplingFrequencyTable[audioSpecificConfig->sampleFrequencyIndex];
495  } else {
496  diag.emplace_back(DiagLevel::Warning, "Audio specific config has invalid sample frequency index.", context);
497  }
498  if (audioSpecificConfig->extensionSampleFrequencyIndex == 0xF) {
499  //m_extensionSamplingFrequency = audioSpecificConfig->extensionSampleFrequency;
500  } else if (audioSpecificConfig->extensionSampleFrequencyIndex < sizeof(mpeg4SamplingFrequencyTable)) {
501  //m_extensionSamplingFrequency = mpeg4SamplingFrequencyTable[audioSpecificConfig->extensionSampleFrequencyIndex];
502  } else {
503  diag.emplace_back(DiagLevel::Warning, "Audio specific config has invalid extension sample frequency index.", context);
504  }
505  m_channelConfig = audioSpecificConfig->channelConfiguration;
506  m_extensionChannelConfig = audioSpecificConfig->extensionChannelConfiguration;
507  }
508  break;
510  if ((codecPrivateElement = m_trackElement->childById(MatroskaIds::CodecPrivate, diag))) {
511  auto avcConfig = make_unique<TagParser::AvcConfiguration>();
512  try {
513  m_istream->seekg(static_cast<streamoff>(codecPrivateElement->dataOffset()));
514  avcConfig->parse(m_reader, codecPrivateElement->dataSize(), diag);
515  Mp4Track::addInfo(*avcConfig, *this);
516  } catch (const TruncatedDataException &) {
517  diag.emplace_back(DiagLevel::Critical, "AVC configuration is truncated.", context);
518  } catch (const Failure &) {
519  diag.emplace_back(DiagLevel::Critical, "AVC configuration is invalid.", context);
520  }
521  }
522  break;
523  default:;
524  }
525 
526  // parse format name for unknown formats
528  if (startsWith<string>(m_formatId, "V_") || startsWith<string>(m_formatId, "A_") || startsWith<string>(m_formatId, "S_")) {
529  m_formatName = m_formatId.substr(2);
530  } else {
532  }
533  m_formatName.append(" (unknown)");
534  }
535 
536  // use pixel size as display size if display size not specified
537  if (!m_displaySize.width()) {
539  }
540  if (!m_displaySize.height()) {
542  }
543 
544  // set English if no ISO language has been specified (it is the default value of MatroskaIds::TrackLanguage)
545  if (!hasIsoLanguage) {
546  m_locale.emplace_back("eng"sv, LocaleFormat::ISO_639_2_B);
547  }
548 }
549 
561 MatroskaTrackHeaderMaker::MatroskaTrackHeaderMaker(const MatroskaTrack &track, Diagnostics &diag)
562  : m_track(track)
563  , m_language(m_track.locale().abbreviatedName(LocaleFormat::ISO_639_2_B, LocaleFormat::Unknown))
564  , m_languageIETF(m_track.locale().abbreviatedName(LocaleFormat::BCP_47))
565  , m_dataSize(0)
566 {
567  CPP_UTILITIES_UNUSED(diag);
568 
569  // calculate size for recognized elements
570  m_dataSize += 2u + 1u + EbmlElement::calculateUIntegerLength(m_track.id());
571  m_dataSize += 1u + 1u + EbmlElement::calculateUIntegerLength(m_track.trackNumber());
572  m_dataSize += 1u + 1u + EbmlElement::calculateUIntegerLength(m_track.isEnabled());
573  m_dataSize += 1u + 1u + EbmlElement::calculateUIntegerLength(m_track.isDefault());
574  m_dataSize += 2u + 1u + EbmlElement::calculateUIntegerLength(m_track.isForced());
575  if (!m_track.name().empty()) {
576  m_dataSize += 2u + EbmlElement::calculateSizeDenotationLength(m_track.name().size()) + m_track.name().size();
577  }
578 
579  // compute size of the mandatory "Language" element (if there's no language set, the 3 byte long value "und" is used)
580  const auto languageSize = m_language.empty() ? 3 : m_language.size();
581  const auto languageElementSize = 3 + EbmlElement::calculateSizeDenotationLength(languageSize) + languageSize;
582  // compute size of the optional "LanguageIETF" element
583  const auto languageIETFElementSize
584  = m_languageIETF.empty() ? 0 : (3 + EbmlElement::calculateSizeDenotationLength(m_languageIETF.size()) + m_languageIETF.size());
585  m_dataSize += languageElementSize + languageIETFElementSize;
586 
587  // calculate size for other elements
588  for (EbmlElement *trackInfoElement = m_track.m_trackElement->firstChild(); trackInfoElement; trackInfoElement = trackInfoElement->nextSibling()) {
589  switch (trackInfoElement->id()) {
598  // skip recognized elements
599  break;
600  default:
601  trackInfoElement->makeBuffer();
602  m_dataSize += trackInfoElement->totalSize();
603  }
604  }
605  m_sizeDenotationLength = EbmlElement::calculateSizeDenotationLength(m_dataSize);
606  m_requiredSize = 1u + m_sizeDenotationLength + m_dataSize;
607 }
608 
616 void MatroskaTrackHeaderMaker::make(ostream &stream) const
617 {
618  // make ID and size
619  char buffer[9];
620  *buffer = static_cast<char>(MatroskaIds::TrackEntry);
621  EbmlElement::makeSizeDenotation(m_dataSize, buffer + 1);
622  stream.write(buffer, 1 + m_sizeDenotationLength);
623 
624  // make recognized elements
630  if (!m_track.name().empty()) {
632  }
633  EbmlElement::makeSimpleElement(stream, MatroskaIds::TrackLanguage, m_language.empty() ? "und" : m_language);
634  if (!m_languageIETF.empty()) {
636  }
637 
638  // make other elements
639  for (EbmlElement *trackInfoElement = m_track.m_trackElement->firstChild(); trackInfoElement; trackInfoElement = trackInfoElement->nextSibling()) {
640  switch (trackInfoElement->id()) {
649  // skip recognized elements
650  break;
651  default:
652  trackInfoElement->copyBuffer(stream);
653  }
654  }
655 }
656 
657 } // namespace TagParser
The AbortableProgressFeedback class provides feedback about an ongoing operation via callbacks.
The AbstractTrack class parses and stores technical information about video, audio and other kinds of...
Definition: abstracttrack.h:65
std::uint64_t id() const
Returns the track ID if known; otherwise returns 0.
std::uint32_t m_colorSpace
std::uint8_t m_extensionChannelConfig
std::uint64_t m_sampleCount
const Locale & locale() const
Returns the locale of the track if known; otherwise returns an empty locale.
std::uint16_t m_bitsPerSample
std::uint32_t m_trackNumber
bool isEnabled() const
Returns true if the track is marked as enabled; otherwise returns false.
std::uint16_t m_channelCount
std::uint8_t m_channelConfig
CppUtilities::BinaryReader & reader()
Returns a binary reader for the associated stream.
CppUtilities::TimeSpan m_duration
std::uint32_t trackNumber() const
Returns the track number if known; otherwise returns 0.
CppUtilities::BinaryReader m_reader
CppUtilities::DateTime m_modificationTime
std::uint32_t m_extensionSamplingFrequency
bool isForced() const
Returns true if the track is marked as forced; otherwise returns false.
const std::string name() const
Returns the track name if known; otherwise returns an empty string.
bool isDefault() const
Returns true if the track is marked as default; otherwise returns false.
CppUtilities::DateTime m_creationTime
std::istream * m_istream
std::uint32_t m_samplingFrequency
The BitmapInfoHeader class parses the BITMAPINFOHEADER structure defined by MS.
void parse(CppUtilities::BinaryReader &reader)
Parses the BITMAPINFOHEADER structure using the specified reader.
The Diagnostics class is a container for DiagMessage.
Definition: diagnostics.h:156
The EbmlElement class helps to parse EBML files such as Matroska files.
Definition: ebmlelement.h:32
static void makeSimpleElement(std::ostream &stream, IdentifierType id, std::uint64_t content)
Makes a simple EBML element.
static std::uint8_t calculateSizeDenotationLength(std::uint64_t size)
Returns the length of the size denotation for the specified size in byte.
static std::uint8_t makeSizeDenotation(std::uint64_t size, char *buff)
Makes the size denotation for the specified size and stores it to buff.
static std::uint8_t calculateUIntegerLength(std::uint64_t integer)
Returns the length of the specified unsigned integer in byte.
The class inherits from std::exception and serves as base class for exceptions thrown by the elements...
Definition: exceptions.h:11
ImplementationType * childById(const IdentifierType &id, Diagnostics &diag)
Returns the first child with the specified id.
ImplementationType * nextSibling()
Returns the next sibling of the element.
ImplementationType * firstChild()
Returns the first child of the element.
DataSizeType dataSize() const
Returns the data size of the element in byte.
std::uint64_t dataOffset() const
Returns the data offset of the element in the related stream.
void setRight(std::uint32_t right)
Sets the right margin to right.
Definition: margin.h:107
void setLeft(std::uint32_t left)
Sets the left margin to left.
Definition: margin.h:75
void setTop(std::uint32_t top)
Sets the top margin to top.
Definition: margin.h:59
void setBottom(std::uint32_t bottom)
Sets the bottom margin to bottom.
Definition: margin.h:91
void make(std::ostream &stream) const
Saves the header for the track (specified when constructing the object) to the specified stream (make...
Implementation of TagParser::AbstractTrack for the Matroska container.
Definition: matroskatrack.h:48
static MediaFormat codecIdToMediaFormat(const std::string &codecId)
Returns the MediaFormat for the specified Matroska codec ID.
void readStatisticsFromTags(const std::vector< std::unique_ptr< MatroskaTag >> &tags, Diagnostics &diag)
Reads track-specific statistics from the specified tags.
TrackType type() const override
Returns the type of the track if known; otherwise returns TrackType::Unspecified.
void internalParseHeader(Diagnostics &diag, AbortableProgressFeedback &progress) override
This method is internally called to parse header information.
~MatroskaTrack() override
Destroys the track.
The MediaFormat class specifies the format of media data.
Definition: mediaformat.h:246
unsigned char extension
Definition: mediaformat.h:261
GeneralMediaFormat general
Definition: mediaformat.h:259
static void addInfo(const AvcConfiguration &avcConfig, AbstractTrack &track)
Adds the information from the specified avcConfig to the specified track.
Definition: mp4track.cpp:1016
static std::unique_ptr< Mpeg4AudioSpecificConfig > parseAudioSpecificConfig(std::istream &stream, std::uint64_t startOffset, std::uint64_t size, Diagnostics &diag)
Parses the audio specific configuration for the track.
Definition: mp4track.cpp:649
constexpr std::uint32_t height() const
Returns the height.
Definition: size.h:68
void setWidth(std::uint32_t value)
Sets the width.
Definition: size.h:76
constexpr std::uint32_t width() const
Returns the width.
Definition: size.h:60
void setHeight(std::uint32_t value)
Sets the height.
Definition: size.h:84
The TagTarget class specifies the target of a tag.
Definition: tagtarget.h:20
const IdContainerType & tracks() const
Returns the tracks.
Definition: tagtarget.h:104
The TagValue class wraps values of different types.
Definition: tagvalue.h:95
CppUtilities::DateTime toDateTime() const
Converts the value of the current TagValue object to its equivalent DateTime representation.
Definition: tagvalue.cpp:467
std::string toString(TagTextEncoding encoding=TagTextEncoding::Unspecified) const
Converts the value of the current TagValue object to its equivalent std::string representation.
Definition: tagvalue.h:485
bool isEmpty() const
Returns whether no or an empty value is assigned.
Definition: tagvalue.h:527
CppUtilities::TimeSpan toTimeSpan() const
Converts the value of the current TagValue object to its equivalent TimeSpan representation.
Definition: tagvalue.cpp:439
The exception that is thrown when the data to be parsed is truncated and therefore can not be parsed ...
Definition: exceptions.h:39
static void addInfo(const WaveFormatHeader &waveHeader, AbstractTrack &track)
Adds the information from the specified waveHeader to the specified track.
The WaveFormatHeader class parses the WAVEFORMATEX structure defined by MS.
std::uint64_t parse(CppUtilities::BinaryReader &reader, std::uint64_t maxSize, Diagnostics &diag)
Parses the WAVE "fmt " header segment using the specified reader.
TAG_PARSER_EXPORT MediaFormat fourccToMediaFormat(std::uint32_t fourccId)
Definition: mp4ids.cpp:47
constexpr TAG_PARSER_EXPORT std::string_view writingDate()
constexpr TAG_PARSER_EXPORT std::string_view duration()
constexpr TAG_PARSER_EXPORT std::string_view bitrate()
The track's bit rate in bits per second.
constexpr TAG_PARSER_EXPORT std::string_view numberOfBytes()
constexpr TAG_PARSER_EXPORT std::string_view numberOfFrames()
TAG_PARSER_EXPORT MediaFormat idToMediaFormat(std::uint8_t mpeg4AudioObjectId, bool sbrPresent=false, bool psPresent=false)
Definition: mp4ids.cpp:367
Contains all classes and functions of the TagInfo library.
Definition: aaccodebook.h:10
LocaleFormat
The LocaleFormat enum class specifies the format used by a LocaleDetail.
Definition: localehelper.h:14
std::uint32_t mpeg4SamplingFrequencyTable[13]
Definition: mp4ids.cpp:423
TrackType
The TrackType enum specifies the underlying file type of a track and the concrete class of the track ...
Definition: abstracttrack.h:31