virtual void pass() = 0;
virtual void seek(ContentTime time, bool accurate) = 0;
- signals2<void (ContentVideo)> Video;
- signals2<void (ContentAudio, AudioStreamPtr)> Audio;
- signals2<void (ContentTextSubtitle)> TextSubtitle;
+ signal<void (ContentVideo)> Video;
+ signal<void (ContentAudio, AudioStreamPtr)> Audio;
+ signal<void (ContentTextSubtitle)> TextSubtitle;
};
\end{lstlisting}
\subsection{Steps}
\begin{itemize}
+\item Add signals to \texttt{Player}.
+ \begin{itemize}
+ \item \texttt{signal<void (shared\_ptr<PlayerVideo>), DCPTime> Video;}
+ \item \texttt{signal<void (shared\_ptr<AudioBuffers>, DCPTime)> Audio;}
+ \item \texttt{signal<void (PlayerSubtitles, DCPTimePeriod)> Subtitle;}
+ \end{itemize}
\item Remove \texttt{get()}-based loops and replace with \texttt{pass()} and signal connections.
\item Remove \texttt{get()} and \texttt{seek()} from decoder parts; add emission signals.
\item Put \texttt{AudioMerger} back.
\item Remove \texttt{during} stuff from \texttt{SubtitleDecoder} and decoder classes that use it.
\item Rename \texttt{give} methods to \texttt{emit}.
- \item Remove \text{get} methods from \texttt{Player}; replace with \texttt{pass()} and \texttt{seek()}.
+ \item Remove \texttt{get} methods from \texttt{Player}; replace with \texttt{pass()} and \texttt{seek()}.
\end{itemize}
\end{document}
return TimePeriod<T> (from + o, to + o);
}
- boost::optional<TimePeriod<T> > overlap (TimePeriod<T> const & other) {
+ boost::optional<TimePeriod<T> > overlap (TimePeriod<T> const & other) const {
T const max_from = std::max (from, other.from);
T const min_to = std::min (to, other.to);
int
Encoder::video_frames_enqueued () const
{
- if (!_last_player_video) {
+ if (!_last_player_video_time) {
return 0;
}
- return _last_player_video->time().frames_floor (_film->video_frame_rate ());
+ return _last_player_video_time->frames_floor (_film->video_frame_rate ());
}
/** Should be called when a frame has been encoded successfully.
* for this DCP frame.
*/
void
-Encoder::encode (shared_ptr<PlayerVideo> pv)
+Encoder::encode (shared_ptr<PlayerVideo> pv, DCPTime time)
{
_waker.nudge ();
*/
rethrow ();
- Frame const position = pv->time().frames_floor(_film->video_frame_rate());
+ Frame const position = time.frames_floor(_film->video_frame_rate());
if (_writer->can_fake_write (position)) {
/* We can fake-write this frame */
}
_last_player_video = pv;
+ _last_player_video_time = time;
}
void
void begin ();
/** Called to pass a bit of video to be encoded as the next DCP frame */
- void encode (boost::shared_ptr<PlayerVideo> f);
+ void encode (boost::shared_ptr<PlayerVideo> f, DCPTime time);
/** Called when a processing run has finished */
void end ();
Waker _waker;
boost::shared_ptr<PlayerVideo> _last_player_video;
+ boost::optional<DCPTime> _last_player_video_time;
boost::signals2::scoped_connection _server_found_connection;
};
}
shared_ptr<PlayerVideo>
-Player::black_player_video_frame (DCPTime time) const
+Player::black_player_video_frame () const
{
return shared_ptr<PlayerVideo> (
new PlayerVideo (
shared_ptr<const ImageProxy> (new RawImageProxy (_black_image)),
- time,
Crop (),
optional<double> (),
_video_container_size,
optional<PositionImage> subtitles;
- BOOST_FOREACH (PlayerSubtitles i, _subtitles) {
+ for (list<pair<PlayerSubtitles, DCPTimePeriod> >::const_iterator i = _subtitles.begin(); i != _subtitles.end(); ++i) {
- if (!i.period.overlap (period)) {
+ if (!i->second.overlap (period)) {
continue;
}
list<PositionImage> sub_images;
/* Image subtitles */
- list<PositionImage> c = transform_image_subtitles (i.image);
+ list<PositionImage> c = transform_image_subtitles (i->first.image);
copy (c.begin(), c.end(), back_inserter (sub_images));
/* Text subtitles (rendered to an image) */
- if (!i.text.empty ()) {
- list<PositionImage> s = render_subtitles (i.text, i.fonts, _video_container_size, time);
+ if (!i->first.text.empty ()) {
+ list<PositionImage> s = render_subtitles (i->first.text, i->first.fonts, _video_container_size, time);
copy (s.begin (), s.end (), back_inserter (sub_images));
}
if (_last_video_time) {
for (DCPTime i = _last_video_time.get(); i < time; i += DCPTime::from_frames (1, _film->video_frame_rate())) {
if (_playlist->video_content_at(i) && _last_video) {
- Video (_last_video->clone (i));
+ Video (shared_ptr<PlayerVideo> (new PlayerVideo (*_last_video)), i);
} else {
- Video (black_player_video_frame (i));
+ Video (black_player_video_frame (), i);
}
}
}
_last_video.reset (
new PlayerVideo (
video.image,
- time,
piece->content->video->crop (),
piece->content->video->fade (video.frame.index()),
piece->content->video->scale().size (
_last_video_time = time;
cout << "Video @ " << to_string(_last_video_time.get()) << "\n";
- Video (_last_video);
+ Video (_last_video, *_last_video_time);
/* Discard any subtitles we no longer need */
- for (list<PlayerSubtitles>::iterator i = _subtitles.begin (); i != _subtitles.end(); ) {
- list<PlayerSubtitles>::iterator tmp = i;
+ for (list<pair<PlayerSubtitles, DCPTimePeriod> >::iterator i = _subtitles.begin (); i != _subtitles.end(); ) {
+ list<pair<PlayerSubtitles, DCPTimePeriod> >::iterator tmp = i;
++tmp;
- if (i->period.to < time) {
+ if (i->second.to < time) {
_subtitles.erase (i);
}
PlayerSubtitles ps;
ps.image.push_back (subtitle.sub);
- ps.period = DCPTimePeriod (content_time_to_dcp (piece, subtitle.period().from), content_time_to_dcp (piece, subtitle.period().to));
+ DCPTimePeriod period (content_time_to_dcp (piece, subtitle.period().from), content_time_to_dcp (piece, subtitle.period().to));
if (piece->content->subtitle->use() && (piece->content->subtitle->burn() || _always_burn_subtitles)) {
- _subtitles.push_back (ps);
+ _subtitles.push_back (make_pair (ps, period));
} else {
- Subtitle (ps);
+ Subtitle (ps, period);
}
}
}
PlayerSubtitles ps;
+ DCPTimePeriod const period (content_time_to_dcp (piece, subtitle.period().from), content_time_to_dcp (piece, subtitle.period().to));
BOOST_FOREACH (dcp::SubtitleString s, subtitle.subs) {
s.set_h_position (s.h_position() + piece->content->subtitle->x_offset ());
s.set_aspect_adjust (xs / ys);
}
- ps.period = DCPTimePeriod (content_time_to_dcp (piece, subtitle.period().from), content_time_to_dcp (piece, subtitle.period().to));
-
- s.set_in (dcp::Time(ps.period.from.seconds(), 1000));
- s.set_out (dcp::Time(ps.period.to.seconds(), 1000));
+ s.set_in (dcp::Time(period.from.seconds(), 1000));
+ s.set_out (dcp::Time(period.to.seconds(), 1000));
ps.text.push_back (SubtitleString (s, piece->content->subtitle->outline_width()));
ps.add_fonts (piece->content->subtitle->fonts ());
}
if (piece->content->subtitle->use() && (piece->content->subtitle->burn() || _always_burn_subtitles)) {
- _subtitles.push_back (ps);
+ _subtitles.push_back (make_pair (ps, period));
} else {
- Subtitle (ps);
+ Subtitle (ps, period);
}
}
*/
boost::signals2::signal<void (bool)> Changed;
- boost::signals2::signal<void (boost::shared_ptr<PlayerVideo>)> Video;
+ boost::signals2::signal<void (boost::shared_ptr<PlayerVideo>, DCPTime)> Video;
boost::signals2::signal<void (boost::shared_ptr<AudioBuffers>, DCPTime)> Audio;
- boost::signals2::signal<void (PlayerSubtitles)> Subtitle;
+ boost::signals2::signal<void (PlayerSubtitles, DCPTimePeriod)> Subtitle;
private:
friend class PlayerWrapper;
DCPTime resampled_audio_to_dcp (boost::shared_ptr<const Piece> piece, Frame f) const;
ContentTime dcp_to_content_time (boost::shared_ptr<const Piece> piece, DCPTime t) const;
DCPTime content_time_to_dcp (boost::shared_ptr<const Piece> piece, ContentTime t) const;
- boost::shared_ptr<PlayerVideo> black_player_video_frame (DCPTime) const;
+ boost::shared_ptr<PlayerVideo> black_player_video_frame () const;
std::list<boost::shared_ptr<Piece> > overlaps (DCPTime from, DCPTime to, boost::function<bool (Content *)> valid);
void video (boost::weak_ptr<Piece>, ContentVideo);
void audio (boost::weak_ptr<Piece>, AudioStreamPtr, ContentAudio);
AudioMerger _audio_merger;
DCPTime _last_audio_time;
- std::list<PlayerSubtitles> _subtitles;
+ std::list<std::pair<PlayerSubtitles, DCPTimePeriod> > _subtitles;
boost::shared_ptr<AudioProcessor> _audio_processor;
void add_fonts (std::list<boost::shared_ptr<Font> > fonts_);
std::list<boost::shared_ptr<Font> > fonts;
- DCPTimePeriod period;
-
/** ImageSubtitles, with their rectangles transformed as specified by their content */
std::list<ImageSubtitle> image;
std::list<SubtitleString> text;
PlayerVideo::PlayerVideo (
shared_ptr<const ImageProxy> in,
- DCPTime time,
Crop crop,
boost::optional<double> fade,
dcp::Size inter_size,
optional<ColourConversion> colour_conversion
)
: _in (in)
- , _time (time)
, _crop (crop)
, _fade (fade)
, _inter_size (inter_size)
PlayerVideo::PlayerVideo (shared_ptr<cxml::Node> node, shared_ptr<Socket> socket)
{
- _time = DCPTime (node->number_child<DCPTime::Type> ("Time"));
_crop = Crop (node);
_fade = node->optional_number_child<double> ("Fade");
void
PlayerVideo::add_metadata (xmlpp::Node* node) const
{
- node->add_child("Time")->add_child_text (raw_convert<string> (_time.get ()));
_crop.as_xml (node);
if (_fade) {
node->add_child("Fade")->add_child_text (raw_convert<string> (_fade.get ()));
return Position<int> ((_out_size.width - _inter_size.width) / 2, (_out_size.height - _inter_size.height) / 2);
}
-/** @return true if this PlayerVideo is definitely the same as another
- * (apart from _time), false if it is probably not
- */
+/** @return true if this PlayerVideo is definitely the same as another, false if it is probably not */
bool
PlayerVideo::same (shared_ptr<const PlayerVideo> other) const
{
{
return p == AV_PIX_FMT_XYZ12LE ? AV_PIX_FMT_XYZ12LE : AV_PIX_FMT_RGB48LE;
}
-
-shared_ptr<PlayerVideo>
-PlayerVideo::clone (DCPTime time) const
-{
- shared_ptr<PlayerVideo> c (new PlayerVideo (*this));
- c->_time = time;
- return c;
-}
public:
PlayerVideo (
boost::shared_ptr<const ImageProxy>,
- DCPTime,
Crop,
boost::optional<double>,
dcp::Size,
bool has_j2k () const;
dcp::Data j2k () const;
- DCPTime time () const {
- return _time;
- }
-
Eyes eyes () const {
return _eyes;
}
bool same (boost::shared_ptr<const PlayerVideo> other) const;
- boost::shared_ptr<PlayerVideo> clone (DCPTime time) const;
-
private:
boost::shared_ptr<const ImageProxy> _in;
- DCPTime _time;
Crop _crop;
boost::optional<double> _fade;
dcp::Size _inter_size;
, _finishing (false)
, _non_burnt_subtitles (false)
{
- _player->Video.connect (bind (&Transcoder::video, this, _1));
+ _player->Video.connect (bind (&Transcoder::video, this, _1, _2));
_player->Audio.connect (bind (&Transcoder::audio, this, _1, _2));
- _player->Subtitle.connect (bind (&Transcoder::subtitle, this, _1));
+ _player->Subtitle.connect (bind (&Transcoder::subtitle, this, _1, _2));
BOOST_FOREACH (shared_ptr<const Content> c, _film->content ()) {
if (c->subtitle && c->subtitle->use() && !c->subtitle->burn()) {
}
void
-Transcoder::video (shared_ptr<PlayerVideo> data)
+Transcoder::video (shared_ptr<PlayerVideo> data, DCPTime time)
{
if (!_film->three_d() && data->eyes() == EYES_LEFT) {
/* Use left-eye images for both eyes */
data->set_eyes (EYES_BOTH);
}
- _encoder->encode (data);
+ _encoder->encode (data, time);
}
void
}
void
-Transcoder::subtitle (PlayerSubtitles data)
+Transcoder::subtitle (PlayerSubtitles data, DCPTimePeriod period)
{
if (_non_burnt_subtitles) {
- _writer->write (data);
+ _writer->write (data, period);
}
}
private:
- void video (boost::shared_ptr<PlayerVideo>);
+ void video (boost::shared_ptr<PlayerVideo>, DCPTime);
void audio (boost::shared_ptr<AudioBuffers>, DCPTime);
- void subtitle (PlayerSubtitles);
+ void subtitle (PlayerSubtitles, DCPTimePeriod);
boost::shared_ptr<const Film> _film;
boost::weak_ptr<Job> _job;
}
void
-Writer::write (PlayerSubtitles subs)
+Writer::write (PlayerSubtitles subs, DCPTimePeriod period)
{
if (subs.text.empty ()) {
return;
}
- if (_subtitle_reel->period().to <= subs.period.from) {
+ if (_subtitle_reel->period().to <= period.from) {
++_subtitle_reel;
}
bool can_repeat (Frame) const;
void repeat (Frame, Eyes);
void write (boost::shared_ptr<const AudioBuffers>);
- void write (PlayerSubtitles subs);
+ void write (PlayerSubtitles subs, DCPTimePeriod period);
void write (std::list<boost::shared_ptr<Font> > fonts);
void write (ReferencedReelAsset asset);
void finish ();
_film->Changed.connect (boost::bind (&FilmViewer::film_changed, this, _1));
_player->Changed.connect (boost::bind (&FilmViewer::player_changed, this, _1));
- _player->Video.connect (boost::bind (&FilmViewer::video, this, _1));
+ _player->Video.connect (boost::bind (&FilmViewer::video, this, _1, _2));
calculate_sizes ();
refresh ();
}
void
-FilmViewer::video (shared_ptr<PlayerVideo> pv)
+FilmViewer::video (shared_ptr<PlayerVideo> pv, DCPTime time)
{
if (!_player) {
return;
ImageChanged (pv);
- _position = pv->time ();
+ _position = time;
_inter_position = pv->inter_position ();
_inter_size = pv->inter_size ();
void player_changed (bool);
void update_position_label ();
void update_position_slider ();
- void video (boost::shared_ptr<PlayerVideo>);
+ void video (boost::shared_ptr<PlayerVideo>, DCPTime time);
void get ();
void seek (DCPTime t, bool accurate);
void refresh_panel ();
shared_ptr<PlayerVideo> pvf (
new PlayerVideo (
shared_ptr<ImageProxy> (new RawImageProxy (image)),
- DCPTime (),
Crop (),
optional<double> (),
dcp::Size (1998, 1080),
shared_ptr<PlayerVideo> pvf (
new PlayerVideo (
shared_ptr<ImageProxy> (new RawImageProxy (image)),
- DCPTime (),
Crop (),
optional<double> (),
dcp::Size (1998, 1080),
shared_ptr<PlayerVideo> raw_pvf (
new PlayerVideo (
shared_ptr<ImageProxy> (new RawImageProxy (image)),
- DCPTime (),
Crop (),
optional<double> (),
dcp::Size (1998, 1080),
shared_ptr<PlayerVideo> j2k_pvf (
new PlayerVideo (
shared_ptr<ImageProxy> (new J2KImageProxy (raw_locally_encoded, dcp::Size (1998, 1080), AV_PIX_FMT_XYZ12LE)),
- DCPTime (),
Crop (),
optional<double> (),
dcp::Size (1998, 1080),