diff options
| author | Carl Hetherington <cth@carlh.net> | 2014-01-15 16:21:41 +0000 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2014-01-15 16:21:41 +0000 |
| commit | 86214f4619476b1a4951e15f002a93743b5f7a1e (patch) | |
| tree | a827550b72a7409d280d21fc6e0a820c9f940fc2 /src | |
| parent | a890bedf688f0066d70dd5e9b07cbd86736cc0b1 (diff) | |
Basics of subtitle rendering.
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib/ffmpeg_decoder.cc | 4 | ||||
| -rw-r--r-- | src/lib/player.cc | 67 | ||||
| -rw-r--r-- | src/lib/player.h | 11 | ||||
| -rw-r--r-- | src/lib/render_subtitles.cc | 150 | ||||
| -rw-r--r-- | src/lib/render_subtitles.h | 27 | ||||
| -rw-r--r-- | src/lib/subrip.cc | 2 | ||||
| -rw-r--r-- | src/lib/subrip.h | 12 | ||||
| -rw-r--r-- | src/lib/subrip_decoder.cc | 66 | ||||
| -rw-r--r-- | src/lib/subrip_decoder.h | 40 | ||||
| -rw-r--r-- | src/lib/subtitle_decoder.cc | 13 | ||||
| -rw-r--r-- | src/lib/subtitle_decoder.h | 12 | ||||
| -rw-r--r-- | src/lib/util.cc | 2 | ||||
| -rw-r--r-- | src/lib/wscript | 4 |
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' |
