Fix missing version string when Popen communicate returns byte strings.
[libdcp.git] / src / j2k.cc
1 /*
2     Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
3
4     This file is part of libdcp.
5
6     libdcp is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     libdcp is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with libdcp.  If not, see <http://www.gnu.org/licenses/>.
18
19     In addition, as a special exception, the copyright holders give
20     permission to link the code of portions of this program with the
21     OpenSSL library under certain conditions as described in each
22     individual source file, and distribute linked combinations
23     including the two.
24
25     You must obey the GNU General Public License in all respects
26     for all of the code used other than OpenSSL.  If you modify
27     file(s) with this exception, you may extend this exception to your
28     version of the file(s), but you are not obligated to do so.  If you
29     do not wish to do so, delete this exception statement from your
30     version.  If you delete this exception statement from all source
31     files in the program, then also delete it here.
32 */
33
34 #include "j2k.h"
35 #include "exceptions.h"
36 #include "openjpeg_image.h"
37 #include "data.h"
38 #include "dcp_assert.h"
39 #include "compose.hpp"
40 #include <openjpeg.h>
41 #include <cmath>
42 #include <iostream>
43
44 using std::min;
45 using std::pow;
46 using boost::shared_ptr;
47 using boost::shared_array;
48 using namespace dcp;
49
50 shared_ptr<dcp::OpenJPEGImage>
51 dcp::decompress_j2k (Data data, int reduce)
52 {
53         return dcp::decompress_j2k (data.data().get(), data.size(), reduce);
54 }
55
56 #ifdef LIBDCP_OPENJPEG2
57
58 class ReadBuffer
59 {
60 public:
61         ReadBuffer (uint8_t* data, int64_t size)
62                 : _data (data)
63                 , _size (size)
64                 , _offset (0)
65         {}
66
67         OPJ_SIZE_T read (void* buffer, OPJ_SIZE_T nb_bytes)
68         {
69                 int64_t N = min (nb_bytes, _size - _offset);
70                 memcpy (buffer, _data + _offset, N);
71                 _offset += N;
72                 return N;
73         }
74
75 private:
76         uint8_t* _data;
77         OPJ_SIZE_T _size;
78         OPJ_SIZE_T _offset;
79 };
80
81 static OPJ_SIZE_T
82 read_function (void* buffer, OPJ_SIZE_T nb_bytes, void* data)
83 {
84         return reinterpret_cast<ReadBuffer*>(data)->read (buffer, nb_bytes);
85 }
86
87 static void
88 read_free_function (void* data)
89 {
90         delete reinterpret_cast<ReadBuffer*>(data);
91 }
92
93 static void
94 error_callback (char const * msg, void *)
95 {
96         throw MiscError (msg);
97 }
98
99 /** Decompress a JPEG2000 image to a bitmap.
100  *  @param data JPEG2000 data.
101  *  @param size Size of data in bytes.
102  *  @param reduce A power of 2 by which to reduce the size of the decoded image;
103  *  e.g. 0 reduces by (2^0 == 1), ie keeping the same size.
104  *       1 reduces by (2^1 == 2), ie halving the size of the image.
105  *  This is useful for scaling 4K DCP images down to 2K.
106  *  @return OpenJPEGImage.
107  */
108 shared_ptr<dcp::OpenJPEGImage>
109 dcp::decompress_j2k (uint8_t* data, int64_t size, int reduce)
110 {
111         DCP_ASSERT (reduce >= 0);
112
113         uint8_t const jp2_magic[] = {
114                 0x00,
115                 0x00,
116                 0x00,
117                 0x0c,
118                 'j',
119                 'P',
120                 0x20,
121                 0x20
122         };
123
124         OPJ_CODEC_FORMAT format = OPJ_CODEC_J2K;
125         if (size >= int (sizeof (jp2_magic)) && memcmp (data, jp2_magic, sizeof (jp2_magic)) == 0) {
126                 format = OPJ_CODEC_JP2;
127         }
128
129         opj_codec_t* decoder = opj_create_decompress (format);
130         if (!decoder) {
131                 boost::throw_exception (DCPReadError ("could not create JPEG2000 decompresser"));
132         }
133         opj_dparameters_t parameters;
134         opj_set_default_decoder_parameters (&parameters);
135         parameters.cp_reduce = reduce;
136         opj_setup_decoder (decoder, &parameters);
137
138         opj_stream_t* stream = opj_stream_default_create (OPJ_TRUE);
139         if (!stream) {
140                 throw MiscError ("could not create JPEG2000 stream");
141         }
142
143         opj_set_error_handler(decoder, error_callback, 00);
144
145         opj_stream_set_read_function (stream, read_function);
146         ReadBuffer* buffer = new ReadBuffer (data, size);
147         opj_stream_set_user_data (stream, buffer, read_free_function);
148         opj_stream_set_user_data_length (stream, size);
149
150         opj_image_t* image = 0;
151         opj_read_header (stream, decoder, &image);
152         if (opj_decode (decoder, stream, image) == OPJ_FALSE) {
153                 opj_destroy_codec (decoder);
154                 opj_stream_destroy (stream);
155                 if (format == OPJ_CODEC_J2K) {
156                         boost::throw_exception (DCPReadError (String::compose ("could not decode JPEG2000 codestream of %1 bytes.", size)));
157                 } else {
158                         boost::throw_exception (DCPReadError (String::compose ("could not decode JP2 file of %1 bytes.", size)));
159                 }
160         }
161
162         opj_destroy_codec (decoder);
163         opj_stream_destroy (stream);
164
165         image->x1 = rint (float(image->x1) / pow (2.0f, reduce));
166         image->y1 = rint (float(image->y1) / pow (2.0f, reduce));
167         return shared_ptr<OpenJPEGImage> (new OpenJPEGImage (image));
168 }
169 #endif
170
171 #ifdef LIBDCP_OPENJPEG1
172 /** Decompress a JPEG2000 image to a bitmap.
173  *  @param data JPEG2000 data.
174  *  @param size Size of data in bytes.
175  *  @param reduce A power of 2 by which to reduce the size of the decoded image;
176  *  e.g. 0 reduces by (2^0 == 1), ie keeping the same size.
177  *       1 reduces by (2^1 == 2), ie halving the size of the image.
178  *  This is useful for scaling 4K DCP images down to 2K.
179  *  @return XYZ image.
180  */
181 shared_ptr<dcp::OpenJPEGImage>
182 dcp::decompress_j2k (uint8_t* data, int64_t size, int reduce)
183 {
184         opj_dinfo_t* decoder = opj_create_decompress (CODEC_J2K);
185         opj_dparameters_t parameters;
186         opj_set_default_decoder_parameters (&parameters);
187         parameters.cp_reduce = reduce;
188         opj_setup_decoder (decoder, &parameters);
189         opj_cio_t* cio = opj_cio_open ((opj_common_ptr) decoder, data, size);
190         opj_image_t* image = opj_decode (decoder, cio);
191         if (!image) {
192                 opj_destroy_decompress (decoder);
193                 opj_cio_close (cio);
194                 boost::throw_exception (DCPReadError (String::compose ("could not decode JPEG2000 codestream of %1 bytes.", size)));
195         }
196
197         opj_destroy_decompress (decoder);
198         opj_cio_close (cio);
199
200         image->x1 = rint (float(image->x1) / pow (2, reduce));
201         image->y1 = rint (float(image->y1) / pow (2, reduce));
202         return shared_ptr<OpenJPEGImage> (new OpenJPEGImage (image));
203 }
204 #endif
205
206 #ifdef LIBDCP_OPENJPEG2
207 class WriteBuffer
208 {
209 public:
210 /* XXX: is there a better strategy for this? */
211 #define MAX_J2K_SIZE (1024 * 1024 * 2)
212         WriteBuffer ()
213                 : _data (shared_array<uint8_t> (new uint8_t[MAX_J2K_SIZE]), MAX_J2K_SIZE)
214                 , _offset (0)
215         {
216                 _data.set_size (0);
217         }
218
219         OPJ_SIZE_T write (void* buffer, OPJ_SIZE_T nb_bytes)
220         {
221                 DCP_ASSERT ((_offset + nb_bytes) < MAX_J2K_SIZE);
222                 memcpy (_data.data().get() + _offset, buffer, nb_bytes);
223                 _offset += nb_bytes;
224                 if (_offset > OPJ_SIZE_T (_data.size())) {
225                         _data.set_size (_offset);
226                 }
227                 return nb_bytes;
228         }
229
230         OPJ_BOOL seek (OPJ_SIZE_T nb_bytes)
231         {
232                 _offset = nb_bytes;
233                 return OPJ_TRUE;
234         }
235
236         Data data () const
237         {
238                 return _data;
239         }
240
241 private:
242         Data _data;
243         OPJ_SIZE_T _offset;
244 };
245
246 static OPJ_SIZE_T
247 write_function (void* buffer, OPJ_SIZE_T nb_bytes, void* data)
248 {
249         return reinterpret_cast<WriteBuffer*>(data)->write (buffer, nb_bytes);
250 }
251
252 static void
253 write_free_function (void* data)
254 {
255         delete reinterpret_cast<WriteBuffer*>(data);
256 }
257
258 static OPJ_BOOL
259 seek_function (OPJ_OFF_T nb_bytes, void* data)
260 {
261         return reinterpret_cast<WriteBuffer*>(data)->seek (nb_bytes);
262 }
263
264 /** @xyz Picture to compress.  Parts of xyz's data WILL BE OVERWRITTEN by libopenjpeg so xyz cannot be re-used
265  *  after this call; see opj_j2k_encode where if l_reuse_data is false it will set l_tilec->data = l_img_comp->data.
266  */
267 Data
268 dcp::compress_j2k (shared_ptr<const OpenJPEGImage> xyz, int bandwidth, int frames_per_second, bool threed, bool fourk)
269 {
270         /* get a J2K compressor handle */
271         opj_codec_t* encoder = opj_create_compress (OPJ_CODEC_J2K);
272         if (encoder == 0) {
273                 throw MiscError ("could not create JPEG2000 encoder");
274         }
275
276         opj_set_error_handler (encoder, error_callback, 0);
277
278         /* Set encoding parameters to default values */
279         opj_cparameters_t parameters;
280         opj_set_default_encoder_parameters (&parameters);
281         if (fourk) {
282                 parameters.numresolution = 7;
283         }
284         parameters.rsiz = fourk ? OPJ_PROFILE_CINEMA_4K : OPJ_PROFILE_CINEMA_2K;
285         parameters.cp_comment = strdup ("libdcp");
286
287         /* set max image */
288         parameters.max_cs_size = (bandwidth / 8) / frames_per_second;
289         if (threed) {
290                 /* In 3D we have only half the normal bandwidth per eye */
291                 parameters.max_cs_size /= 2;
292         }
293         parameters.max_comp_size = parameters.max_cs_size / 1.25;
294         parameters.tcp_numlayers = 1;
295         parameters.tcp_mct = 1;
296
297         /* Setup the encoder parameters using the current image and user parameters */
298         opj_setup_encoder (encoder, &parameters, xyz->opj_image());
299
300         opj_stream_t* stream = opj_stream_default_create (OPJ_FALSE);
301         if (!stream) {
302                 throw MiscError ("could not create JPEG2000 stream");
303         }
304
305         opj_stream_set_write_function (stream, write_function);
306         opj_stream_set_seek_function (stream, seek_function);
307         WriteBuffer* buffer = new WriteBuffer ();
308         opj_stream_set_user_data (stream, buffer, write_free_function);
309
310         if (!opj_start_compress (encoder, xyz->opj_image(), stream)) {
311                 if ((errno & 0x61500) == 0x61500) {
312                         /* We've had one of the magic error codes from our patched openjpeg */
313                         throw MiscError (String::compose ("could not start JPEG2000 encoding (%1)", errno & 0xff));
314                 } else {
315                         throw MiscError ("could not start JPEG2000 encoding");
316                 }
317         }
318
319         if (!opj_encode (encoder, stream)) {
320                 opj_destroy_codec (encoder);
321                 opj_stream_destroy (stream);
322                 throw MiscError ("JPEG2000 encoding failed");
323         }
324
325         if (!opj_end_compress (encoder, stream)) {
326                 opj_destroy_codec (encoder);
327                 opj_stream_destroy (stream);
328                 throw MiscError ("could not end JPEG2000 encoding");
329         }
330
331         Data enc (buffer->data ());
332
333         free (parameters.cp_comment);
334         opj_destroy_codec (encoder);
335         opj_stream_destroy (stream);
336
337         return enc;
338 }
339 #endif
340
341 #ifdef LIBDCP_OPENJPEG1
342 Data
343 dcp::compress_j2k (shared_ptr<const OpenJPEGImage> xyz, int bandwidth, int frames_per_second, bool threed, bool fourk)
344 {
345         /* Set the max image and component sizes based on frame_rate */
346         int max_cs_len = ((float) bandwidth) / 8 / frames_per_second;
347         if (threed) {
348                 /* In 3D we have only half the normal bandwidth per eye */
349                 max_cs_len /= 2;
350         }
351         int const max_comp_size = max_cs_len / 1.25;
352
353         /* get a J2K compressor handle */
354         opj_cinfo_t* cinfo = opj_create_compress (CODEC_J2K);
355         if (cinfo == 0) {
356                 throw MiscError ("could not create JPEG2000 encoder");
357         }
358
359         /* Set encoding parameters to default values */
360         opj_cparameters_t parameters;
361         opj_set_default_encoder_parameters (&parameters);
362         if (fourk) {
363                 parameters.numresolution = 7;
364         }
365
366         /* Set default cinema parameters */
367         parameters.tile_size_on = false;
368         parameters.cp_tdx = 1;
369         parameters.cp_tdy = 1;
370
371         /* Tile part */
372         parameters.tp_flag = 'C';
373         parameters.tp_on = 1;
374
375         /* Tile and Image shall be at (0,0) */
376         parameters.cp_tx0 = 0;
377         parameters.cp_ty0 = 0;
378         parameters.image_offset_x0 = 0;
379         parameters.image_offset_y0 = 0;
380
381         /* Codeblock size = 32x32 */
382         parameters.cblockw_init = 32;
383         parameters.cblockh_init = 32;
384         parameters.csty |= 0x01;
385
386         /* The progression order shall be CPRL */
387         parameters.prog_order = CPRL;
388
389         /* No ROI */
390         parameters.roi_compno = -1;
391
392         parameters.subsampling_dx = 1;
393         parameters.subsampling_dy = 1;
394
395         /* 9-7 transform */
396         parameters.irreversible = 1;
397
398         parameters.tcp_rates[0] = 0;
399         parameters.tcp_numlayers++;
400         parameters.cp_disto_alloc = 1;
401         parameters.cp_rsiz = fourk ? CINEMA4K : CINEMA2K;
402         if (fourk) {
403                 parameters.numpocs = 2;
404                 parameters.POC[0].tile = 1;
405                 parameters.POC[0].resno0 = 0;
406                 parameters.POC[0].compno0 = 0;
407                 parameters.POC[0].layno1 = 1;
408                 parameters.POC[0].resno1 = parameters.numresolution - 1;
409                 parameters.POC[0].compno1 = 3;
410                 parameters.POC[0].prg1 = CPRL;
411                 parameters.POC[1].tile = 1;
412                 parameters.POC[1].resno0 = parameters.numresolution - 1;
413                 parameters.POC[1].compno0 = 0;
414                 parameters.POC[1].layno1 = 1;
415                 parameters.POC[1].resno1 = parameters.numresolution;
416                 parameters.POC[1].compno1 = 3;
417                 parameters.POC[1].prg1 = CPRL;
418         }
419
420         parameters.cp_comment = strdup ("libdcp");
421         parameters.cp_cinema = fourk ? CINEMA4K_24 : CINEMA2K_24;
422
423         /* 3 components, so use MCT */
424         parameters.tcp_mct = 1;
425
426         /* set max image */
427         parameters.max_comp_size = max_comp_size;
428         parameters.tcp_rates[0] = ((float) (3 * xyz->size().width * xyz->size().height * 12)) / (max_cs_len * 8);
429
430         /* Set event manager to null (openjpeg 1.3 bug) */
431         cinfo->event_mgr = 0;
432
433         /* Setup the encoder parameters using the current image and user parameters */
434         opj_setup_encoder (cinfo, &parameters, xyz->opj_image ());
435
436         opj_cio_t* cio = opj_cio_open ((opj_common_ptr) cinfo, 0, 0);
437         if (cio == 0) {
438                 opj_destroy_compress (cinfo);
439                 throw MiscError ("could not open JPEG2000 stream");
440         }
441
442         int const r = opj_encode (cinfo, cio, xyz->opj_image(), 0);
443         if (r == 0) {
444                 opj_cio_close (cio);
445                 opj_destroy_compress (cinfo);
446                 throw MiscError ("JPEG2000 encoding failed");
447         }
448
449         Data enc (cio->buffer, cio_tell (cio));
450
451         opj_cio_close (cio);
452         free (parameters.cp_comment);
453         opj_destroy_compress (cinfo);
454
455         return enc;
456 }
457
458 #endif