17f5b6ac6dd05195bc68a994a4316cecf069ab09
[dcpomatic.git] / src / lib / poznan_encoder.cc
1 /*
2     Copyright (C) 2015 Carl Hetherington <cth@carlh.net>
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #include "poznan_encoder.h"
21 #include "exceptions.h"
22 #include <dlfcn.h>
23
24 #include "i18n.h"
25
26 using std::string;
27 using boost::shared_ptr;
28
29 PoznanEncoder::PoznanEncoder ()
30 {
31         void* config = open_library ("config");
32         void* preprocessing = open_library ("preprocessing");
33         void* dwt = open_library ("dwt");
34         void* tier1 = open_library ("tier1");
35         void* tier2 = open_library ("tier2");
36         
37         _init_device = (void (*)(type_parameters *)) dlsym (config, "init_device");
38         _mct = (void (*)(type_image *, type_parameters *)) dlsym (preprocessing, "mct");
39         _fwt = (void (*)(type_tile *)) dlsym (dwt, "fwt");
40         _quantize_tile = (void (*)(type_tile *)) dlsym (tier1, "quantize_tile");
41         _encode_tile = (void (*)(type_tile *)) dlsym (tier1, "encode_tile");
42         _write_codestream = (void (*)(type_image *)) dlsym (tier2, "write_codestream");
43         
44         if (!_init_device || !_mct || !_fwt || !_quantize_tile || !_encode_tile || !_write_codestream) {
45                 throw JPEG2000EncoderUnavailableException (name(), "missing symbol");
46         }
47
48         setup_device ();
49 }
50
51 void *
52 PoznanEncoder::open_library (string library_name)
53 {
54         /* XXX: need cross-platform implementation of dlopen etc. */
55         
56         library_name = "libdcpomatic-" + library_name + ".so";
57         void* lib = dlopen (library_name.c_str(), RTLD_LAZY | RTLD_GLOBAL);
58         if (!lib) {
59                 throw JPEG2000EncoderUnavailableException (name(), "could not find " + library_name);
60         }
61         return lib;
62 }
63
64 void
65 PoznanEncoder::setup_device ()
66 {
67         /* One tile which covers entire image */
68         _param.param_tile_w = -1;
69         _param.param_tile_h = -1;
70
71         /* Wavelet decomposition levels */
72         _param.param_tile_comp_dlvls = _resolution.get() == RESOLUTION_2K ? 5 : 6;
73
74         /* Power of 2 for maximum codeblock size */
75         _param.param_cblk_exp_w = 5;
76         _param.param_cblk_exp_h = 5;
77
78         /* DWT 9/7 transform */
79         _param.param_wavelet_type = 1;
80
81         /* Use MCT */
82         _param.param_use_mct = 1;
83
84         /* Device to run on */
85         _param.param_device = 0;
86
87         /* Target file size */
88         _param.param_target_size = (_bandwidth.get() / _frame_rate.get()) / 8;
89         if (_threed.get ()) {
90                 _param.param_target_size /= 2;
91         }
92
93         /* Bits per pixel per component */
94         _param.param_bp = 12;
95
96         /* Don't know about these: use the defaults */
97         _param.param_use_part2_mct = 0;
98         _param.param_mct_compression_method = 0;
99         _param.param_mct_klt_iterations = 10000;
100         _param.param_mct_klt_border_eigenvalue = 0.000001;
101         _param.param_mct_klt_err = 1.0e-7;
102         
103         _init_device (&_param);
104 }
105
106 string
107 PoznanEncoder::name () const
108 {
109         return _("CUDA (GPU) encoder (Poznan Supercomputing and Networking Center)");
110 }
111
112 shared_ptr<EncodedData>
113 PoznanEncoder::do_encode (shared_ptr<const dcp::XYZImage> input, dcp::NoteHandler note_handler)
114 {
115         type_image img;
116         _mct (&img, &_param);
117         for (size_t i = 0; i < img.num_tiles; ++i) {
118                 type_tile* tile = &(img.tile[i]);
119                 _fwt (tile);
120                 _quantize_tile (tile);
121                 _encode_tile (tile);
122         }
123         _write_codestream (&img);
124         return shared_ptr<EncodedData> ();
125 }
126
127 void
128 PoznanEncoder::parameters_changed ()
129 {
130         setup_device ();
131 }