Hopefully improve subtitle decoder seeking etc.
authorCarl Hetherington <cth@carlh.net>
Wed, 2 Jul 2014 17:10:58 +0000 (18:10 +0100)
committerCarl Hetherington <cth@carlh.net>
Wed, 2 Jul 2014 17:10:58 +0000 (18:10 +0100)
src/lib/dcpomatic_time.cc
src/lib/ffmpeg_content.cc
src/lib/ffmpeg_content.h
src/lib/ffmpeg_decoder.cc
src/lib/ffmpeg_decoder.h
src/lib/subrip_decoder.cc
src/lib/subrip_decoder.h
src/lib/subtitle_decoder.cc
src/lib/subtitle_decoder.h

index ae4dea44f5c0752f6b387365713f772336e8d867..dcdfd97daf4a2d54b63210092de4220b217ed18a 100644 (file)
@@ -53,5 +53,5 @@ operator<< (ostream& s, DCPTime t)
 bool
 ContentTimePeriod::overlaps (ContentTimePeriod const & other) const
 {
-       return (from < other.to && to > other.from);
+       return (from < other.to && to >= other.from);
 }
index a12f45a30f81d20d6af73fb97e0b62f805a54a54..f97e324bb4bb5d521467c0fcdd8a837e73299f7b 100644 (file)
@@ -396,20 +396,22 @@ FFmpegContent::audio_analysis_path () const
        return p;
 }
 
-bool
-FFmpegContent::has_subtitle_during (ContentTimePeriod period) const
+list<ContentTimePeriod>
+FFmpegContent::subtitles_during (ContentTimePeriod period) const
 {
+       list<ContentTimePeriod> d;
+       
        shared_ptr<FFmpegSubtitleStream> stream = subtitle_stream ();
        if (!stream) {
-               return false;
+               return d;
        }
 
        /* XXX: inefficient */
        for (vector<ContentTimePeriod>::const_iterator i = stream->periods.begin(); i != stream->periods.end(); ++i) {
-               if (i->from <= period.to && i->to >= period.from) {
-                       return true;
+               if (period.overlaps (*i)) {
+                       d.push_back (*i);
                }
        }
 
-       return false;
+       return d;
 }
index 367c30103e77812927878d0f2f31062e995cc647..dbb207959ffa2dc21e89e9977414e3cd9abc0d3b 100644 (file)
@@ -108,7 +108,7 @@ public:
                return _first_video;
        }
 
-       bool has_subtitle_during (ContentTimePeriod) const;
+       std::list<ContentTimePeriod> subtitles_during (ContentTimePeriod) const;
 
 private:
        friend class ffmpeg_pts_offset_test;
index 885bd0e85e03ad11a79e1ff6da34f2173e05b184..668cab88530d1b385821056aeb837d4b2a011ff0 100644 (file)
@@ -481,8 +481,8 @@ FFmpegDecoder::decode_subtitle_packet ()
        avsubtitle_free (&sub);
 }
 
-bool
-FFmpegDecoder::has_subtitle_during (ContentTimePeriod p) const
+list<ContentTimePeriod>
+FFmpegDecoder::subtitles_during (ContentTimePeriod p) const
 {
-       return _ffmpeg_content->has_subtitle_during (p);
+       return _ffmpeg_content->subtitles_during (p);
 }
index d6cb8c24643c0aed8c1d0f63471f8af9fca1629f..15811d5b92c9174798ba5bec1f08ecdd35e69704 100644 (file)
@@ -66,7 +66,7 @@ private:
        void maybe_add_subtitle ();
        boost::shared_ptr<AudioBuffers> deinterleave_audio (uint8_t** data, int size);
 
-       bool has_subtitle_during (ContentTimePeriod) const;
+       std::list<ContentTimePeriod> subtitles_during (ContentTimePeriod) const;
        
        boost::shared_ptr<Log> _log;
        
index 3d971fd4b4fe8516ec43d5b7111b9f095b6176be..370118d3065debae3aee18dfae4bcf33cc00fa06 100644 (file)
@@ -79,16 +79,18 @@ SubRipDecoder::pass ()
        return false;
 }
 
-bool
-SubRipDecoder::has_subtitle_during (ContentTimePeriod p) const
+list<ContentTimePeriod>
+SubRipDecoder::subtitles_during (ContentTimePeriod p) const
 {
        /* XXX: inefficient */
 
+       list<ContentTimePeriod> d;
+
        for (vector<SubRipSubtitle>::const_iterator i = _subtitles.begin(); i != _subtitles.end(); ++i) {
                if (p.overlaps (i->period)) {
-                       return true;
+                       d.push_back (i->period);
                }
        }
 
-       return false;
+       return d;
 }
index d6c6e6bc2fa7fd37df7c4769c572fedaa7a7823c..927ccc728e347141de9384b274163f2ca6ad402f 100644 (file)
@@ -35,7 +35,7 @@ protected:
        bool pass ();
 
 private:
-       bool has_subtitle_during (ContentTimePeriod) const;
+       std::list<ContentTimePeriod> subtitles_during (ContentTimePeriod) const;
        
        size_t _next;
 };
index 1b789fdab478e5cde0200a64f7a0e92fdb2bee0b..b8cb3e5c86c8fc2d49733c131077d1327b330fcd 100644 (file)
@@ -51,20 +51,23 @@ template <class T>
 list<T>
 SubtitleDecoder::get (list<T> const & subs, ContentTimePeriod period)
 {
-       if (!has_subtitle_during (period)) {
+       /* Get the full periods of the subtitles that are showing during the specified period */
+       list<ContentTimePeriod> sp = subtitles_during (period);
+       if (sp.empty ()) {
+               /* Nothing in this period */
                return list<T> ();
        }
 
-       if (subs.empty() || period.from < subs.front().period().from || period.to > (subs.back().period().to + ContentTime::from_seconds (10))) {
-               /* Either we have no decoded data, or what we do have is a long way from what we want: seek */
-               seek (period.from, true);
+       /* Seek if what we want is before what we have, or more than a reasonable amount after */
+       if (subs.empty() || sp.back().to < subs.front().period().from || sp.front().from > (subs.back().period().to + ContentTime::from_seconds (5))) {
+               seek (sp.front().from, true);
        }
 
        /* Now enough pass() calls will either:
         *  (a) give us what we want, or
         *  (b) hit the end of the decoder.
         */
-       while (!pass() && (subs.empty() || (subs.front().period().from > period.from || period.to < subs.back().period().to))) {}
+       while (!pass() && (subs.empty() || (subs.back().period().to < sp.back().to))) {}
 
        /* Now look for what we wanted in the data we have collected */
        /* XXX: inefficient */
index 3f06afae396260c1d5d3ebb17fe294905c2dcfc9..51faca97ff50355e04f0d831f1b4ca33ab9c205d 100644 (file)
@@ -51,7 +51,7 @@ private:
        template <class T>
        std::list<T> get (std::list<T> const & subs, ContentTimePeriod period);
 
-       virtual bool has_subtitle_during (ContentTimePeriod) const = 0;
+       virtual std::list<ContentTimePeriod> subtitles_during (ContentTimePeriod) const = 0;
        
        boost::shared_ptr<const SubtitleContent> _subtitle_content;
 };