Store and allow access to the raw XML that is read in from
[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
94 static void
95 decompress_error_callback (char const * msg, void *)
96 {
97         throw J2KDecompressionError (msg);
98 }
99
100
101 static void
102 compress_error_callback (char const * msg, void *)
103 {
104         throw MiscError (msg);
105 }
106
107 /** Decompress a JPEG2000 image to a bitmap.
108  *  @param data JPEG2000 data.
109  *  @param size Size of data in bytes.
110  *  @param reduce A power of 2 by which to reduce the size of the decoded image;
111  *  e.g. 0 reduces by (2^0 == 1), ie keeping the same size.
112  *       1 reduces by (2^1 == 2), ie halving the size of the image.
113  *  This is useful for scaling 4K DCP images down to 2K.
114  *  @return OpenJPEGImage.
115  */
116 shared_ptr<dcp::OpenJPEGImage>
117 dcp::decompress_j2k (uint8_t* data, int64_t size, int reduce)
118 {
119         DCP_ASSERT (reduce >= 0);
120
121         uint8_t const jp2_magic[] = {
122                 0x00,
123                 0x00,
124                 0x00,
125                 0x0c,
126                 'j',
127                 'P',
128                 0x20,
129                 0x20
130         };
131
132         OPJ_CODEC_FORMAT format = OPJ_CODEC_J2K;
133         if (size >= int (sizeof (jp2_magic)) && memcmp (data, jp2_magic, sizeof (jp2_magic)) == 0) {
134                 format = OPJ_CODEC_JP2;
135         }
136
137         opj_codec_t* decoder = opj_create_decompress (format);
138         if (!decoder) {
139                 boost::throw_exception (ReadError ("could not create JPEG2000 decompresser"));
140         }
141         opj_dparameters_t parameters;
142         opj_set_default_decoder_parameters (&parameters);
143         parameters.cp_reduce = reduce;
144         opj_setup_decoder (decoder, &parameters);
145
146         opj_stream_t* stream = opj_stream_default_create (OPJ_TRUE);
147         if (!stream) {
148                 throw MiscError ("could not create JPEG2000 stream");
149         }
150
151         opj_set_error_handler(decoder, decompress_error_callback, 00);
152
153         opj_stream_set_read_function (stream, read_function);
154         ReadBuffer* buffer = new ReadBuffer (data, size);
155         opj_stream_set_user_data (stream, buffer, read_free_function);
156         opj_stream_set_user_data_length (stream, size);
157
158         opj_image_t* image = 0;
159         opj_read_header (stream, decoder, &image);
160         if (opj_decode (decoder, stream, image) == OPJ_FALSE) {
161                 opj_destroy_codec (decoder);
162                 opj_stream_destroy (stream);
163                 if (format == OPJ_CODEC_J2K) {
164                         boost::throw_exception (ReadError (String::compose ("could not decode JPEG2000 codestream of %1 bytes.", size)));
165                 } else {
166                         boost::throw_exception (ReadError (String::compose ("could not decode JP2 file of %1 bytes.", size)));
167                 }
168         }
169
170         opj_destroy_codec (decoder);
171         opj_stream_destroy (stream);
172
173         image->x1 = rint (float(image->x1) / pow (2.0f, reduce));
174         image->y1 = rint (float(image->y1) / pow (2.0f, reduce));
175         return shared_ptr<OpenJPEGImage> (new OpenJPEGImage (image));
176 }
177 #endif
178
179 #ifdef LIBDCP_OPENJPEG1
180 /** Decompress a JPEG2000 image to a bitmap.
181  *  @param data JPEG2000 data.
182  *  @param size Size of data in bytes.
183  *  @param reduce A power of 2 by which to reduce the size of the decoded image;
184  *  e.g. 0 reduces by (2^0 == 1), ie keeping the same size.
185  *       1 reduces by (2^1 == 2), ie halving the size of the image.
186  *  This is useful for scaling 4K DCP images down to 2K.
187  *  @return XYZ image.
188  */
189 shared_ptr<dcp::OpenJPEGImage>
190 dcp::decompress_j2k (uint8_t* data, int64_t size, int reduce)
191 {
192         opj_dinfo_t* decoder = opj_create_decompress (CODEC_J2K);
193         opj_dparameters_t parameters;
194         opj_set_default_decoder_parameters (&parameters);
195         parameters.cp_reduce = reduce;
196         opj_setup_decoder (decoder, &parameters);
197         opj_cio_t* cio = opj_cio_open ((opj_common_ptr) decoder, data, size);
198         opj_image_t* image = opj_decode (decoder, cio);
199         if (!image) {
200                 opj_destroy_decompress (decoder);
201                 opj_cio_close (cio);
202                 boost::throw_exception (ReadError (String::compose ("could not decode JPEG2000 codestream of %1 bytes.", size)));
203         }
204
205         opj_destroy_decompress (decoder);
206         opj_cio_close (cio);
207
208         image->x1 = rint (float(image->x1) / pow (2, reduce));
209         image->y1 = rint (float(image->y1) / pow (2, reduce));
210         return shared_ptr<OpenJPEGImage> (new OpenJPEGImage (image));
211 }
212 #endif
213
214 #ifdef LIBDCP_OPENJPEG2
215 class WriteBuffer
216 {
217 public:
218 /* XXX: is there a better strategy for this? */
219 #define MAX_J2K_SIZE (1024 * 1024 * 2)
220         WriteBuffer ()
221                 : _data (shared_array<uint8_t> (new uint8_t[MAX_J2K_SIZE]), MAX_J2K_SIZE)
222                 , _offset (0)
223         {
224                 _data.set_size (0);
225         }
226
227         OPJ_SIZE_T write (void* buffer, OPJ_SIZE_T nb_bytes)
228         {
229                 DCP_ASSERT ((_offset + nb_bytes) < MAX_J2K_SIZE);
230                 memcpy (_data.data().get() + _offset, buffer, nb_bytes);
231                 _offset += nb_bytes;
232                 if (_offset > OPJ_SIZE_T (_data.size())) {
233                         _data.set_size (_offset);
234                 }
235                 return nb_bytes;
236         }
237
238         OPJ_BOOL seek (OPJ_SIZE_T nb_bytes)
239         {
240                 _offset = nb_bytes;
241                 return OPJ_TRUE;
242         }
243
244         Data data () const
245         {
246                 return _data;
247         }
248
249 private:
250         Data _data;
251         OPJ_SIZE_T _offset;
252 };
253
254 static OPJ_SIZE_T
255 write_function (void* buffer, OPJ_SIZE_T nb_bytes, void* data)
256 {
257         return reinterpret_cast<WriteBuffer*>(data)->write (buffer, nb_bytes);
258 }
259
260 static void
261 write_free_function (void* data)
262 {
263         delete reinterpret_cast<WriteBuffer*>(data);
264 }
265
266 static OPJ_BOOL
267 seek_function (OPJ_OFF_T nb_bytes, void* data)
268 {
269         return reinterpret_cast<WriteBuffer*>(data)->seek (nb_bytes);
270 }
271
272 /** @xyz Picture to compress.  Parts of xyz's data WILL BE OVERWRITTEN by libopenjpeg so xyz cannot be re-used
273  *  after this call; see opj_j2k_encode where if l_reuse_data is false it will set l_tilec->data = l_img_comp->data.
274  */
275 Data
276 dcp::compress_j2k (shared_ptr<const OpenJPEGImage> xyz, int bandwidth, int frames_per_second, bool threed, bool fourk)
277 {
278         /* get a J2K compressor handle */
279         opj_codec_t* encoder = opj_create_compress (OPJ_CODEC_J2K);
280         if (encoder == 0) {
281                 throw MiscError ("could not create JPEG2000 encoder");
282         }
283
284         opj_set_error_handler (encoder, compress_error_callback, 0);
285
286         /* Set encoding parameters to default values */
287         opj_cparameters_t parameters;
288         opj_set_default_encoder_parameters (&parameters);
289         if (fourk) {
290                 parameters.numresolution = 7;
291         }
292         parameters.rsiz = fourk ? OPJ_PROFILE_CINEMA_4K : OPJ_PROFILE_CINEMA_2K;
293         parameters.cp_comment = strdup ("libdcp");
294
295         /* set max image */
296         parameters.max_cs_size = (bandwidth / 8) / frames_per_second;
297         if (threed) {
298                 /* In 3D we have only half the normal bandwidth per eye */
299                 parameters.max_cs_size /= 2;
300         }
301         parameters.max_comp_size = parameters.max_cs_size / 1.25;
302         parameters.tcp_numlayers = 1;
303         parameters.tcp_mct = 1;
304
305         /* Setup the encoder parameters using the current image and user parameters */
306         opj_setup_encoder (encoder, &parameters, xyz->opj_image());
307
308         opj_stream_t* stream = opj_stream_default_create (OPJ_FALSE);
309         if (!stream) {
310                 throw MiscError ("could not create JPEG2000 stream");
311         }
312
313         opj_stream_set_write_function (stream, write_function);
314         opj_stream_set_seek_function (stream, seek_function);
315         WriteBuffer* buffer = new WriteBuffer ();
316         opj_stream_set_user_data (stream, buffer, write_free_function);
317
318         if (!opj_start_compress (encoder, xyz->opj_image(), stream)) {
319                 if ((errno & 0x61500) == 0x61500) {
320                         /* We've had one of the magic error codes from our patched openjpeg */
321                         boost::throw_exception (StartCompressionError (errno & 0xff));
322                 } else {
323                         boost::throw_exception (StartCompressionError ());
324                 }
325         }
326
327         if (!opj_encode (encoder, stream)) {
328                 opj_destroy_codec (encoder);
329                 opj_stream_destroy (stream);
330                 throw MiscError ("JPEG2000 encoding failed");
331         }
332
333         if (!opj_end_compress (encoder, stream)) {
334                 opj_destroy_codec (encoder);
335                 opj_stream_destroy (stream);
336                 throw MiscError ("could not end JPEG2000 encoding");
337         }
338
339         Data enc (buffer->data ());
340
341         free (parameters.cp_comment);
342         opj_destroy_codec (encoder);
343         opj_stream_destroy (stream);
344
345         return enc;
346 }
347 #endif
348
349 #ifdef LIBDCP_OPENJPEG1
350 Data
351 dcp::compress_j2k (shared_ptr<const OpenJPEGImage> xyz, int bandwidth, int frames_per_second, bool threed, bool fourk)
352 {
353         /* Set the max image and component sizes based on frame_rate */
354         int max_cs_len = ((float) bandwidth) / 8 / frames_per_second;
355         if (threed) {
356                 /* In 3D we have only half the normal bandwidth per eye */
357                 max_cs_len /= 2;
358         }
359         int const max_comp_size = max_cs_len / 1.25;
360
361         /* get a J2K compressor handle */
362         opj_cinfo_t* cinfo = opj_create_compress (CODEC_J2K);
363         if (cinfo == 0) {
364                 throw MiscError ("could not create JPEG2000 encoder");
365         }
366
367         /* Set encoding parameters to default values */
368         opj_cparameters_t parameters;
369         opj_set_default_encoder_parameters (&parameters);
370         if (fourk) {
371                 parameters.numresolution = 7;
372         }
373
374         /* Set default cinema parameters */
375         parameters.tile_size_on = false;
376         parameters.cp_tdx = 1;
377         parameters.cp_tdy = 1;
378
379         /* Tile part */
380         parameters.tp_flag = 'C';
381         parameters.tp_on = 1;
382
383         /* Tile and Image shall be at (0,0) */
384         parameters.cp_tx0 = 0;
385         parameters.cp_ty0 = 0;
386         parameters.image_offset_x0 = 0;
387         parameters.image_offset_y0 = 0;
388
389         /* Codeblock size = 32x32 */
390         parameters.cblockw_init = 32;
391         parameters.cblockh_init = 32;
392         parameters.csty |= 0x01;
393
394         /* The progression order shall be CPRL */
395         parameters.prog_order = CPRL;
396
397         /* No ROI */
398         parameters.roi_compno = -1;
399
400         parameters.subsampling_dx = 1;
401         parameters.subsampling_dy = 1;
402
403         /* 9-7 transform */
404         parameters.irreversible = 1;
405
406         parameters.tcp_rates[0] = 0;
407         parameters.tcp_numlayers++;
408         parameters.cp_disto_alloc = 1;
409         parameters.cp_rsiz = fourk ? CINEMA4K : CINEMA2K;
410         if (fourk) {
411                 parameters.numpocs = 2;
412                 parameters.POC[0].tile = 1;
413                 parameters.POC[0].resno0 = 0;
414                 parameters.POC[0].compno0 = 0;
415                 parameters.POC[0].layno1 = 1;
416                 parameters.POC[0].resno1 = parameters.numresolution - 1;
417                 parameters.POC[0].compno1 = 3;
418                 parameters.POC[0].prg1 = CPRL;
419                 parameters.POC[1].tile = 1;
420                 parameters.POC[1].resno0 = parameters.numresolution - 1;
421                 parameters.POC[1].compno0 = 0;
422                 parameters.POC[1].layno1 = 1;
423                 parameters.POC[1].resno1 = parameters.numresolution;
424                 parameters.POC[1].compno1 = 3;
425                 parameters.POC[1].prg1 = CPRL;
426         }
427
428         parameters.cp_comment = strdup ("libdcp");
429         parameters.cp_cinema = fourk ? CINEMA4K_24 : CINEMA2K_24;
430
431         /* 3 components, so use MCT */
432         parameters.tcp_mct = 1;
433
434         /* set max image */
435         parameters.max_comp_size = max_comp_size;
436         parameters.tcp_rates[0] = ((float) (3 * xyz->size().width * xyz->size().height * 12)) / (max_cs_len * 8);
437
438         /* Set event manager to null (openjpeg 1.3 bug) */
439         cinfo->event_mgr = 0;
440
441         /* Setup the encoder parameters using the current image and user parameters */
442         opj_setup_encoder (cinfo, &parameters, xyz->opj_image ());
443
444         opj_cio_t* cio = opj_cio_open ((opj_common_ptr) cinfo, 0, 0);
445         if (cio == 0) {
446                 opj_destroy_compress (cinfo);
447                 throw MiscError ("could not open JPEG2000 stream");
448         }
449
450         int const r = opj_encode (cinfo, cio, xyz->opj_image(), 0);
451         if (r == 0) {
452                 opj_cio_close (cio);
453                 opj_destroy_compress (cinfo);
454                 throw MiscError ("JPEG2000 encoding failed");
455         }
456
457         Data enc (cio->buffer, cio_tell (cio));
458
459         opj_cio_close (cio);
460         free (parameters.cp_comment);
461         opj_destroy_compress (cinfo);
462
463         return enc;
464 }
465
466 #endif