7 #include "../avi/bitmapinfoheader.h" 9 #include "../wav/waveaudiostream.h" 11 #include "../avc/avcconfiguration.h" 13 #include "../mp4/mp4ids.h" 14 #include "../mp4/mp4track.h" 16 #include "../mediaformat.h" 17 #include "../exceptions.h" 19 #include <c++utilities/conversion/stringconversion.h> 38 AbstractTrack(trackElement.stream(), trackElement.startOffset()),
39 m_trackElement(&trackElement)
60 const auto &part1 = parts[0], &part2 = parts[1], &part3 = parts[2];
62 if(part1 ==
"V_MS" && part2 ==
"VFW" && part3 ==
"FOURCC") {
64 }
else if(part1 ==
"V_UNCOMPRESSED") {
66 }
else if(part1 ==
"V_MPEG4") {
71 }
else if(part3 ==
"ASP") {
73 }
else if(part3 ==
"AVC") {
76 }
else if(part2 ==
"MS" && part3 ==
"V3") {
79 }
else if(part1 ==
"V_MPEG1") {
81 }
else if(part1 ==
"V_MPEG2") {
83 }
else if(part1 ==
"V_REAL") {
85 }
else if(part1 ==
"V_QUICKTIME") {
87 }
else if(part1 ==
"V_THEORA") {
89 }
else if(part1 ==
"V_PRORES") {
91 }
else if(part1 ==
"V_VP8") {
93 }
else if(part1 ==
"V_VP9") {
95 }
else if(part1 ==
"A_MPEG") {
99 }
else if(part2 ==
"L2") {
101 }
else if(part2 ==
"L3") {
104 }
else if(part1 ==
"V_MPEGH" && part2 ==
"ISO" && part3 ==
"HEVC") {
106 }
else if(part1 ==
"A_PCM") {
111 }
else if(part3 ==
"LIT") {
114 }
else if (part2 ==
"FLOAT" && part3 ==
"IEEE") {
117 }
else if(part1 ==
"A_MPC") {
119 }
else if(part1 ==
"A_AC3") {
121 }
else if(part1 ==
"A_ALAC") {
123 }
else if(part1 ==
"A_DTS") {
125 if(part2 ==
"EXPRESS") {
127 }
else if(part2 ==
"LOSSLESS") {
130 }
else if(part1 ==
"A_VORBIS") {
132 }
else if(part1 ==
"A_FLAC") {
134 }
else if(part1 ==
"A_OPUS") {
136 }
else if(part1 ==
"A_REAL") {
138 }
else if(part1 ==
"A_MS" && part2 ==
"ACM") {
140 }
else if(part1 ==
"A_AAC") {
142 if(part2 ==
"MPEG2") {
143 if(part3 ==
"MAIN") {
145 }
else if(part3 ==
"LC") {
147 }
else if(part3 ==
"SBR") {
150 }
else if(part3 ==
"SSR") {
153 }
else if(part2 ==
"MPEG4") {
154 if(part3 ==
"MAIN") {
156 }
else if(part3 ==
"LC") {
158 }
else if(part3 ==
"SBR") {
161 }
else if(part3 ==
"SSR") {
163 }
else if(part3 ==
"LTP") {
167 }
else if(part1 ==
"A_QUICKTIME") {
169 }
else if(part1 ==
"A_TTA1") {
171 }
else if(part1 ==
"A_WAVPACK4") {
173 }
else if(part1 ==
"S_TEXT") {
175 if(part2 ==
"UTF8") {
177 }
else if(part2 ==
"SSA") {
179 }
else if(part2 ==
"ASS") {
181 }
else if(part2 ==
"USF") {
183 }
else if(part2 ==
"WEBVTT") {
186 }
else if(part1 ==
"S_IMAGE") {
191 }
else if(part1 ==
"S_VOBSUB") {
193 }
else if(part1 ==
"S_KATE") {
195 }
else if(part1 ==
"B_VOBBTN") {
197 }
else if(part1 ==
"S_DVBSUB") {
199 }
else if(part1 ==
"V_MSWMV") {
207 template<
typename PropertyType,
typename ConversionFunction>
208 void MatroskaTrack::assignPropertyFromTagValue(
const std::unique_ptr<MatroskaTag> &tag,
const char *fieldId, PropertyType &property,
const ConversionFunction &conversionFunction)
210 const TagValue &value = tag->value(fieldId);
213 property = conversionFunction(value);
214 }
catch(
const ConversionException &) {
218 }
catch(
const ConversionException &) {
219 message = argsToString(
"Ignoring invalid value of \"", fieldId,
'\"',
'.');
226 template<
typename NumberType, Traits::EnableIf<std::is_
integral<NumberType>>...>
227 NumberType tagValueToNumber(
const TagValue &tagValue)
243 template<
typename NumberType, Traits::EnableIf<std::is_
floating_po
int<NumberType>>...>
244 NumberType tagValueToBitrate(
const TagValue &tagValue)
263 using namespace MatroskaTagIds::TrackSpecific;
264 for(
const auto &tag : tags) {
282 static const string context(
"parsing header of Matroska track");
284 m_trackElement->parse();
290 for(
EbmlElement *trackInfoElement = m_trackElement->
firstChild(), *subElement =
nullptr; trackInfoElement; trackInfoElement = trackInfoElement->nextSibling()) {
292 trackInfoElement->parse();
297 uint32 defaultDuration = 0;
298 switch(trackInfoElement->id()) {
300 switch(trackInfoElement->readUInteger()) {
321 for(subElement = trackInfoElement->firstChild(); subElement; subElement = subElement->nextSibling()) {
328 switch(subElement->id()) {
354 m_fps = subElement->readFloat();
368 for(subElement = trackInfoElement->firstChild(); subElement; subElement = subElement->nextSibling()) {
375 switch(subElement->id()) {
401 m_id = trackInfoElement->readUInteger();
404 m_name = trackInfoElement->readString();
418 m_enabled = trackInfoElement->readUInteger();
421 m_default = trackInfoElement->readUInteger();
424 m_forced = trackInfoElement->readUInteger();
427 m_lacing = trackInfoElement->readUInteger();
430 defaultDuration = trackInfoElement->readUInteger();
437 if(!
m_fps && defaultDuration) {
438 m_fps = 1000000000.0 /
static_cast<double>(defaultDuration);
452 if(codecPrivateElement->
dataSize() >= 0x28) {
469 if(codecPrivateElement->
dataSize() >= 16) {
483 if(audioSpecificConfig->sampleFrequencyIndex == 0xF) {
490 if(audioSpecificConfig->extensionSampleFrequencyIndex == 0xF) {
503 auto avcConfig = make_unique<Media::AvcConfiguration>();
521 if(startsWith<string>(
m_formatId,
"V_") || startsWith<string>(
m_formatId,
"A_") || startsWith<string>(m_formatId,
"S_")) {
554 MatroskaTrackHeaderMaker::MatroskaTrackHeaderMaker(
const MatroskaTrack &track) :
564 if(!m_track.name().empty()) {
567 if(!m_track.language().empty()) {
572 for(
EbmlElement *trackInfoElement = m_track.m_trackElement->
firstChild(); trackInfoElement; trackInfoElement = trackInfoElement->nextSibling()) {
573 switch(trackInfoElement->id()) {
584 trackInfoElement->makeBuffer();
585 m_dataSize += trackInfoElement->totalSize();
589 m_requiredSize = 2 + m_sizeDenotationLength + m_dataSize;
605 stream.write(buffer, 2 + m_sizeDenotationLength);
613 if(!m_track.name().empty()) {
616 if(!m_track.language().empty()) {
621 for(
EbmlElement *trackInfoElement = m_track.m_trackElement->
firstChild(); trackInfoElement; trackInfoElement = trackInfoElement->nextSibling()) {
622 switch(trackInfoElement->id()) {
633 trackInfoElement->copyBuffer(stream);