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