From: Carl Hetherington Date: Mon, 17 Mar 2014 00:22:52 +0000 (+0000) Subject: Merge master. X-Git-Tag: v2.0.48~891 X-Git-Url: https://main.carlh.net/gitweb/?p=dcpomatic.git;a=commitdiff_plain;h=2e504b33eb9f38cac629ad31b7c107fb0cf5efda;hp=48b2c7b8ec57e72f2f27d5080e54e4b3c3fcda3d Merge master. --- diff --git a/ChangeLog b/ChangeLog index c4c2c9c63..e70b7373e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2014-03-07 Carl Hetherington + + * Add subtitle view. + 2014-03-17 Carl Hetherington * Improve appearance of config dialog on OS X. diff --git a/cscript b/cscript index 988072ecf..b8b058006 100644 --- a/cscript +++ b/cscript @@ -130,7 +130,7 @@ def make_control(debian_version, bits, filename, debug): def dependencies(target): return (('ffmpeg-cdist', '08827fa4e1d483511e6135c424d2ca9c56a9ed50'), - ('libdcp', '57d6bed')) + ('libdcp', '1.0')) def build(target, options): cmd = './waf configure --prefix=%s' % target.work_dir_cscript() diff --git a/doc/design/resampling.tex b/doc/design/resampling.tex index 44aeee9b1..cf9cfb1ed 100644 --- a/doc/design/resampling.tex +++ b/doc/design/resampling.tex @@ -1,4 +1,5 @@ \documentclass{article} +\usepackage{amsmath} \begin{document} Here is what resampling we need to do. Content video is at $C_V$ fps, audio at $C_A$. @@ -18,6 +19,7 @@ $C_V$ is a DCI rate, $C_A$ is not. e.g.\ if $C_V = 24$, $C_A = 44.1\times{}10^3 \textbf{Resample $C_A$ to the DCI rate.} \section{Hard case 1} +\label{sec:hard1} $C_V$ is not a DCI rate, $C_A$ is, e.g.\ if $C_V = 25$, $C_A = 48\times{}10^3$. We will run the video at a nearby DCI rate $F_V$, @@ -31,5 +33,24 @@ resample audio to $25 * 48\times{}10^3 / 24 = 50\times{}10^3$. \medskip \textbf{Resample $C_A$ to $C_V C_A / F_V$} +\section{Hard case 2} + +Neither $C_V$ nor $C_A$ is not a DCI rate, e.g.\ if $C_V = 25$, $C_A = +44.1\times{}10^3$. We will run the video at a nearby DCI rate $F_V$, +meaning that it will run faster or slower than it should. We first +resample the audio to a DCI rate $F_A$, then perform as with +Section~\ref{sec:hard1} above. + +\medskip +\textbf{Resample $C_A$ to $C_V F_A / F_V$} + + +\section{The general case} + +Given a DCP running at $F_V$ and $F_A$ and a piece of content at $C_V$ +and $C_A$, resample the audio to $R_A$ where +\begin{align*} +R_A &= \frac{C_V F_A}{F_V} +\end{align*} \end{document} diff --git a/src/lib/analyse_audio_job.cc b/src/lib/analyse_audio_job.cc index bfe0ed61f..fc0abe0a3 100644 --- a/src/lib/analyse_audio_job.cc +++ b/src/lib/analyse_audio_job.cc @@ -18,6 +18,7 @@ */ #include "audio_analysis.h" +#include "audio_buffers.h" #include "analyse_audio_job.h" #include "compose.hpp" #include "film.h" @@ -69,13 +70,13 @@ AnalyseAudioJob::run () player->Audio.connect (bind (&AnalyseAudioJob::audio, this, _1, _2)); - _samples_per_point = max (int64_t (1), _film->time_to_audio_frames (_film->length()) / _num_points); + int64_t const len = _film->length().frames (_film->audio_frame_rate()); + _samples_per_point = max (int64_t (1), len / _num_points); _current.resize (_film->audio_channels ()); _analysis.reset (new AudioAnalysis (_film->audio_channels ())); _done = 0; - OutputAudioFrame const len = _film->time_to_audio_frames (_film->length ()); while (!player->pass ()) { set_progress (double (_done) / len); } @@ -87,7 +88,7 @@ AnalyseAudioJob::run () } void -AnalyseAudioJob::audio (shared_ptr b, Time) +AnalyseAudioJob::audio (shared_ptr b, DCPTime) { for (int i = 0; i < b->frames(); ++i) { for (int j = 0; j < b->channels(); ++j) { diff --git a/src/lib/analyse_audio_job.h b/src/lib/analyse_audio_job.h index 3e376634c..0a0be8fa0 100644 --- a/src/lib/analyse_audio_job.h +++ b/src/lib/analyse_audio_job.h @@ -20,6 +20,7 @@ #include "job.h" #include "audio_analysis.h" #include "types.h" +#include "dcpomatic_time.h" class AudioBuffers; class AudioContent; @@ -34,10 +35,10 @@ public: void run (); private: - void audio (boost::shared_ptr, Time); + void audio (boost::shared_ptr, DCPTime); boost::weak_ptr _content; - OutputAudioFrame _done; + int64_t _done; int64_t _samples_per_point; std::vector _current; diff --git a/src/lib/audio_content.cc b/src/lib/audio_content.cc index b96300e15..6da5afa0c 100644 --- a/src/lib/audio_content.cc +++ b/src/lib/audio_content.cc @@ -40,7 +40,7 @@ int const AudioContentProperty::AUDIO_GAIN = 203; int const AudioContentProperty::AUDIO_DELAY = 204; int const AudioContentProperty::AUDIO_MAPPING = 205; -AudioContent::AudioContent (shared_ptr f, Time s) +AudioContent::AudioContent (shared_ptr f, DCPTime s) : Content (f, s) , _audio_gain (0) , _audio_delay (Config::instance()->default_audio_delay ()) @@ -149,5 +149,11 @@ AudioContent::audio_analysis_path () const string AudioContent::technical_summary () const { - return String::compose ("audio: channels %1, length %2, raw rate %3, out rate %4", audio_channels(), audio_length(), content_audio_frame_rate(), output_audio_frame_rate()); + return String::compose ( + "audio: channels %1, length %2, raw rate %3, out rate %4", + audio_channels(), + audio_length().seconds(), + content_audio_frame_rate(), + output_audio_frame_rate() + ); } diff --git a/src/lib/audio_content.h b/src/lib/audio_content.h index d30db02d7..cecc8f13d 100644 --- a/src/lib/audio_content.h +++ b/src/lib/audio_content.h @@ -43,7 +43,7 @@ class AudioContent : public virtual Content public: typedef int64_t Frame; - AudioContent (boost::shared_ptr, Time); + AudioContent (boost::shared_ptr, DCPTime); AudioContent (boost::shared_ptr, boost::filesystem::path); AudioContent (boost::shared_ptr, boost::shared_ptr); AudioContent (boost::shared_ptr, std::vector >); @@ -52,7 +52,7 @@ public: std::string technical_summary () const; virtual int audio_channels () const = 0; - virtual AudioContent::Frame audio_length () const = 0; + virtual ContentTime audio_length () const = 0; virtual int content_audio_frame_rate () const = 0; virtual int output_audio_frame_rate () const = 0; virtual AudioMapping audio_mapping () const = 0; diff --git a/src/lib/audio_decoder.cc b/src/lib/audio_decoder.cc index c0ef02f65..32453cc13 100644 --- a/src/lib/audio_decoder.cc +++ b/src/lib/audio_decoder.cc @@ -22,6 +22,7 @@ #include "exceptions.h" #include "log.h" #include "resampler.h" +#include "util.h" #include "i18n.h" @@ -32,27 +33,52 @@ using std::cout; using boost::optional; using boost::shared_ptr; -AudioDecoder::AudioDecoder (shared_ptr film, shared_ptr content) - : Decoder (film) - , _audio_content (content) - , _audio_position (0) +AudioDecoder::AudioDecoder (shared_ptr content) + : _audio_content (content) { + if (content->output_audio_frame_rate() != content->content_audio_frame_rate() && content->audio_channels ()) { + _resampler.reset (new Resampler (content->content_audio_frame_rate(), content->output_audio_frame_rate(), content->audio_channels ())); + } +} + +/** Audio timestamping is made hard by many factors, but the final nail in the coffin is resampling. + * We have to assume that we are feeding continuous data into the resampler, and so we get continuous + * data out. Hence we do the timestamping here, post-resampler, just by counting samples. + * + * The time is passed in here so that after a seek we can set up our _audio_position. The + * time is ignored once this has been done. + */ +void +AudioDecoder::audio (shared_ptr data, ContentTime time) +{ + if (_resampler) { + data = _resampler->run (data); + } + if (!_audio_position) { + _audio_position = time; + } + + _pending.push_back (shared_ptr (new DecodedAudio (_audio_position.get (), data))); + _audio_position = _audio_position.get() + ContentTime (data->frames (), _audio_content->output_audio_frame_rate ()); } void -AudioDecoder::audio (shared_ptr data, AudioContent::Frame frame) +AudioDecoder::flush () { - Audio (data, frame); - _audio_position = frame + data->frames (); + if (!_resampler) { + return; + } + + shared_ptr b = _resampler->flush (); + if (b) { + _pending.push_back (shared_ptr (new DecodedAudio (_audio_position.get (), b))); + _audio_position = _audio_position.get() + ContentTime (b->frames (), _audio_content->output_audio_frame_rate ()); + } } -/** This is a bit odd, but necessary when we have (e.g.) FFmpegDecoders with no audio. - * The player needs to know that there is no audio otherwise it will keep trying to - * pass() the decoder to get it to emit audio. - */ -bool -AudioDecoder::has_audio () const +void +AudioDecoder::seek (ContentTime, bool) { - return _audio_content->audio_channels () > 0; + _audio_position.reset (); } diff --git a/src/lib/audio_decoder.h b/src/lib/audio_decoder.h index ab6c4b8a9..35d9f3560 100644 --- a/src/lib/audio_decoder.h +++ b/src/lib/audio_decoder.h @@ -27,8 +27,10 @@ #include "decoder.h" #include "content.h" #include "audio_content.h" +#include "decoded.h" class AudioBuffers; +class Resampler; /** @class AudioDecoder. * @brief Parent class for audio decoders. @@ -36,18 +38,22 @@ class AudioBuffers; class AudioDecoder : public virtual Decoder { public: - AudioDecoder (boost::shared_ptr, boost::shared_ptr); - - bool has_audio () const; - - /** Emitted when some audio data is ready */ - boost::signals2::signal, AudioContent::Frame)> Audio; - + AudioDecoder (boost::shared_ptr); + + boost::shared_ptr audio_content () const { + return _audio_content; + } + + void seek (ContentTime time, bool accurate); + protected: - void audio (boost::shared_ptr, AudioContent::Frame); + void audio (boost::shared_ptr, ContentTime); + void flush (); + boost::shared_ptr _audio_content; - AudioContent::Frame _audio_position; + boost::shared_ptr _resampler; + boost::optional _audio_position; }; #endif diff --git a/src/lib/audio_mapping.cc b/src/lib/audio_mapping.cc index ae7702998..1db827046 100644 --- a/src/lib/audio_mapping.cc +++ b/src/lib/audio_mapping.cc @@ -68,11 +68,11 @@ AudioMapping::make_default () if (_content_channels == 1) { /* Mono -> Centre */ - set (0, libdcp::CENTRE, 1); + set (0, dcp::CENTRE, 1); } else { /* 1:1 mapping */ for (int i = 0; i < _content_channels; ++i) { - set (i, static_cast (i), 1); + set (i, static_cast (i), 1); } } } @@ -85,14 +85,14 @@ AudioMapping::AudioMapping (shared_ptr node, int state_version /* Old-style: on/off mapping */ list const c = node->node_children ("Map"); for (list::const_iterator i = c.begin(); i != c.end(); ++i) { - set ((*i)->number_child ("ContentIndex"), static_cast ((*i)->number_child ("DCP")), 1); + set ((*i)->number_child ("ContentIndex"), static_cast ((*i)->number_child ("DCP")), 1); } } else { list const c = node->node_children ("Gain"); for (list::const_iterator i = c.begin(); i != c.end(); ++i) { set ( (*i)->number_attribute ("Content"), - static_cast ((*i)->number_attribute ("DCP")), + static_cast ((*i)->number_attribute ("DCP")), lexical_cast ((*i)->content ()) ); } @@ -100,13 +100,13 @@ AudioMapping::AudioMapping (shared_ptr node, int state_version } void -AudioMapping::set (int c, libdcp::Channel d, float g) +AudioMapping::set (int c, dcp::Channel d, float g) { _gain[c][d] = g; } float -AudioMapping::get (int c, libdcp::Channel d) const +AudioMapping::get (int c, dcp::Channel d) const { return _gain[c][d]; } @@ -121,7 +121,7 @@ AudioMapping::as_xml (xmlpp::Node* node) const xmlpp::Element* t = node->add_child ("Gain"); t->set_attribute ("Content", lexical_cast (c)); t->set_attribute ("DCP", lexical_cast (d)); - t->add_child_text (lexical_cast (get (c, static_cast (d)))); + t->add_child_text (lexical_cast (get (c, static_cast (d)))); } } } diff --git a/src/lib/audio_mapping.h b/src/lib/audio_mapping.h index 26087bfff..f3096764c 100644 --- a/src/lib/audio_mapping.h +++ b/src/lib/audio_mapping.h @@ -21,7 +21,7 @@ #define DCPOMATIC_AUDIO_MAPPING_H #include -#include +#include #include namespace xmlpp { @@ -50,8 +50,8 @@ public: void make_default (); - void set (int, libdcp::Channel, float); - float get (int, libdcp::Channel) const; + void set (int, dcp::Channel, float); + float get (int, dcp::Channel) const; int content_channels () const { return _content_channels; diff --git a/src/lib/audio_merger.cc b/src/lib/audio_merger.cc new file mode 100644 index 000000000..ad110a44f --- /dev/null +++ b/src/lib/audio_merger.cc @@ -0,0 +1,92 @@ +/* + Copyright (C) 2013-2014 Carl Hetherington + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include "audio_buffers.h" +#include "audio_merger.h" + +using std::min; +using std::max; +using boost::shared_ptr; + +AudioMerger::AudioMerger (int channels, int frame_rate) + : _buffers (new AudioBuffers (channels, 0)) + , _frame_rate (frame_rate) + , _last_pull (0) +{ + +} + + +TimedAudioBuffers +AudioMerger::pull (DCPTime time) +{ + assert (time >= _last_pull); + + TimedAudioBuffers out; + + int64_t const to_return = DCPTime (time - _last_pull).frames (_frame_rate); + out.audio.reset (new AudioBuffers (_buffers->channels(), to_return)); + /* And this is how many we will get from our buffer */ + int64_t const to_return_from_buffers = min (to_return, int64_t (_buffers->frames ())); + + /* Copy the data that we have to the back end of the return buffer */ + out.audio->copy_from (_buffers.get(), to_return_from_buffers, 0, to_return - to_return_from_buffers); + /* Silence any gap at the start */ + out.audio->make_silent (0, to_return - to_return_from_buffers); + + out.time = _last_pull; + _last_pull = time; + + /* And remove the data we're returning from our buffers */ + if (_buffers->frames() > to_return_from_buffers) { + _buffers->move (to_return_from_buffers, 0, _buffers->frames() - to_return_from_buffers); + } + _buffers->set_frames (_buffers->frames() - to_return_from_buffers); + + return out; +} + +void +AudioMerger::push (shared_ptr audio, DCPTime time) +{ + assert (time >= _last_pull); + + int64_t frame = time.frames (_frame_rate); + int64_t after = max (int64_t (_buffers->frames()), frame + audio->frames() - _last_pull.frames (_frame_rate)); + _buffers->ensure_size (after); + _buffers->accumulate_frames (audio.get(), 0, frame - _last_pull.frames (_frame_rate), audio->frames ()); + _buffers->set_frames (after); +} + +TimedAudioBuffers +AudioMerger::flush () +{ + if (_buffers->frames() == 0) { + return TimedAudioBuffers (); + } + + return TimedAudioBuffers (_buffers, _last_pull); +} + +void +AudioMerger::clear (DCPTime t) +{ + _last_pull = t; + _buffers.reset (new AudioBuffers (_buffers->channels(), 0)); +} diff --git a/src/lib/audio_merger.h b/src/lib/audio_merger.h index 226601e0e..756e5ab31 100644 --- a/src/lib/audio_merger.h +++ b/src/lib/audio_merger.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Carl Hetherington + Copyright (C) 2013-2014 Carl Hetherington This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,93 +17,25 @@ */ -#include "audio_buffers.h" #include "util.h" -template +class AudioBuffers; + class AudioMerger { public: - AudioMerger (int channels, boost::function t_to_f, boost::function f_to_t) - : _buffers (new AudioBuffers (channels, 0)) - , _last_pull (0) - , _t_to_f (t_to_f) - , _f_to_t (f_to_t) - {} + AudioMerger (int channels, int frame_rate); /** Pull audio up to a given time; after this call, no more data can be pushed * before the specified time. */ - TimedAudioBuffers - pull (T time) - { - TimedAudioBuffers out; - - F const to_return = _t_to_f (time - _last_pull); - out.audio.reset (new AudioBuffers (_buffers->channels(), to_return)); - /* And this is how many we will get from our buffer */ - F const to_return_from_buffers = min (to_return, _buffers->frames ()); - - /* Copy the data that we have to the back end of the return buffer */ - out.audio->copy_from (_buffers.get(), to_return_from_buffers, 0, to_return - to_return_from_buffers); - /* Silence any gap at the start */ - out.audio->make_silent (0, to_return - to_return_from_buffers); - - out.time = _last_pull; - _last_pull = time; - - /* And remove the data we're returning from our buffers */ - if (_buffers->frames() > to_return_from_buffers) { - _buffers->move (to_return_from_buffers, 0, _buffers->frames() - to_return_from_buffers); - } - _buffers->set_frames (_buffers->frames() - to_return_from_buffers); - - return out; - } - - void - push (boost::shared_ptr audio, T time) - { - assert (time >= _last_pull); - - F frame = _t_to_f (time); - F after = max (_buffers->frames(), frame + audio->frames() - _t_to_f (_last_pull)); - _buffers->ensure_size (after); - _buffers->accumulate_frames (audio.get(), 0, frame - _t_to_f (_last_pull), audio->frames ()); - _buffers->set_frames (after); - } - - F min (F a, int b) - { - if (a < b) { - return a; - } - - return b; - } - - F max (int a, F b) - { - if (a > b) { - return a; - } - - return b; - } - - TimedAudioBuffers - flush () - { - if (_buffers->frames() == 0) { - return TimedAudioBuffers (); - } - - return TimedAudioBuffers (_buffers, _last_pull); - } + TimedAudioBuffers pull (DCPTime time); + void push (boost::shared_ptr audio, DCPTime time); + TimedAudioBuffers flush (); + void clear (DCPTime t); private: boost::shared_ptr _buffers; - T _last_pull; - boost::function _t_to_f; - boost::function _f_to_t; + int _frame_rate; + DCPTime _last_pull; }; diff --git a/src/lib/cinema.cc b/src/lib/cinema.cc index fca6b6afd..43a432239 100644 --- a/src/lib/cinema.cc +++ b/src/lib/cinema.cc @@ -70,7 +70,7 @@ Cinema::remove_screen (shared_ptr s) Screen::Screen (shared_ptr node) { name = node->string_child ("Name"); - certificate = shared_ptr (new libdcp::Certificate (node->string_child ("Certificate"))); + certificate = shared_ptr (new dcp::Certificate (node->string_child ("Certificate"))); } void diff --git a/src/lib/cinema.h b/src/lib/cinema.h index 40dc15ae0..d8e28ecfd 100644 --- a/src/lib/cinema.h +++ b/src/lib/cinema.h @@ -18,7 +18,7 @@ */ #include -#include +#include class Cinema; @@ -29,7 +29,7 @@ namespace cxml { class Screen { public: - Screen (std::string const & n, boost::shared_ptr cert) + Screen (std::string const & n, boost::shared_ptr cert) : name (n) , certificate (cert) {} @@ -40,7 +40,7 @@ public: boost::shared_ptr cinema; std::string name; - boost::shared_ptr certificate; + boost::shared_ptr certificate; }; class Cinema : public boost::enable_shared_from_this diff --git a/src/lib/colour_conversion.cc b/src/lib/colour_conversion.cc index c3fa05426..e4a2a84bf 100644 --- a/src/lib/colour_conversion.cc +++ b/src/lib/colour_conversion.cc @@ -19,7 +19,7 @@ #include #include -#include +#include #include #include "config.h" #include "colour_conversion.h" @@ -43,7 +43,7 @@ ColourConversion::ColourConversion () { for (int i = 0; i < 3; ++i) { for (int j = 0; j < 3; ++j) { - matrix (i, j) = libdcp::colour_matrix::srgb_to_xyz[i][j]; + matrix (i, j) = dcp::colour_matrix::srgb_to_xyz[i][j]; } } } diff --git a/src/lib/config.cc b/src/lib/config.cc index 30f85850d..ad1408cff 100644 --- a/src/lib/config.cc +++ b/src/lib/config.cc @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include #include "config.h" #include "server.h" @@ -78,9 +78,9 @@ Config::Config () _allowed_dcp_frame_rates.push_back (50); _allowed_dcp_frame_rates.push_back (60); - _colour_conversions.push_back (PresetColourConversion (_("sRGB"), 2.4, true, libdcp::colour_matrix::srgb_to_xyz, 2.6)); - _colour_conversions.push_back (PresetColourConversion (_("sRGB non-linearised"), 2.4, false, libdcp::colour_matrix::srgb_to_xyz, 2.6)); - _colour_conversions.push_back (PresetColourConversion (_("Rec. 709"), 2.2, false, libdcp::colour_matrix::rec709_to_xyz, 2.6)); + _colour_conversions.push_back (PresetColourConversion (_("sRGB"), 2.4, true, dcp::colour_matrix::srgb_to_xyz, 2.6)); + _colour_conversions.push_back (PresetColourConversion (_("sRGB non-linearised"), 2.4, false, dcp::colour_matrix::srgb_to_xyz, 2.6)); + _colour_conversions.push_back (PresetColourConversion (_("Rec. 709"), 2.2, false, dcp::colour_matrix::rec709_to_xyz, 2.6)); } void @@ -164,7 +164,7 @@ Config::read () /* Loading version 0 (before Rec. 709 was added as a preset). Add it in. */ - _colour_conversions.push_back (PresetColourConversion (_("Rec. 709"), 2.2, false, libdcp::colour_matrix::rec709_to_xyz, 2.6)); + _colour_conversions.push_back (PresetColourConversion (_("Rec. 709"), 2.2, false, dcp::colour_matrix::rec709_to_xyz, 2.6)); } list cin = f.node_children ("Cinema"); diff --git a/src/lib/config.h b/src/lib/config.h index b9e8d6b02..68aae7414 100644 --- a/src/lib/config.h +++ b/src/lib/config.h @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include "dci_metadata.h" #include "colour_conversion.h" #include "server.h" @@ -137,7 +137,7 @@ public: return _default_dcp_content_type; } - libdcp::XMLMetadata dcp_metadata () const { + dcp::XMLMetadata dcp_metadata () const { return _dcp_metadata; } @@ -265,7 +265,7 @@ public: write (); } - void set_dcp_metadata (libdcp::XMLMetadata m) { + void set_dcp_metadata (dcp::XMLMetadata m) { _dcp_metadata = m; write (); } @@ -362,7 +362,7 @@ private: int _default_still_length; Ratio const * _default_container; DCPContentType const * _default_dcp_content_type; - libdcp::XMLMetadata _dcp_metadata; + dcp::XMLMetadata _dcp_metadata; int _default_j2k_bandwidth; int _default_audio_delay; std::vector _colour_conversions; diff --git a/src/lib/content.cc b/src/lib/content.cc index 829468247..1fb4681a2 100644 --- a/src/lib/content.cc +++ b/src/lib/content.cc @@ -54,7 +54,7 @@ Content::Content (shared_ptr f) } -Content::Content (shared_ptr f, Time p) +Content::Content (shared_ptr f, DCPTime p) : _film (f) , _position (p) , _trim_start (0) @@ -83,9 +83,9 @@ Content::Content (shared_ptr f, shared_ptr node) _paths.push_back ((*i)->content ()); } _digest = node->string_child ("Digest"); - _position = node->number_child