diff options
| author | Carl Hetherington <cth@carlh.net> | 2013-07-30 21:34:16 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2013-07-30 21:34:16 +0100 |
| commit | c57e92b12c64d4ad1a7f23876a97471565f9a252 (patch) | |
| tree | 008213d35e4be34c55caa51760ab7aef6fa33113 /src/lib | |
| parent | e241b3d295fe4158239170f17391e08473e159c5 (diff) | |
Somewhat untested and sketchy basics of trimming.
Diffstat (limited to 'src/lib')
| -rw-r--r-- | src/lib/content.cc | 68 | ||||
| -rw-r--r-- | src/lib/content.h | 39 | ||||
| -rw-r--r-- | src/lib/ffmpeg_content.cc | 2 | ||||
| -rw-r--r-- | src/lib/ffmpeg_content.h | 2 | ||||
| -rw-r--r-- | src/lib/film.cc | 2 | ||||
| -rw-r--r-- | src/lib/moving_image_content.cc | 2 | ||||
| -rw-r--r-- | src/lib/moving_image_content.h | 2 | ||||
| -rw-r--r-- | src/lib/player.cc | 47 | ||||
| -rw-r--r-- | src/lib/playlist.cc | 11 | ||||
| -rw-r--r-- | src/lib/sndfile_content.cc | 2 | ||||
| -rw-r--r-- | src/lib/sndfile_content.h | 2 | ||||
| -rw-r--r-- | src/lib/still_image_content.cc | 2 | ||||
| -rw-r--r-- | src/lib/still_image_content.h | 2 |
13 files changed, 133 insertions, 50 deletions
diff --git a/src/lib/content.cc b/src/lib/content.cc index 372be3020..950814491 100644 --- a/src/lib/content.cc +++ b/src/lib/content.cc @@ -30,12 +30,16 @@ using std::set; using boost::shared_ptr; using boost::lexical_cast; -int const ContentProperty::START = 400; +int const ContentProperty::POSITION = 400; int const ContentProperty::LENGTH = 401; +int const ContentProperty::TRIM_START = 402; +int const ContentProperty::TRIM_END = 403; -Content::Content (shared_ptr<const Film> f, Time s) +Content::Content (shared_ptr<const Film> f, Time p) : _film (f) - , _start (s) + , _position (p) + , _trim_start (0) + , _trim_end (0) , _change_signals_frequent (false) { @@ -44,7 +48,9 @@ Content::Content (shared_ptr<const Film> f, Time s) Content::Content (shared_ptr<const Film> f, boost::filesystem::path p) : _film (f) , _path (p) - , _start (0) + , _position (0) + , _trim_start (0) + , _trim_end (0) , _change_signals_frequent (false) { @@ -56,7 +62,9 @@ Content::Content (shared_ptr<const Film> f, shared_ptr<const cxml::Node> node) { _path = node->string_child ("Path"); _digest = node->string_child ("Digest"); - _start = node->number_child<Time> ("Start"); + _position = node->number_child<Time> ("Position"); + _trim_start = node->number_child<Time> ("TrimStart"); + _trim_end = node->number_child<Time> ("TrimEnd"); } void @@ -65,7 +73,9 @@ Content::as_xml (xmlpp::Node* node) const boost::mutex::scoped_lock lm (_mutex); node->add_child("Path")->add_child_text (_path.string()); node->add_child("Digest")->add_child_text (_digest); - node->add_child("Start")->add_child_text (lexical_cast<string> (_start)); + node->add_child("Position")->add_child_text (lexical_cast<string> (_position)); + node->add_child("TrimStart")->add_child_text (lexical_cast<string> (_trim_start)); + node->add_child("TrimEnd")->add_child_text (lexical_cast<string> (_trim_end)); } void @@ -91,16 +101,39 @@ Content::signal_changed (int p) } void -Content::set_start (Time s) +Content::set_position (Time p) { { boost::mutex::scoped_lock lm (_mutex); - _start = s; + _position = p; } - signal_changed (ContentProperty::START); + signal_changed (ContentProperty::POSITION); } +void +Content::set_trim_start (Time t) +{ + { + boost::mutex::scoped_lock lm (_mutex); + _trim_start = t; + } + + signal_changed (ContentProperty::TRIM_START); +} + +void +Content::set_trim_end (Time t) +{ + { + boost::mutex::scoped_lock lm (_mutex); + _trim_end = t; + } + + signal_changed (ContentProperty::TRIM_END); +} + + shared_ptr<Content> Content::clone () const { @@ -119,5 +152,20 @@ Content::clone () const string Content::technical_summary () const { - return String::compose ("%1 %2 %3", path(), digest(), start()); + return String::compose ("%1 %2 %3", path(), digest(), position()); +} + +Time +Content::length_after_trim () const +{ + return full_length () - _trim_start - _trim_end; +} + +/** @param t A time relative to the start of this content (not the position). + * @return true if this time is trimmed by our trim settings. + */ +bool +Content::trimmed (Time t) const +{ + return (t < trim_start() || t > (full_length() - trim_end ())); } diff --git a/src/lib/content.h b/src/lib/content.h index 78b80e254..e3f559752 100644 --- a/src/lib/content.h +++ b/src/lib/content.h @@ -38,8 +38,10 @@ class Film; class ContentProperty { public: - static int const START; + static int const POSITION; static int const LENGTH; + static int const TRIM_START; + static int const TRIM_END; }; class Content : public boost::enable_shared_from_this<Content>, public boost::noncopyable @@ -55,7 +57,7 @@ public: virtual std::string technical_summary () const; virtual std::string information () const = 0; virtual void as_xml (xmlpp::Node *) const; - virtual Time length () const = 0; + virtual Time full_length () const = 0; boost::shared_ptr<Content> clone () const; @@ -70,21 +72,42 @@ public: return _digest; } - void set_start (Time); + void set_position (Time); - Time start () const { + /** Time that this content starts; i.e. the time that the first + * bit of the content (trimmed or not) will happen. + */ + Time position () const { boost::mutex::scoped_lock lm (_mutex); - return _start; + return _position; } + void set_trim_start (Time); + + Time trim_start () const { + boost::mutex::scoped_lock lm (_mutex); + return _trim_start; + } + + void set_trim_end (Time); + + Time trim_end () const { + boost::mutex::scoped_lock lm (_mutex); + return _trim_end; + } + Time end () const { - return start() + length(); + return position() + length_after_trim(); } + Time length_after_trim () const; + void set_change_signals_frequent (bool f) { _change_signals_frequent = f; } + bool trimmed (Time) const; + boost::signals2::signal<void (boost::weak_ptr<Content>, int, bool)> Changed; protected: @@ -97,7 +120,9 @@ private: /** Path of a file or a directory containing files */ boost::filesystem::path _path; std::string _digest; - Time _start; + Time _position; + Time _trim_start; + Time _trim_end; bool _change_signals_frequent; }; diff --git a/src/lib/ffmpeg_content.cc b/src/lib/ffmpeg_content.cc index 84be76d27..de967c045 100644 --- a/src/lib/ffmpeg_content.cc +++ b/src/lib/ffmpeg_content.cc @@ -346,7 +346,7 @@ FFmpegSubtitleStream::as_xml (xmlpp::Node* root) const } Time -FFmpegContent::length () const +FFmpegContent::full_length () const { shared_ptr<const Film> film = _film.lock (); assert (film); diff --git a/src/lib/ffmpeg_content.h b/src/lib/ffmpeg_content.h index 96d8c1727..775cb9220 100644 --- a/src/lib/ffmpeg_content.h +++ b/src/lib/ffmpeg_content.h @@ -107,7 +107,7 @@ public: std::string technical_summary () const; std::string information () const; void as_xml (xmlpp::Node *) const; - Time length () const; + Time full_length () const; std::string identifier () const; diff --git a/src/lib/film.cc b/src/lib/film.cc index 13c1558e9..2f7e07873 100644 --- a/src/lib/film.cc +++ b/src/lib/film.cc @@ -806,7 +806,7 @@ Film::add_content (shared_ptr<Content> c) { /* Add video content after any existing content */ if (dynamic_pointer_cast<VideoContent> (c)) { - c->set_start (_playlist->video_end ()); + c->set_position (_playlist->video_end ()); } _playlist->add (c); diff --git a/src/lib/moving_image_content.cc b/src/lib/moving_image_content.cc index 30030d9fd..63b4b9f24 100644 --- a/src/lib/moving_image_content.cc +++ b/src/lib/moving_image_content.cc @@ -94,7 +94,7 @@ MovingImageContent::examine (shared_ptr<Job> job) } Time -MovingImageContent::length () const +MovingImageContent::full_length () const { shared_ptr<const Film> film = _film.lock (); assert (film); diff --git a/src/lib/moving_image_content.h b/src/lib/moving_image_content.h index 2b3c48dd1..1a64750fe 100644 --- a/src/lib/moving_image_content.h +++ b/src/lib/moving_image_content.h @@ -42,7 +42,7 @@ public: std::string summary () const; std::string technical_summary () const; void as_xml (xmlpp::Node *) const; - Time length () const; + Time full_length () const; std::string identifier () const; diff --git a/src/lib/player.cc b/src/lib/player.cc index 33a5bbfef..63cf4ee7f 100644 --- a/src/lib/player.cc +++ b/src/lib/player.cc @@ -55,15 +55,15 @@ class Piece public: Piece (shared_ptr<Content> c) : content (c) - , video_position (c->start ()) - , audio_position (c->start ()) + , video_position (c->position ()) + , audio_position (c->position ()) {} Piece (shared_ptr<Content> c, shared_ptr<Decoder> d) : content (c) , decoder (d) - , video_position (c->start ()) - , audio_position (c->start ()) + , video_position (c->position ()) + , audio_position (c->position ()) {} shared_ptr<Content> content; @@ -83,7 +83,7 @@ std::ostream& operator<<(std::ostream& s, Piece const & p) s << "\tsndfile "; } - s << " at " << p.content->start() << " until " << p.content->end(); + s << " at " << p.content->position() << " until " << p.content->end(); return s; } @@ -248,14 +248,19 @@ Player::process_video (weak_ptr<Piece> weak_piece, shared_ptr<const Image> image return; } + Time const relative_time = (frame * frc.factor() * TIME_HZ / _film->video_frame_rate()); + if (content->trimmed (relative_time)) { + return; + } + shared_ptr<Image> work_image = image->crop (content->crop(), true); libdcp::Size const image_size = content->ratio()->size (_video_container_size); work_image = work_image->scale_and_convert_to_rgb (image_size, _film->scaler(), true); - Time time = content->start() + (frame * frc.factor() * TIME_HZ / _film->video_frame_rate()); - + Time time = content->position() + relative_time - content->trim_start (); + if (_film->with_subtitles () && _out_subtitle.image && time >= _out_subtitle.from && time <= _out_subtitle.to) { work_image->alpha_blend (_out_subtitle.image, _out_subtitle.position); } @@ -297,6 +302,15 @@ Player::process_audio (weak_ptr<Piece> weak_piece, shared_ptr<const AudioBuffers shared_ptr<AudioContent> content = dynamic_pointer_cast<AudioContent> (piece->content); assert (content); + Time const relative_time = _film->audio_frames_to_time (frame) + + (content->audio_delay() * TIME_HZ / 1000); + + if (content->trimmed (relative_time)) { + return; + } + + Time time = content->position() + relative_time; + /* Resample */ if (content->content_audio_frame_rate() != content->output_audio_frame_rate()) { shared_ptr<Resampler> r = resampler (content, true); @@ -317,10 +331,6 @@ Player::process_audio (weak_ptr<Piece> weak_piece, shared_ptr<const AudioBuffers audio = dcp_mapped; - Time time = content->start() - + _film->audio_frames_to_time (frame) - + (content->audio_delay() * TIME_HZ / 1000); - /* We must cut off anything that comes before the start of all time */ if (time < 0) { int const frames = - time * _film->audio_frame_rate() / TIME_HZ; @@ -380,18 +390,18 @@ Player::seek (Time t, bool accurate) continue; } - Time s = t - vc->start (); + Time s = t - vc->position (); s = max (static_cast<Time> (0), s); - s = min (vc->length(), s); + s = min (vc->length_after_trim(), s); - (*i)->video_position = (*i)->audio_position = vc->start() + s; + (*i)->video_position = (*i)->audio_position = vc->position() + s; FrameRateConversion frc (vc->video_frame_rate(), _film->video_frame_rate()); /* Here we are converting from time (in the DCP) to a frame number in the content. Hence we need to use the DCP's frame rate and the double/skip correction, not the source's rate. */ - VideoContent::Frame f = s * _film->video_frame_rate() / (frc.factor() * TIME_HZ); + VideoContent::Frame f = (s + vc->trim_start ()) * _film->video_frame_rate() / (frc.factor() * TIME_HZ); dynamic_pointer_cast<VideoDecoder>((*i)->decoder)->seek (f, accurate); } @@ -487,7 +497,8 @@ Player::content_changed (weak_ptr<Content> w, int property, bool frequent) } if ( - property == ContentProperty::START || property == ContentProperty::LENGTH || + property == ContentProperty::POSITION || property == ContentProperty::LENGTH || + property == ContentProperty::TRIM_START || property == ContentProperty::TRIM_END || property == VideoContentProperty::VIDEO_CROP || property == VideoContentProperty::VIDEO_RATIO ) { @@ -622,6 +633,6 @@ Player::update_subtitle () _out_subtitle.position.y = rint (_video_container_size.height * (in_rect.y + (in_rect.height * (1 - sc->subtitle_scale ()) / 2))); _out_subtitle.image = _in_subtitle.image->scale (libdcp::Size (scaled_size.width, scaled_size.height), Scaler::from_id ("bicubic"), true); - _out_subtitle.from = _in_subtitle.from + piece->content->start (); - _out_subtitle.to = _in_subtitle.to + piece->content->start (); + _out_subtitle.from = _in_subtitle.from + piece->content->position (); + _out_subtitle.to = _in_subtitle.to + piece->content->position (); } diff --git a/src/lib/playlist.cc b/src/lib/playlist.cc index e9ea3e3c7..de48ff5f5 100644 --- a/src/lib/playlist.cc +++ b/src/lib/playlist.cc @@ -72,7 +72,6 @@ Playlist::content_changed (weak_ptr<Content> content, int property, bool frequen ContentChanged (content, property, frequent); } - void Playlist::maybe_sequence_video () { @@ -90,7 +89,7 @@ Playlist::maybe_sequence_video () continue; } - (*i)->set_start (last); + (*i)->set_position (last); last = (*i)->end (); } @@ -295,7 +294,7 @@ Playlist::set_sequence_video (bool s) bool ContentSorter::operator() (shared_ptr<Content> a, shared_ptr<Content> b) { - return a->start() < b->start(); + return a->position() < b->position(); } /** @return content in an undefined order */ @@ -310,8 +309,8 @@ Playlist::repeat (ContentList c, int n) { pair<Time, Time> range (TIME_MAX, 0); for (ContentList::iterator i = c.begin(); i != c.end(); ++i) { - range.first = min (range.first, (*i)->start ()); - range.second = max (range.second, (*i)->start ()); + range.first = min (range.first, (*i)->position ()); + range.second = max (range.second, (*i)->position ()); range.first = min (range.first, (*i)->end ()); range.second = max (range.second, (*i)->end ()); } @@ -320,7 +319,7 @@ Playlist::repeat (ContentList c, int n) for (int i = 0; i < n; ++i) { for (ContentList::iterator i = c.begin(); i != c.end(); ++i) { shared_ptr<Content> copy = (*i)->clone (); - copy->set_start (pos + copy->start() - range.first); + copy->set_position (pos + copy->position() - range.first); _content.push_back (copy); } pos += range.second - range.first; diff --git a/src/lib/sndfile_content.cc b/src/lib/sndfile_content.cc index 2ca00cf6d..fc6f45d00 100644 --- a/src/lib/sndfile_content.cc +++ b/src/lib/sndfile_content.cc @@ -136,7 +136,7 @@ SndfileContent::as_xml (xmlpp::Node* node) const } Time -SndfileContent::length () const +SndfileContent::full_length () const { shared_ptr<const Film> film = _film.lock (); assert (film); diff --git a/src/lib/sndfile_content.h b/src/lib/sndfile_content.h index 27e0ca21d..191d62527 100644 --- a/src/lib/sndfile_content.h +++ b/src/lib/sndfile_content.h @@ -44,7 +44,7 @@ public: std::string technical_summary () const; std::string information () const; void as_xml (xmlpp::Node *) const; - Time length () const; + Time full_length () const; /* AudioContent */ int audio_channels () const { diff --git a/src/lib/still_image_content.cc b/src/lib/still_image_content.cc index 5a3fed1b3..0cf80b546 100644 --- a/src/lib/still_image_content.cc +++ b/src/lib/still_image_content.cc @@ -94,7 +94,7 @@ StillImageContent::set_video_length (VideoContent::Frame len) } Time -StillImageContent::length () const +StillImageContent::full_length () const { shared_ptr<const Film> film = _film.lock (); assert (film); diff --git a/src/lib/still_image_content.h b/src/lib/still_image_content.h index 24d5174a0..ccd7fbc03 100644 --- a/src/lib/still_image_content.h +++ b/src/lib/still_image_content.h @@ -42,7 +42,7 @@ public: std::string summary () const; std::string technical_summary () const; void as_xml (xmlpp::Node *) const; - Time length () const; + Time full_length () const; std::string identifier () const; |
