--- /dev/null
+/*
+ Copyright (C) 2017 Carl Hetherington <cth@carlh.net>
+
+ This file is part of DCP-o-matic.
+
+ DCP-o-matic 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.
+
+ DCP-o-matic 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 DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "active_subtitles.h"
+#include "piece.h"
+#include "subtitle_content.h"
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+
+using std::list;
+using std::pair;
+using std::make_pair;
+using boost::weak_ptr;
+using boost::shared_ptr;
+
+list<PlayerSubtitles>
+ActiveSubtitles::get (DCPTime time, bool always_burn_subtitles) const
+{
+ list<PlayerSubtitles> ps;
+
+ for (Map::const_iterator i = _data.begin(); i != _data.end(); ++i) {
+
+ shared_ptr<Piece> piece = i->first.lock ();
+ if (!piece) {
+ continue;
+ }
+
+ if (!piece->content->subtitle->use() || (!always_burn_subtitles && !piece->content->subtitle->burn())) {
+ continue;
+ }
+
+ BOOST_FOREACH (Period j, i->second) {
+ if (j.from <= time && (!j.to || j.to.get() > time)) {
+ ps.push_back (j.subs);
+ }
+ }
+ }
+
+ return ps;
+}
+
+void
+ActiveSubtitles::clear_before (DCPTime time)
+{
+ Map updated;
+ for (Map::const_iterator i = _data.begin(); i != _data.end(); ++i) {
+ list<Period> as;
+ BOOST_FOREACH (Period j, i->second) {
+ if (!j.to || j.to.get() >= time) {
+ as.push_back (j);
+ }
+ }
+ if (!as.empty ()) {
+ updated[i->first] = as;
+ }
+ }
+ _data = updated;
+}
+
+void
+ActiveSubtitles::add_from (weak_ptr<Piece> piece, PlayerSubtitles ps, DCPTime from)
+{
+ if (_data.find(piece) == _data.end()) {
+ _data[piece] = list<Period>();
+ }
+ _data[piece].push_back (Period (ps, from));
+}
+
+pair<PlayerSubtitles, DCPTime>
+ActiveSubtitles::add_to (weak_ptr<Piece> piece, DCPTime to)
+{
+ DCPOMATIC_ASSERT (_data.find(piece) != _data.end());
+
+ _data[piece].back().to = to;
+
+ BOOST_FOREACH (SubtitleString& i, _data[piece].back().subs.text) {
+ i.set_out (dcp::Time(to.seconds(), 1000));
+ }
+
+ return make_pair (_data[piece].back().subs, _data[piece].back().from);
+}
+
+bool
+ActiveSubtitles::have (weak_ptr<Piece> piece) const
+{
+ Map::const_iterator i = _data.find(piece);
+ if (i == _data.end()) {
+ return false;
+ }
+
+ return !i->second.empty();
+}
+
+void
+ActiveSubtitles::clear ()
+{
+ _data.clear ();
+}
--- /dev/null
+/*
+ Copyright (C) 2017 Carl Hetherington <cth@carlh.net>
+
+ This file is part of DCP-o-matic.
+
+ DCP-o-matic 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.
+
+ DCP-o-matic 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 DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "dcpomatic_time.h"
+#include "player_subtitles.h"
+#include <boost/noncopyable.hpp>
+#include <list>
+#include <map>
+
+class Piece;
+
+class ActiveSubtitles : public boost::noncopyable
+{
+public:
+ std::list<PlayerSubtitles> get (DCPTime time, bool always_burn_subtitles) const;
+ void clear_before (DCPTime time);
+ void clear ();
+ void add_from (boost::weak_ptr<Piece> piece, PlayerSubtitles ps, DCPTime from);
+ std::pair<PlayerSubtitles, DCPTime> add_to (boost::weak_ptr<Piece> piece, DCPTime to);
+ bool have (boost::weak_ptr<Piece> piece) const;
+
+private:
+ class Period
+ {
+ public:
+ Period () {}
+
+ Period (PlayerSubtitles s, DCPTime f)
+ : subs (s)
+ , from (f)
+ {}
+
+ PlayerSubtitles subs;
+ DCPTime from;
+ boost::optional<DCPTime> to;
+ };
+
+ typedef std::map<boost::weak_ptr<Piece>, std::list<Period> > Map;
+
+ Map _data;
+};
optional<PositionImage>
Player::subtitles_for_frame (DCPTime time) const
{
- /* Get any subtitles */
+ list<PositionImage> subtitles;
- optional<PositionImage> subtitles;
+ BOOST_FOREACH (PlayerSubtitles i, _active_subtitles.get(time, _always_burn_subtitles)) {
- for (ActiveSubtitlesMap::const_iterator i = _active_subtitles.begin(); i != _active_subtitles.end(); ++i) {
+ /* Image subtitles */
+ list<PositionImage> c = transform_image_subtitles (i.image);
+ copy (c.begin(), c.end(), back_inserter (subtitles));
- shared_ptr<Piece> sub_piece = i->first.lock ();
- if (!sub_piece) {
- continue;
- }
-
- if (!sub_piece->content->subtitle->use() || (!_always_burn_subtitles && !sub_piece->content->subtitle->burn())) {
- continue;
+ /* Text subtitles (rendered to an image) */
+ if (!i.text.empty ()) {
+ list<PositionImage> s = render_subtitles (i.text, i.fonts, _video_container_size, time);
+ copy (s.begin(), s.end(), back_inserter (subtitles));
}
+ }
- BOOST_FOREACH (ActiveSubtitles j, i->second) {
-
- if (j.from > time || (j.to && j.to.get() <= time)) {
- continue;
- }
-
- list<PositionImage> sub_images;
-
- /* Image subtitles */
- list<PositionImage> c = transform_image_subtitles (j.subs.image);
- copy (c.begin(), c.end(), back_inserter (sub_images));
-
- /* Text subtitles (rendered to an image) */
- if (!j.subs.text.empty ()) {
- list<PositionImage> s = render_subtitles (j.subs.text, j.subs.fonts, _video_container_size, time);
- copy (s.begin (), s.end (), back_inserter (sub_images));
- }
-
- if (!sub_images.empty ()) {
- subtitles = merge (sub_images);
- }
- }
+ if (subtitles.empty ()) {
+ return optional<PositionImage> ();
}
- return subtitles;
+ return merge (subtitles);
}
void
_last_video_time = time + one_video_frame ();
- /* Clear any finished _active_subtitles */
- ActiveSubtitlesMap updated;
- for (ActiveSubtitlesMap::const_iterator i = _active_subtitles.begin(); i != _active_subtitles.end(); ++i) {
- list<ActiveSubtitles> as;
- BOOST_FOREACH (ActiveSubtitles j, i->second) {
- if (!j.to || j.to.get() >= time) {
- as.push_back (j);
- }
- }
- if (!as.empty ()) {
- updated[i->first] = as;
- }
- }
- _active_subtitles = updated;
+ _active_subtitles.clear_before (time);
}
void
ps.image.push_back (subtitle.sub);
DCPTime from (content_time_to_dcp (piece, subtitle.from()));
- if (_active_subtitles.find(wp) == _active_subtitles.end()) {
- _active_subtitles[wp] = list<ActiveSubtitles>();
- }
- _active_subtitles[wp].push_back (ActiveSubtitles (ps, from));
+ _active_subtitles.add_from (wp, ps, from);
}
void
ps.add_fonts (piece->content->subtitle->fonts ());
}
- if (_active_subtitles.find(wp) == _active_subtitles.end()) {
- _active_subtitles[wp] = list<ActiveSubtitles> ();
- }
- _active_subtitles[wp].push_back (ActiveSubtitles (ps, from));
+ _active_subtitles.add_from (wp, ps, from);
}
void
Player::subtitle_stop (weak_ptr<Piece> wp, ContentTime to)
{
- if (_active_subtitles.find (wp) == _active_subtitles.end ()) {
+ if (!_active_subtitles.have (wp)) {
return;
}
DCPTime const dcp_to = content_time_to_dcp (piece, to);
- if (piece->content->subtitle->use() && !_always_burn_subtitles && !piece->content->subtitle->burn()) {
- Subtitle (_active_subtitles[wp].back().subs, DCPTimePeriod (_active_subtitles[wp].back().from, dcp_to));
- }
-
- _active_subtitles[wp].back().to = dcp_to;
+ pair<PlayerSubtitles, DCPTime> from = _active_subtitles.add_to (wp, dcp_to);
- BOOST_FOREACH (SubtitleString& i, _active_subtitles[wp].back().subs.text) {
- i.set_out (dcp::Time(dcp_to.seconds(), 1000));
+ if (piece->content->subtitle->use() && !_always_burn_subtitles && !piece->content->subtitle->burn()) {
+ Subtitle (from.first, DCPTimePeriod (from.second, dcp_to));
}
}
#define DCPOMATIC_PLAYER_H
#include "player_subtitles.h"
+#include "active_subtitles.h"
#include "film.h"
#include "content.h"
#include "position_image.h"
std::list<DCPTimePeriod> _no_video;
std::list<DCPTimePeriod> _no_audio;
- class ActiveSubtitles
- {
- public:
- ActiveSubtitles () {}
-
- ActiveSubtitles (PlayerSubtitles s, DCPTime f)
- : subs (s)
- , from (f)
- {}
-
- PlayerSubtitles subs;
- DCPTime from;
- boost::optional<DCPTime> to;
- };
- typedef std::map<boost::weak_ptr<Piece>, std::list<ActiveSubtitles> > ActiveSubtitlesMap;
- ActiveSubtitlesMap _active_subtitles;
-
+ ActiveSubtitles _active_subtitles;
boost::shared_ptr<AudioProcessor> _audio_processor;
typedef std::map<std::pair<boost::shared_ptr<const AudioContent>, AudioStreamPtr>, boost::shared_ptr<Resampler> > ResamplerMap;
ResamplerMap _resamplers;
import i18n
sources = """
+ active_subtitles.cc
analyse_audio_job.cc
atmos_mxf_content.cc
audio_analysis.cc