1 /*
2 mkvmerge -- utility for splicing together matroska files
3 from component media subtypes
4
5 Distributed under the GPL v2
6 see the file COPYING for details
7 or visit https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
8
9 Definitions for the various Codec IDs
10
11 Written by Moritz Bunkus <moritz@bunkus.org>.
12 */
13
14 #include "common/common_pch.h"
15
16 #include <QRegularExpression>
17
18 #include "common/codec.h"
19 #include "common/mp4.h"
20 #include "common/qt.h"
21
22 namespace {
23
24 using specialization_map_t = std::unordered_map<codec_c::specialization_e, std::string, mtx::hash<codec_c::specialization_e> >;
25
26 std::vector<codec_c> s_codecs;
27 specialization_map_t s_specialization_descriptions;
28
29 }
30
31 class codec_private_c {
32 friend class codec_c;
33
34 protected:
35 std::string name;
36 codec_c::type_e type{codec_c::type_e::UNKNOWN};
37 codec_c::specialization_e specialization{codec_c::specialization_e::none};
38 track_type the_track_type{static_cast<track_type>(0)};
39 QRegularExpression match_re;
40 std::vector<fourcc_c> fourccs;
41 std::vector<uint16_t> audio_formats;
42
43 public:
44 codec_private_c() = default;
45 codec_private_c(std::string const &p_name, codec_c::type_e p_type, track_type p_track_type, std::string const &p_match_re);
46
47 codec_private_c(codec_private_c const &src) = default;
48 codec_private_c(codec_private_c &&src) = default;
49
50 codec_private_c &operator =(codec_private_c const &src) = default;
51 codec_private_c &operator =(codec_private_c &&src) = default;
52 };
53
codec_private_c(std::string const & p_name,codec_c::type_e p_type,track_type p_track_type,std::string const & p_match_re)54 codec_private_c::codec_private_c(std::string const &p_name,
55 codec_c::type_e p_type,
56 track_type p_track_type,
57 std::string const &p_match_re)
58 : name{p_name}
59 , type{p_type}
60 , the_track_type{p_track_type}
61 , match_re{Q(fmt::format("^(?:{0})$", p_match_re)), QRegularExpression::CaseInsensitiveOption}
62 {
63 }
64
65 // ------------------------------------------------------------
66
codec_c()67 codec_c::codec_c()
68 : p_ptr{new codec_private_c}
69 {
70 }
71
codec_c(codec_private_c & p)72 codec_c::codec_c(codec_private_c &p)
73 : p_ptr{&p}
74 {
75 }
76
codec_c(std::string const & name,type_e type,track_type p_track_type,std::string const & match_re,uint16_t audio_format)77 codec_c::codec_c(std::string const &name,
78 type_e type,
79 track_type p_track_type,
80 std::string const &match_re,
81 uint16_t audio_format)
82 : p_ptr{new codec_private_c{name, type, p_track_type, match_re}}
83 {
84 if (audio_format)
85 p_ptr->audio_formats.push_back(audio_format);
86 }
87
codec_c(std::string const & name,type_e type,track_type p_track_type,std::string const & match_re,fourcc_c const & fourcc)88 codec_c::codec_c(std::string const &name,
89 type_e type,
90 track_type p_track_type,
91 std::string const &match_re,
92 fourcc_c const &fourcc)
93 : p_ptr{new codec_private_c{name, type, p_track_type, match_re}}
94 {
95 p_ptr->fourccs.push_back(fourcc);
96 }
97
codec_c(std::string const & name,type_e type,track_type p_track_type,std::string const & match_re,std::vector<uint16_t> const & audio_formats)98 codec_c::codec_c(std::string const &name,
99 type_e type,
100 track_type p_track_type,
101 std::string const &match_re,
102 std::vector<uint16_t> const &audio_formats)
103 : p_ptr{new codec_private_c{name, type, p_track_type, match_re}}
104 {
105 p_ptr->audio_formats = audio_formats;
106 }
107
codec_c(std::string const & name,type_e type,track_type p_track_type,std::string const & match_re,std::vector<fourcc_c> const & fourccs)108 codec_c::codec_c(std::string const &name,
109 type_e type,
110 track_type p_track_type,
111 std::string const &match_re,
112 std::vector<fourcc_c> const &fourccs)
113 : p_ptr{new codec_private_c{name, type, p_track_type, match_re}}
114 {
115 p_ptr->fourccs = fourccs;
116 }
117
codec_c(codec_c const & src)118 codec_c::codec_c(codec_c const &src)
119 : p_ptr{new codec_private_c{*src.p_ptr}}
120 {
121 }
122
~codec_c()123 codec_c::~codec_c() {
124 }
125
126 codec_c &
operator =(codec_c const & src)127 codec_c::operator =(codec_c const &src) {
128 *p_ptr = *src.p_ptr;
129 return *this;
130 }
131
132 void
initialize()133 codec_c::initialize() {
134 if (!s_codecs.empty())
135 return;
136 s_codecs.emplace_back("AV1", type_e::V_AV1, track_video, "av01|V_AV1", fourcc_c{"AV01"});
137 s_codecs.emplace_back("AVC/H.264/MPEG-4p10", type_e::V_MPEG4_P10, track_video, "avc.|[hx]264|V_MPEG4/ISO/AVC");
138 s_codecs.emplace_back("Bitfields", type_e::V_BITFIELDS, track_video, "", fourcc_c{0x03000000u});
139 s_codecs.emplace_back("Cinepak", type_e::V_CINEPAK, track_video, "cvid");
140 s_codecs.emplace_back("Dirac", type_e::V_DIRAC, track_video, "drac|V_DIRAC");
141 s_codecs.emplace_back("HEVC/H.265/MPEG-H", type_e::V_MPEGH_P2, track_video, "hevc|hvc1|hev1|[hx]265|dvh[1e]|V_MPEGH/ISO/HEVC");
142 s_codecs.emplace_back("MPEG-1/2", type_e::V_MPEG12, track_video, "mpeg|mpg[12]|m[12]v.|mpgv|mp[12]v|h262|V_MPEG[12]");
143 s_codecs.emplace_back("MPEG-4p2", type_e::V_MPEG4_P2, track_video, "3iv2|xvi[dx]|divx|dx50|fmp4|mp4v|V_MPEG4/ISO/(?:SP|AP|ASP)");
144 s_codecs.emplace_back("ProRes", type_e::V_PRORES, track_video, "apch|apcn|apcs|apco|ap4h|V_PRORES");
145 s_codecs.emplace_back("RLE4", type_e::V_RLE4, track_video, "", fourcc_c{0x02000000u});
146 s_codecs.emplace_back("RLE8", type_e::V_RLE8, track_video, "", fourcc_c{0x01000000u});
147 s_codecs.emplace_back("RealVideo", type_e::V_REAL, track_video, "rv[1234]\\d|V_REAL/RV\\d+");
148 s_codecs.emplace_back("Sorenson v1", type_e::V_SVQ1, track_video, "svq[i1]");
149 s_codecs.emplace_back("Sorenson v3", type_e::V_SVQ3, track_video, "svq3");
150 s_codecs.emplace_back("Theora", type_e::V_THEORA, track_video, "theo|thra|V_THEORA");
151 s_codecs.emplace_back("Uncompressed", type_e::V_UNCOMPRESSED, track_video, "", fourcc_c{0x00000000u});
152 s_codecs.emplace_back("VC-1", type_e::V_VC1, track_video, "wvc1|vc-1");
153 s_codecs.emplace_back("VP8", type_e::V_VP8, track_video, "vp8\\d|V_VP8", fourcc_c{"VP80"});
154 s_codecs.emplace_back("VP9", type_e::V_VP9, track_video, "vp9\\d|V_VP9", std::vector<fourcc_c>{ fourcc_c{"VP90"}, fourcc_c{"vp09"} });
155
156 s_codecs.emplace_back("AAC", type_e::A_AAC, track_audio, "mp4a|aac.|raac|racp|A_AAC.*", std::vector<uint16_t>{ 0x00ffu, 0x706du });
157 s_codecs.emplace_back("AC-3", type_e::A_AC3, track_audio, "ac3.|ac-3|sac3|eac3|ec-3|a52[\\sb]|dnet|A_E?AC3", 0x2000u);
158 s_codecs.emplace_back("ALAC", type_e::A_ALAC, track_audio, "alac|A_ALAC");
159 s_codecs.emplace_back("ATRAC3", type_e::A_ATRAC3, track_audio, "atrc|A_REAL/ATRC");
160 s_codecs.emplace_back("DTS", type_e::A_DTS, track_audio, "dts[\\sbcehl]|A_DTS", 0x2001u);
161 s_codecs.emplace_back("FLAC", type_e::A_FLAC, track_audio, "flac|A_FLAC");
162 s_codecs.emplace_back("G2/Cook", type_e::A_COOK, track_audio, "cook|A_REAL/COOK");
163 s_codecs.emplace_back("LD-CELP", type_e::A_LD_CELP, track_audio, "28_8|A_REAL/28_8");
164 s_codecs.emplace_back("MLP", type_e::A_MLP, track_audio, "mlp\\s|A_MLP");
165 s_codecs.emplace_back("MP2", type_e::A_MP2, track_audio, "mp2.|\\.mp[12]|mp2a|A_MPEG/L2", 0x0050);
166 s_codecs.emplace_back("MP3", type_e::A_MP3, track_audio, "mp3.|\\.mp3|LAME|mpga|A_MPEG/L3", 0x0055);
167 s_codecs.emplace_back("Opus", type_e::A_OPUS, track_audio, "opus|A_OPUS(?:/EXPERIMENTAL)?");
168 s_codecs.emplace_back("PCM", type_e::A_PCM, track_audio, "twos|sowt|raw.|lpcm|in24|A_PCM/(?:INT|FLOAT)/.+", std::vector<uint16_t>{ 0x0001u, 0x0003u });
169 s_codecs.emplace_back("QDMC", type_e::A_QDMC, track_audio, "qdm2|A_QUICKTIME/QDM[2C]");
170 s_codecs.emplace_back("RealAudio-Lossless", type_e::A_RALF, track_audio, "ralf|A_REAL/RALF");
171 s_codecs.emplace_back("Sipro/ACELP-NET", type_e::A_ACELP_NET, track_audio, "sipr|A_REAL/SIPR");
172 s_codecs.emplace_back("TrueAudio", type_e::A_TTA, track_audio, "tta1|A_TTA1?");
173 s_codecs.emplace_back("TrueHD", type_e::A_TRUEHD, track_audio, "trhd|A_TRUEHD");
174 s_codecs.emplace_back("VSELP", type_e::A_VSELP, track_audio, "lpcj|14_4|A_REAL/LPCJ|A_REAL/14_4");
175 s_codecs.emplace_back("Vorbis", type_e::A_VORBIS, track_audio, "vor[1b]|A_VORBIS", std::vector<uint16_t>{ 0x566fu, 0xfffeu });
176 s_codecs.emplace_back("WavPack4", type_e::A_WAVPACK4, track_audio, "wvpk|A_WAVPACK4");
177
178 s_codecs.emplace_back("DVBSUB", type_e::S_DVBSUB, track_subtitle, MKV_S_DVBSUB);
179 s_codecs.emplace_back("HDMV PGS", type_e::S_HDMV_PGS, track_subtitle, MKV_S_HDMV_PGS);
180 s_codecs.emplace_back("HDMV TextST", type_e::S_HDMV_TEXTST, track_subtitle, MKV_S_HDMV_TEXTST);
181 s_codecs.emplace_back("Kate", type_e::S_KATE, track_subtitle, "kate|S_KATE");
182 s_codecs.emplace_back("SubRip/SRT", type_e::S_SRT, track_subtitle, "S_TEXT/(?:UTF8|ASCII)");
183 s_codecs.emplace_back("SubStationAlpha", type_e::S_SSA_ASS, track_subtitle, "ssa\\s|ass\\s|S_TEXT/(?:SSA|ASS)");
184 s_codecs.emplace_back("UniversalSubtitleFormat", type_e::S_USF, track_subtitle, "usf\\s|S_TEXT/USF");
185 s_codecs.emplace_back("VobSub", type_e::S_VOBSUB, track_subtitle, "S_VOBSUB(?:/ZLIB)?");
186 s_codecs.emplace_back("WebVTT", type_e::S_WEBVTT, track_subtitle, MKV_S_TEXTWEBVTT);
187
188 s_codecs.emplace_back("VobButton", type_e::B_VOBBTN, track_buttons, "B_VOBBTN");
189
190 s_specialization_descriptions.emplace(specialization_e::dts_hd_master_audio, "DTS-HD Master Audio");
191 s_specialization_descriptions.emplace(specialization_e::dts_hd_high_resolution, "DTS-HD High Resolution Audio");
192 s_specialization_descriptions.emplace(specialization_e::dts_express, "DTS Express");
193 s_specialization_descriptions.emplace(specialization_e::dts_es, "DTS-ES");
194 s_specialization_descriptions.emplace(specialization_e::dts_96_24, "DTS 96/24");
195 s_specialization_descriptions.emplace(specialization_e::dts_x, "DTS:X");
196
197 s_specialization_descriptions.emplace(specialization_e::mpeg_1_2_layer_1, "MP1");
198 s_specialization_descriptions.emplace(specialization_e::mpeg_1_2_layer_2, "MP2");
199 s_specialization_descriptions.emplace(specialization_e::mpeg_1_2_layer_3, "MP3");
200
201 s_specialization_descriptions.emplace(specialization_e::truehd_atmos, "TrueHD Atmos");
202
203 s_specialization_descriptions.emplace(specialization_e::ac3_dolby_surround_ex, "AC-3 Dolby Surround EX");
204 s_specialization_descriptions.emplace(specialization_e::e_ac_3, "E-AC-3");
205 }
206
207 bool
valid() const208 codec_c::valid()
209 const {
210 return p_func()->type != type_e::UNKNOWN;
211 }
212
operator bool() const213 codec_c::operator bool()
214 const {
215 return valid();
216 }
217
218 bool
is(type_e type) const219 codec_c::is(type_e type)
220 const {
221 return type == p_func()->type;
222 }
223
224 codec_c::type_e
get_type() const225 codec_c::get_type()
226 const {
227 return p_func()->type;
228 }
229
230 codec_c::specialization_e
get_specialization() const231 codec_c::get_specialization()
232 const {
233 return p_func()->specialization;
234 }
235
236 track_type
get_track_type() const237 codec_c::get_track_type()
238 const {
239 return p_func()->the_track_type;
240 }
241
242 std::vector<fourcc_c> const &
get_fourccs() const243 codec_c::get_fourccs()
244 const {
245 return p_func()->fourccs;
246 }
247
248 std::vector<uint16_t> const &
get_audio_formats() const249 codec_c::get_audio_formats()
250 const {
251 return p_func()->audio_formats;
252 }
253
254 codec_c &
set_specialization(specialization_e specialization)255 codec_c::set_specialization(specialization_e specialization) {
256 p_func()->specialization = specialization;
257 return *this;
258 }
259
260 codec_c
specialize(specialization_e specialization) const261 codec_c::specialize(specialization_e specialization)
262 const {
263 auto new_codec = *this;
264 new_codec.set_specialization(specialization);
265 return new_codec;
266 }
267
268 codec_c const
look_up(std::string const & fourcc_or_codec_id)269 codec_c::look_up(std::string const &fourcc_or_codec_id) {
270 initialize();
271
272 auto itr = std::find_if(s_codecs.begin(), s_codecs.end(), [&fourcc_or_codec_id](codec_c const &c) { return c.matches(fourcc_or_codec_id); });
273
274 return itr == s_codecs.end() ? codec_c{} : *itr;
275 }
276
277 codec_c const
look_up(type_e type)278 codec_c::look_up(type_e type) {
279 initialize();
280
281 auto itr = std::find_if(s_codecs.begin(), s_codecs.end(), [type](codec_c const &c) { return c.get_type() == type; });
282
283 return itr == s_codecs.end() ? codec_c{} : *itr;
284 }
285
286 codec_c const
look_up(char const * fourcc_or_codec_id)287 codec_c::look_up(char const *fourcc_or_codec_id) {
288 return look_up(std::string{fourcc_or_codec_id});
289 }
290
291 codec_c const
look_up(fourcc_c const & fourcc)292 codec_c::look_up(fourcc_c const &fourcc) {
293 initialize();
294
295 auto itr = std::find_if(s_codecs.begin(), s_codecs.end(), [&fourcc](codec_c const &c) {
296 auto const &fourccs = c.get_fourccs();
297 return std::find(fourccs.begin(), fourccs.end(), fourcc) != fourccs.end();
298 });
299
300 return itr != s_codecs.end() ? *itr : look_up(fourcc.str());
301 }
302
303 codec_c const
look_up_audio_format(uint16_t audio_format)304 codec_c::look_up_audio_format(uint16_t audio_format) {
305 initialize();
306
307 auto itr = std::find_if(s_codecs.begin(), s_codecs.end(), [audio_format](codec_c const &c) {
308 auto const &audio_formats = c.get_audio_formats();
309 return std::find(audio_formats.begin(), audio_formats.end(), audio_format) != audio_formats.end();
310 });
311
312 return itr == s_codecs.end() ? codec_c{} : *itr;
313 }
314
315 codec_c const
look_up_object_type_id(unsigned int object_type_id)316 codec_c::look_up_object_type_id(unsigned int object_type_id) {
317 return look_up( ( (mtx::mp4::OBJECT_TYPE_MPEG4Audio == object_type_id)
318 || (mtx::mp4::OBJECT_TYPE_MPEG2AudioMain == object_type_id)
319 || (mtx::mp4::OBJECT_TYPE_MPEG2AudioLowComplexity == object_type_id)
320 || (mtx::mp4::OBJECT_TYPE_MPEG2AudioScaleableSamplingRate == object_type_id)) ? type_e::A_AAC
321 : mtx::mp4::OBJECT_TYPE_MPEG1Audio == object_type_id ? type_e::A_MP2
322 : mtx::mp4::OBJECT_TYPE_MPEG2AudioPart3 == object_type_id ? type_e::A_MP3
323 : mtx::mp4::OBJECT_TYPE_DTS == object_type_id ? type_e::A_DTS
324 : mtx::mp4::OBJECT_TYPE_VORBIS == object_type_id ? type_e::A_VORBIS
325 : ( (mtx::mp4::OBJECT_TYPE_MPEG2VisualSimple == object_type_id)
326 || (mtx::mp4::OBJECT_TYPE_MPEG2VisualMain == object_type_id)
327 || (mtx::mp4::OBJECT_TYPE_MPEG2VisualSNR == object_type_id)
328 || (mtx::mp4::OBJECT_TYPE_MPEG2VisualSpatial == object_type_id)
329 || (mtx::mp4::OBJECT_TYPE_MPEG2VisualHigh == object_type_id)
330 || (mtx::mp4::OBJECT_TYPE_MPEG2Visual422 == object_type_id)
331 || (mtx::mp4::OBJECT_TYPE_MPEG1Visual == object_type_id)) ? type_e::V_MPEG12
332 : mtx::mp4::OBJECT_TYPE_MPEG4Visual == object_type_id ? type_e::V_MPEG4_P2
333 : mtx::mp4::OBJECT_TYPE_VOBSUB == object_type_id ? type_e::S_VOBSUB
334 : type_e::UNKNOWN);
335 }
336
337 bool
matches(std::string const & fourcc_or_codec_id) const338 codec_c::matches(std::string const &fourcc_or_codec_id)
339 const {
340 auto &p = *p_func();
341
342 if (Q(fourcc_or_codec_id).contains(p.match_re))
343 return true;
344
345 if (fourcc_or_codec_id.length() == 4)
346 return std::find(p.fourccs.begin(), p.fourccs.end(), fourcc_c{fourcc_or_codec_id}) != p.fourccs.end();
347
348 return false;
349 }
350
351 std::string const
get_name(std::string fallback) const352 codec_c::get_name(std::string fallback)
353 const {
354 auto &p = *p_func();
355
356 if (!valid())
357 return fallback;
358
359 if (specialization_e::none == p.specialization)
360 return p.name;
361
362 return s_specialization_descriptions[p.specialization];
363 }
364
365 std::string const
get_name(std::string const & fourcc_or_codec_id,std::string const & fallback)366 codec_c::get_name(std::string const &fourcc_or_codec_id,
367 std::string const &fallback) {
368 auto codec = look_up(fourcc_or_codec_id);
369 return codec ? codec.get_name() : fallback;
370 }
371
372 std::string const
get_name(type_e type,std::string const & fallback)373 codec_c::get_name(type_e type,
374 std::string const &fallback) {
375 auto codec = look_up(type);
376 return codec ? codec.get_name() : fallback;
377 }
378