summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2014-01-15 16:21:41 +0000
committerCarl Hetherington <cth@carlh.net>2014-01-15 16:21:41 +0000
commit86214f4619476b1a4951e15f002a93743b5f7a1e (patch)
treea827550b72a7409d280d21fc6e0a820c9f940fc2 /src
parenta890bedf688f0066d70dd5e9b07cbd86736cc0b1 (diff)
Basics of subtitle rendering.
Diffstat (limited to 'src')
-rw-r--r--src/lib/ffmpeg_decoder.cc4
-rw-r--r--src/lib/player.cc67
-rw-r--r--src/lib/player.h11
-rw-r--r--src/lib/render_subtitles.cc150
-rw-r--r--src/lib/render_subtitles.h27
-rw-r--r--src/lib/subrip.cc2
-rw-r--r--src/lib/subrip.h12
-rw-r--r--src/lib/subrip_decoder.cc66
-rw-r--r--src/lib/subrip_decoder.h40
-rw-r--r--src/lib/subtitle_decoder.cc13
-rw-r--r--src/lib/subtitle_decoder.h12
-rw-r--r--src/lib/util.cc2
-rw-r--r--src/lib/wscript4
13 files changed, 378 insertions, 32 deletions
diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc
index a6f9a17c3..a051bcd12 100644
--- a/src/lib/ffmpeg_decoder.cc
+++ b/src/lib/ffmpeg_decoder.cc
@@ -546,7 +546,7 @@ FFmpegDecoder::decode_subtitle_packet ()
indicate that the previous subtitle should stop.
*/
if (sub.num_rects <= 0) {
- subtitle (shared_ptr<Image> (), dcpomatic::Rect<double> (), 0, 0);
+ image_subtitle (shared_ptr<Image> (), dcpomatic::Rect<double> (), 0, 0);
return;
} else if (sub.num_rects > 1) {
throw DecodeError (_("multi-part subtitles not yet supported"));
@@ -594,7 +594,7 @@ FFmpegDecoder::decode_subtitle_packet ()
libdcp::Size const vs = _ffmpeg_content->video_size ();
- subtitle (
+ image_subtitle (
image,
dcpomatic::Rect<double> (
static_cast<double> (rect->x) / vs.width,
diff --git a/src/lib/player.cc b/src/lib/player.cc
index ce5109733..faf783ef6 100644
--- a/src/lib/player.cc
+++ b/src/lib/player.cc
@@ -27,6 +27,8 @@
#include "sndfile_decoder.h"
#include "sndfile_content.h"
#include "subtitle_content.h"
+#include "subrip_decoder.h"
+#include "subrip_content.h"
#include "playlist.h"
#include "job.h"
#include "image.h"
@@ -34,6 +36,7 @@
#include "resampler.h"
#include "log.h"
#include "scaler.h"
+#include "render_subtitles.h"
using std::list;
using std::cout;
@@ -464,7 +467,8 @@ Player::setup_pieces ()
fd->Video.connect (bind (&Player::process_video, this, weak_ptr<Piece> (piece), _1, _2, _3, _4, 0));
fd->Audio.connect (bind (&Player::process_audio, this, weak_ptr<Piece> (piece), _1, _2));
- fd->Subtitle.connect (bind (&Player::process_subtitle, this, weak_ptr<Piece> (piece), _1, _2, _3, _4));
+ fd->ImageSubtitle.connect (bind (&Player::process_image_subtitle, this, weak_ptr<Piece> (piece), _1, _2, _3, _4));
+ fd->TextSubtitle.connect (bind (&Player::process_text_subtitle, this, weak_ptr<Piece> (piece), _1));
fd->seek (fc->time_to_content_video_frames (fc->trim_start ()), true);
piece->decoder = fd;
@@ -498,6 +502,14 @@ Player::setup_pieces ()
piece->decoder = sd;
}
+ shared_ptr<const SubRipContent> rc = dynamic_pointer_cast<const SubRipContent> (*i);
+ if (rc) {
+ shared_ptr<SubRipDecoder> sd (new SubRipDecoder (_film, rc));
+ sd->TextSubtitle.connect (bind (&Player::process_text_subtitle, this, weak_ptr<Piece> (piece), _1));
+
+ piece->decoder = sd;
+ }
+
_pieces.push_back (piece);
}
@@ -523,7 +535,8 @@ Player::content_changed (weak_ptr<Content> w, int property, bool frequent)
} else if (property == SubtitleContentProperty::SUBTITLE_OFFSET || property == SubtitleContentProperty::SUBTITLE_SCALE) {
- update_subtitle ();
+ update_subtitle_from_image ();
+ update_subtitle_from_text ();
Changed (frequent);
} else if (
@@ -628,26 +641,35 @@ 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)
+Player::process_image_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;
+ _image_subtitle.piece = weak_piece;
+ _image_subtitle.image = image;
+ _image_subtitle.rect = rect;
+ _image_subtitle.from = from;
+ _image_subtitle.to = to;
- update_subtitle ();
+ update_subtitle_from_image ();
+}
+
+void
+Player::process_text_subtitle (weak_ptr<Piece>, list<libdcp::Subtitle> s)
+{
+ _text_subtitles = s;
+
+ update_subtitle_from_text ();
}
+/** Update _out_subtitle from _image_subtitle */
void
-Player::update_subtitle ()
+Player::update_subtitle_from_image ()
{
- shared_ptr<Piece> piece = _in_subtitle.piece.lock ();
+ shared_ptr<Piece> piece = _image_subtitle.piece.lock ();
if (!piece) {
return;
}
- if (!_in_subtitle.image) {
+ if (!_image_subtitle.image) {
_out_subtitle.image.reset ();
return;
}
@@ -655,7 +677,7 @@ Player::update_subtitle ()
shared_ptr<SubtitleContent> sc = dynamic_pointer_cast<SubtitleContent> (piece->content);
assert (sc);
- dcpomatic::Rect<double> in_rect = _in_subtitle.rect;
+ dcpomatic::Rect<double> in_rect = _image_subtitle.rect;
libdcp::Size scaled_size;
in_rect.y += sc->subtitle_offset ();
@@ -679,16 +701,16 @@ Player::update_subtitle ()
_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 (
+ _out_subtitle.image = _image_subtitle.image->scale (
scaled_size,
Scaler::from_id ("bicubic"),
- _in_subtitle.image->pixel_format (),
+ _image_subtitle.image->pixel_format (),
true
);
/* XXX: hack */
- Time from = _in_subtitle.from;
- Time to = _in_subtitle.to;
+ Time from = _image_subtitle.from;
+ Time to = _image_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());
@@ -721,6 +743,17 @@ Player::repeat_last_video ()
return true;
}
+void
+Player::update_subtitle_from_text ()
+{
+ if (_text_subtitles.empty ()) {
+ _out_subtitle.image.reset ();
+ return;
+ }
+
+ render_subtitles (_text_subtitles, _video_container_size, _out_subtitle.image, _out_subtitle.position);
+}
+
PlayerImage::PlayerImage (
shared_ptr<const Image> in,
Crop crop,
diff --git a/src/lib/player.h b/src/lib/player.h
index 11cc99e77..88d05ea64 100644
--- a/src/lib/player.h
+++ b/src/lib/player.h
@@ -23,6 +23,7 @@
#include <list>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
+#include <libdcp/subtitle_asset.h>
#include "playlist.h"
#include "content.h"
#include "film.h"
@@ -120,7 +121,8 @@ private:
void process_video (boost::weak_ptr<Piece>, boost::shared_ptr<const Image>, Eyes, bool, VideoContent::Frame, Time);
void process_audio (boost::weak_ptr<Piece>, boost::shared_ptr<const AudioBuffers>, AudioContent::Frame);
- void process_subtitle (boost::weak_ptr<Piece>, boost::shared_ptr<Image>, dcpomatic::Rect<double>, Time, Time);
+ void process_image_subtitle (boost::weak_ptr<Piece>, boost::shared_ptr<Image>, dcpomatic::Rect<double>, Time, Time);
+ void process_text_subtitle (boost::weak_ptr<Piece>, std::list<libdcp::Subtitle>);
void setup_pieces ();
void playlist_changed ();
void content_changed (boost::weak_ptr<Content>, int, bool);
@@ -130,7 +132,8 @@ private:
void emit_silence (OutputAudioFrame);
boost::shared_ptr<Resampler> resampler (boost::shared_ptr<AudioContent>, bool);
void film_changed (Film::Property);
- void update_subtitle ();
+ void update_subtitle_from_image ();
+ void update_subtitle_from_text ();
boost::shared_ptr<const Film> _film;
boost::shared_ptr<const Playlist> _playlist;
@@ -159,7 +162,9 @@ private:
dcpomatic::Rect<double> rect;
Time from;
Time to;
- } _in_subtitle;
+ } _image_subtitle;
+
+ std::list<libdcp::Subtitle> _text_subtitles;
struct {
boost::shared_ptr<Image> image;
diff --git a/src/lib/render_subtitles.cc b/src/lib/render_subtitles.cc
new file mode 100644
index 000000000..630681761
--- /dev/null
+++ b/src/lib/render_subtitles.cc
@@ -0,0 +1,150 @@
+/*
+ Copyright (C) 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 <cairomm/cairomm.h>
+#include <pangomm.h>
+#include "render_subtitles.h"
+#include "types.h"
+#include "image.h"
+
+using std::list;
+using std::cout;
+using std::string;
+using std::min;
+using std::max;
+using boost::shared_ptr;
+using boost::optional;
+
+static int
+calculate_position (libdcp::VAlign v_align, double v_position, int target_height, int offset)
+{
+ switch (v_align) {
+ case libdcp::TOP:
+ return (v_position / 100) * target_height - offset;
+ case libdcp::CENTER:
+ return (0.5 + v_position / 100) * target_height - offset;
+ case libdcp::BOTTOM:
+ return (1.0 - v_position / 100) * target_height - offset;
+ }
+
+ return 0;
+}
+
+void
+render_subtitles (list<libdcp::Subtitle> subtitles, libdcp::Size target, shared_ptr<Image>& image, Position<int>& position)
+{
+ if (subtitles.empty ()) {
+ image.reset ();
+ return;
+ }
+
+ /* Estimate height that the subtitle image needs to be */
+ optional<int> top;
+ optional<int> bottom;
+ for (list<libdcp::Subtitle>::const_iterator i = subtitles.begin(); i != subtitles.end(); ++i) {
+ int const b = calculate_position (i->v_align(), i->v_position(), target.height, 0);
+ int const t = b - i->size() * target.height / (11 * 72);
+
+ top = min (top.get_value_or (t), t);
+ bottom = max (bottom.get_value_or (b), b);
+ }
+
+ top = top.get() - 32;
+ bottom = bottom.get() + 32;
+
+ image.reset (new Image (PIX_FMT_RGBA, libdcp::Size (target.width, bottom.get() - top.get ()), false));
+ image->make_black ();
+
+ Cairo::RefPtr<Cairo::ImageSurface> surface = Cairo::ImageSurface::create (
+ image->data()[0],
+ Cairo::FORMAT_ARGB32,
+ image->size().width,
+ image->size().height,
+ Cairo::ImageSurface::format_stride_for_width (Cairo::FORMAT_ARGB32, image->size().width)
+ );
+
+ Cairo::RefPtr<Cairo::Context> context = Cairo::Context::create (surface);
+ Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create (context);
+
+ layout->set_width (image->size().width * PANGO_SCALE);
+ layout->set_alignment (Pango::ALIGN_CENTER);
+
+ context->set_line_width (1);
+
+ for (list<libdcp::Subtitle>::const_iterator i = subtitles.begin(); i != subtitles.end(); ++i) {
+ string f = i->font ();
+ if (f.empty ()) {
+ f = "Arial";
+ }
+ Pango::FontDescription font (f);
+ font.set_absolute_size (i->size_in_pixels (target.height) * PANGO_SCALE);
+ if (i->italic ()) {
+ font.set_style (Pango::STYLE_ITALIC);
+ }
+ layout->set_font_description (font);
+ layout->set_text (i->text ());
+
+ /* Compute fade factor */
+ /* XXX */
+ float fade_factor = 1;
+#if 0
+ libdcp::Time now (time * 1000 / (4 * TIME_HZ));
+ libdcp::Time end_fade_up = i->in() + i->fade_up_time ();
+ libdcp::Time start_fade_down = i->out() - i->fade_down_time ();
+ if (now < end_fade_up) {
+ fade_factor = (now - i->in()) / i->fade_up_time();
+ } else if (now > start_fade_down) {
+ fade_factor = 1.0 - ((now - start_fade_down) / i->fade_down_time ());
+ }
+#endif
+
+ layout->update_from_cairo_context (context);
+
+ /* Work out position */
+
+ int const x = 0;
+ int const y = calculate_position (i->v_align (), i->v_position (), target.height, (layout->get_baseline() / PANGO_SCALE) + top.get ());
+
+ if (i->effect() == libdcp::SHADOW) {
+ /* Drop-shadow effect */
+ libdcp::Color const ec = i->effect_color ();
+ context->set_source_rgba (float(ec.r) / 255, float(ec.g) / 255, float(ec.b) / 255, fade_factor);
+ context->move_to (x + 4, y + 4);
+ layout->add_to_cairo_context (context);
+ context->fill ();
+ }
+
+ /* The actual subtitle */
+ context->move_to (x, y);
+ libdcp::Color const c = i->color ();
+ context->set_source_rgba (float(c.r) / 255, float(c.g) / 255, float(c.b) / 255, fade_factor);
+ layout->add_to_cairo_context (context);
+ context->fill ();
+
+ if (i->effect() == libdcp::BORDER) {
+ /* Border effect */
+ context->move_to (x, y);
+ libdcp::Color ec = i->effect_color ();
+ context->set_source_rgba (float(ec.r) / 255, float(ec.g) / 255, float(ec.b) / 255, fade_factor);
+ layout->add_to_cairo_context (context);
+ context->stroke ();
+ }
+ }
+}
+
diff --git a/src/lib/render_subtitles.h b/src/lib/render_subtitles.h
new file mode 100644
index 000000000..22648387e
--- /dev/null
+++ b/src/lib/render_subtitles.h
@@ -0,0 +1,27 @@
+/*
+ Copyright (C) 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 <libdcp/subtitle_asset.h>
+#include <libdcp/util.h>
+#include "position.h"
+
+class Image;
+
+void
+render_subtitles (std::list<libdcp::Subtitle>, libdcp::Size, boost::shared_ptr<Image> &, Position<int> &);
diff --git a/src/lib/subrip.cc b/src/lib/subrip.cc
index 04765532f..be2c6f666 100644
--- a/src/lib/subrip.cc
+++ b/src/lib/subrip.cc
@@ -34,7 +34,7 @@ using boost::shared_ptr;
using boost::lexical_cast;
using boost::algorithm::trim;
-SubRip::SubRip (shared_ptr<SubRipContent> content)
+SubRip::SubRip (shared_ptr<const SubRipContent> content)
{
FILE* f = fopen_boost (content->path (0), "r");
if (!f) {
diff --git a/src/lib/subrip.h b/src/lib/subrip.h
index 6451c105f..91bc7156b 100644
--- a/src/lib/subrip.h
+++ b/src/lib/subrip.h
@@ -17,6 +17,9 @@
*/
+#ifndef DCPOMATIC_SUBRIP_H
+#define DCPOMATIC_SUBRIP_H
+
#include "subrip_subtitle.h"
class SubRipContent;
@@ -28,10 +31,13 @@ class subrip_parse_test;
class SubRip
{
public:
- SubRip (boost::shared_ptr<SubRipContent>);
+ SubRip (boost::shared_ptr<const SubRipContent>);
Time length () const;
+protected:
+ std::vector<SubRipSubtitle> _subtitles;
+
private:
friend class subrip_time_test;
friend class subrip_coordinate_test;
@@ -42,6 +48,6 @@ private:
static int convert_coordinate (std::string);
static std::list<SubRipSubtitlePiece> convert_content (std::list<std::string>);
static void maybe_content (std::list<SubRipSubtitlePiece> &, SubRipSubtitlePiece &);
-
- std::list<SubRipSubtitle> _subtitles;
};
+
+#endif
diff --git a/src/lib/subrip_decoder.cc b/src/lib/subrip_decoder.cc
new file mode 100644
index 000000000..deee82847
--- /dev/null
+++ b/src/lib/subrip_decoder.cc
@@ -0,0 +1,66 @@
+/*
+ Copyright (C) 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 "subrip_decoder.h"
+
+using std::list;
+using boost::shared_ptr;
+
+SubRipDecoder::SubRipDecoder (shared_ptr<const Film> film, shared_ptr<const SubRipContent> content)
+ : Decoder (film)
+ , SubtitleDecoder (film)
+ , SubRip (content)
+ , _next (0)
+{
+
+}
+
+void
+SubRipDecoder::pass ()
+{
+ list<libdcp::Subtitle> out;
+ for (list<SubRipSubtitlePiece>::const_iterator i = _subtitles[_next].pieces.begin(); i != _subtitles[_next].pieces.end(); ++i) {
+ out.push_back (
+ libdcp::Subtitle (
+ "Arial",
+ i->italic,
+ libdcp::Color (255, 255, 255),
+ 72,
+ _subtitles[_next].from,
+ _subtitles[_next].to,
+ 0.9,
+ libdcp::BOTTOM,
+ i->text,
+ libdcp::NONE,
+ libdcp::Color (255, 255, 255),
+ 0,
+ 0
+ )
+ );
+ }
+
+ text_subtitle (out);
+ _next++;
+}
+
+bool
+SubRipDecoder::done () const
+{
+ return _next == _subtitles.size ();
+}
diff --git a/src/lib/subrip_decoder.h b/src/lib/subrip_decoder.h
new file mode 100644
index 000000000..b963bfb35
--- /dev/null
+++ b/src/lib/subrip_decoder.h
@@ -0,0 +1,40 @@
+/*
+ Copyright (C) 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.
+
+*/
+
+#ifndef DCPOMATIC_SUBRIP_DECODER_H
+#define DCPOMATIC_SUBRIP_DECODER_H
+
+#include "subtitle_decoder.h"
+#include "subrip.h"
+
+class SubRipContent;
+
+class SubRipDecoder : public SubtitleDecoder, public SubRip
+{
+public:
+ SubRipDecoder (boost::shared_ptr<const Film>, boost::shared_ptr<const SubRipContent>);
+
+ void pass ();
+ bool done () const;
+
+private:
+ size_t _next;
+};
+
+#endif
diff --git a/src/lib/subtitle_decoder.cc b/src/lib/subtitle_decoder.cc
index c06f3d718..49c04501e 100644
--- a/src/lib/subtitle_decoder.cc
+++ b/src/lib/subtitle_decoder.cc
@@ -20,6 +20,7 @@
#include <boost/shared_ptr.hpp>
#include "subtitle_decoder.h"
+using std::list;
using boost::shared_ptr;
SubtitleDecoder::SubtitleDecoder (shared_ptr<const Film> f)
@@ -29,11 +30,17 @@ SubtitleDecoder::SubtitleDecoder (shared_ptr<const Film> f)
}
-/** Called by subclasses when a subtitle is ready.
+/** Called by subclasses when an image subtitle is ready.
* Image may be 0 to say that there is no current subtitle.
*/
void
-SubtitleDecoder::subtitle (shared_ptr<Image> image, dcpomatic::Rect<double> rect, Time from, Time to)
+SubtitleDecoder::image_subtitle (shared_ptr<Image> image, dcpomatic::Rect<double> rect, Time from, Time to)
{
- Subtitle (image, rect, from, to);
+ ImageSubtitle (image, rect, from, to);
+}
+
+void
+SubtitleDecoder::text_subtitle (list<libdcp::Subtitle> s)
+{
+ TextSubtitle (s);
}
diff --git a/src/lib/subtitle_decoder.h b/src/lib/subtitle_decoder.h
index eeeadbd3f..31b03b066 100644
--- a/src/lib/subtitle_decoder.h
+++ b/src/lib/subtitle_decoder.h
@@ -17,7 +17,11 @@
*/
+#ifndef DCPOMATIC_SUBTITLE_DECODER_H
+#define DCPOMATIC_SUBTITLE_DECODER_H
+
#include <boost/signals2.hpp>
+#include <libdcp/subtitle_asset.h>
#include "decoder.h"
#include "rect.h"
#include "types.h"
@@ -31,8 +35,12 @@ class SubtitleDecoder : public virtual Decoder
public:
SubtitleDecoder (boost::shared_ptr<const Film>);
- boost::signals2::signal<void (boost::shared_ptr<Image>, dcpomatic::Rect<double>, Time, Time)> Subtitle;
+ boost::signals2::signal<void (boost::shared_ptr<Image>, dcpomatic::Rect<double>, Time, Time)> ImageSubtitle;
+ boost::signals2::signal<void (std::list<libdcp::Subtitle>)> TextSubtitle;
protected:
- void subtitle (boost::shared_ptr<Image>, dcpomatic::Rect<double>, Time, Time);
+ void image_subtitle (boost::shared_ptr<Image>, dcpomatic::Rect<double>, Time, Time);
+ void text_subtitle (std::list<libdcp::Subtitle>);
};
+
+#endif
diff --git a/src/lib/util.cc b/src/lib/util.cc
index edb202df2..4a52cd2b7 100644
--- a/src/lib/util.cc
+++ b/src/lib/util.cc
@@ -47,6 +47,7 @@
#include <openssl/md5.h>
#include <magick/MagickCore.h>
#include <magick/version.h>
+#include <pangomm/init.h>
#include <libdcp/version.h>
#include <libdcp/util.h>
#include <libdcp/signer_chain.h>
@@ -309,6 +310,7 @@ dcpomatic_setup ()
setenv ("LTDL_LIBRARY_PATH", lib.c_str (), 1);
#endif
+ Pango::init ();
libdcp::init ();
Ratio::setup_ratios ();
diff --git a/src/lib/wscript b/src/lib/wscript
index 284baa725..8a20618c0 100644
--- a/src/lib/wscript
+++ b/src/lib/wscript
@@ -41,6 +41,7 @@ sources = """
player.cc
playlist.cc
ratio.cc
+ render_subtitles.cc
resampler.cc
scp_dcp_job.cc
scaler.cc
@@ -52,6 +53,7 @@ sources = """
sound_processor.cc
subrip.cc
subrip_content.cc
+ subrip_decoder.cc
subtitle_content.cc
subtitle_decoder.cc
timer.cc
@@ -78,7 +80,7 @@ def build(bld):
AVCODEC AVUTIL AVFORMAT AVFILTER SWSCALE SWRESAMPLE
BOOST_FILESYSTEM BOOST_THREAD BOOST_DATETIME BOOST_SIGNALS2
SNDFILE OPENJPEG POSTPROC TIFF MAGICK SSH DCP CXML GLIB LZMA XML++
- CURL ZIP QUICKMAIL
+ CURL ZIP QUICKMAIL PANGOMM CAIROMM
"""
obj.source = sources + ' version.cc'