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