Speed up passing subtitles to VSFilter a little

Use temp_file_mapping so that it normally never actually hits the disk
on Windows and use AssSubtitleFormat directly.
This commit is contained in:
Thomas Goyne 2014-04-29 17:05:53 -07:00
parent 1eba2f035c
commit 4366ece827
1 changed files with 24 additions and 21 deletions

View File

@ -37,16 +37,15 @@
#include "include/aegisub/subtitles_provider.h" #include "include/aegisub/subtitles_provider.h"
#include "options.h" #include "options.h"
#include "subtitle_format.h" #include "subtitle_format_ass.h"
#include "video_frame.h" #include "video_frame.h"
#include <libaegisub/fs.h> #include <libaegisub/file_mapping.h>
#include <libaegisub/path.h> #include <libaegisub/path.h>
#include <libaegisub/scoped_ptr.h>
#include <libaegisub/make_unique.h> #include <libaegisub/make_unique.h>
#include <libaegisub/vfr.h>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <boost/interprocess/streams/vectorstream.hpp>
#include <mutex> #include <mutex>
#ifdef WIN32 #ifdef WIN32
@ -60,25 +59,28 @@ namespace {
// is not) // is not)
std::mutex csri_mutex; std::mutex csri_mutex;
class CSRISubtitlesProvider final : public SubtitlesProvider { struct closer {
agi::scoped_holder<csri_inst*> instance; void operator()(csri_inst *inst) { if (inst) csri_close(inst); }
csri_rend *renderer; };
class CSRISubtitlesProvider final : public SubtitlesProvider {
std::unique_ptr<csri_inst, closer> instance;
csri_rend *renderer = nullptr;
boost::interprocess::basic_ovectorstream<std::vector<char>> ostr;
/// Name of the file passed to renderers with can_open_mem false /// Name of the file passed to renderers with can_open_mem false
agi::fs::path tempfile; agi::fs::path tempfile;
public: public:
CSRISubtitlesProvider(std::string subType); CSRISubtitlesProvider(std::string subType);
~CSRISubtitlesProvider();
void LoadSubtitles(AssFile *subs); void LoadSubtitles(AssFile *subs);
void DrawSubtitles(VideoFrame &dst, double time); void DrawSubtitles(VideoFrame &dst, double time);
}; };
CSRISubtitlesProvider::CSRISubtitlesProvider(std::string type) CSRISubtitlesProvider::CSRISubtitlesProvider(std::string type) {
: instance(nullptr, csri_close) ostr.reserve(0x10000);
{
std::lock_guard<std::mutex> lock(csri_mutex);
std::lock_guard<std::mutex> lock(csri_mutex);
for (csri_rend *cur = csri_renderer_default(); cur; cur = csri_renderer_next(cur)) { for (csri_rend *cur = csri_renderer_default(); cur; cur = csri_renderer_next(cur)) {
if (type == csri_renderer_info(cur)->name) { if (type == csri_renderer_info(cur)->name) {
renderer = cur; renderer = cur;
@ -90,20 +92,21 @@ CSRISubtitlesProvider::CSRISubtitlesProvider(std::string type)
throw agi::InternalError("CSRI renderer vanished between initial list and creation?", 0); throw agi::InternalError("CSRI renderer vanished between initial list and creation?", 0);
} }
CSRISubtitlesProvider::~CSRISubtitlesProvider() {
agi::fs::Remove(tempfile);
}
void CSRISubtitlesProvider::LoadSubtitles(AssFile *subs) { void CSRISubtitlesProvider::LoadSubtitles(AssFile *subs) {
ostr.rdbuf()->clear();
AssSubtitleFormat::WriteToStream(subs, ostr);
if (tempfile.empty()) if (tempfile.empty())
tempfile = unique_path(config::path->Decode("?temp/csri-%%%%-%%%%-%%%%-%%%%.ass")); tempfile = unique_path(config::path->Decode("?temp/csri-%%%%-%%%%-%%%%-%%%%.ass"));
SubtitleFormat::GetWriter(tempfile)->WriteFile(subs, tempfile, 0, "utf-8"); auto size = ostr.vector().size();
agi::temp_file_mapping file(tempfile, size);
memcpy(file.write(0, size), &ostr.vector()[0], size);
std::lock_guard<std::mutex> lock(csri_mutex); std::lock_guard<std::mutex> lock(csri_mutex);
instance = csri_open_file(renderer, tempfile.string().c_str(), nullptr); instance.reset(csri_open_file(renderer, tempfile.string().c_str(), nullptr));
} }
void CSRISubtitlesProvider::DrawSubtitles(VideoFrame &dst,double time) { void CSRISubtitlesProvider::DrawSubtitles(VideoFrame &dst, double time) {
if (!instance) return; if (!instance) return;
csri_frame frame; csri_frame frame;
@ -120,8 +123,8 @@ void CSRISubtitlesProvider::DrawSubtitles(VideoFrame &dst,double time) {
csri_fmt format = { frame.pixfmt, dst.width, dst.height }; csri_fmt format = { frame.pixfmt, dst.width, dst.height };
std::lock_guard<std::mutex> lock(csri_mutex); std::lock_guard<std::mutex> lock(csri_mutex);
if (!csri_request_fmt(instance, &format)) if (!csri_request_fmt(instance.get(), &format))
csri_render(instance, &frame, time); csri_render(instance.get(), &frame, time);
} }
} }