Push the dropping of non-visible lines into the serialization logic

Makes things way less gross and trivially faster.
This commit is contained in:
Thomas Goyne 2014-04-30 07:22:41 -07:00 committed by Thomas Goyne
parent 7a5c92aaee
commit af20d31699
6 changed files with 16 additions and 34 deletions

View File

@ -44,7 +44,7 @@ struct VideoFrame;
class SubtitlesProvider {
public:
virtual ~SubtitlesProvider() = default;
virtual void LoadSubtitles(AssFile *subs)=0;
virtual void LoadSubtitles(AssFile *subs, int time = -1)=0;
virtual void DrawSubtitles(VideoFrame &dst, double time)=0;
};

View File

@ -135,9 +135,14 @@ void AssSubtitleFormat::WriteFile(const AssFile *src, agi::fs::path const& filen
writer.WriteExtradata(src->Extradata);
}
void AssSubtitleFormat::WriteToStream(const AssFile *src, std::ostream &ostr) {
void AssSubtitleFormat::WriteToStream(const AssFile *src, std::ostream &ostr, int time) {
Writer writer(ostr);
writer.Write(src->Info);
writer.Write(src->Styles);
writer.Write(src->Events);
writer.file.WriteLineToFile("[Events]");
for (auto const& line : src->Events) {
if (!line.Comment && time < 0 || !(line.Start > time || line.End <= time))
writer.file.WriteLineToFile(line.GetEntryData());
}
}

View File

@ -28,5 +28,5 @@ public:
void ReadFile(AssFile *target, agi::fs::path const& filename, agi::vfr::Framerate const& fps, std::string const& forceEncoding) const override;
void WriteFile(const AssFile *src, agi::fs::path const& filename, agi::vfr::Framerate const& fps, std::string const& encoding) const override;
static void WriteToStream(const AssFile *src, std::ostream &ostr);
static void WriteToStream(const AssFile *src, std::ostream &ostr, int time);
};

View File

@ -73,7 +73,7 @@ class CSRISubtitlesProvider final : public SubtitlesProvider {
public:
CSRISubtitlesProvider(std::string subType);
void LoadSubtitles(AssFile *subs);
void LoadSubtitles(AssFile *subs, int time);
void DrawSubtitles(VideoFrame &dst, double time);
};
@ -92,9 +92,9 @@ CSRISubtitlesProvider::CSRISubtitlesProvider(std::string type) {
throw agi::InternalError("CSRI renderer vanished between initial list and creation?", 0);
}
void CSRISubtitlesProvider::LoadSubtitles(AssFile *subs) {
void CSRISubtitlesProvider::LoadSubtitles(AssFile *subs, int time) {
ostr.rdbuf()->clear();
AssSubtitleFormat::WriteToStream(subs, ostr);
AssSubtitleFormat::WriteToStream(subs, ostr, time);
if (tempfile.empty())
tempfile = unique_path(config::path->Decode("?temp/csri-%%%%-%%%%-%%%%-%%%%.ass"));

View File

@ -131,7 +131,7 @@ public:
LibassSubtitlesProvider(agi::BackgroundRunner *br);
~LibassSubtitlesProvider();
void LoadSubtitles(AssFile *subs) override;
void LoadSubtitles(AssFile *subs, int time) override;
void DrawSubtitles(VideoFrame &dst, double time) override;
};
@ -155,10 +155,10 @@ LibassSubtitlesProvider::~LibassSubtitlesProvider() {
if (ass_track) ass_free_track(ass_track);
}
void LibassSubtitlesProvider::LoadSubtitles(AssFile *subs) {
void LibassSubtitlesProvider::LoadSubtitles(AssFile *subs, int time) {
boost::interprocess::basic_ovectorstream<std::vector<char>> ostr;
ostr.reserve(0x4000);
AssSubtitleFormat::WriteToStream(subs, ostr);
AssSubtitleFormat::WriteToStream(subs, ostr, time);
if (ass_track) ass_free_track(ass_track);
ass_track = ass_read_memory(library, const_cast<char *>(ostr.vector().data()), ostr.vector().size(), nullptr);

View File

@ -29,11 +29,8 @@
#include "video_frame.h"
#include "video_provider_manager.h"
#include <libaegisub/address_of_adaptor.h>
#include <libaegisub/dispatch.h>
#include <boost/range/adaptor/indirected.hpp>
#include <boost/range/algorithm_ext.hpp>
#include <condition_variable>
#include <functional>
#include <mutex>
@ -67,28 +64,8 @@ std::shared_ptr<VideoFrame> ThreadedFrameSource::ProcFrame(int frame_number, dou
}
else {
AssFixStylesFilter().ProcessSubs(subs.get(), nullptr);
single_frame = frame_number;
// Copying a nontrivially sized AssFile is fairly slow, so
// instead muck around with its innards to just temporarily
// remove the non-visible lines without deleting them
std::deque<AssDialogue*> full;
boost::push_back(full, subs->Events | agi::address_of);
subs->Events.remove_if([=](AssDialogue const& diag) {
return diag.Start > time || diag.End <= time;
});
try {
subs_provider->LoadSubtitles(subs.get());
subs->Events.clear();
boost::push_back(subs->Events, full | boost::adaptors::indirected);
}
catch (...) {
subs->Events.clear();
boost::push_back(subs->Events, full | boost::adaptors::indirected);
throw;
}
subs_provider->LoadSubtitles(subs.get(), time);
}
}
}