Make burnt-in subtitle outline width configurable (#940).
[dcpomatic.git] / src / lib / player.cc
index 1d3e22e2094435f0488237ebb179357a40533076..10c92c0736eb87385b5d4e0e20f88ba95c473f43 100644 (file)
@@ -52,7 +52,6 @@
 #include <dcp/reel_subtitle_asset.h>
 #include <dcp/reel_picture_asset.h>
 #include <boost/foreach.hpp>
-#include <boost/make_shared.hpp>
 #include <stdint.h>
 #include <algorithm>
 #include <iostream>
@@ -72,7 +71,6 @@ using std::map;
 using std::make_pair;
 using std::copy;
 using boost::shared_ptr;
-using boost::make_shared;
 using boost::weak_ptr;
 using boost::dynamic_pointer_cast;
 using boost::optional;
@@ -125,7 +123,7 @@ Player::setup_pieces ()
                        continue;
                }
 
-               shared_ptr<Decoder> decoder = decoder_factory (i, _film->log(), _fast);
+               shared_ptr<Decoder> decoder = decoder_factory (i, _film->log());
                FrameRateChange frc (i->active_video_frame_rate(), _film->video_frame_rate());
 
                if (!decoder) {
@@ -141,7 +139,16 @@ Player::setup_pieces ()
                        decoder->audio->set_ignore ();
                }
 
-               _pieces.push_back (make_shared<Piece> (i, decoder, frc));
+               if (decoder->audio && _fast) {
+                       decoder->audio->set_fast ();
+               }
+
+               shared_ptr<DCPDecoder> dcp = dynamic_pointer_cast<DCPDecoder> (decoder);
+               if (dcp && _play_referenced) {
+                       dcp->set_decode_referenced ();
+               }
+
+               _pieces.push_back (shared_ptr<Piece> (new Piece (i, decoder, frc)));
        }
 
        _have_valid_pieces = true;
@@ -165,26 +172,41 @@ Player::playlist_content_changed (weak_ptr<Content> w, int property, bool freque
                property == DCPContentProperty::CAN_BE_PLAYED ||
                property == SubtitleContentProperty::COLOUR ||
                property == SubtitleContentProperty::OUTLINE ||
-               property == SubtitleContentProperty::OUTLINE_COLOUR ||
-               property == FFmpegContentProperty::SUBTITLE_STREAM
+               property == SubtitleContentProperty::SHADOW ||
+               property == SubtitleContentProperty::EFFECT_COLOUR ||
+               property == FFmpegContentProperty::SUBTITLE_STREAM ||
+               property == VideoContentProperty::COLOUR_CONVERSION
                ) {
 
                _have_valid_pieces = false;
                Changed (frequent);
 
+       } else if (
+               property == SubtitleContentProperty::LINE_SPACING ||
+               property == SubtitleContentProperty::OUTLINE_WIDTH ||
+               property == SubtitleContentProperty::Y_SCALE
+               ) {
+
+               /* These changes just need the pieces' decoders to be reset.
+                  It's quite possible that other changes could be handled by
+                  this branch rather than the _have_valid_pieces = false branch
+                  above.  This would make things a lot faster.
+               */
+
+               reset_pieces ();
+               Changed (frequent);
+
        } else if (
                property == ContentProperty::VIDEO_FRAME_RATE ||
                property == SubtitleContentProperty::USE ||
                property == SubtitleContentProperty::X_OFFSET ||
                property == SubtitleContentProperty::Y_OFFSET ||
                property == SubtitleContentProperty::X_SCALE ||
-               property == SubtitleContentProperty::Y_SCALE ||
                property == SubtitleContentProperty::FONTS ||
                property == VideoContentProperty::CROP ||
                property == VideoContentProperty::SCALE ||
                property == VideoContentProperty::FADE_IN ||
-               property == VideoContentProperty::FADE_OUT ||
-               property == VideoContentProperty::COLOUR_CONVERSION
+               property == VideoContentProperty::FADE_OUT
                ) {
 
                Changed (frequent);
@@ -280,7 +302,7 @@ Player::black_player_video_frame (DCPTime time) const
 {
        return shared_ptr<PlayerVideo> (
                new PlayerVideo (
-                       make_shared<RawImageProxy> (_black_image),
+                       shared_ptr<const ImageProxy> (new RawImageProxy (_black_image)),
                        time,
                        Crop (),
                        optional<double> (),
@@ -316,7 +338,7 @@ Player::get_video (DCPTime time, bool accurate)
 
        /* Text subtitles (rendered to an image) */
        if (!ps.text.empty ()) {
-               list<PositionImage> s = render_subtitles (ps.text, ps.fonts, _video_container_size);
+               list<PositionImage> s = render_subtitles (ps.text, ps.fonts, _video_container_size, time);
                copy (s.begin (), s.end (), back_inserter (sub_images));
        }
 
@@ -415,7 +437,7 @@ Player::get_audio (DCPTime time, DCPTime length, bool accurate)
 
        Frame const length_frames = length.frames_round (_film->audio_frame_rate ());
 
-       shared_ptr<AudioBuffers> audio = make_shared<AudioBuffers> (_film->audio_channels(), length_frames);
+       shared_ptr<AudioBuffers> audio (new AudioBuffers (_film->audio_channels(), length_frames));
        audio->make_silent ();
 
        list<shared_ptr<Piece> > ov = overlaps (time, time + length, has_audio);
@@ -472,13 +494,13 @@ Player::get_audio (DCPTime time, DCPTime length, bool accurate)
 
                        /* Gain */
                        if (i->content->audio->gain() != 0) {
-                               shared_ptr<AudioBuffers> gain = make_shared<AudioBuffers> (all.audio);
+                               shared_ptr<AudioBuffers> gain (new AudioBuffers (all.audio));
                                gain->apply_gain (i->content->audio->gain ());
                                all.audio = gain;
                        }
 
                        /* Remap channels */
-                       shared_ptr<AudioBuffers> dcp_mapped = make_shared<AudioBuffers> (_film->audio_channels(), all.audio->frames());
+                       shared_ptr<AudioBuffers> dcp_mapped (new AudioBuffers (_film->audio_channels(), all.audio->frames()));
                        dcp_mapped->make_silent ();
                        AudioMapping map = j->mapping ();
                        for (int i = 0; i < map.input_channels(); ++i) {
@@ -569,7 +591,7 @@ Player::get_subtitles (DCPTime time, DCPTime length, bool starting, bool burnt,
 {
        list<shared_ptr<Piece> > subs = overlaps (time, time + length, has_subtitle);
 
-       PlayerSubtitles ps (time, length);
+       PlayerSubtitles ps (time);
 
        for (list<shared_ptr<Piece> >::const_iterator j = subs.begin(); j != subs.end(); ++j) {
                if (!(*j)->content->subtitle->use () || (!_always_burn_subtitles && (burnt != (*j)->content->subtitle->burn ()))) {
@@ -627,7 +649,7 @@ Player::get_subtitles (DCPTime time, DCPTime length, bool starting, bool burnt,
                                }
                                s.set_in (dcp::Time(content_subtitle_to_dcp (*j, ts.period().from).seconds(), 1000));
                                s.set_out (dcp::Time(content_subtitle_to_dcp (*j, ts.period().to).seconds(), 1000));
-                               ps.text.push_back (s);
+                               ps.text.push_back (SubtitleString (s, (*j)->content->subtitle->outline_width()));
                                ps.add_fonts ((*j)->content->subtitle->fonts ());
                        }
                }
@@ -708,7 +730,7 @@ Player::get_reel_assets ()
 
                scoped_ptr<DCPDecoder> decoder;
                try {
-                       decoder.reset (new DCPDecoder (j, _film->log(), false));
+                       decoder.reset (new DCPDecoder (j, _film->log()));
                } catch (...) {
                        return a;
                }
@@ -768,3 +790,11 @@ Player::overlaps (DCPTime from, DCPTime to, boost::function<bool (Content *)> va
 
        return overlaps;
 }
+
+void
+Player::reset_pieces ()
+{
+       BOOST_FOREACH (shared_ptr<Piece> i, _pieces) {
+               i->decoder->reset ();
+       }
+}