Port to openjpeg version 2.1.
[libdcp.git] / src / util.cc
1 /*
2     Copyright (C) 2012-2014 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 /** @file  src/util.cc
21  *  @brief Utility methods.
22  */
23
24 #include "util.h"
25 #include "exceptions.h"
26 #include "types.h"
27 #include "certificate.h"
28 #include "openjpeg_image.h"
29 #include "dcp_assert.h"
30 #include "compose.hpp"
31 #include "KM_util.h"
32 #include "KM_fileio.h"
33 #include "AS_DCP.h"
34 #include <openjpeg.h>
35 #include <xmlsec/xmldsig.h>
36 #include <xmlsec/dl.h>
37 #include <xmlsec/app.h>
38 #include <xmlsec/crypto.h>
39 #include <libxml++/nodes/element.h>
40 #include <libxml++/document.h>
41 #include <openssl/sha.h>
42 #include <boost/filesystem.hpp>
43 #include <boost/algorithm/string.hpp>
44 #include <stdexcept>
45 #include <sstream>
46 #include <iostream>
47 #include <iomanip>
48
49 using std::string;
50 using std::wstring;
51 using std::cout;
52 using std::stringstream;
53 using std::min;
54 using std::max;
55 using std::list;
56 using std::setw;
57 using std::setfill;
58 using std::ostream;
59 using boost::shared_ptr;
60 using boost::shared_array;
61 using boost::optional;
62 using boost::function;
63 using boost::algorithm::trim;
64 using namespace dcp;
65
66 /** Create a UUID.
67  *  @return UUID.
68  */
69 string
70 dcp::make_uuid ()
71 {
72         char buffer[64];
73         Kumu::UUID id;
74         Kumu::GenRandomValue (id);
75         id.EncodeHex (buffer, 64);
76         return string (buffer);
77 }
78
79
80 /** Create a digest for a file.
81  *  @param filename File name.
82  *  @param progress Optional progress reporting function.  The function will be called
83  *  with a progress value between 0 and 1.
84  *  @return Digest.
85  */
86 string
87 dcp::make_digest (boost::filesystem::path filename, function<void (float)> progress)
88 {
89         Kumu::FileReader reader;
90         Kumu::Result_t r = reader.OpenRead (filename.string().c_str ());
91         if (ASDCP_FAILURE (r)) {
92                 boost::throw_exception (FileError ("could not open file to compute digest", filename, r));
93         }
94
95         SHA_CTX sha;
96         SHA1_Init (&sha);
97
98         int const buffer_size = 65536;
99         Kumu::ByteString read_buffer (buffer_size);
100
101         Kumu::fsize_t done = 0;
102         Kumu::fsize_t const size = reader.Size ();
103         while (1) {
104                 ui32_t read = 0;
105                 Kumu::Result_t r = reader.Read (read_buffer.Data(), read_buffer.Capacity(), &read);
106
107                 if (r == Kumu::RESULT_ENDOFFILE) {
108                         break;
109                 } else if (ASDCP_FAILURE (r)) {
110                         boost::throw_exception (FileError ("could not read file to compute digest", filename, r));
111                 }
112
113                 SHA1_Update (&sha, read_buffer.Data(), read);
114
115                 if (progress) {
116                         progress (float (done) / size);
117                         done += read;
118                 }
119         }
120
121         byte_t byte_buffer[SHA_DIGEST_LENGTH];
122         SHA1_Final (byte_buffer, &sha);
123
124         char digest[64];
125         return Kumu::base64encode (byte_buffer, SHA_DIGEST_LENGTH, digest, 64);
126 }
127
128 /** Convert a content kind to a string which can be used in a
129  *  &lt;ContentKind&gt; node.
130  *  @param kind ContentKind.
131  *  @return string.
132  */
133 string
134 dcp::content_kind_to_string (ContentKind kind)
135 {
136         switch (kind) {
137         case FEATURE:
138                 return "feature";
139         case SHORT:
140                 return "short";
141         case TRAILER:
142                 return "trailer";
143         case TEST:
144                 return "test";
145         case TRANSITIONAL:
146                 return "transitional";
147         case RATING:
148                 return "rating";
149         case TEASER:
150                 return "teaser";
151         case POLICY:
152                 return "policy";
153         case PUBLIC_SERVICE_ANNOUNCEMENT:
154                 return "psa";
155         case ADVERTISEMENT:
156                 return "advertisement";
157         }
158
159         DCP_ASSERT (false);
160 }
161
162 /** Convert a string from a &lt;ContentKind&gt; node to a libdcp ContentKind.
163  *  Reasonably tolerant about varying case.
164  *  @param kind Content kind string.
165  *  @return libdcp ContentKind.
166  */
167 dcp::ContentKind
168 dcp::content_kind_from_string (string kind)
169 {
170         transform (kind.begin(), kind.end(), kind.begin(), ::tolower);
171
172         if (kind == "feature") {
173                 return FEATURE;
174         } else if (kind == "short") {
175                 return SHORT;
176         } else if (kind == "trailer") {
177                 return TRAILER;
178         } else if (kind == "test") {
179                 return TEST;
180         } else if (kind == "transitional") {
181                 return TRANSITIONAL;
182         } else if (kind == "rating") {
183                 return RATING;
184         } else if (kind == "teaser") {
185                 return TEASER;
186         } else if (kind == "policy") {
187                 return POLICY;
188         } else if (kind == "psa") {
189                 return PUBLIC_SERVICE_ANNOUNCEMENT;
190         } else if (kind == "advertisement") {
191                 return ADVERTISEMENT;
192         }
193
194         DCP_ASSERT (false);
195 }
196
197 shared_ptr<dcp::OpenJPEGImage>
198 dcp::decompress_j2k (Data data, int reduce)
199 {
200         return dcp::decompress_j2k (data.data.get(), data.size, reduce);
201 }
202
203 class ReadBuffer
204 {
205 public:
206         ReadBuffer (uint8_t* data, int64_t size)
207                 : _data (data)
208                 , _size (size)
209                 , _offset (0)
210         {}
211
212         OPJ_SIZE_T read (void* buffer, OPJ_SIZE_T nb_bytes)
213         {
214                 int64_t N = min (nb_bytes, _size - _offset);
215                 memcpy (buffer, _data + _offset, N);
216                 _offset += N;
217                 return N;
218         }
219
220 private:
221         uint8_t* _data;
222         OPJ_SIZE_T _size;
223         OPJ_SIZE_T _offset;
224 };
225
226 static OPJ_SIZE_T
227 read_function (void* buffer, OPJ_SIZE_T nb_bytes, void* data)
228 {
229         return reinterpret_cast<ReadBuffer*>(data)->read (buffer, nb_bytes);
230 }
231
232 static void
233 read_free_function (void* data)
234 {
235         delete reinterpret_cast<ReadBuffer*>(data);
236 }
237
238 /** Decompress a JPEG2000 image to a bitmap.
239  *  @param data JPEG2000 data.
240  *  @param size Size of data in bytes.
241  *  @param reduce A power of 2 by which to reduce the size of the decoded image;
242  *  e.g. 0 reduces by (2^0 == 1), ie keeping the same size.
243  *       1 reduces by (2^1 == 2), ie halving the size of the image.
244  *  This is useful for scaling 4K DCP images down to 2K.
245  *  @return OpenJPEGImage.
246  */
247 shared_ptr<dcp::OpenJPEGImage>
248 dcp::decompress_j2k (uint8_t* data, int64_t size, int reduce)
249 {
250         uint8_t const jp2_magic[] = {
251                 0x00,
252                 0x00,
253                 0x00,
254                 0x0c,
255                 'j',
256                 'P',
257                 0x20,
258                 0x20
259         };
260
261         OPJ_CODEC_FORMAT format = OPJ_CODEC_J2K;
262         if (size >= int (sizeof (jp2_magic)) && memcmp (data, jp2_magic, sizeof (jp2_magic)) == 0) {
263                 format = OPJ_CODEC_JP2;
264         }
265
266         opj_codec_t* decoder = opj_create_decompress (format);
267         if (!decoder) {
268                 boost::throw_exception (DCPReadError ("could not create JPEG2000 decompresser"));
269         }
270         opj_dparameters_t parameters;
271         opj_set_default_decoder_parameters (&parameters);
272         parameters.cp_reduce = reduce;
273         opj_setup_decoder (decoder, &parameters);
274
275         opj_stream_t* stream = opj_stream_default_create (OPJ_TRUE);
276         if (!stream) {
277                 throw MiscError ("could not create JPEG2000 stream");
278         }
279
280         opj_stream_set_read_function (stream, read_function);
281         ReadBuffer* buffer = new ReadBuffer (data, size);
282         opj_stream_set_user_data (stream, buffer, read_free_function);
283         opj_stream_set_user_data_length (stream, size);
284
285         opj_image_t* image = 0;
286         opj_read_header (stream, decoder, &image);
287         if (opj_decode (decoder, stream, image) == OPJ_FALSE) {
288                 opj_destroy_codec (decoder);
289                 opj_stream_destroy (stream);
290                 if (format == OPJ_CODEC_J2K) {
291                         boost::throw_exception (DCPReadError (String::compose ("could not decode JPEG2000 codestream of %1 bytes.", size)));
292                 } else {
293                         boost::throw_exception (DCPReadError (String::compose ("could not decode JP2 file of %1 bytes.", size)));
294                 }
295         }
296
297         opj_destroy_codec (decoder);
298         opj_stream_destroy (stream);
299
300         image->x1 = rint (float(image->x1) / pow (2, reduce));
301         image->y1 = rint (float(image->y1) / pow (2, reduce));
302         return shared_ptr<OpenJPEGImage> (new OpenJPEGImage (image));
303 }
304
305 class WriteBuffer
306 {
307 public:
308 /* XXX: is there a better strategy for this? */
309 #define MAX_J2K_SIZE (1024 * 1024 * 2)
310         WriteBuffer ()
311                 : _data (shared_array<uint8_t> (new uint8_t[MAX_J2K_SIZE]), MAX_J2K_SIZE)
312                 , _offset (0)
313         {}
314
315         OPJ_SIZE_T write (void* buffer, OPJ_SIZE_T nb_bytes)
316         {
317                 DCP_ASSERT ((_offset + nb_bytes) < MAX_J2K_SIZE);
318                 memcpy (_data.data.get() + _offset, buffer, nb_bytes);
319                 _offset += nb_bytes;
320                 return nb_bytes;
321         }
322
323         Data data () const {
324                 return _data;
325         }
326
327 private:
328         Data _data;
329         OPJ_SIZE_T _offset;
330 };
331
332 static OPJ_SIZE_T
333 write_function (void* buffer, OPJ_SIZE_T nb_bytes, void* data)
334 {
335         return reinterpret_cast<WriteBuffer*>(data)->write (buffer, nb_bytes);
336 }
337
338 static void
339 write_free_function (void* data)
340 {
341         delete reinterpret_cast<WriteBuffer*>(data);
342 }
343
344 Data
345 dcp::compress_j2k (shared_ptr<const OpenJPEGImage> xyz, int bandwidth, int frames_per_second, bool threed, bool fourk)
346 {
347         /* XXX: should probably use opj_set_*_handler */
348
349         /* Set the max image and component sizes based on frame_rate */
350         int max_cs_len = ((float) bandwidth) / 8 / frames_per_second;
351         if (threed) {
352                 /* In 3D we have only half the normal bandwidth per eye */
353                 max_cs_len /= 2;
354         }
355         int const max_comp_size = max_cs_len / 1.25;
356
357         /* get a J2K compressor handle */
358         opj_codec_t* encoder = opj_create_compress (OPJ_CODEC_J2K);
359         if (encoder == 0) {
360                 throw MiscError ("could not create JPEG2000 encoder");
361         }
362
363         /* Set encoding parameters to default values */
364         opj_cparameters_t parameters;
365         opj_set_default_encoder_parameters (&parameters);
366
367         /* Set default cinema parameters */
368         parameters.tile_size_on = OPJ_FALSE;
369         parameters.cp_tdx = 1;
370         parameters.cp_tdy = 1;
371
372         /* Tile part */
373         parameters.tp_flag = 'C';
374         parameters.tp_on = 1;
375
376         /* Tile and Image shall be at (0,0) */
377         parameters.cp_tx0 = 0;
378         parameters.cp_ty0 = 0;
379         parameters.image_offset_x0 = 0;
380         parameters.image_offset_y0 = 0;
381
382         /* Codeblock size = 32x32 */
383         parameters.cblockw_init = 32;
384         parameters.cblockh_init = 32;
385         parameters.csty |= 0x01;
386
387         /* The progression order shall be CPRL */
388         parameters.prog_order = OPJ_CPRL;
389
390         /* No ROI */
391         parameters.roi_compno = -1;
392
393         parameters.subsampling_dx = 1;
394         parameters.subsampling_dy = 1;
395
396         /* 9-7 transform */
397         parameters.irreversible = 1;
398
399         parameters.tcp_rates[0] = 0;
400         parameters.tcp_numlayers++;
401         parameters.cp_disto_alloc = 1;
402         parameters.cp_rsiz = fourk ? OPJ_CINEMA4K : OPJ_CINEMA2K;
403         if (fourk) {
404                 parameters.numpocs = 2;
405                 parameters.POC[0].tile = 1;
406                 parameters.POC[0].resno0 = 0;
407                 parameters.POC[0].compno0 = 0;
408                 parameters.POC[0].layno1 = 1;
409                 parameters.POC[0].resno1 = parameters.numresolution - 1;
410                 parameters.POC[0].compno1 = 3;
411                 parameters.POC[0].prg1 = OPJ_CPRL;
412                 parameters.POC[1].tile = 1;
413                 parameters.POC[1].resno0 = parameters.numresolution - 1;
414                 parameters.POC[1].compno0 = 0;
415                 parameters.POC[1].layno1 = 1;
416                 parameters.POC[1].resno1 = parameters.numresolution;
417                 parameters.POC[1].compno1 = 3;
418                 parameters.POC[1].prg1 = OPJ_CPRL;
419         }
420
421         parameters.cp_comment = strdup ("libdcp");
422         parameters.cp_cinema = fourk ? OPJ_CINEMA4K_24 : OPJ_CINEMA2K_24;
423
424         /* 3 components, so use MCT */
425         parameters.tcp_mct = 1;
426
427         /* set max image */
428         parameters.max_comp_size = max_comp_size;
429         parameters.tcp_rates[0] = ((float) (3 * xyz->size().width * xyz->size().height * 12)) / (max_cs_len * 8);
430
431         /* Setup the encoder parameters using the current image and user parameters */
432         opj_setup_encoder (encoder, &parameters, xyz->opj_image());
433
434         opj_stream_t* stream = opj_stream_default_create (OPJ_FALSE);
435         if (!stream) {
436                 throw MiscError ("could not create JPEG2000 stream");
437         }
438
439         opj_stream_set_write_function (stream, write_function);
440         WriteBuffer* buffer = new WriteBuffer ();
441         opj_stream_set_user_data (stream, buffer, write_free_function);
442
443         if (!opj_start_compress (encoder, xyz->opj_image(), stream)) {
444                 throw MiscError ("could not start JPEG2000 encoding");
445         }
446
447         if (!opj_encode (encoder, stream)) {
448                 opj_destroy_codec (encoder);
449                 opj_stream_destroy (stream);
450                 throw MiscError ("JPEG2000 encoding failed");
451         }
452
453         if (!opj_end_compress (encoder, stream)) {
454                 throw MiscError ("could not end JPEG2000 encoding");
455         }
456
457         Data enc (buffer->data ());
458
459         free (parameters.cp_comment);
460         opj_destroy_codec (encoder);
461         opj_stream_destroy (stream);
462
463         return enc;
464 }
465
466 /** @param s A string.
467  *  @return true if the string contains only space, newline or tab characters, or is empty.
468  */
469 bool
470 dcp::empty_or_white_space (string s)
471 {
472         for (size_t i = 0; i < s.length(); ++i) {
473                 if (s[i] != ' ' && s[i] != '\n' && s[i] != '\t') {
474                         return false;
475                 }
476         }
477
478         return true;
479 }
480
481 /** Set up various bits that the library needs.  Should be called one
482  *  by client applications.
483  */
484 void
485 dcp::init ()
486 {
487         if (xmlSecInit() < 0) {
488                 throw MiscError ("could not initialise xmlsec");
489         }
490
491 #ifdef XMLSEC_CRYPTO_DYNAMIC_LOADING
492         if (xmlSecCryptoDLLoadLibrary(BAD_CAST XMLSEC_CRYPTO) < 0) {
493                 throw MiscError ("unable to load default xmlsec-crypto library");
494         }
495 #endif
496
497         if (xmlSecCryptoAppInit(0) < 0) {
498                 throw MiscError ("could not initialise crypto");
499         }
500
501         if (xmlSecCryptoInit() < 0) {
502                 throw MiscError ("could not initialise xmlsec-crypto");
503         }
504 }
505
506 bool dcp::operator== (dcp::Size const & a, dcp::Size const & b)
507 {
508         return (a.width == b.width && a.height == b.height);
509 }
510
511 bool dcp::operator!= (dcp::Size const & a, dcp::Size const & b)
512 {
513         return !(a == b);
514 }
515
516 ostream& dcp::operator<< (ostream& s, dcp::Size const & a)
517 {
518         s << a.width << "x" << a.height;
519         return s;
520 }
521
522 /** Decode a base64 string.  The base64 decode routine in KM_util.cpp
523  *  gives different values to both this and the command-line base64
524  *  for some inputs.  Not sure why.
525  *
526  *  @param in base64-encoded string.
527  *  @param out Output buffer.
528  *  @param out_length Length of output buffer.
529  *  @return Number of characters written to the output buffer.
530  */
531 int
532 dcp::base64_decode (string const & in, unsigned char* out, int out_length)
533 {
534         BIO* b64 = BIO_new (BIO_f_base64 ());
535
536         /* This means the input should have no newlines */
537         BIO_set_flags (b64, BIO_FLAGS_BASE64_NO_NL);
538
539         /* Copy our input string, removing newlines */
540         char in_buffer[in.size() + 1];
541         char* p = in_buffer;
542         for (size_t i = 0; i < in.size(); ++i) {
543                 if (in[i] != '\n' && in[i] != '\r') {
544                         *p++ = in[i];
545                 }
546         }
547
548         BIO* bmem = BIO_new_mem_buf (in_buffer, p - in_buffer);
549         bmem = BIO_push (b64, bmem);
550         int const N = BIO_read (bmem, out, out_length);
551         BIO_free_all (bmem);
552
553         return N;
554 }
555
556 /** @param p Path to open.
557  *  @param t mode flags, as for fopen(3).
558  *  @return FILE pointer or 0 on error.
559  *
560  *  Apparently there is no way to create an ofstream using a UTF-8
561  *  filename under Windows.  We are hence reduced to using fopen
562  *  with this wrapper.
563  */
564 FILE *
565 dcp::fopen_boost (boost::filesystem::path p, string t)
566 {
567 #ifdef LIBDCP_WINDOWS
568         wstring w (t.begin(), t.end());
569         /* c_str() here should give a UTF-16 string */
570         return _wfopen (p.c_str(), w.c_str ());
571 #else
572         return fopen (p.c_str(), t.c_str ());
573 #endif
574 }
575
576 optional<boost::filesystem::path>
577 dcp::relative_to_root (boost::filesystem::path root, boost::filesystem::path file)
578 {
579         boost::filesystem::path::const_iterator i = root.begin ();
580         boost::filesystem::path::const_iterator j = file.begin ();
581
582         while (i != root.end() && j != file.end() && *i == *j) {
583                 ++i;
584                 ++j;
585         }
586
587         if (i != root.end ()) {
588                 return optional<boost::filesystem::path> ();
589         }
590
591         boost::filesystem::path rel;
592         while (j != file.end ()) {
593                 rel /= *j++;
594         }
595
596         return rel;
597 }
598
599 bool
600 dcp::ids_equal (string a, string b)
601 {
602         transform (a.begin(), a.end(), a.begin(), ::tolower);
603         transform (b.begin(), b.end(), b.begin(), ::tolower);
604         trim (a);
605         trim (b);
606         return a == b;
607 }
608
609 string
610 dcp::file_to_string (boost::filesystem::path p, uintmax_t max_length)
611 {
612         uintmax_t len = boost::filesystem::file_size (p);
613         if (len > max_length) {
614                 throw MiscError ("Unexpectedly long file");
615         }
616
617         FILE* f = fopen_boost (p, "r");
618         if (!f) {
619                 throw FileError ("could not open file", p, errno);
620         }
621
622         char* c = new char[len];
623         /* This may read less than `len' if we are on Windows and we have CRLF in the file */
624         int const N = fread (c, 1, len, f);
625         fclose (f);
626
627         string s (c, N);
628         delete[] c;
629
630         return s;
631 }
632
633 /** @param key RSA private key in PEM format (optionally with -----BEGIN... / -----END...)
634  *  @return SHA1 fingerprint of key
635  */
636 string
637 dcp::private_key_fingerprint (string key)
638 {
639         boost::replace_all (key, "-----BEGIN RSA PRIVATE KEY-----\n", "");
640         boost::replace_all (key, "\n-----END RSA PRIVATE KEY-----\n", "");
641
642         unsigned char buffer[4096];
643         int const N = base64_decode (key, buffer, sizeof (buffer));
644
645         SHA_CTX sha;
646         SHA1_Init (&sha);
647         SHA1_Update (&sha, buffer, N);
648         uint8_t digest[20];
649         SHA1_Final (digest, &sha);
650
651         char digest_base64[64];
652         return Kumu::base64encode (digest, 20, digest_base64, 64);
653 }
654
655 xmlpp::Node *
656 dcp::find_child (xmlpp::Node const * node, string name)
657 {
658         xmlpp::Node::NodeList c = node->get_children ();
659         xmlpp::Node::NodeList::iterator i = c.begin();
660         while (i != c.end() && (*i)->get_name() != name) {
661                 ++i;
662         }
663
664         DCP_ASSERT (i != c.end ());
665         return *i;
666 }