Collect player subtitle processing into a Subtitle class.
authorCarl Hetherington <cth@carlh.net>
Fri, 25 Apr 2014 22:27:42 +0000 (23:27 +0100)
committerCarl Hetherington <cth@carlh.net>
Fri, 25 Apr 2014 22:27:42 +0000 (23:27 +0100)
src/lib/player.cc
src/lib/player.h
src/lib/subtitle.cc [new file with mode: 0644]
src/lib/subtitle.h [new file with mode: 0644]
src/lib/wscript

index 7afe748..d0653bc 100644 (file)
@@ -219,14 +219,14 @@ Player::process_video (weak_ptr<Piece> weak_piece, shared_ptr<const Image> image
                        )
                );
        
-       if (_film->with_subtitles () && _out_subtitle.image && time >= _out_subtitle.from && time <= _out_subtitle.to) {
+       if (_film->with_subtitles () && _subtitle && _subtitle->out_image() && _subtitle->covers (time)) {
 
                Position<int> const container_offset (
                        (_video_container_size.width - image_size.width) / 2,
                        (_video_container_size.height - image_size.width) / 2
                        );
 
-               pi->set_subtitle (_out_subtitle.image, _out_subtitle.position + container_offset);
+               pi->set_subtitle (_subtitle->out_image(), _subtitle->out_position() + container_offset);
        }
                
                                            
@@ -466,7 +466,9 @@ Player::content_changed (weak_ptr<Content> w, int property, bool frequent)
                property == SubtitleContentProperty::SUBTITLE_SCALE
                ) {
 
-               update_subtitle ();
+               if (_subtitle) {
+                       _subtitle->update (_film, _video_container_size);
+               }
                Changed (frequent);
 
        } else if (
@@ -574,74 +576,7 @@ Player::film_changed (Film::Property p)
 void
 Player::process_subtitle (weak_ptr<Piece> weak_piece, shared_ptr<Image> image, dcpomatic::Rect<double> rect, Time from, Time to)
 {
-       _in_subtitle.piece = weak_piece;
-       _in_subtitle.image = image;
-       _in_subtitle.rect = rect;
-       _in_subtitle.from = from;
-       _in_subtitle.to = to;
-
-       update_subtitle ();
-}
-
-void
-Player::update_subtitle ()
-{
-       shared_ptr<Piece> piece = _in_subtitle.piece.lock ();
-       if (!piece) {
-               return;
-       }
-
-       if (!_in_subtitle.image) {
-               _out_subtitle.image.reset ();
-               return;
-       }
-
-       shared_ptr<SubtitleContent> sc = dynamic_pointer_cast<SubtitleContent> (piece->content);
-       assert (sc);
-
-       dcpomatic::Rect<double> in_rect = _in_subtitle.rect;
-       libdcp::Size scaled_size;
-
-       in_rect.x += sc->subtitle_x_offset ();
-       in_rect.y += sc->subtitle_y_offset ();
-
-       /* We will scale the subtitle up to fit _video_container_size, and also by the additional subtitle_scale */
-       scaled_size.width = in_rect.width * _video_container_size.width * sc->subtitle_scale ();
-       scaled_size.height = in_rect.height * _video_container_size.height * sc->subtitle_scale ();
-
-       /* Then we need a corrective translation, consisting of two parts:
-        *
-        * 1.  that which is the result of the scaling of the subtitle by _video_container_size; this will be
-        *     rect.x * _video_container_size.width and rect.y * _video_container_size.height.
-        *
-        * 2.  that to shift the origin of the scale by subtitle_scale to the centre of the subtitle; this will be
-        *     (width_before_subtitle_scale * (1 - subtitle_scale) / 2) and
-        *     (height_before_subtitle_scale * (1 - subtitle_scale) / 2).
-        *
-        * Combining these two translations gives these expressions.
-        */
-       
-       _out_subtitle.position.x = rint (_video_container_size.width * (in_rect.x + (in_rect.width * (1 - sc->subtitle_scale ()) / 2)));
-       _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 (
-               scaled_size,
-               Scaler::from_id ("bicubic"),
-               _in_subtitle.image->pixel_format (),
-               true
-               );
-
-       /* XXX: hack */
-       Time from = _in_subtitle.from;
-       Time to = _in_subtitle.to;
-       shared_ptr<VideoContent> vc = dynamic_pointer_cast<VideoContent> (piece->content);
-       if (vc) {
-               from = rint (from * vc->video_frame_rate() / _film->video_frame_rate());
-               to = rint (to * vc->video_frame_rate() / _film->video_frame_rate());
-       }
-       
-       _out_subtitle.from = from + piece->content->position ();
-       _out_subtitle.to = to + piece->content->position ();
+       _subtitle = Subtitle (_film, _video_container_size, weak_piece, image, rect, from, to);
 }
 
 /** Re-emit the last frame that was emitted, using current settings for crop, ratio, scaler and subtitles.
index 4368f48..5dad80e 100644 (file)
@@ -30,6 +30,7 @@
 #include "audio_merger.h"
 #include "audio_content.h"
 #include "piece.h"
+#include "subtitle.h"
 
 class Job;
 class Film;
@@ -142,20 +143,7 @@ private:
        boost::shared_ptr<PlayerImage> _black_frame;
        std::map<boost::shared_ptr<AudioContent>, boost::shared_ptr<Resampler> > _resamplers;
 
-       struct {
-               boost::weak_ptr<Piece> piece;
-               boost::shared_ptr<Image> image;
-               dcpomatic::Rect<double> rect;
-               Time from;
-               Time to;
-       } _in_subtitle;
-
-       struct {
-               boost::shared_ptr<Image> image;
-               Position<int> position;
-               Time from;
-               Time to;
-       } _out_subtitle;
+       boost::optional<Subtitle> _subtitle;
 
 #ifdef DCPOMATIC_DEBUG
        boost::shared_ptr<Content> _last_video;
diff --git a/src/lib/subtitle.cc b/src/lib/subtitle.cc
new file mode 100644 (file)
index 0000000..f348833
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+    Copyright (C) 2013-2014 Carl Hetherington <cth@carlh.net>
+
+    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 "subtitle.h"
+#include "subtitle_content.h"
+#include "piece.h"
+#include "image.h"
+#include "scaler.h"
+#include "film.h"
+
+using boost::shared_ptr;
+using boost::dynamic_pointer_cast;
+using boost::weak_ptr;
+
+Subtitle::Subtitle (shared_ptr<const Film> film, libdcp::Size video_container_size, weak_ptr<Piece> weak_piece, shared_ptr<Image> image, dcpomatic::Rect<double> rect, Time from, Time to)
+       : _piece (weak_piece)
+       , _in_image (image)
+       , _in_rect (rect)
+       , _in_from (from)
+       , _in_to (to)
+{
+       update (film, video_container_size);
+}
+
+void
+Subtitle::update (shared_ptr<const Film> film, libdcp::Size video_container_size)
+{
+       shared_ptr<Piece> piece = _piece.lock ();
+       if (!piece) {
+               return;
+       }
+
+       if (!_in_image) {
+               _out_image.reset ();
+               return;
+       }
+
+       shared_ptr<SubtitleContent> sc = dynamic_pointer_cast<SubtitleContent> (piece->content);
+       assert (sc);
+
+       dcpomatic::Rect<double> in_rect = _in_rect;
+       libdcp::Size scaled_size;
+
+       in_rect.x += sc->subtitle_x_offset ();
+       in_rect.y += sc->subtitle_y_offset ();
+
+       /* We will scale the subtitle up to fit _video_container_size, and also by the additional subtitle_scale */
+       scaled_size.width = in_rect.width * video_container_size.width * sc->subtitle_scale ();
+       scaled_size.height = in_rect.height * video_container_size.height * sc->subtitle_scale ();
+
+       /* Then we need a corrective translation, consisting of two parts:
+        *
+        * 1.  that which is the result of the scaling of the subtitle by _video_container_size; this will be
+        *     rect.x * _video_container_size.width and rect.y * _video_container_size.height.
+        *
+        * 2.  that to shift the origin of the scale by subtitle_scale to the centre of the subtitle; this will be
+        *     (width_before_subtitle_scale * (1 - subtitle_scale) / 2) and
+        *     (height_before_subtitle_scale * (1 - subtitle_scale) / 2).
+        *
+        * Combining these two translations gives these expressions.
+        */
+       
+       _out_position.x = rint (video_container_size.width * (in_rect.x + (in_rect.width * (1 - sc->subtitle_scale ()) / 2)));
+       _out_position.y = rint (video_container_size.height * (in_rect.y + (in_rect.height * (1 - sc->subtitle_scale ()) / 2)));
+       
+       _out_image = _in_image->scale (
+               scaled_size,
+               Scaler::from_id ("bicubic"),
+               _in_image->pixel_format (),
+               true
+               );
+
+       /* XXX: hack */
+       Time from = _in_from;
+       Time to = _in_to;
+       shared_ptr<VideoContent> vc = dynamic_pointer_cast<VideoContent> (piece->content);
+       if (vc) {
+               from = rint (from * vc->video_frame_rate() / film->video_frame_rate());
+               to = rint (to * vc->video_frame_rate() / film->video_frame_rate());
+       }
+       
+       _out_from = from + piece->content->position ();
+       _out_to = to + piece->content->position ();
+}
+
+bool
+Subtitle::covers (Time t) const
+{
+       return _out_from <= t && t <= _out_to;
+}
diff --git a/src/lib/subtitle.h b/src/lib/subtitle.h
new file mode 100644 (file)
index 0000000..7ba5912
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+    Copyright (C) 2013-2014 Carl Hetherington <cth@carlh.net>
+
+    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 <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+#include <libdcp/util.h>
+#include "rect.h"
+#include "types.h"
+
+class Film;
+class Piece;
+class Image;
+
+class Subtitle
+{
+public:
+
+       Subtitle (boost::shared_ptr<const Film>, libdcp::Size, boost::weak_ptr<Piece>, boost::shared_ptr<Image>, dcpomatic::Rect<double>, Time, Time);
+
+       void update (boost::shared_ptr<const Film>, libdcp::Size);
+
+       bool covers (Time t) const;
+
+       boost::shared_ptr<Image> out_image () const {
+               return _out_image;
+       }
+
+       Position<int> out_position () const {
+               return _out_position;
+       }
+       
+private:       
+       boost::weak_ptr<Piece> _piece;
+       boost::shared_ptr<Image> _in_image;
+       dcpomatic::Rect<double> _in_rect;
+       Time _in_from;
+       Time _in_to;
+
+       boost::shared_ptr<Image> _out_image;
+       Position<int> _out_position;
+       Time _out_from;
+       Time _out_to;
+};
index dc90e17..d4231fd 100644 (file)
@@ -53,6 +53,7 @@ sources = """
           sndfile_content.cc
           sndfile_decoder.cc
           sound_processor.cc
+          subtitle.cc
           subtitle_content.cc
           subtitle_decoder.cc
           timer.cc