summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2014-07-10 11:27:26 +0100
committerCarl Hetherington <cth@carlh.net>2014-07-10 11:27:26 +0100
commitbde76c3341775bd02da59932d285e14eade64ae0 (patch)
tree7f0922faf1e64e74c029037afe8857c63f25e51a /src
parentc7b68d663ac3db10dcf2bfcc11009dce46f820dc (diff)
Basics of DCP subtitle import.
Diffstat (limited to 'src')
-rw-r--r--src/lib/content_factory.cc5
-rw-r--r--src/lib/dcp_content.cc6
-rw-r--r--src/lib/dcp_content.h1
-rw-r--r--src/lib/dcp_subtitle_content.cc87
-rw-r--r--src/lib/dcp_subtitle_content.h37
-rw-r--r--src/lib/dcp_subtitle_decoder.cc82
-rw-r--r--src/lib/dcp_subtitle_decoder.h38
-rw-r--r--src/lib/player.cc9
-rw-r--r--src/lib/subrip_content.cc14
-rw-r--r--src/lib/subrip_content.h1
-rw-r--r--src/lib/subrip_decoder.cc2
-rw-r--r--src/lib/subtitle_content.cc13
-rw-r--r--src/lib/subtitle_content.h1
-rw-r--r--src/lib/wscript2
-rw-r--r--src/wx/subtitle_panel.cc26
-rw-r--r--src/wx/subtitle_view.cc5
-rw-r--r--src/wx/subtitle_view.h4
17 files changed, 308 insertions, 25 deletions
diff --git a/src/lib/content_factory.cc b/src/lib/content_factory.cc
index 73e333816..16340adb4 100644
--- a/src/lib/content_factory.cc
+++ b/src/lib/content_factory.cc
@@ -27,6 +27,7 @@
#include "sndfile_content.h"
#include "subrip_content.h"
#include "dcp_content.h"
+#include "dcp_subtitle_content.h"
#include "util.h"
using std::string;
@@ -57,6 +58,8 @@ content_factory (shared_ptr<const Film> film, cxml::NodePtr node, int version, l
content.reset (new SubRipContent (film, node, version));
} else if (type == "DCP") {
content.reset (new DCPContent (film, node, version));
+ } else if (type == "DCPSubtitle") {
+ content.reset (new DCPSubtitleContent (film, node, version));
}
return content;
@@ -81,6 +84,8 @@ content_factory (shared_ptr<const Film> film, boost::filesystem::path path)
content.reset (new SndfileContent (film, path));
} else if (ext == ".srt") {
content.reset (new SubRipContent (film, path));
+ } else if (ext == ".xml") {
+ content.reset (new DCPSubtitleContent (film, path));
} else {
content.reset (new FFmpegContent (film, path));
}
diff --git a/src/lib/dcp_content.cc b/src/lib/dcp_content.cc
index 8ecd52f24..b1d0d9a37 100644
--- a/src/lib/dcp_content.cc
+++ b/src/lib/dcp_content.cc
@@ -110,3 +110,9 @@ DCPContent::full_length () const
assert (film);
return DCPTime (video_length (), FrameRateChange (video_frame_rate (), film->video_frame_rate ()));
}
+
+string
+DCPContent::identifier () const
+{
+ return SubtitleContent::identifier ();
+}
diff --git a/src/lib/dcp_content.h b/src/lib/dcp_content.h
index a6ef97400..7ead80ecb 100644
--- a/src/lib/dcp_content.h
+++ b/src/lib/dcp_content.h
@@ -38,6 +38,7 @@ public:
std::string summary () const;
std::string technical_summary () const;
void as_xml (xmlpp::Node *) const;
+ std::string identifier () const;
boost::filesystem::path directory () const {
boost::mutex::scoped_lock lm (_mutex);
diff --git a/src/lib/dcp_subtitle_content.cc b/src/lib/dcp_subtitle_content.cc
new file mode 100644
index 000000000..e9998dd2a
--- /dev/null
+++ b/src/lib/dcp_subtitle_content.cc
@@ -0,0 +1,87 @@
+/*
+ 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 <dcp/subtitle_content.h>
+#include <dcp/raw_convert.h>
+#include "dcp_subtitle_content.h"
+
+#include "i18n.h"
+
+using std::string;
+using boost::shared_ptr;
+using dcp::raw_convert;
+
+DCPSubtitleContent::DCPSubtitleContent (shared_ptr<const Film> film, boost::filesystem::path path)
+ : Content (film, path)
+ , SubtitleContent (film, path)
+{
+
+}
+
+DCPSubtitleContent::DCPSubtitleContent (shared_ptr<const Film> film, cxml::ConstNodePtr node, int version)
+ : Content (film, node)
+ , SubtitleContent (film, node, version)
+ , _length (node->number_child<DCPTime::Type> ("Length"))
+{
+
+}
+
+void
+DCPSubtitleContent::examine (shared_ptr<Job> job)
+{
+ Content::examine (job);
+ dcp::SubtitleContent sc (path (0), false);
+ _length = DCPTime::from_frames (sc.intrinsic_duration(), sc.edit_rate().as_float ());
+}
+
+DCPTime
+DCPSubtitleContent::full_length () const
+{
+ /* XXX: this assumes that the timing of the subtitle file is appropriate
+ for the DCP's frame rate.
+ */
+ return _length;
+}
+
+string
+DCPSubtitleContent::summary () const
+{
+ return path_summary() + " " + _("[subtitles]");
+}
+
+string
+DCPSubtitleContent::technical_summary () const
+{
+ return Content::technical_summary() + " - " + _("DCP XML subtitles");
+}
+
+string
+DCPSubtitleContent::information () const
+{
+
+}
+
+void
+DCPSubtitleContent::as_xml (xmlpp::Node* node) const
+{
+ node->add_child("Type")->add_child_text ("DCPSubtitle");
+ Content::as_xml (node);
+ SubtitleContent::as_xml (node);
+ node->add_child("Length")->add_child_text (raw_convert<string> (_length.get ()));
+}
diff --git a/src/lib/dcp_subtitle_content.h b/src/lib/dcp_subtitle_content.h
new file mode 100644
index 000000000..79338c1af
--- /dev/null
+++ b/src/lib/dcp_subtitle_content.h
@@ -0,0 +1,37 @@
+/*
+ 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 "subtitle_content.h"
+
+class DCPSubtitleContent : public SubtitleContent
+{
+public:
+ DCPSubtitleContent (boost::shared_ptr<const Film>, boost::filesystem::path);
+ DCPSubtitleContent (boost::shared_ptr<const Film>, cxml::ConstNodePtr, int);
+
+ void examine (boost::shared_ptr<Job>);
+ std::string summary () const;
+ std::string technical_summary () const;
+ std::string information () const;
+ void as_xml (xmlpp::Node *) const;
+ DCPTime full_length () const;
+
+private:
+ DCPTime _length;
+};
diff --git a/src/lib/dcp_subtitle_decoder.cc b/src/lib/dcp_subtitle_decoder.cc
new file mode 100644
index 000000000..c1f0ab500
--- /dev/null
+++ b/src/lib/dcp_subtitle_decoder.cc
@@ -0,0 +1,82 @@
+/*
+ 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 <dcp/subtitle_content.h>
+#include "dcp_subtitle_decoder.h"
+#include "dcp_subtitle_content.h"
+
+using std::list;
+using boost::shared_ptr;
+
+DCPSubtitleDecoder::DCPSubtitleDecoder (shared_ptr<const DCPSubtitleContent> content)
+ : SubtitleDecoder (content)
+{
+ dcp::SubtitleContent c (content->path (0), false);
+ _subtitles = c.subtitles ();
+ _next = _subtitles.begin ();
+}
+
+void
+DCPSubtitleDecoder::seek (ContentTime time, bool accurate)
+{
+ SubtitleDecoder::seek (time, accurate);
+
+ _next = _subtitles.begin ();
+ list<dcp::SubtitleString>::const_iterator i = _subtitles.begin ();
+ while (i != _subtitles.end() && ContentTime::from_seconds (_next->in().to_seconds()) < time) {
+ ++i;
+ }
+}
+
+bool
+DCPSubtitleDecoder::pass ()
+{
+ if (_next == _subtitles.end ()) {
+ return true;
+ }
+
+ list<dcp::SubtitleString> s;
+ s.push_back (*_next);
+ text_subtitle (s);
+ ++_next;
+
+ return false;
+}
+
+list<ContentTimePeriod>
+DCPSubtitleDecoder::subtitles_during (ContentTimePeriod p, bool starting) const
+{
+ /* XXX: inefficient */
+
+ list<ContentTimePeriod> d;
+
+ for (list<dcp::SubtitleString>::const_iterator i = _subtitles.begin(); i != _subtitles.end(); ++i) {
+ ContentTimePeriod period (
+ ContentTime::from_seconds (i->in().to_seconds ()),
+ ContentTime::from_seconds (i->out().to_seconds ())
+ );
+
+ if ((starting && p.contains (period.from)) || (!starting && p.overlaps (period))) {
+ d.push_back (period);
+ }
+ }
+
+ return d;
+}
+
diff --git a/src/lib/dcp_subtitle_decoder.h b/src/lib/dcp_subtitle_decoder.h
new file mode 100644
index 000000000..070562458
--- /dev/null
+++ b/src/lib/dcp_subtitle_decoder.h
@@ -0,0 +1,38 @@
+/*
+ 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 "subtitle_decoder.h"
+
+class DCPSubtitleContent;
+
+class DCPSubtitleDecoder : public SubtitleDecoder
+{
+public:
+ DCPSubtitleDecoder (boost::shared_ptr<const DCPSubtitleContent>);
+
+protected:
+ void seek (ContentTime time, bool accurate);
+ bool pass ();
+
+private:
+ std::list<ContentTimePeriod> subtitles_during (ContentTimePeriod, bool starting) const;
+
+ std::list<dcp::SubtitleString> _subtitles;
+ std::list<dcp::SubtitleString>::const_iterator _next;
+};
diff --git a/src/lib/player.cc b/src/lib/player.cc
index c855471b4..9e14b65b3 100644
--- a/src/lib/player.cc
+++ b/src/lib/player.cc
@@ -45,6 +45,8 @@
#include "frame_rate_change.h"
#include "dcp_content.h"
#include "dcp_decoder.h"
+#include "dcp_subtitle_content.h"
+#include "dcp_subtitle_decoder.h"
#define LOG_GENERAL(...) _film->log()->log (String::compose (__VA_ARGS__), Log::TYPE_GENERAL);
@@ -160,6 +162,13 @@ Player::setup_pieces ()
frc = best_overlap_frc;
}
+ /* DCPSubtitleContent */
+ shared_ptr<const DCPSubtitleContent> dsc = dynamic_pointer_cast<const DCPSubtitleContent> (*i);
+ if (dsc) {
+ decoder.reset (new DCPSubtitleDecoder (dsc));
+ frc = best_overlap_frc;
+ }
+
_pieces.push_back (shared_ptr<Piece> (new Piece (*i, decoder, frc.get ())));
}
diff --git a/src/lib/subrip_content.cc b/src/lib/subrip_content.cc
index 455bd1e8f..c60b05d50 100644
--- a/src/lib/subrip_content.cc
+++ b/src/lib/subrip_content.cc
@@ -77,7 +77,7 @@ SubRipContent::technical_summary () const
string
SubRipContent::information () const
{
-
+
}
void
@@ -97,15 +97,3 @@ SubRipContent::full_length () const
*/
return _length;
}
-
-string
-SubRipContent::identifier () const
-{
- stringstream s;
- s << Content::identifier()
- << "_" << raw_convert<string> (subtitle_scale())
- << "_" << raw_convert<string> (subtitle_x_offset())
- << "_" << raw_convert<string> (subtitle_y_offset());
-
- return s.str ();
-}
diff --git a/src/lib/subrip_content.h b/src/lib/subrip_content.h
index 5688f81d5..7da6e71f7 100644
--- a/src/lib/subrip_content.h
+++ b/src/lib/subrip_content.h
@@ -35,7 +35,6 @@ public:
std::string information () const;
void as_xml (xmlpp::Node *) const;
DCPTime full_length () const;
- std::string identifier () const;
private:
DCPTime _length;
diff --git a/src/lib/subrip_decoder.cc b/src/lib/subrip_decoder.cc
index 4bdf06e7c..e2bdc347b 100644
--- a/src/lib/subrip_decoder.cc
+++ b/src/lib/subrip_decoder.cc
@@ -75,7 +75,7 @@ SubRipDecoder::pass ()
}
text_subtitle (out);
- _next++;
+ ++_next;
return false;
}
diff --git a/src/lib/subtitle_content.cc b/src/lib/subtitle_content.cc
index 88e48b420..8c94a94b9 100644
--- a/src/lib/subtitle_content.cc
+++ b/src/lib/subtitle_content.cc
@@ -26,6 +26,7 @@
#include "i18n.h"
using std::string;
+using std::stringstream;
using std::vector;
using std::cout;
using boost::shared_ptr;
@@ -155,3 +156,15 @@ SubtitleContent::set_subtitle_scale (double s)
}
signal_changed (SubtitleContentProperty::SUBTITLE_SCALE);
}
+
+string
+SubtitleContent::identifier () const
+{
+ stringstream s;
+ s << Content::identifier()
+ << "_" << raw_convert<string> (subtitle_scale())
+ << "_" << raw_convert<string> (subtitle_x_offset())
+ << "_" << raw_convert<string> (subtitle_y_offset());
+
+ return s.str ();
+}
diff --git a/src/lib/subtitle_content.h b/src/lib/subtitle_content.h
index f46a87c15..1425c33cd 100644
--- a/src/lib/subtitle_content.h
+++ b/src/lib/subtitle_content.h
@@ -40,6 +40,7 @@ public:
SubtitleContent (boost::shared_ptr<const Film>, std::vector<boost::shared_ptr<Content> >);
void as_xml (xmlpp::Node *) const;
+ std::string identifier () const;
void set_subtitle_use (bool);
void set_subtitle_x_offset (double);
diff --git a/src/lib/wscript b/src/lib/wscript
index ae6e0b800..d96bb7f96 100644
--- a/src/lib/wscript
+++ b/src/lib/wscript
@@ -19,6 +19,8 @@ sources = """
dcp_content_type.cc
dcp_decoder.cc
dcp_examiner.cc
+ dcp_subtitle_content.cc
+ dcp_subtitle_decoder.cc
dcp_video.cc
dcpomatic_time.cc
dolby_cp750.cc
diff --git a/src/wx/subtitle_panel.cc b/src/wx/subtitle_panel.cc
index adbd0f32e..5cfd29504 100644
--- a/src/wx/subtitle_panel.cc
+++ b/src/wx/subtitle_panel.cc
@@ -22,6 +22,9 @@
#include "lib/ffmpeg_content.h"
#include "lib/subrip_content.h"
#include "lib/ffmpeg_subtitle_stream.h"
+#include "lib/dcp_subtitle_content.h"
+#include "lib/subrip_decoder.h"
+#include "lib/dcp_subtitle_decoder.h"
#include "subtitle_panel.h"
#include "film_editor.h"
#include "wx_util.h"
@@ -156,18 +159,19 @@ SubtitlePanel::setup_sensitivity ()
{
int any_subs = 0;
int ffmpeg_subs = 0;
- int subrip_subs = 0;
+ int subrip_or_dcp_subs = 0;
SubtitleContentList c = _editor->selected_subtitle_content ();
for (SubtitleContentList::const_iterator i = c.begin(); i != c.end(); ++i) {
shared_ptr<const FFmpegContent> fc = boost::dynamic_pointer_cast<const FFmpegContent> (*i);
shared_ptr<const SubRipContent> sc = boost::dynamic_pointer_cast<const SubRipContent> (*i);
+ shared_ptr<const DCPSubtitleContent> dsc = boost::dynamic_pointer_cast<const DCPSubtitleContent> (*i);
if (fc) {
if (!fc->subtitle_streams().empty ()) {
++ffmpeg_subs;
++any_subs;
}
- } else if (sc) {
- ++subrip_subs;
+ } else if (sc || dsc) {
+ ++subrip_or_dcp_subs;
++any_subs;
} else {
++any_subs;
@@ -181,7 +185,7 @@ SubtitlePanel::setup_sensitivity ()
_y_offset->Enable (any_subs > 0 && use);
_scale->Enable (any_subs > 0 && use);
_stream->Enable (ffmpeg_subs == 1);
- _view_button->Enable (subrip_subs == 1);
+ _view_button->Enable (subrip_or_dcp_subs == 1);
}
void
@@ -253,9 +257,21 @@ SubtitlePanel::view_clicked ()
SubtitleContentList c = _editor->selected_subtitle_content ();
assert (c.size() == 1);
+
+ shared_ptr<SubtitleDecoder> decoder;
+
shared_ptr<SubRipContent> sr = dynamic_pointer_cast<SubRipContent> (c.front ());
if (sr) {
- _view = new SubtitleView (this, _editor->film(), sr);
+ decoder.reset (new SubRipDecoder (sr));
+ }
+
+ shared_ptr<DCPSubtitleContent> dc = dynamic_pointer_cast<DCPSubtitleContent> (c.front ());
+ if (dc) {
+ decoder.reset (new DCPSubtitleDecoder (dc));
+ }
+
+ if (decoder) {
+ _view = new SubtitleView (this, _editor->film(), decoder, c.front()->position ());
_view->Show ();
}
}
diff --git a/src/wx/subtitle_view.cc b/src/wx/subtitle_view.cc
index 25392c81a..dc41db2fa 100644
--- a/src/wx/subtitle_view.cc
+++ b/src/wx/subtitle_view.cc
@@ -28,7 +28,7 @@ using std::list;
using boost::shared_ptr;
using boost::dynamic_pointer_cast;
-SubtitleView::SubtitleView (wxWindow* parent, shared_ptr<Film> film, shared_ptr<SubRipContent> content)
+SubtitleView::SubtitleView (wxWindow* parent, shared_ptr<Film> film, shared_ptr<SubtitleDecoder> decoder, DCPTime position)
: wxDialog (parent, wxID_ANY, _("Subtitles"))
{
_list = new wxListCtrl (this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_REPORT | wxLC_SINGLE_SEL);
@@ -65,9 +65,8 @@ SubtitleView::SubtitleView (wxWindow* parent, shared_ptr<Film> film, shared_ptr<
sizer->Add (buttons, wxSizerFlags().Expand().DoubleBorder());
}
- shared_ptr<SubRipDecoder> decoder (new SubRipDecoder (content));
list<ContentTextSubtitle> subs = decoder->get_text_subtitles (ContentTimePeriod (ContentTime(), ContentTime::max ()), true);
- FrameRateChange const frc = film->active_frame_rate_change (content->position ());
+ FrameRateChange const frc = film->active_frame_rate_change (position);
int n = 0;
for (list<ContentTextSubtitle>::const_iterator i = subs.begin(); i != subs.end(); ++i) {
for (list<dcp::SubtitleString>::const_iterator j = i->subs.begin(); j != i->subs.end(); ++j) {
diff --git a/src/wx/subtitle_view.h b/src/wx/subtitle_view.h
index 2edc28c09..338742afc 100644
--- a/src/wx/subtitle_view.h
+++ b/src/wx/subtitle_view.h
@@ -21,12 +21,12 @@
#include <wx/wx.h>
#include <wx/listctrl.h>
-class SubRipContent;
+class SubtitleDecoder;
class SubtitleView : public wxDialog
{
public:
- SubtitleView (wxWindow *, boost::shared_ptr<Film>, boost::shared_ptr<SubRipContent>);
+ SubtitleView (wxWindow *, boost::shared_ptr<Film>, boost::shared_ptr<SubtitleDecoder>, DCPTime position);
private:
wxListCtrl* _list;