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 Helper routines for various compression libs
10
11 Written by Moritz Bunkus <moritz@bunkus.org>.
12 */
13
14 #include "common/common_pch.h"
15
16 #include <matroska/KaxContentEncoding.h>
17 #include <matroska/KaxTracks.h>
18
19 #include "common/compression.h"
20 #include "common/ebml.h"
21 #include "common/endian.h"
22 #include "common/strings/formatting.h"
23
24 using namespace libmatroska;
25
26 static const char *compression_methods[] = {
27 "unspecified", "zlib", "header_removal", "mpeg4_p2", "mpeg4_p10", "dirac", "dts", "ac3", "mp3", "analyze_header_removal", "none"
28 };
29
30 static const int compression_method_map[] = {
31 0, // unspecified
32 0, // zlib
33 3, // header removal
34 3, // mpeg4_p2 is header removal
35 3, // mpeg4_p10 is header removal
36 3, // dirac is header removal
37 3, // dts is header removal
38 3, // ac3 is header removal
39 3, // mp3 is header removal
40 999999999, // analyze_header_removal
41 0 // none
42 };
43
~compressor_c()44 compressor_c::~compressor_c() {
45 if (0 == items)
46 return;
47
48 mxdebug_if(m_debug,
49 fmt::format("compression: Overall stats: raw size: {0}, compressed size: {1}, items: {2}, ratio: {3:.2f}%, avg bytes per item: {4}\n",
50 raw_size, compressed_size, items, compressed_size * 100.0 / raw_size, compressed_size / items));
51 }
52
53 void
set_track_headers(KaxContentEncoding & c_encoding)54 compressor_c::set_track_headers(KaxContentEncoding &c_encoding) {
55 // Set compression method.
56 GetChild<KaxContentCompAlgo>(GetChild<KaxContentCompression>(c_encoding)).SetValue(compression_method_map[method]);
57 }
58
59 compressor_ptr
create(compression_method_e method)60 compressor_c::create(compression_method_e method) {
61 if ((COMPRESSION_UNSPECIFIED >= method) || (COMPRESSION_NUM < method))
62 return compressor_ptr();
63
64 return create(compression_methods[method]);
65 }
66
67 compressor_ptr
create(const char * method)68 compressor_c::create(const char *method) {
69 if (!strcasecmp(method, compression_methods[COMPRESSION_ZLIB]))
70 return compressor_ptr(new zlib_compressor_c());
71
72 if (!strcasecmp(method, compression_methods[COMPRESSION_MPEG4_P2]))
73 return compressor_ptr(new mpeg4_p2_compressor_c());
74
75 if (!strcasecmp(method, compression_methods[COMPRESSION_MPEG4_P10]))
76 return compressor_ptr(new mpeg4_p10_compressor_c());
77
78 if (!strcasecmp(method, compression_methods[COMPRESSION_DIRAC]))
79 return compressor_ptr(new dirac_compressor_c());
80
81 if (!strcasecmp(method, compression_methods[COMPRESSION_DTS]))
82 return compressor_ptr(new dts_compressor_c());
83
84 if (!strcasecmp(method, compression_methods[COMPRESSION_AC3]))
85 return compressor_ptr(new ac3_compressor_c());
86
87 if (!strcasecmp(method, compression_methods[COMPRESSION_MP3]))
88 return compressor_ptr(new mp3_compressor_c());
89
90 if (!strcasecmp(method, compression_methods[COMPRESSION_ANALYZE_HEADER_REMOVAL]))
91 return compressor_ptr(new analyze_header_removal_compressor_c());
92
93 if (!strcasecmp(method, "none"))
94 return std::make_shared<compressor_c>(COMPRESSION_NONE);
95
96 return compressor_ptr();
97 }
98
99 compressor_ptr
create_from_file_name(std::string const & file_name)100 compressor_c::create_from_file_name(std::string const &file_name) {
101 auto pos = file_name.rfind(".");
102 auto ext = balg::to_lower_copy(pos == std::string::npos ? file_name : file_name.substr(pos + 1));
103
104 if (ext == "gz")
105 return compressor_ptr(new zlib_compressor_c());
106
107 return std::make_shared<compressor_c>(COMPRESSION_NONE);
108 }
109