class Image;
class Log;
class DelayLine;
-class TimedSubtitle;
-class Subtitle;
class FilterGraph;
/** @class Decoder.
#include "log.h"
#include "ffmpeg_decoder.h"
#include "filter_graph.h"
-#include "subtitle.h"
#include "audio_buffers.h"
#include "i18n.h"
if (avcodec_decode_subtitle2 (_subtitle_codec_context, &sub, &got_subtitle, &_packet) < 0 || !got_subtitle) {
return;
}
-
+
/* Sometimes we get an empty AVSubtitle, which is used by some codecs to
indicate that the previous subtitle should stop.
*/
- if (sub.num_rects > 0) {
- shared_ptr<TimedSubtitle> ts;
- try {
- subtitle (shared_ptr<TimedSubtitle> (new TimedSubtitle (sub)));
- } catch (...) {
- /* some problem with the subtitle; we probably didn't understand it */
+ if (sub.num_rects <= 0) {
+ subtitle (shared_ptr<Image> (), dcpomatic::Rect<double> (), 0, 0);
+ return;
+ } else if (sub.num_rects > 1) {
+ throw DecodeError (_("multi-part subtitles not yet supported"));
+ }
+
+ /* Subtitle PTS in seconds (within the source, not taking into account any of the
+ source that we may have chopped off for the DCP)
+ */
+ double const packet_time = static_cast<double> (sub.pts) / AV_TIME_BASE;
+
+ /* hence start time for this sub */
+ Time const from = (packet_time + (double (sub.start_display_time) / 1e3)) * TIME_HZ;
+ Time const to = (packet_time + (double (sub.end_display_time) / 1e3)) * TIME_HZ;
+
+ AVSubtitleRect const * rect = sub.rects[0];
+
+ if (rect->type != SUBTITLE_BITMAP) {
+ throw DecodeError (_("non-bitmap subtitles not yet supported"));
+ }
+
+ shared_ptr<Image> image (new SimpleImage (PIX_FMT_RGBA, libdcp::Size (rect->w, rect->h), true));
+
+ /* Start of the first line in the subtitle */
+ uint8_t* sub_p = rect->pict.data[0];
+ /* sub_p looks up into a RGB palette which is here */
+ uint32_t const * palette = (uint32_t *) rect->pict.data[1];
+ /* Start of the output data */
+ uint32_t* out_p = (uint32_t *) image->data()[0];
+
+ for (int y = 0; y < rect->h; ++y) {
+ uint8_t* sub_line_p = sub_p;
+ uint32_t* out_line_p = out_p;
+ for (int x = 0; x < rect->w; ++x) {
+ *out_line_p++ = palette[*sub_line_p++];
}
- } else {
- subtitle (shared_ptr<TimedSubtitle> ());
+ sub_p += rect->pict.linesize[0];
+ out_p += image->stride()[0] / sizeof (uint32_t);
}
+
+ libdcp::Size const vs = _ffmpeg_content->video_size ();
+
+ subtitle (
+ image,
+ dcpomatic::Rect<double> (
+ static_cast<double> (rect->x) / vs.width,
+ static_cast<double> (rect->y) / vs.height,
+ static_cast<double> (rect->w) / vs.width,
+ static_cast<double> (rect->h) / vs.height
+ ),
+ from,
+ to
+ );
+
avsubtitle_free (&sub);
}
}
void
-Image::alpha_blend (shared_ptr<const Image> other, Position position)
+Image::alpha_blend (shared_ptr<const Image> other, Position<int> position)
{
/* Only implemented for RGBA onto RGB24 so far */
assert (_pixel_format == PIX_FMT_RGB24 && other->pixel_format() == PIX_FMT_RGBA);
}
void
-Image::copy (shared_ptr<const Image> other, Position position)
+Image::copy (shared_ptr<const Image> other, Position<int> position)
{
/* Only implemented for RGB24 onto RGB24 so far */
assert (_pixel_format == PIX_FMT_RGB24 && other->pixel_format() == PIX_FMT_RGB24);
#include <libavfilter/avfilter.h>
}
#include "util.h"
+#include "position.h"
class Scaler;
class SimpleImage;
boost::shared_ptr<Image> scale_and_convert_to_rgb (libdcp::Size, Scaler const *, bool) const;
boost::shared_ptr<Image> scale (libdcp::Size, Scaler const *, bool aligned) const;
boost::shared_ptr<Image> post_process (std::string, bool aligned) const;
- void alpha_blend (boost::shared_ptr<const Image> image, Position pos);
- void copy (boost::shared_ptr<const Image> image, Position pos);
+ void alpha_blend (boost::shared_ptr<const Image> image, Position<int> pos);
+ void copy (boost::shared_ptr<const Image> image, Position<int> pos);
boost::shared_ptr<Image> crop (Crop c, bool aligned) const;
void make_black ();
#include "image.h"
#include "ratio.h"
#include "resampler.h"
-#include "subtitle.h"
+#include "scaler.h"
using std::list;
using std::cout;
using boost::weak_ptr;
using boost::dynamic_pointer_cast;
-#define DEBUG_PLAYER 1
+//#define DEBUG_PLAYER 1
class Piece
{
Time time = content->start() + (frame * frc.factor() * TIME_HZ / _film->dcp_video_frame_rate());
- if (_film->with_subtitles ()) {
- shared_ptr<Subtitle> sub;
- if (_subtitle && _subtitle->displayed_at (time - _subtitle_content_time)) {
- sub = _subtitle->subtitle ();
- }
-
- if (sub) {
- dcpomatic::Rect const tx = subtitle_transformed_area (
- float (image_size.width) / content->video_size().width,
- float (image_size.height) / content->video_size().height,
- sub->area(), _subtitle_offset, _subtitle_scale
- );
-
- shared_ptr<Image> im = sub->image()->scale (tx.size(), _film->scaler(), true);
- work_image->alpha_blend (im, tx.position());
- }
+ 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);
}
if (image_size != _video_container_size) {
assert (image_size.height <= _video_container_size.height);
shared_ptr<Image> im (new SimpleImage (PIX_FMT_RGB24, _video_container_size, true));
im->make_black ();
- im->copy (work_image, Position ((_video_container_size.width - image_size.width) / 2, (_video_container_size.height - image_size.height) / 2));
+ im->copy (work_image, Position<int> ((_video_container_size.width - image_size.width) / 2, (_video_container_size.height - image_size.height) / 2));
work_image = im;
}
fd->Video.connect (bind (&Player::process_video, this, piece, _1, _2, _3));
fd->Audio.connect (bind (&Player::process_audio, this, piece, _1, _2));
- fd->Subtitle.connect (bind (&Player::process_subtitle, this, piece, _1));
+ fd->Subtitle.connect (bind (&Player::process_subtitle, this, piece, _1, _2, _3, _4));
piece->decoder = fd;
}
_have_valid_pieces = false;
Changed ();
+
+ } else if (p == SubtitleContentProperty::SUBTITLE_OFFSET || p == SubtitleContentProperty::SUBTITLE_SCALE) {
+ update_subtitle ();
+ Changed ();
}
}
}
void
-Player::process_subtitle (weak_ptr<Piece> weak_piece, shared_ptr<TimedSubtitle> sub)
+Player::process_subtitle (weak_ptr<Piece> weak_piece, shared_ptr<Image> image, dcpomatic::Rect<double> rect, Time from, Time to)
{
- shared_ptr<Piece> piece = weak_piece.lock ();
+ _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;
}
shared_ptr<SubtitleContent> sc = dynamic_pointer_cast<SubtitleContent> (piece->content);
assert (sc);
- _subtitle = sub;
- _subtitle_content_time = piece->content->start ();
- _subtitle_offset = sc->subtitle_offset ();
- _subtitle_scale = sc->subtitle_scale ();
+ dcpomatic::Rect<double> in_rect = _in_subtitle.rect;
+ libdcp::Size scaled_size;
+
+ in_rect.y += sc->subtitle_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 (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 ();
}
#include "audio_buffers.h"
#include "content.h"
#include "film.h"
+#include "rect.h"
class Job;
class Film;
class Piece;
class Image;
class Resampler;
-class TimedSubtitle;
/** @class Player
* @brief A class which can `play' a Playlist; emitting its audio and video.
void process_video (boost::weak_ptr<Piece>, boost::shared_ptr<const Image>, bool, VideoContent::Frame);
void process_audio (boost::weak_ptr<Piece>, boost::shared_ptr<const AudioBuffers>, AudioContent::Frame);
- void process_subtitle (boost::weak_ptr<Piece>, boost::shared_ptr<TimedSubtitle>);
+ void process_subtitle (boost::weak_ptr<Piece>, boost::shared_ptr<Image>, dcpomatic::Rect<double>, Time, Time);
void setup_pieces ();
void playlist_changed ();
void content_changed (boost::weak_ptr<Content>, int);
void emit_silence (OutputAudioFrame);
boost::shared_ptr<Resampler> resampler (boost::shared_ptr<AudioContent>);
void film_changed (Film::Property);
+ void update_subtitle ();
boost::shared_ptr<const Film> _film;
boost::shared_ptr<const Playlist> _playlist;
boost::shared_ptr<Image> _black_frame;
std::map<boost::shared_ptr<AudioContent>, boost::shared_ptr<Resampler> > _resamplers;
- boost::shared_ptr<TimedSubtitle> _subtitle;
- Time _subtitle_content_time;
- int _subtitle_offset;
- float _subtitle_scale;
+ 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;
};
#endif
--- /dev/null
+/*
+ Copyright (C) 2013 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 DVDOMATIC_POSITION_H
+#define DVDOMATIC_POSITION_H
+
+/** @struct Position
+ * @brief A position.
+ */
+template <class T>
+class Position
+{
+public:
+ Position ()
+ : x (0)
+ , y (0)
+ {}
+
+ Position (T x_, T y_)
+ : x (x_)
+ , y (y_)
+ {}
+
+ /** x coordinate */
+ T x;
+ /** y coordinate */
+ T y;
+};
+
+#endif
--- /dev/null
+/*
+ Copyright (C) 2013 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 DVDOMATIC_RECT_H
+#define DVDOMATIC_RECT_H
+
+#include "position.h"
+
+/* Put this inside a namespace as Apple put a Rect in the global namespace */
+
+namespace dcpomatic
+{
+
+/** @struct Rect
+ * @brief A rectangle.
+ */
+template <class T>
+class Rect
+{
+public:
+
+ Rect ()
+ : x (0)
+ , y (0)
+ , width (0)
+ , height (0)
+ {}
+
+ Rect (T x_, T y_, T w_, T h_)
+ : x (x_)
+ , y (y_)
+ , width (w_)
+ , height (h_)
+ {}
+
+ T x;
+ T y;
+ T width;
+ T height;
+
+ Position<T> position () const {
+ return Position<T> (x, y);
+ }
+
+ Rect<T> intersection (Rect<T> const & other) const {
+ T const tx = max (x, other.x);
+ T const ty = max (y, other.y);
+
+ return Rect (
+ tx, ty,
+ min (x + width, other.x + other.width) - tx,
+ min (y + height, other.y + other.height) - ty
+ );
+ }
+
+ bool contains (Position<T> p) const {
+ return (p.x >= x && p.x <= (x + width) && p.y >= y && p.y <= (y + height));
+ }
+};
+
+}
+
+#endif
#include "image.h"
#include "dcp_video_frame.h"
#include "config.h"
-#include "subtitle.h"
#include "i18n.h"
+++ /dev/null
-/*
- Copyright (C) 2012 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.
-
-*/
-
-/** @file src/subtitle.cc
- * @brief Representations of subtitles.
- */
-
-#include "subtitle.h"
-#include "image.h"
-#include "exceptions.h"
-
-#include "i18n.h"
-
-using boost::shared_ptr;
-using libdcp::Size;
-
-/** Construct a TimedSubtitle. This is a subtitle image, position,
- * and a range of time over which it should be shown.
- * @param sub AVSubtitle to read.
- */
-TimedSubtitle::TimedSubtitle (AVSubtitle const & sub)
-{
- assert (sub.num_rects > 0);
-
- /* Subtitle PTS in seconds (within the source, not taking into account any of the
- source that we may have chopped off for the DCP)
- */
- double const packet_time = static_cast<double> (sub.pts) / AV_TIME_BASE;
-
- /* hence start time for this sub */
- _from = (packet_time + (double (sub.start_display_time) / 1e3)) * TIME_HZ;
- _to = (packet_time + (double (sub.end_display_time) / 1e3)) * TIME_HZ;
-
- if (sub.num_rects > 1) {
- throw DecodeError (_("multi-part subtitles not yet supported"));
- }
-
- AVSubtitleRect const * rect = sub.rects[0];
-
- if (rect->type != SUBTITLE_BITMAP) {
- throw DecodeError (_("non-bitmap subtitles not yet supported"));
- }
-
- shared_ptr<Image> image (new SimpleImage (PIX_FMT_RGBA, libdcp::Size (rect->w, rect->h), true));
-
- /* Start of the first line in the subtitle */
- uint8_t* sub_p = rect->pict.data[0];
- /* sub_p looks up into a RGB palette which is here */
- uint32_t const * palette = (uint32_t *) rect->pict.data[1];
- /* Start of the output data */
- uint32_t* out_p = (uint32_t *) image->data()[0];
-
- for (int y = 0; y < rect->h; ++y) {
- uint8_t* sub_line_p = sub_p;
- uint32_t* out_line_p = out_p;
- for (int x = 0; x < rect->w; ++x) {
- *out_line_p++ = palette[*sub_line_p++];
- }
- sub_p += rect->pict.linesize[0];
- out_p += image->stride()[0] / sizeof (uint32_t);
- }
-
- _subtitle.reset (new Subtitle (Position (rect->x, rect->y), image));
-}
-
-/** @param t Time from the start of the source */
-bool
-TimedSubtitle::displayed_at (Time t) const
-{
- return t >= _from && t <= _to;
-}
-
-/** Construct a subtitle, which is an image and a position.
- * @param p Position within the (uncropped) source frame.
- * @param i Image of the subtitle (should be RGBA).
- */
-Subtitle::Subtitle (Position p, shared_ptr<Image> i)
- : _position (p)
- , _image (i)
-{
-
-}
-
-/** Given the area of a subtitle, work out the area it should
- * take up when its video frame is scaled up, and it is optionally
- * itself scaled and offset.
- * @param target_x_scale the x scaling of the video frame that the subtitle is in.
- * @param target_y_scale the y scaling of the video frame that the subtitle is in.
- * @param sub_area The area of the subtitle within the original source.
- * @param subtitle_offset y offset to apply to the subtitle position (+ve is down)
- * in the coordinate space of the source.
- * @param subtitle_scale scaling factor to apply to the subtitle image.
- */
-dcpomatic::Rect
-subtitle_transformed_area (
- float target_x_scale, float target_y_scale,
- dcpomatic::Rect sub_area, int subtitle_offset, float subtitle_scale
- )
-{
- dcpomatic::Rect tx;
-
- sub_area.y += subtitle_offset;
-
- /* We will scale the subtitle by the same amount as the video frame, and also by the additional
- subtitle_scale
- */
- tx.width = sub_area.width * target_x_scale * subtitle_scale;
- tx.height = sub_area.height * target_y_scale * 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 target_x_scale and target_y_scale; this will be
- * sub_area.x * target_x_scale and sub_area.y * target_y_scale.
- *
- * 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.
- */
-
- tx.x = rint (target_x_scale * (sub_area.x + (sub_area.width * (1 - subtitle_scale) / 2)));
- tx.y = rint (target_y_scale * (sub_area.y + (sub_area.height * (1 - subtitle_scale) / 2)));
-
- return tx;
-}
-
-/** @return area that this subtitle takes up, in the original uncropped source's coordinate space */
-dcpomatic::Rect
-Subtitle::area () const
-{
- return dcpomatic::Rect (_position.x, _position.y, _image->size().width, _image->size().height);
-}
+++ /dev/null
-/*
- Copyright (C) 2012 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.
-
-*/
-
-/** @file src/subtitle.h
- * @brief Representations of subtitles.
- */
-
-#include <list>
-#include <boost/shared_ptr.hpp>
-#include "types.h"
-
-struct AVSubtitle;
-class Image;
-
-/** A subtitle, consisting of an image and a position */
-class Subtitle
-{
-public:
- Subtitle (Position p, boost::shared_ptr<Image> i);
-
- void set_position (Position p) {
- _position = p;
- }
-
- Position position () const {
- return _position;
- }
-
- boost::shared_ptr<Image> image () const {
- return _image;
- }
-
- dcpomatic::Rect area () const;
-
-private:
- Position _position;
- boost::shared_ptr<Image> _image;
-};
-
-dcpomatic::Rect
-subtitle_transformed_area (
- float target_x_scale, float target_y_scale,
- dcpomatic::Rect sub_area, int subtitle_offset, float subtitle_scale
- );
-
-/** A Subtitle class with details of the time over which it should be shown */
-/** XXX: merge with Subtitle? */
-class TimedSubtitle
-{
-public:
- TimedSubtitle (AVSubtitle const &);
-
- bool displayed_at (Time) const;
-
- boost::shared_ptr<Subtitle> subtitle () const {
- return _subtitle;
- }
-
-private:
- /** the subtitle */
- boost::shared_ptr<Subtitle> _subtitle;
- /** display from time from the start of the content */
- Time _from;
- /** display to time from the start of the content */
- Time _to;
-};
}
void
-SubtitleContent::set_subtitle_offset (int o)
+SubtitleContent::set_subtitle_offset (double o)
{
{
boost::mutex::scoped_lock lm (_mutex);
}
void
-SubtitleContent::set_subtitle_scale (float s)
+SubtitleContent::set_subtitle_scale (double s)
{
{
boost::mutex::scoped_lock lm (_mutex);
void as_xml (xmlpp::Node *) const;
- void set_subtitle_offset (int);
- void set_subtitle_scale (float);
+ void set_subtitle_offset (double);
+ void set_subtitle_scale (double);
- int subtitle_offset () const {
+ double subtitle_offset () const {
boost::mutex::scoped_lock lm (_mutex);
return _subtitle_offset;
}
- float subtitle_scale () const {
+ double subtitle_scale () const {
boost::mutex::scoped_lock lm (_mutex);
return _subtitle_scale;
}
private:
- /** y offset for placing subtitles, in source pixels; +ve is further down
- the frame, -ve is further up.
+ /** y offset for placing subtitles, as a proportion of the container height;
+ +ve is further down the frame, -ve is further up.
*/
- int _subtitle_offset;
+ double _subtitle_offset;
/** scale factor to apply to subtitles */
- float _subtitle_scale;
+ double _subtitle_scale;
};
#endif
#include <boost/shared_ptr.hpp>
#include "subtitle_decoder.h"
-#include "subtitle.h"
using boost::shared_ptr;
/** Called by subclasses when a subtitle is ready.
- * s may be 0 to say that there is no current subtitle.
- * @param s New current subtitle, or 0.
+ * Image may be 0 to say that there is no current subtitle.
*/
void
-SubtitleDecoder::subtitle (shared_ptr<TimedSubtitle> s)
+SubtitleDecoder::subtitle (shared_ptr<Image> image, dcpomatic::Rect<double> rect, Time from, Time to)
{
- Subtitle (s);
+ Subtitle (image, rect, from, to);
}
#include <boost/signals2.hpp>
#include "decoder.h"
+#include "rect.h"
+#include "types.h"
class Film;
class TimedSubtitle;
public:
SubtitleDecoder (boost::shared_ptr<const Film>);
- boost::signals2::signal<void (boost::shared_ptr<TimedSubtitle>)> Subtitle;
+ boost::signals2::signal<void (boost::shared_ptr<Image>, dcpomatic::Rect<double>, Time, Time)> Subtitle;
protected:
- void subtitle (boost::shared_ptr<TimedSubtitle>);
+ void subtitle (boost::shared_ptr<Image>, dcpomatic::Rect<double>, Time, Time);
};
return !(a == b);
}
-
-/** @param other A Rect.
- * @return The intersection of this with `other'.
- */
-dcpomatic::Rect
-dcpomatic::Rect::intersection (Rect const & other) const
-{
- int const tx = max (x, other.x);
- int const ty = max (y, other.y);
-
- return Rect (
- tx, ty,
- min (x + width, other.x + other.width) - tx,
- min (y + height, other.y + other.height) - ty
- );
-}
-
-bool
-dcpomatic::Rect::contains (Position p) const
-{
- return (p.x >= x && p.x <= (x + width) && p.y >= y && p.y <= (y + height));
-}
extern bool operator== (Crop const & a, Crop const & b);
extern bool operator!= (Crop const & a, Crop const & b);
-/** @struct Position
- * @brief A position.
- */
-struct Position
-{
- Position ()
- : x (0)
- , y (0)
- {}
-
- Position (int x_, int y_)
- : x (x_)
- , y (y_)
- {}
-
- /** x coordinate */
- int x;
- /** y coordinate */
- int y;
-};
-
-namespace dcpomatic {
-
-/** @struct Rect
- * @brief A rectangle.
- */
-struct Rect
-{
- Rect ()
- : x (0)
- , y (0)
- , width (0)
- , height (0)
- {}
-
- Rect (int x_, int y_, int w_, int h_)
- : x (x_)
- , y (y_)
- , width (w_)
- , height (h_)
- {}
-
- int x;
- int y;
- int width;
- int height;
-
- Position position () const {
- return Position (x, y);
- }
-
- libdcp::Size size () const {
- return libdcp::Size (width, height);
- }
-
- Rect intersection (Rect const & other) const;
-
- bool contains (Position) const;
-};
-
-}
-
#endif
*/
#include "video_decoder.h"
-#include "subtitle.h"
-#include "film.h"
#include "image.h"
-#include "ratio.h"
#include "i18n.h"
sndfile_content.cc
sndfile_decoder.cc
sound_processor.cc
- subtitle.cc
subtitle_content.cc
subtitle_decoder.cc
timer.cc
wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
_subtitle_offset = new wxSpinCtrl (_subtitle_panel);
s->Add (_subtitle_offset);
- add_label_to_sizer (s, _subtitle_panel, _("pixels"), false);
+ add_label_to_sizer (s, _subtitle_panel, _("%"), false);
grid->Add (s);
}
_subtitle_stream = new wxChoice (_subtitle_panel, wxID_ANY);
grid->Add (_subtitle_stream, 1, wxEXPAND);
- _subtitle_offset->SetRange (-1024, 1024);
+ _subtitle_offset->SetRange (-100, 100);
_subtitle_scale->SetRange (1, 1000);
}
return;
}
- c->set_subtitle_offset (_subtitle_offset->GetValue ());
+ c->set_subtitle_offset (_subtitle_offset->GetValue() / 100.0);
}
void
_dcp_sizer->Layout ();
}
} else if (property == SubtitleContentProperty::SUBTITLE_OFFSET) {
- checked_set (_subtitle_offset, subtitle_content ? subtitle_content->subtitle_offset() : 0);
+ checked_set (_subtitle_offset, subtitle_content ? (subtitle_content->subtitle_offset() * 100) : 0);
} else if (property == SubtitleContentProperty::SUBTITLE_SCALE) {
checked_set (_subtitle_scale, subtitle_content ? (subtitle_content->subtitle_scale() * 100) : 100);
}
_timeline.force_redraw (bbox ());
}
- virtual dcpomatic::Rect bbox () const = 0;
+ virtual dcpomatic::Rect<int> bbox () const = 0;
protected:
virtual void do_paint (wxGraphicsContext *) = 0;
Timeline& _timeline;
private:
- dcpomatic::Rect _last_paint_bbox;
+ dcpomatic::Rect<int> _last_paint_bbox;
};
class ContentView : public View
_content_connection = c->Changed.connect (bind (&ContentView::content_changed, this, _2));
}
- dcpomatic::Rect bbox () const
+ dcpomatic::Rect<int> bbox () const
{
shared_ptr<const Film> film = _timeline.film ();
shared_ptr<const Content> content = _content.lock ();
if (!film || !content) {
- return dcpomatic::Rect ();
+ return dcpomatic::Rect<int> ();
}
- return dcpomatic::Rect (
+ return dcpomatic::Rect<int> (
time_x (content->start ()) - 8,
y_pos (_track) - 8,
content->length () * _timeline.pixels_per_time_unit() + 16,
, _y (y)
{}
- dcpomatic::Rect bbox () const
+ dcpomatic::Rect<int> bbox () const
{
- return dcpomatic::Rect (0, _y - 4, _timeline.width(), 24);
+ return dcpomatic::Rect<int> (0, _y - 4, _timeline.width(), 24);
}
void set_y (int y)
Timeline::left_down (wxMouseEvent& ev)
{
list<shared_ptr<View> >::iterator i = _views.begin();
- Position const p (ev.GetX(), ev.GetY());
+ Position<int> const p (ev.GetX(), ev.GetY());
while (i != _views.end() && !(*i)->bbox().contains (p)) {
++i;
}
}
void
-Timeline::force_redraw (dcpomatic::Rect const & r)
+Timeline::force_redraw (dcpomatic::Rect<int> const & r)
{
RefreshRect (wxRect (r.x, r.y, r.width, r.height), false);
}
#include <boost/signals2.hpp>
#include <wx/wx.h>
#include "util.h"
+#include "rect.h"
class Film;
class View;
boost::shared_ptr<const Film> film () const;
- void force_redraw (dcpomatic::Rect const &);
+ void force_redraw (dcpomatic::Rect<int> const &);
int x_offset () const {
return 8;
return _pixels_per_time_unit;
}
- Position tracks_position () const {
- return Position (8, 8);
+ Position<int> tracks_position () const {
+ return Position<int> (8, 8);
}
int tracks () const;
p += sub_image->stride()[0];
}
- shared_ptr<Subtitle> subtitle (new Subtitle (Position (50, 60), sub_image));
+// shared_ptr<Subtitle> subtitle (new Subtitle (Position<int> (50, 60), sub_image));
shared_ptr<FileLog> log (new FileLog ("build/test/client_server_test.log"));
#include "server.h"
#include "cross.h"
#include "job.h"
-#include "subtitle.h"
#include "scaler.h"
#include "ffmpeg_decoder.h"
#include "sndfile_decoder.h"