summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2015-05-13 00:41:50 +0100
committerCarl Hetherington <cth@carlh.net>2015-05-13 00:41:50 +0100
commit83e5567530d0be24490abdda46d196e4279c5030 (patch)
treeae1b8f679fa448d7fc48b7a0521e52c256611cd6 /src/lib
parent2bfd531137f1a4874493186015046e33c5a07c1e (diff)
Look up unknown subtitle end times from the data prepared by the examiner.
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/ffmpeg_content.cc15
-rw-r--r--src/lib/ffmpeg_content.h2
-rw-r--r--src/lib/ffmpeg_decoder.cc46
-rw-r--r--src/lib/ffmpeg_decoder.h4
-rw-r--r--src/lib/ffmpeg_examiner.cc4
-rw-r--r--src/lib/ffmpeg_subtitle_stream.cc42
-rw-r--r--src/lib/ffmpeg_subtitle_stream.h9
-rw-r--r--src/lib/util.cc1
8 files changed, 68 insertions, 55 deletions
diff --git a/src/lib/ffmpeg_content.cc b/src/lib/ffmpeg_content.cc
index 3a42b169f..ad9096b92 100644
--- a/src/lib/ffmpeg_content.cc
+++ b/src/lib/ffmpeg_content.cc
@@ -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
@@ -377,21 +377,12 @@ FFmpegContent::audio_analysis_path () const
list<ContentTimePeriod>
FFmpegContent::subtitles_during (ContentTimePeriod period, bool starting) const
{
- list<ContentTimePeriod> d;
-
shared_ptr<FFmpegSubtitleStream> stream = subtitle_stream ();
if (!stream) {
- return d;
- }
-
- /* XXX: inefficient */
- for (vector<ContentTimePeriod>::const_iterator i = stream->periods.begin(); i != stream->periods.end(); ++i) {
- if ((starting && period.contains (i->from)) || (!starting && period.overlaps (*i))) {
- d.push_back (*i);
- }
+ return list<ContentTimePeriod> ();
}
- return d;
+ return stream->subtitles_during (period, starting);
}
bool
diff --git a/src/lib/ffmpeg_content.h b/src/lib/ffmpeg_content.h
index 76ba43567..d6edb2bdb 100644
--- a/src/lib/ffmpeg_content.h
+++ b/src/lib/ffmpeg_content.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
diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc
index 5dc06fa8e..a3d647cde 100644
--- a/src/lib/ffmpeg_decoder.cc
+++ b/src/lib/ffmpeg_decoder.cc
@@ -426,35 +426,30 @@ FFmpegDecoder::decode_subtitle_packet ()
if (avcodec_decode_subtitle2 (subtitle_codec_context(), &sub, &got_subtitle, &_packet) < 0 || !got_subtitle) {
return;
}
-
- /* Subtitle PTS (within the source, not taking into account any of the
- source that we may have chopped off for the DCP)
- */
- FFmpegSubtitlePeriod period = subtitle_period (sub);
- period.from += _pts_offset;
- if (period.to) {
- period.to = period.to.get() + _pts_offset;
- }
if (sub.num_rects <= 0) {
/* Sometimes we get an empty AVSubtitle, which is used by some codecs to
- indicate that the previous subtitle should stop. Emit the pending one.
+ indicate that the previous subtitle should stop. We can ignore it here.
*/
- if (_pending_subtitle_from && _pending_subtitle_image && _pending_subtitle_rect) {
- image_subtitle (
- ContentTimePeriod (_pending_subtitle_from.get(), period.from),
- _pending_subtitle_image,
- _pending_subtitle_rect.get ()
- );
- _pending_subtitle_from = optional<ContentTime> ();
- _pending_subtitle_image.reset ();
- _pending_subtitle_rect = optional<dcpomatic::Rect<double> > ();
- }
return;
} else if (sub.num_rects > 1) {
throw DecodeError (_("multi-part subtitles not yet supported"));
}
-
+
+ /* Subtitle PTS (within the source, not taking into account any of the
+ source that we may have chopped off for the DCP).
+ */
+ FFmpegSubtitlePeriod sub_period = subtitle_period (sub);
+ ContentTimePeriod period;
+ period.from = sub_period.from + _pts_offset;
+ if (sub_period.to) {
+ /* We already know the subtitle period `to' time */
+ period.to = sub_period.to.get() + _pts_offset;
+ } else {
+ /* We have to look up the `to' time in the stream's records */
+ period.to = ffmpeg_content()->subtitle_stream()->find_subtitle_to (sub_period.from);
+ }
+
AVSubtitleRect const * rect = sub.rects[0];
if (rect->type != SUBTITLE_BITMAP) {
@@ -494,14 +489,7 @@ FFmpegDecoder::decode_subtitle_packet ()
static_cast<double> (rect->h) / vs.height
);
- if (period.to) {
- image_subtitle (ContentTimePeriod (period.from, period.to.get()), image, scaled_rect);
- } else {
- /* We don't know when this subtitle stops, so store it until we find out */
- _pending_subtitle_from = period.from;
- _pending_subtitle_image = image;
- _pending_subtitle_rect = scaled_rect;
- }
+ image_subtitle (ContentTimePeriod (period.from, period.to), image, scaled_rect);
avsubtitle_free (&sub);
}
diff --git a/src/lib/ffmpeg_decoder.h b/src/lib/ffmpeg_decoder.h
index b5bcdd358..0a0eea18a 100644
--- a/src/lib/ffmpeg_decoder.h
+++ b/src/lib/ffmpeg_decoder.h
@@ -67,10 +67,6 @@ private:
void maybe_add_subtitle ();
boost::shared_ptr<AudioBuffers> deinterleave_audio (uint8_t** data, int size);
- boost::optional<ContentTime> _pending_subtitle_from;
- boost::shared_ptr<Image> _pending_subtitle_image;
- boost::optional<dcpomatic::Rect<double> > _pending_subtitle_rect;
-
std::list<ContentTimePeriod> image_subtitles_during (ContentTimePeriod, bool starting) const;
std::list<ContentTimePeriod> text_subtitles_during (ContentTimePeriod, bool starting) const;
diff --git a/src/lib/ffmpeg_examiner.cc b/src/lib/ffmpeg_examiner.cc
index e4f4e6f29..8afd4c164 100644
--- a/src/lib/ffmpeg_examiner.cc
+++ b/src/lib/ffmpeg_examiner.cc
@@ -152,11 +152,11 @@ FFmpegExaminer::subtitle_packet (AVCodecContext* context, shared_ptr<FFmpegSubti
if (avcodec_decode_subtitle2 (context, &sub, &frame_finished, &_packet) >= 0 && frame_finished) {
FFmpegSubtitlePeriod const period = subtitle_period (sub);
if (sub.num_rects <= 0 && _last_subtitle_start) {
- stream->periods.push_back (ContentTimePeriod (_last_subtitle_start.get (), period.from));
+ stream->add_subtitle (ContentTimePeriod (_last_subtitle_start.get (), period.from));
_last_subtitle_start = optional<ContentTime> ();
} else if (sub.num_rects == 1) {
if (period.to) {
- stream->periods.push_back (ContentTimePeriod (period.from, period.to.get ()));
+ stream->add_subtitle (ContentTimePeriod (period.from, period.to.get ()));
} else {
_last_subtitle_start = period.from;
}
diff --git a/src/lib/ffmpeg_subtitle_stream.cc b/src/lib/ffmpeg_subtitle_stream.cc
index 66b587209..77a56e330 100644
--- a/src/lib/ffmpeg_subtitle_stream.cc
+++ b/src/lib/ffmpeg_subtitle_stream.cc
@@ -23,6 +23,8 @@
#include <boost/foreach.hpp>
using std::string;
+using std::map;
+using std::list;
/** Construct a SubtitleStream from a value returned from to_string().
* @param t String returned from to_string().
@@ -32,7 +34,7 @@ FFmpegSubtitleStream::FFmpegSubtitleStream (cxml::ConstNodePtr node)
: FFmpegStream (node)
{
BOOST_FOREACH (cxml::NodePtr i, node->node_children ("Period")) {
- periods.push_back (
+ add_subtitle (
ContentTimePeriod (
ContentTime (node->number_child<ContentTime::Type> ("From")),
ContentTime (node->number_child<ContentTime::Type> ("To"))
@@ -46,9 +48,39 @@ FFmpegSubtitleStream::as_xml (xmlpp::Node* root) const
{
FFmpegStream::as_xml (root);
- BOOST_FOREACH (ContentTimePeriod const & i, periods) {
- xmlpp::Node* node = root->add_child ("Period");
- node->add_child("From")->add_child_text (raw_convert<string> (i.from.get ()));
- node->add_child("To")->add_child_text (raw_convert<string> (i.to.get ()));
+ for (map<ContentTime, ContentTime>::const_iterator i = _subtitles.begin(); i != _subtitles.end(); ++i) {
+ xmlpp::Node* node = root->add_child ("Subtitle");
+ node->add_child("From")->add_child_text (raw_convert<string> (i->first.get ()));
+ node->add_child("To")->add_child_text (raw_convert<string> (i->second.get ()));
}
}
+
+void
+FFmpegSubtitleStream::add_subtitle (ContentTimePeriod period)
+{
+ DCPOMATIC_ASSERT (_subtitles.find (period.from) == _subtitles.end ());
+ _subtitles[period.from] = period.to;
+}
+
+list<ContentTimePeriod>
+FFmpegSubtitleStream::subtitles_during (ContentTimePeriod period, bool starting) const
+{
+ list<ContentTimePeriod> d;
+
+ /* XXX: inefficient */
+ for (map<ContentTime, ContentTime>::const_iterator i = _subtitles.begin(); i != _subtitles.end(); ++i) {
+ if ((starting && period.contains (i->first)) || (!starting && period.overlaps (ContentTimePeriod (i->first, i->second)))) {
+ d.push_back (ContentTimePeriod (i->first, i->second));
+ }
+ }
+
+ return d;
+}
+
+ContentTime
+FFmpegSubtitleStream::find_subtitle_to (ContentTime from) const
+{
+ map<ContentTime, ContentTime>::const_iterator i = _subtitles.find (from);
+ DCPOMATIC_ASSERT (i != _subtitles.end ());
+ return i->second;
+}
diff --git a/src/lib/ffmpeg_subtitle_stream.h b/src/lib/ffmpeg_subtitle_stream.h
index b16b825e7..3ed931b8c 100644
--- a/src/lib/ffmpeg_subtitle_stream.h
+++ b/src/lib/ffmpeg_subtitle_stream.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
@@ -31,6 +31,11 @@ public:
void as_xml (xmlpp::Node *) const;
- std::vector<ContentTimePeriod> periods;
+ void add_subtitle (ContentTimePeriod period);
+ std::list<ContentTimePeriod> subtitles_during (ContentTimePeriod period, bool starting) const;
+ ContentTime find_subtitle_to (ContentTime from) const;
+
+private:
+ std::map<ContentTime, ContentTime> _subtitles;
};
diff --git a/src/lib/util.cc b/src/lib/util.cc
index d8c754607..99d9ba2c4 100644
--- a/src/lib/util.cc
+++ b/src/lib/util.cc
@@ -670,3 +670,4 @@ write_frame_info (FILE* file, int frame, Eyes eyes, dcp::FrameInfo info)
fwrite (&info.size, sizeof (info.size), 1, file);
fwrite (info.hash.c_str(), 1, info.hash.size(), file);
}
+