summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2013-07-30 21:34:16 +0100
committerCarl Hetherington <cth@carlh.net>2013-07-30 21:34:16 +0100
commitc57e92b12c64d4ad1a7f23876a97471565f9a252 (patch)
tree008213d35e4be34c55caa51760ab7aef6fa33113 /src/lib
parente241b3d295fe4158239170f17391e08473e159c5 (diff)
Somewhat untested and sketchy basics of trimming.
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/content.cc68
-rw-r--r--src/lib/content.h39
-rw-r--r--src/lib/ffmpeg_content.cc2
-rw-r--r--src/lib/ffmpeg_content.h2
-rw-r--r--src/lib/film.cc2
-rw-r--r--src/lib/moving_image_content.cc2
-rw-r--r--src/lib/moving_image_content.h2
-rw-r--r--src/lib/player.cc47
-rw-r--r--src/lib/playlist.cc11
-rw-r--r--src/lib/sndfile_content.cc2
-rw-r--r--src/lib/sndfile_content.h2
-rw-r--r--src/lib/still_image_content.cc2
-rw-r--r--src/lib/still_image_content.h2
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;