summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2015-06-25 11:58:12 +0100
committerCarl Hetherington <cth@carlh.net>2015-06-25 13:36:17 +0100
commit89ee4cc6019036fa4fc0a6e07e052ffdc3b136ac (patch)
tree5a1d1b3e1e6fc4d280f1ff0f1598a37e0fea3257 /src/lib
parente08c1d30bb5e2d77339541eb7dbe7d1ca95485ab (diff)
Make player decide whether subtitles should be burnt based on
content settings rather than using the film's settings. Remove film property of burn-subtitles.
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/dcp_video.cc14
-rw-r--r--src/lib/dcp_video.h3
-rw-r--r--src/lib/encoder.cc1
-rw-r--r--src/lib/film.cc20
-rw-r--r--src/lib/film.h8
-rw-r--r--src/lib/player.cc76
-rw-r--r--src/lib/player.h12
-rw-r--r--src/lib/player_video.cc12
-rw-r--r--src/lib/player_video.h6
-rw-r--r--src/lib/transcoder.cc27
10 files changed, 89 insertions, 90 deletions
diff --git a/src/lib/dcp_video.cc b/src/lib/dcp_video.cc
index b72353d9e..3879947eb 100644
--- a/src/lib/dcp_video.cc
+++ b/src/lib/dcp_video.cc
@@ -77,14 +77,13 @@ using dcp::Size;
* @param l Log to write to.
*/
DCPVideo::DCPVideo (
- shared_ptr<const PlayerVideo> frame, int index, int dcp_fps, int bw, Resolution r, bool b, shared_ptr<Log> l
+ shared_ptr<const PlayerVideo> frame, int index, int dcp_fps, int bw, Resolution r, shared_ptr<Log> l
)
: _frame (frame)
, _index (index)
, _frames_per_second (dcp_fps)
, _j2k_bandwidth (bw)
, _resolution (r)
- , _burn_subtitles (b)
, _log (l)
{
@@ -98,7 +97,6 @@ DCPVideo::DCPVideo (shared_ptr<const PlayerVideo> frame, shared_ptr<const cxml::
_frames_per_second = node->number_child<int> ("FramesPerSecond");
_j2k_bandwidth = node->number_child<int> ("J2KBandwidth");
_resolution = Resolution (node->optional_number_child<int>("Resolution").get_value_or (RESOLUTION_2K));
- _burn_subtitles = node->bool_child ("BurnSubtitles");
}
/** J2K-encode this frame on the local host.
@@ -109,7 +107,7 @@ DCPVideo::encode_locally (dcp::NoteHandler note)
{
shared_ptr<dcp::OpenJPEGImage> xyz;
- shared_ptr<Image> image = _frame->image (AV_PIX_FMT_RGB48LE, _burn_subtitles, note);
+ shared_ptr<Image> image = _frame->image (AV_PIX_FMT_RGB48LE, note);
if (_frame->colour_conversion()) {
xyz = dcp::rgb_to_xyz (
image->data()[0],
@@ -276,7 +274,7 @@ DCPVideo::encode_remotely (ServerDescription serv)
socket->write ((uint8_t *) xml.c_str(), xml.length() + 1);
/* Send binary data */
- _frame->send_binary (socket, _burn_subtitles);
+ _frame->send_binary (socket);
/* Read the response (JPEG2000-encoded data); this blocks until the data
is ready and sent back.
@@ -296,8 +294,7 @@ DCPVideo::add_metadata (xmlpp::Element* el) const
el->add_child("FramesPerSecond")->add_child_text (raw_convert<string> (_frames_per_second));
el->add_child("J2KBandwidth")->add_child_text (raw_convert<string> (_j2k_bandwidth));
el->add_child("Resolution")->add_child_text (raw_convert<string> (int (_resolution)));
- el->add_child("BurnSubtitles")->add_child_text (_burn_subtitles ? "1" : "0");
- _frame->add_metadata (el, _burn_subtitles);
+ _frame->add_metadata (el);
}
Eyes
@@ -314,8 +311,7 @@ DCPVideo::same (shared_ptr<const DCPVideo> other) const
{
if (_frames_per_second != other->_frames_per_second ||
_j2k_bandwidth != other->_j2k_bandwidth ||
- _resolution != other->_resolution ||
- _burn_subtitles != other->_burn_subtitles) {
+ _resolution != other->_resolution) {
return false;
}
diff --git a/src/lib/dcp_video.h b/src/lib/dcp_video.h
index 97be07798..8fd668b00 100644
--- a/src/lib/dcp_video.h
+++ b/src/lib/dcp_video.h
@@ -46,7 +46,7 @@ class Data;
class DCPVideo : public boost::noncopyable
{
public:
- DCPVideo (boost::shared_ptr<const PlayerVideo>, int, int, int, Resolution, bool b, boost::shared_ptr<Log>);
+ DCPVideo (boost::shared_ptr<const PlayerVideo>, int, int, int, Resolution, boost::shared_ptr<Log>);
DCPVideo (boost::shared_ptr<const PlayerVideo>, cxml::ConstNodePtr, boost::shared_ptr<Log>);
Data encode_locally (dcp::NoteHandler note);
@@ -69,7 +69,6 @@ private:
int _frames_per_second; ///< Frames per second that we will use for the DCP
int _j2k_bandwidth; ///< J2K bandwidth to use
Resolution _resolution; ///< Resolution (2K or 4K)
- bool _burn_subtitles; ///< true to burn subtitles into the image
boost::shared_ptr<Log> _log; ///< log
};
diff --git a/src/lib/encoder.cc b/src/lib/encoder.cc
index 93e15031d..c3ad08441 100644
--- a/src/lib/encoder.cc
+++ b/src/lib/encoder.cc
@@ -236,7 +236,6 @@ Encoder::enqueue (shared_ptr<PlayerVideo> pv)
_film->video_frame_rate(),
_film->j2k_bandwidth(),
_film->resolution(),
- _film->burn_subtitles(),
_film->log()
)
));
diff --git a/src/lib/film.cc b/src/lib/film.cc
index 75dfa45eb..2ef59fe21 100644
--- a/src/lib/film.cc
+++ b/src/lib/film.cc
@@ -128,7 +128,6 @@ Film::Film (boost::filesystem::path dir, bool log)
, _three_d (false)
, _sequence_video (true)
, _interop (false)
- , _burn_subtitles (false)
, _audio_processor (0)
, _state_version (current_state_version)
, _dirty (false)
@@ -199,10 +198,6 @@ Film::video_identifier () const
s << "_S";
}
- if (_burn_subtitles) {
- s << "_B";
- }
-
if (_three_d) {
s << "_3D";
}
@@ -285,13 +280,13 @@ Film::make_dcp ()
ContentList cl = content ();
BOOST_FOREACH (shared_ptr<Content> c, cl) {
shared_ptr<SubtitleContent> sc = dynamic_pointer_cast<SubtitleContent> (c);
- if (sc && sc->has_image_subtitles() && sc->use_subtitles() && !burn_subtitles()) {
+ if (sc && sc->has_image_subtitles() && sc->use_subtitles() && !sc->burn_subtitles ()) {
must_burn = true;
}
}
if (must_burn) {
- throw EncodeError (_("this project has content with image-based subtitles, which this version of DCP-o-matic cannot include as separate DCP subtitles. To use subtitles with this project you must burn them into the image (tick the box on the DCP Video tab)."));
+ throw EncodeError (_("this project has content with image-based subtitles, which this version of DCP-o-matic cannot include as separate DCP subtitles. To use these subtitles you must burn them into the image (tick the box in the Subtitles tab)."));
}
set_isdcf_date_today ();
@@ -359,7 +354,6 @@ Film::metadata () const
root->add_child("ThreeD")->add_child_text (_three_d ? "1" : "0");
root->add_child("SequenceVideo")->add_child_text (_sequence_video ? "1" : "0");
root->add_child("Interop")->add_child_text (_interop ? "1" : "0");
- root->add_child("BurnSubtitles")->add_child_text (_burn_subtitles ? "1" : "0");
root->add_child("Signed")->add_child_text (_signed ? "1" : "0");
root->add_child("Encrypted")->add_child_text (_encrypted ? "1" : "0");
root->add_child("Key")->add_child_text (_key.hex ());
@@ -441,9 +435,6 @@ Film::read_metadata ()
_sequence_video = f.bool_child ("SequenceVideo");
_three_d = f.bool_child ("ThreeD");
_interop = f.bool_child ("Interop");
- if (_state_version >= 32) {
- _burn_subtitles = f.bool_child ("BurnSubtitles");
- }
_key = dcp::Key (f.string_child ("Key"));
if (f.optional_string_child ("AudioProcessor")) {
@@ -819,13 +810,6 @@ Film::set_interop (bool i)
}
void
-Film::set_burn_subtitles (bool b)
-{
- _burn_subtitles = b;
- signal_changed (BURN_SUBTITLES);
-}
-
-void
Film::set_audio_processor (AudioProcessor const * processor)
{
_audio_processor = processor;
diff --git a/src/lib/film.h b/src/lib/film.h
index 5e4c01c86..6c7333ec1 100644
--- a/src/lib/film.h
+++ b/src/lib/film.h
@@ -164,8 +164,6 @@ public:
THREE_D,
SEQUENCE_VIDEO,
INTEROP,
- /** The setting of _burn_subtitles has changed */
- BURN_SUBTITLES,
AUDIO_PROCESSOR,
};
@@ -238,10 +236,6 @@ public:
return _interop;
}
- bool burn_subtitles () const {
- return _burn_subtitles;
- }
-
AudioProcessor const * audio_processor () const {
return _audio_processor;
}
@@ -273,7 +267,6 @@ public:
void set_isdcf_date_today ();
void set_sequence_video (bool);
void set_interop (bool);
- void set_burn_subtitles (bool);
void set_audio_processor (AudioProcessor const * processor);
/** Emitted when some property has of the Film has changed */
@@ -334,7 +327,6 @@ private:
bool _three_d;
bool _sequence_video;
bool _interop;
- bool _burn_subtitles;
AudioProcessor const * _audio_processor;
int _state_version;
diff --git a/src/lib/player.cc b/src/lib/player.cc
index be1268f48..361f41c92 100644
--- a/src/lib/player.cc
+++ b/src/lib/player.cc
@@ -72,7 +72,7 @@ Player::Player (shared_ptr<const Film> film)
: _film (film)
, _have_valid_pieces (false)
, _ignore_video (false)
- , _burn_subtitles (film->burn_subtitles ())
+ , _always_burn_subtitles (false)
{
_film_content_changed_connection = _film->ContentChanged.connect (bind (&Player::content_changed, this, _1, _2, _3));
_film_changed_connection = _film->Changed.connect (bind (&Player::film_changed, this, _1));
@@ -322,6 +322,29 @@ Player::get_video (DCPTime time, bool accurate)
setup_pieces ();
}
+ /* Find subtitles for possible burn-in */
+
+ PlayerSubtitles ps = get_subtitles (time, DCPTime::from_frames (1, _film->video_frame_rate ()), false, true);
+
+ list<PositionImage> sub_images;
+
+ /* Image subtitles */
+ list<PositionImage> c = transform_image_subtitles (ps.image);
+ copy (c.begin(), c.end(), back_inserter (sub_images));
+
+ /* Text subtitles (rendered to an image) */
+ if (!ps.text.empty ()) {
+ list<PositionImage> s = render_subtitles (ps.text, _video_container_size);
+ copy (s.begin (), s.end (), back_inserter (sub_images));
+ }
+
+ optional<PositionImage> subtitles;
+ if (!sub_images.empty ()) {
+ subtitles = merge (sub_images);
+ }
+
+ /* Find video */
+
list<shared_ptr<Piece> > ov = overlaps<VideoContent> (
time,
time + DCPTime::from_frames (1, _film->video_frame_rate ()) - DCPTime::delta()
@@ -338,8 +361,8 @@ Player::get_video (DCPTime time, bool accurate)
shared_ptr<Piece> piece = ov.back ();
shared_ptr<VideoDecoder> decoder = dynamic_pointer_cast<VideoDecoder> (piece->decoder);
DCPOMATIC_ASSERT (decoder);
- shared_ptr<VideoContent> content = dynamic_pointer_cast<VideoContent> (piece->content);
- DCPOMATIC_ASSERT (content);
+ shared_ptr<VideoContent> video_content = dynamic_pointer_cast<VideoContent> (piece->content);
+ DCPOMATIC_ASSERT (video_content);
list<ContentVideo> content_video = decoder->get_video (dcp_to_content_video (piece, time), accurate);
if (content_video.empty ()) {
@@ -347,7 +370,7 @@ Player::get_video (DCPTime time, bool accurate)
return pvf;
}
- dcp::Size image_size = content->scale().size (content, _video_container_size, _film->frame_size ());
+ dcp::Size image_size = video_content->scale().size (video_content, _video_container_size, _film->frame_size ());
for (list<ContentVideo>::const_iterator i = content_video.begin(); i != content_video.end(); ++i) {
pvf.push_back (
@@ -355,38 +378,22 @@ Player::get_video (DCPTime time, bool accurate)
new PlayerVideo (
i->image,
content_video_to_dcp (piece, i->frame),
- content->crop (),
- content->fade (i->frame),
+ video_content->crop (),
+ video_content->fade (i->frame),
image_size,
_video_container_size,
i->eyes,
i->part,
- content->colour_conversion ()
+ video_content->colour_conversion ()
)
)
);
}
}
- /* Add subtitles (for possible burn-in) to whatever PlayerVideos we got */
-
- PlayerSubtitles ps = get_subtitles (time, DCPTime::from_frames (1, _film->video_frame_rate ()), false);
-
- list<PositionImage> sub_images;
-
- /* Image subtitles */
- list<PositionImage> c = transform_image_subtitles (ps.image);
- copy (c.begin(), c.end(), back_inserter (sub_images));
-
- /* Text subtitles (rendered to an image) */
- if (_burn_subtitles && !ps.text.empty ()) {
- list<PositionImage> s = render_subtitles (ps.text, _video_container_size);
- copy (s.begin (), s.end (), back_inserter (sub_images));
- }
-
- if (!sub_images.empty ()) {
- for (list<shared_ptr<PlayerVideo> >::const_iterator i = pvf.begin(); i != pvf.end(); ++i) {
- (*i)->set_subtitle (merge (sub_images));
+ if (subtitles) {
+ BOOST_FOREACH (shared_ptr<PlayerVideo> p, pvf) {
+ p->set_subtitle (subtitles.get ());
}
}
@@ -541,8 +548,12 @@ Player::statistics () const
return _statistics;
}
+/** @param burnt true to return only subtitles to be burnt, false to return only
+ * subtitles that should not be burnt. This parameter will be ignored if
+ * _always_burn_subtitles is true; in this case, all subtitles will be returned.
+ */
PlayerSubtitles
-Player::get_subtitles (DCPTime time, DCPTime length, bool starting)
+Player::get_subtitles (DCPTime time, DCPTime length, bool starting, bool burnt)
{
list<shared_ptr<Piece> > subs = overlaps<SubtitleContent> (time, time + length);
@@ -550,7 +561,7 @@ Player::get_subtitles (DCPTime time, DCPTime length, bool starting)
for (list<shared_ptr<Piece> >::const_iterator j = subs.begin(); j != subs.end(); ++j) {
shared_ptr<SubtitleContent> subtitle_content = dynamic_pointer_cast<SubtitleContent> ((*j)->content);
- if (!subtitle_content->use_subtitles ()) {
+ if (!subtitle_content->use_subtitles () || (!_always_burn_subtitles && (burnt != subtitle_content->burn_subtitles ()))) {
continue;
}
@@ -626,11 +637,12 @@ Player::set_ignore_video ()
_ignore_video = true;
}
-/** Set whether or not this player should burn text subtitles into the image.
- * @param burn true to burn subtitles, false to not.
+/** Set whether or not this player should always burn text subtitles into the image,
+ * regardless of the content settings.
+ * @param burn true to always burn subtitles, false to obey content settings.
*/
void
-Player::set_burn_subtitles (bool burn)
+Player::set_always_burn_subtitles (bool burn)
{
- _burn_subtitles = burn;
+ _always_burn_subtitles = burn;
}
diff --git a/src/lib/player.h b/src/lib/player.h
index f22faa7ac..6edfa49b7 100644
--- a/src/lib/player.h
+++ b/src/lib/player.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2013-2014 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2013-2015 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
@@ -87,13 +87,13 @@ public:
std::list<boost::shared_ptr<PlayerVideo> > get_video (DCPTime time, bool accurate);
boost::shared_ptr<AudioBuffers> get_audio (DCPTime time, DCPTime length, bool accurate);
- PlayerSubtitles get_subtitles (DCPTime time, DCPTime length, bool starting);
+ PlayerSubtitles get_subtitles (DCPTime time, DCPTime length, bool starting, bool burnt);
std::list<boost::shared_ptr<Font> > get_subtitle_fonts ();
void set_video_container_size (dcp::Size);
void set_ignore_video ();
void set_enable_subtitles (bool enable);
- void set_burn_subtitles (bool burn);
+ void set_always_burn_subtitles (bool burn);
PlayerStatistics const & statistics () const;
@@ -157,8 +157,10 @@ private:
/** true if the player should ignore all video; i.e. never produce any */
bool _ignore_video;
- /** true if the player should burn subtitles into the video */
- bool _burn_subtitles;
+ /** true if the player should always burn subtitles into the video regardless
+ of content settings
+ */
+ bool _always_burn_subtitles;
boost::shared_ptr<AudioProcessor> _audio_processor;
diff --git a/src/lib/player_video.cc b/src/lib/player_video.cc
index 7b6ea574e..765896a0e 100644
--- a/src/lib/player_video.cc
+++ b/src/lib/player_video.cc
@@ -89,7 +89,7 @@ PlayerVideo::set_subtitle (PositionImage image)
}
shared_ptr<Image>
-PlayerVideo::image (AVPixelFormat pixel_format, bool burn_subtitle, dcp::NoteHandler note) const
+PlayerVideo::image (AVPixelFormat pixel_format, dcp::NoteHandler note) const
{
shared_ptr<Image> im = _in->image (optional<dcp::NoteHandler> (note));
@@ -118,7 +118,7 @@ PlayerVideo::image (AVPixelFormat pixel_format, bool burn_subtitle, dcp::NoteHan
shared_ptr<Image> out = im->crop_scale_window (total_crop, _inter_size, _out_size, yuv_to_rgb, pixel_format, true);
- if (burn_subtitle && _subtitle) {
+ if (_subtitle) {
out->alpha_blend (_subtitle->image, _subtitle->position);
}
@@ -130,7 +130,7 @@ PlayerVideo::image (AVPixelFormat pixel_format, bool burn_subtitle, dcp::NoteHan
}
void
-PlayerVideo::add_metadata (xmlpp::Node* node, bool send_subtitles) const
+PlayerVideo::add_metadata (xmlpp::Node* node) const
{
node->add_child("Time")->add_child_text (raw_convert<string> (_time.get ()));
_crop.as_xml (node);
@@ -147,7 +147,7 @@ PlayerVideo::add_metadata (xmlpp::Node* node, bool send_subtitles) const
if (_colour_conversion) {
_colour_conversion.get().as_xml (node);
}
- if (send_subtitles && _subtitle) {
+ if (_subtitle) {
node->add_child ("SubtitleWidth")->add_child_text (raw_convert<string> (_subtitle->image->size().width));
node->add_child ("SubtitleHeight")->add_child_text (raw_convert<string> (_subtitle->image->size().height));
node->add_child ("SubtitleX")->add_child_text (raw_convert<string> (_subtitle->position.x));
@@ -156,10 +156,10 @@ PlayerVideo::add_metadata (xmlpp::Node* node, bool send_subtitles) const
}
void
-PlayerVideo::send_binary (shared_ptr<Socket> socket, bool send_subtitles) const
+PlayerVideo::send_binary (shared_ptr<Socket> socket) const
{
_in->send_binary (socket);
- if (send_subtitles && _subtitle) {
+ if (_subtitle) {
_subtitle->image->write_to_socket (socket);
}
}
diff --git a/src/lib/player_video.h b/src/lib/player_video.h
index 50c27bebe..0dcc2eeec 100644
--- a/src/lib/player_video.h
+++ b/src/lib/player_video.h
@@ -54,10 +54,10 @@ public:
void set_subtitle (PositionImage);
- boost::shared_ptr<Image> image (AVPixelFormat pix_fmt, bool burn_subtitle, dcp::NoteHandler note) const;
+ boost::shared_ptr<Image> image (AVPixelFormat pix_fmt, dcp::NoteHandler note) const;
- void add_metadata (xmlpp::Node* node, bool send_subtitles) const;
- void send_binary (boost::shared_ptr<Socket> socket, bool send_subtitles) const;
+ void add_metadata (xmlpp::Node* node) const;
+ void send_binary (boost::shared_ptr<Socket> socket) const;
bool has_j2k () const;
Data j2k () const;
diff --git a/src/lib/transcoder.cc b/src/lib/transcoder.cc
index 3ecc3a064..fd216c101 100644
--- a/src/lib/transcoder.cc
+++ b/src/lib/transcoder.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2015 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
@@ -24,8 +24,6 @@
* as a parameter to the constructor.
*/
-#include <iostream>
-#include <boost/signals2.hpp>
#include "transcoder.h"
#include "encoder.h"
#include "film.h"
@@ -34,6 +32,10 @@
#include "player.h"
#include "job.h"
#include "writer.h"
+#include "subtitle_content.h"
+#include <boost/signals2.hpp>
+#include <boost/foreach.hpp>
+#include <iostream>
using std::string;
using std::cout;
@@ -64,7 +66,20 @@ Transcoder::go ()
DCPTime const frame = DCPTime::from_frames (1, _film->video_frame_rate ());
DCPTime const length = _film->length ();
- if (!_film->burn_subtitles ()) {
+ int burnt_subtitles = 0;
+ int non_burnt_subtitles = 0;
+ BOOST_FOREACH (shared_ptr<const Content> c, _film->content ()) {
+ shared_ptr<const SubtitleContent> sc = dynamic_pointer_cast<const SubtitleContent> (c);
+ if (sc && sc->use_subtitles()) {
+ if (sc->burn_subtitles()) {
+ ++burnt_subtitles;
+ } else {
+ ++non_burnt_subtitles;
+ }
+ }
+ }
+
+ if (non_burnt_subtitles) {
_writer->write (_player->get_subtitle_fonts ());
}
@@ -74,8 +89,8 @@ Transcoder::go ()
_encoder->enqueue (*i);
}
_writer->write (_player->get_audio (t, frame, true));
- if (!_film->burn_subtitles ()) {
- _writer->write (_player->get_subtitles (t, frame, true));
+ if (non_burnt_subtitles) {
+ _writer->write (_player->get_subtitles (t, frame, true, false));
}
}