2 Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
4 This file is part of libdcp.
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.
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.
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/>.
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
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.
35 /** @file src/j2k_transcode.cc
36 * @brief Methods to encode and decode JPEG2000
40 #include "array_data.h"
41 #include "j2k_transcode.h"
42 #include "exceptions.h"
43 #include "openjpeg_image.h"
44 #include "dcp_assert.h"
45 #include "compose.hpp"
54 using std::shared_ptr;
55 using boost::shared_array;
59 shared_ptr<dcp::OpenJPEGImage>
60 dcp::decompress_j2k (Data const& data, int reduce)
62 return dcp::decompress_j2k (data.data(), data.size(), reduce);
66 shared_ptr<dcp::OpenJPEGImage>
67 dcp::decompress_j2k (shared_ptr<const Data> data, int reduce)
69 return dcp::decompress_j2k (data->data(), data->size(), reduce);
73 #ifdef LIBDCP_OPENJPEG2
78 ReadBuffer (uint8_t const * data, int64_t size)
84 OPJ_SIZE_T read (void* buffer, OPJ_SIZE_T nb_bytes)
86 int64_t N = min (nb_bytes, _size - _offset);
87 memcpy (buffer, _data + _offset, N);
93 uint8_t const * _data;
100 read_function (void* buffer, OPJ_SIZE_T nb_bytes, void* data)
102 return reinterpret_cast<ReadBuffer*>(data)->read (buffer, nb_bytes);
107 read_free_function (void* data)
109 delete reinterpret_cast<ReadBuffer*>(data);
114 decompress_error_callback (char const * msg, void *)
116 throw J2KDecompressionError (msg);
121 compress_error_callback (char const * msg, void *)
123 throw MiscError (msg);
127 shared_ptr<dcp::OpenJPEGImage>
128 dcp::decompress_j2k (uint8_t const * data, int64_t size, int reduce)
130 DCP_ASSERT (reduce >= 0);
132 uint8_t const jp2_magic[] = {
143 auto format = OPJ_CODEC_J2K;
144 if (size >= int (sizeof (jp2_magic)) && memcmp (data, jp2_magic, sizeof (jp2_magic)) == 0) {
145 format = OPJ_CODEC_JP2;
148 auto decoder = opj_create_decompress (format);
150 boost::throw_exception (ReadError ("could not create JPEG2000 decompresser"));
152 opj_dparameters_t parameters;
153 opj_set_default_decoder_parameters (¶meters);
154 parameters.cp_reduce = reduce;
155 opj_setup_decoder (decoder, ¶meters);
157 auto stream = opj_stream_default_create (OPJ_TRUE);
159 throw MiscError ("could not create JPEG2000 stream");
162 opj_set_error_handler(decoder, decompress_error_callback, 00);
164 opj_stream_set_read_function (stream, read_function);
165 auto buffer = new ReadBuffer (data, size);
166 opj_stream_set_user_data (stream, buffer, read_free_function);
167 opj_stream_set_user_data_length (stream, size);
169 opj_image_t* image = 0;
170 opj_read_header (stream, decoder, &image);
171 if (opj_decode (decoder, stream, image) == OPJ_FALSE) {
172 opj_destroy_codec (decoder);
173 opj_stream_destroy (stream);
174 if (format == OPJ_CODEC_J2K) {
175 boost::throw_exception (ReadError (String::compose ("could not decode JPEG2000 codestream of %1 bytes.", size)));
177 boost::throw_exception (ReadError (String::compose ("could not decode JP2 file of %1 bytes.", size)));
181 opj_destroy_codec (decoder);
182 opj_stream_destroy (stream);
184 image->x1 = rint (float(image->x1) / pow (2.0f, reduce));
185 image->y1 = rint (float(image->y1) / pow (2.0f, reduce));
186 return shared_ptr<OpenJPEGImage> (new OpenJPEGImage (image));
192 #ifdef LIBDCP_OPENJPEG1
194 shared_ptr<dcp::OpenJPEGImage>
195 dcp::decompress_j2k (uint8_t* data, int64_t size, int reduce)
197 auto decoder = opj_create_decompress (CODEC_J2K);
198 opj_dparameters_t parameters;
199 opj_set_default_decoder_parameters (¶meters);
200 parameters.cp_reduce = reduce;
201 opj_setup_decoder (decoder, ¶meters);
202 auto cio = opj_cio_open ((opj_common_ptr) decoder, data, size);
203 auto image = opj_decode (decoder, cio);
205 opj_destroy_decompress (decoder);
207 boost::throw_exception (ReadError (String::compose ("could not decode JPEG2000 codestream of %1 bytes.", size)));
210 opj_destroy_decompress (decoder);
213 image->x1 = rint (float(image->x1) / pow (2, reduce));
214 image->y1 = rint (float(image->y1) / pow (2, reduce));
215 return shared_ptr<OpenJPEGImage> (new OpenJPEGImage (image));
220 #ifdef LIBDCP_OPENJPEG2
225 /* XXX: is there a better strategy for this? */
226 #define MAX_J2K_SIZE (1024 * 1024 * 2)
228 : _data (shared_array<uint8_t>(new uint8_t[MAX_J2K_SIZE]), MAX_J2K_SIZE)
234 OPJ_SIZE_T write (void* buffer, OPJ_SIZE_T nb_bytes)
236 DCP_ASSERT ((_offset + nb_bytes) < MAX_J2K_SIZE);
237 memcpy (_data.data() + _offset, buffer, nb_bytes);
239 if (_offset > OPJ_SIZE_T(_data.size())) {
240 _data.set_size (_offset);
245 OPJ_BOOL seek (OPJ_SIZE_T nb_bytes)
251 ArrayData data () const
263 write_function (void* buffer, OPJ_SIZE_T nb_bytes, void* data)
265 return reinterpret_cast<WriteBuffer*>(data)->write(buffer, nb_bytes);
270 write_free_function (void* data)
272 delete reinterpret_cast<WriteBuffer*>(data);
277 seek_function (OPJ_OFF_T nb_bytes, void* data)
279 return reinterpret_cast<WriteBuffer*>(data)->seek(nb_bytes);
285 dcp::compress_j2k (shared_ptr<const OpenJPEGImage> xyz, int bandwidth, int frames_per_second, bool threed, bool fourk, string comment)
287 /* get a J2K compressor handle */
288 auto encoder = opj_create_compress (OPJ_CODEC_J2K);
289 if (encoder == nullptr) {
290 throw MiscError ("could not create JPEG2000 encoder");
293 if (comment.empty()) {
294 /* asdcplib complains with "Illegal data size" when reading frames encoded with an empty comment */
295 throw MiscError("compress_j2k comment can not be an empty string");
298 opj_set_error_handler (encoder, compress_error_callback, 0);
300 /* Set encoding parameters to default values */
301 opj_cparameters_t parameters;
302 opj_set_default_encoder_parameters (¶meters);
304 parameters.numresolution = 7;
306 parameters.rsiz = fourk ? OPJ_PROFILE_CINEMA_4K : OPJ_PROFILE_CINEMA_2K;
307 parameters.cp_comment = strdup (comment.c_str());
310 parameters.max_cs_size = (bandwidth / 8) / frames_per_second;
312 /* In 3D we have only half the normal bandwidth per eye */
313 parameters.max_cs_size /= 2;
315 parameters.max_comp_size = parameters.max_cs_size / 1.25;
316 parameters.tcp_numlayers = 1;
317 parameters.tcp_mct = 1;
318 parameters.numgbits = fourk ? 2 : 1;
320 /* Setup the encoder parameters using the current image and user parameters */
321 opj_setup_encoder (encoder, ¶meters, xyz->opj_image());
323 auto stream = opj_stream_default_create (OPJ_FALSE);
325 opj_destroy_codec (encoder);
326 free (parameters.cp_comment);
327 throw MiscError ("could not create JPEG2000 stream");
330 opj_stream_set_write_function (stream, write_function);
331 opj_stream_set_seek_function (stream, seek_function);
332 WriteBuffer* buffer = new WriteBuffer ();
333 opj_stream_set_user_data (stream, buffer, write_free_function);
335 if (!opj_start_compress (encoder, xyz->opj_image(), stream)) {
336 opj_stream_destroy (stream);
337 opj_destroy_codec (encoder);
338 free (parameters.cp_comment);
339 if ((errno & 0x61500) == 0x61500) {
340 /* We've had one of the magic error codes from our patched openjpeg */
341 boost::throw_exception (StartCompressionError (errno & 0xff));
343 boost::throw_exception (StartCompressionError ());
347 if (!opj_encode (encoder, stream)) {
348 opj_stream_destroy (stream);
349 opj_destroy_codec (encoder);
350 free (parameters.cp_comment);
351 throw MiscError ("JPEG2000 encoding failed");
354 if (!opj_end_compress (encoder, stream)) {
355 opj_stream_destroy (stream);
356 opj_destroy_codec (encoder);
357 free (parameters.cp_comment);
358 throw MiscError ("could not end JPEG2000 encoding");
361 ArrayData enc (buffer->data ());
363 opj_stream_destroy (stream);
364 opj_destroy_codec (encoder);
365 free (parameters.cp_comment);
373 #ifdef LIBDCP_OPENJPEG1
376 dcp::compress_j2k (shared_ptr<const OpenJPEGImage> xyz, int bandwidth, int frames_per_second, bool threed, bool fourk)
378 /* Set the max image and component sizes based on frame_rate */
379 int max_cs_len = ((float) bandwidth) / 8 / frames_per_second;
381 /* In 3D we have only half the normal bandwidth per eye */
384 int const max_comp_size = max_cs_len / 1.25;
386 /* get a J2K compressor handle */
387 auto cinfo = opj_create_compress (CODEC_J2K);
388 if (cinfo == nullptr) {
389 throw MiscError ("could not create JPEG2000 encoder");
392 /* Set encoding parameters to default values */
393 opj_cparameters_t parameters;
394 opj_set_default_encoder_parameters (¶meters);
396 parameters.numresolution = 7;
399 /* Set default cinema parameters */
400 parameters.tile_size_on = false;
401 parameters.cp_tdx = 1;
402 parameters.cp_tdy = 1;
405 parameters.tp_flag = 'C';
406 parameters.tp_on = 1;
408 /* Tile and Image shall be at (0,0) */
409 parameters.cp_tx0 = 0;
410 parameters.cp_ty0 = 0;
411 parameters.image_offset_x0 = 0;
412 parameters.image_offset_y0 = 0;
414 /* Codeblock size = 32x32 */
415 parameters.cblockw_init = 32;
416 parameters.cblockh_init = 32;
417 parameters.csty |= 0x01;
419 /* The progression order shall be CPRL */
420 parameters.prog_order = CPRL;
423 parameters.roi_compno = -1;
425 parameters.subsampling_dx = 1;
426 parameters.subsampling_dy = 1;
429 parameters.irreversible = 1;
431 parameters.tcp_rates[0] = 0;
432 parameters.tcp_numlayers++;
433 parameters.cp_disto_alloc = 1;
434 parameters.cp_rsiz = fourk ? CINEMA4K : CINEMA2K;
436 parameters.numpocs = 2;
437 parameters.POC[0].tile = 1;
438 parameters.POC[0].resno0 = 0;
439 parameters.POC[0].compno0 = 0;
440 parameters.POC[0].layno1 = 1;
441 parameters.POC[0].resno1 = parameters.numresolution - 1;
442 parameters.POC[0].compno1 = 3;
443 parameters.POC[0].prg1 = CPRL;
444 parameters.POC[1].tile = 1;
445 parameters.POC[1].resno0 = parameters.numresolution - 1;
446 parameters.POC[1].compno0 = 0;
447 parameters.POC[1].layno1 = 1;
448 parameters.POC[1].resno1 = parameters.numresolution;
449 parameters.POC[1].compno1 = 3;
450 parameters.POC[1].prg1 = CPRL;
453 parameters.cp_comment = strdup ("libdcp");
454 parameters.cp_cinema = fourk ? CINEMA4K_24 : CINEMA2K_24;
456 /* 3 components, so use MCT */
457 parameters.tcp_mct = 1;
460 parameters.max_comp_size = max_comp_size;
461 parameters.tcp_rates[0] = ((float) (3 * xyz->size().width * xyz->size().height * 12)) / (max_cs_len * 8);
463 /* Set event manager to null (openjpeg 1.3 bug) */
464 cinfo->event_mgr = 0;
466 /* Setup the encoder parameters using the current image and user parameters */
467 opj_setup_encoder (cinfo, ¶meters, xyz->opj_image());
469 auto cio = opj_cio_open ((opj_common_ptr) cinfo, 0, 0);
470 if (cio == nullptr) {
471 opj_destroy_compress (cinfo);
472 throw MiscError ("could not open JPEG2000 stream");
475 int const r = opj_encode (cinfo, cio, xyz->opj_image(), 0);
478 opj_destroy_compress (cinfo);
479 throw MiscError ("JPEG2000 encoding failed");
482 ArrayData enc (cio->buffer, cio_tell (cio));
485 free (parameters.cp_comment);
486 opj_destroy_compress (cinfo);