Make film hold its DCP frame rate.
[dcpomatic.git] / src / lib / film.cc
1 /*
2     Copyright (C) 2012 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 #include <stdexcept>
21 #include <iostream>
22 #include <algorithm>
23 #include <fstream>
24 #include <cstdlib>
25 #include <sstream>
26 #include <iomanip>
27 #include <unistd.h>
28 #include <boost/filesystem.hpp>
29 #include <boost/algorithm/string.hpp>
30 #include <boost/lexical_cast.hpp>
31 #include <boost/date_time.hpp>
32 #include "film.h"
33 #include "format.h"
34 #include "job.h"
35 #include "filter.h"
36 #include "transcoder.h"
37 #include "util.h"
38 #include "job_manager.h"
39 #include "ab_transcode_job.h"
40 #include "transcode_job.h"
41 #include "scp_dcp_job.h"
42 #include "log.h"
43 #include "options.h"
44 #include "exceptions.h"
45 #include "examine_content_job.h"
46 #include "scaler.h"
47 #include "decoder_factory.h"
48 #include "config.h"
49 #include "version.h"
50 #include "ui_signaller.h"
51 #include "video_decoder.h"
52 #include "audio_decoder.h"
53 #include "external_audio_decoder.h"
54 #include "analyse_audio_job.h"
55
56 #include "i18n.h"
57
58 using std::string;
59 using std::stringstream;
60 using std::multimap;
61 using std::pair;
62 using std::map;
63 using std::vector;
64 using std::ifstream;
65 using std::ofstream;
66 using std::setfill;
67 using std::min;
68 using std::make_pair;
69 using boost::shared_ptr;
70 using boost::lexical_cast;
71 using boost::to_upper_copy;
72 using boost::ends_with;
73 using boost::starts_with;
74 using boost::optional;
75 using libdcp::Size;
76
77 int const Film::state_version = 4;
78
79 /** Construct a Film object in a given directory, reading any metadata
80  *  file that exists in that directory.  An exception will be thrown if
81  *  must_exist is true and the specified directory does not exist.
82  *
83  *  @param d Film directory.
84  *  @param must_exist true to throw an exception if does not exist.
85  */
86
87 Film::Film (string d, bool must_exist)
88         : _use_dci_name (true)
89         , _trust_content_header (true)
90         , _dcp_content_type (0)
91         , _format (0)
92         , _scaler (Scaler::from_id (N_("bicubic")))
93         , _trim_start (0)
94         , _trim_end (0)
95         , _dcp_ab (false)
96         , _use_content_audio (true)
97         , _audio_gain (0)
98         , _audio_delay (0)
99         , _still_duration (10)
100         , _with_subtitles (false)
101         , _subtitle_offset (0)
102         , _subtitle_scale (1)
103         , _colour_lut (0)
104         , _j2k_bandwidth (200000000)
105         , _dci_metadata (Config::instance()->default_dci_metadata ())
106         , _dcp_frame_rate (0)
107         , _source_frame_rate (0)
108         , _dirty (false)
109 {
110         set_dci_date_today ();
111         
112         /* Make state.directory a complete path without ..s (where possible)
113            (Code swiped from Adam Bowen on stackoverflow)
114         */
115         
116         boost::filesystem::path p (boost::filesystem::system_complete (d));
117         boost::filesystem::path result;
118         for (boost::filesystem::path::iterator i = p.begin(); i != p.end(); ++i) {
119                 if (*i == N_("..")) {
120                         if (boost::filesystem::is_symlink (result) || result.filename() == N_("..")) {
121                                 result /= *i;
122                         } else {
123                                 result = result.parent_path ();
124                         }
125                 } else if (*i != N_(".")) {
126                         result /= *i;
127                 }
128         }
129
130         set_directory (result.string ());
131         
132         if (!boost::filesystem::exists (directory())) {
133                 if (must_exist) {
134                         throw OpenFileError (directory());
135                 } else {
136                         boost::filesystem::create_directory (directory());
137                 }
138         }
139
140         _external_audio_stream = ExternalAudioStream::create ();
141         
142         if (must_exist) {
143                 read_metadata ();
144         }
145
146         _log = new FileLog (file (N_("log")));
147 }
148
149 Film::Film (Film const & o)
150         : boost::enable_shared_from_this<Film> (o)
151         , _log (0)
152         , _directory         (o._directory)
153         , _name              (o._name)
154         , _use_dci_name      (o._use_dci_name)
155         , _content           (o._content)
156         , _trust_content_header (o._trust_content_header)
157         , _dcp_content_type  (o._dcp_content_type)
158         , _format            (o._format)
159         , _crop              (o._crop)
160         , _filters           (o._filters)
161         , _scaler            (o._scaler)
162         , _trim_start        (o._trim_start)
163         , _trim_end          (o._trim_end)
164         , _dcp_ab            (o._dcp_ab)
165         , _content_audio_stream (o._content_audio_stream)
166         , _external_audio    (o._external_audio)
167         , _use_content_audio (o._use_content_audio)
168         , _audio_gain        (o._audio_gain)
169         , _audio_delay       (o._audio_delay)
170         , _still_duration    (o._still_duration)
171         , _subtitle_stream   (o._subtitle_stream)
172         , _with_subtitles    (o._with_subtitles)
173         , _subtitle_offset   (o._subtitle_offset)
174         , _subtitle_scale    (o._subtitle_scale)
175         , _colour_lut        (o._colour_lut)
176         , _j2k_bandwidth     (o._j2k_bandwidth)
177         , _dci_metadata      (o._dci_metadata)
178         , _dci_date          (o._dci_date)
179         , _dcp_frame_rate    (o._dcp_frame_rate)
180         , _size              (o._size)
181         , _length            (o._length)
182         , _dcp_intrinsic_duration (o._dcp_intrinsic_duration)
183         , _content_digest    (o._content_digest)
184         , _content_audio_streams (o._content_audio_streams)
185         , _external_audio_stream (o._external_audio_stream)
186         , _subtitle_streams  (o._subtitle_streams)
187         , _source_frame_rate (o._source_frame_rate)
188         , _dirty             (o._dirty)
189 {
190
191 }
192
193 Film::~Film ()
194 {
195         delete _log;
196 }
197
198 string
199 Film::video_state_identifier () const
200 {
201         assert (format ());
202
203         pair<string, string> f = Filter::ffmpeg_strings (filters());
204
205         stringstream s;
206         s << format()->id()
207           << N_("_") << content_digest()
208           << N_("_") << crop().left << N_("_") << crop().right << N_("_") << crop().top << N_("_") << crop().bottom
209           << N_("_") << _dcp_frame_rate
210           << N_("_") << f.first << N_("_") << f.second
211           << N_("_") << scaler()->id()
212           << N_("_") << j2k_bandwidth()
213           << N_("_") << boost::lexical_cast<int> (colour_lut());
214
215         if (dcp_ab()) {
216                 pair<string, string> fa = Filter::ffmpeg_strings (Config::instance()->reference_filters());
217                 s << N_("ab_") << Config::instance()->reference_scaler()->id() << N_("_") << fa.first << N_("_") << fa.second;
218         }
219
220         return s.str ();
221 }
222           
223 /** @return The path to the directory to write video frame info files to */
224 string
225 Film::info_dir () const
226 {
227         boost::filesystem::path p;
228         p /= N_("info");
229         p /= video_state_identifier ();
230         return dir (p.string());
231 }
232
233 string
234 Film::video_mxf_dir () const
235 {
236         boost::filesystem::path p;
237         return dir (N_("video"));
238 }
239
240 string
241 Film::video_mxf_filename () const
242 {
243         return video_state_identifier() + N_(".mxf");
244 }
245
246 string
247 Film::audio_analysis_path () const
248 {
249         boost::filesystem::path p;
250         p /= "analysis";
251         p /= content_digest();
252         return file (p.string ());
253 }
254
255 /** Add suitable Jobs to the JobManager to create a DCP for this Film */
256 void
257 Film::make_dcp ()
258 {
259         set_dci_date_today ();
260         
261         if (dcp_name().find (N_("/")) != string::npos) {
262                 throw BadSettingError (_("name"), _("cannot contain slashes"));
263         }
264         
265         log()->log (String::compose (N_("DVD-o-matic %1 git %2 using %3"), dvdomatic_version, dvdomatic_git_commit, dependency_version_summary()));
266
267         {
268                 char buffer[128];
269                 gethostname (buffer, sizeof (buffer));
270                 log()->log (String::compose (N_("Starting to make DCP on %1"), buffer));
271         }
272         
273         log()->log (String::compose (N_("Content is %1; type %2"), content_path(), (content_type() == STILL ? _("still") : _("video"))));
274         if (length()) {
275                 log()->log (String::compose (N_("Content length %1"), length().get()));
276         }
277         log()->log (String::compose (N_("Content digest %1"), content_digest()));
278         log()->log (String::compose (N_("%1 threads"), Config::instance()->num_local_encoding_threads()));
279         log()->log (String::compose (N_("J2K bandwidth %1"), j2k_bandwidth()));
280 #ifdef DVDOMATIC_DEBUG
281         log()->log (N_("DVD-o-matic built in debug mode."));
282 #else
283         log()->log (N_("DVD-o-matic built in optimised mode."));
284 #endif
285 #ifdef LIBDCP_DEBUG
286         log()->log (N_("libdcp built in debug mode."));
287 #else
288         log()->log (N_("libdcp built in optimised mode."));
289 #endif
290         pair<string, int> const c = cpu_info ();
291         log()->log (String::compose (N_("CPU: %1, %2 processors"), c.first, c.second));
292         
293         if (format() == 0) {
294                 throw MissingSettingError (_("format"));
295         }
296
297         if (content().empty ()) {
298                 throw MissingSettingError (_("content"));
299         }
300
301         if (dcp_content_type() == 0) {
302                 throw MissingSettingError (_("content type"));
303         }
304
305         if (name().empty()) {
306                 throw MissingSettingError (_("name"));
307         }
308
309         DecodeOptions od;
310         od.decode_subtitles = with_subtitles ();
311
312         shared_ptr<Job> r;
313
314         if (dcp_ab()) {
315                 r = JobManager::instance()->add (shared_ptr<Job> (new ABTranscodeJob (shared_from_this(), od)));
316         } else {
317                 r = JobManager::instance()->add (shared_ptr<Job> (new TranscodeJob (shared_from_this(), od)));
318         }
319 }
320
321 /** Start a job to analyse the audio of our content file */
322 void
323 Film::analyse_audio ()
324 {
325         if (_analyse_audio_job) {
326                 return;
327         }
328
329         _analyse_audio_job.reset (new AnalyseAudioJob (shared_from_this()));
330         _analyse_audio_job->Finished.connect (bind (&Film::analyse_audio_finished, this));
331         JobManager::instance()->add (_analyse_audio_job);
332 }
333
334 /** Start a job to examine our content file */
335 void
336 Film::examine_content ()
337 {
338         if (_examine_content_job) {
339                 return;
340         }
341
342         _examine_content_job.reset (new ExamineContentJob (shared_from_this()));
343         _examine_content_job->Finished.connect (bind (&Film::examine_content_finished, this));
344         JobManager::instance()->add (_examine_content_job);
345 }
346
347 void
348 Film::analyse_audio_finished ()
349 {
350         ensure_ui_thread ();
351         _analyse_audio_job.reset ();
352
353         AudioAnalysisFinished ();
354 }
355
356 void
357 Film::examine_content_finished ()
358 {
359         _examine_content_job.reset ();
360 }
361
362 /** Start a job to send our DCP to the configured TMS */
363 void
364 Film::send_dcp_to_tms ()
365 {
366         shared_ptr<Job> j (new SCPDCPJob (shared_from_this()));
367         JobManager::instance()->add (j);
368 }
369
370 /** Count the number of frames that have been encoded for this film.
371  *  @return frame count.
372  */
373 int
374 Film::encoded_frames () const
375 {
376         if (format() == 0) {
377                 return 0;
378         }
379
380         int N = 0;
381         for (boost::filesystem::directory_iterator i = boost::filesystem::directory_iterator (info_dir ()); i != boost::filesystem::directory_iterator(); ++i) {
382                 ++N;
383                 boost::this_thread::interruption_point ();
384         }
385
386         return N;
387 }
388
389 /** Write state to our `metadata' file */
390 void
391 Film::write_metadata () const
392 {
393         boost::mutex::scoped_lock lm (_state_mutex);
394
395         boost::filesystem::create_directories (directory());
396
397         string const m = file (N_("metadata"));
398         ofstream f (m.c_str ());
399         if (!f.good ()) {
400                 throw CreateFileError (m);
401         }
402
403         f << N_("version ") << state_version << N_("\n");
404
405         /* User stuff */
406         f << N_("name ") << _name << N_("\n");
407         f << N_("use_dci_name ") << _use_dci_name << N_("\n");
408         f << N_("content ") << _content << N_("\n");
409         f << N_("trust_content_header ") << (_trust_content_header ? N_("1") : N_("0")) << N_("\n");
410         if (_dcp_content_type) {
411                 f << N_("dcp_content_type ") << _dcp_content_type->dci_name () << N_("\n");
412         }
413         if (_format) {
414                 f << N_("format ") << _format->as_metadata () << N_("\n");
415         }
416         f << N_("left_crop ") << _crop.left << N_("\n");
417         f << N_("right_crop ") << _crop.right << N_("\n");
418         f << N_("top_crop ") << _crop.top << N_("\n");
419         f << N_("bottom_crop ") << _crop.bottom << N_("\n");
420         for (vector<Filter const *>::const_iterator i = _filters.begin(); i != _filters.end(); ++i) {
421                 f << N_("filter ") << (*i)->id () << N_("\n");
422         }
423         f << N_("scaler ") << _scaler->id () << N_("\n");
424         f << N_("trim_start ") << _trim_start << N_("\n");
425         f << N_("trim_end ") << _trim_end << N_("\n");
426         f << N_("dcp_ab ") << (_dcp_ab ? N_("1") : N_("0")) << N_("\n");
427         if (_content_audio_stream) {
428                 f << N_("selected_content_audio_stream ") << _content_audio_stream->to_string() << N_("\n");
429         }
430         for (vector<string>::const_iterator i = _external_audio.begin(); i != _external_audio.end(); ++i) {
431                 f << N_("external_audio ") << *i << N_("\n");
432         }
433         f << N_("use_content_audio ") << (_use_content_audio ? N_("1") : N_("0")) << N_("\n");
434         f << N_("audio_gain ") << _audio_gain << N_("\n");
435         f << N_("audio_delay ") << _audio_delay << N_("\n");
436         f << N_("still_duration ") << _still_duration << N_("\n");
437         if (_subtitle_stream) {
438                 f << N_("selected_subtitle_stream ") << _subtitle_stream->to_string() << N_("\n");
439         }
440         f << N_("with_subtitles ") << _with_subtitles << N_("\n");
441         f << N_("subtitle_offset ") << _subtitle_offset << N_("\n");
442         f << N_("subtitle_scale ") << _subtitle_scale << N_("\n");
443         f << N_("colour_lut ") << _colour_lut << N_("\n");
444         f << N_("j2k_bandwidth ") << _j2k_bandwidth << N_("\n");
445         _dci_metadata.write (f);
446         f << N_("dci_date ") << boost::gregorian::to_iso_string (_dci_date) << N_("\n");
447         f << N_("dcp_frame_rate ") << _dcp_frame_rate << "\n";
448         f << N_("width ") << _size.width << N_("\n");
449         f << N_("height ") << _size.height << N_("\n");
450         f << N_("length ") << _length.get_value_or(0) << N_("\n");
451         f << N_("dcp_intrinsic_duration ") << _dcp_intrinsic_duration.get_value_or(0) << N_("\n");
452         f << N_("content_digest ") << _content_digest << N_("\n");
453
454         for (vector<shared_ptr<AudioStream> >::const_iterator i = _content_audio_streams.begin(); i != _content_audio_streams.end(); ++i) {
455                 f << N_("content_audio_stream ") << (*i)->to_string () << N_("\n");
456         }
457
458         f << N_("external_audio_stream ") << _external_audio_stream->to_string() << N_("\n");
459
460         for (vector<shared_ptr<SubtitleStream> >::const_iterator i = _subtitle_streams.begin(); i != _subtitle_streams.end(); ++i) {
461                 f << N_("subtitle_stream ") << (*i)->to_string () << N_("\n");
462         }
463
464         f << N_("source_frame_rate ") << _source_frame_rate << N_("\n");
465         
466         _dirty = false;
467 }
468
469 /** Read state from our metadata file */
470 void
471 Film::read_metadata ()
472 {
473         boost::mutex::scoped_lock lm (_state_mutex);
474
475         _external_audio.clear ();
476         _content_audio_streams.clear ();
477         _subtitle_streams.clear ();
478
479         boost::optional<int> version;
480
481         /* Backward compatibility things */
482         boost::optional<int> audio_sample_rate;
483         boost::optional<int> audio_stream_index;
484         boost::optional<int> subtitle_stream_index;
485
486         ifstream f (file (N_("metadata")).c_str());
487         if (!f.good()) {
488                 throw OpenFileError (file (N_("metadata")));
489         }
490         
491         multimap<string, string> kv = read_key_value (f);
492
493         /* We need version before anything else */
494         multimap<string, string>::iterator v = kv.find (N_("version"));
495         if (v != kv.end ()) {
496                 version = atoi (v->second.c_str());
497         }
498         
499         for (multimap<string, string>::const_iterator i = kv.begin(); i != kv.end(); ++i) {
500                 string const k = i->first;
501                 string const v = i->second;
502
503                 if (k == N_("audio_sample_rate")) {
504                         audio_sample_rate = atoi (v.c_str());
505                 }
506
507                 /* User-specified stuff */
508                 if (k == N_("name")) {
509                         _name = v;
510                 } else if (k == N_("use_dci_name")) {
511                         _use_dci_name = (v == N_("1"));
512                 } else if (k == N_("content")) {
513                         _content = v;
514                 } else if (k == N_("trust_content_header")) {
515                         _trust_content_header = (v == N_("1"));
516                 } else if (k == N_("dcp_content_type")) {
517                         if (version < 3) {
518                                 _dcp_content_type = DCPContentType::from_pretty_name (v);
519                         } else {
520                                 _dcp_content_type = DCPContentType::from_dci_name (v);
521                         }
522                 } else if (k == N_("format")) {
523                         _format = Format::from_metadata (v);
524                 } else if (k == N_("left_crop")) {
525                         _crop.left = atoi (v.c_str ());
526                 } else if (k == N_("right_crop")) {
527                         _crop.right = atoi (v.c_str ());
528                 } else if (k == N_("top_crop")) {
529                         _crop.top = atoi (v.c_str ());
530                 } else if (k == N_("bottom_crop")) {
531                         _crop.bottom = atoi (v.c_str ());
532                 } else if (k == N_("filter")) {
533                         _filters.push_back (Filter::from_id (v));
534                 } else if (k == N_("scaler")) {
535                         _scaler = Scaler::from_id (v);
536                 } else if ( ((!version || version < 2) && k == N_("dcp_trim_start")) || k == N_("trim_start")) {
537                         _trim_start = atoi (v.c_str ());
538                 } else if ( ((!version || version < 2) && k == N_("dcp_trim_end")) || k == N_("trim_end")) {
539                         _trim_end = atoi (v.c_str ());
540                 } else if (k == N_("dcp_ab")) {
541                         _dcp_ab = (v == N_("1"));
542                 } else if (k == N_("selected_content_audio_stream") || (!version && k == N_("selected_audio_stream"))) {
543                         if (!version) {
544                                 audio_stream_index = atoi (v.c_str ());
545                         } else {
546                                 _content_audio_stream = audio_stream_factory (v, version);
547                         }
548                 } else if (k == N_("external_audio")) {
549                         _external_audio.push_back (v);
550                 } else if (k == N_("use_content_audio")) {
551                         _use_content_audio = (v == N_("1"));
552                 } else if (k == N_("audio_gain")) {
553                         _audio_gain = atof (v.c_str ());
554                 } else if (k == N_("audio_delay")) {
555                         _audio_delay = atoi (v.c_str ());
556                 } else if (k == N_("still_duration")) {
557                         _still_duration = atoi (v.c_str ());
558                 } else if (k == N_("selected_subtitle_stream")) {
559                         if (!version) {
560                                 subtitle_stream_index = atoi (v.c_str ());
561                         } else {
562                                 _subtitle_stream = subtitle_stream_factory (v, version);
563                         }
564                 } else if (k == N_("with_subtitles")) {
565                         _with_subtitles = (v == N_("1"));
566                 } else if (k == N_("subtitle_offset")) {
567                         _subtitle_offset = atoi (v.c_str ());
568                 } else if (k == N_("subtitle_scale")) {
569                         _subtitle_scale = atof (v.c_str ());
570                 } else if (k == N_("colour_lut")) {
571                         _colour_lut = atoi (v.c_str ());
572                 } else if (k == N_("j2k_bandwidth")) {
573                         _j2k_bandwidth = atoi (v.c_str ());
574                 } else if (k == N_("dci_date")) {
575                         _dci_date = boost::gregorian::from_undelimited_string (v);
576                 } else if (k == "dcp_frame_rate") {
577                         _dcp_frame_rate = atoi (v.c_str ());
578                 }
579
580                 _dci_metadata.read (k, v);
581                 
582                 /* Cached stuff */
583                 if (k == N_("width")) {
584                         _size.width = atoi (v.c_str ());
585                 } else if (k == N_("height")) {
586                         _size.height = atoi (v.c_str ());
587                 } else if (k == N_("length")) {
588                         int const vv = atoi (v.c_str ());
589                         if (vv) {
590                                 _length = vv;
591                         }
592                 } else if (k == N_("dcp_intrinsic_duration")) {
593                         int const vv = atoi (v.c_str ());
594                         if (vv) {
595                                 _dcp_intrinsic_duration = vv;
596                         }
597                 } else if (k == N_("content_digest")) {
598                         _content_digest = v;
599                 } else if (k == N_("content_audio_stream") || (!version && k == N_("audio_stream"))) {
600                         _content_audio_streams.push_back (audio_stream_factory (v, version));
601                 } else if (k == N_("external_audio_stream")) {
602                         _external_audio_stream = audio_stream_factory (v, version);
603                 } else if (k == N_("subtitle_stream")) {
604                         _subtitle_streams.push_back (subtitle_stream_factory (v, version));
605                 } else if (k == N_("source_frame_rate") || (version < 4 && k == "frames_per_second")) {
606                         _source_frame_rate = atof (v.c_str ());
607                 }
608         }
609
610         if (!version) {
611                 if (audio_sample_rate) {
612                         /* version < 1 didn't specify sample rate in the audio streams, so fill it in here */
613                         for (vector<shared_ptr<AudioStream> >::iterator i = _content_audio_streams.begin(); i != _content_audio_streams.end(); ++i) {
614                                 (*i)->set_sample_rate (audio_sample_rate.get());
615                         }
616                 }
617
618                 /* also the selected stream was specified as an index */
619                 if (audio_stream_index && audio_stream_index.get() >= 0 && audio_stream_index.get() < (int) _content_audio_streams.size()) {
620                         _content_audio_stream = _content_audio_streams[audio_stream_index.get()];
621                 }
622
623                 /* similarly the subtitle */
624                 if (subtitle_stream_index && subtitle_stream_index.get() >= 0 && subtitle_stream_index.get() < (int) _subtitle_streams.size()) {
625                         _subtitle_stream = _subtitle_streams[subtitle_stream_index.get()];
626                 }
627         }
628                 
629         _dirty = false;
630 }
631
632 libdcp::Size
633 Film::cropped_size (libdcp::Size s) const
634 {
635         boost::mutex::scoped_lock lm (_state_mutex);
636         s.width -= _crop.left + _crop.right;
637         s.height -= _crop.top + _crop.bottom;
638         return s;
639 }
640
641 /** Given a directory name, return its full path within the Film's directory.
642  *  The directory (and its parents) will be created if they do not exist.
643  */
644 string
645 Film::dir (string d) const
646 {
647         boost::mutex::scoped_lock lm (_directory_mutex);
648         
649         boost::filesystem::path p;
650         p /= _directory;
651         p /= d;
652         
653         boost::filesystem::create_directories (p);
654         
655         return p.string ();
656 }
657
658 /** Given a file or directory name, return its full path within the Film's directory.
659  *  _directory_mutex must not be locked on entry.
660  *  Any required parent directories will be created.
661  */
662 string
663 Film::file (string f) const
664 {
665         boost::mutex::scoped_lock lm (_directory_mutex);
666
667         boost::filesystem::path p;
668         p /= _directory;
669         p /= f;
670
671         boost::filesystem::create_directories (p.parent_path ());
672         
673         return p.string ();
674 }
675
676 /** @return full path of the content (actual video) file
677  *  of the Film.
678  */
679 string
680 Film::content_path () const
681 {
682         boost::mutex::scoped_lock lm (_state_mutex);
683         if (boost::filesystem::path(_content).has_root_directory ()) {
684                 return _content;
685         }
686
687         return file (_content);
688 }
689
690 ContentType
691 Film::content_type () const
692 {
693         if (boost::filesystem::is_directory (_content)) {
694                 /* Directory of images, we assume */
695                 return VIDEO;
696         }
697
698         if (still_image_file (_content)) {
699                 return STILL;
700         }
701
702         return VIDEO;
703 }
704
705 /** @return The sampling rate that we will resample the audio to */
706 int
707 Film::target_audio_sample_rate () const
708 {
709         if (!audio_stream()) {
710                 return 0;
711         }
712         
713         /* Resample to a DCI-approved sample rate */
714         double t = dcp_audio_sample_rate (audio_stream()->sample_rate());
715
716         FrameRateConversion frc (source_frame_rate(), dcp_frame_rate());
717
718         /* Compensate if the DCP is being run at a different frame rate
719            to the source; that is, if the video is run such that it will
720            look different in the DCP compared to the source (slower or faster).
721            skip/repeat doesn't come into effect here.
722         */
723
724         if (frc.change_speed) {
725                 t *= source_frame_rate() * frc.factor() / dcp_frame_rate();
726         }
727
728         return rint (t);
729 }
730
731 int
732 Film::still_duration_in_frames () const
733 {
734         return still_duration() * source_frame_rate();
735 }
736
737 /** @return a DCI-compliant name for a DCP of this film */
738 string
739 Film::dci_name (bool if_created_now) const
740 {
741         stringstream d;
742
743         string fixed_name = to_upper_copy (name());
744         for (size_t i = 0; i < fixed_name.length(); ++i) {
745                 if (fixed_name[i] == ' ') {
746                         fixed_name[i] = '-';
747                 }
748         }
749
750         /* Spec is that the name part should be maximum 14 characters, as I understand it */
751         if (fixed_name.length() > 14) {
752                 fixed_name = fixed_name.substr (0, 14);
753         }
754
755         d << fixed_name << N_("_");
756
757         if (dcp_content_type()) {
758                 d << dcp_content_type()->dci_name() << N_("_");
759         }
760
761         if (format()) {
762                 d << format()->dci_name() << N_("_");
763         }
764
765         DCIMetadata const dm = dci_metadata ();
766
767         if (!dm.audio_language.empty ()) {
768                 d << dm.audio_language;
769                 if (!dm.subtitle_language.empty() && with_subtitles()) {
770                         d << N_("-") << dm.subtitle_language;
771                 } else {
772                         d << N_("-XX");
773                 }
774                         
775                 d << N_("_");
776         }
777
778         if (!dm.territory.empty ()) {
779                 d << dm.territory;
780                 if (!dm.rating.empty ()) {
781                         d << N_("-") << dm.rating;
782                 }
783                 d << N_("_");
784         }
785
786         switch (audio_channels()) {
787         case 1:
788                 d << N_("10_");
789                 break;
790         case 2:
791                 d << N_("20_");
792                 break;
793         case 6:
794                 d << N_("51_");
795                 break;
796         case 8:
797                 d << N_("71_");
798                 break;
799         }
800
801         d << N_("2K_");
802
803         if (!dm.studio.empty ()) {
804                 d << dm.studio << N_("_");
805         }
806
807         if (if_created_now) {
808                 d << boost::gregorian::to_iso_string (boost::gregorian::day_clock::local_day ()) << N_("_");
809         } else {
810                 d << boost::gregorian::to_iso_string (_dci_date) << N_("_");
811         }
812
813         if (!dm.facility.empty ()) {
814                 d << dm.facility << N_("_");
815         }
816
817         if (!dm.package_type.empty ()) {
818                 d << dm.package_type;
819         }
820
821         return d.str ();
822 }
823
824 /** @return name to give the DCP */
825 string
826 Film::dcp_name (bool if_created_now) const
827 {
828         if (use_dci_name()) {
829                 return dci_name (if_created_now);
830         }
831
832         return name();
833 }
834
835
836 void
837 Film::set_directory (string d)
838 {
839         boost::mutex::scoped_lock lm (_state_mutex);
840         _directory = d;
841         _dirty = true;
842 }
843
844 void
845 Film::set_name (string n)
846 {
847         {
848                 boost::mutex::scoped_lock lm (_state_mutex);
849                 _name = n;
850         }
851         signal_changed (NAME);
852 }
853
854 void
855 Film::set_use_dci_name (bool u)
856 {
857         {
858                 boost::mutex::scoped_lock lm (_state_mutex);
859                 _use_dci_name = u;
860         }
861         signal_changed (USE_DCI_NAME);
862 }
863
864 void
865 Film::set_content (string c)
866 {
867         string check = directory ();
868
869         boost::filesystem::path slash (N_("/"));
870         string platform_slash = slash.make_preferred().string ();
871
872         if (!ends_with (check, platform_slash)) {
873                 check += platform_slash;
874         }
875         
876         if (boost::filesystem::path(c).has_root_directory () && starts_with (c, check)) {
877                 c = c.substr (_directory.length() + 1);
878         }
879
880         string old_content;
881         
882         {
883                 boost::mutex::scoped_lock lm (_state_mutex);
884                 if (c == _content) {
885                         return;
886                 }
887
888                 old_content = _content;
889                 _content = c;
890         }
891
892         /* Reset streams here in case the new content doesn't have one or the other */
893         _content_audio_stream = shared_ptr<AudioStream> ();
894         _subtitle_stream = shared_ptr<SubtitleStream> ();
895
896         /* Start off using content audio */
897         set_use_content_audio (true);
898
899         /* Create a temporary decoder so that we can get information
900            about the content.
901         */
902
903         try {
904                 Decoders d = decoder_factory (shared_from_this(), DecodeOptions());
905                 
906                 set_size (d.video->native_size ());
907                 set_source_frame_rate (d.video->frames_per_second ());
908                 set_subtitle_streams (d.video->subtitle_streams ());
909                 if (d.audio) {
910                         set_content_audio_streams (d.audio->audio_streams ());
911                 }
912
913                 {
914                         boost::mutex::scoped_lock lm (_state_mutex);
915                         _content = c;
916                 }
917                 
918                 signal_changed (CONTENT);
919                 
920                 /* Start off with the first audio and subtitle streams */
921                 if (d.audio && !d.audio->audio_streams().empty()) {
922                         set_content_audio_stream (d.audio->audio_streams().front());
923                 }
924                 
925                 if (!d.video->subtitle_streams().empty()) {
926                         set_subtitle_stream (d.video->subtitle_streams().front());
927                 }
928                 
929                 examine_content ();
930
931         } catch (...) {
932
933                 boost::mutex::scoped_lock lm (_state_mutex);
934                 _content = old_content;
935                 throw;
936
937         }
938
939         /* Default format */
940         switch (content_type()) {
941         case STILL:
942                 set_format (Format::from_id (N_("var-185")));
943                 break;
944         case VIDEO:
945                 set_format (Format::from_id (N_("185")));
946                 break;
947         }
948
949         /* Still image DCPs must use external audio */
950         if (content_type() == STILL) {
951                 set_use_content_audio (false);
952         }
953 }
954
955 void
956 Film::set_trust_content_header (bool t)
957 {
958         {
959                 boost::mutex::scoped_lock lm (_state_mutex);
960                 _trust_content_header = t;
961         }
962         
963         signal_changed (TRUST_CONTENT_HEADER);
964
965         if (!_trust_content_header && !content().empty()) {
966                 /* We just said that we don't trust the content's header */
967                 examine_content ();
968         }
969 }
970                
971 void
972 Film::set_dcp_content_type (DCPContentType const * t)
973 {
974         {
975                 boost::mutex::scoped_lock lm (_state_mutex);
976                 _dcp_content_type = t;
977         }
978         signal_changed (DCP_CONTENT_TYPE);
979 }
980
981 void
982 Film::set_format (Format const * f)
983 {
984         {
985                 boost::mutex::scoped_lock lm (_state_mutex);
986                 _format = f;
987         }
988         signal_changed (FORMAT);
989 }
990
991 void
992 Film::set_crop (Crop c)
993 {
994         {
995                 boost::mutex::scoped_lock lm (_state_mutex);
996                 _crop = c;
997         }
998         signal_changed (CROP);
999 }
1000
1001 void
1002 Film::set_left_crop (int c)
1003 {
1004         {
1005                 boost::mutex::scoped_lock lm (_state_mutex);
1006                 
1007                 if (_crop.left == c) {
1008                         return;
1009                 }
1010                 
1011                 _crop.left = c;
1012         }
1013         signal_changed (CROP);
1014 }
1015
1016 void
1017 Film::set_right_crop (int c)
1018 {
1019         {
1020                 boost::mutex::scoped_lock lm (_state_mutex);
1021                 if (_crop.right == c) {
1022                         return;
1023                 }
1024                 
1025                 _crop.right = c;
1026         }
1027         signal_changed (CROP);
1028 }
1029
1030 void
1031 Film::set_top_crop (int c)
1032 {
1033         {
1034                 boost::mutex::scoped_lock lm (_state_mutex);
1035                 if (_crop.top == c) {
1036                         return;
1037                 }
1038                 
1039                 _crop.top = c;
1040         }
1041         signal_changed (CROP);
1042 }
1043
1044 void
1045 Film::set_bottom_crop (int c)
1046 {
1047         {
1048                 boost::mutex::scoped_lock lm (_state_mutex);
1049                 if (_crop.bottom == c) {
1050                         return;
1051                 }
1052                 
1053                 _crop.bottom = c;
1054         }
1055         signal_changed (CROP);
1056 }
1057
1058 void
1059 Film::set_filters (vector<Filter const *> f)
1060 {
1061         {
1062                 boost::mutex::scoped_lock lm (_state_mutex);
1063                 _filters = f;
1064         }
1065         signal_changed (FILTERS);
1066 }
1067
1068 void
1069 Film::set_scaler (Scaler const * s)
1070 {
1071         {
1072                 boost::mutex::scoped_lock lm (_state_mutex);
1073                 _scaler = s;
1074         }
1075         signal_changed (SCALER);
1076 }
1077
1078 void
1079 Film::set_trim_start (int t)
1080 {
1081         {
1082                 boost::mutex::scoped_lock lm (_state_mutex);
1083                 _trim_start = t;
1084         }
1085         signal_changed (TRIM_START);
1086 }
1087
1088 void
1089 Film::set_trim_end (int t)
1090 {
1091         {
1092                 boost::mutex::scoped_lock lm (_state_mutex);
1093                 _trim_end = t;
1094         }
1095         signal_changed (TRIM_END);
1096 }
1097
1098 void
1099 Film::set_dcp_ab (bool a)
1100 {
1101         {
1102                 boost::mutex::scoped_lock lm (_state_mutex);
1103                 _dcp_ab = a;
1104         }
1105         signal_changed (DCP_AB);
1106 }
1107
1108 void
1109 Film::set_content_audio_stream (shared_ptr<AudioStream> s)
1110 {
1111         {
1112                 boost::mutex::scoped_lock lm (_state_mutex);
1113                 _content_audio_stream = s;
1114         }
1115         signal_changed (CONTENT_AUDIO_STREAM);
1116 }
1117
1118 void
1119 Film::set_external_audio (vector<string> a)
1120 {
1121         {
1122                 boost::mutex::scoped_lock lm (_state_mutex);
1123                 _external_audio = a;
1124         }
1125
1126         shared_ptr<ExternalAudioDecoder> decoder (new ExternalAudioDecoder (shared_from_this(), DecodeOptions()));
1127         if (decoder->audio_stream()) {
1128                 _external_audio_stream = decoder->audio_stream ();
1129         }
1130         
1131         signal_changed (EXTERNAL_AUDIO);
1132 }
1133
1134 void
1135 Film::set_use_content_audio (bool e)
1136 {
1137         {
1138                 boost::mutex::scoped_lock lm (_state_mutex);
1139                 _use_content_audio = e;
1140         }
1141
1142         signal_changed (USE_CONTENT_AUDIO);
1143 }
1144
1145 void
1146 Film::set_audio_gain (float g)
1147 {
1148         {
1149                 boost::mutex::scoped_lock lm (_state_mutex);
1150                 _audio_gain = g;
1151         }
1152         signal_changed (AUDIO_GAIN);
1153 }
1154
1155 void
1156 Film::set_audio_delay (int d)
1157 {
1158         {
1159                 boost::mutex::scoped_lock lm (_state_mutex);
1160                 _audio_delay = d;
1161         }
1162         signal_changed (AUDIO_DELAY);
1163 }
1164
1165 void
1166 Film::set_still_duration (int d)
1167 {
1168         {
1169                 boost::mutex::scoped_lock lm (_state_mutex);
1170                 _still_duration = d;
1171         }
1172         signal_changed (STILL_DURATION);
1173 }
1174
1175 void
1176 Film::set_subtitle_stream (shared_ptr<SubtitleStream> s)
1177 {
1178         {
1179                 boost::mutex::scoped_lock lm (_state_mutex);
1180                 _subtitle_stream = s;
1181         }
1182         signal_changed (SUBTITLE_STREAM);
1183 }
1184
1185 void
1186 Film::set_with_subtitles (bool w)
1187 {
1188         {
1189                 boost::mutex::scoped_lock lm (_state_mutex);
1190                 _with_subtitles = w;
1191         }
1192         signal_changed (WITH_SUBTITLES);
1193 }
1194
1195 void
1196 Film::set_subtitle_offset (int o)
1197 {
1198         {
1199                 boost::mutex::scoped_lock lm (_state_mutex);
1200                 _subtitle_offset = o;
1201         }
1202         signal_changed (SUBTITLE_OFFSET);
1203 }
1204
1205 void
1206 Film::set_subtitle_scale (float s)
1207 {
1208         {
1209                 boost::mutex::scoped_lock lm (_state_mutex);
1210                 _subtitle_scale = s;
1211         }
1212         signal_changed (SUBTITLE_SCALE);
1213 }
1214
1215 void
1216 Film::set_colour_lut (int i)
1217 {
1218         {
1219                 boost::mutex::scoped_lock lm (_state_mutex);
1220                 _colour_lut = i;
1221         }
1222         signal_changed (COLOUR_LUT);
1223 }
1224
1225 void
1226 Film::set_j2k_bandwidth (int b)
1227 {
1228         {
1229                 boost::mutex::scoped_lock lm (_state_mutex);
1230                 _j2k_bandwidth = b;
1231         }
1232         signal_changed (J2K_BANDWIDTH);
1233 }
1234
1235 void
1236 Film::set_dci_metadata (DCIMetadata m)
1237 {
1238         {
1239                 boost::mutex::scoped_lock lm (_state_mutex);
1240                 _dci_metadata = m;
1241         }
1242         signal_changed (DCI_METADATA);
1243 }
1244
1245
1246 void
1247 Film::set_dcp_frame_rate (int f)
1248 {
1249         {
1250                 boost::mutex::scoped_lock lm (_state_mutex);
1251                 _dcp_frame_rate = f;
1252         }
1253         signal_changed (DCP_FRAME_RATE);
1254 }
1255
1256 void
1257 Film::set_size (libdcp::Size s)
1258 {
1259         {
1260                 boost::mutex::scoped_lock lm (_state_mutex);
1261                 _size = s;
1262         }
1263         signal_changed (SIZE);
1264 }
1265
1266 void
1267 Film::set_length (SourceFrame l)
1268 {
1269         {
1270                 boost::mutex::scoped_lock lm (_state_mutex);
1271                 _length = l;
1272         }
1273         signal_changed (LENGTH);
1274 }
1275
1276 void
1277 Film::unset_length ()
1278 {
1279         {
1280                 boost::mutex::scoped_lock lm (_state_mutex);
1281                 _length = boost::none;
1282         }
1283         signal_changed (LENGTH);
1284 }
1285
1286 void
1287 Film::set_dcp_intrinsic_duration (int d)
1288 {
1289         {
1290                 boost::mutex::scoped_lock lm (_state_mutex);
1291                 _dcp_intrinsic_duration = d;
1292         }
1293         signal_changed (DCP_INTRINSIC_DURATION);
1294 }
1295
1296 void
1297 Film::set_content_digest (string d)
1298 {
1299         {
1300                 boost::mutex::scoped_lock lm (_state_mutex);
1301                 _content_digest = d;
1302         }
1303         _dirty = true;
1304 }
1305
1306 void
1307 Film::set_content_audio_streams (vector<shared_ptr<AudioStream> > s)
1308 {
1309         {
1310                 boost::mutex::scoped_lock lm (_state_mutex);
1311                 _content_audio_streams = s;
1312         }
1313         signal_changed (CONTENT_AUDIO_STREAMS);
1314 }
1315
1316 void
1317 Film::set_subtitle_streams (vector<shared_ptr<SubtitleStream> > s)
1318 {
1319         {
1320                 boost::mutex::scoped_lock lm (_state_mutex);
1321                 _subtitle_streams = s;
1322         }
1323         signal_changed (SUBTITLE_STREAMS);
1324 }
1325
1326 void
1327 Film::set_source_frame_rate (float f)
1328 {
1329         {
1330                 boost::mutex::scoped_lock lm (_state_mutex);
1331                 _source_frame_rate = f;
1332         }
1333         signal_changed (SOURCE_FRAME_RATE);
1334 }
1335         
1336 void
1337 Film::signal_changed (Property p)
1338 {
1339         {
1340                 boost::mutex::scoped_lock lm (_state_mutex);
1341                 _dirty = true;
1342         }
1343
1344         if (ui_signaller) {
1345                 ui_signaller->emit (boost::bind (boost::ref (Changed), p));
1346         }
1347 }
1348
1349 int
1350 Film::audio_channels () const
1351 {
1352         shared_ptr<AudioStream> s = audio_stream ();
1353         if (!s) {
1354                 return 0;
1355         }
1356
1357         return s->channels ();
1358 }
1359
1360 void
1361 Film::set_dci_date_today ()
1362 {
1363         _dci_date = boost::gregorian::day_clock::local_day ();
1364 }
1365
1366 boost::shared_ptr<AudioStream>
1367 Film::audio_stream () const
1368 {
1369         if (use_content_audio()) {
1370                 return _content_audio_stream;
1371         }
1372
1373         return _external_audio_stream;
1374 }
1375
1376 string
1377 Film::info_path (int f) const
1378 {
1379         boost::filesystem::path p;
1380         p /= info_dir ();
1381
1382         stringstream s;
1383         s.width (8);
1384         s << setfill('0') << f << N_(".md5");
1385
1386         p /= s.str();
1387
1388         /* info_dir() will already have added any initial bit of the path,
1389            so don't call file() on this.
1390         */
1391         return p.string ();
1392 }
1393
1394 string
1395 Film::j2c_path (int f, bool t) const
1396 {
1397         boost::filesystem::path p;
1398         p /= N_("j2c");
1399         p /= video_state_identifier ();
1400
1401         stringstream s;
1402         s.width (8);
1403         s << setfill('0') << f << N_(".j2c");
1404
1405         if (t) {
1406                 s << N_(".tmp");
1407         }
1408
1409         p /= s.str();
1410         return file (p.string ());
1411 }
1412
1413 /** Make an educated guess as to whether we have a complete DCP
1414  *  or not.
1415  *  @return true if we do.
1416  */
1417
1418 bool
1419 Film::have_dcp () const
1420 {
1421         try {
1422                 libdcp::DCP dcp (dir (dcp_name()));
1423                 dcp.read ();
1424         } catch (...) {
1425                 return false;
1426         }
1427
1428         return true;
1429 }