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